@opengsd/gsd-core 1.8.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 (174) 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 +31 -1
  4. package/agents/gsd-code-fixer.md +1 -1
  5. package/agents/gsd-codebase-mapper.md +1 -1
  6. package/agents/gsd-debug-session-manager.md +36 -0
  7. package/agents/gsd-executor.md +20 -7
  8. package/agents/gsd-intel-updater.md +3 -3
  9. package/agents/gsd-phase-researcher.md +4 -2
  10. package/agents/gsd-plan-checker.md +20 -0
  11. package/agents/gsd-planner.md +15 -23
  12. package/agents/gsd-project-researcher.md +2 -2
  13. package/agents/gsd-ui-auditor.md +0 -40
  14. package/bin/install.js +186 -55
  15. package/commands/gsd/plan-review-convergence.md +5 -1
  16. package/gsd-core/bin/gsd-tools.cjs +849 -2
  17. package/gsd-core/bin/lib/api-coverage.cjs +22 -8
  18. package/gsd-core/bin/lib/audit.cjs +8 -8
  19. package/gsd-core/bin/lib/capability-consent.cjs +40 -1
  20. package/gsd-core/bin/lib/capability-lifecycle.cjs +58 -0
  21. package/gsd-core/bin/lib/capability-loader.cjs +23 -1
  22. package/gsd-core/bin/lib/capability-registry.cjs +1353 -132
  23. package/gsd-core/bin/lib/capability-trust.cjs +468 -33
  24. package/gsd-core/bin/lib/capability-validator.cjs +882 -6
  25. package/gsd-core/bin/lib/check-command-router.cjs +12 -2
  26. package/gsd-core/bin/lib/cjs-command-router-adapter.cjs +15 -0
  27. package/gsd-core/bin/lib/claude-orchestration-command-router.cjs +102 -12
  28. package/gsd-core/bin/lib/claude-orchestration.cjs +125 -22
  29. package/gsd-core/bin/lib/commands.cjs +246 -18
  30. package/gsd-core/bin/lib/config-loader.cjs +200 -28
  31. package/gsd-core/bin/lib/config.cjs +90 -5
  32. package/gsd-core/bin/lib/estimate-cli.cjs +336 -0
  33. package/gsd-core/bin/lib/frontmatter.cjs +125 -15
  34. package/gsd-core/bin/lib/host-integration.cjs +215 -8
  35. package/gsd-core/bin/lib/init.cjs +44 -19
  36. package/gsd-core/bin/lib/install-engine.cjs +1 -0
  37. package/gsd-core/bin/lib/milestone.cjs +5 -5
  38. package/gsd-core/bin/lib/model-catalog.cjs +51 -1
  39. package/gsd-core/bin/lib/observability/logger.cjs +7 -2
  40. package/gsd-core/bin/lib/phase-command-router.cjs +10 -1
  41. package/gsd-core/bin/lib/phase-estimation.cjs +398 -0
  42. package/gsd-core/bin/lib/phase-id.cjs +278 -5
  43. package/gsd-core/bin/lib/phase.cjs +57 -5
  44. package/gsd-core/bin/lib/plan-drift-guard.cjs +1 -1
  45. package/gsd-core/bin/lib/plan-scan.cjs +1 -1
  46. package/gsd-core/bin/lib/planning-workspace.cjs +9 -2
  47. package/gsd-core/bin/lib/profile-output.cjs +34 -8
  48. package/gsd-core/bin/lib/review-lane-descriptor.cjs +927 -0
  49. package/gsd-core/bin/lib/review-lane-invocation.cjs +348 -0
  50. package/gsd-core/bin/lib/review-lane-runner.cjs +594 -0
  51. package/gsd-core/bin/lib/review-reviewer-selection.cjs +114 -32
  52. package/gsd-core/bin/lib/roadmap-parser.cjs +54 -6
  53. package/gsd-core/bin/lib/roadmap.cjs +10 -4
  54. package/gsd-core/bin/lib/runtime-artifact-conversion.cjs +31 -4
  55. package/gsd-core/bin/lib/runtime-artifact-layout.cjs +1 -1
  56. package/gsd-core/bin/lib/runtime-hooks-surface.cjs +140 -0
  57. package/gsd-core/bin/lib/runtime-name-policy.cjs +15 -2
  58. package/gsd-core/bin/lib/smart-entry.cjs +1 -1
  59. package/gsd-core/bin/lib/state-document.cjs +164 -20
  60. package/gsd-core/bin/lib/state-transition.cjs +28 -10
  61. package/gsd-core/bin/lib/state.cjs +141 -21
  62. package/gsd-core/bin/lib/uat-predicate.cjs +6 -4
  63. package/gsd-core/bin/lib/uat.cjs +9 -7
  64. package/gsd-core/bin/lib/ui-consideration-probe.cjs +2 -2
  65. package/gsd-core/bin/lib/unusable-input.cjs +216 -0
  66. package/gsd-core/bin/lib/validate.cjs +32 -0
  67. package/gsd-core/bin/lib/verification.cjs +51 -14
  68. package/gsd-core/bin/lib/verify.cjs +128 -20
  69. package/gsd-core/bin/lib/worktree-safety.cjs +360 -15
  70. package/gsd-core/bin/shared/config-defaults.manifest.json +1 -0
  71. package/gsd-core/bin/shared/config-schema.manifest.json +1 -13
  72. package/gsd-core/bin/shared/model-catalog.json +5 -0
  73. package/gsd-core/bin/shared/runtime-aliases.manifest.json +5 -0
  74. package/gsd-core/references/context-budget.md +40 -0
  75. package/gsd-core/references/gate-prompts.md +6 -3
  76. package/gsd-core/references/model-profile-resolution.md +64 -13
  77. package/gsd-core/references/offer-next.md +88 -0
  78. package/gsd-core/references/planning-config.md +2 -1
  79. package/gsd-core/references/reviewer-instances.md +28 -21
  80. package/gsd-core/references/runtime-aware-dispatch.md +42 -0
  81. package/gsd-core/references/ui-consideration-probe.md +2 -2
  82. package/gsd-core/references/worktree-branch-check.md +4 -4
  83. package/gsd-core/templates/summary-minimal.md +4 -0
  84. package/gsd-core/templates/summary-standard.md +4 -0
  85. package/gsd-core/templates/summary.md +7 -0
  86. package/gsd-core/workflows/ai-integration-phase.md +4 -4
  87. package/gsd-core/workflows/audit-fix.md +4 -0
  88. package/gsd-core/workflows/audit-milestone.md +8 -0
  89. package/gsd-core/workflows/autonomous.md +19 -15
  90. package/gsd-core/workflows/check-todos.md +2 -2
  91. package/gsd-core/workflows/code-review-fix.md +14 -6
  92. package/gsd-core/workflows/code-review.md +76 -19
  93. package/gsd-core/workflows/debug.md +10 -2
  94. package/gsd-core/workflows/diagnose-issues.md +4 -0
  95. package/gsd-core/workflows/discuss-phase/modes/advisor.md +2 -4
  96. package/gsd-core/workflows/discuss-phase/modes/auto.md +0 -6
  97. package/gsd-core/workflows/discuss-phase-assumptions.md +15 -9
  98. package/gsd-core/workflows/discuss-phase.md +2 -2
  99. package/gsd-core/workflows/docs-update.md +8 -0
  100. package/gsd-core/workflows/eval-review.md +1 -1
  101. package/gsd-core/workflows/execute-phase/steps/codebase-drift-gate.md +4 -0
  102. package/gsd-core/workflows/execute-phase/steps/executor-isolation-dispatch.md +160 -0
  103. package/gsd-core/workflows/execute-phase.md +85 -115
  104. package/gsd-core/workflows/execute-plan.md +5 -4
  105. package/gsd-core/workflows/explore.md +4 -0
  106. package/gsd-core/workflows/extract-learnings.md +21 -0
  107. package/gsd-core/workflows/help/modes/full.md +3 -3
  108. package/gsd-core/workflows/import.md +4 -1
  109. package/gsd-core/workflows/ingest-docs.md +4 -0
  110. package/gsd-core/workflows/map-codebase.md +13 -6
  111. package/gsd-core/workflows/new-milestone.md +10 -2
  112. package/gsd-core/workflows/new-project.md +11 -4
  113. package/gsd-core/workflows/next.md +5 -2
  114. package/gsd-core/workflows/plan-phase.md +42 -46
  115. package/gsd-core/workflows/plan-review-convergence.md +18 -14
  116. package/gsd-core/workflows/progress.md +1 -1
  117. package/gsd-core/workflows/quick.md +14 -3
  118. package/gsd-core/workflows/review.md +146 -575
  119. package/gsd-core/workflows/scan.md +9 -1
  120. package/gsd-core/workflows/secure-phase.md +10 -2
  121. package/gsd-core/workflows/ship.md +41 -11
  122. package/gsd-core/workflows/smart-entry.md +1 -1
  123. package/gsd-core/workflows/ui-phase.md +8 -1
  124. package/gsd-core/workflows/ui-review.md +8 -1
  125. package/gsd-core/workflows/update.md +104 -5
  126. package/gsd-core/workflows/validate-phase.md +10 -2
  127. package/gsd-core/workflows/verify-work.md +8 -1
  128. package/hooks/dist/gsd-cursor-session-start.js +6 -2
  129. package/hooks/dist/gsd-cursor-stop.js +6 -2
  130. package/hooks/dist/gsd-cursor-subagent-start.js +6 -2
  131. package/hooks/dist/gsd-graphify-update.sh +9 -0
  132. package/hooks/dist/gsd-phase-boundary.sh +14 -2
  133. package/hooks/dist/gsd-prompt-guard.js +101 -2
  134. package/hooks/dist/gsd-read-guard.js +100 -2
  135. package/hooks/dist/gsd-read-injection-scanner.js +109 -2
  136. package/hooks/dist/gsd-statusline.js +9 -6
  137. package/hooks/dist/gsd-workflow-guard.js +110 -6
  138. package/hooks/dist/gsd-worktree-path-guard.js +132 -8
  139. package/hooks/dist/lib/cursor-workspace.js +74 -0
  140. package/hooks/gsd-cursor-session-start.js +6 -2
  141. package/hooks/gsd-cursor-stop.js +6 -2
  142. package/hooks/gsd-cursor-subagent-start.js +6 -2
  143. package/hooks/gsd-graphify-update.sh +9 -0
  144. package/hooks/gsd-phase-boundary.sh +14 -2
  145. package/hooks/gsd-prompt-guard.js +101 -2
  146. package/hooks/gsd-read-guard.js +100 -2
  147. package/hooks/gsd-read-injection-scanner.js +109 -2
  148. package/hooks/gsd-statusline.js +9 -6
  149. package/hooks/gsd-workflow-guard.js +110 -6
  150. package/hooks/gsd-worktree-path-guard.js +132 -8
  151. package/hooks/lib/cursor-workspace.js +74 -0
  152. package/package.json +7 -7
  153. package/pi/gsd.cjs +26 -1
  154. package/scripts/check-coverage-gate.cjs +51 -0
  155. package/scripts/check-glossary-refs.cjs +24 -0
  156. package/scripts/ci-test-scope.cjs +67 -17
  157. package/scripts/gen-adr-index.cjs +6 -4
  158. package/scripts/gen-capability-matrix.cjs +26 -2
  159. package/scripts/gen-capability-registry.cjs +132 -34
  160. package/scripts/gen-emitted-baseline.cjs +145 -0
  161. package/scripts/lint-compiled-artifact-sync.cjs +146 -0
  162. package/scripts/lint-emitted-drift-ack.cjs +149 -0
  163. package/scripts/lint-fix-has-regression-test.cjs +131 -0
  164. package/scripts/lint-resolution-provenance.cjs +9 -0
  165. package/scripts/mutation-matrix.cjs +4 -0
  166. package/scripts/prompt-injection-scan.sh +6 -0
  167. package/scripts/registry-schema.cjs +57 -8
  168. package/scripts/release-notes/conventional-title.cjs +19 -1
  169. package/scripts/release-notes/format-github-release-notes.cjs +7 -3
  170. package/scripts/workflow-size.cjs +16 -8
  171. package/skills/gsd-plan-review-convergence/SKILL.md +5 -1
  172. package/vscode/package.json +1 -1
  173. package/scripts/gen-golden-install-parity-zcode.cjs +0 -77
  174. package/scripts/update-size-baseline.cjs +0 -68
