@opengsd/gsd-core 1.7.0 → 1.9.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 (261) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/.opencode/plugins/gsd-core.js +45 -1
  4. package/README.md +2 -0
  5. package/agents/gsd-code-fixer.md +1 -1
  6. package/agents/gsd-codebase-mapper.md +1 -1
  7. package/agents/gsd-debug-session-manager.md +78 -4
  8. package/agents/gsd-debugger.md +87 -29
  9. package/agents/gsd-executor.md +49 -9
  10. package/agents/gsd-intel-updater.md +3 -3
  11. package/agents/gsd-phase-researcher.md +4 -2
  12. package/agents/gsd-plan-checker.md +20 -0
  13. package/agents/gsd-planner.md +44 -59
  14. package/agents/gsd-project-researcher.md +2 -2
  15. package/agents/gsd-ui-auditor.md +0 -40
  16. package/agents/gsd-verifier.md +2 -2
  17. package/bin/install.js +1338 -135
  18. package/commands/gsd/ai-integration-phase.md +1 -1
  19. package/commands/gsd/mempalace-capture.md +9 -5
  20. package/commands/gsd/new-milestone.md +1 -1
  21. package/commands/gsd/plan-phase.md +5 -3
  22. package/commands/gsd/plan-review-convergence.md +7 -2
  23. package/gsd-core/bin/gsd-tools.cjs +2690 -2472
  24. package/gsd-core/bin/lib/adapter-imperative.cjs +8 -1
  25. package/gsd-core/bin/lib/agent-command-router.cjs +20 -5
  26. package/gsd-core/bin/lib/api-coverage.cjs +360 -53
  27. package/gsd-core/bin/lib/audit.cjs +8 -8
  28. package/gsd-core/bin/lib/broken-windows.cjs +716 -0
  29. package/gsd-core/bin/lib/capability-command-router.cjs +733 -0
  30. package/gsd-core/bin/lib/capability-consent.cjs +40 -1
  31. package/gsd-core/bin/lib/capability-lifecycle.cjs +58 -0
  32. package/gsd-core/bin/lib/capability-loader.cjs +23 -1
  33. package/gsd-core/bin/lib/capability-registry.cjs +1450 -160
  34. package/gsd-core/bin/lib/capability-trust.cjs +468 -33
  35. package/gsd-core/bin/lib/capability-validator.cjs +882 -6
  36. package/gsd-core/bin/lib/capability-writer.cjs +6 -1
  37. package/gsd-core/bin/lib/check-command-router.cjs +140 -27
  38. package/gsd-core/bin/lib/cjs-command-router-adapter.cjs +15 -0
  39. package/gsd-core/bin/lib/claude-orchestration-command-router.cjs +209 -31
  40. package/gsd-core/bin/lib/claude-orchestration.cjs +203 -25
  41. package/gsd-core/bin/lib/command-aliases.cjs +14 -0
  42. package/gsd-core/bin/lib/commands.cjs +326 -21
  43. package/gsd-core/bin/lib/config-loader.cjs +214 -30
  44. package/gsd-core/bin/lib/config.cjs +158 -22
  45. package/gsd-core/bin/lib/core-utils.cjs +6 -1
  46. package/gsd-core/bin/lib/decisions.cjs +32 -8
  47. package/gsd-core/bin/lib/docs.cjs +6 -0
  48. package/gsd-core/bin/lib/estimate-cli.cjs +336 -0
  49. package/gsd-core/bin/lib/external-descriptor-trust.cjs +14 -2
  50. package/gsd-core/bin/lib/frontmatter.cjs +125 -15
  51. package/gsd-core/bin/lib/gap-checker.cjs +17 -2
  52. package/gsd-core/bin/lib/host-integration.cjs +215 -8
  53. package/gsd-core/bin/lib/init.cjs +155 -66
  54. package/gsd-core/bin/lib/install-engine.cjs +299 -23
  55. package/gsd-core/bin/lib/install-profiles.cjs +239 -1
  56. package/gsd-core/bin/lib/installer-migrations/005-opencode-baseline-commands-dir.cjs +146 -0
  57. package/gsd-core/bin/lib/installer-migrations/006-pi-extension-cjs-to-js.cjs +91 -0
  58. package/gsd-core/bin/lib/installer-migrations.cjs +44 -5
  59. package/gsd-core/bin/lib/markdown-sectionizer.cjs +107 -0
  60. package/gsd-core/bin/lib/milestone.cjs +248 -14
  61. package/gsd-core/bin/lib/model-catalog.cjs +69 -4
  62. package/gsd-core/bin/lib/model-resolver.cjs +189 -7
  63. package/gsd-core/bin/lib/observability/logger.cjs +7 -2
  64. package/gsd-core/bin/lib/onboard-projection.cjs +11 -8
  65. package/gsd-core/bin/lib/phase-command-router.cjs +10 -1
  66. package/gsd-core/bin/lib/phase-estimation.cjs +398 -0
  67. package/gsd-core/bin/lib/phase-id.cjs +304 -9
  68. package/gsd-core/bin/lib/phase.cjs +258 -17
  69. package/gsd-core/bin/lib/plan-drift-guard.cjs +1 -1
  70. package/gsd-core/bin/lib/plan-scan.cjs +70 -2
  71. package/gsd-core/bin/lib/planning-workspace.cjs +9 -2
  72. package/gsd-core/bin/lib/profile-output.cjs +34 -8
  73. package/gsd-core/bin/lib/review-lane-descriptor.cjs +927 -0
  74. package/gsd-core/bin/lib/review-lane-invocation.cjs +348 -0
  75. package/gsd-core/bin/lib/review-lane-runner.cjs +594 -0
  76. package/gsd-core/bin/lib/review-reviewer-selection.cjs +114 -32
  77. package/gsd-core/bin/lib/roadmap-parser.cjs +61 -10
  78. package/gsd-core/bin/lib/roadmap.cjs +23 -7
  79. package/gsd-core/bin/lib/runtime-artifact-conversion.cjs +38 -5
  80. package/gsd-core/bin/lib/runtime-artifact-layout.cjs +23 -9
  81. package/gsd-core/bin/lib/runtime-hooks-surface.cjs +156 -0
  82. package/gsd-core/bin/lib/runtime-name-policy.cjs +15 -2
  83. package/gsd-core/bin/lib/smart-entry.cjs +70 -5
  84. package/gsd-core/bin/lib/state-document.cjs +171 -24
  85. package/gsd-core/bin/lib/state-transition.cjs +50 -11
  86. package/gsd-core/bin/lib/state.cjs +206 -32
  87. package/gsd-core/bin/lib/surface.cjs +51 -9
  88. package/gsd-core/bin/lib/uat-predicate.cjs +6 -4
  89. package/gsd-core/bin/lib/uat.cjs +428 -11
  90. package/gsd-core/bin/lib/ui-consideration-probe.cjs +2 -2
  91. package/gsd-core/bin/lib/unusable-input.cjs +216 -0
  92. package/gsd-core/bin/lib/validate.cjs +44 -8
  93. package/gsd-core/bin/lib/verification.cjs +163 -31
  94. package/gsd-core/bin/lib/verify.cjs +348 -42
  95. package/gsd-core/bin/lib/worktree-safety.cjs +360 -15
  96. package/gsd-core/bin/shared/config-defaults.manifest.json +1 -0
  97. package/gsd-core/bin/shared/config-schema.manifest.json +4 -15
  98. package/gsd-core/bin/shared/model-catalog.json +5 -0
  99. package/gsd-core/bin/shared/runtime-aliases.manifest.json +5 -0
  100. package/gsd-core/references/api-coverage.md +37 -7
  101. package/gsd-core/references/checkpoints.md +1 -1
  102. package/gsd-core/references/common-bug-patterns.md +13 -0
  103. package/gsd-core/references/context-budget.md +40 -0
  104. package/gsd-core/references/debugger-bug-taxonomy.md +111 -0
  105. package/gsd-core/references/debugger-fix-acceptance.md +157 -0
  106. package/gsd-core/references/debugger-philosophy.md +1 -0
  107. package/gsd-core/references/debugger-prevention.md +98 -0
  108. package/gsd-core/references/debugger-rca-branching.md +98 -0
  109. package/gsd-core/references/debugger-repro-hardening.md +130 -0
  110. package/gsd-core/references/debugger-sbfl.md +110 -0
  111. package/gsd-core/references/debugger-semantic-recall.md +81 -0
  112. package/gsd-core/references/execute-phase-quota-recovery.md +55 -0
  113. package/gsd-core/references/execute-phase-requirement-revert.md +8 -0
  114. package/gsd-core/references/execute-phase-response-language.md +7 -0
  115. package/gsd-core/references/gate-prompts.md +6 -3
  116. package/gsd-core/references/model-profile-resolution.md +64 -13
  117. package/gsd-core/references/offer-next.md +88 -0
  118. package/gsd-core/references/planner-antipatterns.md +6 -0
  119. package/gsd-core/references/planner-mvp-mode.md +12 -13
  120. package/gsd-core/references/planner-preconditions.md +156 -0
  121. package/gsd-core/references/planner-reversibility.md +132 -0
  122. package/gsd-core/references/planning-config.md +2 -1
  123. package/gsd-core/references/reviewer-instances.md +28 -19
  124. package/gsd-core/references/runtime-aware-dispatch.md +42 -0
  125. package/gsd-core/references/skeleton-template.md +1 -1
  126. package/gsd-core/references/thinking-models-planning.md +3 -1
  127. package/gsd-core/references/ui-consideration-probe.md +2 -2
  128. package/gsd-core/references/worktree-branch-check.md +4 -4
  129. package/gsd-core/templates/DEBUG.md +5 -3
  130. package/gsd-core/templates/summary-minimal.md +4 -0
  131. package/gsd-core/templates/summary-standard.md +4 -0
  132. package/gsd-core/templates/summary.md +7 -0
  133. package/gsd-core/workflows/add-phase.md +2 -0
  134. package/gsd-core/workflows/add-tests.md +3 -1
  135. package/gsd-core/workflows/add-todo.md +32 -1
  136. package/gsd-core/workflows/ai-integration-phase.md +8 -6
  137. package/gsd-core/workflows/audit-fix.md +6 -2
  138. package/gsd-core/workflows/audit-milestone.md +8 -0
  139. package/gsd-core/workflows/autonomous.md +19 -15
  140. package/gsd-core/workflows/check-todos.md +5 -3
  141. package/gsd-core/workflows/cleanup.md +7 -1
  142. package/gsd-core/workflows/code-review-fix.md +14 -6
  143. package/gsd-core/workflows/code-review.md +93 -24
  144. package/gsd-core/workflows/complete-milestone.md +3 -0
  145. package/gsd-core/workflows/debug.md +35 -7
  146. package/gsd-core/workflows/diagnose-issues.md +5 -1
  147. package/gsd-core/workflows/discovery-phase.md +7 -0
  148. package/gsd-core/workflows/discuss-phase/modes/advisor.md +2 -4
  149. package/gsd-core/workflows/discuss-phase/modes/auto.md +0 -6
  150. package/gsd-core/workflows/discuss-phase/templates/context.md +16 -2
  151. package/gsd-core/workflows/discuss-phase-assumptions.md +18 -9
  152. package/gsd-core/workflows/discuss-phase.md +2 -2
  153. package/gsd-core/workflows/do.md +7 -1
  154. package/gsd-core/workflows/docs-update.md +9 -0
  155. package/gsd-core/workflows/eval-review.md +4 -1
  156. package/gsd-core/workflows/execute-phase/steps/codebase-drift-gate.md +4 -0
  157. package/gsd-core/workflows/execute-phase/steps/executor-isolation-dispatch.md +160 -0
  158. package/gsd-core/workflows/execute-phase/steps/post-merge-gate.md +4 -4
  159. package/gsd-core/workflows/execute-phase/steps/regression-gate.md +2 -2
  160. package/gsd-core/workflows/execute-phase.md +110 -149
  161. package/gsd-core/workflows/execute-plan.md +20 -8
  162. package/gsd-core/workflows/explore.md +4 -0
  163. package/gsd-core/workflows/extract-learnings.md +21 -0
  164. package/gsd-core/workflows/graduation.md +3 -0
  165. package/gsd-core/workflows/health.md +7 -1
  166. package/gsd-core/workflows/help/modes/full.md +9 -5
  167. package/gsd-core/workflows/import.md +11 -2
  168. package/gsd-core/workflows/inbox.md +7 -0
  169. package/gsd-core/workflows/ingest-docs.md +19 -10
  170. package/gsd-core/workflows/manager.md +3 -1
  171. package/gsd-core/workflows/map-codebase.md +17 -10
  172. package/gsd-core/workflows/mvp-phase.md +3 -0
  173. package/gsd-core/workflows/new-milestone.md +79 -23
  174. package/gsd-core/workflows/new-project.md +28 -19
  175. package/gsd-core/workflows/new-workspace.md +3 -1
  176. package/gsd-core/workflows/next.md +5 -2
  177. package/gsd-core/workflows/onboard.md +3 -0
  178. package/gsd-core/workflows/plan-phase.md +56 -51
  179. package/gsd-core/workflows/plan-review-convergence.md +61 -12
  180. package/gsd-core/workflows/plant-seed.md +3 -0
  181. package/gsd-core/workflows/profile-user.md +7 -1
  182. package/gsd-core/workflows/progress.md +31 -3
  183. package/gsd-core/workflows/quick.md +33 -10
  184. package/gsd-core/workflows/remove-workspace.md +3 -0
  185. package/gsd-core/workflows/review.md +172 -585
  186. package/gsd-core/workflows/scan.md +10 -2
  187. package/gsd-core/workflows/secure-phase.md +13 -2
  188. package/gsd-core/workflows/settings-integrations.md +3 -0
  189. package/gsd-core/workflows/settings.md +3 -0
  190. package/gsd-core/workflows/ship.md +88 -11
  191. package/gsd-core/workflows/sketch.md +3 -0
  192. package/gsd-core/workflows/smart-entry.md +4 -1
  193. package/gsd-core/workflows/spike.md +7 -1
  194. package/gsd-core/workflows/ui-phase.md +11 -2
  195. package/gsd-core/workflows/ui-review.md +11 -1
  196. package/gsd-core/workflows/undo.md +7 -0
  197. package/gsd-core/workflows/update.md +106 -5
  198. package/gsd-core/workflows/validate-phase.md +13 -2
  199. package/gsd-core/workflows/verify-phase.md +2 -2
  200. package/gsd-core/workflows/verify-work.md +15 -4
  201. package/hooks/dist/gsd-context-monitor.js +27 -9
  202. package/hooks/dist/gsd-cursor-session-start.js +6 -2
  203. package/hooks/dist/gsd-cursor-stop.js +6 -2
  204. package/hooks/dist/gsd-cursor-subagent-start.js +6 -2
  205. package/hooks/dist/gsd-graphify-update.sh +9 -0
  206. package/hooks/dist/gsd-phase-boundary.sh +14 -2
  207. package/hooks/dist/gsd-prompt-guard.js +101 -2
  208. package/hooks/dist/gsd-read-guard.js +100 -2
  209. package/hooks/dist/gsd-read-injection-scanner.js +109 -2
  210. package/hooks/dist/gsd-statusline.js +97 -9
  211. package/hooks/dist/gsd-workflow-guard.js +110 -6
  212. package/hooks/dist/gsd-worktree-path-guard.js +132 -8
  213. package/hooks/dist/lib/cursor-workspace.js +74 -0
  214. package/hooks/gsd-context-monitor.js +27 -9
  215. package/hooks/gsd-cursor-session-start.js +6 -2
  216. package/hooks/gsd-cursor-stop.js +6 -2
  217. package/hooks/gsd-cursor-subagent-start.js +6 -2
  218. package/hooks/gsd-graphify-update.sh +9 -0
  219. package/hooks/gsd-phase-boundary.sh +14 -2
  220. package/hooks/gsd-prompt-guard.js +101 -2
  221. package/hooks/gsd-read-guard.js +100 -2
  222. package/hooks/gsd-read-injection-scanner.js +109 -2
  223. package/hooks/gsd-statusline.js +97 -9
  224. package/hooks/gsd-workflow-guard.js +110 -6
  225. package/hooks/gsd-worktree-path-guard.js +132 -8
  226. package/hooks/lib/cursor-workspace.js +74 -0
  227. package/package.json +10 -8
  228. package/pi/gsd.cjs +34 -3
  229. package/scripts/changeset/lint.cjs +1 -0
  230. package/scripts/changeset/parse.cjs +26 -0
  231. package/scripts/check-coverage-gate.cjs +51 -0
  232. package/scripts/check-glossary-refs.cjs +244 -0
  233. package/scripts/ci-rebase-check.cjs +48 -4
  234. package/scripts/ci-test-scope.cjs +67 -17
  235. package/scripts/gen-adr-index.cjs +528 -0
  236. package/scripts/gen-capability-matrix.cjs +26 -2
  237. package/scripts/gen-capability-registry.cjs +132 -34
  238. package/scripts/gen-emitted-baseline.cjs +145 -0
  239. package/scripts/gen-test-timings.cjs +201 -0
  240. package/scripts/lint-compiled-artifact-sync.cjs +146 -0
  241. package/scripts/lint-emitted-drift-ack.cjs +149 -0
  242. package/scripts/lint-fix-has-regression-test.cjs +131 -0
  243. package/scripts/lint-portable-timeout.cjs +140 -0
  244. package/scripts/lint-resolution-provenance.cjs +9 -0
  245. package/scripts/lint-test-file-count.allowlist.json +1 -0
  246. package/scripts/mutation-matrix.cjs +4 -0
  247. package/scripts/prompt-injection-scan.sh +6 -0
  248. package/scripts/registry-schema.cjs +57 -8
  249. package/scripts/release-notes/conventional-title.cjs +19 -1
  250. package/scripts/release-notes/format-github-release-notes.cjs +7 -3
  251. package/scripts/release-tarball-smoke.cjs +18 -11
  252. package/scripts/run-tests.cjs +420 -58
  253. package/scripts/workflow-size.cjs +16 -8
  254. package/skills/gsd-ai-integration-phase/SKILL.md +1 -1
  255. package/skills/gsd-mempalace-capture/SKILL.md +9 -5
  256. package/skills/gsd-new-milestone/SKILL.md +1 -1
  257. package/skills/gsd-plan-phase/SKILL.md +5 -3
  258. package/skills/gsd-plan-review-convergence/SKILL.md +7 -2
  259. package/vscode/package.json +1 -1
  260. package/scripts/gen-golden-install-parity-zcode.cjs +0 -77
  261. package/scripts/update-size-baseline.cjs +0 -68
