freeharness 0.4.1 → 0.4.2

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 (194) hide show
  1. package/README.md +8 -7
  2. package/canonical/HARVEST.yaml +25 -14
  3. package/canonical/PROVENANCE.yaml +1 -1
  4. package/canonical/agents/README.md +77 -36
  5. package/canonical/agents/agentic-architect.md +2 -1
  6. package/canonical/agents/database-reviewer.md +6 -8
  7. package/canonical/agents/explorer-ai-engineer-analyst.md +2 -6
  8. package/canonical/agents/implementer.md +30 -0
  9. package/canonical/agents/pr-reviewer.md +9 -11
  10. package/canonical/agents/python-reviewer.md +7 -9
  11. package/canonical/agents/report-formatter.md +7 -3
  12. package/canonical/agents/security-reviewer.md +7 -8
  13. package/canonical/agents/test-writer.md +5 -2
  14. package/canonical/hooks/cost-prices.json +11 -9
  15. package/canonical/hooks/freeharness-config-guard.mjs +8072 -87
  16. package/canonical/hooks/freeharness-context-monitor.mjs +88 -54
  17. package/canonical/hooks/freeharness-converge.mjs +78 -23
  18. package/canonical/hooks/freeharness-cost-tracker.mjs +1129 -218
  19. package/canonical/hooks/freeharness-memory-guard.mjs +20 -23
  20. package/canonical/hooks/freeharness-precompact.mjs +217 -87
  21. package/canonical/hooks/freeharness-quota-tap.mjs +173 -0
  22. package/canonical/hooks/freeharness-reload-context.mjs +197 -0
  23. package/canonical/hooks/freeharness-repeat-tool.mjs +1 -1
  24. package/canonical/hooks/freeharness-sdd-context.mjs +970 -0
  25. package/canonical/hooks/freeharness-session-start +297 -59
  26. package/canonical/hooks/hooks.claude-code.json +1 -1
  27. package/canonical/hooks/hooks.config-guard.claude-code.json +3 -2
  28. package/canonical/hooks/hooks.context-monitor.claude-code.json +1 -1
  29. package/canonical/hooks/hooks.converge.claude-code.json +1 -1
  30. package/canonical/hooks/hooks.memory-guard.claude-code.json +3 -2
  31. package/canonical/hooks/hooks.reload-context.claude-code.json +15 -0
  32. package/canonical/openspec/schema.spec-driven.yaml +29 -8
  33. package/canonical/openspec/templates/follow-ups.md +3 -2
  34. package/canonical/openspec/templates/proposal.md +1 -1
  35. package/canonical/openspec/templates/tasks.md +8 -0
  36. package/canonical/rules/CLAUDE.md +5 -4
  37. package/canonical/rules/routing.md +10 -9
  38. package/canonical/skills/agent-evaluation/SKILL.md +17 -6
  39. package/canonical/skills/agent-evaluation/evals/cases.yaml +38 -23
  40. package/canonical/skills/agentic-architecture/SKILL.md +4 -0
  41. package/canonical/skills/agentic-architecture/evals/cases.yaml +27 -0
  42. package/canonical/skills/code-review/SKILL.md +9 -2
  43. package/canonical/skills/code-review/evals/cases.yaml +1118 -27
  44. package/canonical/skills/git-workflow/SKILL.md +2 -0
  45. package/canonical/skills/local-code/SKILL.md +2 -2
  46. package/canonical/skills/local-code/evals/cases.yaml +1 -1
  47. package/canonical/skills/report-formatting/SKILL.md +10 -2
  48. package/canonical/skills/report-formatting/reference/ARCHITECTURE.md +3 -3
  49. package/canonical/skills/report-formatting/reference/HELPERS.md +10 -5
  50. package/canonical/skills/report-formatting/reference/RELEASE.md +1 -2
  51. package/canonical/skills/report-formatting/reference/TEMPLATES.md +3 -2
  52. package/canonical/skills/report-formatting/reference/authoring.md +25 -37
  53. package/canonical/skills/report-formatting/scripts/build-architecture.js +1 -1
  54. package/canonical/skills/report-formatting/scripts/build-md-claro.js +5 -8
  55. package/canonical/skills/report-formatting/scripts/check-env.js +0 -4
  56. package/canonical/skills/report-formatting/scripts/docmodel.js +3 -11
  57. package/canonical/skills/report-formatting/scripts/example-build.js +8 -10
  58. package/canonical/skills/report-formatting/scripts/example_build_ArchitectureReview_docx.js +8 -10
  59. package/canonical/skills/report-formatting/scripts/example_build_ExecutiveReport_docx.js +8 -10
  60. package/canonical/skills/report-formatting/scripts/theme-claro.js +39 -10
  61. package/canonical/skills/subagent-driven-development/SKILL.md +35 -28
  62. package/canonical/skills/subagent-driven-development/evals/cases.yaml +3496 -19
  63. package/canonical/skills/subagent-driven-development/reference/brief.md +185 -35
  64. package/canonical/skills/subagent-driven-development/reference/handoff.md +82 -2
  65. package/canonical/skills/subagent-driven-development/reference/loop.md +57 -0
  66. package/canonical/skills/subagent-driven-development/reference/trees.md +40 -0
  67. package/canonical/skills/subagent-driven-development/reference/workspace.md +31 -0
  68. package/canonical/skills/subagent-driven-development/scripts/validate-handoff.mjs +4771 -326
  69. package/dist/adapters/harness/claude-code.d.ts +19 -3
  70. package/dist/adapters/harness/claude-code.js +204 -39
  71. package/dist/adapters/harness/opencode.js +16 -2
  72. package/dist/adapters/harness/plugin.js +28 -17
  73. package/dist/adapters/memory/doctor.d.ts +174 -29
  74. package/dist/adapters/memory/doctor.js +758 -134
  75. package/dist/adapters/memory/migrate.d.ts +95 -0
  76. package/dist/adapters/memory/migrate.js +497 -0
  77. package/dist/adapters/memory/paths.d.ts +22 -0
  78. package/dist/adapters/memory/paths.js +85 -0
  79. package/dist/adapters/memory/vendored.d.ts +56 -29
  80. package/dist/adapters/memory/vendored.js +191 -154
  81. package/dist/adapters/sync/diff.js +4 -1
  82. package/dist/cli/cleanup-prompt.d.ts +35 -0
  83. package/dist/cli/cleanup-prompt.js +68 -0
  84. package/dist/cli/cleanup.d.ts +22 -24
  85. package/dist/cli/cleanup.js +182 -68
  86. package/dist/cli/cost-quota.d.ts +158 -0
  87. package/dist/cli/cost-quota.js +645 -0
  88. package/dist/cli/cost.d.ts +408 -46
  89. package/dist/cli/cost.js +1731 -57
  90. package/dist/cli/doctor.d.ts +52 -13
  91. package/dist/cli/doctor.js +193 -44
  92. package/dist/cli/hard-cleanup.d.ts +93 -0
  93. package/dist/cli/hard-cleanup.js +552 -0
  94. package/dist/cli/install-facts.d.ts +28 -0
  95. package/dist/cli/install-facts.js +66 -0
  96. package/dist/cli/json-key-edit.d.ts +18 -0
  97. package/dist/cli/json-key-edit.js +118 -0
  98. package/dist/cli/memory-import.d.ts +74 -0
  99. package/dist/cli/memory-import.js +469 -0
  100. package/dist/cli/plugin-validate.d.ts +12 -0
  101. package/dist/cli/plugin-validate.js +43 -0
  102. package/dist/cli/uninstall.d.ts +1 -1
  103. package/dist/cli/uninstall.js +2 -2
  104. package/dist/cli/upstream-launchers.d.ts +49 -0
  105. package/dist/cli/upstream-launchers.js +287 -0
  106. package/dist/index.js +247 -70
  107. package/dist/infra/fsutil.d.ts +31 -3
  108. package/dist/infra/fsutil.js +69 -6
  109. package/dist/infra/manifest.d.ts +2 -1
  110. package/dist/infra/manifest.js +3 -2
  111. package/dist/infra/prices.d.ts +18 -0
  112. package/dist/infra/prices.js +64 -0
  113. package/node_modules/@freeharness/core/dist/tiers.d.ts +10 -1
  114. package/node_modules/@freeharness/core/dist/tiers.js +24 -2
  115. package/node_modules/@freeharness/core/package.json +1 -1
  116. package/node_modules/@freeharness/sdd/PROVENANCE.yaml +279 -2
  117. package/node_modules/@freeharness/sdd/dist/src/bin/openspec.js +34 -8
  118. package/node_modules/@freeharness/sdd/dist/src/shim/archive.d.ts +7 -6
  119. package/node_modules/@freeharness/sdd/dist/src/shim/archive.js +72 -64
  120. package/node_modules/@freeharness/sdd/dist/src/shim/follow-up.d.ts +48 -16
  121. package/node_modules/@freeharness/sdd/dist/src/shim/follow-up.js +168 -70
  122. package/node_modules/@freeharness/sdd/dist/src/shim/instructions.d.ts +36 -6
  123. package/node_modules/@freeharness/sdd/dist/src/shim/instructions.js +110 -49
  124. package/node_modules/@freeharness/sdd/dist/src/shim/list.d.ts +1 -1
  125. package/node_modules/@freeharness/sdd/dist/src/shim/list.js +57 -14
  126. package/node_modules/@freeharness/sdd/dist/src/shim/nested-change.d.ts +7 -0
  127. package/node_modules/@freeharness/sdd/dist/src/shim/nested-change.js +118 -0
  128. package/node_modules/@freeharness/sdd/dist/src/shim/new-change.js +3 -1
  129. package/node_modules/@freeharness/sdd/dist/src/shim/proposal-capabilities.d.ts +12 -0
  130. package/node_modules/@freeharness/sdd/dist/src/shim/proposal-capabilities.js +94 -0
  131. package/node_modules/@freeharness/sdd/dist/src/shim/shared.d.ts +17 -0
  132. package/node_modules/@freeharness/sdd/dist/src/shim/shared.js +182 -1
  133. package/node_modules/@freeharness/sdd/dist/src/shim/status.d.ts +2 -2
  134. package/node_modules/@freeharness/sdd/dist/src/shim/status.js +34 -5
  135. package/node_modules/@freeharness/sdd/dist/src/shim/validate.d.ts +9 -0
  136. package/node_modules/@freeharness/sdd/dist/src/shim/validate.js +49 -41
  137. package/node_modules/@freeharness/sdd/dist/src/shim/warnings.d.ts +21 -0
  138. package/node_modules/@freeharness/sdd/dist/src/shim/warnings.js +66 -0
  139. package/node_modules/@freeharness/sdd/dist/vendor/openspec/apply/line-endings.d.ts +4 -0
  140. package/node_modules/@freeharness/sdd/dist/vendor/openspec/apply/line-endings.js +17 -0
  141. package/node_modules/@freeharness/sdd/dist/vendor/openspec/apply/specs-apply.js +95 -22
  142. package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/change-status-policy.d.ts +6 -0
  143. package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/change-status-policy.js +14 -6
  144. package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/index.d.ts +1 -1
  145. package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/index.js +1 -1
  146. package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/outputs.d.ts +3 -3
  147. package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/outputs.js +24 -4
  148. package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/task-progress.js +4 -7
  149. package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/types.js +13 -1
  150. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/apply-change.js +21 -6
  151. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/archive-change.js +80 -19
  152. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/explore.js +42 -22
  153. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/project-root.d.ts +32 -0
  154. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/project-root.js +39 -0
  155. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/propose.js +16 -9
  156. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/sync-specs.js +36 -1
  157. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/update-change.js +65 -30
  158. package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/constants.d.ts +1 -1
  159. package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/constants.js +1 -1
  160. package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/parsers/change-parser.d.ts +8 -13
  161. package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/parsers/change-parser.js +79 -102
  162. package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/parsers/markdown-parser.js +4 -9
  163. package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/parsers/requirement-blocks.d.ts +50 -10
  164. package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/parsers/requirement-blocks.js +165 -37
  165. package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/parsers/requirement-text.d.ts +24 -3
  166. package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/parsers/requirement-text.js +55 -8
  167. package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/parsers/spec-structure.js +4 -1
  168. package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/purpose-placeholder.js +19 -9
  169. package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/spec-discovery.d.ts +10 -0
  170. package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/spec-discovery.js +115 -0
  171. package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/task-lines.d.ts +3 -3
  172. package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/task-lines.js +20 -20
  173. package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/validator.d.ts +6 -0
  174. package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/validator.js +75 -14
  175. package/node_modules/@freeharness/sdd/package.json +1 -1
  176. package/node_modules/@freeharness/sdd/vendor/openspec/assets/schema.upstream.yaml +47 -7
  177. package/node_modules/@freeharness/sdd/vendor/openspec/assets/skills/openspec-apply-change/SKILL.md +25 -7
  178. package/node_modules/@freeharness/sdd/vendor/openspec/assets/skills/openspec-archive-change/SKILL.md +50 -11
  179. package/node_modules/@freeharness/sdd/vendor/openspec/assets/skills/openspec-bulk-archive-change/SKILL.md +48 -10
  180. package/node_modules/@freeharness/sdd/vendor/openspec/assets/skills/openspec-continue-change/SKILL.md +27 -7
  181. package/node_modules/@freeharness/sdd/vendor/openspec/assets/skills/openspec-explore/SKILL.md +25 -12
  182. package/node_modules/@freeharness/sdd/vendor/openspec/assets/skills/openspec-ff-change/SKILL.md +17 -5
  183. package/node_modules/@freeharness/sdd/vendor/openspec/assets/skills/openspec-new-change/SKILL.md +12 -1
  184. package/node_modules/@freeharness/sdd/vendor/openspec/assets/skills/openspec-onboard/SKILL.md +47 -33
  185. package/node_modules/@freeharness/sdd/vendor/openspec/assets/skills/openspec-propose/SKILL.md +17 -5
  186. package/node_modules/@freeharness/sdd/vendor/openspec/assets/skills/openspec-sync-specs/SKILL.md +29 -1
  187. package/node_modules/@freeharness/sdd/vendor/openspec/assets/skills/openspec-update-change/SKILL.md +31 -13
  188. package/node_modules/@freeharness/sdd/vendor/openspec/assets/skills/openspec-verify-change/SKILL.md +75 -27
  189. package/package.json +6 -4
  190. package/provenance/canonical.PROVENANCE.yaml +1 -1
  191. package/provenance/memory.PROVENANCE.yaml +458 -6
  192. package/provenance/sdd.PROVENANCE.yaml +279 -2
  193. package/canonical/hooks/freeharness-auto-memory.mjs +0 -158
  194. package/canonical/hooks/hooks.auto-memory.claude-code.json +0 -16
