@opengsd/gsd-core 1.13.0 → 1.14.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 (257) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/agents/gsd-advisor-researcher.compact.md +85 -0
  4. package/agents/gsd-ai-researcher.compact.md +96 -0
  5. package/agents/gsd-assumptions-analyzer.compact.md +81 -0
  6. package/agents/gsd-code-fixer.compact.md +458 -0
  7. package/agents/gsd-code-fixer.md +5 -5
  8. package/agents/gsd-code-reviewer.compact.md +269 -0
  9. package/agents/gsd-code-reviewer.md +15 -3
  10. package/agents/gsd-codebase-mapper.compact.md +760 -0
  11. package/agents/gsd-debug-session-manager.compact.md +345 -0
  12. package/agents/gsd-doc-classifier.compact.md +192 -0
  13. package/agents/gsd-doc-synthesizer.compact.md +200 -0
  14. package/agents/gsd-doc-verifier.compact.md +143 -0
  15. package/agents/gsd-doc-writer.compact.md +440 -0
  16. package/agents/gsd-dom-verifier.compact.md +138 -0
  17. package/agents/gsd-domain-researcher.compact.md +141 -0
  18. package/agents/gsd-eval-auditor.compact.md +160 -0
  19. package/agents/gsd-eval-planner.compact.md +137 -0
  20. package/agents/gsd-framework-selector.compact.md +82 -0
  21. package/agents/gsd-integration-checker.compact.md +245 -0
  22. package/agents/gsd-intel-updater.compact.md +226 -0
  23. package/agents/gsd-mempalace-curator.compact.md +45 -0
  24. package/agents/gsd-nyquist-auditor.compact.md +179 -0
  25. package/agents/gsd-pattern-mapper.compact.md +275 -0
  26. package/agents/gsd-project-researcher.compact.md +587 -0
  27. package/agents/gsd-research-synthesizer.compact.md +212 -0
  28. package/agents/gsd-roadmapper.compact.md +454 -0
  29. package/agents/gsd-roadmapper.md +13 -0
  30. package/agents/gsd-security-auditor.compact.md +162 -0
  31. package/agents/gsd-ui-auditor.compact.md +404 -0
  32. package/agents/gsd-ui-checker.compact.md +277 -0
  33. package/agents/gsd-ui-researcher.compact.md +282 -0
  34. package/agents/gsd-user-profiler.compact.md +108 -0
  35. package/bin/install.js +206 -68
  36. package/commands/gsd/cleanup.md +1 -0
  37. package/commands/gsd/code-review.md +2 -1
  38. package/commands/gsd/complete-milestone.md +1 -0
  39. package/commands/gsd/config.md +1 -0
  40. package/commands/gsd/debug.md +1 -0
  41. package/commands/gsd/graphify.md +1 -0
  42. package/commands/gsd/health.md +1 -0
  43. package/commands/gsd/mempalace-capture.md +1 -0
  44. package/commands/gsd/mempalace-recall.md +1 -0
  45. package/commands/gsd/new-milestone.md +1 -0
  46. package/commands/gsd/new-project.md +1 -0
  47. package/commands/gsd/next.md +1 -0
  48. package/commands/gsd/pause-work.md +1 -0
  49. package/commands/gsd/phase.md +1 -0
  50. package/commands/gsd/pr-branch.md +1 -0
  51. package/commands/gsd/resume-work.md +1 -0
  52. package/commands/gsd/review-backlog.md +1 -0
  53. package/commands/gsd/settings.md +2 -1
  54. package/commands/gsd/stats.md +1 -0
  55. package/commands/gsd/thread.md +1 -0
  56. package/commands/gsd/workspace.md +1 -0
  57. package/commands/gsd/workstreams.md +1 -0
  58. package/gsd-core/bin/check-latest-version.cjs +8 -3
  59. package/gsd-core/bin/gsd-tools.cjs +338 -125
  60. package/gsd-core/bin/lib/adr-parser.cjs +1 -1
  61. package/gsd-core/bin/lib/artifacts.cjs +2 -1
  62. package/gsd-core/bin/lib/audit.cjs +39 -22
  63. package/gsd-core/bin/lib/broken-windows.cjs +168 -49
  64. package/gsd-core/bin/lib/capability-lifecycle.cjs +10 -6
  65. package/gsd-core/bin/lib/capability-loader.cjs +135 -1
  66. package/gsd-core/bin/lib/capability-registry.cjs +79 -67
  67. package/gsd-core/bin/lib/capability-source.cjs +19 -2
  68. package/gsd-core/bin/lib/capability-validator.cjs +14 -1
  69. package/gsd-core/bin/lib/check-command-router.cjs +113 -36
  70. package/gsd-core/bin/lib/code-review-depth.cjs +2 -2
  71. package/gsd-core/bin/lib/commands.cjs +650 -72
  72. package/gsd-core/bin/lib/config-loader.cjs +1 -0
  73. package/gsd-core/bin/lib/config.cjs +153 -38
  74. package/gsd-core/bin/lib/coverage.cjs +1 -1
  75. package/gsd-core/bin/lib/decisions.cjs +137 -34
  76. package/gsd-core/bin/lib/external-descriptor-trust.cjs +29 -14
  77. package/gsd-core/bin/lib/gsd2-import.cjs +1 -2
  78. package/gsd-core/bin/lib/health-diagnostic-rules/state-consistency.cjs +12 -1
  79. package/gsd-core/bin/lib/health-diagnostic-rules/worktree-health.cjs +1 -1
  80. package/gsd-core/bin/lib/init.cjs +409 -47
  81. package/gsd-core/bin/lib/install-engine.cjs +16 -3
  82. package/gsd-core/bin/lib/install-profiles.cjs +14 -0
  83. package/gsd-core/bin/lib/installer-migrations.cjs +33 -4
  84. package/gsd-core/bin/lib/loop-resolver.cjs +50 -31
  85. package/gsd-core/bin/lib/mcp-catalog.cjs +2 -2
  86. package/gsd-core/bin/lib/milestone.cjs +19 -8
  87. package/gsd-core/bin/lib/model-resolver.cjs +101 -10
  88. package/gsd-core/bin/lib/phase-command-router.cjs +7 -1
  89. package/gsd-core/bin/lib/phase-id.cjs +161 -22
  90. package/gsd-core/bin/lib/phase-lifecycle.cjs +61 -0
  91. package/gsd-core/bin/lib/phase.cjs +167 -63
  92. package/gsd-core/bin/lib/planning-inspect.cjs +34 -18
  93. package/gsd-core/bin/lib/planning-snapshot.cjs +61 -12
  94. package/gsd-core/bin/lib/planning-workspace.cjs +50 -1
  95. package/gsd-core/bin/lib/pristine-baseline.cjs +182 -0
  96. package/gsd-core/bin/lib/prohibition-enforcement.cjs +91 -4
  97. package/gsd-core/bin/lib/quick-batch.cjs +1 -1
  98. package/gsd-core/bin/lib/refactor-trigger-command-router.cjs +61 -2
  99. package/gsd-core/bin/lib/research-store.cjs +11 -12
  100. package/gsd-core/bin/lib/review-lane-invocation.cjs +23 -0
  101. package/gsd-core/bin/lib/reviewer-step-dispatch.cjs +337 -0
  102. package/gsd-core/bin/lib/roadmap-parser.cjs +56 -15
  103. package/gsd-core/bin/lib/roadmap.cjs +108 -14
  104. package/gsd-core/bin/lib/runtime-artifact-conversion.cjs +27 -10
  105. package/gsd-core/bin/lib/runtime-artifact-install-plan.cjs +12 -3
  106. package/gsd-core/bin/lib/runtime-artifact-layout.cjs +13 -5
  107. package/gsd-core/bin/lib/runtime-hooks-surface.cjs +193 -4
  108. package/gsd-core/bin/lib/security.cjs +126 -7
  109. package/gsd-core/bin/lib/state-document.cjs +130 -28
  110. package/gsd-core/bin/lib/state-md-schema.cjs +21 -14
  111. package/gsd-core/bin/lib/state-transition.cjs +142 -28
  112. package/gsd-core/bin/lib/state.cjs +223 -27
  113. package/gsd-core/bin/lib/surface.cjs +60 -2
  114. package/gsd-core/bin/lib/task-command-router.cjs +12 -6
  115. package/gsd-core/bin/lib/uat.cjs +1 -1
  116. package/gsd-core/bin/lib/update-context.cjs +30 -24
  117. package/gsd-core/bin/lib/vendor/js-yaml.cjs +11 -3
  118. package/gsd-core/bin/lib/verification.cjs +47 -15
  119. package/gsd-core/bin/lib/verify-command-grounding.cjs +1 -1
  120. package/gsd-core/bin/lib/verify.cjs +188 -23
  121. package/gsd-core/bin/lib/workstream-inventory.cjs +1 -0
  122. package/gsd-core/bin/lib/worktree-safety.cjs +13 -7
  123. package/gsd-core/bin/shared/config-defaults.manifest.json +1 -0
  124. package/gsd-core/bin/shared/config-schema.manifest.json +5 -0
  125. package/gsd-core/bin/verify-reapply-patches.cjs +439 -80
  126. package/gsd-core/references/compact-content-gate.md +66 -0
  127. package/gsd-core/references/loop-hook-dispatch.md +18 -0
  128. package/gsd-core/references/model-profiles.md +12 -3
  129. package/gsd-core/references/planning-config.md +3 -0
  130. package/gsd-core/references/tdd.md +5 -2
  131. package/gsd-core/references/thinking-models-planning.md +18 -2
  132. package/gsd-core/references/verification-patterns.md +17 -4
  133. package/gsd-core/references/worktree-path-safety.md +112 -2
  134. package/gsd-core/templates/README.md +7 -1
  135. package/gsd-core/templates/state.md +6 -3
  136. package/gsd-core/templates/summary.compact.md +212 -0
  137. package/gsd-core/templates/user-setup.compact.md +199 -0
  138. package/gsd-core/templates/user-setup.md +0 -9
  139. package/gsd-core/workflows/add-todo.md +3 -2
  140. package/gsd-core/workflows/autonomous.md +13 -10
  141. package/gsd-core/workflows/check-todos.md +4 -2
  142. package/gsd-core/workflows/cleanup.md +3 -1
  143. package/gsd-core/workflows/code-review/steps/structural-pre-pass.md +7 -0
  144. package/gsd-core/workflows/code-review-fix.md +3 -3
  145. package/gsd-core/workflows/code-review.md +156 -30
  146. package/gsd-core/workflows/complete-milestone/detail/elaboration.md +274 -0
  147. package/gsd-core/workflows/complete-milestone.md +39 -262
  148. package/gsd-core/workflows/docs-update/detail/elaboration.md +179 -0
  149. package/gsd-core/workflows/docs-update.md +14 -155
  150. package/gsd-core/workflows/execute-phase/detail/elaboration.md +124 -0
  151. package/gsd-core/workflows/execute-phase/steps/codebase-drift-gate.md +18 -3
  152. package/gsd-core/workflows/execute-phase/steps/completion-reconciliation.md +56 -0
  153. package/gsd-core/workflows/execute-phase/steps/executor-isolation-dispatch.md +7 -2
  154. package/gsd-core/workflows/execute-phase/steps/executor-progress-policy.md +43 -0
  155. package/gsd-core/workflows/execute-phase/steps/sequential-root-pin.md +35 -0
  156. package/gsd-core/workflows/execute-phase.md +53 -152
  157. package/gsd-core/workflows/execute-plan.md +20 -7
  158. package/gsd-core/workflows/help/modes/full.compact.md +398 -0
  159. package/gsd-core/workflows/help.md +1 -1
  160. package/gsd-core/workflows/map-codebase.md +50 -3
  161. package/gsd-core/workflows/new-milestone.md +54 -12
  162. package/gsd-core/workflows/new-project/detail/elaboration.md +216 -0
  163. package/gsd-core/workflows/new-project.md +32 -202
  164. package/gsd-core/workflows/plan-phase/detail/elaboration.md +209 -0
  165. package/gsd-core/workflows/plan-phase.md +22 -181
  166. package/gsd-core/workflows/pr-branch.md +19 -7
  167. package/gsd-core/workflows/quick.md +8 -1
  168. package/gsd-core/workflows/reapply-patches.md +77 -3
  169. package/gsd-core/workflows/settings.md +18 -5
  170. package/gsd-core/workflows/update.md +7 -5
  171. package/gsd-core/workflows/verify-work/detail/elaboration.md +230 -0
  172. package/gsd-core/workflows/verify-work.md +20 -180
  173. package/hooks/dist/gsd-agent-isolation-guard.js +42 -16
  174. package/hooks/dist/gsd-context-monitor.js +88 -15
  175. package/hooks/dist/gsd-cursor-subagent-start.js +34 -14
  176. package/hooks/dist/gsd-secret-read-guard.js +44 -18
  177. package/hooks/dist/gsd-statusline.js +11 -7
  178. package/hooks/dist/gsd-validate-commit.sh +34 -4
  179. package/hooks/dist/gsd-worktree-path-guard.js +25 -14
  180. package/hooks/dist/gsd-write-guard.js +46 -1
  181. package/hooks/dist/lib/dispatch-identity.js +187 -0
  182. package/hooks/dist/lib/filename-classification.js +64 -0
  183. package/hooks/dist/lib/isolation-deny-reason.js +53 -1
  184. package/hooks/dist/lib/isolation-sentinel.js +58 -19
  185. package/hooks/gsd-agent-isolation-guard.js +42 -16
  186. package/hooks/gsd-context-monitor.js +88 -15
  187. package/hooks/gsd-cursor-subagent-start.js +34 -14
  188. package/hooks/gsd-secret-read-guard.js +44 -18
  189. package/hooks/gsd-statusline.js +11 -7
  190. package/hooks/gsd-validate-commit.sh +34 -4
  191. package/hooks/gsd-worktree-path-guard.js +25 -14
  192. package/hooks/gsd-write-guard.js +46 -1
  193. package/hooks/lib/dispatch-identity.js +187 -0
  194. package/hooks/lib/filename-classification.js +64 -0
  195. package/hooks/lib/isolation-deny-reason.js +53 -1
  196. package/hooks/lib/isolation-sentinel.js +58 -19
  197. package/package.json +10 -6
  198. package/scripts/benchmark-compact-content-variants.cjs +298 -0
  199. package/scripts/benchmark-compact-content.cjs +368 -0
  200. package/scripts/check-contract-drift.cjs +4 -1
  201. package/scripts/check-env.cjs +36 -8
  202. package/scripts/check-glossary-refs.cjs +25 -21
  203. package/scripts/ci-next-health.cjs +271 -0
  204. package/scripts/ci-prepare-test-scope.cjs +7 -7
  205. package/scripts/ci-test-scope.cjs +126 -20
  206. package/scripts/ci-timeout-report.cjs +1 -1
  207. package/scripts/diff-touches-shipped-paths.cjs +1 -1
  208. package/scripts/docs-guard-registry.cjs +7 -2
  209. package/scripts/gen-adr-index.cjs +8 -2
  210. package/scripts/gen-inventory-manifest.cjs +12 -0
  211. package/scripts/gen-platform-conformance-tier.cjs +557 -0
  212. package/scripts/lib/drift-scan.cjs +1 -1
  213. package/scripts/lib/macos-conformance-tier.generated.cjs +210 -0
  214. package/scripts/lib/npm-version-check-diagnosis.cjs +59 -0
  215. package/scripts/lib/platform-conformance-tier.generated.cjs +276 -0
  216. package/scripts/lib/suite-detection.cjs +32 -0
  217. package/scripts/lint-allowed-tools-parity.cjs +221 -0
  218. package/scripts/lint-docs-guard-registration.exempt-baseline.cjs +19 -2
  219. package/scripts/lint-phase-id-drift.cjs +338 -13
  220. package/scripts/lint-response-language-coverage.cjs +9 -3
  221. package/scripts/lint-source-test-name-collision.cjs +1 -1
  222. package/scripts/lint-test-file-count.allowlist.json +1 -0
  223. package/scripts/lint-vendored-deps.cjs +128 -17
  224. package/scripts/lint-workflow-shellcheck-baseline.json +85 -0
  225. package/scripts/prompt-injection-scan.sh +14 -0
  226. package/scripts/workflow-size.cjs +139 -0
  227. package/skills/gsd-cleanup/SKILL.md +1 -0
  228. package/skills/gsd-code-review/SKILL.md +2 -1
  229. package/skills/gsd-complete-milestone/SKILL.md +1 -0
  230. package/skills/gsd-config/SKILL.md +1 -0
  231. package/skills/gsd-debug/SKILL.md +1 -0
  232. package/skills/gsd-graphify/SKILL.md +1 -0
  233. package/skills/gsd-health/SKILL.md +1 -0
  234. package/skills/gsd-mempalace-capture/SKILL.md +1 -0
  235. package/skills/gsd-mempalace-recall/SKILL.md +1 -0
  236. package/skills/gsd-new-milestone/SKILL.md +1 -0
  237. package/skills/gsd-new-project/SKILL.md +1 -0
  238. package/skills/gsd-next/SKILL.md +1 -0
  239. package/skills/gsd-pause-work/SKILL.md +1 -0
  240. package/skills/gsd-phase/SKILL.md +1 -0
  241. package/skills/gsd-pr-branch/SKILL.md +1 -0
  242. package/skills/gsd-resume-work/SKILL.md +1 -0
  243. package/skills/gsd-review-backlog/SKILL.md +1 -0
  244. package/skills/gsd-settings/SKILL.md +2 -1
  245. package/skills/gsd-stats/SKILL.md +1 -0
  246. package/skills/gsd-thread/SKILL.md +1 -0
  247. package/skills/gsd-workspace/SKILL.md +1 -0
  248. package/skills/gsd-workstreams/SKILL.md +1 -0
  249. package/vscode/package.json +1 -1
  250. package/gsd-core/templates/claude-md.md +0 -145
  251. package/gsd-core/templates/codebase/concerns.md +0 -310
  252. package/gsd-core/templates/codebase/conventions.md +0 -307
  253. package/gsd-core/templates/codebase/integrations.md +0 -280
  254. package/gsd-core/templates/codebase/structure.md +0 -285
  255. package/gsd-core/templates/codebase/testing.md +0 -480
  256. package/gsd-core/templates/debug-subagent-prompt.md +0 -91
  257. package/gsd-core/templates/discovery.md +0 -146
@@ -0,0 +1,66 @@
1
+ # Compact Content Gate
2
+
3
+ Shared by every workflow spine split under ADR-4139, and by every lazily-read fragment or
4
+ planning-artifact template given a compact variant under Phase 6 (#4406). States the config check
5
+ and both resolution rules once — a spine or fragment references this file; it never restates
6
+ either check inline.
7
+
8
+ ## The check
9
+
10
+ ```bash
11
+ COMPACT_CONTENT=$(gsd_run query config-get workflow.compact_content --raw 2>/dev/null || echo "false")
12
+ ```
13
+
14
+ ## Stream 1 — spine + detail (top-level, eagerly `@`-included workflows)
15
+
16
+ - **`COMPACT_CONTENT` is `"false"` (default):** Read every part under this workflow's own `detail/` directory (a sibling of this spine, e.g. `gsd-core/workflows/<name>/detail/*.md`) now, in full, before continuing past this point. Their content elaborates on the spine you are reading — treat everything they say as part of this document from here on.
17
+ - **`COMPACT_CONTENT` is `"true"`:** Do not read the detail file. Continue directly with the spine's own content — per ADR-4139 Decision 3, it is complete enough to run this workflow correctly on its own.
18
+
19
+ **The fail-safe this holds (ADR-4139 Decision 4):** A `Read` that does not fire for any reason (tool error, a skipped step, a misread condition) leaves you running on the spine alone. That is the same, correct, terser state an opted-in project runs in on purpose — never a state with no instructions. The spine's own completeness is what makes this safe; this gate is only ever additive.
20
+
21
+ ## Streams 1b and 4 — variant resolution (lazily-read fragments and planning-artifact templates)
22
+
23
+ For a `workflows/<name>/{modes,steps,templates}/*.md` fragment or a `gsd-core/templates/**`
24
+ planning-artifact template that has a registered `.compact.md` sibling (same directory, same stem,
25
+ `.compact.md` suffix):
26
+
27
+ - **`COMPACT_CONTENT` is `"false"` (default), or the file has no registered `.compact.md` sibling:** Read the canonical path exactly as named — unchanged from today.
28
+ - **`COMPACT_CONTENT` is `"true"` and a `.compact.md` sibling is registered:** Read the `.compact.md` sibling instead of the canonical path.
29
+
30
+ Both files are complete, independently — Read exactly one, never both, and never read the compact
31
+ sibling's content as an addendum to the canonical file.
32
+
33
+ **The fail-safe this holds:** unlike stream 1, a call site this rule actually applies to is already
34
+ reached only by a runtime `Read` — a missed `Read` already means zero overlay content, with or
35
+ without `workflow.compact_content`. Selecting between two independently-complete files at that
36
+ call site does not introduce a new way to end up with nothing; the worst case is identical to
37
+ today's. This is why stream 1b/4 can use variant-swap (two independent files) where stream 1 could
38
+ not: the degradation-direction argument that ruled out converting stream 1's `@`-includes (ADR-4139
39
+ Decision 4) does not apply at a genuine runtime-`Read` call site, because there is no
40
+ host-guaranteed baseline being traded away there.
41
+
42
+ **This rule is scoped per call site, not per file.** A `gsd-core/templates/**` file can have both
43
+ kinds of reference in the corpus at once — some places name it inside an eager `@`-include or an
44
+ orchestrator build-time embed (the same mechanism as stream 1, just reaching a template path
45
+ instead of a workflow path), others name it in prose instructing a runtime `Read`. Only the latter
46
+ gets rewritten to point at this rule; an eager reference to the canonical file is left exactly as
47
+ it is, for the same reason stream 1's `@`-includes were left alone — converting it would trade a
48
+ host-guaranteed load for a conditional one. Before wiring any call site, confirm by inspection
49
+ which kind it is; do not assume every mention of a `gsd-core/templates/**` path is a runtime `Read`
50
+ just because the directory's typical case is.
51
+
52
+ ## Stream 2 — agent-skill payloads (the `gsd_run query agent-skills` CLI seam)
53
+
54
+ `agents/<name>.compact.md`, same directory, same stem, `.compact.md` suffix — registered and
55
+ checked the same way as streams 1b/4. The selection is different: this seam already runs through
56
+ a real function call (`cmdAgentSkills`, `src/init.cts`), so the resolution happens **in code**,
57
+ not by a `gsd_run query config-get` prose instruction. There is nothing to state here for a
58
+ workflow author to follow, because no workflow author calls this seam directly — it fires only
59
+ inside the `#2454` persona fallback for non-Claude, AGENTS-native runtimes that cannot dispatch a
60
+ named subagent.
61
+
62
+ Same two rules as streams 1b/4, enforced in code instead of prose: `workflow.compact_content` off,
63
+ or no registered `.compact.md` sibling for that agent, serves the canonical persona unchanged; on,
64
+ with a sibling registered, serves the compact one. The one addition code gives that prose could
65
+ not: a missing sibling is disclosed in the served payload itself (a leading `<!-- gsd: no compact
66
+ payload registered ... -->` comment) rather than silently serving canonical with no signal at all.
@@ -57,6 +57,24 @@ Dispatch the referenced unit. Exactly one of `ref.skill`, `ref.agent`, or `ref.c
57
57
 
58
58
  Wait for the result before continuing to the next hook or the next step.
59
59
 
60
+ **`supportsReviewerLanes` (optional, boolean).** A `step` entry may carry
61
+ `supportsReviewerLanes: true` alongside `ref` (#4209). A workflow opts a step into external
62
+ reviewer-lane dispatch by calling `gsd_run review-lane dispatch-step --cap-id <capId> --point
63
+ <point> --explicit <slugs> ...` — `dispatch-step` resolves its OWN active hook for `<point>` (via
64
+ `resolveActiveHooksForPoint`, the same in-process resolver `loop render-hooks` itself calls) and
65
+ checks whether `<capId>`'s hook carries this field before proceeding; the workflow does not
66
+ resolve or gate on the trait itself, only passes the two flags naming which step it is. When the
67
+ trait reads exactly `true`, `dispatch-step` routes through `dispatchReviewerLanes`, the one
68
+ interpreter in `src/reviewer-step-dispatch.cts` that reuses the existing reviewer-lane selection,
69
+ planning, and invocation machinery, so any explicitly selected reviewer lane also reviews the
70
+ same scope. Absent or `false` is inert: `dispatch-step` itself is a no-op (a non-boolean value is
71
+ rejected by `capability-validator.cjs` at load time, so it never reaches `dispatch-step` at all).
72
+ This is the only place a step opts into reviewer-lane support: a capability beyond `code-review`
73
+ reuses it by declaring the same trait on its own step and calling `dispatch-step` with
74
+ `--cap-id`/`--point`, with zero bespoke TRAIT-RESOLUTION code of its own. The workflow still owns
75
+ matching its own CLI flags against the reviewer-lane roster and assembling the evidence block
76
+ handed to its consolidator — those are NOT part of what this trait makes reusable.
77
+
60
78
  A `step` is **advisory by construction**: it never blocks or redirects the host workflow —
61
79
  that is what a `gate` is for. Each dispatch is best-effort; on error record a warning and
62
80
  continue, honoring `onError`.
@@ -58,6 +58,10 @@ Model profiles control which Claude model each GSD agent uses. This allows balan
58
58
  3. **Profile table** — the per-agent column from the active `model_profile`
59
59
  4. **Runtime default** — when nothing else applies
60
60
 
61
+ Steps 2–4 select the *tier*; a `model_profile_overrides.<runtime>.<tier>` entry then
62
+ maps that tier to a concrete model (#4192 — honored on the claude runtime as well, so
63
+ pinning composes with tiering instead of replacing it).
64
+
61
65
  ### Why two layers above the profile?
62
66
 
63
67
  - **Profile** is a global tier strategy (everyone runs balanced).
@@ -215,8 +219,11 @@ is (highest → lowest):
215
219
  (see §Dynamic Routing — escalation steps tier up per attempt counter)
216
220
  4. If no dynamic_routing match, check models[phase_type] for a phase-type tier
217
221
  (see §Per-Phase-Type Model Map for the agent → phase-type mapping)
218
- 5. If no phase-type slot, look up agent in profile table
219
- 6. Pass model parameter to Task call
222
+ 5. Check model_profile_overrides.<runtime>.<tier> for a per-tier model override
223
+ (honored on the claude runtime too — #4192; verbatim unless it maps to the
224
+ current tier alias)
225
+ 6. If no phase-type slot, look up agent in profile table
226
+ 7. Pass model parameter to Task call
220
227
  ```
