@mmerterden/multi-agent-pipeline 20.23.2 → 20.25.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (123) hide show
  1. package/CHANGELOG.md +46 -0
  2. package/README.md +8 -6
  3. package/README.tr.md +7 -5
  4. package/docs/architecture.md +3 -3
  5. package/docs/ecosystem.md +5 -5
  6. package/docs/facts.json +7 -6
  7. package/docs/features.md +9 -4
  8. package/install/catalog-history.json +1 -1
  9. package/install/templates/claude-hooks.json +14 -1
  10. package/install/templates/codex-hooks.json +18 -0
  11. package/manifest.json +126 -98
  12. package/package.json +1 -1
  13. package/pipeline/agents/task-clarifier.md +1 -1
  14. package/pipeline/commands/multi-agent/analysis-jira/SKILL.md +4 -2
  15. package/pipeline/commands/multi-agent/deps/SKILL.md +61 -0
  16. package/pipeline/commands/multi-agent/model/SKILL.md +2 -2
  17. package/pipeline/commands/multi-agent/postmortem/SKILL.md +90 -0
  18. package/pipeline/commands/multi-agent/review/SKILL.md +5 -5
  19. package/pipeline/commands/multi-agent/route-on/SKILL.md +1 -1
  20. package/pipeline/commands/multi-agent/setup/SKILL.md +7 -5
  21. package/pipeline/commands/multi-agent/sync/SKILL.md +4 -4
  22. package/pipeline/commands/multi-agent/testflight-validation/SKILL.md +2 -3
  23. package/pipeline/contract/fixtures/runs-failed.json +1 -1
  24. package/pipeline/contract/fixtures/runs-old-schema.json +1 -1
  25. package/pipeline/contract/fixtures/runs-pr-opened-redacted.json +1 -1
  26. package/pipeline/contract/fixtures/runs-pr-opened.json +1 -1
  27. package/pipeline/contract/fixtures/runs-running.json +1 -1
  28. package/pipeline/lib/analysis-jira-write.sh +70 -0
  29. package/pipeline/lib/credential-inventory.sh +5 -5
  30. package/pipeline/lib/decisions.mjs +130 -0
  31. package/pipeline/lib/fetch-crashlytics.sh +6 -8
  32. package/pipeline/lib/model-rung.sh +1 -1
  33. package/pipeline/lib/plan-todos.sh +177 -37
  34. package/pipeline/lib/post-pr-review.sh +4 -6
  35. package/pipeline/lib/route-state.sh +1 -1
  36. package/pipeline/lib/shadow-git.sh +4 -5
  37. package/pipeline/lib/task-graph.mjs +446 -0
  38. package/pipeline/lib/tdd-evidence.mjs +579 -0
  39. package/pipeline/multi-agent-refs/analysis-template-corporate.md +2 -0
  40. package/pipeline/multi-agent-refs/analysis-template.md +4 -2
  41. package/pipeline/multi-agent-refs/cross-cli-contract.md +10 -11
  42. package/pipeline/multi-agent-refs/features/analysis-jira.md +42 -0
  43. package/pipeline/multi-agent-refs/features/autopilot-decisions.md +34 -0
  44. package/pipeline/multi-agent-refs/features/cost-analysis.md +4 -0
  45. package/pipeline/multi-agent-refs/features/dep-bump.md +176 -0
  46. package/pipeline/multi-agent-refs/features/model-fallback.md +21 -14
  47. package/pipeline/multi-agent-refs/features/mutation-probe.md +58 -0
  48. package/pipeline/multi-agent-refs/features/plan-checks.md +67 -0
  49. package/pipeline/multi-agent-refs/features/plan-todos.md +40 -1
  50. package/pipeline/multi-agent-refs/features/rework-escalation.md +49 -0
  51. package/pipeline/multi-agent-refs/features/scope-check.md +1 -0
  52. package/pipeline/multi-agent-refs/help/en.md +2 -0
  53. package/pipeline/multi-agent-refs/help/tr.md +2 -0
  54. package/pipeline/multi-agent-refs/phases/phase-0-init.md +1 -1
  55. package/pipeline/multi-agent-refs/phases/phase-1-plan.md +2 -3
  56. package/pipeline/multi-agent-refs/phases/phase-2-dev.md +7 -7
  57. package/pipeline/multi-agent-refs/phases/phase-3-review.md +18 -16
  58. package/pipeline/multi-agent-refs/phases/phase-5-report.md +3 -3
  59. package/pipeline/multi-agent-refs/picker-contract.md +3 -2
  60. package/pipeline/multi-agent-refs/response-shape.md +65 -0
  61. package/pipeline/multi-agent-refs/tracker-contract.md +6 -6
  62. package/pipeline/rules/response-shape.md +18 -0
  63. package/pipeline/schemas/agent-state.schema.json +36 -1
  64. package/pipeline/schemas/phases.json +4 -0
  65. package/pipeline/schemas/plan-todos.schema.json +104 -3
  66. package/pipeline/schemas/planning-output.schema.json +46 -0
  67. package/pipeline/schemas/prefs.schema.json +122 -3
  68. package/pipeline/scripts/_code-graph.mjs +2 -2
  69. package/pipeline/scripts/_jsonl.mjs +151 -0
  70. package/pipeline/scripts/_plan-overlap.mjs +231 -0
  71. package/pipeline/scripts/_redact.mjs +124 -10
  72. package/pipeline/scripts/_transcript-hosts.mjs +406 -0
  73. package/pipeline/scripts/analysis-story-tree.mjs +153 -8
  74. package/pipeline/scripts/autopilot-publish.mjs +12 -1
  75. package/pipeline/scripts/build-stack-plugins.mjs +3 -3
  76. package/pipeline/scripts/capture-flush.sh +7 -7
  77. package/pipeline/scripts/code-graph-rules/android.json +1 -1
  78. package/pipeline/scripts/cost-analyze.mjs +32 -43
  79. package/pipeline/scripts/cost-table.json +35 -19
  80. package/pipeline/scripts/decisions-log.mjs +118 -0
  81. package/pipeline/scripts/dep-bump.mjs +1556 -0
  82. package/pipeline/scripts/edit-syntax-gate.mjs +362 -0
  83. package/pipeline/scripts/edit-syntax-gate.sh +32 -0
  84. package/pipeline/scripts/find-polluter.mjs +281 -0
  85. package/pipeline/scripts/gate-ledger.mjs +46 -13
  86. package/pipeline/scripts/gc-abandoned.sh +2 -2
  87. package/pipeline/scripts/gen-mode-dispatch.mjs +3 -3
  88. package/pipeline/scripts/git-path.mjs +1 -2
  89. package/pipeline/scripts/host-hooks.mjs +265 -0
  90. package/pipeline/scripts/jira-attach.sh +1 -1
  91. package/pipeline/scripts/keychain.py +3 -3
  92. package/pipeline/scripts/mutation-probe.mjs +484 -0
  93. package/pipeline/scripts/output-quality-check.sh +1 -1
  94. package/pipeline/scripts/phase-tracker.sh +5 -6
  95. package/pipeline/scripts/phase0-exit-gate.mjs +3 -3
  96. package/pipeline/scripts/plan-complexity.mjs +259 -0
  97. package/pipeline/scripts/pre-push-check.sh +3 -6
  98. package/pipeline/scripts/review-decision-gate.mjs +33 -1
  99. package/pipeline/scripts/rework-escalation.mjs +264 -0
  100. package/pipeline/scripts/test-strength.mjs +5 -3
  101. package/pipeline/scripts/transcript-index.mjs +1131 -0
  102. package/pipeline/scripts/uninstall.mjs +90 -4
  103. package/pipeline/scripts/update-issue-progress.sh +4 -6
  104. package/pipeline/scripts/usage-report.mjs +2 -2
  105. package/pipeline/scripts/validate-planning.mjs +48 -6
  106. package/pipeline/skills/.skill-manifest.json +20 -12
  107. package/pipeline/skills/.skills-index.json +23 -1
  108. package/pipeline/skills/shared/README.md +5 -3
  109. package/pipeline/skills/shared/core/multi-agent/SKILL.md +6 -6
  110. package/pipeline/skills/shared/core/multi-agent-analysis-jira/SKILL.md +4 -2
  111. package/pipeline/skills/shared/core/multi-agent-deps/SKILL.md +60 -0
  112. package/pipeline/skills/shared/core/multi-agent-model/SKILL.md +2 -2
  113. package/pipeline/skills/shared/core/multi-agent-postmortem/SKILL.md +69 -0
  114. package/pipeline/skills/shared/core/multi-agent-review/SKILL.md +5 -5
  115. package/pipeline/skills/shared/core/multi-agent-route-on/SKILL.md +1 -1
  116. package/pipeline/skills/shared/core/multi-agent-setup/SKILL.md +7 -5
  117. package/pipeline/skills/shared/core/multi-agent-sync/SKILL.md +4 -4
  118. package/pipeline/skills/shared/core/multi-agent-testflight-validation/SKILL.md +2 -3
  119. package/pipeline/skills/shared/external/app-store-optimization/SKILL.md +15 -0
  120. package/pipeline/skills/shared/external/app-store-optimization/evals/evals.json +13 -0
  121. package/pipeline/skills/shared/external/debugging-strategies/SKILL.md +8 -0
  122. package/pipeline/skills/shared/external/ios-coding-standard/references/rules.yml +2 -2
  123. package/pipeline/skills/skills-index.md +3 -1
