Start Task (SAM Task Execution Helper)
You are implementing a specific task in a SAM plan, addressed as P{id}/T{id}. The backend resolves that address and returns the task — no path is involved.
<task_input> $ARGUMENTS </task_input>
<sam_cli> uv run "${CLAUDE_PLUGIN_ROOT}/sam_schema/cli.py" </sam_cli>
<mcp_server_scripts> SAM server: uv run --script "${CLAUDE_PLUGIN_ROOT}/scripts/run_sam_server.py" Backlog server: uv run --script "${CLAUDE_PLUGIN_ROOT}/scripts/run_backlog_server.py" --project-dir . </mcp_server_scripts>
MCP server availability: This skill uses mcp__plugin_dh_sam__* tools. If a tool is unavailable, see the troubleshooting steps at ${CLAUDE_PLUGIN_ROOT}/docs/mcp-connection-check.md — its commands use the <sam_cli/> and <mcp_server_scripts/> values above.
Parse Arguments
plan_address(required): plan address inP{hex}form, e.g.Pdec8934d--task <id>(optional): Task ID to start (defaults to first ready task)--complete <id>(optional): Task ID to mark COMPLETE
If --complete <task-id> Provided
- Run
uv run "${CLAUDE_PLUGIN_ROOT}/sam_schema/cli.py" plan state --address P{N}/T{M} --new-status completeto mark the task complete. - Output:
Task {ID} marked as complete
Starting a Task
-
Read the task assignment via the SAM CLI:
uv run "${CLAUDE_PLUGIN_ROOT}/sam_schema/cli.py" plan read --address P{N}/T{M}The response is a
TaskAssignmentmodel containing:plan.goal— the overall feature goalplan.context— plan-level context manifest (architecture decisions, codebase notes)task— full task details: title, requirements, constraints, acceptance criteria, verification stepstask.skills— skill names to load before implementing
Use the address form
P{N}/T{M}whereNis the plan number andMis the task number from the--taskargument.
1a. Discover plan artifacts via manifest (when issue number is known):
If the TaskAssignment model contains a parent_issue_number or the plan has an issue field, query the artifact manifest to discover available plan artifacts:
uv run "${CLAUDE_PLUGIN_ROOT}/sam_schema/cli.py" artifact list --item-id N
If the response contains artifacts (non-empty artifacts list), use artifact_read to fetch the architect spec and feature context content:
uv run "${CLAUDE_PLUGIN_ROOT}/sam_schema/cli.py" artifact read --item-id N --artifact-type architect
uv run "${CLAUDE_PLUGIN_ROOT}/sam_schema/cli.py" artifact read --item-id N --artifact-type feature-context
Use the returned content as context for implementation instead of reading filesystem paths directly. This is especially important for worktree-isolated agents that cannot access uncommitted plan files from the root worktree.
Fallback: If artifact_list returns an empty manifest (no artifacts entries) or an error, try artifact_read with types architect and feature-context directly. These artifact types are registered by the agents that produce them.
- Select the task:
- If
--taskprovided, use that ID - Else pick the first task where status is
not-startedand all dependencies are resolved (checktask.dependenciesin the TaskAssignment)
- If
2a. Load task-level skills (if present):
- Read
task.skillsfrom theTaskAssignmentmodel (an array of skill names). - If absent or empty, skip.
- For each skill name, invoke:
Skill(skill="{skill-name}") - If a skill fails to load, log a warning and continue. Do not abort task execution.
- Task-level skills are additive to any skills already declared in the agent definition's frontmatter.
-
Claim the task (prevents duplicate dispatch):
Use
sam_task(action='claim')(MCP) orplan claim(CLI). This is the ONLY permitted way to mark a task in-progress. Do NOT edit status or started fields directly with the Edit tool.uv run "${CLAUDE_PLUGIN_ROOT}/sam_schema/cli.py" plan claim --address P{N}/T{M}If the response contains
"claimed": false:- The task was already claimed by another agent, or is complete, or could not be found.
- Output the full JSON result for the orchestrator.
- STOP. Do not proceed with implementation. Do not write the context file.
- The orchestrator's hook will detect the stop and the task remains in its current state.
If the response contains
"claimed": true:- The task is claimed.
status: in-progressandstarted:are written on disk. - Proceed to step 4 (write context file) and step 5 (implement).
-
Register the active-task context via the SAM CLI (required for hook-driven updates):
uv run "${CLAUDE_PLUGIN_ROOT}/sam_schema/cli.py" active-task set \ --address P{N}/T{M} \ --parent-issue N \ --session-id "${CLAUDE_CODE_SESSION_ID}"Omit
--parent-issueif the story issue number is not known. The hook treats absence asNoneand skips backend sync.--parent-issueacceptsstr | int— GitHub integer IDs (e.g.,42) and beads string IDs (e.g.,"bd-a3f8") are both valid.
If parent_issue_number is known (str | int), the sam_task(action='claim') step already
writes in-progress status via the backend-agnostic SAM router. The task_status_hook.py
handles any external tracker sync on task completion. No additional call is required here.
-
Record divergence observations during implementation.
While implementing, if you discover that the architect spec or feature-context describes something that does not match what you are implementing, record a divergence note on the task through the SAM task update operation.
When to record: Record a divergence note when ALL of these hold:
- You are implementing something that differs from what the architect spec or feature-context describes
- The difference is not a trivial implementation detail (e.g., different variable name, different import path)
- The difference affects the observable behavior, structure, or scope of the feature
Write the note and its running count in one call. The
append_sectionheading, the note body, and thedivergence-notesfield update are non-exclusive sub-operations of a singleupdateaction:mcp__plugin_dh_sam__sam_task( plan="P{N}", task="T{M}", config={ "action": "update", "append_section": "Divergence Notes", "section_content": "{note body}", "set_fields_json": {"divergence-notes": {new_count}}, }, ){new_count}is the task's currentdivergence-notesvalue plus one. Read the current value fromsam_task(plan="P{N}", task="T{M}", config={"action": "read"})before the update call.The
append_sectionvalue supplies the## Divergence Notesheading —{note body}carries no heading of its own:
### DN-1: {Brief title}
- Plan artifact: `artifact_read(item_id={N}, artifact_type="architect")`, section "{section name}"
- Plan claim: "{quoted text from plan artifact}"
- Actual implementation: "{what was actually done and why}"
- Classification: design-refinement | intent-divergence
- Recorded: {ISO timestamp}
Never record a divergence note by editing a file. The task is addressed logically; on a remote backend no task file exists to edit, and a file written in one worktree is unreadable from another, so a file-based note is silently lost.
For full artifact classification rules and divergence thresholds, see plan-artifact-lifecycle.md.
-
Commit message restriction — Fixes #N trailers are PROHIBITED in task-level commits.
Task-level commits must NEVER include
Fixes #N,Closes #N, orResolves #Ntrailers. These trailers trigger automatic GitHub issue closure. Issue closure is handled exclusively by/complete-implementationin its final commit step, after all quality gates pass. Including these trailers in task commits causes premature issue closure before verification is complete. -
Implement against the task acceptance criteria and run its verification steps.