@@ -1,60 +1,67 @@
1
1
  ---
2
2
  name: subagent-driven-development
3
- description: Use when executing an approved tasks.md from an OpenSpec change: one brief per task under .freeharness/sdd/<change>/, a fresh implementer per dispatch with an explicit tier and a disjoint write scope, a JSON handoff, the lead's own test run and diff review, one combined task reviewer, a 5-round circuit breaker and one final branch review via code-review. Not for ad-hoc one-file edits.
3
+ description: Use when executing an approved tasks.md from an OpenSpec change: one small brief per task under .freeharness/sdd/<change>/, a fresh implementer per dispatch routed by class, tier and effort with a disjoint write scope and acceptance probes, a JSON handoff, the lead's own test run and diff review, one combined task reviewer, fix rounds only for blocking findings, a round-cap circuit breaker and one final branch review via code-review. Not for ad-hoc one-file edits.
4
4
  ---
5
5
 
6
6
  # Subagent-Driven Development Protocol
7
7
 
8
8
  <orchestrator_directive>
9
- The primary session is the lead: it dispatches, evaluates and rules; it never writes production code while executing `tasks.md`. A feature starts at `/opsx:propose`; this skill runs the approved `tasks.md` after `/opsx:apply`. Continuous execution: no "should I continue?" between tasks; the stop conditions below are the only pauses.
9
+ The primary session is the lead: it dispatches, evaluates and rules; it never writes production code while running `tasks.md`. A feature starts at `/opsx:propose`; this skill runs the approved `tasks.md` after `/opsx:apply`. Continuous execution: no "should I continue?" between tasks; only the stop conditions below pause it.
10
10
  </orchestrator_directive>