@@ -10,7 +10,7 @@ const capabilities = {
10
10
  "ai-integration": {
11
11
  "id": "ai-integration",
12
12
  "role": "feature",
13
- "version": "1.7.0",
13
+ "version": "1.9.0",
14
14
  "title": "AI design contract",
15
15
  "description": "AI-SPEC design contract workflow for phases that build AI systems; owns the AI integration command, agents, and workflow.ai_integration_phase activation key.",
16
16
  "tier": "full",
@@ -68,7 +68,7 @@ const capabilities = {
68
68
  "into": "planner",
69
69
  "fragment": {
70
70
  "path": "fragments/api-coverage-plan-pre.md",
71
- "inline": "# API Coverage Decision Checkpoint\n\n> Full API Coverage by Default — Opt Out, Never Opt In. Fires when a phase\n> integrates an external API / SDK / service. Most non-API phases will not fire\n> it — that is the point.\n\n## Why this exists\n\n\"We integrated the API\" too often silently means \"we integrated whatever the\nfirst use case exercised.\" Every un-built capability is then an invisible hole,\ndiscovered later by a user who reasonably expected it to work. The phase sealed\ngreen because its tasks completed; nobody decided the gaps were acceptable,\nbecause nobody enumerated them. This checkpoint makes the surface **visible and\ndecided** before the phase can seal.\n\n## Detect whether this phase integrates an external API\n\nThe detector is a deterministic scan over the phase scope. It strips fenced\ncode blocks first, so a trigger term inside a code snippet does not fire. It\nreturns a typed result: `{ detected, signals[], terms }`. Run it on the phase\nscope (the concatenation of this phase's ROADMAP section + the PLAN body):\n\n```bash\nSCOPE=\"$(cat \"${PHASE_DIR}\"/*-PLAN.md 2>/dev/null) $(gsd_run query roadmap.get-phase \"${PHASE}\" 2>/dev/null || true)\"\nAPI_COVERAGE_JSON=$(printf '%s' \"$SCOPE\" | node gsd-core/bin/lib/api-coverage.cjs --json 2>/dev/null || echo '{\"detected\":false,\"signals\":[]}')\n```\n\nRead `API_COVERAGE_JSON.detected`. Act on it only — do **not** pattern-match the\nprose yourself.\n\n**If `detected` is `false`:** this phase does not integrate an external API. Skip\nthe checkpoint entirely and continue planning. Do not raise it with the user.\n\n**If `detected` is `true`:** an external-API integration is in scope. You MUST\nproduce a **coverage matrix** before the plan is finalized.\n\n## Produce the coverage matrix\n\nEnumerate the external API's full **capability surface** — the verb/endpoint/method\nlist (e.g. for a music service: `search`, `play`, `pause`, `skip`, `set_volume`,\n`get_playlist`, `create_playlist`, `add_to_playlist`, …). For each capability\nrecord a decision, starting from **full coverage** as the default:\n\n| capability | decision | reason |\n|---|---|---|\n| `<capability-id>` | `INTEGRATE` \\| `OPT-OUT` | `<one-line reason if OPT-OUT>` |\n\nRules:\n\n- **`INTEGRATE` is the default.** Every capability starts as INTEGRATE; the\n matrix is the *subtraction record*.\n- **Every `OPT-OUT` MUST carry a one-line reason** (`not needed`, `not needed\n yet`, `explicitly out of scope`, …). An opt-out without a reason is an\n un-decided hole — the exact failure mode this gate exists to close.\n- **A second integration against the same need** (e.g. a second platform for the\n same capability) starts from the **same full-coverage baseline** as the first.\n Do not carry over the first integration's opt-outs silently — re-decide each\n capability for the new surface, so a first-class/fallback asymmetry cannot\n accumulate.\n\nWrite the matrix to `${PHASE_DIR}/COVERAGE.md` (canonical markdown-table form):\n\n```markdown\n# API Coverage — <service>\n\n> Full coverage by default. Opt-outs are explicit, reasoned decisions.\n\n| capability | decision | reason |\n|---|---|---|\n| search | INTEGRATE | |\n| playlists | INTEGRATE | |\n| skip | OPT-OUT | not needed yet — tracked for follow-up phase |\n```\n\nA fenced ` ```coverage ` JSON block is also accepted for machine-generated\nmatrices; the markdown table is preferred (human-editable, diff-friendly).\n\n## The seal-time gate\n\nThis checkpoint is enforced. At `verify:pre` the `api-coverage.verify-pre` gate\nruns `check api-coverage.verify-pre <phase-dir>`:\n\n- If `COVERAGE.md` exists, it is validated — every row needs a valid decision and\n every `OPT-OUT` a reason. A malformed/partial matrix **blocks the seal**.\n- If `COVERAGE.md` is absent, the detector runs again over the phase scope. If a\n strong external-API-integration signal is found, the seal is **blocked** until a\n matrix is produced. If no signal is found, the phase is treated as a non-API\n phase and the seal proceeds.\n\nSo: an API-integrating phase cannot seal without a decided matrix. Produce it at\nplan time; do not leave it for seal time.\n\n## Tuning the vocabulary (optional)\n\nThe trigger vocabulary is a curated, additive-only set in\n`gsd-core/bin/lib/api-coverage.cjs` (`DEFAULT_API_COVERAGE_TERMS`). To widen it\nfor a project, override at the call site:\n\n```bash\nprintf '%s' \"$SCOPE\" | node gsd-core/bin/lib/api-coverage.cjs --json \\\n --verbs integrate,wrap,connect,embed --nouns api,sdk,rest,grpc,webhook,plugin\n```\n\nThe whole checkpoint is toggleable via `workflow.api_coverage_gate` in\n`.planning/config.json`.\n"
71
+ "inline": "# API Coverage Decision Checkpoint\n\n> Full API Coverage by Default — Opt Out, Never Opt In. Fires when a phase\n> integrates an external API / SDK / service. Most non-API phases will not fire\n> it — that is the point.\n\n## Why this exists\n\n\"We integrated the API\" too often silently means \"we integrated whatever the\nfirst use case exercised.\" Every un-built capability is then an invisible hole,\ndiscovered later by a user who reasonably expected it to work. The phase sealed\ngreen because its tasks completed; nobody decided the gaps were acceptable,\nbecause nobody enumerated them. This checkpoint makes the surface **visible and\ndecided** before the phase can seal.\n\n## Detect whether this phase integrates an external API\n\nThe detector is a deterministic scan over the phase scope. It strips fenced\ncode blocks first, so a trigger term inside a code snippet does not fire. It\nreturns a typed result: `{ detected, signals[], terms }`. Run it on the phase\nscope (the concatenation of this phase's ROADMAP section + the PLAN body):\n\n```bash\nSCOPE=\"$(cat \"${PHASE_DIR}\"/*-PLAN.md 2>/dev/null) $(gsd_run query roadmap.get-phase \"${PHASE}\" 2>/dev/null || true)\"\nAPI_COVERAGE_JSON=$(printf '%s' \"$SCOPE\" | node gsd-core/bin/lib/api-coverage.cjs --json 2>/dev/null || echo '{\"detected\":false,\"signals\":[]}')\n```\n\nRead `API_COVERAGE_JSON.detected`. Act on it only — do **not** pattern-match the\nprose yourself.\n\n**If `detected` is `false`:** this phase does not integrate an external API. Skip\nthe checkpoint entirely and continue planning. Do not raise it with the user.\n\n**If `detected` is `true`:** an external-API integration is in scope. You MUST\nproduce a **coverage matrix** before the plan is finalized.\n\n**If `detected` is `true` but the phase genuinely integrates no external API**\n(the detector is deterministic, not infallible — confirm by re-reading the phase\nscope, not by preference): do NOT fabricate a matrix row for a capability that\ndoes not exist. Write a reasoned declaration to `${PHASE_DIR}/COVERAGE.md`\ninstead:\n\n```markdown\nNo external API integration: <one-line reason — what the phase touches instead>.\n```\n\nThe reason is required, exactly like an `OPT-OUT` reason. The seal-time gate\naccepts this declaration in place of a matrix.\n\n## Produce the coverage matrix\n\nEnumerate the external API's full **capability surface** — the verb/endpoint/method\nlist (e.g. for a music service: `search`, `play`, `pause`, `skip`, `set_volume`,\n`get_playlist`, `create_playlist`, `add_to_playlist`, …). For each capability\nrecord a decision, starting from **full coverage** as the default:\n\n| capability | decision | reason |\n|---|---|---|\n| `<capability-id>` | `INTEGRATE` \\| `OPT-OUT` | `<one-line reason if OPT-OUT>` |\n\nRules:\n\n- **`INTEGRATE` is the default.** Every capability starts as INTEGRATE; the\n matrix is the *subtraction record*.\n- **Every `OPT-OUT` MUST carry a one-line reason** (`not needed`, `not needed\n yet`, `explicitly out of scope`, …). An opt-out without a reason is an\n un-decided hole — the exact failure mode this gate exists to close.\n- **A second integration against the same need** (e.g. a second platform for the\n same capability) starts from the **same full-coverage baseline** as the first.\n Do not carry over the first integration's opt-outs silently — re-decide each\n capability for the new surface, so a first-class/fallback asymmetry cannot\n accumulate.\n\nWrite the matrix to `${PHASE_DIR}/COVERAGE.md` (canonical markdown-table form):\n\n```markdown\n# API Coverage — <service>\n\n> Full coverage by default. Opt-outs are explicit, reasoned decisions.\n\n| capability | decision | reason |\n|---|---|---|\n| search | INTEGRATE | |\n| playlists | INTEGRATE | |\n| skip | OPT-OUT | not needed yet — tracked for follow-up phase |\n```\n\nA fenced ` ```coverage ` JSON block is also accepted for machine-generated\nmatrices; the markdown table is preferred (human-editable, diff-friendly).\n\n## The seal-time gate\n\nThis checkpoint is enforced. At `verify:pre` the `api-coverage.verify-pre` gate\nruns `check api-coverage.verify-pre <phase-dir>`:\n\n- If `COVERAGE.md` exists, it is validated — every row needs a valid decision and\n every `OPT-OUT` a reason. A malformed/partial matrix **blocks the seal**. A\n reasoned `No external API integration: …` declaration (and no rows) passes.\n- If `COVERAGE.md` is absent, the detector runs again over the phase scope. If a\n strong external-API-integration signal is found, the seal is **blocked** until a\n matrix is produced. If no signal is found, the phase is treated as a non-API\n phase and the seal proceeds.\n\nSo: an API-integrating phase cannot seal without a decided matrix. Produce it at\nplan time; do not leave it for seal time.\n\n## Tuning the vocabulary (optional)\n\nThe trigger vocabulary is a curated, additive-only set in\n`gsd-core/bin/lib/api-coverage.cjs` (`DEFAULT_API_COVERAGE_TERMS`). To widen it\nfor a project, override at the call site:\n\n```bash\nprintf '%s' \"$SCOPE\" | node gsd-core/bin/lib/api-coverage.cjs --json \\\n --verbs integrate,wrap,connect,embed --nouns api,sdk,rest,grpc,webhook,plugin\n```\n\nThe whole checkpoint is toggleable via `workflow.api_coverage_gate` in\n`.planning/config.json`.\n"
72
72
  },
73
73
  "produces": [
74
74
  "COVERAGE.md"
@@ -95,7 +95,7 @@ const capabilities = {
95
95
  "antigravity": {
96
96
  "id": "antigravity",
97
97
  "role": "runtime",
98
- "version": "1.7.0",
98
+ "version": "1.9.0",
99
99
  "title": "Antigravity",
100
100
  "description": "Google Antigravity IDE — nested under ~/.gemini/antigravity; probed across 1.x and 2.x layouts; Gemini hook event dialect; flat skill layout; tier-1 support.",
101
101
  "tier": "core",
@@ -176,13 +176,15 @@ const capabilities = {
176
176
  "maxDepth": "undocumented",
177
177
  "background": true,
178
178
  "subagentToolkit": "full",
179
- "backgroundDispatch": "undocumented"
179
+ "backgroundDispatch": "undocumented",
180
+ "isolation": "undocumented"
180
181
  },
181
182
  "modelMode": "passive",
182
183
  "hookBus": "host",
183
184
  "stateIO": "filesystem",
184
185
  "transport": "mcp",
185
- "runtime": "go"
186
+ "runtime": "go",
187
+ "effortSurface": "undocumented"
186
188
  },
187
189
  "hostBehaviors": {
188
190
  "reviewerCli": true,
@@ -191,12 +193,53 @@ const capabilities = {
191
193
  "hookPathStyle": "raw",
192
194
  "globalDirResolver": "antigravity"
193
195
  }
196
+ },
197
+ "reviewer": {
198
+ "slug": "antigravity",
199
+ "flags": [
200
+ "--antigravity",
201
+ "--agy"
202
+ ],
203
+ "transport": "spawn",
204
+ "probe": {
205
+ "kind": "command-exists",
206
+ "binary": "agy"
207
+ },
208
+ "invoke": {
209
+ "binary": "agy",
210
+ "args": [
211
+ "--print-timeout",
212
+ "540s",
213
+ "{{model}}",
214
+ "-p",
215
+ "{{prompt}}"
216
+ ],
217
+ "promptChannel": "argv-file-ref",
218
+ "outputChannel": "stdout",
219
+ "modelArg": "--model",
220
+ "effortChannel": "none"
221
+ },
222
+ "timeoutFloorMs": 600000,
223
+ "emptyOutput": "handler-owned",
224
+ "reviewsSection": "Antigravity",
225
+ "evidenceClass": "source-grounded",
226
+ "requiresBinaries": [],
227
+ "promptBudgetKey": null,
228
+ "modelConfigKey": "review.models.agy",
229
+ "handler": "antigravity"
230
+ },
231
+ "config": {
232
+ "review.models.agy": {
233
+ "type": "string",
234
+ "default": "",
235
+ "description": "Model passed to the Antigravity reviewer lane. The key suffix is the lane binary/flag alias `agy`, not the slug `antigravity` — preserved verbatim so existing .planning/config.json files keep working."
236
+ }
194
237
  }
195
238
  },
196
239
  "assumption-delta": {
197
240
  "id": "assumption-delta",
198
241
  "role": "feature",
199
- "version": "1.7.0",
242
+ "version": "1.9.0",
200
243
  "title": "Assumption-delta architecture checkpoint",
201
244
  "description": "Rarely-firing advisory checkpoint that triggers when a phase makes something plural, optional, or chosen that used to be singular, required, or derived. Surfaces one identity-model question (promote the new general representation to primary, or add it alongside?) so a silent primary-key drift does not accumulate into a later user-facing bug. Non-blocking; fires only on a detected signal.",
202
245
  "tier": "full",
@@ -242,7 +285,7 @@ const capabilities = {
242
285
  "audit": {
243
286
  "id": "audit",
244
287
  "role": "feature",
245
- "version": "1.7.0",
288
+ "version": "1.9.0",
246
289
  "title": "Audit",
247
290
  "description": "Open-artifact audit and UAT-gap audit for milestone close gates; exposes `gsd-tools audit-uat` (cross-phase UAT outstanding items) and `gsd-tools audit-open` (structured open-artifact scan across debug, tasks, threads, todos, seeds, UAT, verification, context-questions).",
248
291
  "tier": "full",
@@ -279,7 +322,7 @@ const capabilities = {
279
322
  "augment": {
280
323
  "id": "augment",
281
324
  "role": "runtime",
282
- "version": "1.7.0",
325
+ "version": "1.9.0",
283
326
  "title": "Augment Code",
284
327
  "description": "Augment Code CLI — commands + nested-skill artifact layout; settings-json hook surface; Claude hook event dialect; tier-2 support.",
285
328
  "tier": "core",
@@ -373,20 +416,68 @@ const capabilities = {
373
416
  "maxDepth": "undocumented",
374
417
  "background": true,
375
418
  "subagentToolkit": "full",
376
- "backgroundDispatch": "undocumented"
419
+ "backgroundDispatch": "undocumented",
420
+ "isolation": "undocumented"
377
421
  },
378
422
  "modelMode": "passive",
379
423
  "hookBus": "host",
380
424
  "stateIO": "filesystem",
381
425
  "transport": "mcp",
382
- "runtime": "node"
426
+ "runtime": "node",
427
+ "effortSurface": "undocumented"
383
428
  }
384
429
  }
385
430
  },
431
+ "broken-windows": {
432
+ "id": "broken-windows",
433
+ "role": "feature",
434
+ "version": "1.9.0",
435
+ "title": "Broken-windows ledger",
436
+ "description": "Cross-phase defect register accumulating stubs, TODOs, skipped tests, unrun verifies, and unmet truths into .planning/WINDOWS.md. Blocks /gsd-ship while any window is open unless explicitly waived with a recorded reason. Operationalizes GSD's no-defer discipline as a tracked, enforced artifact (issue #1950).",
437
+ "tier": "full",
438
+ "requires": [],
439
+ "engines": {
440
+ "gsd": ">=1.7.0"
441
+ },
442
+ "runtimeCompat": {
443
+ "supported": [
444
+ "*"
445
+ ],
446
+ "unsupported": []
447
+ },
448
+ "skills": [],
449
+ "agents": [],
450
+ "hooks": [],
451
+ "config": {
452
+ "workflow.windows_enforce": {
453
+ "type": "boolean",
454
+ "default": false,
455
+ "description": "Enable the blocking ship:pre gate for the broken-windows ledger. When true (opt-in), /gsd-ship blocks while .planning/WINDOWS.md has any open entry. When false (default), windows are still tracked (the executor and verifier still populate WINDOWS.md via gsd-tools windows append) but ship does not block — teams can adopt tracking before enforcement. Issue #1950."
456
+ }
457
+ },
458
+ "steps": [],
459
+ "contributions": [],
460
+ "gates": [
461
+ {
462
+ "point": "ship:pre",
463
+ "check": {
464
+ "predicate": {
465
+ "kind": "artifact-frontmatter-equals",
466
+ "artifact": "WINDOWS.md",
467
+ "field": "open_count",
468
+ "equals": 0
469
+ }
470
+ },
471
+ "when": "workflow.windows_enforce",
472
+ "blocking": true,
473
+ "onError": "halt"
474
+ }
475
+ ]
476
+ },
386
477
  "claude": {
387
478
  "id": "claude",
388
479
  "role": "runtime",
389
- "version": "1.7.0",
480
+ "version": "1.9.0",
390
481
  "title": "Claude Code",
391
482
  "description": "Anthropic Claude Code — primary development runtime; tier-1 support with full hook surface and skills-based global install.",
392
483
  "tier": "core",
@@ -457,14 +548,17 @@ const capabilities = {
457
548
  "maxDepth": 5,
458
549
  "background": true,
459
550
  "subagentToolkit": "full",
460
- "backgroundDispatch": false
551
+ "backgroundDispatch": false,
552
+ "isolation": "harness-worktree"
461
553
  },
462
554
  "modelMode": "passive",
463
555
  "hookBus": "host",
464
556
  "stateIO": "filesystem",
465
557
  "transport": "mcp",
466
- "runtime": "node"
558
+ "runtime": "node",
559
+ "effortSurface": "argv"
467
560
  },
561
+ "harnessIsolationFlag": "isolation=\"worktree\"",
468
562
  "hostBehaviors": {
469
563
  "attributionSource": "settings-json-commit",
470
564
  "authorsCanonicalWorkflow": true,
@@ -486,12 +580,51 @@ const capabilities = {
486
580
  "hyphenNameAgentBody": true,
487
581
  "reviewerCli": true
488
582
  }
583
+ },
584
+ "reviewer": {
585
+ "slug": "claude",
586
+ "flags": [
587
+ "--claude"
588
+ ],
589
+ "transport": "spawn",
590
+ "probe": {
591
+ "kind": "command-exists",
592
+ "binary": "claude"
593
+ },
594
+ "invoke": {
595
+ "binary": "claude",
596
+ "args": [
597
+ "{{model}}",
598
+ "{{effort}}",
599
+ "-p",
600
+ "-"
601
+ ],
602
+ "promptChannel": "stdin",
603
+ "outputChannel": "stdout",
604
+ "modelArg": "--model",
605
+ "effortChannel": "argv"
606
+ },
607
+ "timeoutFloorMs": 1200000,
608
+ "emptyOutput": "stub-with-stderr",
609
+ "reviewsSection": "Claude",
610
+ "evidenceClass": "source-grounded",
611
+ "requiresBinaries": [],
612
+ "promptBudgetKey": null,
613
+ "modelConfigKey": "review.models.claude",
614
+ "handler": null
615
+ },
616
+ "config": {
617
+ "review.models.claude": {
618
+ "type": "string",
619
+ "default": "",
620
+ "description": "Model passed to the Claude reviewer lane."
621
+ }
489
622
  }
490
623
  },
491
624
  "claude-orchestration": {
492
625
  "id": "claude-orchestration",
493
626
  "role": "feature",
494
- "version": "1.7.0",
627
+ "version": "1.9.0",
495
628
  "title": "Claude orchestration (Workflow backend)",
496
629
  "description": "Default-off, BETA, claude-only capability that adopts Claude Code's Workflow tool (the engine behind /effort ultracode) as an optional parallel-execution backend for the GSD loop. When the runtime exposes the Workflow tool and claude_orchestration.execution_backend resolves to 'workflow', execute-phase emits a generated Workflow script (waves -> parallel() barriers, plans -> agent({ agentType: 'gsd-executor', isolation: 'worktree' }), files_modified overlap -> separate sequential stages, resumeFromRunId wired to the phase run id, shared token budget) that composes the SAME gsd-executor agent and worktree isolation the inline path uses, restoring the wave parallelism the #853 backgrounded-agent nesting limitation forces inline on Claude Code. (The plan-checker and verifier remain inline until separately wired — this capability delivers the parallel-execution backend, not those gates.) Also folds the ultraplan plan-offload under one runtime gate (plan:* surface). On any runtime lacking the Workflow tool, or when the capability is disabled, behaviour is byte-identical to today (inline/manual dispatch). Detection + emission live in gsd-core/bin/lib/claude-orchestration.cjs (pure, fail-closed). Mirrors the existing gsd-ultraplan-phase BETA-isolation posture.",
497
630
  "tier": "full",
@@ -515,7 +648,8 @@ const capabilities = {
515
648
  "router": "routeClaudeOrchestrationCommand",
516
649
  "subcommands": [
517
650
  "detect-backend",
518
- "emit-workflow"
651
+ "emit-workflow",
652
+ "resolve-wave-dispatch"
519
653
  ]
520
654
  }
521
655
  ],
@@ -545,11 +679,11 @@ const capabilities = {
545
679
  "steps": [],
546
680
  "contributions": [
547
681
  {
548
- "point": "execute:wave:post",
682
+ "point": "execute:wave:pre",
549
683
  "into": "executor",
550
684
  "fragment": {
551
- "path": "fragments/execute-wave-post.md",
552
- "inline": "# Claude orchestration — Workflow execution backend (BETA)\n\n> Injected at `execute:wave:post` `into: executor` only when\n> `claude_orchestration.enabled` is true. Default-off; `onError: skip`.\n\n## When this contribution is active\n\nThe Claude orchestration capability is **default-off and BETA**. It activates only\nwhen ALL of the following hold:\n\n1. `claude_orchestration.enabled` is `true` in `.planning/config.json`, AND\n2. the active runtime is **Claude Code** (the Workflow tool is Claude / Agent\n SDK-specific), AND\n3. `claude_orchestration.execution_backend` resolves to `workflow` — either\n explicitly, or via `auto` — **and** the Agent SDK version is\n `>= claude_orchestration.min_agent_sdk_version` (default `0.3.149`). The SDK\n floor applies in both `auto` and `workflow` modes (fail-closed: a pre-release\n or older SDK never activates the preview backend).\n\nDetection is fail-closed: any miss degrades to **inline, manual, one-agent-per-\nmessage dispatch** — exactly today's behaviour. On a non-Claude runtime this\ncontribution is a no-op.\n\n## What the executor does when the Workflow backend is active\n\nInstead of the orchestrator fanning out one `Agent(subagent_type=gsd-executor,\nisolation=worktree, run_in_background=true)` per message (which on Claude Code\ncannot nest further subagents — #853 — and so degrades to sequential inline\nexecution), execute-phase **emits a generated Workflow script** and lets the main\nloop orchestrate it:\n\n- **waves → one or more sequential `parallel()` barriers** — each wave is a\n barrier group; when plans within a wave share `files_modified`, they are split\n into separate sequential stages within that wave's barrier (the next wave\n still waits for the previous wave to complete).\n- **plans → `agent(brief, { agentType: 'gsd-executor', isolation: 'worktree' })`**\n — the SAME executor agent and worktree isolation the inline path uses, so the\n produced `SUMMARY.md` and commits are identical.\n- **`files_modified` overlap → separate sequential stages** — two plans that\n touch the same file are placed in different stages within the wave (the same\n overlap rule execute-phase already applies inline).\n- **`resumeFromRunId`** — wired to the phase run id, so an interrupted phase\n resumes without re-running completed plans.\n- **`budget(tokens)`** — a shared token pool across the whole phase when the\n orchestrator passes a `budgetTokens` value to `emitWorkflowScript` (it is a\n function parameter, not a config key; the orchestrator decides the budget).\n\nThe emitter is a pure function exposed through the capability command surface:\n`gsd-tools claude-orchestration emit-workflow --waves <manifest.json> --run-id <id>\n[--phase-dir <dir>] [--budget <n>]` (or `require('gsd-core/bin/lib/claude-orchestration.cjs').emitWorkflowScript`\ndirectly). It maps the phase's wave/plan manifest to the Workflow script string\nand never invokes the Workflow tool itself; the orchestrator runs the emitted\nscript. Detection is resolved by the orchestrator calling the pure\n`detectWorkflowBackend` with the LIVE host descriptor (the CLI\n`gsd-tools claude-orchestration detect-backend` is a simulation harness that\nassumes a capable host unless `--no-nested-dispatch` is passed — it does not probe\nthe real runtime; the orchestrator supplies the real descriptor).\n\n## Fallback contract\n\nIf detection resolves to `inline` (tool absent, SDK too old, runtime not Claude,\nor the capability disabled), execute-phase MUST proceed with the standard inline\nwave dispatch. The executor MUST NOT assume parallelism, a shared budget, or\nresume-from-run-id semantics in that mode.\n"
685
+ "path": "fragments/execute-wave-pre.md",
686
+ "inline": "# Claude orchestration — Workflow execution backend (BETA)\n\n> Injected at `execute:wave:pre` `into: executor` only when\n> `claude_orchestration.enabled` is true. Default-off; `onError: skip`.\n\n## When this contribution is active\n\nThe Claude orchestration capability is **default-off and BETA**. It activates only\nwhen ALL of the following hold:\n\n1. `claude_orchestration.enabled` is `true` in `.planning/config.json`, AND\n2. the active runtime is **Claude Code** (the Workflow tool is Claude / Agent\n SDK-specific), AND\n3. `claude_orchestration.execution_backend` resolves to `workflow` — either\n explicitly, or via `auto` — **and** the Agent SDK version is\n `>= claude_orchestration.min_agent_sdk_version` (default `0.3.149`). The SDK\n floor applies in both `auto` and `workflow` modes (fail-closed: a pre-release\n or older SDK never activates the preview backend).\n\nDetection is fail-closed: any miss degrades to **inline, manual, one-agent-per-\nmessage dispatch** — exactly today's behaviour. On a non-Claude runtime this\ncontribution is a no-op.\n\n## Why `execute:wave:pre` (not `execute:wave:post`)\n\nThis is a **dispatch-backend selector** — it decides HOW a wave's executor agents\nare spawned. That decision has to be made BEFORE the wave's `Agent()` calls in\n`execute-phase.md` step 3, not after the wave has already finished (#2285). The\ncapability previously registered at `execute:wave:post`, which fires only after\nworktree merge/post-merge tests/tracking updates — by then the wave was already\ndispatched inline, so the contribution was structurally unable to change how\ndispatch happened. This fragment is injected at the point that actually precedes\ndispatch.\n\n## What the orchestrator does when the Workflow backend is active\n\nBefore spawning executor agents for the current wave (execute-phase.md step 3),\nresolve the dispatch backend through the single composed CLI seam:\n\n```bash\ngsd-tools claude-orchestration resolve-wave-dispatch \\\n --waves \"$WAVE_MANIFEST_PATH\" --run-id \"$PHASE_RUN_ID\" \\\n --runtime \"$RUNTIME\" \\\n --phase-dir \"$PHASE_DIR\" --raw\n```\n\n`--agent-sdk-version` is no longer passed here (#2590). The router resolves the\ninstalled Agent SDK version itself; see **Agent SDK version** below. The former\n`${AGENT_SDK_VERSION:+--agent-sdk-version \"$AGENT_SDK_VERSION\"}` line was also\n**shell-dependent**: zsh does not word-split unquoted parameter expansions, so it\ncollapsed to a SINGLE argv element there, `argValue()` never matched, and the run\nfailed into `agent_sdk_version_unknown` — indistinguishable from genuinely\nunknown. Pass `--agent-sdk-version <ver>` explicitly only to pin a version.\n\nThis composes `detectWorkflowBackend` (the gate ladder above) with\n`emitWorkflowScript` (the wave→plan mapping below) in ONE call — the pure\nfunction backing it is `resolveWaveDispatch` in\n`gsd-core/bin/lib/claude-orchestration.cjs`. Response shape:\n`{ backend: 'inline'|'workflow', reason, script?, summary? }`.\n\n### Manifest construction (`$WAVE_MANIFEST_PATH`, `$PHASE_RUN_ID`, `$PHASE_DIR`)\n\nThese are NOT pre-existing execute-phase.md variables — the orchestrator builds\nthem at this step, from data it already has in-context from `discover_and_group_plans`\n(the `PLAN_INDEX` JSON) and step 2.5 (the per-plan `USE_WORKTREES_FOR_PLAN` decision):\n\n1. **`$PHASE_DIR`** — reuse `{phase_dir}` from the `INIT` bundle (already loaded\n in the `initialize` step). No new value needed.\n\n2. **`$PHASE_RUN_ID`** — a stable identifier for THIS phase-execution attempt, so\n `resumeFromRunId` can resume an interrupted run without re-dispatching plans\n the Workflow tool already completed. Construct it deterministically —\n `execute-{phase_number}-{phase_slug}` — from `INIT`'s `phase_number`/`phase_slug`\n (both are already validated identifiers used elsewhere in this workflow, so\n they satisfy `emitWorkflowScript`'s `isScriptableIdentifier` check). Do NOT\n mint a new random id per wave — the SAME `$PHASE_RUN_ID` is reused for every\n wave in the phase so the Workflow tool can correctly track cross-wave resume\n state.\n\n3. **`$WAVE_MANIFEST_PATH`** — a fresh temp file for THIS wave's manifest (one\n wave = one `waves` array with a single entry, matching the wave-by-wave\n dispatch loop; do not batch multiple waves into one manifest — waves are\n dispatched in wave order, not all at once):\n\n ```bash\n WAVE_MANIFEST_PATH=$(mktemp \"${TMPDIR:-/tmp}/gsd-wave-dispatch-XXXXXX\") && mv \"$WAVE_MANIFEST_PATH\" \"$WAVE_MANIFEST_PATH.json\" && WAVE_MANIFEST_PATH=\"$WAVE_MANIFEST_PATH.json\"\n ```\n\n Then **use the Write tool** (not a bash/jq pipeline — the orchestrator already\n has every field parsed in-context) to write the manifest JSON to\n `$WAVE_MANIFEST_PATH`:\n\n ```json\n {\n \"waves\": [\n {\n \"id\": \"wave-{N}\",\n \"plans\": [\n {\n \"id\": \"{plan_id}\",\n \"brief\": \"{the SAME <objective>...<success_criteria> prompt block step 3 builds for this plan's inline Agent() call}\",\n \"files_modified\": [\"{from PLAN_INDEX.plans[].files_modified for this plan}\"],\n \"use_worktree\": {true unless step 2.5 set USE_WORKTREES_FOR_PLAN=false for this plan}\n }\n ]\n }\n ]\n }\n ```\n\n - **`id`** — the plan id from `PLAN_INDEX`, e.g. `\"01-01\"`.\n - **`brief`** — MUST carry the same task content as step 3's inline `Agent()`\n prompt (the `<objective>`/`<execution_context>`/`<files_to_read>`/\n `<success_criteria>` block, with `{plan_number}`/`{phase_number}`/\n `{phase_name}` substituted) — a short summary here would NOT reproduce\n step 3's behavior and would violate the \"identical artifacts\" contract.\n - **`files_modified`** — copy verbatim from the plan's `PLAN_INDEX` entry.\n - **`use_worktree`** — `true` for every plan UNLESS step 2.5's per-plan\n worktree gate (`execute-phase/steps/per-plan-worktree-gate.md`) set\n `USE_WORKTREES_FOR_PLAN=false` for that plan (submodule-touching plan, or\n project-level `USE_WORKTREES=false`) — in which case pass `false` here so\n `emitWorkflowScript` omits `isolation: \"worktree\"` for that plan (#2772 /\n #2285 finding 1). **Never** hardcode `true` — that would force worktree\n isolation on a plan the inline path explicitly keeps out of worktrees.\n\n4. **`$AGENT_SDK_VERSION`** — no longer built here; the router resolves it.\n\n**Agent SDK version:** the orchestrator has no *bash-computable* way to\nintrospect the live Agent SDK version — but the router runs in Node, so it\nresolves the version itself (#2590), in this order:\n\n1. an explicit `--agent-sdk-version <ver>` (pin a version),\n2. `GSD_AGENT_SDK_VERSION`,\n3. the **installed** `@anthropic-ai/claude-agent-sdk` package version, read from\n its `package.json` on disk by walking `node_modules` up the tree. (Read\n directly rather than via `require.resolve`: the SDK's `exports` map does not\n expose `./package.json`, so `require.resolve` throws\n `ERR_PACKAGE_PATH_NOT_EXPORTED`.)\n\nPreviously nothing computed this at all, so gate 5 returned\n`agent_sdk_version_unknown` on **every** automated run and the Workflow backend\ncould never activate — while `gsd-tools capability state` still reported the\ncapability `active: true`. Fail-closed is preserved: when no version can be\nresolved, gate 5 still declines to `inline`. What changed is that a resolvable\nversion is now actually found, so a genuinely-too-old SDK reports\n`agent_sdk_version_below_floor` — the truthful reason — instead of `unknown`.\n\n**If `backend == \"workflow\"`:** run the emitted `script` via the Workflow tool\nfor THIS wave instead of the per-message `Agent()` loop in step 3. The script\ncomposes the SAME `gsd-executor` agent type the inline path uses, with\nworktree isolation applied PER PLAN from the manifest's `use_worktree` field\n(see `emitWorkflowScript`):\n\n- **waves → one or more sequential `parallel()` barriers** — each wave is a\n barrier group; when plans within a wave share `files_modified`, they are split\n into separate sequential stages within that wave's barrier.\n- **plans → `agent(brief, { agentType: 'gsd-executor', isolation: 'worktree' })`**\n when `use_worktree` is not `false`, or `agent(brief, { agentType: 'gsd-executor' })`\n (no isolation) when it is — so the produced `SUMMARY.md` and commits are\n identical to inline dispatch, INCLUDING the inline path's submodule safety\n gate (#2772 / #2285 finding 1).\n- **`files_modified` overlap → separate sequential stages** — the same overlap\n rule execute-phase already applies inline (step 1 of the wave loop).\n- **`resumeFromRunId`** — **pass `summary.resumeRunId` as the Workflow tool's\n `resumeFromRunId` INPUT when you invoke the tool.** It is a tool parameter,\n not a script function; the script deliberately does not call it (#2590 — doing\n so threw \"resumeFromRunId is not defined\" and rejected the entire script).\n Omitting it from the tool invocation silently regresses phase-resume to a\n no-op: an interrupted phase re-runs completed plans.\n\nThe orchestrator still runs steps 4–5.8 (wait for completion, worktree cleanup,\npost-merge gate, tracking update) exactly as it does for inline dispatch — the\nWorkflow backend only replaces HOW agents are spawned for this wave, not what\nhappens after they return.\n\n**If `backend == \"inline\"`** (any gate miss, or `resolve-wave-dispatch` itself\nunavailable/erroring): proceed to step 3's standard per-message `Agent()`\ndispatch — the default, byte-identical-to-today path. `onError: skip` on this\ncontribution means a `resolve-wave-dispatch` command failure is treated exactly\nlike an `inline` result, never as a fatal wave error.\n\n## Fallback contract\n\nDetection is fail-closed end-to-end: capability disabled, non-Claude runtime,\n`execution_backend:\"inline\"`, missing/incapable host descriptor, unknown or\nbelow-floor Agent SDK version, or an `emitWorkflowScript` failure on a malformed\nwave manifest — ANY of these degrades to `backend:\"inline\"` and execute-phase's\nstandard inline dispatch (step 3) runs unmodified. The Workflow backend never\npartially activates; the executor MUST NOT assume parallelism, a shared budget,\nor resume-from-run-id semantics when `backend == \"inline\"`.\n"
553
687
  },
554
688
  "produces": [],
555
689
  "consumes": [
@@ -578,7 +712,7 @@ const capabilities = {
578
712
  "cline": {
579
713
  "id": "cline",
580
714
  "role": "runtime",
581
- "version": "1.7.0",
715
+ "version": "1.9.0",
582
716
  "title": "Cline",
583
717
  "description": "Cline (VS Code extension) — global-only nested-skill layout; cline-rules hook surface (.clinerules); no hook events emitted; tier-2 support.",
584
718
  "tier": "core",
@@ -626,13 +760,15 @@ const capabilities = {
626
760
  "maxDepth": 1,
627
761
  "background": true,
628
762
  "subagentToolkit": "read-only",
629
- "backgroundDispatch": false
763
+ "backgroundDispatch": false,
764
+ "isolation": "undocumented"
630
765
  },
631
766
  "modelMode": "active",
632
767
  "hookBus": "host",
633
768
  "stateIO": "filesystem",
634
769
  "transport": "mcp",
635
- "runtime": "node"
770
+ "runtime": "node",
771
+ "effortSurface": "undocumented"
636
772
  },
637
773
  "hostBehaviors": {
638
774
  "reapplyCommand": "/gsd-update --reapply",
@@ -647,7 +783,7 @@ const capabilities = {
647
783
  "code-review": {
648
784
  "id": "code-review",
649
785
  "role": "feature",
650
- "version": "1.7.0",
786
+ "version": "1.9.0",
651
787
  "title": "Code review",
652
788
  "description": "Source-file code review and review-fix workflow support for completed execution work.",
653
789
  "tier": "full",
@@ -708,7 +844,7 @@ const capabilities = {
708
844
  "codebuddy": {
709
845
  "id": "codebuddy",
710
846
  "role": "runtime",
711
- "version": "1.7.0",
847
+ "version": "1.9.0",
712
848
  "title": "CodeBuddy",
713
849
  "description": "CodeBuddy (Tencent) — converted commands + skills artifact layout; settings-json hook surface; Claude hook event dialect; tier-2 support.",
714
850
  "tier": "core",
@@ -803,23 +939,67 @@ const capabilities = {
803
939
  "maxDepth": 1,
804
940
  "background": true,
805
941
  "subagentToolkit": "full",
806
- "backgroundDispatch": false
942
+ "backgroundDispatch": false,
943
+ "isolation": "undocumented"
807
944
  },
808
945
  "modelMode": "passive",
809
946
  "hookBus": "host",
810
947
  "stateIO": "filesystem",
811
948
  "transport": "mcp",
812
- "runtime": "node"
949
+ "runtime": "node",
950
+ "effortSurface": "undocumented"
813
951
  },
814
952
  "hostBehaviors": {
815
953
  "reportCommandsDir": true
816
954
  }
817
955
  }
818
956
  },
957
+ "coderabbit": {
958
+ "id": "coderabbit",
959
+ "role": "reviewer",
960
+ "version": "1.9.0",
961
+ "title": "CodeRabbit",
962
+ "description": "CodeRabbit CLI — cross-AI /gsd:review reviewer lane only; not a GSD install target (no runtime body, no artifacts). Reviews the working-tree diff (`coderabbit review --prompt-only`), not the source tree, and accepts neither a prompt nor a model flag; findings are down-weighted in consensus (evidenceClass: diff-only).",
963
+ "tier": "full",
964
+ "requires": [],
965
+ "engines": {
966
+ "gsd": ">=1.8.0"
967
+ },
968
+ "reviewer": {
969
+ "slug": "coderabbit",
970
+ "flags": [
971
+ "--coderabbit"
972
+ ],
973
+ "transport": "spawn",
974
+ "probe": {
975
+ "kind": "command-exists",
976
+ "binary": "coderabbit"
977
+ },
978
+ "invoke": {
979
+ "binary": "coderabbit",
980
+ "args": [
981
+ "review",
982
+ "--prompt-only"
983
+ ],
984
+ "promptChannel": "none",
985
+ "outputChannel": "stdout",
986
+ "modelArg": null,
987
+ "effortChannel": "none"
988
+ },
989
+ "timeoutFloorMs": 360000,
990
+ "emptyOutput": "stub-with-stderr",
991
+ "reviewsSection": "CodeRabbit",
992
+ "evidenceClass": "diff-only",
993
+ "requiresBinaries": [],
994
+ "promptBudgetKey": null,
995
+ "modelConfigKey": null,
996
+ "handler": null
997
+ }
998
+ },
819
999
  "codex": {
820
1000
  "id": "codex",
821
1001
  "role": "runtime",
822
- "version": "1.7.0",
1002
+ "version": "1.9.0",
823
1003
  "title": "OpenAI Codex CLI",
824
1004
  "description": "OpenAI Codex CLI — shell-var command style; per-agent sandbox tiers; config.toml + hooks.json hook surface; tier-1 support.",
825
1005
  "tier": "core",
@@ -883,13 +1063,23 @@ const capabilities = {
883
1063
  "maxDepth": 1,
884
1064
  "background": true,
885
1065
  "subagentToolkit": "full",
886
- "backgroundDispatch": true
1066
+ "backgroundDispatch": true,
1067
+ "isolation": "orchestrator-worktree"
887
1068
  },
888
1069
  "modelMode": "passive",
889
1070
  "hookBus": "host",
890
1071
  "stateIO": "filesystem",
891
1072
  "transport": "mcp",
892
- "runtime": "node"
1073
+ "runtime": "node",
1074
+ "effortSurface": "argv"
1075
+ },
1076
+ "orchestratorExec": {
1077
+ "command": "codex",
1078
+ "args": [
1079
+ "exec"
1080
+ ],
1081
+ "cwdFlag": "--cd",
1082
+ "promptFlag": null
893
1083
  },
894
1084
  "hostBehaviors": {
895
1085
  "reapplyCommand": "$gsd-update --reapply",
@@ -899,12 +1089,55 @@ const capabilities = {
899
1089
  "frontmatterDialect": "codex",
900
1090
  "reviewerCli": true
901
1091
  }
1092
+ },
1093
+ "reviewer": {
1094
+ "slug": "codex",
1095
+ "flags": [
1096
+ "--codex"
1097
+ ],
1098
+ "transport": "spawn",
1099
+ "probe": {
1100
+ "kind": "command-exists",
1101
+ "binary": "codex"
1102
+ },
1103
+ "invoke": {
1104
+ "binary": "codex",
1105
+ "args": [
1106
+ "exec",
1107
+ "--ephemeral",
1108
+ "{{model}}",
1109
+ "{{effort}}",
1110
+ "--skip-git-repo-check",
1111
+ "{{output}}",
1112
+ "-"
1113
+ ],
1114
+ "promptChannel": "stdin",
1115
+ "outputChannel": "file-arg",
1116
+ "outputArg": "-o",
1117
+ "modelArg": "--model",
1118
+ "effortChannel": "argv"
1119
+ },
1120
+ "timeoutFloorMs": 1200000,
1121
+ "emptyOutput": "stub-with-stderr",
1122
+ "reviewsSection": "Codex",
1123
+ "evidenceClass": "source-grounded",
1124
+ "requiresBinaries": [],
1125
+ "promptBudgetKey": null,
1126
+ "modelConfigKey": "review.models.codex",
1127
+ "handler": null
1128
+ },
1129
+ "config": {
1130
+ "review.models.codex": {
1131
+ "type": "string",
1132
+ "default": "",
1133
+ "description": "Model passed to the Codex reviewer lane."
1134
+ }
902
1135
  }
903
1136
  },
904
1137
  "copilot": {
905
1138
  "id": "copilot",
906
1139
  "role": "runtime",
907
- "version": "1.7.0",
1140
+ "version": "1.9.0",
908
1141
  "title": "GitHub Copilot",
909
1142
  "description": "GitHub Copilot (VS Code) — markdown config format; copilot-inline hook surface; no hook events emitted; flat skill nesting (unconfirmed recursive loader); tier-2 support.",
910
1143
  "tier": "core",
@@ -978,13 +1211,15 @@ const capabilities = {
978
1211
  "maxDepth": 1,
979
1212
  "background": true,
980
1213
  "subagentToolkit": "full",
981
- "backgroundDispatch": false
1214
+ "backgroundDispatch": false,
1215
+ "isolation": "undocumented"
982
1216
  },
983
1217
  "modelMode": "passive",
984
1218
  "hookBus": "host",
985
1219
  "stateIO": "filesystem",
986
1220
  "transport": "mcp",
987
- "runtime": "undocumented"
1221
+ "runtime": "undocumented",
1222
+ "effortSurface": "undocumented"
988
1223
  },
989
1224
  "hostBehaviors": {
990
1225
  "reapplyCommand": "/gsd-update --reapply",
@@ -997,7 +1232,7 @@ const capabilities = {
997
1232
  "cursor": {
998
1233
  "id": "cursor",
999
1234
  "role": "runtime",
1000
- "version": "1.7.0",
1235
+ "version": "1.9.0",
1001
1236
  "title": "Cursor",
1002
1237
  "description": "Cursor IDE — skills + converted commands artifact layout; hooks.json surface; Claude hook event dialect; recursive skill loader (flat nesting); tier-2 support.",
1003
1238
  "tier": "core",
@@ -1087,14 +1322,17 @@ const capabilities = {
1087
1322
  "maxDepth": 2,
1088
1323
  "background": true,
1089
1324
  "subagentToolkit": "full",
1090
- "backgroundDispatch": true
1325
+ "backgroundDispatch": true,
1326
+ "isolation": "harness-worktree"
1091
1327
  },
1092
1328
  "modelMode": "passive",
1093
1329
  "hookBus": "host",
1094
1330
  "stateIO": "filesystem",
1095
1331
  "transport": "mcp",
1096
- "runtime": "node"
1332
+ "runtime": "node",
1333
+ "effortSurface": "undocumented"
1097
1334
  },
1335
+ "harnessIsolationFlag": "--worktree",
1098
1336
  "hostBehaviors": {
1099
1337
  "reapplyCommand": "gsd-update --reapply (mention the skill name)",
1100
1338
  "frontmatterDialect": "cursor",
@@ -1113,12 +1351,47 @@ const capabilities = {
1113
1351
  ],
1114
1352
  "reviewerCli": true
1115
1353
  }
1354
+ },
1355
+ "reviewer": {
1356
+ "slug": "cursor",
1357
+ "flags": [
1358
+ "--cursor"
1359
+ ],
1360
+ "transport": "spawn",
1361
+ "probe": {
1362
+ "kind": "command-exists",
1363
+ "binary": "cursor-agent"
1364
+ },
1365
+ "invoke": {
1366
+ "binary": "cursor-agent",
1367
+ "args": [
1368
+ "-p",
1369
+ "--mode",
1370
+ "ask",
1371
+ "--trust",
1372
+ "--output-format",
1373
+ "text",
1374
+ "{{prompt}}"
1375
+ ],
1376
+ "promptChannel": "argv-file-ref",
1377
+ "outputChannel": "stdout",
1378
+ "modelArg": null,
1379
+ "effortChannel": "none"
1380
+ },
1381
+ "timeoutFloorMs": 900000,
1382
+ "emptyOutput": "stub-with-stderr",
1383
+ "reviewsSection": "Cursor",
1384
+ "evidenceClass": "source-grounded",
1385
+ "requiresBinaries": [],
1386
+ "promptBudgetKey": null,
1387
+ "modelConfigKey": null,
1388
+ "handler": null
1116
1389
  }
1117
1390
  },
1118
1391
  "drift": {
1119
1392
  "id": "drift",
1120
1393
  "role": "feature",
1121
- "version": "1.7.0",
1394
+ "version": "1.9.0",
1122
1395
  "title": "Drift detection gates",
1123
1396
  "description": "Drift detection gates for the planning loop. At execute:wave:post: a blocking schema drift gate (detects schema files changed without a database push) and a non-blocking codebase drift gate (detects structural additions not reflected in STRUCTURE.md). At plan:pre: a non-blocking, warn-only codebase drift gate (gated on workflow.plan_drift_precheck) that flags a stale codebase map before planning, so plans are authored against a fresh STRUCTURE.md instead of discovering drift mid-execution.",
1124
1397
  "tier": "full",
@@ -1196,7 +1469,7 @@ const capabilities = {
1196
1469
  "external-job": {
1197
1470
  "id": "external-job",
1198
1471
  "role": "feature",
1199
- "version": "1.7.0",
1472
+ "version": "1.9.0",
1200
1473
  "title": "Async external-job scheduler adapter",
1201
1474
  "description": "Default-off producer of the async external-job manifest (#1164). At execute:wave:post an executor can externalize long-running compute (SLURM first, scheduler-pluggable), commit a .planning/async-jobs/<job>.json manifest, defer SUMMARY.md, and return external_job_waiting. The core loop (#1165) consumes the manifest; this capability is the only thing that writes it. NOTE on contribution point: #1164 specifies execute:wave:pre, but execute-phase.md only dispatches execute:wave:post today (wave:pre is declared in the loop host contract but not rendered); wiring wave:pre dispatch is a core-loop change #1164 explicitly puts out of scope, so this capability registers at wave:post and the executor honors the runtime_budget classification guidance before running any tagged task. The adapter (scripts/slurm-adapter.cjs) reads external_job.submit_timeout_ms / poll_timeout_ms / artifact_dir through the canonical capability-config seam (env override > config > registry default).",
1202
1475
  "tier": "full",
@@ -1279,7 +1552,7 @@ const capabilities = {
1279
1552
  "gap-analysis": {
1280
1553
  "id": "gap-analysis",
1281
1554
  "role": "feature",
1282
- "version": "1.7.0",
1555
+ "version": "1.9.0",
1283
1556
  "title": "Post-planning gap analysis",
1284
1557
  "description": "Proactive, non-blocking post-planning coverage report. After all PLAN.md files are generated, cross-references every REQ-ID and D-ID from REQUIREMENTS.md and CONTEXT.md against plan bodies. Emits a Source | Item | Status table. Does not block phase advancement.",
1285
1558
  "tier": "standard",
@@ -1317,10 +1590,60 @@ const capabilities = {
1317
1590
  }
1318
1591
  ]
1319
1592
  },
1593
+ "gemini": {
1594
+ "id": "gemini",
1595
+ "role": "reviewer",
1596
+ "version": "1.9.0",
1597
+ "title": "Gemini CLI",
1598
+ "description": "Google Gemini CLI — cross-AI /gsd:review reviewer lane only; not a GSD install target (no runtime body, no artifacts). Spawned as `gemini -p - -m <model>` with the plan piped on stdin.",
1599
+ "tier": "full",
1600
+ "requires": [],
1601
+ "engines": {
1602
+ "gsd": ">=1.8.0"
1603
+ },
1604
+ "reviewer": {
1605
+ "slug": "gemini",
1606
+ "flags": [
1607
+ "--gemini"
1608
+ ],
1609
+ "transport": "spawn",
1610
+ "probe": {
1611
+ "kind": "command-exists",
1612
+ "binary": "gemini"
1613
+ },
1614
+ "invoke": {
1615
+ "binary": "gemini",
1616
+ "args": [
1617
+ "{{model}}",
1618
+ "-p",
1619
+ "-"
1620
+ ],
1621
+ "promptChannel": "stdin",
1622
+ "outputChannel": "stdout",
1623
+ "modelArg": "-m",
1624
+ "effortChannel": "none"
1625
+ },
1626
+ "timeoutFloorMs": 900000,
1627
+ "emptyOutput": "stub-with-stderr",
1628
+ "reviewsSection": "Gemini",
1629
+ "evidenceClass": "source-grounded",
1630
+ "requiresBinaries": [],
1631
+ "promptBudgetKey": null,
1632
+ "modelConfigKey": "review.models.gemini",
1633
+ "handler": null
1634
+ },
1635
+ "config": {
1636
+ "review.models.gemini": {
1637
+ "type": "string",
1638
+ "default": "",
1639
+ "description": "Model passed to the Gemini reviewer lane."
1640
+ }
1641
+ }
1642
+ },
1320
1643
  "graphify": {
1321
1644
  "id": "graphify",
1322
1645
  "role": "feature",
1323
- "version": "1.7.0",
1646
+ "version": "1.9.0",
1324
1647
  "title": "Knowledge graph",
1325
1648
  "description": "Build, query, and inspect the project knowledge graph in `.planning/graphs/`; exposes graphify CLI subcommands (build, query, status, diff) and the /gsd-graphify skill.",
1326
1649
  "tier": "full",
@@ -1361,7 +1684,7 @@ const capabilities = {
1361
1684
  "hermes": {
1362
1685
  "id": "hermes",
1363
1686
  "role": "runtime",
1364
- "version": "1.7.0",
1687
+ "version": "1.9.0",
1365
1688
  "title": "Hermes Agent",
1366
1689
  "description": "Hermes Agent (NousResearch) — skills nest under skills/gsd/ category bucket; nested skill layout; settings-json hook surface; Claude hook event dialect; tier-2 support.",
1367
1690
  "tier": "core",
@@ -1437,20 +1760,22 @@ const capabilities = {
1437
1760
  "maxDepth": 1,
1438
1761
  "background": true,
1439
1762
  "subagentToolkit": "read-only",
1440
- "backgroundDispatch": false
1763
+ "backgroundDispatch": false,
1764
+ "isolation": "undocumented"
1441
1765
  },
1442
1766
  "modelMode": "active",
1443
1767
  "hookBus": "host",
1444
1768
  "stateIO": "filesystem",
1445
1769
  "transport": "mcp",
1446
- "runtime": "python"
1770
+ "runtime": "python",
1771
+ "effortSurface": "undocumented"
1447
1772
  }
1448
1773
  }
1449
1774
  },
1450
1775
  "intel": {
1451
1776
  "id": "intel",
1452
1777
  "role": "feature",
1453
- "version": "1.7.0",
1778
+ "version": "1.9.0",
1454
1779
  "title": "Codebase intelligence",
1455
1780
  "description": "Code-intelligence store for codebase querying, diff, snapshot, and API-surface extraction; exposes `gsd-tools intel` subcommands (query, status, update, diff, snapshot, patch-meta, validate, extract-exports, api-surface) and backs `/gsd-map-codebase` and `gsd-intel-updater`.",
1456
1781
  "tier": "full",
@@ -1502,7 +1827,7 @@ const capabilities = {
1502
1827
  "kilo": {
1503
1828
  "id": "kilo",
1504
1829
  "role": "runtime",
1505
- "version": "1.7.0",
1830
+ "version": "1.9.0",
1506
1831
  "title": "Kilo Code",
1507
1832
  "description": "Kilo Code — XDG-based config dir; global skills at ~/.kilo/skills (separate from XDG config); flat command/ + skills artifact layout; no lifecycle hook registration; tier-2 support.",
1508
1833
  "tier": "core",
@@ -1583,13 +1908,15 @@ const capabilities = {
1583
1908
  "maxDepth": -1,
1584
1909
  "background": true,
1585
1910
  "subagentToolkit": "undocumented",
1586
- "backgroundDispatch": false
1911
+ "backgroundDispatch": false,
1912
+ "isolation": "undocumented"
1587
1913
  },
1588
1914
  "modelMode": "active",
1589
1915
  "hookBus": "host",
1590
1916
  "stateIO": "filesystem",
1591
1917
  "transport": "mcp",
1592
- "runtime": "bun"
1918
+ "runtime": "bun",
1919
+ "effortSurface": "undocumented"
1593
1920
  },
1594
1921
  "hostBehaviors": {
1595
1922
  "reapplyCommand": "/gsd-update --reapply",
@@ -1602,15 +1929,14 @@ const capabilities = {
1602
1929
  "file": "gsd-core.js",
1603
1930
  "source": ".kilo/plugins/gsd-core.js"
1604
1931
  },
1605
- "skipUpdateBannerCommand": true,
1606
- "skipSharedHooksInstall": true
1932
+ "skipUpdateBannerCommand": true
1607
1933
  }
1608
1934
  }
1609
1935
  },
1610
1936
  "kimi": {
1611
1937
  "id": "kimi",
1612
1938
  "role": "runtime",
1613
- "version": "1.7.0",
1939
+ "version": "1.9.0",
1614
1940
  "title": "Kimi CLI",
1615
1941
  "description": "Kimi CLI (Moonshot AI) — generic agents root at ~/.config/agents; skills + kimi-agents artifact layout; native config.toml [[hooks]] bus at ~/.kimi/config.toml; background dispatch; tier-2 support.",
1616
1942
  "tier": "core",
@@ -1677,13 +2003,23 @@ const capabilities = {
1677
2003
  "maxDepth": 1,
1678
2004
  "background": true,
1679
2005
  "subagentToolkit": "undocumented",
1680
- "backgroundDispatch": true
2006
+ "backgroundDispatch": true,
2007
+ "isolation": "orchestrator-worktree"
1681
2008
  },
1682
2009
  "modelMode": "passive",
1683
2010
  "hookBus": "host",
1684
2011
  "stateIO": "filesystem",
1685
2012
  "transport": "mcp",
1686
- "runtime": "python"
2013
+ "runtime": "python",
2014
+ "effortSurface": "undocumented"
2015
+ },
2016
+ "orchestratorExec": {
2017
+ "command": "kimi",
2018
+ "args": [
2019
+ "--print"
2020
+ ],
2021
+ "cwdFlag": "--work-dir",
2022
+ "promptFlag": "--prompt"
1687
2023
  },
1688
2024
  "hostBehaviors": {
1689
2025
  "reapplyCommand": "/skill:gsd-update --reapply",
@@ -1695,10 +2031,258 @@ const capabilities = {
1695
2031
  }
1696
2032
  }
1697
2033
  },
2034
+ "kimi-code": {
2035
+ "id": "kimi-code",
2036
+ "role": "runtime",
2037
+ "version": "1.9.0",
2038
+ "title": "Kimi Code CLI",
2039
+ "description": "Kimi Code CLI (Moonshot AI, Node) — Agent Skills auto-discovered at ~/.kimi-code/skills; global AGENTS.md at ~/.kimi-code/AGENTS.md; native config.toml + [[hooks]] bus; three built-in subagents (coder/explore/plan), NO custom named subagents; background dispatch; tier-2 support. Distinct from Python kimi-cli (the 'kimi' capability) per ADR-1239 EoS — Kimi Code cannot dispatch named subagents so the kimi-agents YAML layout does NOT apply; persona injection rides the existing ${AGENT_SKILLS_*} workflow fallback. Install-layout, agent-install-check, and install-time decision (kimi vs kimi-code) land in follow-up PRs; this descriptor is the EoS foundation.",
2040
+ "tier": "core",
2041
+ "requires": [],
2042
+ "engines": {
2043
+ "gsd": ">=1.7.0"
2044
+ },
2045
+ "runtime": {
2046
+ "configHome": {
2047
+ "kind": "dot-home",
2048
+ "name": ".kimi-code",
2049
+ "env": [
2050
+ "KIMI_CODE_HOME"
2051
+ ],
2052
+ "probe": [
2053
+ "~/.kimi-code"
2054
+ ],
2055
+ "probeExists": "config.toml"
2056
+ },
2057
+ "localConfigDir": ".kimi-code",
2058
+ "configFormat": "none",
2059
+ "artifactLayout": {
2060
+ "global": [
2061
+ {
2062
+ "kind": "skills",
2063
+ "destSubpath": "skills",
2064
+ "prefix": "gsd-",
2065
+ "nesting": "flat",
2066
+ "recursive": false,
2067
+ "converter": "convertClaudeCommandToKimiCodeSkill"
2068
+ }
2069
+ ],
2070
+ "local": []
2071
+ },
2072
+ "commandStyle": "slash-hyphen",
2073
+ "hooksSurface": "kimi-hooks-toml",
2074
+ "hookEvents": "claude",
2075
+ "sandboxTier": "none",
2076
+ "supportTier": 2,
2077
+ "installSurface": "profile-marker-only",
2078
+ "writesSharedSettings": false,
2079
+ "permissionWriter": null,
2080
+ "extendedHookEvents": [
2081
+ "SubagentStop",
2082
+ "Stop",
2083
+ "PreCompact",
2084
+ "SubagentStart"
2085
+ ],
2086
+ "hostIntegration": {
2087
+ "embeddingMode": "declarative",
2088
+ "commandSurface": "slash-file",
2089
+ "dispatch": {
2090
+ "namedDispatch": false,
2091
+ "nested": true,
2092
+ "maxDepth": "undocumented",
2093
+ "background": true,
2094
+ "subagentToolkit": "built-in-only",
2095
+ "backgroundDispatch": true,
2096
+ "builtInSubagents": [
2097
+ "coder",
2098
+ "explore",
2099
+ "plan"
2100
+ ],
2101
+ "isolation": "orchestrator-worktree"
2102
+ },
2103
+ "modelMode": "passive",
2104
+ "hookBus": "host",
2105
+ "stateIO": "filesystem",
2106
+ "transport": "mcp",
2107
+ "runtime": "node"
2108
+ },
2109
+ "orchestratorExec": {
2110
+ "command": "kimi",
2111
+ "args": [],
2112
+ "cwdFlag": null,
2113
+ "promptFlag": "--prompt"
2114
+ },
2115
+ "hostBehaviors": {
2116
+ "reapplyCommand": "/skill:gsd-update --reapply",
2117
+ "localInstallDeferred": true,
2118
+ "verificationStyle": "kimi-code",
2119
+ "agentManifestStyle": "none",
2120
+ "doneBannerStyle": "kimi-code",
2121
+ "skipSharedHooksInstall": true,
2122
+ "namedSubagentsSupported": false
2123
+ }
2124
+ },
2125
+ "reviewer": {
2126
+ "slug": "kimi-code",
2127
+ "flags": [
2128
+ "--kimi-code"
2129
+ ],
2130
+ "transport": "spawn",
2131
+ "probe": {
2132
+ "kind": "command-capability",
2133
+ "binary": "kimi",
2134
+ "needle": "--output-format",
2135
+ "timeoutMs": 5000
2136
+ },
2137
+ "invoke": {
2138
+ "binary": "kimi",
2139
+ "args": [
2140
+ "{{model}}",
2141
+ "-p",
2142
+ "{{prompt}}"
2143
+ ],
2144
+ "promptChannel": "argv-file-ref",
2145
+ "outputChannel": "stdout",
2146
+ "modelArg": "-m",
2147
+ "effortChannel": "none"
2148
+ },
2149
+ "timeoutFloorMs": 900000,
2150
+ "emptyOutput": "stub-with-stderr",
2151
+ "reviewsSection": "Kimi Code",
2152
+ "evidenceClass": "source-grounded",
2153
+ "requiresBinaries": [],
2154
+ "promptBudgetKey": null,
2155
+ "modelConfigKey": "review.models.kimi-code",
2156
+ "handler": null
2157
+ },
2158
+ "config": {
2159
+ "review.models.kimi-code": {
2160
+ "type": "string",
2161
+ "default": "",
2162
+ "description": "Model passed to the Kimi Code reviewer lane."
2163
+ }
2164
+ }
2165
+ },
2166
+ "llama-cpp": {
2167
+ "id": "llama-cpp",
2168
+ "role": "reviewer",
2169
+ "version": "1.9.0",
2170
+ "title": "llama.cpp",
2171
+ "description": "llama.cpp server — cross-AI /gsd:review reviewer lane only; not a GSD install target (no runtime body, no artifacts). OpenAI-compatible HTTP transport against a user-configured `review.llama_cpp_host` (POST /v1/chat/completions); model discovered via GET /v1/models piped through jq. Capability id/folder are kebab (`llama-cpp`, required by KEBAB_RE); `reviewer.slug` stays snake (`llama_cpp`) to match the shipped roster and the `review.llama_cpp_host` config key (ADR-2782's three-namespace trap).",
2172
+ "tier": "full",
2173
+ "requires": [],
2174
+ "engines": {
2175
+ "gsd": ">=1.8.0"
2176
+ },
2177
+ "reviewer": {
2178
+ "slug": "llama_cpp",
2179
+ "flags": [
2180
+ "--llama-cpp"
2181
+ ],
2182
+ "transport": "openai-http",
2183
+ "probe": {
2184
+ "kind": "http-reachable",
2185
+ "hostConfigKey": "review.llama_cpp_host",
2186
+ "path": "/v1/models",
2187
+ "timeoutMs": 2000
2188
+ },
2189
+ "invoke": {
2190
+ "hostConfigKey": "review.llama_cpp_host",
2191
+ "defaultHost": "http://localhost:8080",
2192
+ "path": "/v1/chat/completions",
2193
+ "modelDiscovery": "first-from-models-endpoint",
2194
+ "fallbackModel": "local-model",
2195
+ "effortChannel": "none"
2196
+ },
2197
+ "timeoutFloorMs": 120000,
2198
+ "emptyOutput": "stub-with-stderr",
2199
+ "reviewsSection": "llama.cpp",
2200
+ "evidenceClass": "source-grounded",
2201
+ "requiresBinaries": [],
2202
+ "promptBudgetKey": "review.max_prompt_tokens_per_reviewer.llama_cpp",
2203
+ "modelConfigKey": "review.models.llama_cpp",
2204
+ "handler": "openai-compatible"
2205
+ },
2206
+ "config": {
2207
+ "review.models.llama_cpp": {
2208
+ "type": "string",
2209
+ "default": "",
2210
+ "description": "Model requested from the llama.cpp reviewer lane; empty discovers the first model from /v1/models."
2211
+ },
2212
+ "review.llama_cpp_host": {
2213
+ "type": "string",
2214
+ "default": "",
2215
+ "description": "Base URL of the llama.cpp OpenAI-compatible server."
2216
+ },
2217
+ "review.max_prompt_tokens_per_reviewer.llama_cpp": {
2218
+ "type": "number",
2219
+ "default": -1,
2220
+ "description": "Prompt-token budget for the llama.cpp reviewer lane. Unset is -1, a sentinel: 0 is a legitimate value meaning \"do not trim this lane\", so it cannot double as \"not configured\"."
2221
+ }
2222
+ }
2223
+ },
2224
+ "lm-studio": {
2225
+ "id": "lm-studio",
2226
+ "role": "reviewer",
2227
+ "version": "1.9.0",
2228
+ "title": "LM Studio",
2229
+ "description": "LM Studio local model server — cross-AI /gsd:review reviewer lane only; not a GSD install target (no runtime body, no artifacts). OpenAI-compatible HTTP transport against a user-configured `review.lm_studio_host` (POST /v1/chat/completions); model discovered via GET /v1/models piped through jq. Capability id/folder are kebab (`lm-studio`, required by KEBAB_RE); `reviewer.slug` stays snake (`lm_studio`) to match the shipped roster and the `review.lm_studio_host` config key (ADR-2782's three-namespace trap).",
2230
+ "tier": "full",
2231
+ "requires": [],
2232
+ "engines": {
2233
+ "gsd": ">=1.8.0"
2234
+ },
2235
+ "reviewer": {
2236
+ "slug": "lm_studio",
2237
+ "flags": [
2238
+ "--lm-studio"
2239
+ ],
2240
+ "transport": "openai-http",
2241
+ "probe": {
2242
+ "kind": "http-reachable",
2243
+ "hostConfigKey": "review.lm_studio_host",
2244
+ "path": "/v1/models",
2245
+ "timeoutMs": 2000
2246
+ },
2247
+ "invoke": {
2248
+ "hostConfigKey": "review.lm_studio_host",
2249
+ "defaultHost": "http://localhost:1234",
2250
+ "path": "/v1/chat/completions",
2251
+ "modelDiscovery": "first-from-models-endpoint",
2252
+ "fallbackModel": "local-model",
2253
+ "effortChannel": "none"
2254
+ },
2255
+ "timeoutFloorMs": 120000,
2256
+ "emptyOutput": "stub-with-stderr",
2257
+ "reviewsSection": "LM Studio",
2258
+ "evidenceClass": "source-grounded",
2259
+ "requiresBinaries": [],
2260
+ "promptBudgetKey": "review.max_prompt_tokens_per_reviewer.lm_studio",
2261
+ "modelConfigKey": "review.models.lm_studio",
2262
+ "handler": "openai-compatible"
2263
+ },
2264
+ "config": {
2265
+ "review.models.lm_studio": {
2266
+ "type": "string",
2267
+ "default": "",
2268
+ "description": "Model requested from the LM Studio reviewer lane; empty discovers the first model from /v1/models."
2269
+ },
2270
+ "review.lm_studio_host": {
2271
+ "type": "string",
2272
+ "default": "",
2273
+ "description": "Base URL of the LM Studio OpenAI-compatible server."
2274
+ },
2275
+ "review.max_prompt_tokens_per_reviewer.lm_studio": {
2276
+ "type": "number",
2277
+ "default": -1,
2278
+ "description": "Prompt-token budget for the LM Studio reviewer lane. Unset is -1, a sentinel: 0 is a legitimate value meaning \"do not trim this lane\", so it cannot double as \"not configured\"."
2279
+ }
2280
+ }
2281
+ },
1698
2282
  "mempalace": {
1699
2283
  "id": "mempalace",
1700
2284
  "role": "feature",
1701
- "version": "1.7.0",
2285
+ "version": "1.9.0",
1702
2286
  "title": "MemPalace memory",
1703
2287
  "description": "Cross-session, cross-project memory: deliberate recall before discuss/plan and verbatim capture + temporal-KG sync at phase boundaries, via the MemPalace MCP server and CLI.",
1704
2288
  "tier": "full",
@@ -1872,7 +2456,7 @@ const capabilities = {
1872
2456
  "nyquist": {
1873
2457
  "id": "nyquist",
1874
2458
  "role": "feature",
1875
- "version": "1.7.0",
2459
+ "version": "1.9.0",
1876
2460
  "title": "Nyquist validation",
1877
2461
  "description": "Validation coverage audit that maps executed work back to tests and manual-only evidence.",
1878
2462
  "tier": "full",
@@ -1919,12 +2503,70 @@ const capabilities = {
1919
2503
  "contributions": [],
1920
2504
  "gates": []
1921
2505
  },
2506
+ "ollama": {
2507
+ "id": "ollama",
2508
+ "role": "reviewer",
2509
+ "version": "1.9.0",
2510
+ "title": "Ollama",
2511
+ "description": "Ollama local model server — cross-AI /gsd:review reviewer lane only; not a GSD install target (no runtime body, no artifacts). OpenAI-compatible HTTP transport against a user-configured `review.ollama_host` (POST /v1/chat/completions); model discovered via GET /v1/models piped through jq.",
2512
+ "tier": "full",
2513
+ "requires": [],
2514
+ "engines": {
2515
+ "gsd": ">=1.8.0"
2516
+ },
2517
+ "reviewer": {
2518
+ "slug": "ollama",
2519
+ "flags": [
2520
+ "--ollama"
2521
+ ],
2522
+ "transport": "openai-http",
2523
+ "probe": {
2524
+ "kind": "http-reachable",
2525
+ "hostConfigKey": "review.ollama_host",
2526
+ "path": "/v1/models",
2527
+ "timeoutMs": 2000
2528
+ },
2529
+ "invoke": {
2530
+ "hostConfigKey": "review.ollama_host",
2531
+ "defaultHost": "http://localhost:11434",
2532
+ "path": "/v1/chat/completions",
2533
+ "modelDiscovery": "first-from-models-endpoint",
2534
+ "fallbackModel": "llama3",
2535
+ "effortChannel": "none"
2536
+ },
2537
+ "timeoutFloorMs": 120000,
2538
+ "emptyOutput": "stub-with-stderr",
2539
+ "reviewsSection": "Ollama",
2540
+ "evidenceClass": "source-grounded",
2541
+ "requiresBinaries": [],
2542
+ "promptBudgetKey": "review.max_prompt_tokens_per_reviewer.ollama",
2543
+ "modelConfigKey": "review.models.ollama",
2544
+ "handler": "openai-compatible"
2545
+ },
2546
+ "config": {
2547
+ "review.models.ollama": {
2548
+ "type": "string",
2549
+ "default": "",
2550
+ "description": "Model requested from the Ollama reviewer lane; empty discovers the first model from /v1/models."
2551
+ },
2552
+ "review.ollama_host": {
2553
+ "type": "string",
2554
+ "default": "",
2555
+ "description": "Base URL of the Ollama OpenAI-compatible server."
2556
+ },
2557
+ "review.max_prompt_tokens_per_reviewer.ollama": {
2558
+ "type": "number",
2559
+ "default": -1,
2560
+ "description": "Prompt-token budget for the Ollama reviewer lane. Unset is -1, a sentinel: 0 is a legitimate value meaning \"do not trim this lane\", so it cannot double as \"not configured\"."
2561
+ }
2562
+ }
2563
+ },
1922
2564
  "opencode": {
1923
2565
  "id": "opencode",
1924
2566
  "role": "runtime",
1925
- "version": "1.7.0",
2567
+ "version": "1.9.0",
1926
2568
  "title": "OpenCode",
1927
- "description": "OpenCode — XDG-based config dir; flat command/ + skills artifact layout; settings-json config format; no lifecycle hook registration; tier-2 support.",
2569
+ "description": "OpenCode — XDG-based config dir; flat commands/ + skills artifact layout; settings-json config format; no lifecycle hook registration; tier-2 support.",
1928
2570
  "tier": "core",
1929
2571
  "requires": [],
1930
2572
  "engines": {
@@ -1946,7 +2588,7 @@ const capabilities = {
1946
2588
  "global": [
1947
2589
  {
1948
2590
  "kind": "commands",
1949
- "destSubpath": "command",
2591
+ "destSubpath": "commands",
1950
2592
  "prefix": "gsd-",
1951
2593
  "nesting": "flat",
1952
2594
  "recursive": false,
@@ -1964,7 +2606,7 @@ const capabilities = {
1964
2606
  "local": [
1965
2607
  {
1966
2608
  "kind": "commands",
1967
- "destSubpath": "command",
2609
+ "destSubpath": "commands",
1968
2610
  "prefix": "gsd-",
1969
2611
  "nesting": "flat",
1970
2612
  "recursive": false,
@@ -1996,20 +2638,30 @@ const capabilities = {
1996
2638
  "namedDispatch": true,
1997
2639
  "nested": "undocumented",
1998
2640
  "maxDepth": "undocumented",
1999
- "background": true,
2641
+ "background": false,
2000
2642
  "subagentToolkit": "full",
2001
- "backgroundDispatch": true
2643
+ "backgroundDispatch": false,
2644
+ "isolation": "orchestrator-worktree"
2002
2645
  },
2003
2646
  "modelMode": "active",
2004
2647
  "hookBus": "host",
2005
2648
  "stateIO": "filesystem",
2006
2649
  "transport": "mcp",
2007
- "runtime": "bun"
2650
+ "runtime": "bun",
2651
+ "effortSurface": "argv"
2652
+ },
2653
+ "orchestratorExec": {
2654
+ "command": "opencode",
2655
+ "args": [
2656
+ "run"
2657
+ ],
2658
+ "cwdFlag": "--dir",
2659
+ "promptFlag": null
2008
2660
  },
2009
2661
  "hostBehaviors": {
2010
2662
  "reapplyCommand": "/gsd-update --reapply",
2011
2663
  "attributionConfigResolver": "opencode",
2012
- "flatCommandDir": "command",
2664
+ "flatCommandDir": "commands",
2013
2665
  "combinedFamilyInstall": true,
2014
2666
  "frontmatterDialect": "opencode",
2015
2667
  "nativePlugin": {
@@ -2023,12 +2675,53 @@ const capabilities = {
2023
2675
  "skipCodexSkillsManifest": true,
2024
2676
  "reviewerCli": true
2025
2677
  }
2678
+ },
2679
+ "reviewer": {
2680
+ "slug": "opencode",
2681
+ "flags": [
2682
+ "--opencode"
2683
+ ],
2684
+ "transport": "spawn",
2685
+ "probe": {
2686
+ "kind": "command-exists",
2687
+ "binary": "opencode"
2688
+ },
2689
+ "invoke": {
2690
+ "binary": "opencode",
2691
+ "args": [
2692
+ "run",
2693
+ "{{model}}",
2694
+ "{{effort}}",
2695
+ "--format",
2696
+ "json",
2697
+ "-"
2698
+ ],
2699
+ "promptChannel": "stdin",
2700
+ "outputChannel": "stdout",
2701
+ "modelArg": "--model",
2702
+ "effortChannel": "argv"
2703
+ },
2704
+ "timeoutFloorMs": 660000,
2705
+ "emptyOutput": "stub-with-stderr",
2706
+ "reviewsSection": "OpenCode",
2707
+ "evidenceClass": "source-grounded",
2708
+ "requiresBinaries": [],
2709
+ "promptBudgetKey": null,
2710
+ "modelConfigKey": "review.models.opencode",
2711
+ "handler": "opencode"
2712
+ },
2713
+ "config": {
2714
+ "review.models.opencode": {
2715
+ "type": "string",
2716
+ "default": "",
2717
+ "description": "Model passed to the OpenCode reviewer lane."
2718
+ }
2026
2719
  }
2027
2720
  },
2028
2721
  "pattern-mapper": {
2029
2722
  "id": "pattern-mapper",
2030
2723
  "role": "feature",
2031
- "version": "1.7.0",
2724
+ "version": "1.9.0",
2032
2725
  "title": "Pattern mapping",
2033
2726
  "description": "Optional codebase-pattern mapping before planning; owns the pattern mapper agent and workflow.pattern_mapper activation key.",
2034
2727
  "tier": "full",
@@ -2082,9 +2775,9 @@ const capabilities = {
2082
2775
  "pi": {
2083
2776
  "id": "pi",
2084
2777
  "role": "runtime",
2085
- "version": "1.7.0",
2778
+ "version": "1.9.0",
2086
2779
  "title": "pi",
2087
- "description": "pi (pi.dev) — bun-runtime programmatic-CLI; TS ExtensionAPI (registerCommand/registerTool/registerProvider/pi.on); single native-extension file at ~/.pi/agent/extensions/gsd.cjs; no shared-settings hook surface; tier-2 support.",
2780
+ "description": "pi (pi.dev) — bun-runtime programmatic-CLI; TS ExtensionAPI (registerCommand/registerTool/registerProvider/pi.on); single native-extension file at ~/.pi/agent/extensions/gsd.js (.js, not .cjs — pi's extension auto-discovery accepts only .ts/.js, #2470); no shared-settings hook surface; tier-2 support.",
2088
2781
  "tier": "core",
2089
2782
  "requires": [],
2090
2783
  "engines": {
@@ -2121,18 +2814,20 @@ const capabilities = {
2121
2814
  "maxDepth": 0,
2122
2815
  "background": false,
2123
2816
  "backgroundDispatch": false,
2124
- "subagentToolkit": "undocumented"
2817
+ "subagentToolkit": "undocumented",
2818
+ "isolation": "none"
2125
2819
  },
2126
2820
  "modelMode": "active",
2127
2821
  "hookBus": "host",
2128
2822
  "stateIO": "session-log-append",
2129
2823
  "transport": "native-extension",
2130
- "runtime": "bun"
2824
+ "runtime": "bun",
2825
+ "effortSurface": "undocumented"
2131
2826
  },
2132
2827
  "hostBehaviors": {
2133
2828
  "nativePlugin": {
2134
2829
  "dir": "extensions",
2135
- "file": "gsd.cjs",
2830
+ "file": "gsd.js",
2136
2831
  "source": "pi/gsd.cjs"
2137
2832
  },
2138
2833
  "pluginOnlyInstall": true
@@ -2142,7 +2837,7 @@ const capabilities = {
2142
2837
  "profile-pipeline": {
2143
2838
  "id": "profile-pipeline",
2144
2839
  "role": "feature",
2145
- "version": "1.7.0",
2840
+ "version": "1.9.0",
2146
2841
  "title": "Developer profiling pipeline",
2147
2842
  "description": "Developer behavioral profiling from Claude Code session history; scans session JSONL files, extracts and samples user messages, and generates profile artifacts (USER-PROFILE.md, dev-preferences.md, CLAUDE.md sections). Exposes eight `gsd-tools` commands: scan-sessions, extract-messages, profile-sample (pipeline phase) and write-profile, profile-questionnaire, generate-dev-preferences, generate-claude-profile, generate-claude-md (output phase). Backs the /gsd-profile-user skill and gsd-user-profiler agent.",
2148
2843
  "tier": "full",
@@ -2219,7 +2914,7 @@ const capabilities = {
2219
2914
  "qwen": {
2220
2915
  "id": "qwen",
2221
2916
  "role": "runtime",
2222
- "version": "1.7.0",
2917
+ "version": "1.9.0",
2223
2918
  "title": "Qwen Code",
2224
2919
  "description": "Qwen Code (Alibaba) — nested-skill artifact layout; settings-json hook surface; Claude hook event dialect; tier-2 support.",
2225
2920
  "tier": "core",
@@ -2298,13 +2993,15 @@ const capabilities = {
2298
2993
  "maxDepth": 1,
2299
2994
  "background": true,
2300
2995
  "subagentToolkit": "full",
2301
- "backgroundDispatch": false
2996
+ "backgroundDispatch": false,
2997
+ "isolation": "undocumented"
2302
2998
  },
2303
2999
  "modelMode": "passive",
2304
3000
  "hookBus": "host",
2305
3001
  "stateIO": "filesystem",
2306
3002
  "transport": "mcp",
2307
- "runtime": "node"
3003
+ "runtime": "node",
3004
+ "effortSurface": "undocumented"
2308
3005
  },
2309
3006
  "hostBehaviors": {
2310
3007
  "skillPriorityFrontmatter": true,
@@ -2319,12 +3016,41 @@ const capabilities = {
2319
3016
  "hyphenNameAgentBody": true,
2320
3017
  "reviewerCli": true
2321
3018
  }
3019
+ },
3020
+ "reviewer": {
3021
+ "slug": "qwen",
3022
+ "flags": [
3023
+ "--qwen"
3024
+ ],
3025
+ "transport": "spawn",
3026
+ "probe": {
3027
+ "kind": "command-exists",
3028
+ "binary": "qwen"
3029
+ },
3030
+ "invoke": {
3031
+ "binary": "qwen",
3032
+ "args": [
3033
+ "-"
3034
+ ],
3035
+ "promptChannel": "stdin",
3036
+ "outputChannel": "stdout",
3037
+ "modelArg": null,
3038
+ "effortChannel": "none"
3039
+ },
3040
+ "timeoutFloorMs": 900000,
3041
+ "emptyOutput": "stub-with-stderr",
3042
+ "reviewsSection": "Qwen",
3043
+ "evidenceClass": "source-grounded",
3044
+ "requiresBinaries": [],
3045
+ "promptBudgetKey": null,
3046
+ "modelConfigKey": null,
3047
+ "handler": null
2322
3048
  }
2323
3049
  },
2324
3050
  "research": {
2325
3051
  "id": "research",
2326
3052
  "role": "feature",
2327
- "version": "1.7.0",
3053
+ "version": "1.9.0",
2328
3054
  "title": "Phase research",
2329
3055
  "description": "Optional phase research before planning; owns the phase researcher agent and workflow.research activation key.",
2330
3056
  "tier": "standard",
@@ -2376,7 +3102,7 @@ const capabilities = {
2376
3102
  "schema-gate": {
2377
3103
  "id": "schema-gate",
2378
3104
  "role": "feature",
2379
- "version": "1.7.0",
3105
+ "version": "1.9.0",
2380
3106
  "title": "Schema push detection gate",
2381
3107
  "description": "Detects ORM schema-relevant files in the phase scope during planning and injects a mandatory [BLOCKING] schema push task into the plan. Prevents false-positive verification where build/types pass because TypeScript types come from config, not the live database.",
2382
3108
  "tier": "full",
@@ -2422,7 +3148,7 @@ const capabilities = {
2422
3148
  "security": {
2423
3149
  "id": "security",
2424
3150
  "role": "feature",
2425
- "version": "1.7.0",
3151
+ "version": "1.9.0",
2426
3152
  "title": "Security enforcement",
2427
3153
  "description": "Threat mitigation verification and ship-time security blocking for phases with security enforcement enabled.",
2428
3154
  "tier": "full",
@@ -2521,7 +3247,7 @@ const capabilities = {
2521
3247
  "tdd": {
2522
3248
  "id": "tdd",
2523
3249
  "role": "feature",
2524
- "version": "1.7.0",
3250
+ "version": "1.9.0",
2525
3251
  "title": "Test-driven development",
2526
3252
  "description": "Injects TDD heuristics into the planner and enforces RED/GREEN gate compliance on type:tdd plans after execution. Owns workflow.tdd_mode; the --tdd CLI flag is the ephemeral override.",
2527
3253
  "tier": "full",
@@ -2574,7 +3300,7 @@ const capabilities = {
2574
3300
  "trae": {
2575
3301
  "id": "trae",
2576
3302
  "role": "runtime",
2577
- "version": "1.7.0",
3303
+ "version": "1.9.0",
2578
3304
  "title": "Trae IDE",
2579
3305
  "description": "Trae IDE — nested-skill artifact layout; no hook surface (profile-marker-only config); tier-2 support.",
2580
3306
  "tier": "core",
@@ -2647,13 +3373,15 @@ const capabilities = {
2647
3373
  "maxDepth": "undocumented",
2648
3374
  "background": true,
2649
3375
  "subagentToolkit": "undocumented",
2650
- "backgroundDispatch": "undocumented"
3376
+ "backgroundDispatch": "undocumented",
3377
+ "isolation": "undocumented"
2651
3378
  },
2652
3379
  "modelMode": "passive",
2653
3380
  "hookBus": "engine",
2654
3381
  "stateIO": "filesystem",
2655
3382
  "transport": "mcp",
2656
- "runtime": "node"
3383
+ "runtime": "node",
3384
+ "effortSurface": "undocumented"
2657
3385
  },
2658
3386
  "hostBehaviors": {
2659
3387
  "skipSharedHooksInstall": true,
@@ -2664,7 +3392,7 @@ const capabilities = {
2664
3392
  "ui": {
2665
3393
  "id": "ui",
2666
3394
  "role": "feature",
2667
- "version": "1.7.0",
3395
+ "version": "1.9.0",
2668
3396
  "title": "UI design contracts",
2669
3397
  "description": "UI-SPEC design contract + retrospective UI audit for frontend phases.",
2670
3398
  "tier": "full",
@@ -2759,7 +3487,7 @@ const capabilities = {
2759
3487
  "vscode": {
2760
3488
  "id": "vscode",
2761
3489
  "role": "runtime",
2762
- "version": "1.7.0",
3490
+ "version": "1.9.0",
2763
3491
  "title": "VS Code",
2764
3492
  "description": "VS Code — Marketplace/VSIX extension; no file-projected config directory; IDE-profile reference host (active vscode.lm model, engine-owned hook bus, sandboxed globalState/workspaceState stateIO).",
2765
3493
  "tier": "core",
@@ -2797,20 +3525,22 @@ const capabilities = {
2797
3525
  "maxDepth": 5,
2798
3526
  "background": true,
2799
3527
  "subagentToolkit": "undocumented",
2800
- "backgroundDispatch": "undocumented"
3528
+ "backgroundDispatch": "undocumented",
3529
+ "isolation": "undocumented"
2801
3530
  },
2802
3531
  "modelMode": "active",
2803
3532
  "hookBus": "engine",
2804
3533
  "stateIO": "sandboxed-storage",
2805
3534
  "transport": "mcp",
2806
- "runtime": "sandboxed-web"
3535
+ "runtime": "sandboxed-web",
3536
+ "effortSurface": "undocumented"
2807
3537
  }
2808
3538
  }
2809
3539
  },
2810
3540
  "windsurf": {
2811
3541
  "id": "windsurf",
2812
3542
  "role": "runtime",
2813
- "version": "1.7.0",
3543
+ "version": "1.9.0",
2814
3544
  "title": "Windsurf",
2815
3545
  "description": "Windsurf (Codeium) — workspace workflow artifact layout for slash commands; Cascade native hooks.json blocking hook bus (pre_write_code, pre_run_command); tier-2 support.",
2816
3546
  "tier": "core",
@@ -2876,13 +3606,15 @@ const capabilities = {
2876
3606
  "maxDepth": "undocumented",
2877
3607
  "background": "undocumented",
2878
3608
  "subagentToolkit": "undocumented",
2879
- "backgroundDispatch": "undocumented"
3609
+ "backgroundDispatch": "undocumented",
3610
+ "isolation": "none"
2880
3611
  },
2881
3612
  "modelMode": "passive",
2882
3613
  "hookBus": "host",
2883
3614
  "stateIO": "filesystem",
2884
3615
  "transport": "mcp",
2885
- "runtime": "undocumented"
3616
+ "runtime": "undocumented",
3617
+ "effortSurface": "undocumented"
2886
3618
  },
2887
3619
  "hostBehaviors": {
2888
3620
  "skipSharedHooksInstall": true,
@@ -2895,7 +3627,7 @@ const capabilities = {
2895
3627
  "zcode": {
2896
3628
  "id": "zcode",
2897
3629
  "role": "runtime",
2898
- "version": "1.7.0",
3630
+ "version": "1.9.0",
2899
3631
  "title": "ZCode",
2900
3632
  "description": "ZCode (Z.ai) — desktop Agentic Development Environment for GLM-5.2; Claude-shaped nested skills at ~/.zcode/skills/<name>/SKILL.md, slash commands, named subagents, native MCP; declarative plugin surface; profile-marker install; tier-2 community support.",
2901
3633
  "tier": "core",
@@ -2984,13 +3716,15 @@ const capabilities = {
2984
3716
  "maxDepth": "undocumented",
2985
3717
  "background": false,
2986
3718
  "subagentToolkit": "full",
2987
- "backgroundDispatch": false
3719
+ "backgroundDispatch": false,
3720
+ "isolation": "none"
2988
3721
  },
2989
3722
  "modelMode": "passive",
2990
3723
  "hookBus": "host",
2991
3724
  "stateIO": "filesystem",
2992
3725
  "transport": "mcp",
2993
- "runtime": "electron"
3726
+ "runtime": "electron",
3727
+ "effortSurface": "undocumented"
2994
3728
  },
2995
3729
  "hostBehaviors": {
2996
3730
  "skipSharedHooksInstall": true
@@ -3174,7 +3908,7 @@ const byLoopPoint = {
3174
3908
  "into": "planner",
3175
3909
  "fragment": {
3176
3910
  "path": "fragments/api-coverage-plan-pre.md",
3177
- "inline": "# API Coverage Decision Checkpoint\n\n> Full API Coverage by Default — Opt Out, Never Opt In. Fires when a phase\n> integrates an external API / SDK / service. Most non-API phases will not fire\n> it — that is the point.\n\n## Why this exists\n\n\"We integrated the API\" too often silently means \"we integrated whatever the\nfirst use case exercised.\" Every un-built capability is then an invisible hole,\ndiscovered later by a user who reasonably expected it to work. The phase sealed\ngreen because its tasks completed; nobody decided the gaps were acceptable,\nbecause nobody enumerated them. This checkpoint makes the surface **visible and\ndecided** before the phase can seal.\n\n## Detect whether this phase integrates an external API\n\nThe detector is a deterministic scan over the phase scope. It strips fenced\ncode blocks first, so a trigger term inside a code snippet does not fire. It\nreturns a typed result: `{ detected, signals[], terms }`. Run it on the phase\nscope (the concatenation of this phase's ROADMAP section + the PLAN body):\n\n```bash\nSCOPE=\"$(cat \"${PHASE_DIR}\"/*-PLAN.md 2>/dev/null) $(gsd_run query roadmap.get-phase \"${PHASE}\" 2>/dev/null || true)\"\nAPI_COVERAGE_JSON=$(printf '%s' \"$SCOPE\" | node gsd-core/bin/lib/api-coverage.cjs --json 2>/dev/null || echo '{\"detected\":false,\"signals\":[]}')\n```\n\nRead `API_COVERAGE_JSON.detected`. Act on it only — do **not** pattern-match the\nprose yourself.\n\n**If `detected` is `false`:** this phase does not integrate an external API. Skip\nthe checkpoint entirely and continue planning. Do not raise it with the user.\n\n**If `detected` is `true`:** an external-API integration is in scope. You MUST\nproduce a **coverage matrix** before the plan is finalized.\n\n## Produce the coverage matrix\n\nEnumerate the external API's full **capability surface** — the verb/endpoint/method\nlist (e.g. for a music service: `search`, `play`, `pause`, `skip`, `set_volume`,\n`get_playlist`, `create_playlist`, `add_to_playlist`, …). For each capability\nrecord a decision, starting from **full coverage** as the default:\n\n| capability | decision | reason |\n|---|---|---|\n| `<capability-id>` | `INTEGRATE` \\| `OPT-OUT` | `<one-line reason if OPT-OUT>` |\n\nRules:\n\n- **`INTEGRATE` is the default.** Every capability starts as INTEGRATE; the\n matrix is the *subtraction record*.\n- **Every `OPT-OUT` MUST carry a one-line reason** (`not needed`, `not needed\n yet`, `explicitly out of scope`, …). An opt-out without a reason is an\n un-decided hole — the exact failure mode this gate exists to close.\n- **A second integration against the same need** (e.g. a second platform for the\n same capability) starts from the **same full-coverage baseline** as the first.\n Do not carry over the first integration's opt-outs silently — re-decide each\n capability for the new surface, so a first-class/fallback asymmetry cannot\n accumulate.\n\nWrite the matrix to `${PHASE_DIR}/COVERAGE.md` (canonical markdown-table form):\n\n```markdown\n# API Coverage — <service>\n\n> Full coverage by default. Opt-outs are explicit, reasoned decisions.\n\n| capability | decision | reason |\n|---|---|---|\n| search | INTEGRATE | |\n| playlists | INTEGRATE | |\n| skip | OPT-OUT | not needed yet — tracked for follow-up phase |\n```\n\nA fenced ` ```coverage ` JSON block is also accepted for machine-generated\nmatrices; the markdown table is preferred (human-editable, diff-friendly).\n\n## The seal-time gate\n\nThis checkpoint is enforced. At `verify:pre` the `api-coverage.verify-pre` gate\nruns `check api-coverage.verify-pre <phase-dir>`:\n\n- If `COVERAGE.md` exists, it is validated — every row needs a valid decision and\n every `OPT-OUT` a reason. A malformed/partial matrix **blocks the seal**.\n- If `COVERAGE.md` is absent, the detector runs again over the phase scope. If a\n strong external-API-integration signal is found, the seal is **blocked** until a\n matrix is produced. If no signal is found, the phase is treated as a non-API\n phase and the seal proceeds.\n\nSo: an API-integrating phase cannot seal without a decided matrix. Produce it at\nplan time; do not leave it for seal time.\n\n## Tuning the vocabulary (optional)\n\nThe trigger vocabulary is a curated, additive-only set in\n`gsd-core/bin/lib/api-coverage.cjs` (`DEFAULT_API_COVERAGE_TERMS`). To widen it\nfor a project, override at the call site:\n\n```bash\nprintf '%s' \"$SCOPE\" | node gsd-core/bin/lib/api-coverage.cjs --json \\\n --verbs integrate,wrap,connect,embed --nouns api,sdk,rest,grpc,webhook,plugin\n```\n\nThe whole checkpoint is toggleable via `workflow.api_coverage_gate` in\n`.planning/config.json`.\n"
3911
+ "inline": "# API Coverage Decision Checkpoint\n\n> Full API Coverage by Default — Opt Out, Never Opt In. Fires when a phase\n> integrates an external API / SDK / service. Most non-API phases will not fire\n> it — that is the point.\n\n## Why this exists\n\n\"We integrated the API\" too often silently means \"we integrated whatever the\nfirst use case exercised.\" Every un-built capability is then an invisible hole,\ndiscovered later by a user who reasonably expected it to work. The phase sealed\ngreen because its tasks completed; nobody decided the gaps were acceptable,\nbecause nobody enumerated them. This checkpoint makes the surface **visible and\ndecided** before the phase can seal.\n\n## Detect whether this phase integrates an external API\n\nThe detector is a deterministic scan over the phase scope. It strips fenced\ncode blocks first, so a trigger term inside a code snippet does not fire. It\nreturns a typed result: `{ detected, signals[], terms }`. Run it on the phase\nscope (the concatenation of this phase's ROADMAP section + the PLAN body):\n\n```bash\nSCOPE=\"$(cat \"${PHASE_DIR}\"/*-PLAN.md 2>/dev/null) $(gsd_run query roadmap.get-phase \"${PHASE}\" 2>/dev/null || true)\"\nAPI_COVERAGE_JSON=$(printf '%s' \"$SCOPE\" | node gsd-core/bin/lib/api-coverage.cjs --json 2>/dev/null || echo '{\"detected\":false,\"signals\":[]}')\n```\n\nRead `API_COVERAGE_JSON.detected`. Act on it only — do **not** pattern-match the\nprose yourself.\n\n**If `detected` is `false`:** this phase does not integrate an external API. Skip\nthe checkpoint entirely and continue planning. Do not raise it with the user.\n\n**If `detected` is `true`:** an external-API integration is in scope. You MUST\nproduce a **coverage matrix** before the plan is finalized.\n\n**If `detected` is `true` but the phase genuinely integrates no external API**\n(the detector is deterministic, not infallible — confirm by re-reading the phase\nscope, not by preference): do NOT fabricate a matrix row for a capability that\ndoes not exist. Write a reasoned declaration to `${PHASE_DIR}/COVERAGE.md`\ninstead:\n\n```markdown\nNo external API integration: <one-line reason — what the phase touches instead>.\n```\n\nThe reason is required, exactly like an `OPT-OUT` reason. The seal-time gate\naccepts this declaration in place of a matrix.\n\n## Produce the coverage matrix\n\nEnumerate the external API's full **capability surface** — the verb/endpoint/method\nlist (e.g. for a music service: `search`, `play`, `pause`, `skip`, `set_volume`,\n`get_playlist`, `create_playlist`, `add_to_playlist`, …). For each capability\nrecord a decision, starting from **full coverage** as the default:\n\n| capability | decision | reason |\n|---|---|---|\n| `<capability-id>` | `INTEGRATE` \\| `OPT-OUT` | `<one-line reason if OPT-OUT>` |\n\nRules:\n\n- **`INTEGRATE` is the default.** Every capability starts as INTEGRATE; the\n matrix is the *subtraction record*.\n- **Every `OPT-OUT` MUST carry a one-line reason** (`not needed`, `not needed\n yet`, `explicitly out of scope`, …). An opt-out without a reason is an\n un-decided hole — the exact failure mode this gate exists to close.\n- **A second integration against the same need** (e.g. a second platform for the\n same capability) starts from the **same full-coverage baseline** as the first.\n Do not carry over the first integration's opt-outs silently — re-decide each\n capability for the new surface, so a first-class/fallback asymmetry cannot\n accumulate.\n\nWrite the matrix to `${PHASE_DIR}/COVERAGE.md` (canonical markdown-table form):\n\n```markdown\n# API Coverage — <service>\n\n> Full coverage by default. Opt-outs are explicit, reasoned decisions.\n\n| capability | decision | reason |\n|---|---|---|\n| search | INTEGRATE | |\n| playlists | INTEGRATE | |\n| skip | OPT-OUT | not needed yet — tracked for follow-up phase |\n```\n\nA fenced ` ```coverage ` JSON block is also accepted for machine-generated\nmatrices; the markdown table is preferred (human-editable, diff-friendly).\n\n## The seal-time gate\n\nThis checkpoint is enforced. At `verify:pre` the `api-coverage.verify-pre` gate\nruns `check api-coverage.verify-pre <phase-dir>`:\n\n- If `COVERAGE.md` exists, it is validated — every row needs a valid decision and\n every `OPT-OUT` a reason. A malformed/partial matrix **blocks the seal**. A\n reasoned `No external API integration: …` declaration (and no rows) passes.\n- If `COVERAGE.md` is absent, the detector runs again over the phase scope. If a\n strong external-API-integration signal is found, the seal is **blocked** until a\n matrix is produced. If no signal is found, the phase is treated as a non-API\n phase and the seal proceeds.\n\nSo: an API-integrating phase cannot seal without a decided matrix. Produce it at\nplan time; do not leave it for seal time.\n\n## Tuning the vocabulary (optional)\n\nThe trigger vocabulary is a curated, additive-only set in\n`gsd-core/bin/lib/api-coverage.cjs` (`DEFAULT_API_COVERAGE_TERMS`). To widen it\nfor a project, override at the call site:\n\n```bash\nprintf '%s' \"$SCOPE\" | node gsd-core/bin/lib/api-coverage.cjs --json \\\n --verbs integrate,wrap,connect,embed --nouns api,sdk,rest,grpc,webhook,plugin\n```\n\nThe whole checkpoint is toggleable via `workflow.api_coverage_gate` in\n`.planning/config.json`.\n"
3178
3912
  },
3179
3913
  "produces": [
3180
3914
  "COVERAGE.md"
@@ -3333,20 +4067,15 @@ const byLoopPoint = {
3333
4067
  "gates": []
3334
4068
  },
3335
4069
  "execute:wave:pre": {
3336
- "steps": [],
3337
- "contributions": [],
3338
- "gates": []
3339
- },
3340
- "execute:wave:post": {
3341
4070
  "steps": [],
3342
4071
  "contributions": [
3343
4072
  {
3344
4073
  "capId": "claude-orchestration",
3345
- "point": "execute:wave:post",
4074
+ "point": "execute:wave:pre",
3346
4075
  "into": "executor",
3347
4076
  "fragment": {
3348
- "path": "fragments/execute-wave-post.md",
3349
- "inline": "# Claude orchestration — Workflow execution backend (BETA)\n\n> Injected at `execute:wave:post` `into: executor` only when\n> `claude_orchestration.enabled` is true. Default-off; `onError: skip`.\n\n## When this contribution is active\n\nThe Claude orchestration capability is **default-off and BETA**. It activates only\nwhen ALL of the following hold:\n\n1. `claude_orchestration.enabled` is `true` in `.planning/config.json`, AND\n2. the active runtime is **Claude Code** (the Workflow tool is Claude / Agent\n SDK-specific), AND\n3. `claude_orchestration.execution_backend` resolves to `workflow` — either\n explicitly, or via `auto` — **and** the Agent SDK version is\n `>= claude_orchestration.min_agent_sdk_version` (default `0.3.149`). The SDK\n floor applies in both `auto` and `workflow` modes (fail-closed: a pre-release\n or older SDK never activates the preview backend).\n\nDetection is fail-closed: any miss degrades to **inline, manual, one-agent-per-\nmessage dispatch** — exactly today's behaviour. On a non-Claude runtime this\ncontribution is a no-op.\n\n## What the executor does when the Workflow backend is active\n\nInstead of the orchestrator fanning out one `Agent(subagent_type=gsd-executor,\nisolation=worktree, run_in_background=true)` per message (which on Claude Code\ncannot nest further subagents — #853 — and so degrades to sequential inline\nexecution), execute-phase **emits a generated Workflow script** and lets the main\nloop orchestrate it:\n\n- **waves → one or more sequential `parallel()` barriers** — each wave is a\n barrier group; when plans within a wave share `files_modified`, they are split\n into separate sequential stages within that wave's barrier (the next wave\n still waits for the previous wave to complete).\n- **plans → `agent(brief, { agentType: 'gsd-executor', isolation: 'worktree' })`**\n — the SAME executor agent and worktree isolation the inline path uses, so the\n produced `SUMMARY.md` and commits are identical.\n- **`files_modified` overlap → separate sequential stages** — two plans that\n touch the same file are placed in different stages within the wave (the same\n overlap rule execute-phase already applies inline).\n- **`resumeFromRunId`** — wired to the phase run id, so an interrupted phase\n resumes without re-running completed plans.\n- **`budget(tokens)`** — a shared token pool across the whole phase when the\n orchestrator passes a `budgetTokens` value to `emitWorkflowScript` (it is a\n function parameter, not a config key; the orchestrator decides the budget).\n\nThe emitter is a pure function exposed through the capability command surface:\n`gsd-tools claude-orchestration emit-workflow --waves <manifest.json> --run-id <id>\n[--phase-dir <dir>] [--budget <n>]` (or `require('gsd-core/bin/lib/claude-orchestration.cjs').emitWorkflowScript`\ndirectly). It maps the phase's wave/plan manifest to the Workflow script string\nand never invokes the Workflow tool itself; the orchestrator runs the emitted\nscript. Detection is resolved by the orchestrator calling the pure\n`detectWorkflowBackend` with the LIVE host descriptor (the CLI\n`gsd-tools claude-orchestration detect-backend` is a simulation harness that\nassumes a capable host unless `--no-nested-dispatch` is passed — it does not probe\nthe real runtime; the orchestrator supplies the real descriptor).\n\n## Fallback contract\n\nIf detection resolves to `inline` (tool absent, SDK too old, runtime not Claude,\nor the capability disabled), execute-phase MUST proceed with the standard inline\nwave dispatch. The executor MUST NOT assume parallelism, a shared budget, or\nresume-from-run-id semantics in that mode.\n"
4077
+ "path": "fragments/execute-wave-pre.md",
4078
+ "inline": "# Claude orchestration — Workflow execution backend (BETA)\n\n> Injected at `execute:wave:pre` `into: executor` only when\n> `claude_orchestration.enabled` is true. Default-off; `onError: skip`.\n\n## When this contribution is active\n\nThe Claude orchestration capability is **default-off and BETA**. It activates only\nwhen ALL of the following hold:\n\n1. `claude_orchestration.enabled` is `true` in `.planning/config.json`, AND\n2. the active runtime is **Claude Code** (the Workflow tool is Claude / Agent\n SDK-specific), AND\n3. `claude_orchestration.execution_backend` resolves to `workflow` — either\n explicitly, or via `auto` — **and** the Agent SDK version is\n `>= claude_orchestration.min_agent_sdk_version` (default `0.3.149`). The SDK\n floor applies in both `auto` and `workflow` modes (fail-closed: a pre-release\n or older SDK never activates the preview backend).\n\nDetection is fail-closed: any miss degrades to **inline, manual, one-agent-per-\nmessage dispatch** — exactly today's behaviour. On a non-Claude runtime this\ncontribution is a no-op.\n\n## Why `execute:wave:pre` (not `execute:wave:post`)\n\nThis is a **dispatch-backend selector** — it decides HOW a wave's executor agents\nare spawned. That decision has to be made BEFORE the wave's `Agent()` calls in\n`execute-phase.md` step 3, not after the wave has already finished (#2285). The\ncapability previously registered at `execute:wave:post`, which fires only after\nworktree merge/post-merge tests/tracking updates — by then the wave was already\ndispatched inline, so the contribution was structurally unable to change how\ndispatch happened. This fragment is injected at the point that actually precedes\ndispatch.\n\n## What the orchestrator does when the Workflow backend is active\n\nBefore spawning executor agents for the current wave (execute-phase.md step 3),\nresolve the dispatch backend through the single composed CLI seam:\n\n```bash\ngsd-tools claude-orchestration resolve-wave-dispatch \\\n --waves \"$WAVE_MANIFEST_PATH\" --run-id \"$PHASE_RUN_ID\" \\\n --runtime \"$RUNTIME\" \\\n --phase-dir \"$PHASE_DIR\" --raw\n```\n\n`--agent-sdk-version` is no longer passed here (#2590). The router resolves the\ninstalled Agent SDK version itself; see **Agent SDK version** below. The former\n`${AGENT_SDK_VERSION:+--agent-sdk-version \"$AGENT_SDK_VERSION\"}` line was also\n**shell-dependent**: zsh does not word-split unquoted parameter expansions, so it\ncollapsed to a SINGLE argv element there, `argValue()` never matched, and the run\nfailed into `agent_sdk_version_unknown` — indistinguishable from genuinely\nunknown. Pass `--agent-sdk-version <ver>` explicitly only to pin a version.\n\nThis composes `detectWorkflowBackend` (the gate ladder above) with\n`emitWorkflowScript` (the wave→plan mapping below) in ONE call — the pure\nfunction backing it is `resolveWaveDispatch` in\n`gsd-core/bin/lib/claude-orchestration.cjs`. Response shape:\n`{ backend: 'inline'|'workflow', reason, script?, summary? }`.\n\n### Manifest construction (`$WAVE_MANIFEST_PATH`, `$PHASE_RUN_ID`, `$PHASE_DIR`)\n\nThese are NOT pre-existing execute-phase.md variables — the orchestrator builds\nthem at this step, from data it already has in-context from `discover_and_group_plans`\n(the `PLAN_INDEX` JSON) and step 2.5 (the per-plan `USE_WORKTREES_FOR_PLAN` decision):\n\n1. **`$PHASE_DIR`** — reuse `{phase_dir}` from the `INIT` bundle (already loaded\n in the `initialize` step). No new value needed.\n\n2. **`$PHASE_RUN_ID`** — a stable identifier for THIS phase-execution attempt, so\n `resumeFromRunId` can resume an interrupted run without re-dispatching plans\n the Workflow tool already completed. Construct it deterministically —\n `execute-{phase_number}-{phase_slug}` — from `INIT`'s `phase_number`/`phase_slug`\n (both are already validated identifiers used elsewhere in this workflow, so\n they satisfy `emitWorkflowScript`'s `isScriptableIdentifier` check). Do NOT\n mint a new random id per wave — the SAME `$PHASE_RUN_ID` is reused for every\n wave in the phase so the Workflow tool can correctly track cross-wave resume\n state.\n\n3. **`$WAVE_MANIFEST_PATH`** — a fresh temp file for THIS wave's manifest (one\n wave = one `waves` array with a single entry, matching the wave-by-wave\n dispatch loop; do not batch multiple waves into one manifest — waves are\n dispatched in wave order, not all at once):\n\n ```bash\n WAVE_MANIFEST_PATH=$(mktemp \"${TMPDIR:-/tmp}/gsd-wave-dispatch-XXXXXX\") && mv \"$WAVE_MANIFEST_PATH\" \"$WAVE_MANIFEST_PATH.json\" && WAVE_MANIFEST_PATH=\"$WAVE_MANIFEST_PATH.json\"\n ```\n\n Then **use the Write tool** (not a bash/jq pipeline — the orchestrator already\n has every field parsed in-context) to write the manifest JSON to\n `$WAVE_MANIFEST_PATH`:\n\n ```json\n {\n \"waves\": [\n {\n \"id\": \"wave-{N}\",\n \"plans\": [\n {\n \"id\": \"{plan_id}\",\n \"brief\": \"{the SAME <objective>...<success_criteria> prompt block step 3 builds for this plan's inline Agent() call}\",\n \"files_modified\": [\"{from PLAN_INDEX.plans[].files_modified for this plan}\"],\n \"use_worktree\": {true unless step 2.5 set USE_WORKTREES_FOR_PLAN=false for this plan}\n }\n ]\n }\n ]\n }\n ```\n\n - **`id`** — the plan id from `PLAN_INDEX`, e.g. `\"01-01\"`.\n - **`brief`** — MUST carry the same task content as step 3's inline `Agent()`\n prompt (the `<objective>`/`<execution_context>`/`<files_to_read>`/\n `<success_criteria>` block, with `{plan_number}`/`{phase_number}`/\n `{phase_name}` substituted) — a short summary here would NOT reproduce\n step 3's behavior and would violate the \"identical artifacts\" contract.\n - **`files_modified`** — copy verbatim from the plan's `PLAN_INDEX` entry.\n - **`use_worktree`** — `true` for every plan UNLESS step 2.5's per-plan\n worktree gate (`execute-phase/steps/per-plan-worktree-gate.md`) set\n `USE_WORKTREES_FOR_PLAN=false` for that plan (submodule-touching plan, or\n project-level `USE_WORKTREES=false`) — in which case pass `false` here so\n `emitWorkflowScript` omits `isolation: \"worktree\"` for that plan (#2772 /\n #2285 finding 1). **Never** hardcode `true` — that would force worktree\n isolation on a plan the inline path explicitly keeps out of worktrees.\n\n4. **`$AGENT_SDK_VERSION`** — no longer built here; the router resolves it.\n\n**Agent SDK version:** the orchestrator has no *bash-computable* way to\nintrospect the live Agent SDK version — but the router runs in Node, so it\nresolves the version itself (#2590), in this order:\n\n1. an explicit `--agent-sdk-version <ver>` (pin a version),\n2. `GSD_AGENT_SDK_VERSION`,\n3. the **installed** `@anthropic-ai/claude-agent-sdk` package version, read from\n its `package.json` on disk by walking `node_modules` up the tree. (Read\n directly rather than via `require.resolve`: the SDK's `exports` map does not\n expose `./package.json`, so `require.resolve` throws\n `ERR_PACKAGE_PATH_NOT_EXPORTED`.)\n\nPreviously nothing computed this at all, so gate 5 returned\n`agent_sdk_version_unknown` on **every** automated run and the Workflow backend\ncould never activate — while `gsd-tools capability state` still reported the\ncapability `active: true`. Fail-closed is preserved: when no version can be\nresolved, gate 5 still declines to `inline`. What changed is that a resolvable\nversion is now actually found, so a genuinely-too-old SDK reports\n`agent_sdk_version_below_floor` — the truthful reason — instead of `unknown`.\n\n**If `backend == \"workflow\"`:** run the emitted `script` via the Workflow tool\nfor THIS wave instead of the per-message `Agent()` loop in step 3. The script\ncomposes the SAME `gsd-executor` agent type the inline path uses, with\nworktree isolation applied PER PLAN from the manifest's `use_worktree` field\n(see `emitWorkflowScript`):\n\n- **waves → one or more sequential `parallel()` barriers** — each wave is a\n barrier group; when plans within a wave share `files_modified`, they are split\n into separate sequential stages within that wave's barrier.\n- **plans → `agent(brief, { agentType: 'gsd-executor', isolation: 'worktree' })`**\n when `use_worktree` is not `false`, or `agent(brief, { agentType: 'gsd-executor' })`\n (no isolation) when it is — so the produced `SUMMARY.md` and commits are\n identical to inline dispatch, INCLUDING the inline path's submodule safety\n gate (#2772 / #2285 finding 1).\n- **`files_modified` overlap → separate sequential stages** — the same overlap\n rule execute-phase already applies inline (step 1 of the wave loop).\n- **`resumeFromRunId`** — **pass `summary.resumeRunId` as the Workflow tool's\n `resumeFromRunId` INPUT when you invoke the tool.** It is a tool parameter,\n not a script function; the script deliberately does not call it (#2590 — doing\n so threw \"resumeFromRunId is not defined\" and rejected the entire script).\n Omitting it from the tool invocation silently regresses phase-resume to a\n no-op: an interrupted phase re-runs completed plans.\n\nThe orchestrator still runs steps 4–5.8 (wait for completion, worktree cleanup,\npost-merge gate, tracking update) exactly as it does for inline dispatch — the\nWorkflow backend only replaces HOW agents are spawned for this wave, not what\nhappens after they return.\n\n**If `backend == \"inline\"`** (any gate miss, or `resolve-wave-dispatch` itself\nunavailable/erroring): proceed to step 3's standard per-message `Agent()`\ndispatch — the default, byte-identical-to-today path. `onError: skip` on this\ncontribution means a `resolve-wave-dispatch` command failure is treated exactly\nlike an `inline` result, never as a fatal wave error.\n\n## Fallback contract\n\nDetection is fail-closed end-to-end: capability disabled, non-Claude runtime,\n`execution_backend:\"inline\"`, missing/incapable host descriptor, unknown or\nbelow-floor Agent SDK version, or an `emitWorkflowScript` failure on a malformed\nwave manifest — ANY of these degrades to `backend:\"inline\"` and execute-phase's\nstandard inline dispatch (step 3) runs unmodified. The Workflow backend never\npartially activates; the executor MUST NOT assume parallelism, a shared budget,\nor resume-from-run-id semantics when `backend == \"inline\"`.\n"
3350
4079
  },
3351
4080
  "produces": [],
3352
4081
  "consumes": [
@@ -3354,7 +4083,13 @@ const byLoopPoint = {
3354
4083
  ],
3355
4084
  "when": "claude_orchestration.enabled",
3356
4085
  "onError": "skip"
3357
- },
4086
+ }
4087
+ ],
4088
+ "gates": []
4089
+ },
4090
+ "execute:wave:post": {
4091
+ "steps": [],
4092
+ "contributions": [
3358
4093
  {
3359
4094
  "capId": "external-job",
3360
4095
  "point": "execute:wave:post",
@@ -3535,6 +4270,21 @@ const byLoopPoint = {
3535
4270
  "steps": [],
3536
4271
  "contributions": [],
3537
4272
  "gates": [
4273
+ {
4274
+ "capId": "broken-windows",
4275
+ "point": "ship:pre",
4276
+ "check": {
4277
+ "predicate": {
4278
+ "kind": "artifact-frontmatter-equals",
4279
+ "artifact": "WINDOWS.md",
4280
+ "field": "open_count",
4281
+ "equals": 0
4282
+ }
4283
+ },
4284
+ "when": "workflow.windows_enforce",
4285
+ "blocking": true,
4286
+ "onError": "halt"
4287
+ },
3538
4288
  {
3539
4289
  "capId": "security",
3540
4290
  "point": "ship:pre",
@@ -3576,12 +4326,16 @@ const byLoopPoint = {
3576
4326
  const configKeys = {
3577
4327
  "workflow.ai_integration_phase": "ai-integration",
3578
4328
  "workflow.api_coverage_gate": "ai-integration",
4329
+ "review.models.agy": "antigravity",
3579
4330
  "workflow.assumption_delta": "assumption-delta",
4331
+ "workflow.windows_enforce": "broken-windows",
4332
+ "review.models.claude": "claude",
3580
4333
  "claude_orchestration.enabled": "claude-orchestration",
3581
4334
  "claude_orchestration.execution_backend": "claude-orchestration",
3582
4335
  "claude_orchestration.min_agent_sdk_version": "claude-orchestration",
3583
4336
  "workflow.code_review": "code-review",
3584
4337
  "workflow.code_review_depth": "code-review",
4338
+ "review.models.codex": "codex",
3585
4339
  "workflow.drift_threshold": "drift",
3586
4340
  "workflow.drift_action": "drift",
3587
4341
  "workflow.schema_drift_gate": "drift",
@@ -3592,8 +4346,16 @@ const configKeys = {
3592
4346
  "external_job.submit_timeout_ms": "external-job",
3593
4347
  "external_job.poll_timeout_ms": "external-job",
3594
4348
  "workflow.post_planning_gaps": "gap-analysis",
4349
+ "review.models.gemini": "gemini",
3595
4350
  "graphify.enabled": "graphify",
3596
4351
  "intel.enabled": "intel",
4352
+ "review.models.kimi-code": "kimi-code",
4353
+ "review.models.llama_cpp": "llama-cpp",
4354
+ "review.llama_cpp_host": "llama-cpp",
4355
+ "review.max_prompt_tokens_per_reviewer.llama_cpp": "llama-cpp",
4356
+ "review.models.lm_studio": "lm-studio",
4357
+ "review.lm_studio_host": "lm-studio",
4358
+ "review.max_prompt_tokens_per_reviewer.lm_studio": "lm-studio",
3597
4359
  "mempalace.enabled": "mempalace",
3598
4360
  "mempalace.memory_mode": "mempalace",
3599
4361
  "mempalace.wing": "mempalace",
@@ -3605,6 +4367,10 @@ const configKeys = {
3605
4367
  "mempalace.diary_journal": "mempalace",
3606
4368
  "mempalace.auto_capture_hooks": "mempalace",
3607
4369
  "workflow.nyquist_validation": "nyquist",
4370
+ "review.models.ollama": "ollama",
4371
+ "review.ollama_host": "ollama",
4372
+ "review.max_prompt_tokens_per_reviewer.ollama": "ollama",
4373
+ "review.models.opencode": "opencode",
3608
4374
  "workflow.pattern_mapper": "pattern-mapper",
3609
4375
  "profile-pipeline.enabled": "profile-pipeline",
3610
4376
  "workflow.research": "research",
@@ -3631,12 +4397,30 @@ const configSchema = {
3631
4397
  "default": true,
3632
4398
  "description": "Require an explicit API-coverage decision (full-by-default, opt-out-not-opt-in) before a phase that integrates an external API/SDK/service can seal. At plan:pre the planner is prompted to enumerate the API surface into COVERAGE.md; at verify:pre a blocking gate fails the seal unless the matrix exists with every non-integrated capability an explicit, reasoned opt-out. Independent of ai_integration_phase (applies to any external-API integration, not only AI)."
3633
4399
  },
4400
+ "review.models.agy": {
4401
+ "owner": "antigravity",
4402
+ "type": "string",
4403
+ "default": "",
4404
+ "description": "Model passed to the Antigravity reviewer lane. The key suffix is the lane binary/flag alias `agy`, not the slug `antigravity` — preserved verbatim so existing .planning/config.json files keep working."
4405
+ },
3634
4406
  "workflow.assumption_delta": {
3635
4407
  "owner": "assumption-delta",
3636
4408
  "type": "boolean",
3637
4409
  "default": true,
3638
4410
  "description": "Enable the assumption-delta architecture checkpoint during planning. When a pluralization/optional/chosen signal is detected in the phase scope, the planner is prompted to re-ask whether the primary key / identity model still names the right thing. Advisory (non-blocking)."
3639
4411
  },
4412
+ "workflow.windows_enforce": {
4413
+ "owner": "broken-windows",
4414
+ "type": "boolean",
4415
+ "default": false,
4416
+ "description": "Enable the blocking ship:pre gate for the broken-windows ledger. When true (opt-in), /gsd-ship blocks while .planning/WINDOWS.md has any open entry. When false (default), windows are still tracked (the executor and verifier still populate WINDOWS.md via gsd-tools windows append) but ship does not block — teams can adopt tracking before enforcement. Issue #1950."
4417
+ },
4418
+ "review.models.claude": {
4419
+ "owner": "claude",
4420
+ "type": "string",
4421
+ "default": "",
4422
+ "description": "Model passed to the Claude reviewer lane."
4423
+ },
3640
4424
  "claude_orchestration.enabled": {
3641
4425
  "owner": "claude-orchestration",
3642
4426
  "type": "boolean",
@@ -3677,6 +4461,12 @@ const configSchema = {
3677
4461
  "deep"
3678
4462
  ]
3679
4463
  },
4464
+ "review.models.codex": {
4465
+ "owner": "codex",
4466
+ "type": "string",
4467
+ "default": "",
4468
+ "description": "Model passed to the Codex reviewer lane."
4469
+ },
3680
4470
  "workflow.drift_threshold": {
3681
4471
  "owner": "drift",
3682
4472
  "type": "number",
@@ -3744,6 +4534,12 @@ const configSchema = {
3744
4534
  "default": true,
3745
4535
  "description": "Run the post-planning gap analysis report after plans are generated."
3746
4536
  },
4537
+ "review.models.gemini": {
4538
+ "owner": "gemini",
4539
+ "type": "string",
4540
+ "default": "",
4541
+ "description": "Model passed to the Gemini reviewer lane."
4542
+ },
3747
4543
  "graphify.enabled": {
3748
4544
  "owner": "graphify",
3749
4545
  "type": "boolean",
@@ -3756,6 +4552,48 @@ const configSchema = {
3756
4552
  "default": false,
3757
4553
  "description": "Enable the intel code-intelligence command."
3758
4554
  },
4555
+ "review.models.kimi-code": {
4556
+ "owner": "kimi-code",
4557
+ "type": "string",
4558
+ "default": "",
4559
+ "description": "Model passed to the Kimi Code reviewer lane."
4560
+ },
4561
+ "review.models.llama_cpp": {
4562
+ "owner": "llama-cpp",
4563
+ "type": "string",
4564
+ "default": "",
4565
+ "description": "Model requested from the llama.cpp reviewer lane; empty discovers the first model from /v1/models."
4566
+ },
4567
+ "review.llama_cpp_host": {
4568
+ "owner": "llama-cpp",
4569
+ "type": "string",
4570
+ "default": "",
4571
+ "description": "Base URL of the llama.cpp OpenAI-compatible server."
4572
+ },
4573
+ "review.max_prompt_tokens_per_reviewer.llama_cpp": {
4574
+ "owner": "llama-cpp",
4575
+ "type": "number",
4576
+ "default": -1,
4577
+ "description": "Prompt-token budget for the llama.cpp reviewer lane. Unset is -1, a sentinel: 0 is a legitimate value meaning \"do not trim this lane\", so it cannot double as \"not configured\"."
4578
+ },
4579
+ "review.models.lm_studio": {
4580
+ "owner": "lm-studio",
4581
+ "type": "string",
4582
+ "default": "",
4583
+ "description": "Model requested from the LM Studio reviewer lane; empty discovers the first model from /v1/models."
4584
+ },
4585
+ "review.lm_studio_host": {
4586
+ "owner": "lm-studio",
4587
+ "type": "string",
4588
+ "default": "",
4589
+ "description": "Base URL of the LM Studio OpenAI-compatible server."
4590
+ },
4591
+ "review.max_prompt_tokens_per_reviewer.lm_studio": {
4592
+ "owner": "lm-studio",
4593
+ "type": "number",
4594
+ "default": -1,
4595
+ "description": "Prompt-token budget for the LM Studio reviewer lane. Unset is -1, a sentinel: 0 is a legitimate value meaning \"do not trim this lane\", so it cannot double as \"not configured\"."
4596
+ },
3759
4597
  "mempalace.enabled": {
3760
4598
  "owner": "mempalace",
3761
4599
  "type": "boolean",
@@ -3827,6 +4665,30 @@ const configSchema = {
3827
4665
  "default": true,
3828
4666
  "description": "Enable Nyquist validation coverage auditing."
3829
4667
  },
4668
+ "review.models.ollama": {
4669
+ "owner": "ollama",
4670
+ "type": "string",
4671
+ "default": "",
4672
+ "description": "Model requested from the Ollama reviewer lane; empty discovers the first model from /v1/models."
4673
+ },
4674
+ "review.ollama_host": {
4675
+ "owner": "ollama",
4676
+ "type": "string",
4677
+ "default": "",
4678
+ "description": "Base URL of the Ollama OpenAI-compatible server."
4679
+ },
4680
+ "review.max_prompt_tokens_per_reviewer.ollama": {
4681
+ "owner": "ollama",
4682
+ "type": "number",
4683
+ "default": -1,
4684
+ "description": "Prompt-token budget for the Ollama reviewer lane. Unset is -1, a sentinel: 0 is a legitimate value meaning \"do not trim this lane\", so it cannot double as \"not configured\"."
4685
+ },
4686
+ "review.models.opencode": {
4687
+ "owner": "opencode",
4688
+ "type": "string",
4689
+ "default": "",
4690
+ "description": "Model passed to the OpenCode reviewer lane."
4691
+ },
3830
4692
  "workflow.pattern_mapper": {
3831
4693
  "owner": "pattern-mapper",
3832
4694
  "type": "boolean",
@@ -3906,7 +4768,7 @@ const runtimes = {
3906
4768
  "antigravity": {
3907
4769
  "id": "antigravity",
3908
4770
  "role": "runtime",
3909
- "version": "1.7.0",
4771
+ "version": "1.9.0",
3910
4772
  "title": "Antigravity",
3911
4773
  "description": "Google Antigravity IDE — nested under ~/.gemini/antigravity; probed across 1.x and 2.x layouts; Gemini hook event dialect; flat skill layout; tier-1 support.",
3912
4774
  "tier": "core",
@@ -3987,13 +4849,15 @@ const runtimes = {
3987
4849
  "maxDepth": "undocumented",
3988
4850
  "background": true,
3989
4851
  "subagentToolkit": "full",
3990
- "backgroundDispatch": "undocumented"
4852
+ "backgroundDispatch": "undocumented",
4853
+ "isolation": "undocumented"
3991
4854
  },
3992
4855
  "modelMode": "passive",
3993
4856
  "hookBus": "host",
3994
4857
  "stateIO": "filesystem",
3995
4858
  "transport": "mcp",
3996
- "runtime": "go"
4859
+ "runtime": "go",
4860
+ "effortSurface": "undocumented"
3997
4861
  },
3998
4862
  "hostBehaviors": {
3999
4863
  "reviewerCli": true,
@@ -4002,12 +4866,53 @@ const runtimes = {
4002
4866
  "hookPathStyle": "raw",
4003
4867
  "globalDirResolver": "antigravity"
4004
4868
  }
4869
+ },
4870
+ "reviewer": {
4871
+ "slug": "antigravity",
4872
+ "flags": [
4873
+ "--antigravity",
4874
+ "--agy"
4875
+ ],
4876
+ "transport": "spawn",
4877
+ "probe": {
4878
+ "kind": "command-exists",
4879
+ "binary": "agy"
4880
+ },
4881
+ "invoke": {
4882
+ "binary": "agy",
4883
+ "args": [
4884
+ "--print-timeout",
4885
+ "540s",
4886
+ "{{model}}",
4887
+ "-p",
4888
+ "{{prompt}}"
4889
+ ],
4890
+ "promptChannel": "argv-file-ref",
4891
+ "outputChannel": "stdout",
4892
+ "modelArg": "--model",
4893
+ "effortChannel": "none"
4894
+ },
4895
+ "timeoutFloorMs": 600000,
4896
+ "emptyOutput": "handler-owned",
4897
+ "reviewsSection": "Antigravity",
4898
+ "evidenceClass": "source-grounded",
4899
+ "requiresBinaries": [],
4900
+ "promptBudgetKey": null,
4901
+ "modelConfigKey": "review.models.agy",
4902
+ "handler": "antigravity"
4903
+ },
4904
+ "config": {
4905
+ "review.models.agy": {
4906
+ "type": "string",
4907
+ "default": "",
4908
+ "description": "Model passed to the Antigravity reviewer lane. The key suffix is the lane binary/flag alias `agy`, not the slug `antigravity` — preserved verbatim so existing .planning/config.json files keep working."
4909
+ }
4005
4910
  }
4006
4911
  },
4007
4912
  "augment": {
4008
4913
  "id": "augment",
4009
4914
  "role": "runtime",
4010
- "version": "1.7.0",
4915
+ "version": "1.9.0",
4011
4916
  "title": "Augment Code",
4012
4917
  "description": "Augment Code CLI — commands + nested-skill artifact layout; settings-json hook surface; Claude hook event dialect; tier-2 support.",
4013
4918
  "tier": "core",
@@ -4101,20 +5006,22 @@ const runtimes = {
4101
5006
  "maxDepth": "undocumented",
4102
5007
  "background": true,
4103
5008
  "subagentToolkit": "full",
4104
- "backgroundDispatch": "undocumented"
5009
+ "backgroundDispatch": "undocumented",
5010
+ "isolation": "undocumented"
4105
5011
  },
4106
5012
  "modelMode": "passive",
4107
5013
  "hookBus": "host",
4108
5014
  "stateIO": "filesystem",
4109
5015
  "transport": "mcp",
4110
- "runtime": "node"
5016
+ "runtime": "node",
5017
+ "effortSurface": "undocumented"
4111
5018
  }
4112
5019
  }
4113
5020
  },
4114
5021
  "claude": {
4115
5022
  "id": "claude",
4116
5023
  "role": "runtime",
4117
- "version": "1.7.0",
5024
+ "version": "1.9.0",
4118
5025
  "title": "Claude Code",
4119
5026
  "description": "Anthropic Claude Code — primary development runtime; tier-1 support with full hook surface and skills-based global install.",
4120
5027
  "tier": "core",
@@ -4185,14 +5092,17 @@ const runtimes = {
4185
5092
  "maxDepth": 5,
4186
5093
  "background": true,
4187
5094
  "subagentToolkit": "full",
4188
- "backgroundDispatch": false
5095
+ "backgroundDispatch": false,
5096
+ "isolation": "harness-worktree"
4189
5097
  },
4190
5098
  "modelMode": "passive",
4191
5099
  "hookBus": "host",
4192
5100
  "stateIO": "filesystem",
4193
5101
  "transport": "mcp",
4194
- "runtime": "node"
5102
+ "runtime": "node",
5103
+ "effortSurface": "argv"
4195
5104
  },
5105
+ "harnessIsolationFlag": "isolation=\"worktree\"",
4196
5106
  "hostBehaviors": {
4197
5107
  "attributionSource": "settings-json-commit",
4198
5108
  "authorsCanonicalWorkflow": true,
@@ -4214,12 +5124,51 @@ const runtimes = {
4214
5124
  "hyphenNameAgentBody": true,
4215
5125
  "reviewerCli": true
4216
5126
  }
5127
+ },
5128
+ "reviewer": {
5129
+ "slug": "claude",
5130
+ "flags": [
5131
+ "--claude"
5132
+ ],
5133
+ "transport": "spawn",
5134
+ "probe": {
5135
+ "kind": "command-exists",
5136
+ "binary": "claude"
5137
+ },
5138
+ "invoke": {
5139
+ "binary": "claude",
5140
+ "args": [
5141
+ "{{model}}",
5142
+ "{{effort}}",
5143
+ "-p",
5144
+ "-"
5145
+ ],
5146
+ "promptChannel": "stdin",
5147
+ "outputChannel": "stdout",
5148
+ "modelArg": "--model",
5149
+ "effortChannel": "argv"
5150
+ },
5151
+ "timeoutFloorMs": 1200000,
5152
+ "emptyOutput": "stub-with-stderr",
5153
+ "reviewsSection": "Claude",
5154
+ "evidenceClass": "source-grounded",
5155
+ "requiresBinaries": [],
5156
+ "promptBudgetKey": null,
5157
+ "modelConfigKey": "review.models.claude",
5158
+ "handler": null
5159
+ },
5160
+ "config": {
5161
+ "review.models.claude": {
5162
+ "type": "string",
5163
+ "default": "",
5164
+ "description": "Model passed to the Claude reviewer lane."
5165
+ }
4217
5166
  }
4218
5167
  },
4219
5168
  "cline": {
4220
5169
  "id": "cline",
4221
5170
  "role": "runtime",
4222
- "version": "1.7.0",
5171
+ "version": "1.9.0",
4223
5172
  "title": "Cline",
4224
5173
  "description": "Cline (VS Code extension) — global-only nested-skill layout; cline-rules hook surface (.clinerules); no hook events emitted; tier-2 support.",
4225
5174
  "tier": "core",
@@ -4267,13 +5216,15 @@ const runtimes = {
4267
5216
  "maxDepth": 1,
4268
5217
  "background": true,
4269
5218
  "subagentToolkit": "read-only",
4270
- "backgroundDispatch": false
5219
+ "backgroundDispatch": false,
5220
+ "isolation": "undocumented"
4271
5221
  },
4272
5222
  "modelMode": "active",
4273
5223
  "hookBus": "host",
4274
5224
  "stateIO": "filesystem",
4275
5225
  "transport": "mcp",
4276
- "runtime": "node"
5226
+ "runtime": "node",
5227
+ "effortSurface": "undocumented"
4277
5228
  },
4278
5229
  "hostBehaviors": {
4279
5230
  "reapplyCommand": "/gsd-update --reapply",
@@ -4288,7 +5239,7 @@ const runtimes = {
4288
5239
  "codebuddy": {
4289
5240
  "id": "codebuddy",
4290
5241
  "role": "runtime",
4291
- "version": "1.7.0",
5242
+ "version": "1.9.0",
4292
5243
  "title": "CodeBuddy",
4293
5244
  "description": "CodeBuddy (Tencent) — converted commands + skills artifact layout; settings-json hook surface; Claude hook event dialect; tier-2 support.",
4294
5245
  "tier": "core",
@@ -4383,13 +5334,15 @@ const runtimes = {
4383
5334
  "maxDepth": 1,
4384
5335
  "background": true,
4385
5336
  "subagentToolkit": "full",
4386
- "backgroundDispatch": false
5337
+ "backgroundDispatch": false,
5338
+ "isolation": "undocumented"
4387
5339
  },
4388
5340
  "modelMode": "passive",
4389
5341
  "hookBus": "host",
4390
5342
  "stateIO": "filesystem",
4391
5343
  "transport": "mcp",
4392
- "runtime": "node"
5344
+ "runtime": "node",
5345
+ "effortSurface": "undocumented"
4393
5346
  },
4394
5347
  "hostBehaviors": {
4395
5348
  "reportCommandsDir": true
@@ -4399,7 +5352,7 @@ const runtimes = {
4399
5352
  "codex": {
4400
5353
  "id": "codex",
4401
5354
  "role": "runtime",
4402
- "version": "1.7.0",
5355
+ "version": "1.9.0",
4403
5356
  "title": "OpenAI Codex CLI",
4404
5357
  "description": "OpenAI Codex CLI — shell-var command style; per-agent sandbox tiers; config.toml + hooks.json hook surface; tier-1 support.",
4405
5358
  "tier": "core",
@@ -4463,13 +5416,23 @@ const runtimes = {
4463
5416
  "maxDepth": 1,
4464
5417
  "background": true,
4465
5418
  "subagentToolkit": "full",
4466
- "backgroundDispatch": true
5419
+ "backgroundDispatch": true,
5420
+ "isolation": "orchestrator-worktree"
4467
5421
  },
4468
5422
  "modelMode": "passive",
4469
5423
  "hookBus": "host",
4470
5424
  "stateIO": "filesystem",
4471
5425
  "transport": "mcp",
4472
- "runtime": "node"
5426
+ "runtime": "node",
5427
+ "effortSurface": "argv"
5428
+ },
5429
+ "orchestratorExec": {
5430
+ "command": "codex",
5431
+ "args": [
5432
+ "exec"
5433
+ ],
5434
+ "cwdFlag": "--cd",
5435
+ "promptFlag": null
4473
5436
  },
4474
5437
  "hostBehaviors": {
4475
5438
  "reapplyCommand": "$gsd-update --reapply",
@@ -4479,12 +5442,55 @@ const runtimes = {
4479
5442
  "frontmatterDialect": "codex",
4480
5443
  "reviewerCli": true
4481
5444
  }
5445
+ },
5446
+ "reviewer": {
5447
+ "slug": "codex",
5448
+ "flags": [
5449
+ "--codex"
5450
+ ],
5451
+ "transport": "spawn",
5452
+ "probe": {
5453
+ "kind": "command-exists",
5454
+ "binary": "codex"
5455
+ },
5456
+ "invoke": {
5457
+ "binary": "codex",
5458
+ "args": [
5459
+ "exec",
5460
+ "--ephemeral",
5461
+ "{{model}}",
5462
+ "{{effort}}",
5463
+ "--skip-git-repo-check",
5464
+ "{{output}}",
5465
+ "-"
5466
+ ],
5467
+ "promptChannel": "stdin",
5468
+ "outputChannel": "file-arg",
5469
+ "outputArg": "-o",
5470
+ "modelArg": "--model",
5471
+ "effortChannel": "argv"
5472
+ },
5473
+ "timeoutFloorMs": 1200000,
5474
+ "emptyOutput": "stub-with-stderr",
5475
+ "reviewsSection": "Codex",
5476
+ "evidenceClass": "source-grounded",
5477
+ "requiresBinaries": [],
5478
+ "promptBudgetKey": null,
5479
+ "modelConfigKey": "review.models.codex",
5480
+ "handler": null
5481
+ },
5482
+ "config": {
5483
+ "review.models.codex": {
5484
+ "type": "string",
5485
+ "default": "",
5486
+ "description": "Model passed to the Codex reviewer lane."
5487
+ }
4482
5488
  }
4483
5489
  },
4484
5490
  "copilot": {
4485
5491
  "id": "copilot",
4486
5492
  "role": "runtime",
4487
- "version": "1.7.0",
5493
+ "version": "1.9.0",
4488
5494
  "title": "GitHub Copilot",
4489
5495
  "description": "GitHub Copilot (VS Code) — markdown config format; copilot-inline hook surface; no hook events emitted; flat skill nesting (unconfirmed recursive loader); tier-2 support.",
4490
5496
  "tier": "core",
@@ -4558,13 +5564,15 @@ const runtimes = {
4558
5564
  "maxDepth": 1,
4559
5565
  "background": true,
4560
5566
  "subagentToolkit": "full",
4561
- "backgroundDispatch": false
5567
+ "backgroundDispatch": false,
5568
+ "isolation": "undocumented"
4562
5569
  },
4563
5570
  "modelMode": "passive",
4564
5571
  "hookBus": "host",
4565
5572
  "stateIO": "filesystem",
4566
5573
  "transport": "mcp",
4567
- "runtime": "undocumented"
5574
+ "runtime": "undocumented",
5575
+ "effortSurface": "undocumented"
4568
5576
  },
4569
5577
  "hostBehaviors": {
4570
5578
  "reapplyCommand": "/gsd-update --reapply",
@@ -4577,7 +5585,7 @@ const runtimes = {
4577
5585
  "cursor": {
4578
5586
  "id": "cursor",
4579
5587
  "role": "runtime",
4580
- "version": "1.7.0",
5588
+ "version": "1.9.0",
4581
5589
  "title": "Cursor",
4582
5590
  "description": "Cursor IDE — skills + converted commands artifact layout; hooks.json surface; Claude hook event dialect; recursive skill loader (flat nesting); tier-2 support.",
4583
5591
  "tier": "core",
@@ -4667,14 +5675,17 @@ const runtimes = {
4667
5675
  "maxDepth": 2,
4668
5676
  "background": true,
4669
5677
  "subagentToolkit": "full",
4670
- "backgroundDispatch": true
5678
+ "backgroundDispatch": true,
5679
+ "isolation": "harness-worktree"
4671
5680
  },
4672
5681
  "modelMode": "passive",
4673
5682
  "hookBus": "host",
4674
5683
  "stateIO": "filesystem",
4675
5684
  "transport": "mcp",
4676
- "runtime": "node"
5685
+ "runtime": "node",
5686
+ "effortSurface": "undocumented"
4677
5687
  },
5688
+ "harnessIsolationFlag": "--worktree",
4678
5689
  "hostBehaviors": {
4679
5690
  "reapplyCommand": "gsd-update --reapply (mention the skill name)",
4680
5691
  "frontmatterDialect": "cursor",
@@ -4693,12 +5704,47 @@ const runtimes = {
4693
5704
  ],
4694
5705
  "reviewerCli": true
4695
5706
  }
5707
+ },
5708
+ "reviewer": {
5709
+ "slug": "cursor",
5710
+ "flags": [
5711
+ "--cursor"
5712
+ ],
5713
+ "transport": "spawn",
5714
+ "probe": {
5715
+ "kind": "command-exists",
5716
+ "binary": "cursor-agent"
5717
+ },
5718
+ "invoke": {
5719
+ "binary": "cursor-agent",
5720
+ "args": [
5721
+ "-p",
5722
+ "--mode",
5723
+ "ask",
5724
+ "--trust",
5725
+ "--output-format",
5726
+ "text",
5727
+ "{{prompt}}"
5728
+ ],
5729
+ "promptChannel": "argv-file-ref",
5730
+ "outputChannel": "stdout",
5731
+ "modelArg": null,
5732
+ "effortChannel": "none"
5733
+ },
5734
+ "timeoutFloorMs": 900000,
5735
+ "emptyOutput": "stub-with-stderr",
5736
+ "reviewsSection": "Cursor",
5737
+ "evidenceClass": "source-grounded",
5738
+ "requiresBinaries": [],
5739
+ "promptBudgetKey": null,
5740
+ "modelConfigKey": null,
5741
+ "handler": null
4696
5742
  }
4697
5743
  },
4698
5744
  "hermes": {
4699
5745
  "id": "hermes",
4700
5746
  "role": "runtime",
4701
- "version": "1.7.0",
5747
+ "version": "1.9.0",
4702
5748
  "title": "Hermes Agent",
4703
5749
  "description": "Hermes Agent (NousResearch) — skills nest under skills/gsd/ category bucket; nested skill layout; settings-json hook surface; Claude hook event dialect; tier-2 support.",
4704
5750
  "tier": "core",
@@ -4774,20 +5820,22 @@ const runtimes = {
4774
5820
  "maxDepth": 1,
4775
5821
  "background": true,
4776
5822
  "subagentToolkit": "read-only",
4777
- "backgroundDispatch": false
5823
+ "backgroundDispatch": false,
5824
+ "isolation": "undocumented"
4778
5825
  },
4779
5826
  "modelMode": "active",
4780
5827
  "hookBus": "host",
4781
5828
  "stateIO": "filesystem",
4782
5829
  "transport": "mcp",
4783
- "runtime": "python"
5830
+ "runtime": "python",
5831
+ "effortSurface": "undocumented"
4784
5832
  }
4785
5833
  }
4786
5834
  },
4787
5835
  "kilo": {
4788
5836
  "id": "kilo",
4789
5837
  "role": "runtime",
4790
- "version": "1.7.0",
5838
+ "version": "1.9.0",
4791
5839
  "title": "Kilo Code",
4792
5840
  "description": "Kilo Code — XDG-based config dir; global skills at ~/.kilo/skills (separate from XDG config); flat command/ + skills artifact layout; no lifecycle hook registration; tier-2 support.",
4793
5841
  "tier": "core",
@@ -4868,13 +5916,15 @@ const runtimes = {
4868
5916
  "maxDepth": -1,
4869
5917
  "background": true,
4870
5918
  "subagentToolkit": "undocumented",
4871
- "backgroundDispatch": false
5919
+ "backgroundDispatch": false,
5920
+ "isolation": "undocumented"
4872
5921
  },
4873
5922
  "modelMode": "active",
4874
5923
  "hookBus": "host",
4875
5924
  "stateIO": "filesystem",
4876
5925
  "transport": "mcp",
4877
- "runtime": "bun"
5926
+ "runtime": "bun",
5927
+ "effortSurface": "undocumented"
4878
5928
  },
4879
5929
  "hostBehaviors": {
4880
5930
  "reapplyCommand": "/gsd-update --reapply",
@@ -4887,15 +5937,14 @@ const runtimes = {
4887
5937
  "file": "gsd-core.js",
4888
5938
  "source": ".kilo/plugins/gsd-core.js"
4889
5939
  },
4890
- "skipUpdateBannerCommand": true,
4891
- "skipSharedHooksInstall": true
5940
+ "skipUpdateBannerCommand": true
4892
5941
  }
4893
5942
  }
4894
5943
  },
4895
5944
  "kimi": {
4896
5945
  "id": "kimi",
4897
5946
  "role": "runtime",
4898
- "version": "1.7.0",
5947
+ "version": "1.9.0",
4899
5948
  "title": "Kimi CLI",
4900
5949
  "description": "Kimi CLI (Moonshot AI) — generic agents root at ~/.config/agents; skills + kimi-agents artifact layout; native config.toml [[hooks]] bus at ~/.kimi/config.toml; background dispatch; tier-2 support.",
4901
5950
  "tier": "core",
@@ -4962,13 +6011,23 @@ const runtimes = {
4962
6011
  "maxDepth": 1,
4963
6012
  "background": true,
4964
6013
  "subagentToolkit": "undocumented",
4965
- "backgroundDispatch": true
6014
+ "backgroundDispatch": true,
6015
+ "isolation": "orchestrator-worktree"
4966
6016
  },
4967
6017
  "modelMode": "passive",
4968
6018
  "hookBus": "host",
4969
6019
  "stateIO": "filesystem",
4970
6020
  "transport": "mcp",
4971
- "runtime": "python"
6021
+ "runtime": "python",
6022
+ "effortSurface": "undocumented"
6023
+ },
6024
+ "orchestratorExec": {
6025
+ "command": "kimi",
6026
+ "args": [
6027
+ "--print"
6028
+ ],
6029
+ "cwdFlag": "--work-dir",
6030
+ "promptFlag": "--prompt"
4972
6031
  },
4973
6032
  "hostBehaviors": {
4974
6033
  "reapplyCommand": "/skill:gsd-update --reapply",
@@ -4980,12 +6039,144 @@ const runtimes = {
4980
6039
  }
4981
6040
  }
4982
6041
  },
6042
+ "kimi-code": {
6043
+ "id": "kimi-code",
6044
+ "role": "runtime",
6045
+ "version": "1.9.0",
6046
+ "title": "Kimi Code CLI",
6047
+ "description": "Kimi Code CLI (Moonshot AI, Node) — Agent Skills auto-discovered at ~/.kimi-code/skills; global AGENTS.md at ~/.kimi-code/AGENTS.md; native config.toml + [[hooks]] bus; three built-in subagents (coder/explore/plan), NO custom named subagents; background dispatch; tier-2 support. Distinct from Python kimi-cli (the 'kimi' capability) per ADR-1239 EoS — Kimi Code cannot dispatch named subagents so the kimi-agents YAML layout does NOT apply; persona injection rides the existing ${AGENT_SKILLS_*} workflow fallback. Install-layout, agent-install-check, and install-time decision (kimi vs kimi-code) land in follow-up PRs; this descriptor is the EoS foundation.",
6048
+ "tier": "core",
6049
+ "requires": [],
6050
+ "engines": {
6051
+ "gsd": ">=1.7.0"
6052
+ },
6053
+ "runtime": {
6054
+ "configHome": {
6055
+ "kind": "dot-home",
6056
+ "name": ".kimi-code",
6057
+ "env": [
6058
+ "KIMI_CODE_HOME"
6059
+ ],
6060
+ "probe": [
6061
+ "~/.kimi-code"
6062
+ ],
6063
+ "probeExists": "config.toml"
6064
+ },
6065
+ "localConfigDir": ".kimi-code",
6066
+ "configFormat": "none",
6067
+ "artifactLayout": {
6068
+ "global": [
6069
+ {
6070
+ "kind": "skills",
6071
+ "destSubpath": "skills",
6072
+ "prefix": "gsd-",
6073
+ "nesting": "flat",
6074
+ "recursive": false,
6075
+ "converter": "convertClaudeCommandToKimiCodeSkill"
6076
+ }
6077
+ ],
6078
+ "local": []
6079
+ },
6080
+ "commandStyle": "slash-hyphen",
6081
+ "hooksSurface": "kimi-hooks-toml",
6082
+ "hookEvents": "claude",
6083
+ "sandboxTier": "none",
6084
+ "supportTier": 2,
6085
+ "installSurface": "profile-marker-only",
6086
+ "writesSharedSettings": false,
6087
+ "permissionWriter": null,
6088
+ "extendedHookEvents": [
6089
+ "SubagentStop",
6090
+ "Stop",
6091
+ "PreCompact",
6092
+ "SubagentStart"
6093
+ ],
6094
+ "hostIntegration": {
6095
+ "embeddingMode": "declarative",
6096
+ "commandSurface": "slash-file",
6097
+ "dispatch": {
6098
+ "namedDispatch": false,
6099
+ "nested": true,
6100
+ "maxDepth": "undocumented",
6101
+ "background": true,
6102
+ "subagentToolkit": "built-in-only",
6103
+ "backgroundDispatch": true,
6104
+ "builtInSubagents": [
6105
+ "coder",
6106
+ "explore",
6107
+ "plan"
6108
+ ],
6109
+ "isolation": "orchestrator-worktree"
6110
+ },
6111
+ "modelMode": "passive",
6112
+ "hookBus": "host",
6113
+ "stateIO": "filesystem",
6114
+ "transport": "mcp",
6115
+ "runtime": "node"
6116
+ },
6117
+ "orchestratorExec": {
6118
+ "command": "kimi",
6119
+ "args": [],
6120
+ "cwdFlag": null,
6121
+ "promptFlag": "--prompt"
6122
+ },
6123
+ "hostBehaviors": {
6124
+ "reapplyCommand": "/skill:gsd-update --reapply",
6125
+ "localInstallDeferred": true,
6126
+ "verificationStyle": "kimi-code",
6127
+ "agentManifestStyle": "none",
6128
+ "doneBannerStyle": "kimi-code",
6129
+ "skipSharedHooksInstall": true,
6130
+ "namedSubagentsSupported": false
6131
+ }
6132
+ },
6133
+ "reviewer": {
6134
+ "slug": "kimi-code",
6135
+ "flags": [
6136
+ "--kimi-code"
6137
+ ],
6138
+ "transport": "spawn",
6139
+ "probe": {
6140
+ "kind": "command-capability",
6141
+ "binary": "kimi",
6142
+ "needle": "--output-format",
6143
+ "timeoutMs": 5000
6144
+ },
6145
+ "invoke": {
6146
+ "binary": "kimi",
6147
+ "args": [
6148
+ "{{model}}",
6149
+ "-p",
6150
+ "{{prompt}}"
6151
+ ],
6152
+ "promptChannel": "argv-file-ref",
6153
+ "outputChannel": "stdout",
6154
+ "modelArg": "-m",
6155
+ "effortChannel": "none"
6156
+ },
6157
+ "timeoutFloorMs": 900000,
6158
+ "emptyOutput": "stub-with-stderr",
6159
+ "reviewsSection": "Kimi Code",
6160
+ "evidenceClass": "source-grounded",
6161
+ "requiresBinaries": [],
6162
+ "promptBudgetKey": null,
6163
+ "modelConfigKey": "review.models.kimi-code",
6164
+ "handler": null
6165
+ },
6166
+ "config": {
6167
+ "review.models.kimi-code": {
6168
+ "type": "string",
6169
+ "default": "",
6170
+ "description": "Model passed to the Kimi Code reviewer lane."
6171
+ }
6172
+ }
6173
+ },
4983
6174
  "opencode": {
4984
6175
  "id": "opencode",
4985
6176
  "role": "runtime",
4986
- "version": "1.7.0",
6177
+ "version": "1.9.0",
4987
6178
  "title": "OpenCode",
4988
- "description": "OpenCode — XDG-based config dir; flat command/ + skills artifact layout; settings-json config format; no lifecycle hook registration; tier-2 support.",
6179
+ "description": "OpenCode — XDG-based config dir; flat commands/ + skills artifact layout; settings-json config format; no lifecycle hook registration; tier-2 support.",
4989
6180
  "tier": "core",
4990
6181
  "requires": [],
4991
6182
  "engines": {
@@ -5007,7 +6198,7 @@ const runtimes = {
5007
6198
  "global": [
5008
6199
  {
5009
6200
  "kind": "commands",
5010
- "destSubpath": "command",
6201
+ "destSubpath": "commands",
5011
6202
  "prefix": "gsd-",
5012
6203
  "nesting": "flat",
5013
6204
  "recursive": false,
@@ -5025,7 +6216,7 @@ const runtimes = {
5025
6216
  "local": [
5026
6217
  {
5027
6218
  "kind": "commands",
5028
- "destSubpath": "command",
6219
+ "destSubpath": "commands",
5029
6220
  "prefix": "gsd-",
5030
6221
  "nesting": "flat",
5031
6222
  "recursive": false,
@@ -5057,20 +6248,30 @@ const runtimes = {
5057
6248
  "namedDispatch": true,
5058
6249
  "nested": "undocumented",
5059
6250
  "maxDepth": "undocumented",
5060
- "background": true,
6251
+ "background": false,
5061
6252
  "subagentToolkit": "full",
5062
- "backgroundDispatch": true
6253
+ "backgroundDispatch": false,
6254
+ "isolation": "orchestrator-worktree"
5063
6255
  },
5064
6256
  "modelMode": "active",
5065
6257
  "hookBus": "host",
5066
6258
  "stateIO": "filesystem",
5067
6259
  "transport": "mcp",
5068
- "runtime": "bun"
6260
+ "runtime": "bun",
6261
+ "effortSurface": "argv"
6262
+ },
6263
+ "orchestratorExec": {
6264
+ "command": "opencode",
6265
+ "args": [
6266
+ "run"
6267
+ ],
6268
+ "cwdFlag": "--dir",
6269
+ "promptFlag": null
5069
6270
  },
5070
6271
  "hostBehaviors": {
5071
6272
  "reapplyCommand": "/gsd-update --reapply",
5072
6273
  "attributionConfigResolver": "opencode",
5073
- "flatCommandDir": "command",
6274
+ "flatCommandDir": "commands",
5074
6275
  "combinedFamilyInstall": true,
5075
6276
  "frontmatterDialect": "opencode",
5076
6277
  "nativePlugin": {
@@ -5084,14 +6285,55 @@ const runtimes = {
5084
6285
  "skipCodexSkillsManifest": true,
5085
6286
  "reviewerCli": true
5086
6287
  }
6288
+ },
6289
+ "reviewer": {
6290
+ "slug": "opencode",
6291
+ "flags": [
6292
+ "--opencode"
6293
+ ],
6294
+ "transport": "spawn",
6295
+ "probe": {
6296
+ "kind": "command-exists",
6297
+ "binary": "opencode"
6298
+ },
6299
+ "invoke": {
6300
+ "binary": "opencode",
6301
+ "args": [
6302
+ "run",
6303
+ "{{model}}",
6304
+ "{{effort}}",
6305
+ "--format",
6306
+ "json",
6307
+ "-"
6308
+ ],
6309
+ "promptChannel": "stdin",
6310
+ "outputChannel": "stdout",
6311
+ "modelArg": "--model",
6312
+ "effortChannel": "argv"
6313
+ },
6314
+ "timeoutFloorMs": 660000,
6315
+ "emptyOutput": "stub-with-stderr",
6316
+ "reviewsSection": "OpenCode",
6317
+ "evidenceClass": "source-grounded",
6318
+ "requiresBinaries": [],
6319
+ "promptBudgetKey": null,
6320
+ "modelConfigKey": "review.models.opencode",
6321
+ "handler": "opencode"
6322
+ },
6323
+ "config": {
6324
+ "review.models.opencode": {
6325
+ "type": "string",
6326
+ "default": "",
6327
+ "description": "Model passed to the OpenCode reviewer lane."
6328
+ }
5087
6329
  }
5088
6330
  },
5089
6331
  "pi": {
5090
6332
  "id": "pi",
5091
6333
  "role": "runtime",
5092
- "version": "1.7.0",
6334
+ "version": "1.9.0",
5093
6335
  "title": "pi",
5094
- "description": "pi (pi.dev) — bun-runtime programmatic-CLI; TS ExtensionAPI (registerCommand/registerTool/registerProvider/pi.on); single native-extension file at ~/.pi/agent/extensions/gsd.cjs; no shared-settings hook surface; tier-2 support.",
6336
+ "description": "pi (pi.dev) — bun-runtime programmatic-CLI; TS ExtensionAPI (registerCommand/registerTool/registerProvider/pi.on); single native-extension file at ~/.pi/agent/extensions/gsd.js (.js, not .cjs — pi's extension auto-discovery accepts only .ts/.js, #2470); no shared-settings hook surface; tier-2 support.",
5095
6337
  "tier": "core",
5096
6338
  "requires": [],
5097
6339
  "engines": {
@@ -5128,18 +6370,20 @@ const runtimes = {
5128
6370
  "maxDepth": 0,
5129
6371
  "background": false,
5130
6372
  "backgroundDispatch": false,
5131
- "subagentToolkit": "undocumented"
6373
+ "subagentToolkit": "undocumented",
6374
+ "isolation": "none"
5132
6375
  },
5133
6376
  "modelMode": "active",
5134
6377
  "hookBus": "host",
5135
6378
  "stateIO": "session-log-append",
5136
6379
  "transport": "native-extension",
5137
- "runtime": "bun"
6380
+ "runtime": "bun",
6381
+ "effortSurface": "undocumented"
5138
6382
  },
5139
6383
  "hostBehaviors": {
5140
6384
  "nativePlugin": {
5141
6385
  "dir": "extensions",
5142
- "file": "gsd.cjs",
6386
+ "file": "gsd.js",
5143
6387
  "source": "pi/gsd.cjs"
5144
6388
  },
5145
6389
  "pluginOnlyInstall": true
@@ -5149,7 +6393,7 @@ const runtimes = {
5149
6393
  "qwen": {
5150
6394
  "id": "qwen",
5151
6395
  "role": "runtime",
5152
- "version": "1.7.0",
6396
+ "version": "1.9.0",
5153
6397
  "title": "Qwen Code",
5154
6398
  "description": "Qwen Code (Alibaba) — nested-skill artifact layout; settings-json hook surface; Claude hook event dialect; tier-2 support.",
5155
6399
  "tier": "core",
@@ -5228,13 +6472,15 @@ const runtimes = {
5228
6472
  "maxDepth": 1,
5229
6473
  "background": true,
5230
6474
  "subagentToolkit": "full",
5231
- "backgroundDispatch": false
6475
+ "backgroundDispatch": false,
6476
+ "isolation": "undocumented"
5232
6477
  },
5233
6478
  "modelMode": "passive",
5234
6479
  "hookBus": "host",
5235
6480
  "stateIO": "filesystem",
5236
6481
  "transport": "mcp",
5237
- "runtime": "node"
6482
+ "runtime": "node",
6483
+ "effortSurface": "undocumented"
5238
6484
  },
5239
6485
  "hostBehaviors": {
5240
6486
  "skillPriorityFrontmatter": true,
@@ -5249,12 +6495,41 @@ const runtimes = {
5249
6495
  "hyphenNameAgentBody": true,
5250
6496
  "reviewerCli": true
5251
6497
  }
6498
+ },
6499
+ "reviewer": {
6500
+ "slug": "qwen",
6501
+ "flags": [
6502
+ "--qwen"
6503
+ ],
6504
+ "transport": "spawn",
6505
+ "probe": {
6506
+ "kind": "command-exists",
6507
+ "binary": "qwen"
6508
+ },
6509
+ "invoke": {
6510
+ "binary": "qwen",
6511
+ "args": [
6512
+ "-"
6513
+ ],
6514
+ "promptChannel": "stdin",
6515
+ "outputChannel": "stdout",
6516
+ "modelArg": null,
6517
+ "effortChannel": "none"
6518
+ },
6519
+ "timeoutFloorMs": 900000,
6520
+ "emptyOutput": "stub-with-stderr",
6521
+ "reviewsSection": "Qwen",
6522
+ "evidenceClass": "source-grounded",
6523
+ "requiresBinaries": [],
6524
+ "promptBudgetKey": null,
6525
+ "modelConfigKey": null,
6526
+ "handler": null
5252
6527
  }
5253
6528
  },
5254
6529
  "trae": {
5255
6530
  "id": "trae",
5256
6531
  "role": "runtime",
5257
- "version": "1.7.0",
6532
+ "version": "1.9.0",
5258
6533
  "title": "Trae IDE",
5259
6534
  "description": "Trae IDE — nested-skill artifact layout; no hook surface (profile-marker-only config); tier-2 support.",
5260
6535
  "tier": "core",
@@ -5327,13 +6602,15 @@ const runtimes = {
5327
6602
  "maxDepth": "undocumented",
5328
6603
  "background": true,
5329
6604
  "subagentToolkit": "undocumented",
5330
- "backgroundDispatch": "undocumented"
6605
+ "backgroundDispatch": "undocumented",
6606
+ "isolation": "undocumented"
5331
6607
  },
5332
6608
  "modelMode": "passive",
5333
6609
  "hookBus": "engine",
5334
6610
  "stateIO": "filesystem",
5335
6611
  "transport": "mcp",
5336
- "runtime": "node"
6612
+ "runtime": "node",
6613
+ "effortSurface": "undocumented"
5337
6614
  },
5338
6615
  "hostBehaviors": {
5339
6616
  "skipSharedHooksInstall": true,
@@ -5344,7 +6621,7 @@ const runtimes = {
5344
6621
  "vscode": {
5345
6622
  "id": "vscode",
5346
6623
  "role": "runtime",
5347
- "version": "1.7.0",
6624
+ "version": "1.9.0",
5348
6625
  "title": "VS Code",
5349
6626
  "description": "VS Code — Marketplace/VSIX extension; no file-projected config directory; IDE-profile reference host (active vscode.lm model, engine-owned hook bus, sandboxed globalState/workspaceState stateIO).",
5350
6627
  "tier": "core",
@@ -5382,20 +6659,22 @@ const runtimes = {
5382
6659
  "maxDepth": 5,
5383
6660
  "background": true,
5384
6661
  "subagentToolkit": "undocumented",
5385
- "backgroundDispatch": "undocumented"
6662
+ "backgroundDispatch": "undocumented",
6663
+ "isolation": "undocumented"
5386
6664
  },
5387
6665
  "modelMode": "active",
5388
6666
  "hookBus": "engine",
5389
6667
  "stateIO": "sandboxed-storage",
5390
6668
  "transport": "mcp",
5391
- "runtime": "sandboxed-web"
6669
+ "runtime": "sandboxed-web",
6670
+ "effortSurface": "undocumented"
5392
6671
  }
5393
6672
  }
5394
6673
  },
5395
6674
  "windsurf": {
5396
6675
  "id": "windsurf",
5397
6676
  "role": "runtime",
5398
- "version": "1.7.0",
6677
+ "version": "1.9.0",
5399
6678
  "title": "Windsurf",
5400
6679
  "description": "Windsurf (Codeium) — workspace workflow artifact layout for slash commands; Cascade native hooks.json blocking hook bus (pre_write_code, pre_run_command); tier-2 support.",
5401
6680
  "tier": "core",
@@ -5461,13 +6740,15 @@ const runtimes = {
5461
6740
  "maxDepth": "undocumented",
5462
6741
  "background": "undocumented",
5463
6742
  "subagentToolkit": "undocumented",
5464
- "backgroundDispatch": "undocumented"
6743
+ "backgroundDispatch": "undocumented",
6744
+ "isolation": "none"
5465
6745
  },
5466
6746
  "modelMode": "passive",
5467
6747
  "hookBus": "host",
5468
6748
  "stateIO": "filesystem",
5469
6749
  "transport": "mcp",
5470
- "runtime": "undocumented"
6750
+ "runtime": "undocumented",
6751
+ "effortSurface": "undocumented"
5471
6752
  },
5472
6753
  "hostBehaviors": {
5473
6754
  "skipSharedHooksInstall": true,
@@ -5480,7 +6761,7 @@ const runtimes = {
5480
6761
  "zcode": {
5481
6762
  "id": "zcode",
5482
6763
  "role": "runtime",
5483
- "version": "1.7.0",
6764
+ "version": "1.9.0",
5484
6765
  "title": "ZCode",
5485
6766
  "description": "ZCode (Z.ai) — desktop Agentic Development Environment for GLM-5.2; Claude-shaped nested skills at ~/.zcode/skills/<name>/SKILL.md, slash commands, named subagents, native MCP; declarative plugin surface; profile-marker install; tier-2 community support.",
5486
6767
  "tier": "core",
@@ -5569,13 +6850,15 @@ const runtimes = {
5569
6850
  "maxDepth": "undocumented",
5570
6851
  "background": false,
5571
6852
  "subagentToolkit": "full",
5572
- "backgroundDispatch": false
6853
+ "backgroundDispatch": false,
6854
+ "isolation": "none"
5573
6855
  },
5574
6856
  "modelMode": "passive",
5575
6857
  "hookBus": "host",
5576
6858
  "stateIO": "filesystem",
5577
6859
  "transport": "mcp",
5578
- "runtime": "electron"
6860
+ "runtime": "electron",
6861
+ "effortSurface": "undocumented"
5579
6862
  },
5580
6863
  "hostBehaviors": {
5581
6864
  "skipSharedHooksInstall": true
@@ -5738,24 +7021,31 @@ const _requiresGraph = {
5738
7021
  "assumption-delta": [],
5739
7022
  "audit": [],
5740
7023
  "augment": [],
7024
+ "broken-windows": [],
5741
7025
  "claude": [],
5742
7026
  "claude-orchestration": [],
5743
7027
  "cline": [],
5744
7028
  "code-review": [],
5745
7029
  "codebuddy": [],
7030
+ "coderabbit": [],
5746
7031
  "codex": [],
5747
7032
  "copilot": [],
5748
7033
  "cursor": [],
5749
7034
  "drift": [],
5750
7035
  "external-job": [],
5751
7036
  "gap-analysis": [],
7037
+ "gemini": [],
5752
7038
  "graphify": [],
5753
7039
  "hermes": [],
5754
7040
  "intel": [],
5755
7041
  "kilo": [],
5756
7042
  "kimi": [],
7043
+ "kimi-code": [],
7044
+ "llama-cpp": [],
7045
+ "lm-studio": [],
5757
7046
  "mempalace": [],
5758
7047
  "nyquist": [],
7048
+ "ollama": [],
5759
7049
  "opencode": [],
5760
7050
  "pattern-mapper": [
5761
7051
  "research"