Skip to content

feat(agentconfig-mcp): WeveNova planner MCP for planner-skill integration - #253

Open
Harsheet jain (jainharsheet77) wants to merge 4 commits into
microsoft:feature/planner-skillfrom
jainharsheet77:harsheetjain/planner-skill-wevenova-mcp
Open

feat(agentconfig-mcp): WeveNova planner MCP for planner-skill integration#253
Harsheet jain (jainharsheet77) wants to merge 4 commits into
microsoft:feature/planner-skillfrom
jainharsheet77:harsheetjain/planner-skill-wevenova-mcp

Conversation

@jainharsheet77

Copy link
Copy Markdown

What

Brings the self-contained WeveNova AgentConfiguration MCP (the ess-planner
server) onto feature/planner-skill so the planner skill can drive WeveNova
projects, plans, tasks, and plan role attestation end to end during
integration testing.

Single commit; the change set is MCP-only (9-file package under
solutions/ess-maker-skills/src/mcp/agentconfig/ + 3 planner test suites under
tests/mcp/agentconfig/).

Tools

server_planner.py exposes 23 MCP tools over the beta surface — projects
(list/get/create/archive), plans (list/get/create/update/activate/archive),
tasks (list/get/create/role-assign/update/set-state/complete/delete), and role
attestation (list/attest/list-assignments/get/revoke). Identity and tenant are
always taken from the access token, never tool arguments.

Self-healing conflict recovery

Every If-Match mutation now routes through _mutate_with_etag_recovery, so a
planner agent does not have to hand-roll optimistic-concurrency bookkeeping:

  • 412 Precondition Failed (stale ETag): re-read the entity and retry the
    mutation once with the fresh ETag — but only when the version actually
    moved, so a genuine lost update is never silently clobbered. WeveNova bumps a
    task's version as a side effect of ledger reconciliation (e.g. completing a
    producer task reconciles an artifact a consumer task references), so an ETag a
    caller just read can go stale through no edit of its own.
  • 409 Conflict on a task mutation (non-Active parent plan): re-read the plan
    and, when it is not Active, replace the backend's generic conflict text with an
    actionable "activate the plan first" message.

Validation

  • Full live smoke test of every planner tool against a no-auth devtunnel backend
    (projects/plans/tasks/roles, full task lifecycle with ETag threading, multi-active
    plans). All tools pass; the only non-pass observed was backend test-data
    saturation (MaxPlansPerProject=10), not an MCP defect.
  • tests/mcp/agentconfig46 passing (request-construction contract via
    httpx.MockTransport, static + protocol tool-surface contract, and six new
    recovery tests covering the 412 retry, the "version unchanged ⇒ re-raise"
    guard, and the 409 activate-first clarifier).

Notes

  • The ess-planner MCP is environment-configured (AGENTCONFIG_PROJECTS_BASE_URL,
    AGENTCONFIG_ACCESS_TOKEN_FILE); it does not depend on .vscode/mcp.defaults.json.
  • The three base-infra tests (test_client, test_server_contract,
    test_widget_protocol) are intentionally omitted — they assert on
    landing-page-config artifacts not present on feature/planner-skill.

@jainharsheet77
Harsheet jain (jainharsheet77) force-pushed the harsheetjain/planner-skill-wevenova-mcp branch from 5b57e51 to 5821392 Compare August 26, 2026 13:49
Flow-2 "what am I assigned?" file.
the phase files (research, interview, model, assign, evaluate, capture), the sync
file (pull/push the plan with the shared planner), and the Flow-2 "what am I
assigned?" file.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For queries like what am I assigned reach out to mcp and syc as that returns tasks only for the roles and there is no api taht exposes what roels do I have so filtering is intrinsic to call for tasks with $filter

interview or re-asking the objective. Start over only on explicit confirmation.
**Before interviewing, check for an existing plan — and pull first.** The planner
invisibly pulls the shared plan on entry; if a plan then exists (freshly pulled or
already at `workspace/plan/plan.json`), resume it — show its latest state and the

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now there can be many plans as we can have multiple plans in wevenova, get all the plans the person has access to and list and ask which pan would they like to resume, IT is fine to not choose any and create a new one altogether.