@@ -33,6 +33,7 @@
33
33
  "_auto_chain_active": false,
34
34
  "node_repair": true,
35
35
  "node_repair_budget": 2,
36
+ "smart_zone_tokens": 100000,
36
37
  "ui_phase": true,
37
38
  "ui_safety_gate": true,
38
39
  "text_mode": false,
@@ -19,6 +19,7 @@
19
19
  "workflow.auto_advance",
20
20
  "workflow.node_repair",
21
21
  "workflow.node_repair_budget",
22
+ "workflow.smart_zone_tokens",
22
23
  "workflow.human_verify_mode",
23
24
  "workflow.text_mode",
24
25
  "workflow.research_before_questions",
@@ -48,9 +49,6 @@
48
49
  "planning.commit_docs",
49
50
  "planning.search_gitignored",
50
51
  "planning.sub_repos",
51
- "review.ollama_host",
52
- "review.lm_studio_host",
53
- "review.llama_cpp_host",
54
52
  "review.default_reviewers",
55
53
  "review.max_prompt_tokens",
56
54
  "review.max_prompt_tokens_per_reviewer",
@@ -117,11 +115,6 @@
117
115
  "source": "^agent_skills\\.[a-zA-Z0-9_-]+$",
118
116
  "description": "agent_skills.<agent-type>"
