@opengsd/gsd-core 1.14.0 → 1.15.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 (283) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/README.ja-JP.md +3 -3
  4. package/README.ko-KR.md +3 -3
  5. package/README.pt-BR.md +3 -3
  6. package/README.zh-CN.md +3 -3
  7. package/agents/gsd-code-fixer.compact.md +7 -6
  8. package/agents/gsd-code-fixer.md +9 -8
  9. package/agents/gsd-debug-session-manager.compact.md +17 -2
  10. package/agents/gsd-debug-session-manager.md +17 -2
  11. package/agents/gsd-debugger.md +2 -2
  12. package/agents/gsd-eval-auditor.compact.md +1 -1
  13. package/agents/gsd-eval-auditor.md +1 -1
  14. package/agents/gsd-executor.md +13 -8
  15. package/agents/gsd-intel-updater.compact.md +1 -1
  16. package/agents/gsd-intel-updater.md +1 -1
  17. package/agents/gsd-phase-researcher.md +19 -11
  18. package/agents/gsd-plan-checker.md +8 -7
  19. package/agents/gsd-planner.md +12 -8
  20. package/agents/gsd-project-researcher.compact.md +1 -1
  21. package/agents/gsd-project-researcher.md +1 -1
  22. package/agents/gsd-research-synthesizer.compact.md +1 -1
  23. package/agents/gsd-research-synthesizer.md +1 -1
  24. package/agents/gsd-ui-auditor.md +155 -17
  25. package/agents/gsd-ui-researcher.compact.md +1 -1
  26. package/agents/gsd-ui-researcher.md +1 -1
  27. package/agents/gsd-verifier.md +10 -9
  28. package/bin/install.js +642 -95
  29. package/commands/gsd/autonomous.md +2 -2
  30. package/commands/gsd/capture.md +1 -1
  31. package/commands/gsd/mempalace-capture.md +7 -3
  32. package/commands/gsd/plan-review-convergence.md +6 -6
  33. package/commands/gsd/progress.md +1 -1
  34. package/commands/gsd/quick-batch.md +1 -1
  35. package/commands/gsd/review.md +2 -3
  36. package/gsd-core/bin/gsd-tools.cjs +335 -22
  37. package/gsd-core/bin/lib/adr-parser.cjs +3 -1
  38. package/gsd-core/bin/lib/audit.cjs +81 -13
  39. package/gsd-core/bin/lib/capability-registry.cjs +82 -187
  40. package/gsd-core/bin/lib/capability-validator.cjs +0 -1
  41. package/gsd-core/bin/lib/check-command-router.cjs +101 -14
  42. package/gsd-core/bin/lib/codex-agent-toml.cjs +21 -25
  43. package/gsd-core/bin/lib/commands.cjs +175 -42
  44. package/gsd-core/bin/lib/config-loader.cjs +65 -4
  45. package/gsd-core/bin/lib/config.cjs +33 -7
  46. package/gsd-core/bin/lib/decisions.cjs +30 -14
  47. package/gsd-core/bin/lib/frontmatter.cjs +13 -0
  48. package/gsd-core/bin/lib/graphify.cjs +10 -2
  49. package/gsd-core/bin/lib/host-runtime-detection.cjs +9 -0
  50. package/gsd-core/bin/lib/init.cjs +207 -41
  51. package/gsd-core/bin/lib/install-engine.cjs +13 -0
  52. package/gsd-core/bin/lib/installer-migrations.cjs +8 -1
  53. package/gsd-core/bin/lib/milestone.cjs +18 -5
  54. package/gsd-core/bin/lib/model-resolver.cjs +159 -50
  55. package/gsd-core/bin/lib/phase-command-router.cjs +9 -1
  56. package/gsd-core/bin/lib/phase-id-card.cjs +32 -0
  57. package/gsd-core/bin/lib/phase-id-display.cjs +78 -0
  58. package/gsd-core/bin/lib/phase-id.cjs +109 -7
  59. package/gsd-core/bin/lib/phase-locator.cjs +29 -10
  60. package/gsd-core/bin/lib/phase.cjs +227 -26
  61. package/gsd-core/bin/lib/plan-document.cjs +49 -1
  62. package/gsd-core/bin/lib/planning-document.cjs +459 -0
  63. package/gsd-core/bin/lib/planning-inspect.cjs +18 -1
  64. package/gsd-core/bin/lib/planning-workspace.cjs +8 -3
  65. package/gsd-core/bin/lib/pr-branch-patterns.cjs +57 -0
  66. package/gsd-core/bin/lib/probe-core.cjs +7 -1
  67. package/gsd-core/bin/lib/project-root.cjs +41 -2
  68. package/gsd-core/bin/lib/review-lane-descriptor.cjs +10 -30
  69. package/gsd-core/bin/lib/review-reviewer-selection.cjs +2 -2
  70. package/gsd-core/bin/lib/roadmap-command-router.cjs +12 -4
  71. package/gsd-core/bin/lib/roadmap-parser.cjs +163 -3
  72. package/gsd-core/bin/lib/roadmap-upgrade.cjs +1539 -13
  73. package/gsd-core/bin/lib/roadmap.cjs +251 -31
  74. package/gsd-core/bin/lib/runtime-artifact-conversion.cjs +283 -31
  75. package/gsd-core/bin/lib/runtime-artifact-install-plan.cjs +3 -1
  76. package/gsd-core/bin/lib/runtime-homes.cjs +4 -0
  77. package/gsd-core/bin/lib/runtime-hooks-surface.cjs +215 -33
  78. package/gsd-core/bin/lib/runtime-name-policy.cjs +111 -1
  79. package/gsd-core/bin/lib/shell-command-projection.cjs +10 -6
  80. package/gsd-core/bin/lib/state-transition.cjs +39 -2
  81. package/gsd-core/bin/lib/state.cjs +42 -0
  82. package/gsd-core/bin/lib/surface.cjs +17 -1
  83. package/gsd-core/bin/lib/tdd-red-evidence.cjs +78 -5
  84. package/gsd-core/bin/lib/uat-predicate.cjs +47 -4
  85. package/gsd-core/bin/lib/uat.cjs +8 -0
  86. package/gsd-core/bin/lib/ui-consideration-probe.cjs +15 -2
  87. package/gsd-core/bin/lib/ui-frontend-evidence.cjs +100 -9
  88. package/gsd-core/bin/lib/undo-commit-selection.cjs +131 -0
  89. package/gsd-core/bin/lib/verification.cjs +268 -15
  90. package/gsd-core/bin/lib/verify-command-grounding.cjs +46 -2
  91. package/gsd-core/bin/lib/verify.cjs +132 -25
  92. package/gsd-core/bin/lib/worktree-base-ref.cjs +482 -73
  93. package/gsd-core/bin/lib/worktree-safety.cjs +784 -51
  94. package/gsd-core/bin/shared/config-defaults.manifest.json +3 -0
  95. package/gsd-core/bin/shared/config-schema.manifest.json +1 -0
  96. package/gsd-core/references/checkpoints.md +5 -3
  97. package/gsd-core/references/edge-probe-fixtures/01-round-half-even/expected-coverage.json +28 -3
  98. package/gsd-core/references/edge-probe-fixtures/02-merge-intervals/expected-coverage.json +37 -4
  99. package/gsd-core/references/edge-probe-fixtures/03-truncate-graphemes/expected-coverage.json +28 -3
  100. package/gsd-core/references/edge-probe-fixtures/04-money-rounding/expected-coverage.json +28 -3
  101. package/gsd-core/references/edge-probe-fixtures/05-list-dedupe/expected-coverage.json +37 -4
  102. package/gsd-core/references/edge-probe-fixtures/06-resolved-mixed/expected-coverage.json +37 -4
  103. package/gsd-core/references/edge-probe.md +195 -21
  104. package/gsd-core/references/execute-phase-between-wave-reset.md +7 -6
  105. package/gsd-core/references/execute-phase-wave-guard.md +22 -11
  106. package/gsd-core/references/gsd-run-resolver.md +1 -1
  107. package/gsd-core/references/model-profiles.md +1 -1
  108. package/gsd-core/references/phase-argument-parsing.md +9 -7
  109. package/gsd-core/references/phase-id-convention.md +28 -0
  110. package/gsd-core/references/planner-gap-closure.md +2 -0
  111. package/gsd-core/references/planner-load-graph-context.md +24 -13
  112. package/gsd-core/references/planner-verify-command-grounding.md +14 -0
  113. package/gsd-core/references/planning-config.md +11 -2
  114. package/gsd-core/references/tdd.md +27 -4
  115. package/gsd-core/references/ui-consideration-probe.md +10 -5
  116. package/gsd-core/references/verify-command-path-resolvability.md +10 -2
  117. package/gsd-core/references/worktree-path-safety.md +321 -0
  118. package/gsd-core/templates/verification-report.md +1 -1
  119. package/gsd-core/workflows/_runtime-launcher.snippet.sh +1 -1
  120. package/gsd-core/workflows/add-backlog.md +1 -1
  121. package/gsd-core/workflows/add-phase.md +1 -1
  122. package/gsd-core/workflows/add-tests.md +2 -2
  123. package/gsd-core/workflows/add-todo.md +3 -3
  124. package/gsd-core/workflows/ai-integration-phase.md +11 -3
  125. package/gsd-core/workflows/audit-fix.md +1 -1
  126. package/gsd-core/workflows/audit-milestone.md +1 -1
  127. package/gsd-core/workflows/audit-uat.md +1 -1
  128. package/gsd-core/workflows/autonomous/steps/converge-fail-fast.md +9 -18
  129. package/gsd-core/workflows/autonomous.md +16 -6
  130. package/gsd-core/workflows/check-todos.md +2 -2
  131. package/gsd-core/workflows/cleanup.md +2 -2
  132. package/gsd-core/workflows/code-review/steps/dispatch-fix.md +4 -3
  133. package/gsd-core/workflows/code-review/steps/structural-pre-pass.md +1 -1
  134. package/gsd-core/workflows/code-review-fix.md +108 -22
  135. package/gsd-core/workflows/code-review.md +63 -46
  136. package/gsd-core/workflows/complete-milestone/detail/elaboration.md +1 -1
  137. package/gsd-core/workflows/complete-milestone.md +2 -2
  138. package/gsd-core/workflows/debug.md +3 -3
  139. package/gsd-core/workflows/diagnose-issues.md +1 -1
  140. package/gsd-core/workflows/discuss-phase/modes/advisor.md +1 -1
  141. package/gsd-core/workflows/discuss-phase/modes/chain.md +1 -1
  142. package/gsd-core/workflows/discuss-phase-assumptions.md +1 -1
  143. package/gsd-core/workflows/discuss-phase.md +1 -1
  144. package/gsd-core/workflows/do.md +2 -2
  145. package/gsd-core/workflows/docs-update.md +3 -3
  146. package/gsd-core/workflows/edit-phase.md +1 -1
  147. package/gsd-core/workflows/eval-review.md +10 -3
  148. package/gsd-core/workflows/execute-phase/detail/elaboration.md +2 -2
  149. package/gsd-core/workflows/execute-phase/steps/code-review-disposition.md +1017 -0
  150. package/gsd-core/workflows/execute-phase/steps/codebase-drift-gate.md +1 -1
  151. package/gsd-core/workflows/execute-phase/steps/completion-reconciliation.md +3 -3
  152. package/gsd-core/workflows/execute-phase/steps/executor-isolation-dispatch.md +37 -3
  153. package/gsd-core/workflows/execute-phase/steps/gap-closure-artifacts.md +1 -1
  154. package/gsd-core/workflows/execute-phase/steps/partial-wave.md +1 -1
  155. package/gsd-core/workflows/execute-phase/steps/per-plan-executor-routing.md +1 -1
  156. package/gsd-core/workflows/execute-phase/steps/per-plan-worktree-gate.md +1 -1
  157. package/gsd-core/workflows/execute-phase/steps/post-merge-gate.md +46 -9
  158. package/gsd-core/workflows/execute-phase/steps/protected-branch.md +1 -1
  159. package/gsd-core/workflows/execute-phase/steps/ready-wave-gate.md +37 -0
  160. package/gsd-core/workflows/execute-phase/steps/regression-gate-run.md +1 -1
  161. package/gsd-core/workflows/execute-phase/steps/stale-reverification.md +24 -0
  162. package/gsd-core/workflows/execute-phase/steps/tdd-applicability-resolution.md +1 -1
  163. package/gsd-core/workflows/execute-phase/steps/threat-id-gate.md +28 -0
  164. package/gsd-core/workflows/execute-phase/steps/wave-post-gate-hooks.md +1 -1
  165. package/gsd-core/workflows/execute-phase/steps/worktree-base-check.md +25 -0
  166. package/gsd-core/workflows/execute-phase.md +36 -26
  167. package/gsd-core/workflows/execute-plan.md +5 -4
  168. package/gsd-core/workflows/explore.md +3 -3
  169. package/gsd-core/workflows/extract-learnings.md +2 -1
  170. package/gsd-core/workflows/fast.md +1 -1
  171. package/gsd-core/workflows/forensics.md +1 -1
  172. package/gsd-core/workflows/graduation.md +1 -1
  173. package/gsd-core/workflows/health.md +2 -2
  174. package/gsd-core/workflows/help/modes/full.compact.md +3 -3
  175. package/gsd-core/workflows/help/modes/full.md +5 -5
  176. package/gsd-core/workflows/help/modes/topic.md +15 -5
  177. package/gsd-core/workflows/import.md +2 -2
  178. package/gsd-core/workflows/inbox.md +2 -2
  179. package/gsd-core/workflows/ingest-docs.md +3 -3
  180. package/gsd-core/workflows/insert-phase.md +1 -1
  181. package/gsd-core/workflows/list-seeds.md +1 -1
  182. package/gsd-core/workflows/list-workspaces.md +1 -1
  183. package/gsd-core/workflows/manager.md +2 -2
  184. package/gsd-core/workflows/map-codebase.md +2 -2
  185. package/gsd-core/workflows/milestone-summary.md +1 -1
  186. package/gsd-core/workflows/mvp-phase.md +1 -1
  187. package/gsd-core/workflows/new-milestone.md +2 -2
  188. package/gsd-core/workflows/new-project/steps/auto-mode-config.md +3 -3
  189. package/gsd-core/workflows/new-project/steps/codebase-map-offer.md +1 -1
  190. package/gsd-core/workflows/new-project.md +7 -7
  191. package/gsd-core/workflows/new-workspace.md +2 -2
  192. package/gsd-core/workflows/next.md +1 -1
  193. package/gsd-core/workflows/note.md +1 -1
  194. package/gsd-core/workflows/onboard.md +1 -1
  195. package/gsd-core/workflows/pause-work.md +1 -1
  196. package/gsd-core/workflows/plan-phase/detail/elaboration.md +1 -1
  197. package/gsd-core/workflows/plan-phase/steps/chunked-planning-mode.md +17 -5
  198. package/gsd-core/workflows/plan-phase/steps/prd-express-path.md +1 -1
  199. package/gsd-core/workflows/plan-phase/steps/stall-detection-helpers.md +23 -5
  200. package/gsd-core/workflows/plan-phase.md +24 -7
  201. package/gsd-core/workflows/plan-review-convergence.md +21 -5
  202. package/gsd-core/workflows/plant-seed.md +62 -20
  203. package/gsd-core/workflows/pr-branch.md +113 -13
  204. package/gsd-core/workflows/profile-user.md +2 -2
  205. package/gsd-core/workflows/progress.md +1 -1
  206. package/gsd-core/workflows/quick/steps/plan-checker-loop.md +25 -0
  207. package/gsd-core/workflows/quick/steps/quick-verification.md +1 -1
  208. package/gsd-core/workflows/quick/steps/worktree-pre-dispatch-commit.md +1 -1
  209. package/gsd-core/workflows/quick-batch/steps/batch-init.md +1 -1
  210. package/gsd-core/workflows/quick-batch/steps/completion.md +1 -1
  211. package/gsd-core/workflows/quick-batch/steps/merge-wave.md +1 -1
  212. package/gsd-core/workflows/quick-batch/steps/planner-wave.md +1 -1
  213. package/gsd-core/workflows/quick-batch/steps/research-phase.md +1 -1
  214. package/gsd-core/workflows/quick-batch/steps/resume-mode.md +1 -1
  215. package/gsd-core/workflows/quick-batch/steps/verification-wave.md +1 -1
  216. package/gsd-core/workflows/quick-batch/steps/worktree-dispatch.md +1 -1
  217. package/gsd-core/workflows/quick-batch.md +1 -1
  218. package/gsd-core/workflows/quick.md +21 -9
  219. package/gsd-core/workflows/reapply-patches.md +9 -3
  220. package/gsd-core/workflows/remove-phase.md +1 -1
  221. package/gsd-core/workflows/remove-workspace.md +2 -2
  222. package/gsd-core/workflows/resume-project.md +1 -1
  223. package/gsd-core/workflows/review.md +31 -16
  224. package/gsd-core/workflows/scan.md +1 -1
  225. package/gsd-core/workflows/secure-phase.md +3 -2
  226. package/gsd-core/workflows/settings-advanced.md +30 -10
  227. package/gsd-core/workflows/settings-integrations.md +2 -3
  228. package/gsd-core/workflows/settings.md +4 -4
  229. package/gsd-core/workflows/ship.md +3 -2
  230. package/gsd-core/workflows/sketch-wrap-up.md +1 -1
  231. package/gsd-core/workflows/sketch.md +1 -1
  232. package/gsd-core/workflows/smart-entry.md +2 -2
  233. package/gsd-core/workflows/spec-phase.md +15 -5
  234. package/gsd-core/workflows/spike-wrap-up.md +1 -1
  235. package/gsd-core/workflows/spike.md +1 -1
  236. package/gsd-core/workflows/stats.md +1 -1
  237. package/gsd-core/workflows/sync-skills.md +5 -5
  238. package/gsd-core/workflows/thread.md +1 -1
  239. package/gsd-core/workflows/transition.md +1 -1
  240. package/gsd-core/workflows/ui-phase.md +44 -8
  241. package/gsd-core/workflows/ui-review.md +18 -4
  242. package/gsd-core/workflows/ultraplan-phase.md +1 -1
  243. package/gsd-core/workflows/undo.md +339 -20
  244. package/gsd-core/workflows/update.md +7 -7
  245. package/gsd-core/workflows/validate-phase.md +3 -2
  246. package/gsd-core/workflows/verify-work/steps/automated-ui-verification.md +1 -1
  247. package/gsd-core/workflows/verify-work/steps/mvp-uat-framing.md +1 -1
  248. package/gsd-core/workflows/verify-work.md +81 -16
  249. package/hooks/dist/gsd-agent-isolation-guard.js +24 -0
  250. package/hooks/dist/gsd-secret-read-guard.js +27 -1
  251. package/hooks/dist/gsd-statusline.js +70 -13
  252. package/hooks/dist/gsd-validate-commit.sh +63 -4
  253. package/hooks/gsd-agent-isolation-guard.js +24 -0
  254. package/hooks/gsd-secret-read-guard.js +27 -1
  255. package/hooks/gsd-statusline.js +70 -13
  256. package/hooks/gsd-validate-commit.sh +63 -4
  257. package/package.json +3 -2
  258. package/scripts/build-hooks.js +15 -6
  259. package/scripts/check-contract-drift.cjs +127 -11
  260. package/scripts/command-contract-helpers.cjs +3 -0
  261. package/scripts/docs-guard-registry.cjs +28 -0
  262. package/scripts/gen-loop-host-contract.cjs +69 -0
  263. package/scripts/lib/macos-conformance-tier.generated.cjs +14 -0
  264. package/scripts/lib/ndjson-reporter.cjs +3 -2
  265. package/scripts/lib/platform-conformance-tier.generated.cjs +11 -0
  266. package/scripts/lint-docs-guard-registration.exempt-baseline.cjs +28 -1
  267. package/scripts/lint-phase-arg-assignment.cjs +257 -0
  268. package/scripts/lint-phase-id-drift.cjs +290 -5
  269. package/scripts/lint-pr-branch-pattern-drift.cjs +148 -0
  270. package/scripts/lint-retired-runtime-name.cjs +619 -0
  271. package/scripts/lint-state-write-path-drift.cjs +93 -0
  272. package/scripts/lint-test-file-count.allowlist.json +28 -9
  273. package/scripts/lint-workflow-shellcheck-baseline.json +15 -0
  274. package/scripts/prompt-injection-scan.sh +4 -0
  275. package/scripts/release-tarball-smoke.cjs +194 -1
  276. package/skills/gsd-autonomous/SKILL.md +2 -2
  277. package/skills/gsd-capture/SKILL.md +1 -1
  278. package/skills/gsd-mempalace-capture/SKILL.md +7 -3
  279. package/skills/gsd-plan-review-convergence/SKILL.md +5 -5
  280. package/skills/gsd-progress/SKILL.md +1 -1
  281. package/skills/gsd-quick-batch/SKILL.md +1 -1
  282. package/skills/gsd-review/SKILL.md +2 -3
  283. package/vscode/package.json +1 -1
@@ -68,6 +68,9 @@
68
68
  "sub_repos": [],
69
69
  "granularity": "standard"
70
70
  },
71
+ "planner": {
72
+ "stall_detection_enabled": true
73
+ },
71
74
  "hooks": {
72
75
  "context_warnings": true,
73
76
  "workflow_guard": false
@@ -72,6 +72,7 @@
72
72
  "workflow.context_guard_mode",
73
73
  "executor.stall_detect_interval_minutes",
74
74
  "executor.stall_threshold_minutes",
75
+ "planner.stall_detection_enabled",
75
76
  "planner.stall_detect_interval_minutes",
76
77
  "planner.stall_threshold_minutes",
77
78
  "workflow.inline_plan_threshold",
@@ -8,14 +8,14 @@ Plans execute autonomously. Checkpoints formalize interaction points where human
8
8
  2. **Claude sets up the verification environment** - Start dev servers, seed databases, configure env vars
9
9
  3. **User only does what requires human judgment** - Visual checks, UX evaluation, "does this feel right?"
10
10
  4. **Secrets come from user, automation comes from Claude** - Ask for API keys, then Claude uses them via CLI
11
- 5. **Auto-mode bypasses verification/decision checkpoints** — When `workflow._auto_chain_active` or `workflow.auto_advance` is true in config: human-verify auto-approves, decision auto-selects first option, human-action still stops (auth gates cannot be automated)
11
+ 5. **Auto-mode bypasses verification checkpoints, and decision checkpoints with a declared `auto_select`** — When `workflow._auto_chain_active` or `workflow.auto_advance` is true in config: human-verify auto-approves; a `checkpoint:decision` carrying `auto_select="<option-id>"` auto-selects that named option; a `checkpoint:decision` with NO `auto_select` escalates to a human instead of guessing by position (#4095); human-action still stops (auth gates cannot be automated)
12
12
  6. **`gate="blocking-human"` is never auto-approved** — a checkpoint carrying this gate stops for a human in *every* mode, including auto-mode, regardless of its type. Rule 5 does not apply to it. The executor's precondition-unmet checkpoint (a task's `<precondition>` evaluated false — unmet `user_setup` step, missing env var, absent prior-phase artifact) reports this gate (#3210).
13
13
 
14
14
  **The `gate` attribute:**
15
15
 
16
16
  | Value | Auto-mode behavior | Use for |
17
17
  |-------|--------------------|---------|
18
- | `gate="blocking"` | Bypassed per rule 5 (human-verify auto-approves, decision auto-selects) | The default. Post-hoc verification and implementation choices that are safe to take the recommended path on when unattended. |
18
+ | `gate="blocking"` | Bypassed per rule 5 (human-verify auto-approves; decision auto-selects only when `auto_select` names an option, else escalates) | The default. Post-hoc verification and implementation choices that are safe to take the recommended path on when unattended. |
19
19
  | `gate="blocking-human"` | **Never bypassed.** Stops for a human in auto-mode too. | Irreversible or trust-establishing steps a human must actually see: package-legitimacy verification before install, any decision whose default answer would be wrong to assume, and unmet `<precondition>` facts the executor cannot establish on its own (#3210). |
20
20
 
21
21
  Reach for `gate="blocking-human"` whenever auto-approving the checkpoint would defeat its purpose. If the checkpoint exists because a human must *decide* something, `blocking` is the wrong gate — auto-mode will decide it for them.
@@ -147,7 +147,7 @@ HUMAN_VERIFY_MODE=$(gsd_run query config-get workflow.human_verify_mode --defaul
147
147
 
148
148
  **Structure:**
149
149
  ```xml
150
- <task type="checkpoint:decision" gate="blocking">
150
+ <task type="checkpoint:decision" gate="blocking" auto_select="option-a">
151
151
  <decision>[What's being decided]</decision>
152
152
  <context>[Why this decision matters]</context>
153
153
  <options>
@@ -166,6 +166,8 @@ HUMAN_VERIFY_MODE=$(gsd_run query config-get workflow.human_verify_mode --defaul
166
166
  </task>
167
167
  ```
168
168
 
169
+ `auto_select` is optional and names the `id` of the `<option>` auto-mode should pick when this checkpoint is reached unattended. Omit it and auto-mode escalates to a human instead of guessing from option order — the same treatment `gate="blocking-human"` already gets. An `auto_select` value that doesn't match any `<option id="…">` fails `verify plan-structure` at plan-parse time rather than silently falling back to the first option.
170
+
169
171
  **Example: Auth Provider Selection**
170
172
  ```xml
171
173
  <task type="checkpoint:decision" gate="blocking">
@@ -1,7 +1,32 @@
1
1
  {
2
2
  "items": [
3
- { "requirement_id": "R1", "category": "boundary", "status": "unresolved", "verification": null, "resolution": null, "reason": null, "probe": "What happens exactly at each min/max/threshold — and one step either side?" },
4
- { "requirement_id": "R1", "category": "precision", "status": "unresolved", "verification": null, "resolution": null, "reason": null, "probe": "Where can precision loss, overflow, or rounding/tie-breaking occur — and what is the exact contract (e.g. half-up vs half-to-even, ceil/floor/truncate)?" }
3
+ {
4
+ "requirement_id": "R1",
5
+ "category": "boundary",
6
+ "status": "unresolved",
7
+ "verification": null,
8
+ "resolution": null,
9
+ "reason": null,
10
+ "probe": "What happens exactly at each min/max/threshold — and one step either side?"
11
+ },
12
+ {
13
+ "requirement_id": "R1",
14
+ "category": "precision",
15
+ "status": "unresolved",
16
+ "verification": null,
17
+ "resolution": null,
18
+ "reason": null,
19
+ "probe": "Where can precision loss, overflow, or rounding/tie-breaking occur — and what is the exact contract (e.g. half-up vs half-to-even, ceil/floor/truncate)?"
20
+ }
5
21
  ],
6
- "coverage": { "applicable": 2, "resolved": 0, "unresolved": 2, "byVerification": { "explicit": 0, "backstop": 0 } }
22
+ "coverage": {
23
+ "applicable": 2,
24
+ "resolved": 0,
25
+ "unresolved": 2,
26
+ "unclassified": 0,
27
+ "byVerification": {
28
+ "explicit": 0,
29
+ "backstop": 0
30
+ }
31
+ }
7
32
  }
@@ -1,8 +1,41 @@
1
1
  {
2
2
  "items": [
3
- { "requirement_id": "R1", "category": "adjacency", "status": "unresolved", "verification": null, "resolution": null, "reason": null, "probe": "When two things are exactly equal or just touch, do they merge, collide, or separate?" },
4
- { "requirement_id": "R1", "category": "empty", "status": "unresolved", "verification": null, "resolution": null, "reason": null, "probe": "What is the result for empty, single-element, or null input?" },
5
- { "requirement_id": "R1", "category": "ordering", "status": "unresolved", "verification": null, "resolution": null, "reason": null, "probe": "When elements compare equal, is output order specified and stable?" }
3
+ {
4
+ "requirement_id": "R1",
5
+ "category": "adjacency",
6
+ "status": "unresolved",
7
+ "verification": null,
8
+ "resolution": null,
9
+ "reason": null,
10
+ "probe": "When two things are exactly equal or just touch, do they merge, collide, or separate?"
11
+ },
12
+ {
13
+ "requirement_id": "R1",
14
+ "category": "empty",
15
+ "status": "unresolved",
16
+ "verification": null,
17
+ "resolution": null,
18
+ "reason": null,
19
+ "probe": "What is the result for empty, single-element, or null input?"
20
+ },
21
+ {
22
+ "requirement_id": "R1",
23
+ "category": "ordering",
24
+ "status": "unresolved",
25
+ "verification": null,
26
+ "resolution": null,
27
+ "reason": null,
28
+ "probe": "When elements compare equal, is output order specified and stable?"
29
+ }
6
30
  ],
7
- "coverage": { "applicable": 3, "resolved": 0, "unresolved": 3, "byVerification": { "explicit": 0, "backstop": 0 } }
31
+ "coverage": {
32
+ "applicable": 3,
33
+ "resolved": 0,
34
+ "unresolved": 3,
35
+ "unclassified": 0,
36
+ "byVerification": {
37
+ "explicit": 0,
38
+ "backstop": 0
39
+ }
40
+ }
8
41
  }
@@ -1,7 +1,32 @@
1
1
  {
2
2
  "items": [
3
- { "requirement_id": "R1", "category": "empty", "status": "unresolved", "verification": null, "resolution": null, "reason": null, "probe": "What is the result for empty, single-element, or null input?" },
4
- { "requirement_id": "R1", "category": "encoding", "status": "unresolved", "verification": null, "resolution": null, "reason": null, "probe": "Whose definition of length/equality applies — bytes, code points, grapheme clusters, or normalized form?" }
3
+ {
4
+ "requirement_id": "R1",
5
+ "category": "empty",
6
+ "status": "unresolved",
7
+ "verification": null,
8
+ "resolution": null,
9
+ "reason": null,
10
+ "probe": "What is the result for empty, single-element, or null input?"
11
+ },
12
+ {
13
+ "requirement_id": "R1",
14
+ "category": "encoding",
15
+ "status": "unresolved",
16
+ "verification": null,
17
+ "resolution": null,
18
+ "reason": null,
19
+ "probe": "Whose definition of length/equality applies — bytes, code points, grapheme clusters, or normalized form?"
20
+ }
5
21
  ],
6
- "coverage": { "applicable": 2, "resolved": 0, "unresolved": 2, "byVerification": { "explicit": 0, "backstop": 0 } }
22
+ "coverage": {
23
+ "applicable": 2,
24
+ "resolved": 0,
25
+ "unresolved": 2,
26
+ "unclassified": 0,
27
+ "byVerification": {
28
+ "explicit": 0,
29
+ "backstop": 0
30
+ }
31
+ }
7
32
  }
@@ -1,7 +1,32 @@
1
1
  {
2
2
  "items": [
3
- { "requirement_id": "R1", "category": "boundary", "status": "unresolved", "verification": null, "resolution": null, "reason": null, "probe": "What happens exactly at each min/max/threshold — and one step either side?" },
4
- { "requirement_id": "R1", "category": "precision", "status": "unresolved", "verification": null, "resolution": null, "reason": null, "probe": "Where can precision loss, overflow, or rounding/tie-breaking occur — and what is the exact contract (e.g. half-up vs half-to-even, ceil/floor/truncate)?" }
3
+ {
4
+ "requirement_id": "R1",
5
+ "category": "boundary",
6
+ "status": "unresolved",
7
+ "verification": null,
8
+ "resolution": null,
9
+ "reason": null,
10
+ "probe": "What happens exactly at each min/max/threshold — and one step either side?"
11
+ },
12
+ {
13
+ "requirement_id": "R1",
14
+ "category": "precision",
15
+ "status": "unresolved",
16
+ "verification": null,
17
+ "resolution": null,
18
+ "reason": null,
19
+ "probe": "Where can precision loss, overflow, or rounding/tie-breaking occur — and what is the exact contract (e.g. half-up vs half-to-even, ceil/floor/truncate)?"
20
+ }
5
21
  ],
6
- "coverage": { "applicable": 2, "resolved": 0, "unresolved": 2, "byVerification": { "explicit": 0, "backstop": 0 } }
22
+ "coverage": {
23
+ "applicable": 2,
24
+ "resolved": 0,
25
+ "unresolved": 2,
26
+ "unclassified": 0,
27
+ "byVerification": {
28
+ "explicit": 0,
29
+ "backstop": 0
30
+ }
31
+ }
7
32
  }
@@ -1,8 +1,41 @@
1
1
  {
2
2
  "items": [
3
- { "requirement_id": "R1", "category": "adjacency", "status": "unresolved", "verification": null, "resolution": null, "reason": null, "probe": "When two things are exactly equal or just touch, do they merge, collide, or separate?" },
4
- { "requirement_id": "R1", "category": "empty", "status": "unresolved", "verification": null, "resolution": null, "reason": null, "probe": "What is the result for empty, single-element, or null input?" },
5
- { "requirement_id": "R1", "category": "ordering", "status": "unresolved", "verification": null, "resolution": null, "reason": null, "probe": "When elements compare equal, is output order specified and stable?" }
3
+ {
4
+ "requirement_id": "R1",
5
+ "category": "adjacency",
6
+ "status": "unresolved",
7
+ "verification": null,
8
+ "resolution": null,
9
+ "reason": null,
10
+ "probe": "When two things are exactly equal or just touch, do they merge, collide, or separate?"
11
+ },
12
+ {
13
+ "requirement_id": "R1",
14
+ "category": "empty",
15
+ "status": "unresolved",
16
+ "verification": null,
17
+ "resolution": null,
18
+ "reason": null,
19
+ "probe": "What is the result for empty, single-element, or null input?"
20
+ },
21
+ {
22
+ "requirement_id": "R1",
23
+ "category": "ordering",
24
+ "status": "unresolved",
25
+ "verification": null,
26
+ "resolution": null,
27
+ "reason": null,
28
+ "probe": "When elements compare equal, is output order specified and stable?"
29
+ }
6
30
  ],
7
- "coverage": { "applicable": 3, "resolved": 0, "unresolved": 3, "byVerification": { "explicit": 0, "backstop": 0 } }
31
+ "coverage": {
32
+ "applicable": 3,
33
+ "resolved": 0,
34
+ "unresolved": 3,
35
+ "unclassified": 0,
36
+ "byVerification": {
37
+ "explicit": 0,
38
+ "backstop": 0
39
+ }
40
+ }
8
41
  }
@@ -1,8 +1,41 @@
1
1
  {
2
2
  "items": [
3
- { "requirement_id": "R1", "category": "adjacency", "status": "resolved", "verification": "explicit", "resolution": "AC#6: touching intervals merge", "reason": null, "probe": "When two things are exactly equal or just touch, do they merge, collide, or separate?" },
4
- { "requirement_id": "R1", "category": "empty", "status": "unresolved", "verification": null, "resolution": null, "reason": null, "probe": "What is the result for empty, single-element, or null input?" },
5
- { "requirement_id": "R1", "category": "ordering", "status": "dismissed", "verification": null, "resolution": null, "reason": "output is canonically sorted; no tie possible", "probe": "When elements compare equal, is output order specified and stable?" }
3
+ {
4
+ "requirement_id": "R1",
5
+ "category": "adjacency",
6
+ "status": "resolved",
7
+ "verification": "explicit",
8
+ "resolution": "AC#6: touching intervals merge",
9
+ "reason": null,
10
+ "probe": "When two things are exactly equal or just touch, do they merge, collide, or separate?"
11
+ },
12
+ {
13
+ "requirement_id": "R1",
14
+ "category": "empty",
15
+ "status": "unresolved",
16
+ "verification": null,
17
+ "resolution": null,
18
+ "reason": null,
19
+ "probe": "What is the result for empty, single-element, or null input?"
20
+ },
21
+ {
22
+ "requirement_id": "R1",
23
+ "category": "ordering",
24
+ "status": "dismissed",
25
+ "verification": null,
26
+ "resolution": null,
27
+ "reason": "output is canonically sorted; no tie possible",
28
+ "probe": "When elements compare equal, is output order specified and stable?"
29
+ }
6
30
  ],
7
- "coverage": { "applicable": 3, "resolved": 2, "unresolved": 1, "byVerification": { "explicit": 1, "backstop": 0 } }
31
+ "coverage": {
32
+ "applicable": 3,
33
+ "resolved": 2,
34
+ "unresolved": 1,
35
+ "unclassified": 0,
36
+ "byVerification": {
37
+ "explicit": 1,
38
+ "backstop": 0
39
+ }
40
+ }
8
41
  }
@@ -169,11 +169,44 @@ resolutions supplied, every applicable edge is `unresolved`:
169
169
  ```json edge-probe:02-merge-intervals/expected-coverage.json
170
170
  {
171
171
  "items": [
172
- { "requirement_id": "R1", "category": "adjacency", "status": "unresolved", "verification": null, "resolution": null, "reason": null, "probe": "When two things are exactly equal or just touch, do they merge, collide, or separate?" },
173
- { "requirement_id": "R1", "category": "empty", "status": "unresolved", "verification": null, "resolution": null, "reason": null, "probe": "What is the result for empty, single-element, or null input?" },
174
- { "requirement_id": "R1", "category": "ordering", "status": "unresolved", "verification": null, "resolution": null, "reason": null, "probe": "When elements compare equal, is output order specified and stable?" }
172
+ {
173
+ "requirement_id": "R1",
174
+ "category": "adjacency",
175
+ "status": "unresolved",
176
+ "verification": null,
177
+ "resolution": null,
178
+ "reason": null,
179
+ "probe": "When two things are exactly equal or just touch, do they merge, collide, or separate?"
180
+ },
181
+ {
182
+ "requirement_id": "R1",
183
+ "category": "empty",
184
+ "status": "unresolved",
185
+ "verification": null,
186
+ "resolution": null,
187
+ "reason": null,
188
+ "probe": "What is the result for empty, single-element, or null input?"
189
+ },
190
+ {
191
+ "requirement_id": "R1",
192
+ "category": "ordering",
193
+ "status": "unresolved",
194
+ "verification": null,
195
+ "resolution": null,
196
+ "reason": null,
197
+ "probe": "When elements compare equal, is output order specified and stable?"
198
+ }
175
199
  ],
176
- "coverage": { "applicable": 3, "resolved": 0, "unresolved": 3, "byVerification": { "explicit": 0, "backstop": 0 } }
200
+ "coverage": {
201
+ "applicable": 3,
202
+ "resolved": 0,
203
+ "unresolved": 3,
204
+ "unclassified": 0,
205
+ "byVerification": {
206
+ "explicit": 0,
207
+ "backstop": 0
208
+ }
209
+ }
177
210
  }
178
211
  ```
179
212
 
@@ -192,10 +225,35 @@ rule, the requirement classifies as `numeric-range`, which raises `boundary` and
192
225
  ```json edge-probe:01-round-half-even/expected-coverage.json
193
226
  {
194
227
  "items": [
195
- { "requirement_id": "R1", "category": "boundary", "status": "unresolved", "verification": null, "resolution": null, "reason": null, "probe": "What happens exactly at each min/max/threshold — and one step either side?" },
196
- { "requirement_id": "R1", "category": "precision", "status": "unresolved", "verification": null, "resolution": null, "reason": null, "probe": "Where can precision loss, overflow, or rounding/tie-breaking occur — and what is the exact contract (e.g. half-up vs half-to-even, ceil/floor/truncate)?" }
228
+ {
229
+ "requirement_id": "R1",
230
+ "category": "boundary",
231
+ "status": "unresolved",
232
+ "verification": null,
233
+ "resolution": null,
234
+ "reason": null,
235
+ "probe": "What happens exactly at each min/max/threshold — and one step either side?"
236
+ },
237
+ {
238
+ "requirement_id": "R1",
239
+ "category": "precision",
240
+ "status": "unresolved",
241
+ "verification": null,
242
+ "resolution": null,
243
+ "reason": null,
244
+ "probe": "Where can precision loss, overflow, or rounding/tie-breaking occur — and what is the exact contract (e.g. half-up vs half-to-even, ceil/floor/truncate)?"
245
+ }
197
246
  ],
198
- "coverage": { "applicable": 2, "resolved": 0, "unresolved": 2, "byVerification": { "explicit": 0, "backstop": 0 } }
247
+ "coverage": {
248
+ "applicable": 2,
249
+ "resolved": 0,
250
+ "unresolved": 2,
251
+ "unclassified": 0,
252
+ "byVerification": {
253
+ "explicit": 0,
254
+ "backstop": 0
255
+ }
256
+ }
199
257
  }
200
258
  ```
201
259
 
@@ -211,10 +269,35 @@ the requirement classifies as `text`, which raises `empty` and `encoding`:
211
269
  ```json edge-probe:03-truncate-graphemes/expected-coverage.json
212
270
  {
213
271
  "items": [
214
- { "requirement_id": "R1", "category": "empty", "status": "unresolved", "verification": null, "resolution": null, "reason": null, "probe": "What is the result for empty, single-element, or null input?" },
215
- { "requirement_id": "R1", "category": "encoding", "status": "unresolved", "verification": null, "resolution": null, "reason": null, "probe": "Whose definition of length/equality applies — bytes, code points, grapheme clusters, or normalized form?" }
272
+ {
273
+ "requirement_id": "R1",
274
+ "category": "empty",
275
+ "status": "unresolved",
276
+ "verification": null,
277
+ "resolution": null,
278
+ "reason": null,
279
+ "probe": "What is the result for empty, single-element, or null input?"
280
+ },
281
+ {
282
+ "requirement_id": "R1",
283
+ "category": "encoding",
284
+ "status": "unresolved",
285
+ "verification": null,
286
+ "resolution": null,
287
+ "reason": null,
288
+ "probe": "Whose definition of length/equality applies — bytes, code points, grapheme clusters, or normalized form?"
289
+ }
216
290
  ],
217
- "coverage": { "applicable": 2, "resolved": 0, "unresolved": 2, "byVerification": { "explicit": 0, "backstop": 0 } }
291
+ "coverage": {
292
+ "applicable": 2,
293
+ "resolved": 0,
294
+ "unresolved": 2,
295
+ "unclassified": 0,
296
+ "byVerification": {
297
+ "explicit": 0,
298
+ "backstop": 0
299
+ }
300
+ }
218
301
  }
219
302
  ```
220
303
 
@@ -231,10 +314,35 @@ classifies as `numeric-range`, which raises `boundary` and `precision`:
231
314
  ```json edge-probe:04-money-rounding/expected-coverage.json
232
315
  {
233
316
  "items": [
234
- { "requirement_id": "R1", "category": "boundary", "status": "unresolved", "verification": null, "resolution": null, "reason": null, "probe": "What happens exactly at each min/max/threshold — and one step either side?" },
235
- { "requirement_id": "R1", "category": "precision", "status": "unresolved", "verification": null, "resolution": null, "reason": null, "probe": "Where can precision loss, overflow, or rounding/tie-breaking occur — and what is the exact contract (e.g. half-up vs half-to-even, ceil/floor/truncate)?" }
317
+ {
318
+ "requirement_id": "R1",
319
+ "category": "boundary",
320
+ "status": "unresolved",
321
+ "verification": null,
322
+ "resolution": null,
323
+ "reason": null,
324
+ "probe": "What happens exactly at each min/max/threshold — and one step either side?"
325
+ },
326
+ {
327
+ "requirement_id": "R1",
328
+ "category": "precision",
329
+ "status": "unresolved",
330
+ "verification": null,
331
+ "resolution": null,
332
+ "reason": null,
333
+ "probe": "Where can precision loss, overflow, or rounding/tie-breaking occur — and what is the exact contract (e.g. half-up vs half-to-even, ceil/floor/truncate)?"
334
+ }
236
335
  ],
237
- "coverage": { "applicable": 2, "resolved": 0, "unresolved": 2, "byVerification": { "explicit": 0, "backstop": 0 } }
336
+ "coverage": {
337
+ "applicable": 2,
338
+ "resolved": 0,
339
+ "unresolved": 2,
340
+ "unclassified": 0,
341
+ "byVerification": {
342
+ "explicit": 0,
343
+ "backstop": 0
344
+ }
345
+ }
238
346
  }
239
347
  ```
240
348
 
@@ -250,11 +358,44 @@ Given a requirement to deduplicate a list of items, the requirement classifies a
250
358
  ```json edge-probe:05-list-dedupe/expected-coverage.json
251
359
  {
252
360
  "items": [
253
- { "requirement_id": "R1", "category": "adjacency", "status": "unresolved", "verification": null, "resolution": null, "reason": null, "probe": "When two things are exactly equal or just touch, do they merge, collide, or separate?" },
254
- { "requirement_id": "R1", "category": "empty", "status": "unresolved", "verification": null, "resolution": null, "reason": null, "probe": "What is the result for empty, single-element, or null input?" },
255
- { "requirement_id": "R1", "category": "ordering", "status": "unresolved", "verification": null, "resolution": null, "reason": null, "probe": "When elements compare equal, is output order specified and stable?" }
361
+ {
362
+ "requirement_id": "R1",
363
+ "category": "adjacency",
364
+ "status": "unresolved",
365
+ "verification": null,
366
+ "resolution": null,
367
+ "reason": null,
368
+ "probe": "When two things are exactly equal or just touch, do they merge, collide, or separate?"
369
+ },
370
+ {
371
+ "requirement_id": "R1",
372
+ "category": "empty",
373
+ "status": "unresolved",
374
+ "verification": null,
375
+ "resolution": null,
376
+ "reason": null,
377
+ "probe": "What is the result for empty, single-element, or null input?"
378
+ },
379
+ {
380
+ "requirement_id": "R1",
381
+ "category": "ordering",
382
+ "status": "unresolved",
383
+ "verification": null,
384
+ "resolution": null,
385
+ "reason": null,
386
+ "probe": "When elements compare equal, is output order specified and stable?"
387
+ }
256
388
  ],
257
- "coverage": { "applicable": 3, "resolved": 0, "unresolved": 3, "byVerification": { "explicit": 0, "backstop": 0 } }
389
+ "coverage": {
390
+ "applicable": 3,
391
+ "resolved": 0,
392
+ "unresolved": 3,
393
+ "unclassified": 0,
394
+ "byVerification": {
395
+ "explicit": 0,
396
+ "backstop": 0
397
+ }
398
+ }
258
399
  }
259
400
  ```
260
401
 
@@ -270,11 +411,44 @@ left unresolved:
270
411
  ```json edge-probe:06-resolved-mixed/expected-coverage.json
271
412
  {
272
413
  "items": [
273
- { "requirement_id": "R1", "category": "adjacency", "status": "resolved", "verification": "explicit", "resolution": "AC#6: touching intervals merge", "reason": null, "probe": "When two things are exactly equal or just touch, do they merge, collide, or separate?" },
274
- { "requirement_id": "R1", "category": "empty", "status": "unresolved", "verification": null, "resolution": null, "reason": null, "probe": "What is the result for empty, single-element, or null input?" },
275
- { "requirement_id": "R1", "category": "ordering", "status": "dismissed", "verification": null, "resolution": null, "reason": "output is canonically sorted; no tie possible", "probe": "When elements compare equal, is output order specified and stable?" }
414
+ {
415
+ "requirement_id": "R1",
416
+ "category": "adjacency",
417
+ "status": "resolved",
418
+ "verification": "explicit",
419
+ "resolution": "AC#6: touching intervals merge",
420
+ "reason": null,
421
+ "probe": "When two things are exactly equal or just touch, do they merge, collide, or separate?"
422
+ },
423
+ {
424
+ "requirement_id": "R1",
425
+ "category": "empty",
426
+ "status": "unresolved",
427
+ "verification": null,
428
+ "resolution": null,
429
+ "reason": null,
430
+ "probe": "What is the result for empty, single-element, or null input?"
431
+ },
432
+ {
433
+ "requirement_id": "R1",
434
+ "category": "ordering",
435
+ "status": "dismissed",
436
+ "verification": null,
437
+ "resolution": null,
438
+ "reason": "output is canonically sorted; no tie possible",
439
+ "probe": "When elements compare equal, is output order specified and stable?"
440
+ }
276
441
  ],
277
- "coverage": { "applicable": 3, "resolved": 2, "unresolved": 1, "byVerification": { "explicit": 1, "backstop": 0 } }
442
+ "coverage": {
443
+ "applicable": 3,
444
+ "resolved": 2,
445
+ "unresolved": 1,
446
+ "unclassified": 0,
447
+ "byVerification": {
448
+ "explicit": 1,
449
+ "backstop": 0
450
+ }
451
+ }
278
452
  }
279
453
  ```
280
454
 
@@ -24,12 +24,13 @@
24
24
  # Unset per-wave manifest so wave N+1 creates a fresh one (#3384, #1369).
25
25
  unset WAVE_WORKTREE_MANIFEST
26
26
 
27
- # Between-wave base re-check (#1369, #3659): after wave N merges and tracking commits,
28
- # HEAD has advanced. Re-asserting worktree.baseRef:"head" is deliberately NOT done here —
29
- # the runtime harness does not read project-settings baseRef (#48), so in
30
- # harness-worktree mode the setting cannot influence the fork base. The safety re-check
31
- # below compares HEAD against the REAL fork base and degrades the remaining waves
32
- # whenever they diverge, avoiding the base-mismatch FATAL in executor agents.
27
+ # Between-wave base re-check (#1369, #3659, #4588): after wave N merges and tracking
28
+ # commits, HEAD has advanced. Re-asserting worktree.baseRef:"head" is NOT done here — the
29
+ # setting is either already in place (honored by GSD-created worktrees and by the Claude
30
+ # Code harness, #4588) or
31
+ # deliberately absent; a re-write would not change the fork base. The safety re-check
32
+ # below compares HEAD against the fork base and degrades the remaining waves whenever
33
+ # they diverge, avoiding the base-mismatch FATAL in executor agents.
33
34
  if [ "$ISOLATION" = "harness-worktree" ] && [ "$USE_WORKTREES" != "false" ]; then
34
35
  _BETWEEN_DEGRADE=$(gsd_run query worktree.base-check --mode "$ISOLATION" --pick shouldDegrade 2>/dev/null || echo "false")
35
36
  if [ "$_BETWEEN_DEGRADE" = "true" ]; then
@@ -1,10 +1,10 @@
1
1
  0.5. **Inter-wave worktree base re-check (wave N+1 guard — #1369):**
2
2
 
3
3
  After Wave N merges and tracking commits advance orchestrator HEAD, Claude Code's
4
- `isolation="worktree"` still forks new worktrees from `origin/HEAD` (the "fresh" base),
5
- not the live HEAD. This means Wave N+1 worktrees would be created from the stale
6
- pre-Wave-N base, causing the `worktree_branch_check` guard inside each executor to halt
7
- immediately with a base-mismatch fatal.
4
+ `isolation="worktree"` forks new worktrees from `origin/HEAD` (the "fresh" base) unless
5
+ `worktree.baseRef:"head"` is set — not the live HEAD. Without the setting, Wave N+1
6
+ worktrees would be created from the stale pre-Wave-N base, causing the
7
+ `worktree_branch_check` guard inside each executor to halt with a base-mismatch fatal.
8
8
 
9
9
  **Run this check at the start of every wave when `USE_WORKTREES != "false"` and
10
10
  `ISOLATION = "harness-worktree"`** (#2652 — the harness caches the fork base, so this is a
@@ -30,10 +30,21 @@
30
30
  this check and may re-enable worktree isolation once `origin/HEAD` matches HEAD again
31
31
  (e.g. via `git fetch` or a push that advances it).
32
32
 
33
- **Why `worktree.baseRef:"head"` does not avoid this degrade (#48, #3659):** the runtime
34
- harness does not read project-settings `baseRef` — an isolated dispatch always forks from
35
- `origin/HEAD` regardless of the setting, so the check compares against the real fork base
36
- and degrades whenever HEAD has diverged. Parallel worktrees return once HEAD is
37
- merged/pushed so `origin/HEAD` matches it. The setting still restores parallel execution
38
- on runtimes where GSD itself creates the worktrees (orchestrator-managed isolation:
39
- Codex, OpenCode, Kimi, Kimi Code). See #683 for the base-ref configuration detail.
33
+ **How `worktree.baseRef:"head"` interacts with this degrade (#3659, #4588):** with the
34
+ setting in place the check trusts it and does not compare — the worktree creator forks from the
35
+ orchestrator HEAD (GSD's own `git worktree add` by construction; the Claude Code harness as
36
+ measured from all three settings layers, #4588; Cursor unmeasured), so outside the two
37
+ exceptions below this guard only fires when the setting
38
+ is absent and HEAD has diverged from `origin/HEAD`. Parallel worktrees then return once HEAD
39
+ is merged/pushed so `origin/HEAD` matches it, or once the setting is applied. The exceptions
40
+ (#4588): a supplied `--observed-fork-base` is compared against HEAD instead of trusted, in
41
+ both modes; and on a harness-created run with no observation, a Claude Code `WorktreeCreate`
42
+ hook in any of those settings files — or one of them that does not parse, so a hook cannot be
43
+ ruled out — withholds the trust: the hook creates the worktree without applying the setting,
44
+ so the check compares against `origin/HEAD` anyway and a mismatch degrades with
45
+ `baseref-head-bypassed-by-hook`. The #4868 prior-worktree observation does not lift that
46
+ degrade: a worktree at HEAD records nothing about which creator left it there, so one the
47
+ plain harness created before the hook was configured reads the same as one the hook created
48
+ (#4881). On a hook host only `--observed-fork-base` restores a trusted verdict. The exit-42
49
+ guard in each executor remains the backstop on a host that does not honor the setting.
50
+ See #683 for the base-ref configuration detail.