221
228
 
222
229
  `model` and `effort` resolve through different mechanisms at different
@@ -246,7 +253,9 @@ Override specific agents without changing the entire profile:
246
253
  }
247
254
  ```
248
255
 
249
- Overrides take precedence over the profile. Valid values: `opus`, `sonnet`, `haiku`, `inherit`, or any fully-qualified model ID (e.g., `"o3"`, `"openai/o3"`, `"google/gemini-2.5-pro"`).
256
+ Overrides take precedence over the profile. Valid values: `opus`, `sonnet`, `haiku`, `fable`, `inherit`, or any fully-qualified model ID (e.g., `"o3"`, `"openai/o3"`, `"google/gemini-2.5-pro"`). `fable` is a Claude Code Agent-tool alias, not a GSD profile tier — it has no column in the profile table above.
257
+
258
+ On the Claude runtime, fully-qualified Claude model IDs are honored as explicit generation pins (#4192): an ID that names the current tier default (e.g. `"claude-sonnet-5"`) resolves to its tier alias — the same model in the form the Agent tool always accepts — while any other ID (e.g. `"claude-opus-4-7"`) resolves verbatim, with a warn-once stderr note that setups accepting only tier aliases will not honor a full ID. To pin a generation for a whole tier rather than one agent, set `model_profile_overrides.claude.<tier>` (see docs/CONFIGURATION.md — Runtime-Aware Profiles).
250
259
 
251
260
  ## Switching Profiles
252
261
 
@@ -289,6 +289,7 @@ Set via `workflow.*` namespace in config.json (e.g., `"workflow": { "research":
289
289
  | `workflow.ui_phase` | boolean | `true` | `true`, `false` | Generate UI-SPEC.md for frontend phases |
290
290
  | `workflow.ui_safety_gate` | boolean | `true` | `true`, `false` | Require safety gate approval for UI changes |
291
291
  | `workflow.text_mode` | boolean | `false` | `true`, `false` | Use plain-text numbered lists instead of AskUserQuestion menus |
292
+ | `workflow.compact_content` | boolean | `false` | `true`, `false` | Compact content mode (#4139, ADR-4139) — per-project boolean selecting terser payloads. Six workflows branch on it via spine+detail: `plan-phase` (#4402, pilot), `execute-phase`, `docs-update`, `new-project`, `verify-work`, `complete-milestone` (#4405). The rest of the eager-window corpus was reviewed and recorded as not worth splitting (`docs/PARTITION-RULES.md`). Lazily-`Read` workflow fragments and `gsd-core/templates/**` templates use a `.compact.md` sibling instead (#4406, `gsd-core/references/compact-content-gate.md` § "Streams 1b and 4") — wired today for `help --full` and the sequential-execution `SUMMARY.md`/`USER-SETUP.md` reads. Agent-skill payloads (#4407, § "Stream 2") use the same `.compact.md` sibling shape, resolved in code by the `gsd_run query agent-skills` CLI seam rather than prose, for the non-Claude persona fallback only |
292
293
  | `workflow.research_before_questions` | boolean | `false` | `true`, `false` | Run research before interactive questions in discuss phase (also honored on the `/gsd:quick` path, #3894). _Alias:_ `research_before_questions` is the flat-key form used in `CONFIG_DEFAULTS`; `workflow.research_before_questions` is the canonical namespaced form. |
293
294
  | `workflow.discuss_mode` | string | `"discuss"` | `"discuss"`, `"assumptions"` | Default mode for discuss-phase: `"discuss"` runs interactive questioning; `"assumptions"` analyzes codebase and surfaces assumptions instead |
294
295
  | `workflow.skip_discuss` | boolean | `false` | `true`, `false` | Skip discuss phase entirely |
@@ -360,6 +361,8 @@ Set via `hooks.*` namespace (e.g., `"hooks": { "context_warnings": true }`).
360
361
  | Key | Type | Default | Allowed Values | Description |
361
362
  |-----|------|---------|----------------|-------------|
362
363
  | `hooks.context_warnings` | boolean | `true` | `true`, `false` | Show warnings when context budget is exceeded |
364
+ | `hooks.context_warning_threshold` | number | `35` | Greater than 0 and at most 100, and strictly greater than `hooks.context_critical_threshold`. `config-set` refuses 0: nothing is below it, so no critical value could satisfy the pair | Percent of context window REMAINING at or below which the monitor emits CONTEXT WARNING. An out-of-domain value falls back **per key**; both keys revert to their defaults only when the RESOLVED pair violates `critical < warning`. Read from the root project config — a workstream-scoped `config-set` does not reach this hook. Inert on a runtime with no context-monitor hook installed, Codex among them (#2586); see [context-monitor.md](../../docs/context-monitor.md) (#4285) |
365
+ | `hooks.context_critical_threshold` | number | `25` | At least 0 and less than 100, and strictly less than `hooks.context_warning_threshold`. `config-set` refuses 100: nothing is above it, so no warning value could satisfy the pair | Percent of context window REMAINING at or below which the monitor escalates to CONTEXT CRITICAL. Setting only one of the pair is checked against the other's default, so tune both when moving either past the other. Same root-config scope, and the same installed-monitor prerequisite, as the key above (#4285) |
363
366
 
364
367
  ### Learnings Fields
365
368
 
@@ -273,8 +273,11 @@ When `workflow.tdd_mode` is enabled in config, the RED/GREEN/REFACTOR gate seque
273
273
  After completing a `type: tdd` plan, the executor validates the git log:
274
274
  ```bash
275
275
  # The commit protocol promises no zero-padding for ${PHASE}/${PLAN} — strip both and
276
- # match the commit-scope position anchored (#4003).
277
- PHASE_N=$((10#${PHASE})); PLAN_N=$((10#${PLAN}))
276
+ # match the commit-scope position anchored (#4003). #4619: PHASE may be decimal/
277
+ # N-segment; zero-strip only the leading integer segment, escape the rest.
278
+ PHASE_INT=${PHASE%%.*}; PHASE_FRAC=${PHASE#"$PHASE_INT"}
279
+ PHASE_N="$((10#$PHASE_INT))${PHASE_FRAC//./\\.}"
280
+ PLAN_N=$((10#${PLAN}))
278
281
  # Check for RED gate commit
279
282
  git log --oneline -E --grep="^test\((0*${PHASE_N})-(0*${PLAN_N})\):" | head -1
280
283
  # Check for GREEN gate commit
@@ -34,13 +34,29 @@ For each significant decision in this plan, ask what undoing it would cost three
34
34
 
35
35
  This is the reasoning step that produces the rating. The taxonomy itself, the emission rules, and the anti-patterns live in @~/.claude/gsd-core/references/planner-reversibility.md — do not maintain a second classification here.
36
36
 
37
- ## 5. Curse of Knowledge Counter
37
+ ## 5. Occam's Razor
38
+
39
+ **Counters:** Plans that prescribe avoidable dependencies, abstractions, files, or speculative flexibility before execution begins.
40
+
41
+ This check complements the planner's RESEARCH.md `dont_hand_roll` guidance and the plan checker's Dimension 12 (Pattern Compliance): those sources identify capabilities and established patterns, while this check orders otherwise sufficient implementation choices. The executor applies the related check later in `thinking-models-execution.md`, after the plan has already selected an approach.
42
+
43
+ After preserving locked user decisions and complete requirement coverage, choose the first option that is demonstrably sufficient for the task's `<done>` condition:
44
+
45
+ 1. Existing project behavior, helper, or established pattern
46
+ 2. Standard-library capability
47
+ 3. Native platform capability
48
+ 4. Already-installed dependency
49
+ 5. Minimum new implementation
50
+
51
+ This ordering is a sufficiency check, not permission to make the task smaller. It must never reduce requested scope or override locked user decisions, requirement coverage, security, validation, accessibility, error handling, or verification. The planner uses it when choosing implementation actions; the plan checker flags a new abstraction or dependency only when a higher rung is demonstrably sufficient.
52
+
53
+ ## 6. Curse of Knowledge Counter
38
54
 
39
55
  **Counters:** Plan-to-executor ambiguity from compressed instructions.
40
56
 
41
57
  For each `<action>` step, re-read it as if you have NEVER seen this codebase. Is every noun unambiguous (which file? which function? which endpoint?)? Is every verb specific (add WHERE? modify HOW?)? If a step could be interpreted two ways, rewrite it. Include file paths, function names, and expected behavior in every action step.
42
58
 
43
- ## 6. Base Rate Neglect Counter
59
+ ## 7. Base Rate Neglect Counter
44
60
 
45
61
  **Counters:** Planners ignoring low-confidence research caveats.
46
62
 
@@ -309,14 +309,17 @@ grep -r "$hook_name()" src/ --include="*.tsx" --include="*.ts" | grep -v "$hook_
309
309
  # .env file exists
310
310
  [ -f ".env" ] || [ -f ".env.local" ]
311
311
 
312
- # Required variable is defined
313
- grep -E "^$VAR_NAME=" .env .env.local 2>/dev/null
312
+ # Required variable is defined (in the environment: dotenv/direnv/the framework has loaded it)
313
+ printenv "$VAR_NAME" >/dev/null
314
314
  ```
315
315
 
316
316
  **Substantive check:**
317
317
  ```bash
318
- # Variable has actual value (not placeholder)
319
- grep -E "^$VAR_NAME=.+" .env .env.local 2>/dev/null | grep -v "your-.*-here|xxx|placeholder|TODO" -i
318
+ # Variable has an actual value (not a placeholder) -- tests the shape, never prints the value;
319
+ # exit 0 = real value, exit 1 = missing or placeholder (case-insensitive)
320
+ v=$(printenv "$VAR_NAME"); case "$(printf %s "$v" | tr '[:upper:]' '[:lower:]')" in
321
+ ""|*your-*-here*|*xxx*|*placeholder*|*todo*) exit 1;;
322
+ esac
320
323
 
321
324
  # Value looks valid for type:
322
325
  # - URLs should start with http
@@ -324,6 +327,16 @@ grep -E "^$VAR_NAME=.+" .env .env.local 2>/dev/null | grep -v "your-.*-here|xxx|
324
327
  # - Booleans should be true/false
325
328
  ```
326
329
 
330
+ When the variable is not present in the agent's own environment (a framework that loads
331
+ `.env.local` itself at runtime does not export it to the shell that runs these checks),
332
+ ask the user to confirm it is set rather than reading `.env` directly. Variable NAMES can
333
+ still be checked against `.env.example`, which the secret-read guard exempts from its
334
+ protected-file patterns.
335
+
336
+ One guard-matching note worth knowing when auditing docs for `.env` mentions: the guard
337
+ treats a grep PATTERN whose last path segment is a secret file name as a file operand, so
338
+ `grep -n "\.env" file.md` is denied while `grep -n "\.env\b" file.md` is allowed.
339
+
327
340
  **Stub patterns specific to env:**
328
341
  ```bash
329
342
  # RED FLAGS - These are stubs:
@@ -1,7 +1,117 @@
1
1
  # Worktree Path Safety
2
2
 
3
- Guards for executor agents running inside Claude Code worktrees. Three checks
4
- must run before any staging, Edit, or Write operation in worktree mode.
3
+ Guards for executor agents running inside Claude Code worktrees. The
4
+ supplied-root pin (step 0p) runs in EVERY mode; the remaining checks run before
5
+ any staging, Edit, or Write operation in worktree mode.
6
+
7
+ ---
8
+
9
+ ## Supplied-root pin — step 0p (#4254, EVERY mode)
10
+
11
+ Sequential-mode dispatch (no `isolation="worktree"`) gives the executor no
12
+ spawn-time cwd guarantee, and the worktree-only guards below do not apply — so
13
+ a sequential executor whose process cwd resolved to a different checkout of
14
+ the same repo would self-derive that checkout as its root and commit there,
15
+ silently. Step 0p closes that hole by comparing the executor's actual root
16
+ against a root the ORCHESTRATOR already validated — never against anything the
17
+ executor derives itself.
18
+
19
+ **Runtime contract (executor):** if your prompt contains a `<project_root_pin>`
20
+ block, run its guard script verbatim before your first Edit/Write and again
21
+ before every commit, in the same cwd as that write or commit. On FATAL, halt
22
+ and report — recovery (moving commits between checkouts) is an
23
+ orchestrator/human decision, never agent self-repair. If your prompt contains
24
+ NO `<project_root_pin>` block (worktree/isolated dispatch, or a legacy
25
+ orchestrator), emit one warning line and continue with steps 0a/0b below — do
26
+ not fail closed on dispatches that never carried a pin. **Never bind
27
+ `{PINNED_ROOT}` yourself**: if this template reaches you unbound it is
28
+ reference prose, not your pin — only the orchestrator's build-time
29
+ substitution produces a valid guard.
30
+
31
+ **Composition contract (orchestrator — build time, NOT a sub-agent runtime
32
+ step):** copy the guard below into the dispatched prompt inside a
33
+ `<project_root_pin>` block, substituting `{PINNED_ROOT}` with the literal value
34
+ of `$ORCHESTRATOR_WT` captured at execute_waves entry, shell-single-quoted:
35
+ wrap the path in `'…'` and escape any embedded `'` as `'\''`. A path that
36
+ cannot be quoted this way must halt the phase (surface a blocker) rather than
37
+ ship a pin that could mis-parse. The comparison is git-vs-git on BOTH sides —
38
+ `git -C` resolves the pinned path to its repo's canonical toplevel in git's
39
+ own path representation, so symlink aliases, trailing slashes, `/var` vs
40
+ `/private/var` spellings, and Windows drive-letter forms — forward- or
41
+ backslash-separated, `RUNNER~1`-style short names included — compare equal by
42
+ construction (shell `pwd -P` normalization does NOT match git's emission on
43
+ Windows — do not re-introduce it).
44
+
45
+ Two portability rules baked into the guard below, learned from the #4254 CI
46
+ Windows legs: (1) a backslash comparator must be GENERATED at runtime
47
+ (`printf '\134'`), because a backslash written twice in the script text does
48
+ not survive the Windows command-line round-trip into bash — the doubled form
49
+ arrives halved, which silently rewrites any escape pattern that relies on it;
50
+ (2) every FATAL names its `Guard stage` and, where a git capture failed,
51
+ git's own stderr in a `Diagnostic` line, so a platform failure self-describes
52
+ instead of surfacing as a bare `Actual root: <none>`.
53
+
54
+ ```bash
55
+ # gsd:guard=supplied-root-pin (#4254) — run before the first Edit/Write and before every commit.
56
+ PINNED_ROOT='{PINNED_ROOT}' # orchestrator build-time substitution — the only valid source of this value
57
+ PIN_STAGE=''
58
+ PIN_DIAG=''
59
+ gsd_pin_fail() {
60
+ echo "FATAL: executor root does not match the orchestrator-supplied PROJECT_ROOT pin (#4254)." >&2
61
+ echo " Pinned root: ${PINNED_ROOT:-<empty or unexpanded>}" >&2
62
+ echo " Actual root: ${ACTUAL_ROOT:-<none>}" >&2
63
+ echo " Guard stage: ${PIN_STAGE:-<unset>}" >&2
64
+ if [ -n "$PIN_DIAG" ]; then echo " Diagnostic: $PIN_DIAG" >&2; fi
65
+ echo " No writes or commits are permitted from this checkout. HALT and report; recovery is an" >&2
66
+ echo " orchestrator/human decision. Only the IMMEDIATE submodule of the pinned checkout is a" >&2
67
+ echo " legitimate other cwd — nested submodules must surface as a blocker, not self-route." >&2
68
+ exit 1
69
+ }
70
+ # Backslash comparator, generated at runtime: a backslash written twice in this
71
+ # script does not survive the Windows spawn path into bash (the command-line
72
+ # round-trip halves the doubled form), which rejected every C:\ pin at the form
73
+ # gate on the #4254 CI Windows legs. printf's octal escape is a lone backslash,
74
+ # which does survive; the quoted expansion below is literal in a case pattern.
75
+ BS=$(printf '\134')
76
+ # Fail closed if the comparator could not be generated: an empty BS would widen
77
+ # the drive-form arm below to drive-RELATIVE pins (C:foo) — the one fail-open
78
+ # seam in this construction, closed loudly rather than trusted to the shell.
79
+ if [ -z "$BS" ]; then
80
+ PIN_STAGE=form-gate
81
+ PIN_DIAG='backslash comparator generation failed (printf octal escape returned empty)'
82
+ gsd_pin_fail
83
+ fi
84
+ case "$PINNED_ROOT" in
85
+ ''|'{PINNED_ROOT}') PIN_STAGE=pin-unbound; gsd_pin_fail ;; # empty or unexpanded pin — fail closed, never warn-and-proceed
86
+ /*) ;; # absolute POSIX form
87
+ [A-Za-z]:/*|[A-Za-z]:"$BS"*) ;; # Windows drive form, forward- or backslash-separated
88
+ *) PIN_STAGE=form-gate; gsd_pin_fail ;; # relative pin — never trustworthy across cwds
89
+ esac
90
+ ACTUAL_ROOT=$(git rev-parse --show-toplevel 2>/dev/null)
91
+ if [ -z "$ACTUAL_ROOT" ]; then
92
+ PIN_STAGE=actual-capture
93
+ PIN_DIAG="git rev-parse --show-toplevel from the cwd failed: $(git rev-parse --show-toplevel 2>&1 1>/dev/null)"
94
+ gsd_pin_fail
95
+ fi
96
+ PINNED_TL=$(git -C "$PINNED_ROOT" rev-parse --show-toplevel 2>/dev/null)
97
+ if [ -z "$PINNED_TL" ]; then
98
+ PIN_STAGE=pinned-capture
99
+ PIN_DIAG="git -C <pinned root> rev-parse --show-toplevel failed: $(git -C "$PINNED_ROOT" rev-parse --show-toplevel 2>&1 1>/dev/null)"
100
+ gsd_pin_fail
101
+ fi
102
+ if [ "$ACTUAL_ROOT" != "$PINNED_TL" ]; then
103
+ # Registered-submodule allowance: sub_repos plans legitimately commit inside an
104
+ # immediate submodule of the pinned checkout. The superproject working tree is
105
+ # git-emitted in the same representation as PINNED_TL, so the equality is
106
+ # representation-safe on every platform.
107
+ SUPER_TL=$(git rev-parse --show-superproject-working-tree 2>/dev/null)
108
+ if [ "$SUPER_TL" != "$PINNED_TL" ]; then
109
+ PIN_STAGE=root-mismatch
110
+ PIN_DIAG="actual=${ACTUAL_ROOT} pinned=${PINNED_TL} superproject=${SUPER_TL:-<none>}"
111
+ gsd_pin_fail
112
+ fi
113
+ fi
114
+ ```
5
115
 
6
116
  ---
7
117
 
@@ -21,8 +21,14 @@ These files live directly at `.planning/` — not inside phase subdirectories.
21
21
  | `LEARNINGS.md` | *(inline)* | `/gsd:extract-learnings`, `/gsd:execute-phase` (gated: `features.global_learnings`) | Phase retrospective learnings for future plans |
22
22
  | `THREADS.md` | *(inline)* | `/gsd:thread` | Persistent discussion threads |
23
23
  | `config.json` | `config.json` | `/gsd:new-project`, `/gsd:health --repair` | Project-specific GSD configuration |
24
- | `CLAUDE.md` | `claude-md.md` | `/gsd-profile` | Auto-assembled Claude Code context file |
24
+ | `CLAUDE.md` | *(inline)* | `/gsd-profile` | Auto-assembled Claude Code context file |
25
25
  | `RETROSPECTIVE.md` | *(inline)* | `/gsd:complete-milestone` | Living milestone retrospective updated at each milestone close |
26
+ | `WINDOWS.md` | *(none)* | broken-windows ledger (`src/broken-windows.cts`) | Tracked known-broken items pending resolution (#3224) |
27
+ | `STATE-ARCHIVE.md` | *(none)* | `state.cts`'s `cmdStatePrune` | Pruned historical STATE.md entries |
28
+ | `milestone.lock` | *(none)* | `src/milestone-lock.cts` | Persistent milestone (phase + session) claim, unlike the transient `STATE.md.lock`/`WAITING.json` (#3311) |
29
+ | `state.json` | *(none)* | `src/state-contract.cts` | Machine-readable state contract published at step boundaries (#3227) |
30
+ | `skill-manifest.json` | *(none)* | `init.cts`'s `cmdSkillManifest --write` | Project-scoped skill manifest (#3964) |
31
+ | `PATTERNS.md` | *(inline)* | `/gsd:extract-learnings` (graduation, `workflows/graduation.md`, `patterns` target) | Graduated cross-phase patterns -- distinct from the per-phase `NN-PATTERNS.md` below (#4282) |
26
32
 
27
33
  ### Version-stamped artifacts (pattern: `vX.Y-*.md`)
28
34
 
@@ -172,9 +172,12 @@ Updated after each plan completion.
172
172
  **Decisions:** Reference to PROJECT.md Key Decisions table, plus recent decisions summary for quick access. Full decision log lives in PROJECT.md.
173
173
 
174
174
  **Pending Todos:** Ideas captured via /gsd-add-todo
175
- - Count of pending todos
176
- - Reference to .planning/todos/pending/
177
- - Brief list if few, count if many (e.g., "5 pending todos — see /gsd:capture --list")
175
+ - One bullet per pending todo, rendered by `init.todos`'s `pending_todos_markdown`
176
+ (each bullet capped at 240 characters: `- [date] [area] title — [todo file](path) — Needs ...`;
177
+ the todo-file link is repo-relative, so the cap does not depend on checkout path length)
178
+ - `None yet.` when there are no pending todos
179
+ - No collapse-by-count fallback — every pending todo gets its own line, always
180
+ (see #2618 design doc for why a "count if many" fallback was rejected)
178
181
 
179
182
  **Blockers/Concerns:** From "Next Phase Readiness" sections
180
183
  - Issues that affect future work
@@ -0,0 +1,212 @@
1
+ # Summary Template
2
+
3
+ Template for `.planning/phases/XX-name/{phase}-{plan}-SUMMARY.md` - phase completion documentation.
4
+
5
+ ---
6
+
7
+ ## File Template
8
+
9
+ ```markdown
10
+ ---
11
+ phase: XX-name
12
+ plan: YY
13
+ subsystem: [primary category: auth, payments, ui, api, database, infra, testing, etc.]
14
+ tags: [searchable tech: jwt, stripe, react, postgres, prisma]
15
+
16
+ # Dependency graph
17
+ requires:
18
+ - phase: [prior phase this depends on]
19
+ provides: [what that phase built that this uses]
20
+ provides:
21
+ - [bullet list of what this phase built/delivered]
22
+ affects: [list of phase names or keywords that will need this context]
23
+
24
+ # Actuals (#2632) — pairs with the plan's `estimate` to calibrate future estimates.
25
+ # Same estimateTokens scale (chars/4 over the realized diff), never a harness token count.
26
+ actuals:
27
+ tokens: [chars/4 over files actually changed]
28
+ tasks: [tasks completed]
29
+ commits: [commits made]
30
+
31
+ # Tech tracking
32
+ tech-stack:
33
+ added: [libraries/tools added in this phase]
34
+ patterns: [architectural/code patterns established]
35
+
36
+ key-files:
37
+ created: [important files created]
38
+ modified: [important files modified]
39
+
40
+ key-decisions:
41
+ - "Decision 1"
42
+ - "Decision 2"
43
+
44
+ patterns-established:
45
+ - "Pattern 1: description"
46
+ - "Pattern 2: description"
47
+
48
+ requirements-completed: [] # REQUIRED — Copy ALL requirement IDs from this plan's `requirements` frontmatter field.
49
+
50
+ # Coverage metadata (#1602) — one entry per shipped deliverable. Drives DETERMINISTIC UAT routing in verify-work.
51
+ # OMIT this whole block for legacy/prose-only SUMMARYs — verify-work then falls back to the ## Accomplishments bullets
52
+ # (byte-identical behavior for un-migrated phases). See <coverage_guidance> below for the contract.
53
+ coverage:
54
+ - id: D1
55
+ description: "[deliverable in human-readable form — what would have been a prose ## Accomplishments bullet]"
56
+ requirement: "[REQ-ID from this plan's `requirements`, or omit if none]"
57
+ verification:
58
+ - kind: unit # unit | integration | e2e | automated_ui | manual_procedural | other
59
+ ref: "[tests/path.test.ts#test name | playwright:shot.png | command invocation]"
60
+ status: pass # pass | fail | unknown — from the latest run
61
+ human_judgment: false # REQUIRED boolean. false => may auto-pass IF every verification status is `pass`.
62
+ - id: D2
63
+ description: "[a deliverable that needs a human to sign off]"
64
+ verification: []
65
+ human_judgment: true
66
+ rationale: "[REQUIRED when human_judgment: true — why automation is insufficient]"
67
+
68
+ # Metrics
69
+ duration: Xmin
70
+ completed: YYYY-MM-DD
71
+ status: complete
72
+ ---
73
+
74
+ # Phase [X]: [Name] Summary
75
+
76
+ **[Substantive one-liner describing outcome - NOT "phase complete" or "implementation finished"]**
77
+
78
+ ## Performance
79
+
80
+ - **Duration:** [time] (e.g., 23 min, 1h 15m)
81
+ - **Started:** [ISO timestamp]
82
+ - **Completed:** [ISO timestamp]
83
+ - **Tasks:** [count completed]
84
+ - **Files modified:** [count]
85
+
86
+ ## Accomplishments
87
+ - [Most important outcome]
88
+ - [Second key accomplishment]
89
+ - [Third if applicable]
90
+
91
+ ## Task Commits
92
+
93
+ Each task was committed atomically:
94
+
95
+ 1. **Task 1: [task name]** - `abc123f` (feat/fix/test/refactor)
96
+ 2. **Task 2: [task name]** - `def456g` (feat/fix/test/refactor)
97
+ 3. **Task 3: [task name]** - `hij789k` (feat/fix/test/refactor)
98
+
99
+ **Plan metadata:** `lmn012o` (docs: complete plan)
100
+
101
+ _Note: TDD tasks may have multiple commits (test → feat → refactor)_
102
+
103
+ ## Files Created/Modified
104
+ - `path/to/file.ts` - What it does
105
+ - `path/to/another.ts` - What it does
106
+
107
+ ## Decisions Made
108
+ [Key decisions with brief rationale, or "None - followed plan as specified"]
109
+
110
+ ## Deviations from Plan
111
+
112
+ [If no deviations: "None - plan executed exactly as written"]
113
+
114
+ [If deviations occurred:]
115
+
116
+ ### Auto-fixed Issues
117
+
118
+ **1. [Rule X - Category] Brief description**
119
+ - **Found during:** Task [N] ([task name])
120
+ - **Issue:** [What was wrong]
121
+ - **Fix:** [What was done]
122
+ - **Files modified:** [file paths]
123
+ - **Verification:** [How it was verified]
124
+ - **Committed in:** [hash] (part of task commit)
125
+
126
+ [... repeat for each auto-fix ...]
127
+
128
+ ---
129
+
130
+ **Total deviations:** [N] auto-fixed ([breakdown by rule])
131
+ **Impact on plan:** [Brief assessment - e.g., "All auto-fixes necessary for correctness/security. No scope creep."]
132
+
133
+ ## Issues Encountered
134
+ [Problems and how they were resolved, or "None"]
135
+
136
+ [Note: "Deviations from Plan" documents unplanned work that was handled automatically via deviation rules. "Issues Encountered" documents problems during planned work that required problem-solving.]
137
+
138
+ ## User Setup Required
139
+
140
+ [If USER-SETUP.md was generated:]
141
+ **External services require manual configuration.** See [{phase}-USER-SETUP.md](./{phase}-USER-SETUP.md) for:
142
+ - Environment variables to add
143
+ - Dashboard configuration steps
144
+ - Verification commands
145
+
146
+ [If no USER-SETUP.md:]
147
+ None - no external service configuration required.
148
+
149
+ ## Next Phase Readiness
150
+ [What's ready for next phase]
151
+ [Any blockers or concerns]
152
+
153
+ ---
154
+ *Phase: XX-name*
155
+ *Completed: [date]*
156
+ ```
157
+
158
+ <frontmatter_guidance>
159
+ **Purpose:** Enable automatic context assembly via dependency graph. Frontmatter makes summary metadata machine-readable so plan-phase can scan all summaries quickly and select relevant ones based on dependencies (`requires`/`provides`/`affects` create the explicit links; transitive closure follows from them).
160
+
161
+ **Subsystem/Tags:** Primary categorization + searchable technical keywords, for detecting related phases and tech-stack awareness. **Key-files:** important files for @context references in PLAN.md. **Patterns:** established conventions future phases should maintain.
162
+
163
+ **Population:** Frontmatter is populated during summary creation in execute-plan.md. See `<step name="create_summary">` for field-by-field guidance.
164
+
165
+ **Status (#2830):** `status: complete` is the default — the plan finished. Use `status: halted` instead when the plan reached a designed stop (a gate failure, a spike concluding without expanding into the full build, or any other intentional non-completion) and intentionally left tasks unfinished. `halted` is machine-read: any plan whose `depends_on` (directly or transitively) names a halted plan is reported as blocked, not offered to the executor, until the halt is resolved and re-summarized as `complete`.
166
+ </frontmatter_guidance>
167
+
168
+ <coverage_guidance>
169
+ **Purpose (#1602):** The `coverage:` block is a per-deliverable Requirements Traceability Matrix. It lets `verify-work`'s `extract_tests` step route deliverables DETERMINISTICALLY — auto-passing those proven by passing tests and reserving human UAT for genuine judgment — instead of re-deriving coverage from prose. Consumed via `gsd-tools uat classify-coverage --summary <SUMMARY>`.
170
+
171
+ **Field semantics:**
172
+
173
+ | Field | Purpose |
174
+ |---|---|
175
+ | `id` | Stable identifier (`D1`, `D2`…) for cross-referencing from UAT.md and audit reports. Must be unique within the SUMMARY. |
176
+ | `description` | The deliverable in human-readable form — what would have been a prose bullet. |
177
+ | `requirement` | Links back to a REQUIREMENTS.md REQ-ID (joins `requirements-completed`). Optional. |
178
+ | `verification[].kind` | Enum: `unit \| integration \| e2e \| automated_ui \| manual_procedural \| other`. |
179
+ | `verification[].ref` | Test path + descriptor (`file#test name`), Playwright screenshot ref, or command invocation. Required per entry. |
180
+ | `verification[].status` | `pass \| fail \| unknown` — populated from the latest test run. |
181
+ | `human_judgment` | Explicit boolean; REQUIRED. `true` always routes to a human. |
182
+ | `rationale` | REQUIRED when `human_judgment: true`. The audit trail for why automation is insufficient. |
183
+
184
+ **Deterministic contract (what the classifier does):**
185
+ - A deliverable auto-passes (no human prompt) **only** when `human_judgment: false` AND `verification` is non-empty AND every `verification[].status` is `pass`. This is the narrow, fully-proven case.
186
+ - **Everything else is presented to a human** — `human_judgment: true`, an empty `verification:`, any non-`pass`/`unknown` status, or any schema error. A false-negative is a redundant prompt (the status quo); a false-positive ships a bug UAT existed to catch.
187
+ - **Fail-safe default:** if you cannot determine coverage for a deliverable, you MUST set `human_judgment: true` with `rationale: "Coverage not determined at authoring time — verifier must classify"`. Never leave a deliverable's `human_judgment` empty, and never set it `false` just to skip the prompt — auto-pass additionally requires a passing `verification` entry, so the flag alone cannot skip the human.
188
+ - `coverage: []` means "no deliverables to classify" (the single-confirmation path). OMITTING the block entirely means "legacy" — `verify-work` falls back to prose `## Accomplishments` extraction unchanged.
189
+ </coverage_guidance>
190
+
191
+ <one_liner_rules>
192
+ The one-liner MUST be substantive:
193
+
194
+ **Good:** "JWT auth with refresh rotation using jose library" · "Prisma schema with User, Session, and Product models" · "Dashboard with real-time metrics via Server-Sent Events"
195
+
196
+ **Bad:** "Phase complete" · "Authentication implemented" · "Foundation finished" · "All tasks done"
197
+
198
+ The one-liner should tell someone what actually shipped.
199
+ </one_liner_rules>
200
+
201
+ <guidelines>
202
+ **Frontmatter:** MANDATORY - complete all fields. Enables automatic context assembly for future planning.
203
+
204
+ **One-liner:** Must be substantive. "JWT auth with refresh rotation using jose library" not "Authentication implemented".
205
+
206
+ **Decisions section:**
207
+ - Key decisions made during execution with rationale
208
+ - Extracted to STATE.md accumulated context
209
+ - Use "None - followed plan as specified" if no deviations
210
+
211
+ **After creation:** STATE.md updated with position, decisions, issues.
212
+ </guidelines>