---
requirements:
  reasoning: Low
  context: Low
  speed: High
audience: subagent
phase: commit
context:
  architecture: false
  prior_summaries: none
  persona: summary
  master_index: false
  diff_mode: false
deps:
  personas: [engineer]
  skills: [engineer, generic]
  templates: [PROGRESS_TEMPLATE]
  sub_workflows: []
  kb_docs: []
  config_fields: [commands.test, paths.engineering]
---


# Commit Task
## Iron Laws

- Commit only the artifacts produced for this task; do not sweep unrelated working-tree changes into the commit. The commit boundary mirrors the task boundary.
- Announce your identity via `forge_banner` before any other tool use — `.forge/personas/engineer.md` is already loaded as your system prompt; do not re-read it.
- All store I/O via `forge_store` (or `node .forge/tools/store-cli.cjs`). Never edit `.forge/store/*.json` directly.
- **Never run `git add`/`git commit`/`git reset` yourself** — `commit-task.cjs` owns staging, boundary checks, committing, and the terminal transition (#40). Your judgement input is the message.
- **Commit writes NO summary** (`commit` ∉ `VALID_SUMMARY_PHASES` — any `set-summary` is rejected); the tool's terminal `update-status` is this phase's only store write.

## Store-Write Verification

On a store-write failure (non-zero exit or `PreToolUse` exit 2): fix the JSON and retry, up to 3 times, then halt and escalate. Never set `FORGE_SKIP_WRITE_VALIDATION=1`. Rules: `_fragments/store-write-verification.md`.

## Algorithm

```

0. Entity-mode resolution:
   - Read the kickoff arguments. `--task {id}` → `entity_kind = "task"`, `record_id = {id}`. `--bug {id}` → `entity_kind = "bug"`, `record_id = {id}`.

1. Inspect ONCE (message material only — #40 batched-inspection rule):
   - One `git diff --stat`; at most ONE combined `git diff` if the message needs detail.
     Never per-file diffs, never repeated `git status` — each extra turn re-pays full context.
   - Staging is NOT your decision — the tool derives it from the store record.

2. Craft the commit message:
   - Shape: `<type>(<scope>): <subject>` where `<type>` matches the prevailing
     style in `git log` (fix/feat/chore/docs/refactor/test). Include the record
     ID ({record_id}) in the subject or body. Body states what changed and why.
   - `Co-authored-by:` trailer from the host runtime: Claude Code →
     `Co-authored-by: Claude <noreply@anthropic.com>`; pi / Ollama / other →
     `Co-authored-by: {modelId} <noreply@{provider}.ai>` from the session's `provider` and
     `modelId`; if unresolvable, omit rather than guess. Never hardcode
     `Claude Opus 4.6 <noreply@anthropic.com>` (forge#82 regression).
   - Git's configured `user.name`/`user.email` own authorship; never `--author`.

3. Commit via the tool — ONE call:
   - If the `forge_commit` named tool is available (forgecli): call it —
     `forge_commit({ entity:"{entity_kind}", id:"{record_id}", message:"<message>", trailer:"<line>" })`.
     Never pass the message through a bash string when the typed tool exists.
   - Otherwise (Claude Code): `node .forge/tools/commit-task.cjs --{entity_kind} {record_id} --message "<message>" [--trailer "<Co-authored-by line>"]`
   - The tool owns the choreography: preflight gate (`preflight-gate.cjs --phase commit`
     internally), status precondition (task `approved` / bug `in-progress` — wrong-state runs
     halt with `× {record_id} is in state '{status}' …; /forge:approve must complete first`),
     staging (artifact dir + `summaries.implementation.files_changed` provenance),
     commit-boundary guard (aborts on a pre-staged index), `git commit`, terminal transition
     (task → `committed`; bug → `fixed`, the ONLY post-triage `bug.status` write).
   - On `no files_changed provenance` warning: ONE `git status --porcelain`, then re-run the
     tool with `--also <path>` per source file. Never manual `git add`.
   - Success → JSON with `ok:true`. `committed:true` carries `sha` + `staged`;
     `committed:false, reason:"nothing-to-commit"` is ALSO success (fix already at HEAD /
     staging set clean — the tool still sealed the record's terminal status). Do not
     "fix" a no-op by staging things yourself.
   - Failure (exit 1 / ok:false) → print stderr and HALT — no manual staging, no
     `git reset`, no `--force` retry (operator-gated). Tool file missing → HALT;
     instruct `/forge:update` + `/forge:rebuild tools`.
   - NEVER commit before the tool reports `ok: true` — the premature-commit/reset/redo loop
     is forbidden.

4. Finalize:
   - No summary, no `set-summary` (see Iron Laws). **Do NOT emit a phase event yourself** —
     the orchestrator owns event emission. Return the tool's JSON result as your phase output.
```

<!-- See _fragments/generation-instructions.md for Generation Instructions template -->