119
117
  },
120
- {
121
- "topLevel": "review",
122
- "source": "^review\\.models\\.[a-zA-Z0-9_-]+$",
123
- "description": "review.models.<cli-name>"
124
- },
125
118
  {
126
119
  "topLevel": "features",
127
120
  "source": "^features\\.[a-zA-Z0-9_]+$",
@@ -177,11 +170,6 @@
177
170
  "source": "^fast_mode\\.agent_overrides\\.[a-zA-Z0-9_-]+$",
178
171
  "description": "fast_mode.agent_overrides.<agent-id>"
179
172
  },
180
- {
181
- "topLevel": "review",
182
- "source": "^review\\.max_prompt_tokens_per_reviewer\\.[a-zA-Z0-9_-]+$",
183
- "description": "review.max_prompt_tokens_per_reviewer.<reviewer-slug>"
184
- },
185
173
  {
186
174
  "topLevel": "review",
187
175
  "source": "^review\\.reviewer_instances\\.[a-zA-Z0-9_-]+\\.(cli|model|agent)$",
@@ -52,6 +52,11 @@
52
52
  "sonnet": null,
53
53
  "haiku": null
54
54
  },
55
+ "kimi-code": {
56
+ "opus": null,
57
+ "sonnet": null,
58
+ "haiku": null
59
+ },
55
60
  "cursor": {
56
61
  "opus": null,
57
62
  "sonnet": null,
@@ -63,6 +63,11 @@
63
63
  "kimi": [
64
64
  "kimi"
65
65
  ],
66
+ "kimi-code": [
67
+ "kimi-code",
68
+ "kimicode",
69
+ "kimi_code"
70
+ ],
66
71
  "codebuddy": [
67
72
  "codebuddy",
68
73
  "codebuddy-cli"
@@ -83,3 +83,43 @@ Either list works — `enabledMcpjsonServers` is an explicit allow-list, `disabl
83
83
  ### Composition with model_profile
84
84
 
85
85
  Trimming MCPs and tuning `model_profile` are independent levers that **compound**. Disabling a 25k-token MCP saves 25k per turn whether you're running `quality` (opus everywhere) or `budget` (sonnet/haiku); the savings are additive, not in lieu of model tuning. Don't pick one — do both, and audit MCPs first because the per-turn savings show up immediately and stack across every subagent the orchestrator spawns.
86
+
87
+ ---
88
+
89
+ # Phase Sizing (gsd-planner)
90
+
91
+ ## Estimate Emission (#2631, ADR-2629)
92
+
93
+ Every plan carries an `estimate` block. It is the quantitative reason a phase must be sliced — tracer-first says *slice thin*, the estimate says *how thin, for this codebase*.
94
+
95
+ **Compute it:**
96
+ 1. Sum `estimateTokens`-scale cost across the plan: implementation + the files each task reads + verification output. Roughly chars/4 over what the executor will actually touch.
97
+ 2. Run `estimate-calibration` and **multiply your raw figure by its `factor`.** It is the measured estimate-vs-actual ratio for THIS project — a factor of 1 means there is not yet enough history to correct.
98
+ 3. `confidence` is **derived, not judged**: it is the `confidence` value from the same calibration query, keyed to the sample count (`low` <3, `med` 3–5, `high` ≥6). **Do not rate your own certainty.** Self-rated confidence was measured in this project and found weak (`references/honest-verifier.md:25-29`); every signal here routes on measured history instead.
99
+
100
+ **Over budget?** The plan-checker flags a plan whose estimate exceeds `workflow.smart_zone_tokens`. This is advisory — it never blocks. When flagged, re-slice: a tracer plus expansion slices, each inside the budget. Prefer more, smaller plans over one that spends the agent's best early-context tokens and finishes degraded.
101
+
102
+ ## Context Budget Rules
103
+
104
+ Plans should complete within ~50% context (not 80%). No context anxiety, quality maintained start to finish, room for unexpected complexity.
105
+
106
+ **Each plan: 2-3 tasks maximum.**
107
+
108
+ | Context Weight | Tasks/Plan | Context/Task | Total |
109
+ |----------------|------------|--------------|-------|
110
+ | Light (CRUD, config) | 3 | ~10-15% | ~30-45% |
111
+ | Medium (auth, payments) | 2 | ~20-30% | ~40-50% |
112
+ | Heavy (migrations, multi-subsystem) | 1-2 | ~30-40% | ~30-50% |
113
+
114
+ ## Split Signals
115
+
116
+ **ALWAYS split if:**
117
+ - More than 3 tasks
118
+ - Multiple subsystems (DB + API + UI = separate plans)
119
+ - Any task with >5 file modifications
120
+ - Checkpoint + implementation in same plan
121
+ - Discovery + implementation in same plan
122
+
123
+ **CONSIDER splitting:** >5 files total, natural semantic boundaries, context cost estimate exceeds 40% for a single plan. See `<planner_authority_limits>` for prohibited split reasons.
124
+
125
+ See @~/.claude/gsd-core/references/planner-guidance.md for Granularity Calibration table (Coarse/Standard/Fine plans-per-phase).
@@ -90,11 +90,14 @@ Up to 4 suggested next actions with selection (status, resume workflows).
90
90
  3-option handler for existing CONTEXT.md in discuss workflow.
91
91
  - question: "Phase {N} already has a CONTEXT.md. How should we handle it?"
92
92
  - header: "Context"
93
- - options: Overwrite | Append | Cancel
93
+ - options: Update it | View it | Skip
94
94
 
95
95
  ## Pattern: gray-area-option
96
96
  Dynamic template for presenting gray area choices in discuss workflow.
97
97
  - question: "{Gray area title}"
98
98
  - header: "Decision"
99
- - options: {Option 1} | {Option 2} | Let Claude decide
100
- - Note: Options generated at runtime. Always include "Let Claude decide" as last option.
99
+ - options: {Option 1} | {Option 2}
100
+ - Note: Options generated at runtime. Present real choices only — do NOT include a
101
+ "skip" or "you decide" option (the user ran discuss-phase to decide). An "Other"
102
+ free-text escape hatch may be offered per modes/default.md, but never a
103
+ "Let Claude decide" cop-out.
@@ -1,38 +1,89 @@
1
1
  # Model Profile Resolution
2
2
 
3
- Resolve model profile once at the start of orchestration, then use it for all Task spawns.
3
+ Resolve each agent's model through `gsd-tools`, then pass it to the `Agent()` spawn — or
4
+ omit the parameter entirely when nothing resolved.
4
5
 
5
6
  ## Resolution Pattern
6
7
 
8
+ Prefer the field your workflow's own `init.*` payload already emits (every orchestrator
9
+ init that spawns subagents carries one — `mapper_model`, `planner_model`,
10
+ `executor_model`, `doc_writer_model`, …). Declare it in the workflow's parse line so the
11
+ binding is stated, not implied:
12
+
13
+ ```
14
+ Parse JSON for: `mapper_model`, …
15
+ ```
16
+
17
+ When the agent type is only known at runtime — a capability hook naming its own agent, for
18
+ example — resolve it directly instead:
19
+
7
20
  ```bash
8
- MODEL_PROFILE=$(cat .planning/config.json 2>/dev/null | grep -o '"model_profile"[[:space:]]*:[[:space:]]*"[^"]*"' | grep -o '"[^"]*"$' | tr -d '"' || echo "balanced")
21
+ AGENT_MODEL=$(gsd_run query resolve-model "<agent-type>" --raw)
9
22
  ```
10
23
 
11
- Default: `balanced` if not set or config missing.
24
+ Both surfaces return the same thing: a model string for the active runtime, or the **empty
25
+ string** when nothing resolved.
12
26
 
13
27
  ## Lookup Table
14
28
 
15
29
  @~/.claude/gsd-core/references/model-profiles.md
16
30
 
17
- Look up the agent in the table for the resolved profile. Pass the model parameter to Task calls:
31
+ ## Passing the model to a spawn
18
32
 
19
33
  ```
20
- Task(
34
+ Agent(
21
35
  prompt="...",
22
36
  subagent_type="gsd-planner",
23
- model="{resolved_model}" # "inherit", "sonnet", or "haiku"
37
+ model="{planner_model}"
38
+ )
39
+ ```
40
+
41
+ Substitute the field **this workflow bound** — never a generic placeholder name.
42
+
43
+ **#2517 — omit, do not emit an empty model.** When the resolved value is `"inherit"` or
44
+ empty, **omit the `model=` parameter entirely**:
45
+
46
+ ```
47
+ Agent(
48
+ prompt="...",
49
+ subagent_type="gsd-planner"
24
50
  )
25
51
  ```
26
52
 
27
- **Note:** Opus-tier agents resolve to `"inherit"` (not `"opus"`). This causes the agent to use the parent session's model, avoiding conflicts with organization policies that may block specific opus versions.
53
+ No model parameter is passed at all — `planner_model` resolved to `"inherit"` or empty, and
54
+ omitting it inherits the orchestrator's model. Passing either value through as an argument
55
+ instead 404s on non-Claude runtimes.
56
+
57
+ This is not cosmetic, and both values really occur. `model_profile: "inherit"` — and any
58
+ opus-tier agent — resolves to the literal string `"inherit"`. `resolve_model_ids: "omit"`
59
+ resolves to the **empty string** whenever the project sets it explicitly or the active
60
+ runtime has no native tier aliases; an agent type absent from the profile table takes that
61
+ same empty-string path, because it has no tier for the earlier steps to resolve. Emitting
62
+ either value verbatim fails the spawn on every runtime without native tier aliases.
63
+
64
+ **#2684 — substitute a field your workflow actually bound.** `model="{…}"` must name a key
65
+ your own `init.*` payload emits, a shell variable you assigned, or a field on your declared
66
+ parse line. A placeholder that resolves to nothing does not fail loudly — the orchestrator
67
+ silently invents a value, which is the invisible partial application ADR-1411 prohibits.
68
+ `tests/model-omit-when-inherit-guard.test.cjs` enforces both rules.
69
+
70
+ ## Profile semantics
71
+
72
+ **Note:** Opus-tier agents resolve to `"inherit"` (not `"opus"`). This causes the agent to
73
+ use the parent session's model, avoiding conflicts with organization policies that may
74
+ block specific opus versions — and, per the rule above, means the `model=` parameter is
75
+ omitted rather than set.
28
76
 
29
- If `model_profile` is `"adaptive"`, agents resolve to role-based assignments (opus/sonnet/haiku based on agent type).
77
+ If `model_profile` is `"adaptive"`, agents resolve to role-based assignments (opus/sonnet/
78
+ haiku based on agent type).
30
79
 
31
- If `model_profile` is `"inherit"`, all agents resolve to `"inherit"` (useful for OpenCode `/model`).
80
+ If `model_profile` is `"inherit"`, all agents resolve to `"inherit"` (useful for OpenCode
81
+ `/model`).
32
82
 
33
83
  ## Usage
34
84
 
35
- 1. Resolve once at orchestration start
36
- 2. Store the profile value
37
- 3. Look up each agent's model from the table when spawning
38
- 4. Pass model parameter to each Task call (values: `"inherit"`, `"sonnet"`, `"haiku"`)
85
+ 1. Bind the model once — from the `init.*` payload field, or `query resolve-model` when the
86
+ agent type is runtime-determined
87
+ 2. Declare the bound field on the workflow's parse line
88
+ 3. Pass `model="{bound_field}"` on each `Agent()` spawn
89
+ 4. Omit `model=` entirely whenever the bound value is `"inherit"` or empty
@@ -0,0 +1,88 @@
1
+ <!--
2
+ offer-next.md — extracted from execute-phase.md step "offer_next" (#2537).
3
+ Eagerly @-referenced from execute-phase.md so runtime behavior is unchanged; the
4
+ extraction restores byte-budget headroom the frozen ceiling exists to provide.
5
+ -->
6
+
7
+
8
+ **Exception:** If `gaps_found`, the `verify_phase_goal` step already presents the gap-closure path (`/gsd:plan-phase {X} --gaps`). No additional routing needed — skip auto-advance.
9
+
10
+ **No-transition check (spawned by auto-advance chain):**
11
+
12
+ Parse `--no-transition` flag from $ARGUMENTS.
13
+
14
+ **If `--no-transition` flag present:**
15
+
16
+ Execute-phase was spawned by plan-phase's auto-advance. Do NOT run transition.md.
17
+ After verification passes and roadmap is updated, return completion status to parent:
18
+
19
+ ```
20
+ ## PHASE COMPLETE
21
+
22
+ Phase: ${PHASE_NUMBER} - ${PHASE_NAME}
23
+ Plans: ${completed_count}/${total_count}
24
+ Verification: {Passed | Gaps Found}
25
+
26
+ [Include aggregate_results output]
27
+ ```
28
+
29
+ STOP. Do not proceed to auto-advance or transition.
30
+
31
+ **If `--no-transition` flag is NOT present:**
32
+
33
+ **Auto-advance detection:**
34
+
35
+ 1. Parse `--auto` flag from $ARGUMENTS
36
+ 2. Read consolidated auto-mode (`active` = chain flag OR user preference; chain flag already synced in init step):
37
+ ```bash
38
+ AUTO_MODE=$(gsd_run query check auto-mode --pick active 2>/dev/null || echo "false")
39
+ ```
40
+
41
+ **If `--auto` flag present OR `AUTO_MODE` is true (AND verification passed with no gaps):**
42
+
43
+ ```
44
+ ╔══════════════════════════════════════════╗
45
+ ║ AUTO-ADVANCING → TRANSITION ║
46
+ ║ Phase {X} verified, continuing chain ║
47
+ ╚══════════════════════════════════════════╝
48
+ ```
49
+
50
+ Execute the transition workflow inline (do NOT use Agent — orchestrator context is ~10-15%, transition needs phase completion data already in context):
51
+
52
+ Read and follow `~/.claude/gsd-core/workflows/transition.md`, passing through the `--auto` flag so it propagates to the next phase invocation.
53
+
54
+ **If neither `--auto` nor `AUTO_MODE` is true:**
55
+
56
+ **STOP. Do not auto-advance. Do not execute transition. Do not plan next phase. Present options to the user and wait.**
57
+
58
+ **IMPORTANT: There is NO `/gsd-transition` command. Never suggest it. The transition workflow is internal only.**
59
+
60
+ Check whether CONTEXT.md already exists for the next phase:
61
+
62
+ ```bash
63
+ ls .planning/phases/*{next}*/{next}-CONTEXT.md 2>/dev/null || echo "no-context"
64
+ ```
65
+
66
+ If CONTEXT.md does **not** exist for the next phase, present:
67
+
68
+ ```
69
+ ## ✓ Phase {X}: {Name} Complete
70
+
71
+ /gsd:progress ${GSD_WS} — see updated roadmap
72
+ /gsd:discuss-phase {next} ${GSD_WS} — start here: discuss next phase before planning ← recommended
73
+ /gsd:plan-phase {next} ${GSD_WS} — plan next phase (skip discuss)
74
+ /gsd:execute-phase {next} ${GSD_WS} — execute next phase (skip discuss and plan)
75
+ ```
76
+
77
+ If CONTEXT.md **exists** for the next phase, present:
78
+
79
+ ```
80
+ ## ✓ Phase {X}: {Name} Complete
81
+
82
+ /gsd:progress ${GSD_WS} — see updated roadmap
83
+ /gsd:plan-phase {next} ${GSD_WS} — start here: plan next phase (CONTEXT.md already present) ← recommended
84
+ /gsd:discuss-phase {next} ${GSD_WS} — re-discuss next phase
85
+ /gsd:execute-phase {next} ${GSD_WS} — execute next phase (skip planning)
86
+ ```
87
+
88
+ Only suggest the commands listed above. Do not invent or hallucinate command names.
@@ -255,6 +255,7 @@ Set via `workflow.*` namespace in config.json (e.g., `"workflow": { "research":
255
255
  | `workflow.auto_advance` | boolean | `false` | `true`, `false` | Auto-advance to next phase after completion |
256
256
  | `workflow.node_repair` | boolean | `true` | `true`, `false` | Attempt automatic repair of failed plan nodes |
257
257
  | `workflow.node_repair_budget` | number | `2` | Any positive integer | Max repair retries per failed node |
258
+ | `workflow.smart_zone_tokens` | number | `100000` | Any positive integer | Smart-zone token budget for phase-effort estimation (#2630, ADR-2629). A phase whose estimate exceeds this is flagged with a split recommendation — advisory only, never a block. A *policy default*, not a benchmark constant: degradation begins before the advertised context window is full, but the effective ceiling is model- and task-dependent, so the calibration loop corrects it per project. _Alias:_ `smart_zone_tokens` is the flat-key form used in `CONFIG_DEFAULTS`; `workflow.smart_zone_tokens` is the canonical namespaced form. |
258
259
  | `workflow.ai_integration_phase` | boolean | `true` | `true`, `false` | Run /gsd:ai-integration-phase before planning AI system phases |
259
260
  | `workflow.api_coverage_gate` | boolean | `true` | `true`, `false` | 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 prompts a COVERAGE.md matrix; at verify:pre a blocking gate fails the seal unless the matrix exists with every non-integrated capability an explicit, reasoned opt-out (#1562) |
260
261
  | `workflow.ui_phase` | boolean | `true` | `true`, `false` | Generate UI-SPEC.md for frontend phases |
@@ -395,7 +396,7 @@ Several config fields affect each other or trigger special behavior:
395
396
 
396
397
  8. **`sub_repos` auto-sync** -- On every config load, GSD scans for child directories with `.git` and updates the `sub_repos` array if the filesystem has changed. Legacy `multiRepo: true` is automatically migrated to a detected `sub_repos` array.
397
398
 
398
- 9. **`workflow.use_worktrees` and branch divergence** -- When `use_worktrees` is `true` (default), executor worktrees are forked from `origin/HEAD` by the Claude Code harness. If your current branch has commits that `origin/HEAD` does not (for example an unmerged milestone or feature branch), GSD automatically degrades to sequential execution for that run and prints a one-line `⚠ Worktree base mismatch` warning. To restore parallel execution permanently, set `worktree.baseRef:"head"` in `.claude/settings.local.json` (run `node gsd-tools.cjs worktree set-baseref`). This makes the harness fork worktrees from the live HEAD instead of `origin/HEAD`. Both fresh installs and upgrades of GSD Core set this automatically (no-clobber) when `use_worktrees` is enabled; you can also run the command manually at any time. Setting `workflow.use_worktrees: false` is the alternative if worktrees are not needed at all.
399
+ 9. **`workflow.use_worktrees` and branch divergence** -- When `use_worktrees` is `true` (default), executor worktrees are forked from `origin/HEAD` -- by the host's own harness on `dispatch.isolation: harness-worktree` runtimes (Claude Code, Cursor), or by GSD itself on `orchestrator-worktree` runtimes (Codex, OpenCode, Kimi, Kimi Code). The divergence behavior below is identical either way, because the fork base is a property of the repository rather than of whoever creates the worktree. If your current branch has commits that `origin/HEAD` does not (for example an unmerged milestone or feature branch), GSD automatically degrades to sequential execution for that run and prints a one-line `⚠ Worktree base mismatch` warning. To restore parallel execution permanently, set `worktree.baseRef:"head"` in `.claude/settings.local.json` (run `node gsd-tools.cjs worktree set-baseref`). This makes the harness fork worktrees from the live HEAD instead of `origin/HEAD`. Both fresh installs and upgrades of GSD Core set this automatically (no-clobber) when `use_worktrees` is enabled; you can also run the command manually at any time. Setting `workflow.use_worktrees: false` is the alternative if worktrees are not needed at all.
399
400
 
400
401
  ---
401
402
 
@@ -58,32 +58,39 @@ cannot diverge (`DEFECT.GENERATIVE-FIX`; parity-locked in
58
58
 
59
59
  ## Invocation
60
60
 
61
- For each selected INSTANCE, invoke its base `cli` using the instance's own `model`/`agent` —
62
- NOT the global `review.models.<cli>`. Each instance writes to its OWN per-instance output file
63
- under the run-scoped `{run_dir}` (`RUN_DIR` from `gather_context`, #2358 — never a bare
64
- `{phase}`-keyed `/tmp` path) and runs as a distinct reviewer identity.
61
+ An instance resolves **through** a lane; it is not a lane itself (ADR-2782 D8). It takes no part in
62
+ the roster, the flag set, or lane uniqueness — which is why an instance heading
63
+ (`## OpenCode Review (opencode-deepseek)`) must never be read as a lane section.
65
64
 
66
- For an OpenCode-backed instance (the motivating adapter):
65
+ Since Phase 5b (#2799) `invoke_reviewers` iterates declared lanes rather than hand-authored per-CLI
66
+ blocks, so an instance is invoked through the same single seam as its base lane, with two
67
+ substitutions:
67
68
 
68
69
  ```bash
69
- # $INSTANCE_MODEL / $INSTANCE_AGENT come from the instance spec; $INSTANCE_NAME is the
70
- # reviewer identity (e.g. opencode-deepseek). --agent is OpenCode's native subagent flag;
71
- # omit it when the instance has no agent. {run_dir} is the run-scoped mktemp directory
72
- # created once in gather_context (#2358) — same directory every other reviewer block uses.
73
- if [ -n "$INSTANCE_AGENT" ] && [ "$INSTANCE_AGENT" != "null" ]; then
74
- cat {run_dir}/gsd-review-prompt.md | opencode run --model "$INSTANCE_MODEL" --agent "$INSTANCE_AGENT" - 2>/dev/null > {run_dir}/gsd-review-${INSTANCE_NAME}.md
75
- else
76
- cat {run_dir}/gsd-review-prompt.md | opencode run --model "$INSTANCE_MODEL" - 2>/dev/null > {run_dir}/gsd-review-${INSTANCE_NAME}.md
77
- fi
78
- if [ ! -s {run_dir}/gsd-review-${INSTANCE_NAME}.md ]; then
79
- echo "OpenCode review ($INSTANCE_NAME) failed or returned empty output." > {run_dir}/gsd-review-${INSTANCE_NAME}.md
80
- fi
70
+ # $INSTANCE_NAME is the reviewer identity (e.g. opencode-deepseek); $INSTANCE_MODEL / $INSTANCE_AGENT
71
+ # come from the instance spec. --run-dir is the run-scoped mktemp directory created once in
72
+ # gather_context (#2358) — the same directory every lane uses.
73
+ #
74
+ # The instance's OWN model replaces the lane's configured model, and the output lands under the
75
+ # INSTANCE name so two instances of one adapter never overwrite each other.
76
+ gsd_run query review-lane invoke \
77
+ --slug "$INSTANCE_CLI" \
78
+ --run-dir "$RUN_DIR" --repo-root "$REPO_ROOT" \
79
+ --model "$INSTANCE_MODEL" ${INSTANCE_AGENT:+--agent "$INSTANCE_AGENT"} \
80
+ --as "$INSTANCE_NAME"
81
81
  ```
82
82
 
83
- For an instance backed by a DIFFERENT cli, reuse that cli's invocation block with two
84
- substitutions: use the instance's `model` in place of the global `review.models.<cli>` value,
85
- and write to `{run_dir}/gsd-review-${INSTANCE_NAME}.md`. Only `opencode` honours an
86
- `agent` field in v1; ignore `agent` for other adapters.
83
+ `--as` is what makes the run write `{run_dir}/gsd-review-${INSTANCE_NAME}.md` instead of the lane's
84
+ own `{run_dir}/gsd-review-<slug>.md`.
85
+
86
+ Everything the lane declares — probe, prompt channel, output channel, timeout floor, empty-output
87
+ policy, handler — applies unchanged to an instance. That is the point of routing instances through
88
+ the lane rather than duplicating its invocation: a cross-cutting fix reaches instances for free,
89
+ where the previous per-adapter block had to be copied and kept in sync by hand.
90
+
91
+ Only `opencode` honours an `agent` field in v1; it is ignored by other adapters. `model` and `agent`
92
+ are opaque pass-through strings and are NEVER interpolated into a shell string — the runner spawns
93
+ with an argv array and `shell: false`.
87
94
 
88
95
  ---
89
96
 
@@ -0,0 +1,42 @@
1
+ # Runtime-Aware Subagent Dispatch (epic #2505 Phase 4 / #2508)
2
+
3
+ GSD workflows dispatch specialized subagents by role (planner, executor,
4
+ verifier, …). On **named-dispatch runtimes** (Claude Code, OpenCode, Cursor,
5
+ Cline, … — every runtime whose descriptor declares `hostIntegration.dispatch.namedDispatch: true`), the role name dispatches the named subagent directly.
6
+
7
+ On **built-in-only runtimes** (kimi-code — three built-in subagents only:
8
+ `coder`, `explore`, `plan`; no custom registration per
9
+ `moonshotai.github.io/kimi-code/en/customization/agents`), a GSD role name is
10
+ unknown and the dispatch must use the closest built-in.
11
+
12
+ ## Resolution
13
+
14
+ Before dispatching a subagent by role, resolve the type for the current runtime
15
+ via the `resolve-dispatch-type` query. Pass the requested role name; the query
16
+ returns the name unchanged on named-dispatch runtimes and maps to the closest
17
+ built-in (`coder`/`explore`/`plan`) on kimi-code. The `|| echo` fallback
18
+ preserves named-dispatch behavior on older GSD installs that lack the query.
19
+
20
+ The persona rides `${AGENT_SKILLS_<ROLE>}` (Phase 3 / #2510) regardless of the
21
+ resolved type — on non-Claude runtimes with no `agent_skills` config,
22
+ `gsd-tools query agent-skills <role>` returns the installed agent prompt as
23
+ the block. So a coder dispatch with the planner persona injected gives kimi-code
24
+ the planner's behavior in the coder built-in's process.
25
+
26
+ ## Suffix → built-in map
27
+
28
+ | Agent role suffix | Built-in | Rationale |
29
+ |---|---|---|
30
+ | `-planner`, `-roadmapper`, `-selector`, `-spec` | `plan` | Plans/designs; no file writes |
31
+ | `-researcher`, `-mapper`, `-checker`, `-verifier`, `-auditor`, `-analyzer`, `-synthesizer`, `-profiler`, `-curator`, `-classifier`, `-reviewer` | `explore` | Read-only investigation |
32
+ | everything else (`-executor`, `-fixer`, `-writer`, `-debugger`, …) | `coder` | General-purpose with full tool set |
33
+ | `general-purpose`, `general`, `default`, `sonnet`, `opus`, `haiku` | `coder` | Already-generic names |
34
+
35
+ ## Why not a hook?
36
+
37
+ Kimi Code's documented PreToolUse hook API
38
+ (`moonshotai.github.io/kimi-code/en/customization/hooks`) supports only
39
+ `permissionDecision: allow|deny` on blockable events — it cannot rewrite the
40
+ dispatch payload's role field in flight. A PreToolUse-remap hook (the epic's
41
+ original "Option B") is therefore infeasible; this per-dispatch resolution
42
+ (Option A) is the documented-API-correct path.
@@ -30,8 +30,8 @@ bloating this closed core.
30
30
  | id | name | applies to element kinds | consideration question |
31
31
  |----|------|--------------------------|------------------------|
32
32
  | empty | Empty / no data | form, list-collection, media | What is shown when there is no data — zero items, an unfilled form, or absent media? |
33
- | loading | Loading / in-flight | form, list-collection, media, nav | What is shown while data or content is still loading (skeleton, spinner, progressive reveal)? |
34
- | error | Error / failure | form, list-collection, media, nav | What is shown when the load or submit fails (message, retry affordance, partial fallback)? |
33
+ | loading | Loading / in-flight | form, list-collection, media, nav, interactive-control | What is shown while data or content is still loading (skeleton, spinner, progressive reveal)? |
34
+ | error | Error / failure | form, list-collection, media, nav, interactive-control | What is shown when the load or submit fails (message, retry affordance, partial fallback)? |
35
35
  | populated | Populated / happy path | list-collection, media | What does the normal populated (happy-path) state look like at a typical volume of content? |
36
36
  | partial | Partial / incomplete | form, list-collection | What is shown for partial or incomplete data — some fields or rows present, others missing? |
37
37
  | overflow | Overflow / truncation | list-collection, nav, static-content | What happens when content exceeds its container — scroll, clip, wrap, or truncate? |
@@ -17,7 +17,7 @@ did not create (#48).
17
17
  <worktree_branch_check>
18
18
  FIRST ACTION: HEAD assertion MUST run before anything else, and this block is
19
19
  VERIFY-ONLY. Worktrees spawned by Claude Code's `isolation="worktree"` use the
20
- `worktree-agent-<id>` namespace. The orchestrator owns this worktree's lifecycle;
20
+ `agent-<id>` namespace (previously `worktree-agent-<id>`; both are accepted). The orchestrator owns this worktree's lifecycle;
21
21
  a sub-agent MUST NOT hold state-correction primitives (hard-reset, update-ref,
22
22
  force-move, index-discard) on a worktree it did not create (#48, #2924). If ANY
23
23
  assertion below fails, HALT immediately — print the FATAL line, `exit 42`, and let
@@ -27,11 +27,11 @@ commit.
27
27
  HEAD_REF=$(git symbolic-ref --quiet HEAD || echo "DETACHED")
28
28
  ACTUAL_BRANCH=$(git rev-parse --abbrev-ref HEAD)
29
29
  if [ "$HEAD_REF" = "DETACHED" ] || echo "$ACTUAL_BRANCH" | grep -Eq '^(main|master|develop|trunk|release/.*)$'; then
30
- echo "FATAL: worktree HEAD on '$ACTUAL_BRANCH' (expected worktree-agent-*); refusing to commit or self-recover via 'git update-ref' (#2924)." >&2
30
+ echo "FATAL: worktree HEAD on '$ACTUAL_BRANCH' (expected agent-* or worktree-agent-*); refusing to commit or self-recover via 'git update-ref' (#2924)." >&2
31
31
  exit 42
32
32
  fi
33
- if ! echo "$ACTUAL_BRANCH" | grep -Eq '^worktree-agent-[A-Za-z0-9._/-]+$'; then
34
- echo "FATAL: worktree HEAD '$ACTUAL_BRANCH' is not in the worktree-agent-* namespace; refusing to commit (#2924)." >&2
33
+ if ! echo "$ACTUAL_BRANCH" | grep -Eq '^(worktree-)?agent-[A-Za-z0-9._/-]+$'; then
34
+ echo "FATAL: worktree HEAD '$ACTUAL_BRANCH' is not in the agent-* / worktree-agent-* namespace; refusing to commit (#2924)." >&2
35
35
  exit 42
36
36
  fi
37
37
  ACTUAL_BASE=$(git rev-parse HEAD)
@@ -6,6 +6,10 @@ tags: [searchable tech]
6
6
  provides:
7
7
  - [bullet list of what was built/delivered]
8
8
  affects: [list of phase names or keywords]
9
+ actuals:
10
+ tokens: [chars/4 over files actually changed]
11
+ tasks: [tasks completed]
12
+ commits: [commits made]
9
13
  tech-stack:
10
14
  added: [libraries/tools]
11
15
  patterns: [architectural/code patterns]
@@ -6,6 +6,10 @@ tags: [searchable tech]
6
6
  provides:
7
7
  - [bullet list of what was built/delivered]
8
8
  affects: [list of phase names or keywords]
9
+ actuals:
10
+ tokens: [chars/4 over files actually changed]
11
+ tasks: [tasks completed]
12
+ commits: [commits made]
9
13
  tech-stack:
10
14
  added: [libraries/tools]
11
15
  patterns: [architectural/code patterns]
@@ -21,6 +21,13 @@ provides:
21
21
  - [bullet list of what this phase built/delivered]
22
22
  affects: [list of phase names or keywords that will need this context]
23
23
 
24
+ # Actuals (#2632) — pairs with the plan's `estimate` to calibrate future estimates.
25
+ # Same estimateTokens scale (chars/4 over the realized diff), never a harness token count.
26
+ actuals:
27
+ tokens: [chars/4 over files actually changed]
28
+ tasks: [tasks completed]
29
+ commits: [commits made]
30
+
24
31
  # Tech tracking
25
32
  tech-stack:
26
33
  added: [libraries/tools added in this phase]
@@ -33,10 +33,10 @@ Parse JSON for: `phase_dir`, `phase_number`, `phase_name`, `phase_slug`, `padded
33
33
 
34
34
  Resolve agent models:
35
35
  ```bash
36
- SELECTOR_MODEL=$(gsd_run query resolve-model gsd-framework-selector 2>/dev/null | jq -r '.model' 2>/dev/null || true)
37
- RESEARCHER_MODEL=$(gsd_run query resolve-model gsd-ai-researcher 2>/dev/null | jq -r '.model' 2>/dev/null || true)
38
- DOMAIN_MODEL=$(gsd_run query resolve-model gsd-domain-researcher 2>/dev/null | jq -r '.model' 2>/dev/null || true)
39
- PLANNER_MODEL=$(gsd_run query resolve-model gsd-eval-planner 2>/dev/null | jq -r '.model' 2>/dev/null || true)
36
+ SELECTOR_MODEL=$(gsd_run query resolve-model gsd-framework-selector --pick model 2>/dev/null || true)
37
+ RESEARCHER_MODEL=$(gsd_run query resolve-model gsd-ai-researcher --pick model 2>/dev/null || true)
38
+ DOMAIN_MODEL=$(gsd_run query resolve-model gsd-domain-researcher --pick model 2>/dev/null || true)
39
+ PLANNER_MODEL=$(gsd_run query resolve-model gsd-eval-planner --pick model 2>/dev/null || true)
40
40
  ```
41
41
 
42
42
  Check config:
@@ -94,6 +94,10 @@ final output — do not proceed to fixing.
94
94
  <step name="fix-loop">
95
95
  For each **auto-fixable** finding (up to `--max`, ordered by severity desc):
96
96
 
97
+ <!-- #2508 runtime-aware-dispatch -->
98
+
99
+ > **Runtime-aware dispatch (#2508 Phase 4).** GSD workflows dispatch specialized subagents by role. Before dispatching on a built-in-only runtime (kimi-code — three built-ins only), resolve the role to a built-in via `gsd_run query resolve-dispatch-type --requested <role> --raw`. On named-dispatch runtimes (Claude/OpenCode/…) the role is returned unchanged; on kimi-code it maps to `coder`/`explore`/`plan` by role-suffix. The persona rides `${AGENT_SKILLS_<ROLE>}` (Phase 3) regardless. See @gsd-core/references/runtime-aware-dispatch.md.
100
+
97
101
  **a. Spawn executor agent** (runs in a subagent — no output until it returns, ~1–5 min; expected, not a freeze)**:**
98
102
  ```
99
103
  Agent(
@@ -69,6 +69,10 @@ Extract `MILESTONE_REQ_IDS` from REQUIREMENTS.md traceability table — all REQ-
69
69
 
70
70
  Print: "Spawning integration checker (runs in a subagent — no output until it returns, ~1–5 min; expected, not a freeze)"
71
71
 
72
+ <!-- #2517 model-omit-on-inherit -->
73
+
74
+ > **Model omission (#2517).** Omit the `model` parameter entirely when the value it would carry (`integration_checker_model`) is `"inherit"` or empty. An empty value 404s on runtimes without native tier aliases — the default on non-Claude runtimes. Omitting it inherits the orchestrator's model. See @gsd-core/references/model-profile-resolution.md.
75
+
72
76
  ```
73
77
  Agent(
74
78
  prompt="Check cross-phase integration and E2E flows.
@@ -82,6 +86,10 @@ Milestone Requirements:
82
86
 
83
87
  MUST map each integration finding to affected requirement IDs where applicable.
84
88
 
89
+ <!-- #2508 runtime-aware-dispatch -->
90
+
91
+ > **Runtime-aware dispatch (#2508 Phase 4).** GSD workflows dispatch specialized subagents by role. Before dispatching on a built-in-only runtime (kimi-code — three built-ins only), resolve the role to a built-in via `gsd_run query resolve-dispatch-type --requested <role> --raw`. On named-dispatch runtimes (Claude/OpenCode/…) the role is returned unchanged; on kimi-code it maps to `coder`/`explore`/`plan` by role-suffix. The persona rides `${AGENT_SKILLS_<ROLE>}` (Phase 3) regardless. See @gsd-core/references/runtime-aware-dispatch.md.
92
+
85
93
  Verify cross-phase wiring and E2E user flows.
86
94
  ${AGENT_SKILLS_CHECKER}",
87
95
  subagent_type="gsd-integration-checker",