harsheetjain and others added 3 commits August 26, 2026 20:22
…egration

Copy the self-contained WeveNova agent-configuration MCP package onto the planner-skill branch so the planner skill can drive WeveNova projects, plans, tasks, and role attestations via the ess-planner MCP server during integration testing.

Ported verbatim from harsheetjain/wevenova-mcp-for-planner (PR microsoft#251). Tests: tests/mcp/agentconfig planner suites, 40 tests all passing.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Make the shared planner the source of truth for the /planner experience: the
local plan.json becomes a cache that is pulled on entry and pushed as one
object on create. The CLI stays network-free; the skill orchestrates the tool
calls and shuttles JSON through the new sync seam.

- plan_model: add the sync-seam mirror fields (configuringAgentName + etag/
  syncedAt on the plan, remoteId/etag on each task), a CONFIGURING_AGENT_NAMES
  vocab, an acceptanceCriteria context group, and set_configuring_agent_name /
  set_remote_identity; back-fill + validate the new fields.
- sync: new pure mapping module (no network, no IO) — to_remote_plan_body /
  to_remote_task_body export (only allowed fields; acceptance promotion;
  assignee flattening) and hydrate_from_remote import (Blocked<->Cancelled and
  acceptance bridges, Principal reconstruction, case-insensitive reads,
  outputs list->dict), plus stamp_remote_ids.
- cli: add set-agent-name, export-remote-plan, import-remote-plan, stamp-remote.
- skill: rewire SKILL.md to pull-first on entry and publish-as-one-object +
  activate on create; add sync.md; answer "what am I assigned?" from the
  service's caller-filtered tasks. Never name the backend in skill prose.
- tests: tests/planner/test_sync.py covers export shape, the vocab bridges, the
  hydrate round-trip, and the four new CLI commands.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…ndency-ordered tasks

Adds the /roles skill: attest a person into an ESS rollout role so the shared plan's role-pooled tasks become visible to them. Backed by a directory name->object-id resolver (scripts/roles/cli.py resolve-person) that reuses the kit's Graph integration; role reads/writes stay planner-tool calls.

Also renders plan task lists in execution order (a task producing an artifact another consumes is listed first) via a stable, cycle-tolerant topological sort in plan_model.ordered_tasks(), used by summary and the 'what am I assigned?' view; and nudges attestable-role assignment at plan creation.

Skill prose stays backend-agnostic; routing, menu, and the planner assign nudge hook are wired. Tests: tests/roles resolver, tests/flightcheck search_users, and plan_model ordering.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@jainharsheet77
Harsheet jain (jainharsheet77) force-pushed the harsheetjain/planner-skill-wevenova-mcp branch from d7ab659 to 372d022 Compare August 26, 2026 14:54
…block Archived-via-update, normalize task keys

- _mutate_with_etag_recovery: never blind-replay after a 412. An advanced ETag
  is indistinguishable from a concurrent edit, so raise an actionable "entity
  changed, re-read and reapply" 412 instead of clobbering another writer.
  Verified live: a stale If-Match PATCH returns 412 and the prior value is
  preserved (no replay).
- client._request: surface (don't replay) an ambiguous 502/503/504 or network
  error on a non-idempotent request (an unkeyed create) so a
  committed-but-unacknowledged POST can't be duplicated; reads, keyed
  mutations, and PATCH/DELETE keep bounded retry, and 429 always retries.
- update_project_plan: reject {"status":"Archived"} and route archiving (which
  cancels the plan's tasks) through the destructive archive_project_plan tool.
  Verified live: archiving cancels the plan's tasks.
- update_project_plan_task: normalize patch keys to canonical camelCase and
  reject a field named twice under different casing. Verified live: the surface
  deserializes case-insensitively, so this is deterministic-shape hardening,
  not a required fix -- the "wrong casing is rejected" premise does not hold.
- server_planner: reconcile tool docstrings/instructions with the no-replay 412.
- tests: pin no-replay 412 (task/plan/delete), Archived rejection, key
  normalization + duplicate rejection, and unkeyed-create retry suppression.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants