Files
kandev/apps/backend/internal/task
João Salavisa b118a4fe98 fix(mcp): honor explicit task_id in plan/walkthrough/review tools (#1984)
* fix(mcp): honor explicit task_id in plan/walkthrough/review tools

resolveTaskID silently discarded the caller-supplied task_id whenever the
MCP server was session-bound (every agent session) and substituted the
caller's own task. A parent reading a child's plan got the parent's empty
plan back ("No plan exists"), and a cross-task create/update would have
written to the wrong task — all with no error, despite the tool schemas
advertising task_id as a usable parameter.

Honor an explicitly provided task_id and fall back to the session-bound
task only when the argument is absent, matching how message_task_kandev /
stop_task_kandev already address other tasks. Cross-task access stays safe:
internal/mcp/scope attaches the stream owner's identity (from the agent's
own execution, never the payload), and the plan/walkthrough/review services
gate the target task_id through the same workspace-ownership check every
other cross-task surface uses — an out-of-reach task is rejected, not
served. The review service gains the SetTaskAuthorizer wiring the plan and
walkthrough services already had, so publish_review_findings is covered too.

Tool descriptions now document the default-to-current / cross-task-within-
reach behavior. Tests cover the resolution precedence (explicit wins /
fallback to bound / neither errors), a session-bound-to-A reads/creates a
plan for B regression, and the review authorizer allow/deny paths.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(mcp): drop mcp.Required() from task_id on session-defaulting tools

The plan, walkthrough, and publish-review tools default task_id to the
session-bound task when it is omitted, so advertising it as required
contradicted that documented behavior (flagged by Codex and CodeRabbit on
the PR). Mark task_id optional on all eight; handler behavior is unchanged.
The genuinely cross-task tools (update/move/delete/archive_task,
message_task, get_task_conversation) keep task_id required.

Adds a schema test asserting task_id is present-but-optional on every
session-defaulting tool.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* test(mcp): cover review scoping + walkthrough/review tool-desc reach

Addresses two non-blocking review findings:

- Extend TestPlanAndWalkthroughScoping to exercise ReviewService through the
  assembled AuthorizeTaskAccess → SetTaskAuthorizer → PublishFindings path, so
  all three task-scoped services are covered uniformly (foreign owner denied
  with ErrTaskNotFound; real owner passes and the finding is stored).
- Document the default-to-current / cross-task-within-reach semantics in the
  top-level descriptions of the walkthrough and publish-review tools (was only
  in the task_id parameter description), since LLMs read the tool description
  first. Broaden the description test to assert all eight session-defaulting
  tools carry it.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* test(mcp): assert review finding persists through the auth gate

Follow-up to review: query repo.ListTaskReviewFindings after the owner
publish in TestPlanAndWalkthroughScoping and assert exactly one finding was
stored, so the test verifies the write landed in the repository rather than
only the service's returned slice.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Kandev Agent <agent@kandev.dev>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-27 18:34:55 +01:00
..