11
11
 
12
12
  <workspace>
13
- - Artifacts live in `.freeharness/sdd/<change>/` (gitignored; `init --project` creates it): `<task>.brief.md` and `<task>.review.md`. Files survive compaction; after compaction trust the review packages, `tasks.md` checkboxes and `git log`, never recollection.
14
- - Templates: `reference/brief.md`, `reference/handoff.md`. The validator `scripts/validate-handoff.mjs` has six subcommands: `briefs <dir|file...>` (header lines, Spec = change id, digest budget, write-scope overlap), `handoff <file> [--base <sha>] [--brief <brief.md>] [--in-flight <brief.md>...] [--lead <path>...]` (schema plus the diff guards; `--lead` excludes the lead's own paths), `budget <ledger.jsonl> <task> [--ceiling <n>]`, `ledger <change-dir>`, `recover <transcript.jsonl> <report> [--force]` and `name <dispatch-name>` (checks a dispatch name and prints the corrected form).
13
+ - Artifacts live in `.freeharness/sdd/<change>/`: `<task>.brief.md` and `<task>.review.md`, plus the ledger, state and round-base files. Files survive compaction; trust the review packages, `tasks.md` checkboxes and `git log`, never recollection.
14
+ - Templates: `reference/brief.md`, `reference/handoff.md`; the tier map is the emitted `reference/tiers.md`; the validator is `scripts/validate-handoff.mjs`. Read reference/workspace.md when the run starts or a validator subcommand's arguments are needed.
15
+ - Preflight, before task 1: scan pairs of tasks sharing a file or an interface and rule on conflicts in a `## Preflight` note of the first review package.
15
16
  - Worker rules, restated in every brief: never `git stash`, `git checkout --` or `git reset` in the shared working tree (prove RED by writing the tests first or against a temp copy), and never dispatch a subagent.
16
- - Before task 1: read `tasks.md` once, list the tasks, note Global Constraints; scan pairs of tasks that share a file or an interface and rule on conflicts (spec is the authority) in a `## Preflight` note of the first review package.
17
+ - Lead context rules: run `name`, `briefs` and `budget` for a dispatch in one Bash call and every `openspec follow-up add` of a task close in one Bash call; per round read the `git diff --stat`, the guard output and the gate output only, and read the full task diff once, at acceptance; never paste a worker transcript or a full diff into the conversation when a file path serves; run `/compact` at a task boundary once the lead context passes 200,000 tokens; the workspace files carry the state.
17
18
  </workspace>
18
19
 
19
20
  <dispatch>
20
- 1. Brief: write `<task>.brief.md` (template). Header `Spec:` is the OpenSpec change id, never a copied spec; `Tier:` is explicit on every dispatch (fast for transcription of complete plan text or one-file mechanical edits, standard for multi-file integration, strong for design judgment; an omitted tier silently inherits the session model). Write scope names every file the worker may touch.
21
- 2. Disjoint write scopes: run `validate-handoff.mjs briefs` over the batch; any overlap refuses the whole batch naming the file. Two implementers never run in parallel on intersecting scopes.
22
- 3. Batch small same-shape tasks (the same one-line edit or field across files) into one brief and one dispatch; work that needs its own tests, judgment or review surface gets its own dispatch.
23
- 4. Dispatch a fresh implementer with the brief path, the report path and the interfaces earlier tasks produced; nothing from the session history. The implementer follows `test-driven-development`; dispatch `test-writer` for the RED step when the failing tests are non-trivial. Record `Base:` (`git rev-parse HEAD`) before dispatching.
24
- 5. At most 3 implementers in flight; a fix-round resumption counts as one. The fourth task waits for a slot; more than three needs a user ask recorded in the review package.
25
- 6. Dispatch names follow `<role>-<task>[-r<round>][-<slug>]`: `impl-2_3`, `fix-2_3-r2`, `impl-1_3b` (a batch), `review-final-r1` (the final review) and `review-final-r1-security` (one of that round's parallel reviewers, the slug naming its lens). Write `_` for `.` because the Agent tool rejects a dot in a name; the ledger stores the dotted id and reads role, task and round through the slug. The lens slug is lowercase letters, digits and hyphens (`review-final-r1-lenses-b`); any other character leaves role and task null in the ledger. Before every dispatch, run `validate-handoff.mjs name <dispatch-name>` and use the printed corrected form.
26
- 7. Budget: run `validate-handoff.mjs budget <ledger.jsonl> <task>` before every dispatch of a task, and again when its handoff is accepted; the brief's `Ceiling:` header overrides the default of 25,000,000 cache-read tokens for that task.
27
- 8. Rewrite the brief's `## Why and rulings` digest before every re-dispatch (a fix round, a re-brief after `partial` or `blocked`) so it still matches the current decisions; a deviation the handoff does not cite is a reviewer P0 tagged `why-digest`.
28
- 9. No nested subagents: a worker never dispatches helpers or reviewers; a worker-spawned reviewer is a defect, not rigor.
21
+ 1. Brief: start `<task>.brief.md` with `validate-handoff.mjs brief-init <change> <task>` and fill every `<fill: ...>` placeholder it leaves (the template stays the source of the fixed parts; `briefs` refuses one left); one task id per brief and per dispatch, never a batch. Header `Spec:` is the OpenSpec change id, never a copied spec; `Tier:` is explicit on every dispatch. Route by `Class:`: `docs`, `extraction`, `exploration` and `mechanical` (documentation, extraction, exploration, mechanical edits such as matrix rows, renames, one-line values and transcription of complete plan text) run on standard or strong; `summary` on fast, standard or strong, and `extraction` also on fast; `security` (a task that changes a security boundary: a guard, a hook verdict, an auth or secret path, input validation of untrusted payloads) and `complex` (a parser or state machine, concurrency, a cross-file contract, or a task that reached the round cap before; a validator tokenizer or collector edit routes as `complex` unless it changes a verdict a legitimate worker command reaches; lead-written files owe no hostile-input tests) run on strong with `Effort: high` only; `code` (a code change that is neither `security` nor `complex`) runs on strong, or on standard only with `Route: C1-C7 - <reason>` per `reference/brief.md`; any other class, or none, runs on strong only. A fast brief's reading set stays under 100,000 tokens at 4 bytes per token; the validator checks the class, never that bound. A fix round's tier and effort are what `validate-handoff.mjs route <brief> --round <n> [--p0] [--security]` prints (`--p0` or `--security` for a round carrying such a finding), and `round-base` given the same flags refuses a brief below them. `Effort:` is `medium` (default) or `high`, `high` on strong only. Write scope names every file the worker may touch. Read reference/loop.md when a brief is written: the sizing bounds and the split rule, the fixture scope, the grep for statements pinning a changed value, and the class ceilings.
22
+ 2. Probes and project rules: before the dispatch write `## Acceptance probes` (1 to 12 lines, `P<n>: <command, input or observable> -> <expected outcome>`) from the spec scenarios and the design's edge cases; a `security` or `complex` brief carries one probe expecting an allow or a pass and one corpus, fixture replay or generator probe. Fill `## Project rules` (1 to 20 lines) from the project CLAUDE.md invariants and protected boundaries that bear on the write scope plus the artifact rules; workers run without CLAUDE.md, so the section is their only copy. A probe of a guard or hook verdict runs the hook through node on a payload file (reference/brief.md).
23
+ 3. Disjoint write scopes: run `validate-handoff.mjs briefs` over the dispatch; any overlap refuses the whole batch naming the file, so no two implementers in flight share a file.
24
+ 4. Dispatch a fresh `implementer` agent with the brief path, the report path and the interfaces earlier tasks produced; nothing from the session history. On every implementer, test-writer and fix dispatch the per-dispatch model is the brief's `Tier:` resolved through `reference/tiers.md` (the alias the tier maps to; never a model name in this skill) and the per-dispatch effort is the brief's `Effort:` (`medium` when absent); the agent frontmatter is never the source of a brief's effort. An omitted per-dispatch model falls back to the implementer agent's tier. A per-dispatch effort overrides the frontmatter effort. A team dispatch inherits the session effort, except a plugin-defined agent spawned by name, which keeps its own; the agent frontmatter effort applies to plain subagent dispatches. The implementer follows `test-driven-development`; dispatch `test-writer` for the RED step when the failing tests are non-trivial. Record `Base:` (`git rev-parse HEAD`) before dispatching. Reviewers and implementers are never resumed: every review, re-review and fix round is a fresh dispatch. Dispatch every implementer, test-writer and reviewer through the Agent tool without `name`: the prompt's first line is `Dispatch: <dispatch-name>` and the Agent tool `description` repeats it. A named dispatch launches as a teammate when agent teams are enabled, at the session effort by the team rule above and with no SubagentStop until shutdown; without `name` it stays a plain subagent.
25
+ 5. Band of implementers in flight: small, at most 4 (the default); medium, at most 8; large, at most 12, only on the user's ask recorded in the review package with the latest quota reading under 50%. Medium or large only when the median accepted-task duration in the ledger exceeds four times the lead's service time per task. At most 16 dispatches of any role in flight. Every implementer runs in its own worktree whenever more than one is in flight. Read reference/trees.md when more than one implementer is in flight.
26
+ 6. Dispatch names follow `<role>-<task>[-r<round>][-<slug>]`: `impl-2_3`, `fix-2_3-r2`, `impl-2_4_1` (a sub-task), `review-final-r1` (the final review) and `review-final-r1-security` (one of that round's parallel reviewers, the slug naming its lens). The name goes in the prompt and the `description` (rule 4), never in the `name` parameter. Write `_` for `.`. The lens slug is lowercase letters, digits and hyphens. Before every dispatch, run `validate-handoff.mjs name <dispatch-name>` and use the printed corrected form. Read reference/loop.md when the printed form differs from the name.
27
+ 7. Budget: run `validate-handoff.mjs budget <ledger.jsonl> <task>` before every dispatch of a task, and again when its handoff is accepted.
28
+ 8. Rewrite the brief's `## Why and rulings` digest before every re-dispatch (a fix round, a re-brief after `partial` or `blocked`) so it still matches the current decisions; a deviation the handoff does not cite is a reviewer P0 tagged `why-digest`. A `[base]`, `hardening` or follow-up finding never enters a later brief's digest or write scope.
29
+ 9. No nested subagents: a worker never dispatches helpers or reviewers; a worker-spawned reviewer is a defect.
30
+ 10. Frontier: the lead passes the `frontier` model (the alias `frontier` maps to in `reference/tiers.md`) on every `agentic-architect` dispatch (a design, a design review, an architecture review) at effort `high`, or `medium` for a review scoped to one capability or one design decision, and records `Frontier: agentic-architect - <effort> - <reason>` in the review package (planning records: `agentic-architecture`); implementers, test-writers and reviewers never run on `frontier`; under a local-model profile `frontier` is unavailable and `agentic-architect` runs on its frontmatter tier and effort (`strong`, `xhigh`).
29
31
  </dispatch>
30
32
 
31
33
  <handoff>
32
- The worker returns only the JSON block (schema in `reference/handoff.md`): `task`, `status: completed|partial|blocked`, `files_changed`, `tests_run` (command, result, summary), `evidence` (one line per Verify item), `partial_output` (label of what is missing; required when partial), `blocked_reason` (stop token then detail; required when blocked), `concerns`. Stop tokens end the dispatch at the first one: `too-big`, `needs-confirm`, `ambiguous`, `regressed`, `scope`. Handle: `partial` -> re-dispatch with the label as the task; `blocked` -> fix the cause (context, tier, split, ruling) and re-dispatch; never re-run the same dispatch unchanged.
33
- On a missing, empty or block-less reply the first step is `validate-handoff.mjs recover <transcript.jsonl> <report>` over `~/.claude/projects/<project>/<session>/subagents/agent-<id>.jsonl`, never a re-dispatch: it rebuilds the handoff from the last assistant-authored json block and writes it as the head of the review package.
34
+ The worker returns only the JSON block (schema in `reference/handoff.md`): `task`, `status: completed|partial|blocked`, `files_changed`, `tests_run`, `evidence` (one line per Verify item and per probe id), `partial_output` (required when partial), `blocked_reason` (stop token first; required when blocked), `concerns`. Stop tokens end the dispatch at the first one: `too-big`, `needs-confirm`, `ambiguous`, `regressed`, `scope`. Handle: `partial` -> re-dispatch with the label as the task; `blocked` -> fix the cause (context, tier, split, ruling) and re-dispatch; never re-run the same dispatch unchanged. A guard `needs-confirm` on a line naming no guarded path: reference/loop.md.
35
+ Every report ends with `## Checkpoint` (reference/handoff.md). The task's working state `<task>.state.md` is written by the SDD context hook at SubagentStop when installed, otherwise run `validate-handoff.mjs state <report> <task>.state.md`.
36
+ On a missing, empty or block-less reply the first step is `validate-handoff.mjs recover <transcript.jsonl> <report>` over `~/.claude/projects/<project>/<session>/subagents/agent-<id>.jsonl`, never a re-dispatch (reference/handoff.md).
34
37
  </handoff>
35
38
 
36
39
  <acceptance>
37
- - Worker reports are not acceptance. The lead reviews the final diff (`git diff <base>..HEAD`) and runs the Verify commands itself, then appends `## Lead evaluation` to the review package with the commands and their summary lines. A task with only the worker's claim is never marked done.
38
- - Guards before the reviewer: run `validate-handoff.mjs handoff <report> --base <Base> --brief <brief.md>`, adding `--in-flight <brief.md>` for every other brief still running so a peer's files are not charged to this worker, and `--lead <path>` for the lead's own paths (the change's `tasks.md`, any review package outside `.freeharness/`) so they are not charged either; a `claimed-unchanged`, `changed-unclaimed`, `scope`, `peer-scope` or `lead-path` failure returns to the worker as findings (a round), never straight to the reviewer; `peer-scope` means the worker claimed a file another dispatch owns, `lead-path` means it claimed one of the lead's own paths, neither ever worth passing on.
39
- - One combined task reviewer per task (spec compliance + code quality in one dispatch, tier explicit) reads the brief, the review package and the diff file; it treats the report as unverified claims. Findings follow the reviewer contract: `path:line: P0|P1|P2: problem. fix.` At most 3 reviewer dispatches per round; a fourth waits for a second round unless a user ask for more is recorded in the review package.
40
+ - Worker reports are not acceptance. The lead reviews the final diff (`git diff <base>..HEAD`) once and runs the Verify commands itself, every probe included, then appends `## Lead evaluation` to the review package with the commands and their summary lines. A task with only the worker's claim is never marked done. A handoff whose `tests_run` holds no test command (a build alone) is `partial`, and the lead's run covers every test file that exercises an edited source, not only the files the brief names. A `Verify` list holds the task's tests plus the affected tests the changed-term check found, and implementers run only the Verify commands; the lead alone runs the full suite (the brief's `Suite:` command), at most one run at a time, after each accepted wave of parallel tasks and at the whole-change gate (reference/loop.md, "Test tiers and waves").
41
+ - Budget gate: run `validate-handoff.mjs budget <ledger.jsonl> <task>` again when the handoff is accepted; `FAIL ceiling reached` stops dispatching the task and requires the same `## Controller ruling` as the circuit breaker.
42
+ - Guards before the reviewer: run `validate-handoff.mjs handoff <report> --base <Base> --brief <brief.md> --agent <agent_id>`, adding `--in-flight <brief.md>` for every other brief still running and `--lead <path>` for the lead's own paths; every guard failure returns to the worker as findings (a round), never straight to the reviewer. Read reference/loop.md when a guard fails.
43
+ - One combined task reviewer per task (spec compliance + code quality in one dispatch, tier explicit) reads the brief, the review package and the diff file; it treats the report as unverified claims, checks the brief's probes first (running each) and only then reviews the diff against the spec; a probe the reviewer adds after the dispatch is a finding judged by the blocking rule, never a silent new bar. A reviewer never writes to, reverts or checks out files in the shared working tree and proves a test RED only against a temporary copy outside it. Findings follow the reviewer contract: `path:line: P0|P1|P2 <type>: problem. fix.` with `<type>` one of `defect|hardening|refactor|test-gap|docs|design`, `defect` only when the current behavior violates a spec requirement, a documented contract or a behavior the owner has stated; a follow-up's own `Expected:` line alone never makes it a defect. At most 3 reviewer dispatches per round; a fourth waits for a second round unless a user ask for more is recorded in the review package.
44
+ - Review tier: the lead picks each review dispatch's model (task reviewer, scoped re-reviews, the final branch review's reviewers), standard being the default: it runs `validate-handoff.mjs route <brief> --review --base <Base> [--round <n>] [--p0] [--final-spec] [--probed]` (`--final-spec` for the final branch review's spec-compliance pass, `--probed` (S4) for a scoped re-review whose every finding has a reproducing probe) and writes the printed `Review tier: <tier> - S<n> <reason>` line to the review package before the dispatch.
40
45
  - No finding suppression: never tell a reviewer what not to flag, never downgrade a finding for a stated rationale, never drop a finding silently; disagreement is a written ruling.
41
46
  - `test-driven-development` proof (failing run, then passing run) is part of the evidence; coverage numbers are not.
42
47
  </acceptance>
43
48
 
44
49
  <fix_loop>
45
- - A fix round = one fix dispatch + one scoped re-review of the fix diff only. Rounds 1-3 resume the same implementer with the findings verbatim; rounds 4-5 dispatch a fresh implementer one tier up with the brief, the report and the findings.
46
- - Circuit breaker: after round 5 with findings still open, stop dispatching. Write `## Controller ruling` to the review package for every open finding (real and load-bearing: smallest unblocking change, carried into the next brief; real and deferred, or contested: parked with the reason and the cost if wrong). Then ask the user before the next task; a structural defect that leaves every path a guess stops the run.
47
- - Second breaker: the budget ceiling. When `budget` reports `FAIL ceiling reached` for the task, stop dispatching it and write the same `## Controller ruling` as at round 5, one entry per open finding, each ruling carrying an id in the `R:<task>.<n>` form so the next brief's digest can cite it.
48
- - Every round appends `round <n>/5: <addressed>/<open>` to the review package. The lead never fixes findings itself.
50
+ - Blocking: a finding is blocking when it is a P0, or a P1 `defect` introduced by the task's diff (it does not reproduce at the task's `Base:` for a task review, or at the round base for a re-review) or one that fails a brief probe or a spec scenario, or, on a `security` or `complex` task, a P1 of any type introduced by the diff that fails a brief probe, a spec scenario or the corpus probe against the base. The reviewer tags a P1 `defect` that reproduces at the base `[base]`; a `[base]` finding is never blocking. Only blocking findings open a fix round; every other finding is a follow-up recorded at task close. A non-blocking `docs` or `test-gap` finding, or a comment fix, may ride round 1 when a blocking finding opened it and the fix stays inside the write scope, never a later round. A blocking finding whose fix lies outside the write scope gets a controller ruling and a new brief, never a round. The lead retypes a finding only through a written ruling line. The gate cannot tell that a finding meets the evidence test (reference/loop.md): on a `security` or `complex` task the lead retypes such a P1 to `defect` through a written ruling line before running `gate`, so it blocks.
51
+ - Ledger and gate: `<task>.findings.md` holds one line per finding, `F<n> <open|fixed|rejected|follow-up> r<round>: <reviewer contract line>`, written only by the lead. After every review run `validate-handoff.mjs gate <findings.md>`: it prints each `open` line as `blocking` or `follow-up` with the reason and exits non-zero when any is blocking; with no blocking line the task is accepted.
52
+ - A fix round = one fix dispatch + one scoped re-review. Before each fix dispatch run `validate-handoff.mjs round-base <brief.md> <n>`, the round-cap check (it refuses `round-cap <n> over <cap>`), which copies the write-scope files under `rounds/<task>-r<n>/`. Every round dispatches a fresh `implementer` given the brief, the review package and `<task>.findings.md` (the ledger), on the tier and effort `route` prints for the round (dispatch rule 1; strong from round 3 on, never frontier, which is reserved for the agentic-architect role (dispatch rule 10)). Read reference/loop.md when a fix dispatch is written: the fix prompt order and the task state.
53
+ - Re-review: a fresh re-reviewer is given only the ledger, the output of `validate-handoff.mjs round-diff <brief.md> <n>` and the probes; it returns a status for each open id and any new findings (from round 2 on only a P0 with a reproducer on the round diff; any other is a follow-up), and judges only the round diff: a finding on code the round diff does not change is a follow-up unless it is a P0.
54
+ - Circuit breaker: at the round cap (3, or the run authorization's `Rounds:`; `round-base` refuses `round-cap`) with blocking findings still open, stop dispatching. Write `## Controller ruling` to the review package for every open finding (reference/loop.md). Then ask the user before the next task, unless every open finding is ruled "remove the addition". Second breaker: the class ceiling (reference/loop.md). At `FAIL ceiling reached` stop dispatching the task and write the same ruling, each with an `R:<task>.<n>` id the next brief's digest can cite.
55
+ - Every round appends `round <n>/<cap>: <addressed>/<open blocking>` to the review package. The lead never fixes findings itself.
49
56
  </fix_loop>
50
57
 
51
58
  <completion>
52
- - Per task: lead evaluation present, review clean (or rulings written at the cap), `verification-before-completion` evidence recorded, then tick `[x]` in `tasks.md`.
53
- - After the last task: one final branch review via `code-review` over `git merge-base` to HEAD (domain reviewers + `pr-reviewer`, strong tier), under the same cap of 3 reviewer dispatches per round unless a user ask for more is recorded in the review package; one fix dispatch for the whole findings list, one scoped re-review, rulings for residuals. Then `git-workflow` for commit and PR; `/opsx:archive` when the change is done, with its compound step (retrospective line, telemetry file, rules or skill delta, memory observation).
54
- - Every deferred item (a parked ruling, a reviewer finding carried forward, a machine-only measurement) is recorded with `openspec follow-up add <change-id> "<text>" --from <task>`, never as prose; archive prints the unclaimed items.
55
- - Final message lists every ruling made (what, why, cost if wrong) and the `validate-handoff.mjs ledger <change-dir>` summary of dispatches and cache-read spend per task: a ruling that dies in the workspace was a decision made in secret.
59
+ - Per task: lead evaluation present, gate clean (or rulings written at the cap), `verification-before-completion` evidence recorded, then tick `[x]` in `tasks.md`, then commit the task with `validate-handoff.mjs commit <report> [<report>...] -F <message-file> --lead <tasks.md>`, listing every report of the task, adding `--tree <Tree> --base <sha>` for a tree task (the lead writes the message file; the tick rides in the same commit). Every accepted task is committed this way, never by `git add` plus `git commit`. Read reference/loop.md when a task is committed.
60
+ - After the last task: one final branch review via `code-review` over `git merge-base` to HEAD. Read reference/loop.md when the final branch review starts. Before the first final-review dispatch, write `final.brief.md` in the change workspace (header `Task: final`, the change's other headers, `Tier: strong`), since the cost tracker writes no ledger line for a dispatch whose task no in-flight brief declares; the lead writes it from the template, the fix dispatch reads it, and `validate-handoff.mjs briefs` checks it like any brief. Then `git-workflow` for commit and PR; `/opsx:archive` when the change is done, with its compound step (retrospective line, telemetry file, rules or skill delta, memory observation).
61
+ - Every deferred item (a non-blocking finding, a parked ruling, a machine-only measurement) is recorded with `openspec follow-up add <change-id> '<text>' --type <type> --expected '<...>' --current '<...>' --impact '<...>' --from <task>`, never as prose, the type and the expected, current and impact context taken from the finding, plus `owner-step` for a machine or owner measurement and `upstream` for an item owed upstream; the lead passes every value single-quoted (a `'` written as `'\''`) because finding text may quote shell syntax that double quotes would expand; archive prints the unclaimed items.
62
+ - Final message lists every ruling made (what, why, cost if wrong) and the `validate-handoff.mjs ledger <change-dir>` summary of dispatches and cache-read spend per task.
56
63
  </completion>
57
64
 
58
65
  <stop_conditions>
59
- Stop and ask the user only for: an irreversible or destructive operation; a security-sensitive action; a side effect outside the worktree (merge, push to a shared branch, publish); a task flagged "Ask first" in the proposal; the circuit breaker; a plan so broken that every path forward is a guess. Everything else is a ruling, written down, and the run continues.
66
+ Stop and ask the user only for: an irreversible or destructive operation; a security-sensitive action; a merge or push outside the change branch, or a publish; a task flagged "Ask first" in the proposal; the round cap or the class ceiling of the run authorization (the circuit breaker); a plan so broken that every path forward is a guess. Ceilings and the round cap come only from the owner (proposal.md `## Run authorization`, or `--ceiling`); the lead never raises them, and stops for neither below them. A cap with every finding ruled "remove the addition" is no stop. Everything else is a ruling, written down, and the run continues.
60
67
  </stop_conditions>