@@ -61,6 +61,7 @@ Pipeline entries:
61
61
 
62
62
  /multi-agent "task" Worktree
63
63
  /multi-agent:autopilot "task" Worktree, no questions
64
+ /multi-agent:deps [pkg[@ver]] [--major] Bump one dependency, fix only what the bump broke, review, PR; rolls back past depBump.maxFixRounds
64
65
 
65
66
  Phase 0 Step 5b asks where the branch lives; there is no flag for it.
66
67
  autopilot skips every confirmation INCLUDING the plan gate and the workspace
@@ -103,6 +104,7 @@ Post-Hoc & Side-Channel:
103
104
  /multi-agent:build-optimize iOS-only Xcode build perf wrapper → benchmark + analyze + recommend-first .build-benchmark/optimization-plan.md
104
105
  /multi-agent:create-jira ["desc"] [figma-url] [swagger-url] Create a Jira Task/Bug/Story matching team conventions (type, sprint, preview + approval)
105
106
  /multi-agent:diff-explain Map a Phase 3 triage finding back to specific diff lines
107
+ /multi-agent:postmortem [#id|file.jsonl] Post-mortem of a run from its transcripts: loops, stalls, root-cause hypotheses on file:line (read-only, redacted)
106
108
  /multi-agent:estimate <doc|text> Effort range from similar closed work: P25-P75 per role, with the tickets behind it
107
109
  /multi-agent:scenario-audit <csv> Test scenarios vs the code: PRESENT / PARTIAL / ABSENT / UNCLEAR, each PRESENT on a resolving file:line
108
110
  /multi-agent:graph Build and query the repo code graph (symbols, imports, references), LLM-free
@@ -61,6 +61,7 @@ Pipeline girişleri:
61
61
 
62
62
  /multi-agent "task" Worktree var
63
63
  /multi-agent:autopilot "task" Worktree var, soru yok
64
+ /multi-agent:deps [paket[@sürüm]] [--major] Tek bağımlılığı yükselt, yalnızca yükseltmenin kırdığını düzelt, review, PR; depBump.maxFixRounds aşılınca geri alır
64
65
 
65
66
  Faz 0 Adım 5b branch'in nerede yaşayacağını sorar; bayrağı yok.
66
67
  autopilot plan kapısı ve çalışma alanı sorusu dahil her onayı atlar, otomatik
@@ -102,6 +103,7 @@ Post-Hoc & Side-Channel:
102
103
  /multi-agent:build-optimize iOS-only Xcode build performance wrapper → benchmark + analiz + recommend-first .build-benchmark/optimization-plan.md
103
104
  /multi-agent:create-jira ["açıklama"] [figma-url] [swagger-url] Takım standartlarına uygun Jira Task/Bug/Story oluştur (tip, sprint, önizleme + onay)
104
105
  /multi-agent:diff-explain Phase 3 triage bulgusunu diff satırlarına eşle
106
+ /multi-agent:postmortem [#id|dosya.jsonl] Koşunun transkriptlerinden post-mortem: döngüler, takılmalar, dosya:satır dayanaklı kök-neden hipotezleri (salt-okunur, redakte)
105
107
  /multi-agent:estimate <doc|metin> Benzer kapanmış işlerden efor aralığı: rol başına P25-P75, dayandığı ticket'larla
106
108
  /multi-agent:scenario-audit <csv> Test senaryolarını koda karşı denetle: VAR / KISMEN / YOK / BELİRSİZ, her VAR çözülen bir dosya:satır ile
107
109
  /multi-agent:graph Repo kod grafiğini kur ve sorgula (semboller, import'lar, referanslar), LLM'siz
@@ -652,7 +652,7 @@ Log: `Phase 0 Step 7.7: testDepth = {unit|unit+ui|unit+mcp} (source {user|autopi
652
652
 
653
653
  5. Phase 1 Analysis reads `state.clarification.userAnswers` (when present) as additional context - fold answers into the Explore prompt so downstream phases inherit the resolution.
654
654
 
655
- **Reference:** `$HOME/.claude/agents/task-clarifier.md` - scoring rubric, question-quality rules and the ~$0.0025-per-call cost note.
655
+ **Reference:** `$HOME/.claude/agents/task-clarifier.md` - scoring rubric, question-quality rules and the ~$0.0004-per-call cost note.
656
656
 
657
657
  #### Telemetry
658
658
 
@@ -402,6 +402,8 @@ Progress line: ` → checking validator validate-planning`
402
402
 
403
403
  Non-zero exit fails CLOSED: emit the validator stderr + `errors[]` verbatim, attempt ONE self-correction rework (re-invoke the planner with the errors quoted, overwrite `$PLAN_FILE`), re-run the validator. If it fails again -> HALT the phase (never enter Phase 2 with an invalid plan) with recovery hint: `ERR: plan output failed validate-planning.mjs twice. Inspect $PLAN_FILE against $HOME/.claude/schemas/planning-output.schema.json, then resume with /multi-agent:resume #N.` Record `agent-state.phases["1"].validator` (`pass` | `pass-after-rework` | `halted`).
404
404
 
405
+ Then `plan-complexity.mjs "$PLAN_FILE" --graph "$GRAPH_PATH" --write` (`$GRAPH_PATH` as in `features/code-graph.md`; unset, the default graph path); split `split[]` tasks (`features/plan-checks.md`).
406
+
405
407
  Log: "Phase 1: Plan - {N} tasks created, {M} with architecture review, validator:pass"
406
408
 
407
409
  #### Step 10 - Put the plan on the widget (required)
@@ -423,9 +425,6 @@ and stored, only invisible.
423
425
  printf '%s' "$PLAN_JSON" | bash "$HOME/.claude/lib/plan-todos.sh" set "$TASK_ID" -
424
426
  ```
425
427
 
426
- `set` converts a planning-output document itself, so the `tasks[]`-to-`todos[]`
427
- mapping has one definition, the tested one.
428
-
429
428
  Phase 2 (Dev) then iterates with `plan-todos.sh next "$TASK_ID"` until empty, calling `start` before each step and `complete` (with notes) or `fail`/`skip` after. Phase 3 (Review) reads the Todo list to verify all `completed` items map to diff hunks. Phase 5 (Report) renders `list` into the agent-log + PR body.
430
429
 
431
430
  **Why opt-in:** `planning-output.schema.json` already drives Phase 2 dependency order; `plan.todos[]` adds notes, durations and status transitions at the cost of a state write per step. Flip on for visibility into long features.
@@ -47,16 +47,18 @@ The analysis document is the SOLE design source in Phase 2. Variant choices, pad
47
47
 
48
48
  <!-- progress-contract: applied -->
49
49
 
50
- **Progress (per `$HOME/.claude/multi-agent-refs/progress-contract.md`):** every non-trivial step emits one `→ <verb> <object>` line at immediate flush. Canonical set for standard TDD: `→ reading <file>`, `→ writing test <name>`, `→ running xcodebuild RED`, `→ writing code <file>`, `→ running xcodebuild GREEN`, `→ committing WIP <summary>`. Component-task dispatch emits the line `→ dispatching create-component <componentName>` immediately before the Skill-tool call and then relays the plugin skill's progress lines verbatim under indent ` →`.
50
+ **Progress (per `$HOME/.claude/multi-agent-refs/progress-contract.md`):** every non-trivial step emits one `→ <verb> <object>` line at immediate flush. Canonical set for standard TDD: `→ reading <file>`, `→ writing test <name>`, `→ running xcodebuild RED`, `→ writing code <file>`, `→ running xcodebuild GREEN`, `→ committing WIP <summary>`. Component-task dispatch emits the line `→ dispatching create-component <componentName>` before the Skill-tool call, then relays the plugin skill's progress lines verbatim under indent ` →`.
51
51
 
52
52
  #### Input contract
53
53
 
54
54
  Phase 2 consumes the Phase 1 output object conforming to `$HOME/.claude/schemas/planning-output.schema.json` - the task graph (`tasks[]` with `id`, `title`, `type`, `files`, and optional `dependsOn` / `acceptanceCriteria`) plus the architecture review notes. Tasks execute in dependency order; the schema's `dependsOn` field drives the ready-task picker.
55
55
 
56
- **Plan Todo iteration (opt-in)**: gated by `prefs.global.planTodos.enabled` (default: `false`). When enabled and Phase 1 Step 11 emitted a `plan.todos[]`, Phase 2 iterates via `$HOME/.claude/lib/plan-todos.sh next/start/complete/fail` instead of walking `tasks[]` directly. When disabled, the loop walks `tasks[]` from `planning-output` - TDD contract is unchanged. Full helper loop + state semantics: `$HOME/.claude/multi-agent-refs/features/plan-todos.md`. A todo with `sourceTag: Reuse` binds the file analysis already found; `Modify` edits in place. Writing a new file over a `Reuse` step is a Locked 11 violation and Phase 3 flags it.
56
+ **Plan Todo iteration (opt-in)**: gated by `prefs.global.planTodos.enabled` (default `false`). When enabled and Phase 1 Step 11 emitted `plan.todos[]`, iterate via `$HOME/.claude/lib/plan-todos.sh next/start/complete/fail/drift`; disabled, walk `tasks[]`, same TDD contract. Each todo records RED and GREEN runs (`tdd-red` / `tdd-green`); `complete` checks them per `prefs.global.tddEvidence.mode`. Loop + exemptions: `$HOME/.claude/multi-agent-refs/features/plan-todos.md`. A todo with `sourceTag: Reuse` binds the file analysis already found; `Modify` edits in place. Writing a new file over a `Reuse` step is a Locked 11 violation and Phase 3 flags it.
57
57
 
58
58
  **Shadow-Git checkpoints (opt-in)**: gated by `prefs.global.shadowGit.enabled` (default: `false`). When enabled, the orchestrator snapshots the worktree via `$HOME/.claude/lib/shadow-git.sh` so sub-phase rollback is possible without touching the project's real `.git` history. Lifecycle: `shadow-git.sh init` (Phase 0 baseline), `shadow-git.sh snapshot` (per step after `plan-todos complete`), `shadow-git.sh restore <sha> --files` (rollback). Modes: `per-todo-step` (default) or `per-tool-call`. Full wiring + storage cap: `$HOME/.claude/multi-agent-refs/features/shadow-git.md`.
59
59
 
60
+ **Dependency bump** (`state.mode == "deps"`): `dep-bump.mjs apply` first, then capped fix rounds: `$HOME/.claude/multi-agent-refs/features/dep-bump.md`.
61
+
60
62
  #### Component tasks - delegated dispatch (taskType === "component")
61
63
 
62
64
  When Phase 0 Step 7 classified the task as `component`, Phase 2 delegates the entire phase to the enabled `ai-<platform>-toolkit` marketplace plugin's component skill (`create-component`, fallback `create-ui-component`) via the Skill tool and does NOT run the TDD loop below. The dispatch layer passes the plugin skill the analysis Section 6 (Bileşen Envanteri) entry + Section 13.1 conventions for the named component as context. Because plugin skills do not write pipeline state, the **dispatch layer** (not the skill) owns `state.phases["2"].subphases[]`, recording a coarse component-build row - multi-agent's `phase-tracker` reads that array with no special case. Plugin resolution (dual-name), dispatch call, failure/resume, multi-repo, and the intentional cross-CLI divergence live in `$HOME/.claude/multi-agent-refs/component-dispatch.md` - read it before editing component-task behaviour here. Phase 2 still owns: progress line `-> dispatching create-component <name>`, `retryCount` cap at 3, and fallthrough to the TDD path when dispatch prerequisites are missing (`taskType` absent OR the plugin is not enabled in this repo -> log anomaly, halt or run TDD per component-dispatch.md).
@@ -88,6 +90,7 @@ When re-entering from Phase 3:
88
90
  5. `rejected` items are never touched. Log their IDs + triage reasons for audit only.
89
91
  6. After rework, increment `state.phases["2"].retryCount`; hard-kill at `retryCount === 3` and escalate to the user. Do not loop indefinitely. When `prefs.global.autopilotCircuitBreaker.enabled` is true (default), record the hard-kill before escalating as `state.circuitBreaker = {tripped: true, trigger: 3, detail: "rework cycles exhausted", checkpoint: {phase: 3, step: "re-entry", iteration: <n>}, trippedAt, counters: {reworkCycles: <n>}}`: the rework-storm trigger; `autopilotCircuitBreaker.maxReworkCycles` (default 3) is bounded above by this cap.
90
92
  7. When `state.reviewIterations[-1].delta` exists, `stillPresent[]` findings come first in the task list, quoted `STILL PRESENT after round N-1's fix`; repeating the previous attempt is the loop the circuit-breaker stops.
93
+ 8. Before each rework dispatch, `rework-escalation.mjs` picks the rung; findings and the prior report go as files (`features/rework-escalation.md`).
91
94
 
92
95
  If the latest iteration has `triage.approved === true` AND `accepted === []`, Phase 2 was entered by mistake - log the anomaly and return to Phase 3.
93
96
 
@@ -103,7 +106,7 @@ $HOME/.claude/scripts/log-metric.sh "$TASK_ID" 2 rework.started \
103
106
  For each task (respecting dependency order), on start and on end: `bash $HOME/.claude/scripts/phase-tracker.sh sub 2 <task_id> "<title>" in_progress|completed|failed`.
104
107
 
105
108
  1. **Update task status: `in_progress` (required - do not skip or defer)**
106
- - **Why mandatory**: the board/tracker visually stays in "Todo" until this runs. Skipping it means reviewers and the rest of the team cannot see that work has started, and automations downstream (status reports, kanban swimlanes) will be wrong.
109
+ - **Why**: the board shows "Todo" until this runs, and status reports and swimlanes read it.
107
110
  - **Where it applies**:
108
111
  - Jira: transition issue to "In Progress" via REST API (`/rest/api/2/issue/{id}/transitions`)
109
112
  - GitHub Projects V2: `updateProjectV2ItemFieldValue` on the Status field (singleSelectOptionId)
@@ -112,10 +115,7 @@ For each task (respecting dependency order), on start and on end: `bash $HOME/.c
112
115
  - Re-read the Status field after mutation.
113
116
  - If the value is NOT `In Progress` (Jira) / `In Develop` (Projects V2), re-fetch current option IDs and retry ONCE.
114
117
  - If verify still fails after retry → log error, do NOT proceed to TDD. The mutation silently failed and continuing would leave the task mis-tracked.
115
- 2. **Multi-submodule awareness**: If the project has submodules (detected in Phase 0 Step 7), development may span multiple submodules. For example, a UI component might need:
116
- - New types/tokens in the **common** submodule
117
- - The component itself in the **uicomponents** submodule
118
- - Work in BOTH submodules in the same task - this is normal and expected
118
+ 2. **Multi-submodule awareness**: a task may span the submodules Phase 0 Step 7 detected (e.g. tokens in **common**, the component in **uicomponents**); that is expected.
119
119
  3. **TDD cycle** (Launch Agent with `model: "sonnet"`) - gated by `state.testPolicy`: `tdd` = the loop below; `tests-after` = skip RED, author the same tests once green; `none` = author no tests (existing ones never weakened), report "tests not written - project policy" rather than a gap.
120
120
 
121
121
  **RED - Write ONE failing test first:**
@@ -100,9 +100,9 @@ Persist the totals as `state.diffRisk` (Phase 4 `risk` section, Phase 5, `run-me
100
100
  | `ui_critical` | 1.5 | path matches `*View.swift`, `*Screen.kt`, `*Configuration.swift`, etc. |
101
101
  | `loc_changed` | 1.0 | base sensitivity to total `+/-` lines |
102
102
 
103
- **Reviewer prompt injection**: when `$RISK_JSON` is non-empty, the orchestrator builds a `${PRIORITY_FILES}` block (numbered list of top-N files with their score + signals) and injects it once per reviewer. Reviewer prompt template (`code-reviewer.md`) treats it as advisory and does not echo it back. Triage does not see the priority list - its job is to filter the merged findings, not the diff.
103
+ **Reviewer prompt injection**: when `$RISK_JSON` is non-empty, the orchestrator builds a `${PRIORITY_FILES}` block (numbered list of top-N files with their score + signals) and injects it once per reviewer. Reviewers (`code-reviewer.md`) treat it as advisory and do not echo it back. Triage does not see the priority list.
104
104
 
105
- **Gate behavior**: **never blocking**. If risk scoring fails (git, parse, validator), continue with no priority hint: reviewers get the full diff in default order. Failures are logged:
105
+ **Gate behavior**: if risk scoring fails (git, parse, validator), continue with no priority hint: reviewers get the full diff in default order. Failures are logged:
106
106
 
107
107
  ```bash
108
108
  [ -z "$RISK_JSON" ] && $HOME/.claude/scripts/log-metric.sh "$TASK_ID" 3 review.diff_risk_skipped reason=$REASON
@@ -119,11 +119,11 @@ $HOME/.claude/scripts/log-metric.sh "$TASK_ID" 3 review.diff_risk \
119
119
  files=$(jq '.totals.files' <<< "$RISK_JSON")
120
120
  ```
121
121
 
122
- **Opt-out**: `prefs.global.diffRiskAdvisory = false` skips this step (no script, no priority block). Default `true`: the cost is bounded and the signal-to-noise is measured against the golden-task fixtures.
122
+ **Opt-out**: `prefs.global.diffRiskAdvisory = false` skips this step. Default `true`.
123
123
 
124
124
  #### Step 1.76 - Test-integrity gate (produces BLOCKING findings)
125
125
 
126
- Step 1.75's `test_lines_removed` hint is too weak for what it detects: a suite made green by deleting tests. This makes it blocking findings triage must adjudicate. Pure function of the full report. `--out` always writes the file, the empty result included.
126
+ Step 1.75's `test_lines_removed` hint is too weak for a suite made green by deleting tests, so this makes it blocking findings triage must adjudicate. Pure function of the full report. `--out` always writes the file, the empty result included.
127
127
 
128
128
  ```bash
129
129
  TI_FILE="$WORKTREE/.pipeline/test-integrity.json"
@@ -136,6 +136,8 @@ TI_COUNT=$(jq -r '.count // 0' "$TI_FILE" 2>/dev/null || echo 0)
136
136
 
137
137
  The gate never blocks the phase; it *emits* blocking findings (unreadable input: zero). Feed it the FULL report: `--top` hides a shrinking test file below the cut. **No opt-out**: a run that can switch off its own anti-reward-hacking control cannot be trusted to report a pass.
138
138
 
139
+ **TDD evidence**: `node $HOME/.claude/lib/tdd-evidence.mjs unverified --state "$STATE_FILE"` lists todos closed without RED/GREEN or by `--no-tests`, as reviewer notes, not findings.
140
+
139
141
  #### Step 1.761 - Owned-path gate (BLOCKING findings)
140
142
 
141
143
  Phase 2 Gate 0 again, same base:
@@ -146,7 +148,7 @@ node $HOME/.claude/scripts/owned-path-gate.mjs --repo "$WORKTREE" --base "origin
146
148
  --state "$STATE_FILE" --out "$OP_FILE"
147
149
  ```
148
150
 
149
- `--out` drops the old file; exit 2 writes none. A missing `$OP_FILE` is a gate error, never "no findings" (`review-decision-gate.mjs` exit 3 under the gates). Findings merge at Step 3.0. Contract: `features/repo-profile.md`. Step 1.762: `features/valven.md`.
151
+ `--out` drops the old file; exit 2 writes none. A missing `$OP_FILE` is a gate error, never "no findings" (`review-decision-gate.mjs` exit 3 under the gates). Findings merge at Step 3.0. Contract: `features/repo-profile.md`. Step 1.762: `features/valven.md`; opt-in 1.763: `features/mutation-probe.md`.
150
152
 
151
153
  #### Step 1.77 - Reviewer scope (cost gate)
152
154
 
@@ -235,10 +237,10 @@ Launch Agent instances **in parallel** using the shared `code-reviewer` subagent
235
237
 
236
238
  | Reviewer | subagent_type | Claude Code | Copilot CLI | Codex CLI | Focus | Skills Referenced |
237
239
  | ---------- | --------------- | --- | --- | --- | --- | --- |
238
- | Reviewer 1 | `code-reviewer` | `claude-fable-5` | `claude-opus-5` | `gpt-5.6` @ `xhigh` | Deep security + architecture | `api-security-best-practices`, `architecture` |
239
- | Reviewer 2 | `code-reviewer` | `claude-opus-5` | `gpt-5.4` | `gpt-5.4` @ `high` | Edge cases, different perspective | cross-model diversity |
240
- | Reviewer 3 | `code-reviewer` | `claude-sonnet-5` | `claude-sonnet-5` | `gpt-5.6` @ `medium` | Quality + correctness + naming | `ai-backend-toolkit:clean-code`, stack-specific skill |
241
- | Triage | triage persona | `claude-fable-5` | `claude-opus-5` | `gpt-5.6` @ `max` | Filter false positives + out-of-scope | - |
240
+ | Reviewer 1 | `code-reviewer` | `claude-fable-5-1` | `claude-opus-4.7` | `gpt-5.6` @ `xhigh` | Deep security + architecture | `api-security-best-practices`, `architecture` |
241
+ | Reviewer 2 | `code-reviewer` | `claude-opus-5-5` | `gpt-5.4` | `gpt-5.4` @ `high` | Edge cases, different perspective | cross-model diversity |
242
+ | Reviewer 3 | `code-reviewer` | `claude-sonnet-5-5` | `claude-sonnet-4.6` | `gpt-5.6` @ `medium` | Quality + correctness + naming | `ai-backend-toolkit:clean-code`, stack-specific skill |
243
+ | Triage | triage persona | `claude-fable-5-1` | `claude-opus-4.7` | `gpt-5.6` @ `max` | Filter false positives + out-of-scope | - |
242
244
 
243
245
  Reviewer count per host: **Claude Code 3, Copilot CLI 3, Codex CLI 3** - **2** on Claude Code with the fable rung off, per `$HOME/.claude/multi-agent-refs/features/model-fallback.md`.
244
246
 
@@ -263,7 +265,7 @@ borderline finding. Where the diversity budget goes instead:
263
265
 
264
266
  Each reviewer inherits the `code-reviewer` agent's focus areas (Security, Architecture, Quality, Performance) and output contract. The orchestrator overrides only the model and the stack-specific skill per-reviewer - no prompt duplication.
265
267
 
266
- **Model override wiring:** `code-reviewer.md` declares `preferredModel: fable`, so Reviewer 1 uses the persona default (Fable 5). Reviewer 2 (`claude-opus-5` on Claude Code, `gpt-5.4` elsewhere) and Reviewer 3 (`claude-sonnet-5`) set `PHASE_MODEL_OVERRIDE=<model>` before dispatch - the orchestrator exports `CLAUDE_CODE_SUBAGENT_MODEL` on Claude Code, or passes `--model` on Copilot CLI. Full precedence rule: `skills/shared/core/multi-agent/SKILL.md#agent-dispatch--per-persona-model-routing`. Fable dispatches are subject to the fallback contract (`$HOME/.claude/multi-agent-refs/features/model-fallback.md`): dispatch-error retry walks `fable -> opus -> sonnet` and budget-ceiling downgrade.
268
+ **Model override wiring:** `code-reviewer.md` declares `preferredModel: fable`, so Reviewer 1 uses the persona default (Fable 5.1). Reviewer 2 (`claude-opus-5-5` on Claude Code, `gpt-5.4` elsewhere) and Reviewer 3 (sonnet rung, per host above) set `PHASE_MODEL_OVERRIDE=<model>` before dispatch - the orchestrator exports `CLAUDE_CODE_SUBAGENT_MODEL` on Claude Code, or passes `--model` on Copilot CLI. Full precedence rule: `skills/shared/core/multi-agent/SKILL.md#agent-dispatch--per-persona-model-routing`. Fable dispatches are subject to the fallback contract (`$HOME/.claude/multi-agent-refs/features/model-fallback.md`): dispatch-error retry walks `fable -> opus -> sonnet` and budget-ceiling downgrade.
267
269
 
268
270
  **Stack-specific skills loaded per reviewer** (from Phase 1 `detectedStack`). All three columns are used on every host; Reviewer 2 reads them as Opus on Claude Code and as GPT-5.4 elsewhere.
269
271
 
@@ -378,11 +380,11 @@ ANON=$(jq -n --argjson r "$REVIEWERS_JSON" --arg t "$TASK_ID" --argjson i "$ITER
378
380
 
379
381
  `$REVIEWERS_JSON` is `state.reviewIterations[i].reviewers`. Findings come back with `foundBy: "Source A|B|C"` and every identity key removed. Persist the map to `state.reviewIterations[i].anonymizationMap` for Phase 5 per-reviewer telemetry, and **never put the map in a prompt**.
380
382
 
381
- Then append the deterministic findings (Steps 1.76, 1.761, 1.762, 2.7):
383
+ Then append the deterministic findings (Steps 1.76-1.763, 2.7):
382
384
 
383
385
  ```bash
384
386
  SA_FILE="$WORKTREE/.pipeline/security-audit-$ITERATION.json"
385
- MERGED=$(printf '%s' "$ANON" | cat - "$TI_FILE" "$OP_FILE" "$VG_FILE" "$SA_FILE" 2>/dev/null \
387
+ MERGED=$(printf '%s' "$ANON" | cat - "$TI_FILE" "$OP_FILE" "$VG_FILE" "$MP_FILE" "$SA_FILE" 2>/dev/null \
386
388
  | jq -s '.[0] + ([.[1:][] | .findings // []] | add // [])')
387
389
  ```
388
390
 
@@ -390,7 +392,7 @@ Deterministic findings keep their `tag` (`test_integrity`, `owned_path`, `valven
390
392
 
391
393
  ##### 3.1 Short-circuit: no findings
392
394
 
393
- If **merged** findings `length === 0`, **skip triage**: write empty result `{"accepted": [], "deferred": [], "rejected": [], "approved": true}`, log, proceed to Phase 3. Note this is the merged count from 3.0: a run with zero reviewer findings but a non-empty test-integrity set must NOT short-circuit.
395
+ If **merged** findings `length === 0`, **skip triage**: write empty result `{"accepted": [], "deferred": [], "rejected": [], "approved": true}`, log, proceed to Phase 3. This is the merged count from 3.0: zero reviewer findings plus any gate finding must NOT short-circuit.
394
396
 
395
397
  **Autopilot** (or `MULTI_AGENT_UNATTENDED=1`): the triage output, this empty one too, goes through `verify-citations.mjs "$TRIAGE_FILE" --repo "$WORKTREE" --worktree --state "$STATE_FILE"` (every bucket, each `quote` against its line, pre-existing claims against the base commit): `$HOME/.claude/multi-agent-refs/features/unattended-gates.md` section 5. Then `review-decision-gate.mjs` (end of 3.7).
396
398
 
@@ -574,11 +576,11 @@ Merge the JSON into `state.reviewIterations[-1].delta` via `write-state.mjs`; em
574
576
 
575
577
  #### Step 4 - Consensus + Action (triage-driven)
576
578
 
577
- If `triage.consensus.verdict` is `split` or `unverified`, surface `consensus.disagreements[]` to the user before acting: interactive modes show the split and ask whether to treat the unverified agreement as a pass (picker-contract: Trust / Re-review / Treat-as-blocking); autopilot logs `review.consensus=<verdict>` and proceeds on the triage verdict. Never silently average a split into a pass.
579
+ If `triage.consensus.verdict` is `split` or `unverified`, surface `consensus.disagreements[]` to the user before acting: interactive modes show the split and ask whether to treat the unverified agreement as a pass (picker-contract: Trust / Re-review / Treat-as-blocking); autopilot logs `review.consensus=<verdict>`, proceeds on the triage verdict, recorded per `features/autopilot-decisions.md`. Never silently average a split into a pass.
578
580
 
579
581
  Act **only on triage.accepted**:
580
582
 
581
- - **accepted.blocking** → back to Phase 2 (max 3 iterations, with reflection prompt citing only accepted items). The reflection prompt names findings by `fingerprint` and quotes `delta.stillPresent` first, marked `STILL PRESENT after round N-1's fix`. When Step 3.7 ran and `state.reviewIterations[-1].verifyByTest.redTests[]` is non-empty, the reflection prompt cites each red test: "a failing repro test already exists at <testRef>; make it green; do not delete or weaken it."
583
+ - **accepted.blocking** → back to Phase 2 (max 3 iterations, rung per `features/rework-escalation.md`, reflection prompt cites only accepted items). The reflection prompt names findings by `fingerprint` and quotes `delta.stillPresent` first, marked `STILL PRESENT after round N-1's fix`. When Step 3.7 ran and `state.reviewIterations[-1].verifyByTest.redTests[]` is non-empty, the reflection prompt cites each red test: "a failing repro test already exists at <testRef>; make it green; do not delete or weaken it."
582
584
  - **accepted.important** → fix and re-review
583
585
  - **accepted.suggestion** → apply if reasonable
584
586
  - **deferred** → append to Phase 5 report as "follow-up items" (do not block)
@@ -595,7 +597,7 @@ node $HOME/.claude/scripts/learnings-ledger.mjs add --kind fact \
595
597
  --scope "<file-or-area glob from the finding>" --task "$TASK_ID"
596
598
  ```
597
599
 
598
- Statement shape: the durable rule/root cause, not the symptom - "force-unwrapped optional in async callback path", not "fixed crash in LoginView". Always pass `--diagnosis` with the causal why (Reflexion: the verbal reason prevents recurrence; a bare outcome does not). Dedup built in (exit 2 = already stored). Lessons re-enter Phase 1 + triage via `learnings-ledger.mjs brief` (renders diagnosis as "(why: ...)").
600
+ Statement: the root cause, not the symptom ("force-unwrapped optional in async callback path", not "fixed crash in LoginView"). Always pass `--diagnosis`, the causal why: a bare outcome does not prevent recurrence. Dedup built in (exit 2 = already stored). Lessons re-enter Phase 1 + triage via `learnings-ledger.mjs brief` (renders diagnosis as "(why: ...)").
599
601
 
600
602
  Progress line: ` → writing lesson to learnings ledger ({N} entries)`
601
603
 
@@ -170,6 +170,8 @@ Skipped sections: when `planTodos.enabled` is false or no `plan.todos[]` was emi
170
170
 
171
171
  (the last three columns come from `reviewIterations[i].delta.counts` (Phase 3 Step 3.8) and read `-` on iteration 1 and on runs that predate the delta; a tripped circuit-breaker is one extra line under the table: `Circuit-breaker tripped: trigger {n}, {detail}`)
172
172
 
173
+ (autopilot: `decisions-log.mjs render --state "$STATE_FILE"` output verbatim; own heading, nothing when empty)
174
+
173
175
  ## Files Changed
174
176
 
175
177
  (git diff --stat output)
@@ -317,8 +319,6 @@ bash $HOME/.claude/scripts/memory-save.sh "$PROJECT_ROOT" --from-json memory-syn
317
319
  - **user**: only if the user disclosed new context about their role, expertise, or team layout
318
320
  - **Otherwise return `[]`** - blank is the correct default. Do not save derivable facts (code structure, git history, command outputs).
319
321
 
320
- Zero new memories is normal and expected. A typical run produces one or none.
321
-
322
322
  Tracker: `phase-tracker.sh sub 5 3 "Knowledge+Memory" completed`.
323
323
 
324
324
  Log: "Phase 5: Knowledge captured ({N} entries to {files})"
@@ -335,7 +335,7 @@ If user does not respond at the channels multi-select menu within 30 minutes (wa
335
335
  4. Session exits cleanly. State persisted: `state.currentPhase=7, state.waitingFor="user-channels-choice", state.channelsTimeout=true`.
336
336
  5. Resume contract: `/multi-agent:resume <task-id>` re-opens the channels menu with the original state bundle (pipeline log, PR metadata, prefs pre-ticks).
337
337
 
338
- Rationale: silently posting defaults to Jira / Confluence after a timeout would leak wrong-tone content to external systems. Hard-stop + resume is the safer policy.
338
+ Rationale: posting defaults after a timeout would publish text nobody approved.
339
339
 
340
340
  ---
341
341
 
@@ -156,7 +156,8 @@ longer exists. A remembered choice is evidence about this user and this repo; an
156
156
  order is a guess that happens to be sorted. Where the two agree nothing changes, and
157
157
  where they disagree the remembered one is the answer with a reason behind it.
158
158
 
159
- The run records which rule fired (`remembered` or `default`). An autopilot run cannot be
159
+ The run records which rule fired (`remembered`, `default`, or `derived` when the answer follows from the task itself) and lists the choice in
160
+ `state.decisions[]` (`features/autopilot-decisions.md`). An autopilot run cannot be
160
161
  asked anything, so the only thing that keeps it accountable is being readable afterwards.
161
162
 
162
163
  ## Background (unattended, not autopilot) contract
@@ -189,6 +190,6 @@ park it writes `agent-state.json` beside its tracker with `taskId`,
189
190
 
190
191
  ## Deterministic gates note
191
192
 
192
- Claude Code's `PreToolUse` exit-2 hooks are the HARD blocking gates. Three ship, none needing run-specific arguments so they are naturally hookable: (1) `pre-commit-check.sh` scans the staged diff on every `git commit` and blocks on a detected secret; (2) `agent-guard.sh` runs on `git commit` + `git push` and blocks AI/assistant attribution in a commit message and force-push to a protected branch (main/master/develop); (3) `check-read-size.sh` runs on `Read` and on the shell commands that read a file whole, and routes an oversized read to a cheap worker (`bulk-read.sh`) instead of the caller's own rung. The first two inspect what a run WRITES; the third inspects what it pays to READ, and it is inert until `bulkRead.mode` is set to `observe` or `enforce`, so merging the block changes nothing until the user opts in. Its `observe` mode blocks nothing and only logs, which is how the baseline is measured before anything is routed. All three are self-contained and never execute the inspected command. On an internal error they let the call through in an attended session; `agent-guard.sh` blocks instead under `MULTI_AGENT_UNATTENDED=1`, where nobody is watching to notice a gap. Three capture hooks ship in the same block and block nothing: `SessionEnd` runs `capture-flush.sh --if-stale` (writing a killed run's findings into the per-repo stores, so they do not depend on the run reaching Phase 5) plus `note-session.sh` (the mechanical shape of a non-pipeline session: tools used, commands that failed, calls the user refused - never an argument, never any output), `PreCompact` runs `capture-flush.sh` without `--if-stale` (a compaction summarizes a long phase mid-flight, so it is the moment unflushed findings are at risk; the staleness test exists only so a session exit does not re-flush a finished run, and both store writes are idempotent), and `SessionStart` runs `capture-resume.sh`, at most two lines about an unfinished run and a stale observation queue. None of them calls a model; all exit 0 on every path. The recommended hook block ships at `install/templates/claude-hooks.json`; `multi-agent:setup` offers to merge it into `~/.claude/settings.json`. The other deterministic gates (evidence, consensus, intent, learnings) are invoked by the pipeline phases with per-run arguments (a build-log path, the triage JSON, the free-text input), so they are phase-enforced by contract, not OS-hookable.
193
+ Claude Code's `PreToolUse` exit-2 hooks are the HARD blocking gates. Three ship, none needing run-specific arguments so they are naturally hookable: (1) `pre-commit-check.sh` scans the staged diff on every `git commit` and blocks on a detected secret; (2) `agent-guard.sh` runs on `git commit` + `git push` and blocks AI/assistant attribution in a commit message and force-push to a protected branch (main/master/develop); (3) `check-read-size.sh` runs on `Read` and on the shell commands that read a file whole, and routes an oversized read to a cheap worker (`bulk-read.sh`) instead of the caller's own rung. The first two inspect what a run WRITES; the third inspects what it pays to READ, and it is inert until `bulkRead.mode` is set to `observe` or `enforce`, so merging the block changes nothing until the user opts in. Its `observe` mode blocks nothing and only logs, which is how the baseline is measured before anything is routed. All three are self-contained and never execute the inspected command. On an internal error they let the call through in an attended session; `agent-guard.sh` blocks instead under `MULTI_AGENT_UNATTENDED=1`, where nobody is watching to notice a gap. Three capture hooks ship in the same block and block nothing: `SessionEnd` runs `capture-flush.sh --if-stale` (writing a killed run's findings into the per-repo stores, so they do not depend on the run reaching Phase 5) plus `note-session.sh` (the mechanical shape of a non-pipeline session: tools used, commands that failed, calls the user refused - never an argument, never any output), `PreCompact` runs `capture-flush.sh` without `--if-stale` (a compaction summarizes a long phase mid-flight, so it is the moment unflushed findings are at risk; the staleness test exists only so a session exit does not re-flush a finished run, and both store writes are idempotent), and `SessionStart` runs `capture-resume.sh`, at most two lines about an unfinished run and a stale observation queue. None of them calls a model; all exit 0 on every path. One `PostToolUse` hook ships in the same block and blocks nothing either: `edit-syntax-gate.sh` on `Edit|Write|MultiEdit` parses the file the edit just wrote (`swiftc -parse`, `node --check`, `py_compile` into a temp dir, `JSON.parse`, `bash -n`; Kotlin is skipped, no parser answers inside its 2 s deadline) and hands a syntax error to the model as `additionalContext`; it is silent when a parser is missing or slow, and inert until `editSyntaxGate.enabled` is true. The syntax gate also runs on Codex, on `PostToolUse` for `apply_patch` (every file the patch adds, updates or moves to). `multi-agent:setup` Step 8 asks once and registers it there with `host-hooks.mjs install --host codex` from `install/templates/codex-hooks.json`: idempotent, leaving every other hook alone, `status` reports it and uninstall removes it. Codex runs it only after the user trusts it in `/hooks`, which the helper says. Copilot CLI gets no registration: as of 1.0.45 it discards a `postToolUse` hook's output and applies no matcher, so the gate would cost a spawn per tool call and say nothing. Every other registration here is Claude Code's. The recommended hook block ships at `install/templates/claude-hooks.json`; `multi-agent:setup` offers to merge it into `~/.claude/settings.json`. The other deterministic gates (evidence, consensus, intent, learnings) are invoked by the pipeline phases with per-run arguments (a build-log path, the triage JSON, the free-text input), so they are phase-enforced by contract, not OS-hookable.
193
194
 
194
195
  Copilot CLI has no `PreToolUse` equivalent, so the secret scan there is workflow-enforced (run as a phase step, not OS-blocked) plus a CI smoke-gate step.
@@ -0,0 +1,65 @@
1
+ # Reply shape
2
+
3
+ > Loaded on demand by `rules/response-shape.md`, which carries only the rules.
4
+ > This file holds the reasons, the word lists and the examples.
5
+
6
+ A reply is read by someone switching in from other work. The shape below lets
7
+ them act after reading the first and the last line, and find the detail in
8
+ between when they need it.
9
+
10
+ ## Where it applies
11
+
12
+ | Output | Governed by |
13
+ |---|---|
14
+ | A reply in a conversation, inside or outside a run | this file |
15
+ | Run progress lines | the progress contract (`progress-contract.md`) |
16
+ | Phase 5 reports, PR bodies, Jira and Confluence text | their templates, then the humanizer skill |
17
+
18
+ The language is `prefs.global.outputLanguage`; nothing here depends on it.
19
+
20
+ ## The rules, with their reasons
21
+
22
+ 1. **Lead with the answer or the next action.** The first line is the one that
23
+ is always read. Openers that only announce the reply ("Great question",
24
+ "Let me take a look", "Sure! Here is...", "Harika soru", "Hemen bakıyorum")
25
+ spend it on nothing.
26
+ 2. **Numbered steps, one action each.** A step that hides two actions is the
27
+ one that gets half done.
28
+ 3. **At most five items per group, the rest as a count** ("and 7 more, listed
29
+ in the report"). This is display only. A finding, a failed check or a
30
+ verification caveat is never cut to fit; when they do not fit, they go to a
31
+ file and the reply names it. The verification rule in `CLAUDE.md` wins over
32
+ this one every time.
33
+ 4. **Errors as cause, then fix.** "The build failed because X; fixed by Y" or
34
+ "...; needs Z from you". No apology paragraph.
35
+ 5. **Finished work in concrete terms.** What changed (file, commit, version)
36
+ and how it was checked (which tests, which counts). "Done" alone is not a
37
+ report.
38
+ 6. **Tangents at the end, one line.** Something noticed on the way is offered
39
+ ("Also noticed X; want it fixed?"), not woven into the answer.
40
+ 7. **Close with what happens next or what the user decides.** Not "Let me know
41
+ if you need anything else", "Hope this helps", "Başka bir şey olursa
42
+ söyle".
43
+
44
+ ## When the task wins
45
+
46
+ - An explanation the user asked for runs as long as it needs, with headings.
47
+ - A destructive or outward-facing step is confirmed before it runs, whatever
48
+ that does to the shape.
49
+ - Real ambiguity gets one question, not a guess and not a questionnaire.
50
+ - Inside a run, the phase files and their templates decide the format; this
51
+ file only shapes the conversation around them.
52
+
53
+ ## Example
54
+
55
+ Too long to act on:
56
+
57
+ > Great question! I looked into the failing build. It seems there might be an
58
+ > issue with the signing configuration, which could be caused by several
59
+ > things... Let me know if you want me to look further!
60
+
61
+ Shaped:
62
+
63
+ > The build fails on signing: the provisioning profile expired on 12.10.
64
+ > Renew it in the developer portal, then rerun `xcodebuild archive`.
65
+ > I can retry the archive once the new profile is installed.
@@ -146,11 +146,11 @@ acted on, not read.
146
146
  #### Accounting is a gate, not a request
147
147
 
148
148
  `update <N> completed` exits **3** for phases 1-4 when nothing was recorded via
149
- `tokens`. The alternative is what shipped for months: the docs asked for the
150
- call, `smoke-tracker-tokens-invocation.sh` linted that the docs *mention* the
151
- call, and no run made it - every phase priced at `-`, every completion line
152
- printed without numbers, and every gate green. A lint over prose cannot observe
153
- a runtime omission; the tool that would have received the call can.
149
+ `tokens`. A doc that asks for the call, and a lint
150
+ (`smoke-tracker-tokens-invocation.sh`) that checks the doc *mentions* it, cannot
151
+ see a run that skips it: every phase would price at `-` and every completion line
152
+ would print without numbers while every gate passes. A lint over prose cannot
153
+ observe a runtime omission; the tool that would have received the call can.
154
154
 
155
155
  The refusal is recoverable and loses no work:
156
156
 
@@ -160,7 +160,7 @@ phase-tracker.sh tokens <N> <in> <out> [cached]
160
160
  phase-tracker.sh update <N> completed
161
161
  ```
162
162
 
163
- `model` resolves a full model id to its cost-table family (`claude-opus-5` →
163
+ `model` resolves a full model id to its cost-table family (`claude-opus-5-5` →
164
164
  `opus`) and says so out loud when it cannot, because an unpriced name is the
165
165
  other way a phase silently costs nothing. A phase that truly ran no LLM call
166
166
  completes with `--no-llm`, which is recorded and keeps it out of the run
@@ -0,0 +1,18 @@
1
+ ## Reply shape
2
+
3
+ For replies in a conversation. Reports, PR, Jira and Confluence bodies keep
4
+ their own templates; the humanizer governs their wording.
5
+
6
+ - First line: the answer or the next action. No preamble, no recap of the ask.
7
+ - Steps: numbered, one action each. Items: at most five shown, the rest named
8
+ as a count. That limit shapes the display only; never drop a finding, a
9
+ failure or a verification note to fit it.
10
+ - Errors: the cause, then the fix. Finished work: what changed, how it was
11
+ checked.
12
+ - Tangents wait for the end, as one line.
13
+ - Last line: what happens next, or what the user has to decide. No closing
14
+ pleasantries.
15
+ - An explanation asked for runs as long as it needs; a destructive step is
16
+ confirmed first; real ambiguity gets one question.
17
+
18
+ Detail and examples: `$HOME/.claude/multi-agent-refs/response-shape.md`.
@@ -782,9 +782,14 @@
782
782
  "enum": ["component", "bugfix", "feature", "refactor", "chore"],
783
783
  "description": "Phase 0 Step 7 classification. Phase 2 branches on it, and phase0-exit-gate.mjs fails a run that reaches Phase 1 without it. A Figma reference forces component."
784
784
  },
785
+ "depBump": {
786
+ "type": ["object", "null"],
787
+ "additionalProperties": true,
788
+ "description": "A /multi-agent:deps run (state.mode \"deps\"): the bump dep-bump.mjs applied (ecosystem, name, manifest, from, to, risk, lock, alsoMoves, commitMessage), the fix rounds taken against depBump.maxFixRounds, the scope verdict and, when the cap was reached, rolledBack plus what still failed. Contract: multi-agent-refs/features/dep-bump.md."
789
+ },
785
790
  "plan": {
786
791
  "type": ["object", "null"],
787
- "description": "The Phase 1 plan as a Todo list, written by plan-todos.sh when prefs.global.planTodos.enabled is true. Shape: plan-todos.schema.json, which plan-todos.sh validates on write; absent when the opt-in is off."
792
+ "description": "The Phase 1 plan as a Todo list, written by plan-todos.sh when prefs.global.planTodos.enabled is true. Shape: plan-todos.schema.json, which plan-todos.sh validates on write, including the optional todos[].type, the todos[].tdd evidence record, the drift record (the todo ended off-plan) and the needsReplan flag (a step it depends on drifted; it does not start until confirm-replan); absent when the opt-in is off."
788
793
  },
789
794
  "analysis": {
790
795
  "type": ["object", "null"],
@@ -1246,6 +1251,20 @@
1246
1251
  "type": "string",
1247
1252
  "enum": ["fix", "accept", "escalate"]
1248
1253
  },
1254
+ "reworkEscalation": {
1255
+ "type": "object",
1256
+ "additionalProperties": false,
1257
+ "required": ["escalate", "fromTier", "toTier", "trigger", "reason"],
1258
+ "description": "Written by rework-escalation.mjs --state before the rework dispatch this review sent back: the rung it ran on and why, a refusal included (multi-agent-refs/features/rework-escalation.md).",
1259
+ "properties": {
1260
+ "escalate": { "type": "boolean" },
1261
+ "fromTier": { "type": "string" },
1262
+ "toTier": { "type": "string" },
1263
+ "trigger": { "enum": ["last-round", "still-present", null] },
1264
+ "reason": { "type": "string" },
1265
+ "at": { "type": "string", "format": "date-time" }
1266
+ }
1267
+ },
1249
1268
  "delta": {
1250
1269
  "type": "object",
1251
1270
  "additionalProperties": true,
@@ -2084,6 +2103,22 @@
2084
2103
  "sha": { "type": "string" }
2085
2104
  }
2086
2105
  },
2106
+ "decisions": {
2107
+ "type": "array",
2108
+ "description": "Choices an autopilot run made where an attended run would have asked (multi-agent-refs/features/autopilot-decisions.md): parks (gate-ledger.mjs), blockers lowered to important (review-decision-gate.mjs), rework escalations (rework-escalation.mjs), pickers resolved without asking, split consensus taken on the triage verdict, a date-gate model fallback (decisions-log.mjs add). Written only while the quality gates are active. Rendered, redacted, in the Phase 5 report and appended to the autopilot PR body; an empty or absent list renders nothing.",
2109
+ "items": {
2110
+ "type": "object",
2111
+ "additionalProperties": false,
2112
+ "required": ["what", "why", "costIfWrong", "at", "phase"],
2113
+ "properties": {
2114
+ "what": { "type": "string", "minLength": 1, "maxLength": 200 },
2115
+ "why": { "type": "string", "minLength": 1, "maxLength": 500 },
2116
+ "costIfWrong": { "type": "string", "minLength": 1, "maxLength": 300 },
2117
+ "at": { "type": "string", "format": "date-time" },
2118
+ "phase": { "type": "integer", "minimum": 0, "maximum": 5 }
2119
+ }
2120
+ }
2121
+ },
2087
2122
  "verificationFailed": {
2088
2123
  "type": "object",
2089
2124
  "additionalProperties": false,
@@ -73,6 +73,10 @@
73
73
  "analysis": {
74
74
  "phases": [0, 1, 3, 4, 5],
75
75
  "autopilot": false
76
+ },
77
+ "deps": {
78
+ "phases": [0, 1, 2, 3, 4, 5],
79
+ "autopilot": false
76
80
  }
77
81
  },
78
82
  "thresholds": {