@opengsd/gsd-core 1.7.0-rc.2 → 1.7.0-rc.4

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 (184) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/GEMINI.md +25 -23
  4. package/README.ja-JP.md +4 -3
  5. package/README.ko-KR.md +4 -3
  6. package/README.md +7 -6
  7. package/README.pt-BR.md +4 -3
  8. package/README.zh-CN.md +4 -3
  9. package/agents/gsd-advisor-researcher.md +1 -1
  10. package/agents/gsd-ai-researcher.md +1 -1
  11. package/agents/gsd-code-fixer.md +1 -1
  12. package/agents/gsd-debug-session-manager.md +1 -1
  13. package/agents/gsd-debugger.md +1 -1
  14. package/agents/gsd-domain-researcher.md +1 -1
  15. package/agents/gsd-eval-auditor.md +1 -1
  16. package/agents/gsd-executor.md +4 -4
  17. package/agents/gsd-intel-updater.md +1 -1
  18. package/agents/gsd-mempalace-curator.md +1 -1
  19. package/agents/gsd-phase-researcher.md +2 -2
  20. package/agents/gsd-plan-checker.md +1 -1
  21. package/agents/gsd-planner.md +2 -2
  22. package/agents/gsd-project-researcher.md +2 -2
  23. package/agents/gsd-research-synthesizer.md +1 -1
  24. package/agents/gsd-ui-researcher.md +2 -2
  25. package/agents/gsd-verifier.md +2 -2
  26. package/bin/install.js +132 -464
  27. package/commands/gsd/map-codebase.md +4 -4
  28. package/commands/gsd/mempalace-capture.md +1 -1
  29. package/commands/gsd/mempalace-recall.md +9 -5
  30. package/commands/gsd/next.md +29 -0
  31. package/commands/gsd/ns-project.md +2 -1
  32. package/commands/gsd/ns-workflow.md +5 -2
  33. package/commands/gsd/onboard.md +46 -0
  34. package/gsd-core/bin/ensure-runtime-build.cjs +246 -0
  35. package/gsd-core/bin/gsd-tools.cjs +72 -3
  36. package/gsd-core/bin/lib/capability-registry.cjs +684 -264
  37. package/gsd-core/bin/lib/capability-state.cjs +117 -18
  38. package/gsd-core/bin/lib/capability-writer.cjs +11 -1
  39. package/gsd-core/bin/lib/check-command-router.cjs +111 -1
  40. package/gsd-core/bin/lib/claude-orchestration-command-router.cjs +136 -0
  41. package/gsd-core/bin/lib/claude-orchestration.cjs +404 -0
  42. package/gsd-core/bin/lib/clusters.cjs +2 -0
  43. package/gsd-core/bin/lib/command-aliases.cjs +8 -0
  44. package/gsd-core/bin/lib/config.cjs +19 -1
  45. package/gsd-core/bin/lib/core-utils.cjs +41 -0
  46. package/gsd-core/bin/lib/external-job.cjs +287 -0
  47. package/gsd-core/bin/lib/gate-predicate-evaluator.cjs +151 -0
  48. package/gsd-core/bin/lib/graphify.cjs +41 -9
  49. package/gsd-core/bin/lib/init-command-router.cjs +4 -0
  50. package/gsd-core/bin/lib/init.cjs +25 -69
  51. package/gsd-core/bin/lib/install-engine.cjs +8 -5
  52. package/gsd-core/bin/lib/install-profiles.cjs +2 -0
  53. package/gsd-core/bin/lib/loop-resolver.cjs +7 -1
  54. package/gsd-core/bin/lib/milestone.cjs +7 -1
  55. package/gsd-core/bin/lib/model-resolver.cjs +69 -4
  56. package/gsd-core/bin/lib/onboard-projection.cjs +309 -0
  57. package/gsd-core/bin/lib/phase.cjs +14 -2
  58. package/gsd-core/bin/lib/plan-scan.cjs +9 -1
  59. package/gsd-core/bin/lib/profile-output.cjs +1 -1
  60. package/gsd-core/bin/lib/prohibition-enforcement.cjs +21 -19
  61. package/gsd-core/bin/lib/roadmap.cjs +17 -2
  62. package/gsd-core/bin/lib/runtime-hooks-surface.cjs +18 -13
  63. package/gsd-core/bin/lib/runtime-name-policy.cjs +11 -11
  64. package/gsd-core/bin/lib/shell-command-projection.cjs +12 -8
  65. package/gsd-core/bin/lib/smart-entry.cjs +521 -0
  66. package/gsd-core/bin/lib/surface.cjs +63 -33
  67. package/gsd-core/bin/lib/update-context.cjs +0 -5
  68. package/gsd-core/bin/shared/config-schema.manifest.json +1 -0
  69. package/gsd-core/bin/shared/model-catalog.json +5 -5
  70. package/gsd-core/bin/shared/runtime-aliases.manifest.json +0 -5
  71. package/gsd-core/references/gates.md +1 -1
  72. package/gsd-core/references/gsd-run-resolver.md +8 -0
  73. package/gsd-core/references/planning-config.md +1 -1
  74. package/gsd-core/templates/project.md +1 -1
  75. package/gsd-core/workflows/_runtime-launcher.snippet.sh +1 -1
  76. package/gsd-core/workflows/add-backlog.md +1 -1
  77. package/gsd-core/workflows/add-phase.md +1 -1
  78. package/gsd-core/workflows/add-tests.md +1 -1
  79. package/gsd-core/workflows/add-todo.md +1 -1
  80. package/gsd-core/workflows/ai-integration-phase.md +1 -1
  81. package/gsd-core/workflows/audit-fix.md +1 -1
  82. package/gsd-core/workflows/audit-milestone.md +1 -1
  83. package/gsd-core/workflows/audit-uat.md +1 -1
  84. package/gsd-core/workflows/autonomous.md +1 -1
  85. package/gsd-core/workflows/check-todos.md +1 -1
  86. package/gsd-core/workflows/cleanup.md +1 -1
  87. package/gsd-core/workflows/code-review-fix.md +1 -1
  88. package/gsd-core/workflows/code-review.md +1 -1
  89. package/gsd-core/workflows/complete-milestone.md +1 -1
  90. package/gsd-core/workflows/debug.md +1 -1
  91. package/gsd-core/workflows/diagnose-issues.md +1 -1
  92. package/gsd-core/workflows/discuss-phase/modes/advisor.md +1 -1
  93. package/gsd-core/workflows/discuss-phase/modes/auto.md +1 -1
  94. package/gsd-core/workflows/discuss-phase/modes/chain.md +1 -1
  95. package/gsd-core/workflows/discuss-phase-assumptions.md +1 -1
  96. package/gsd-core/workflows/discuss-phase.md +2 -2
  97. package/gsd-core/workflows/do.md +5 -4
  98. package/gsd-core/workflows/docs-update.md +1 -1
  99. package/gsd-core/workflows/edit-phase.md +1 -1
  100. package/gsd-core/workflows/eval-review.md +1 -1
  101. package/gsd-core/workflows/execute-phase/steps/codebase-drift-gate.md +1 -1
  102. package/gsd-core/workflows/execute-phase/steps/post-merge-gate.md +1 -1
  103. package/gsd-core/workflows/execute-phase.md +4 -5
  104. package/gsd-core/workflows/execute-plan.md +1 -1
  105. package/gsd-core/workflows/explore.md +1 -1
  106. package/gsd-core/workflows/extract-learnings.md +1 -1
  107. package/gsd-core/workflows/forensics.md +1 -1
  108. package/gsd-core/workflows/graduation.md +1 -1
  109. package/gsd-core/workflows/health.md +1 -1
  110. package/gsd-core/workflows/help/modes/brief.md +2 -1
  111. package/gsd-core/workflows/help/modes/default.md +2 -1
  112. package/gsd-core/workflows/help/modes/full.md +25 -1
  113. package/gsd-core/workflows/help/modes/topic.md +2 -1
  114. package/gsd-core/workflows/import.md +1 -1
  115. package/gsd-core/workflows/ingest-docs.md +1 -1
  116. package/gsd-core/workflows/insert-phase.md +1 -1
  117. package/gsd-core/workflows/list-seeds.md +1 -1
  118. package/gsd-core/workflows/list-workspaces.md +1 -1
  119. package/gsd-core/workflows/manager.md +1 -1
  120. package/gsd-core/workflows/map-codebase.md +1 -1
  121. package/gsd-core/workflows/milestone-summary.md +1 -1
  122. package/gsd-core/workflows/mvp-phase.md +1 -1
  123. package/gsd-core/workflows/new-milestone.md +1 -1
  124. package/gsd-core/workflows/new-project.md +1 -1
  125. package/gsd-core/workflows/new-workspace.md +1 -1
  126. package/gsd-core/workflows/next.md +1 -1
  127. package/gsd-core/workflows/onboard.md +277 -0
  128. package/gsd-core/workflows/pause-work.md +1 -1
  129. package/gsd-core/workflows/plan-milestone-gaps.md +1 -1
  130. package/gsd-core/workflows/plan-phase/steps/prd-express-path.md +1 -1
  131. package/gsd-core/workflows/plan-phase.md +9 -2
  132. package/gsd-core/workflows/plan-review-convergence.md +1 -1
  133. package/gsd-core/workflows/plant-seed.md +1 -1
  134. package/gsd-core/workflows/pr-branch.md +1 -1
  135. package/gsd-core/workflows/profile-user.md +1 -1
  136. package/gsd-core/workflows/progress.md +1 -1
  137. package/gsd-core/workflows/quick.md +21 -1
  138. package/gsd-core/workflows/reapply-patches.md +1 -1
  139. package/gsd-core/workflows/remove-phase.md +1 -1
  140. package/gsd-core/workflows/remove-workspace.md +1 -1
  141. package/gsd-core/workflows/resume-project.md +1 -1
  142. package/gsd-core/workflows/review.md +43 -7
  143. package/gsd-core/workflows/scan.md +1 -1
  144. package/gsd-core/workflows/secure-phase.md +1 -1
  145. package/gsd-core/workflows/settings-advanced.md +3 -1
  146. package/gsd-core/workflows/settings-integrations.md +1 -1
  147. package/gsd-core/workflows/settings.md +1 -1
  148. package/gsd-core/workflows/ship.md +1 -1
  149. package/gsd-core/workflows/sketch-wrap-up.md +1 -1
  150. package/gsd-core/workflows/sketch.md +1 -1
  151. package/gsd-core/workflows/smart-entry.md +120 -0
  152. package/gsd-core/workflows/spec-phase.md +8 -6
  153. package/gsd-core/workflows/spike-wrap-up.md +1 -1
  154. package/gsd-core/workflows/spike.md +1 -1
  155. package/gsd-core/workflows/stats.md +1 -1
  156. package/gsd-core/workflows/thread.md +1 -1
  157. package/gsd-core/workflows/transition.md +1 -1
  158. package/gsd-core/workflows/ui-phase.md +1 -1
  159. package/gsd-core/workflows/ui-review.md +1 -1
  160. package/gsd-core/workflows/ultraplan-phase.md +1 -1
  161. package/gsd-core/workflows/update.md +3 -6
  162. package/gsd-core/workflows/validate-phase.md +1 -1
  163. package/gsd-core/workflows/verify-phase.md +1 -1
  164. package/gsd-core/workflows/verify-work.md +62 -4
  165. package/package.json +3 -5
  166. package/scripts/ci-test-scope.cjs +19 -1
  167. package/scripts/gen-golden-install-parity-zcode.cjs +77 -0
  168. package/scripts/generate-package-identity.cjs +27 -2
  169. package/scripts/lint-allow-test-rule-refs.allowlist.json +0 -148
  170. package/scripts/lint-regression-test-names.allowlist.json +1 -273
  171. package/scripts/lint-test-file-count.allowlist.json +7 -91
  172. package/scripts/research-profiles.cjs +6 -6
  173. package/scripts/run-tests.cjs +18 -3
  174. package/scripts/slurm-adapter.cjs +269 -0
  175. package/scripts/sync-manifest-versions.cjs +3 -2
  176. package/scripts/sync-runtime-launcher.cjs +20 -2
  177. package/skills/gsd-map-codebase/SKILL.md +3 -3
  178. package/skills/gsd-mempalace-capture/SKILL.md +1 -1
  179. package/skills/gsd-mempalace-recall/SKILL.md +9 -5
  180. package/skills/gsd-next/SKILL.md +30 -0
  181. package/skills/gsd-ns-project/SKILL.md +1 -0
  182. package/skills/gsd-ns-workflow/SKILL.md +4 -1
  183. package/skills/gsd-onboard/SKILL.md +46 -0
  184. package/gemini-extension.json +0 -6
@@ -9,7 +9,7 @@ allowed-tools:
9
9
  - Grep
10
10
  - Write
11
11
  - Agent
12
- requires: [config, new-project, plan-phase]
12
+ requires: [config, new-project, plan-phase, onboard]
13
13
  ---
14
14
 
15
15
  <objective>
@@ -42,7 +42,7 @@ Parse the first token of $ARGUMENTS:
42
42
  Check for .planning/STATE.md - loads context if project already initialized
43
43
 
44
44
  **This command can run:**
45
- - Before /gsd:new-project (brownfield codebases) - creates codebase map first
45
+ - Via /gsd:onboard for first-time brownfield setup - creates codebase map first
46
46
  - After /gsd:new-project (greenfield codebases) - updates codebase map as code evolves
47
47
  - Anytime to refresh codebase understanding
48
48
  </context>
@@ -51,7 +51,7 @@ Check for .planning/STATE.md - loads context if project already initialized
51
51
  **Use map-codebase for:**
52
52
  - Brownfield projects before initialization (understand existing code first)
53
53
  - Refreshing codebase map after significant changes
54
- - Onboarding to an unfamiliar codebase
54
+ - Refreshing or deepening an onboarded codebase map
55
55
  - Before major refactoring (understand current state)
56
56
  - When STATE.md references outdated codebase info
57
57
 
@@ -71,7 +71,7 @@ Check for .planning/STATE.md - loads context if project already initialized
71
71
  4. Wait for agents to complete, collect confirmations (NOT document contents)
72
72
  5. Verify all 7 documents exist with line counts
73
73
  6. Commit codebase map
74
- 7. Offer next steps (typically: /gsd:new-project or /gsd:plan-phase)
74
+ 7. Offer next steps (typically: /gsd:onboard, /gsd:new-project, or /gsd:plan-phase)
75
75
  </process>
76
76
 
77
77
  <success_criteria>
@@ -56,7 +56,7 @@ On any error or timeout, stop and let the phase continue -- capture is best-effo
56
56
 
57
57
  1. **Dedup first.** Interactive: `mempalace_check_duplicate` on the artifact's deterministic drawer id. Headless: rely on `mempalace mine`'s content-hash idempotency.
58
58
  2. **Add the drawer (verbatim).** File the exact artifact text into `room: <room>` of `wing: <wing>` with provenance (`source_file`, phase id). Interactive: `mempalace_add_drawer`. Headless: `mempalace mine <path> --wing <wing> --room <room>`.
59
- 3. **Mirror KG facts** when `config.mempalace.mirror_kg` is true: extract decision/delivery facts and `mempalace_kg_add` them with `valid_from` = the phase date (e.g. `(<project>, decided, <decision>)` from CONTEXT; `(<phase>, delivered, <capability>)` from SUMMARY). Only `augment` is currently wired, so these are an *additive* mirror of `.planning/graphs/`. (`kg_backend`/`replace` are forward-declared and behave as `augment` today.)
59
+ 3. **Mirror KG facts** when `config.mempalace.mirror_kg` is true: extract decision/delivery facts and `mempalace_kg_add` them with `valid_from` = the phase date (e.g. `(<project>, decided, <decision>)` from CONTEXT; `(<phase>, delivered, <capability>)` from SUMMARY). Under `augment` these are an *additive* mirror of GSD's native `.planning/graphs/`. Under `kg_backend`/`replace` the palace KG is the *authoritative* fact store — GSD still produces `.planning/graphs/` through its normal graphify, so an unreachable palace never loses a fact.
60
60
  4. Re-running a phase MUST NOT create duplicate drawers (deterministic ids + `check_duplicate`).
61
61
 
62
62
  ## Step 4 -- Report
@@ -48,13 +48,17 @@ This step is `onError: skip` at `plan:pre` -- recall never blocks planning.
48
48
  ## Step 2 -- Resolve wing, mode, and transport
49
49
 
50
50
  1. **Wing.** Use `config.mempalace.wing` if non-empty; otherwise derive from `config.project_code`; otherwise fall back to the repository directory name.
51
- 2. **Mode.** Read `config.mempalace.memory_mode` (`augment` | `kg_backend` | `replace`, default `augment`). Only `augment` is wired today, so recall always treats the palace as additive; `kg_backend`/`replace` are forward-declared and behave as `augment`.
51
+ 2. **Mode.** Read `config.mempalace.memory_mode` (`augment` | `kg_backend` | `replace`, default `augment`). It sets how authoritative the palace is during recall:
52
+ - `augment` — the palace is an *additional* layer; read native memory (`.planning/graphs/`, STATE) too and treat the palace as supplementary.
53
+ - `kg_backend` — for knowledge-graph facts, query the palace's temporal KG *first, as the primary source*; fall back to `.planning/graphs/` when the palace is unreachable. Non-KG drawer recall stays additive.
54
+ - `replace` — resolve recall *through the palace as the source of truth*; consult native artifacts only as a fallback when the palace is unreachable.
55
+ In every mode an unreachable palace degrades to native memory — recall never blocks (`onError: skip`).
52
56
  3. **Transport.** Prefer the **MCP tools** (`mempalace_*`) in interactive runs *when your MemPalace MCP server is registered and your runtime permits those tools*. Otherwise — headless/cron/autonomous runs, or runtimes that don't grant the MemPalace MCP tools — use the **CLI** (`mempalace wake-up`, `mempalace search`), which this skill's `Bash` allow-tool always covers. If neither is reachable, go to Step 4.
53
57
  4. **Topic.** Read the phase `CONTEXT.md` (the consumed artifact). Derive a short search query from its title, goal, and key decisions.
54
58
 
55
59
  ## Step 3 -- Retrieve (read-only)
56
60
 
57
- All calls in this step are side-effect-free. On any error or timeout, stop retrieving and write whatever was gathered (or the stub) -- never raise.
61
+ All calls in this step are side-effect-free. On any error or timeout, stop retrieving and write whatever was gathered (or the stub) -- never raise. This skill reads only the palace; GSD's planner reads native memory (`.planning/graphs/`, STATE) regardless. So under `kg_backend`/`replace` an unreachable palace falls back to that native memory automatically — reflect that in the stub (Step 4) rather than implying memory is gone.
58
62
 
59
63
  1. **Wake up** (cheap, ~600--900 tokens):
60
64
  - Interactive: read the wing identity/summary, then `mempalace_search`.
@@ -62,7 +66,7 @@ All calls in this step are side-effect-free. On any error or timeout, stop retri
62
66
  2. **Targeted search:**
63
67
  - Interactive: `mempalace_search(query=<topic>, wing=<wing>)`.
64
68
  - Headless: `mempalace search "<topic>" --wing <wing>`.
65
- 3. **Knowledge-graph facts** (when `config.mempalace.mirror_kg` is true): `mempalace_kg_query` / `mempalace_kg_timeline` for decisions relevant to the topic and their validity windows. Only `augment` is currently wired, so the palace KG *supplements* GSD's native `.planning/graphs/` — do not treat it as the sole source. (`kg_backend`/`replace` are forward-declared and behave as `augment` today.)
69
+ 3. **Knowledge-graph facts** (when `config.mempalace.mirror_kg` is true): `mempalace_kg_query` / `mempalace_kg_timeline` for decisions relevant to the topic and their validity windows. Under `augment` the palace KG *supplements* GSD's native `.planning/graphs/` — combine both, do not treat the palace as the sole source. Under `kg_backend` or `replace` the palace KG is the *primary* graph source — query it first and use `.planning/graphs/` only as a fallback when the palace is unreachable.
66
70
  4. **Dedup** the returned drawers/facts; keep the top results.
67
71
 
68
72
  ## Step 4 -- Write MEMORY-RECALL.md
@@ -86,12 +90,12 @@ _Wing: <wing> · Mode: <mode> · Transport: <mcp|cli>_
86
90
  - <surprise> — <provenance>
87
91
  ```
88
92
 
89
- When MemPalace is unreachable, write the stub and continue:
93
+ When MemPalace is unreachable, write the stub and continue. Under `kg_backend`/`replace`, name the native fallback so the planner knows memory is not gone — only un-augmented by the palace this run:
90
94
 
91
95
  ```markdown
92
96
  # Memory Recall (MemPalace)
93
97
 
94
- _MemPalace unavailable at recall time — proceeding without recalled memory._
98
+ _MemPalace unavailable at recall time — falling back to GSD native memory (`.planning/graphs/`, STATE). No palace recall this run._
95
99
  ```
96
100
 
97
101
  ## Anti-Patterns
@@ -0,0 +1,29 @@
1
+ ---
2
+ name: gsd:next
3
+ description: Smart entry — detect project state and route to the right next GSD action.
4
+ effort: low
5
+ allowed-tools:
6
+ - Read
7
+ - Bash
8
+ - Glob
9
+ - SlashCommand
10
+ - AskUserQuestion
11
+ ---
12
+ <objective>
13
+ GSD smart entry — the state-aware front door. Detect what's going on in this project, then present a short menu of the right next actions and dispatch to one.
14
+
15
+ This is a launcher/router only. It never does the work itself. It reads project + workflow state via `gsd-tools smart-entry --json`, shows a situation-appropriate menu, and hands off to an existing GSD command.
16
+ </objective>
17
+
18
+ <execution_context>
19
+ @~/.claude/gsd-core/workflows/smart-entry.md
20
+ @~/.claude/gsd-core/references/ui-brand.md
21
+ </execution_context>
22
+
23
+ <context>
24
+ Arguments: $ARGUMENTS
25
+ </context>
26
+
27
+ <process>
28
+ Follow ~/.claude/gsd-core/workflows/smart-entry.md. Detect the situation, present the menu, and dispatch exactly one command. Then stop.
29
+ </process>
@@ -5,7 +5,7 @@ argument-hint: ""
5
5
  allowed-tools:
6
6
  - Read
7
7
  - Skill
8
- requires: [new-project, new-milestone, complete-milestone, audit-milestone, milestone-summary, import, ingest-docs, profile-user, review-backlog]
8
+ requires: [new-project, onboard, new-milestone, complete-milestone, audit-milestone, milestone-summary, import, ingest-docs, profile-user, review-backlog]
9
9
  ---
10
10
 
11
11
  Route to the appropriate project / milestone skill based on the user's intent.
@@ -15,6 +15,7 @@ inline as part of `gsd-audit-milestone`'s output.
15
15
  | User wants | Invoke |
16
16
  |---|---|
17
17
  | Start a new project | gsd-new-project |
18
+ | Onboard an existing codebase | gsd-onboard |
18
19
  | Create a new milestone | gsd-new-milestone |
19
20
  | Complete the current milestone | gsd-complete-milestone |
20
21
  | Audit a milestone for issues | gsd-audit-milestone |
@@ -5,13 +5,15 @@ argument-hint: ""
5
5
  allowed-tools:
6
6
  - Read
7
7
  - Skill
8
- requires: [discuss-phase, spec-phase, plan-phase, execute-phase, verify-work, phase, progress, ultraplan-phase, plan-review-convergence, add-tests, ai-integration-phase, autonomous, fast, mvp-phase, quick]
8
+ requires: [discuss-phase, spec-phase, plan-phase, execute-phase, verify-work, phase, progress, next, ultraplan-phase, plan-review-convergence, add-tests, ai-integration-phase, autonomous, fast, mvp-phase, quick]
9
9
  ---
10
10
 
11
11
  Route to the appropriate phase-pipeline skill based on the user's intent.
12
12
  Sub-skill names below are post-#2790 consolidated targets — `gsd-phase`
13
13
  absorbs the former add/insert/remove/edit-phase commands and `gsd-progress`
14
- absorbs the former next/do commands.
14
+ absorbs the former next/do workflow-advance commands. The reclaimed
15
+ `gsd-next` target is the state-aware smart-entry launcher, not the retired
16
+ workflow-advance command.
15
17
 
16
18
  | User wants | Invoke |
17
19
  |---|---|
@@ -22,6 +24,7 @@ absorbs the former next/do commands.
22
24
  | Verify built features through UAT | gsd-verify-work |
23
25
  | Add / insert / remove / edit a phase | gsd-phase |
24
26
  | Advance to the next logical step | gsd-progress |
27
+ | Open the state-aware smart-entry launcher | gsd-next |
25
28
  | Offload planning to the ultraplan cloud | gsd-ultraplan-phase |
26
29
  | Cross-AI plan review convergence loop | gsd-plan-review-convergence |
27
30
  | Generate tests for a completed phase | gsd-add-tests |
@@ -0,0 +1,46 @@
1
+ ---
2
+ name: gsd:onboard
3
+ description: Guide existing codebase onboarding through mapping, doc ingest, and planning setup
4
+ argument-hint: "[--fast] [--text]"
5
+ allowed-tools:
6
+ - Read
7
+ - Bash
8
+ - Write
9
+ - Glob
10
+ - Grep
11
+ - Agent
12
+ - AskUserQuestion
13
+ requires: [config, new-project, map-codebase, ingest-docs, manager]
14
+ ---
15
+ <runtime_note>
16
+ **Copilot (VS Code):** Use `vscode_askquestions` wherever this workflow calls `AskUserQuestion`. They are equivalent — `vscode_askquestions` is the VS Code Copilot implementation of the same interactive question API.
17
+ </runtime_note>
18
+
19
+ <objective>
20
+ Guide brownfield onboarding for an existing codebase by routing through the existing GSD primitives in the safe order: codebase map → docs ingest → project initialization → onboarding summary.
21
+
22
+ **Creates or confirms:**
23
+ - `.planning/codebase/` — evidence-backed codebase map from `/gsd:map-codebase`
24
+ - `.planning/PROJECT.md`, `REQUIREMENTS.md`, `ROADMAP.md`, `STATE.md` — project setup from `/gsd:new-project` or `/gsd:ingest-docs`
25
+ - `.planning/onboarding/SUMMARY.md` — lightweight index of what was learned and the next command
26
+
27
+ **Non-goals:** This command does not execute phases, ship work, or overwrite existing planning artifacts without an explicit gate.
28
+ </objective>
29
+
30
+ <execution_context>
31
+ @~/.claude/gsd-core/workflows/onboard.md
32
+ @~/.claude/gsd-core/references/ui-brand.md
33
+ @~/.claude/gsd-core/references/gate-prompts.md
34
+ </execution_context>
35
+
36
+ <context>
37
+ Arguments: $ARGUMENTS
38
+
39
+ Flags:
40
+ - `--fast` — prefer `/gsd:map-codebase --fast` for the mapping handoff; the complete map is still required before `/gsd:new-project`.
41
+ - `--text` — use plain-text numbered lists instead of TUI menus.
42
+ </context>
43
+
44
+ <process>
45
+ Execute the onboard workflow end-to-end. Preserve all safety gates, text-mode fallbacks, idempotency checks, and top-level handoff rules for nested interactive commands.
46
+ </process>
@@ -0,0 +1,246 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ * Self-healing runtime build (#2002).
5
+ *
6
+ * The GSD runtime CLI (gsd-tools.cjs) require()s ~150 compiled modules from
7
+ * ./lib/*.cjs. Per ADR-457 ("build-at-publish") those are build artifacts:
8
+ * compiled from src/*.cts by `npm run build:lib` (tsc -p tsconfig.build.json),
9
+ * gitignored, and shipped prebuilt in the npm tarball via the prepack /
10
+ * prepublishOnly lifecycle scripts.
11
+ *
12
+ * The Claude Code plugin-marketplace channel does NOT go through `npm publish`
13
+ * or bin/install.js. Claude Code materializes the git tag tree into its plugin
14
+ * cache and at most runs `npm install --ignore-scripts`, so neither `prepare`
15
+ * nor `build:lib` ever fires. The compiled ./lib/*.cjs therefore never exist on
16
+ * that path and every CLI command dies at module load with
17
+ * `Cannot find module './lib/cli-exit.cjs'`.
18
+ *
19
+ * This module heals that: before gsd-tools.cjs require()s ./lib, if the compiled
20
+ * output is absent it invokes tsc once — lock-guarded so the many parallel
21
+ * gsd-tools shell-outs a workflow performs do not race the build — then lets the
22
+ * requires proceed. On the npm path the artifacts already exist, so the common
23
+ * case is a single fs.existsSync check and a no-op.
24
+ *
25
+ * Deliberately depends on nothing under ./lib (that tree is precisely what may
26
+ * be missing) — only on Node built-ins.
27
+ */
28
+
29
+ const fs = require('fs');
30
+ const path = require('path');
31
+ const { spawnSync } = require('child_process');
32
+
33
+ // The first module gsd-tools.cjs require()s, and a gitignored build artifact
34
+ // (so it is absent on a raw git-tag checkout even though ~11 other bin/lib/*.cjs
35
+ // are git-tracked). tsconfig.build.json sets noEmitOnError:true, so tsc is
36
+ // all-or-nothing: if this file exists, the whole tree was emitted.
37
+ const SENTINEL = 'cli-exit.cjs';
38
+
39
+ /** Directory holding the compiled ./lib/*.cjs, relative to this file. */
40
+ function defaultLibDir() {
41
+ return path.join(__dirname, 'lib');
42
+ }
43
+
44
+ /**
45
+ * Package root (holds tsconfig.build.json + node_modules). This file lives at
46
+ * <root>/gsd-core/bin/ensure-runtime-build.cjs, so the root is two levels up —
47
+ * true for both the dev repo layout and the marketplace plugin-cache checkout
48
+ * (…/<version>/gsd-core/bin/ensure-runtime-build.cjs).
49
+ */
50
+ function defaultPackageRoot() {
51
+ return path.resolve(__dirname, '..', '..');
52
+ }
53
+
54
+ /**
55
+ * Resolve the tsc entry SCRIPT (not the .bin/tsc shim). We run it as
56
+ * `node <tsc.js>` so behaviour is identical on POSIX and Windows and does not
57
+ * depend on a shell or on the .cmd shim. Returns null when TypeScript is not
58
+ * installed under packageRoot.
59
+ */
60
+ function resolveTscScript(packageRoot) {
61
+ try {
62
+ return require.resolve('typescript/bin/tsc', { paths: [packageRoot] });
63
+ } catch {
64
+ return null;
65
+ }
66
+ }
67
+
68
+ function isBuilt(libDir) {
69
+ return fs.existsSync(path.join(libDir, SENTINEL));
70
+ }
71
+
72
+ /** Synchronous sleep with no dependencies, portable across platforms. */
73
+ function sleepSync(ms) {
74
+ Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, Math.max(0, ms));
75
+ }
76
+
77
+ /**
78
+ * Raised when the runtime library is missing and cannot be auto-built. The
79
+ * message is user-facing and actionable; callers print `.message` (not a stack).
80
+ */
81
+ class RuntimeBuildError extends Error {
82
+ constructor(message) {
83
+ super(message);
84
+ this.name = 'RuntimeBuildError';
85
+ this.code = 'GSD_RUNTIME_BUILD_FAILED';
86
+ }
87
+ }
88
+
89
+ /**
90
+ * Ensure the compiled ./lib/*.cjs exist, building them once if absent.
91
+ *
92
+ * Idempotent and safe to call concurrently from many processes. When another
93
+ * process holds the build lock, this one waits for the build to finish rather
94
+ * than launching a competing tsc.
95
+ *
96
+ * @param {object} [opts]
97
+ * @param {string} [opts.libDir] Override the compiled-output directory.
98
+ * @param {string} [opts.packageRoot] Override the tsconfig/node_modules root.
99
+ * @param {string|null} [opts.tscScript] Override tsc resolution (null = "absent").
100
+ * @param {function} [opts.spawn] Override spawnSync (for tests).
101
+ * @param {function} [opts.log] Override the progress logger.
102
+ * @param {number} [opts.waitTimeoutMs] Max wait for a peer build (default 120s).
103
+ * @param {number} [opts.pollMs] Poll interval while waiting (default 100ms).
104
+ * @param {function} [opts.onPoll] Test hook invoked before each wait-poll.
105
+ * @returns {{built: true, healed: boolean, waited?: boolean}}
106
+ * @throws {RuntimeBuildError} when the library is absent and cannot be built.
107
+ */
108
+ function ensureRuntimeBuild(opts = {}) {
109
+ const libDir = opts.libDir || defaultLibDir();
110
+ const packageRoot = opts.packageRoot || defaultPackageRoot();
111
+ const spawn = opts.spawn || spawnSync;
112
+ const log = opts.log || ((m) => process.stderr.write(m + '\n'));
113
+ const waitTimeoutMs = opts.waitTimeoutMs != null ? opts.waitTimeoutMs : 120000;
114
+ const pollMs = opts.pollMs != null ? opts.pollMs : 100;
115
+
116
+ // Fast path: already built (the npm-registry install and every subsequent run).
117
+ if (isBuilt(libDir)) return { built: true, healed: false };
118
+
119
+ const tsconfig = path.join(packageRoot, 'tsconfig.build.json');
120
+ if (!fs.existsSync(tsconfig)) {
121
+ throw new RuntimeBuildError(
122
+ 'GSD runtime library is not built and cannot be auto-built: ' +
123
+ `${tsconfig} not found. Run \`npm run build:lib\` in the gsd-core package.`,
124
+ );
125
+ }
126
+
127
+ const tscScript =
128
+ opts.tscScript !== undefined ? opts.tscScript : resolveTscScript(packageRoot);
129
+ if (!tscScript) {
130
+ throw new RuntimeBuildError(
131
+ `GSD runtime library is not built (missing ${path.join(libDir, SENTINEL)}) ` +
132
+ 'and TypeScript is unavailable to build it. Run ' +
133
+ `\`npm install && npm run build:lib\` in the gsd-core package (${packageRoot}).`,
134
+ );
135
+ }
136
+
137
+ // libDir may not exist yet on a totally fresh tree; create it so the lock and
138
+ // tsc output have a home.
139
+ fs.mkdirSync(libDir, { recursive: true });
140
+ const lockDir = path.join(libDir, '.build.lock');
141
+
142
+ let haveLock = acquireLock(lockDir);
143
+ if (!haveLock) {
144
+ // A peer process is building. Wait for the sentinel rather than racing tsc.
145
+ const deadline = Date.now() + waitTimeoutMs;
146
+ while (!isBuilt(libDir)) {
147
+ if (typeof opts.onPoll === 'function') opts.onPoll();
148
+ if (isBuilt(libDir)) break;
149
+ if (Date.now() > deadline) break; // peer wedged/crashed — take over below
150
+ sleepSync(pollMs);
151
+ }
152
+ if (isBuilt(libDir)) return { built: true, healed: true, waited: true };
153
+ // Peer never finished; try to take over the (stale) lock.
154
+ haveLock = acquireLock(lockDir);
155
+ if (!haveLock && !isBuilt(libDir)) {
156
+ throw new RuntimeBuildError(
157
+ `GSD runtime build did not complete within ${waitTimeoutMs}ms and the ` +
158
+ `build lock (${lockDir}) is held by another process. Remove it and run ` +
159
+ '`npm run build:lib` if this persists.',
160
+ );
161
+ }
162
+ if (isBuilt(libDir)) return { built: true, healed: true, waited: true };
163
+ }
164
+
165
+ try {
166
+ log('gsd: runtime library not built — compiling once (tsc -p tsconfig.build.json)…');
167
+ // Heal only runs when the build is genuinely absent/broken, so force a full
168
+ // emit: a stale incremental cache from a partial build would make tsc report
169
+ // success without re-emitting the (still-missing) sentinel.
170
+ forceFullEmit(packageRoot, tsconfig);
171
+ const res = spawn(process.execPath, [tscScript, '-p', tsconfig], {
172
+ cwd: packageRoot,
173
+ stdio: ['ignore', 'pipe', 'pipe'],
174
+ encoding: 'utf8',
175
+ });
176
+ if (!res || res.status !== 0) {
177
+ const detail = ((res && (res.stderr || res.stdout)) || '').toString().trim();
178
+ throw new RuntimeBuildError(
179
+ `GSD runtime build failed (tsc exit ${res ? res.status : 'unknown'}). ` +
180
+ `Run \`npm run build:lib\` in ${packageRoot} to see the error.` +
181
+ (detail ? `\n${detail}` : ''),
182
+ );
183
+ }
184
+ } finally {
185
+ releaseLock(lockDir);
186
+ }
187
+
188
+ if (!isBuilt(libDir)) {
189
+ throw new RuntimeBuildError(
190
+ `GSD runtime build ran but ${path.join(libDir, SENTINEL)} is still missing. ` +
191
+ `Run \`npm run build:lib\` in ${packageRoot}.`,
192
+ );
193
+ }
194
+ return { built: true, healed: true };
195
+ }
196
+
197
+ /**
198
+ * Delete tsc's incremental build cache so the heal re-emits every module. The
199
+ * cache path defaults to tsconfig.build.tsbuildinfo (per tsconfig.build.json)
200
+ * but is read from the config when overridden. Best-effort: a missing or
201
+ * unreadable config just falls back to the default and a missing cache is fine.
202
+ */
203
+ function forceFullEmit(packageRoot, tsconfigPath) {
204
+ let rel = 'tsconfig.build.tsbuildinfo';
205
+ try {
206
+ const cfg = JSON.parse(fs.readFileSync(tsconfigPath, 'utf8'));
207
+ if (cfg && cfg.compilerOptions && cfg.compilerOptions.tsBuildInfoFile) {
208
+ rel = cfg.compilerOptions.tsBuildInfoFile;
209
+ }
210
+ } catch {
211
+ /* unreadable/JSONC config — use the default cache path */
212
+ }
213
+ try {
214
+ fs.rmSync(path.resolve(packageRoot, rel), { force: true });
215
+ } catch {
216
+ /* best effort */
217
+ }
218
+ }
219
+
220
+ /** Atomically acquire the build lock. Returns true on success. */
221
+ function acquireLock(lockDir) {
222
+ try {
223
+ fs.mkdirSync(lockDir); // atomic — throws EEXIST if a peer holds it
224
+ return true;
225
+ } catch (e) {
226
+ if (e && e.code === 'EEXIST') return false;
227
+ throw e;
228
+ }
229
+ }
230
+
231
+ /** Best-effort lock release. */
232
+ function releaseLock(lockDir) {
233
+ try {
234
+ fs.rmSync(lockDir, { recursive: true, force: true });
235
+ } catch {
236
+ /* best effort — a leftover lock is recovered by the wait-then-takeover path */
237
+ }
238
+ }
239
+
240
+ module.exports = {
241
+ ensureRuntimeBuild,
242
+ resolveTscScript,
243
+ isBuilt,
244
+ RuntimeBuildError,
245
+ SENTINEL,
246
+ };
@@ -179,14 +179,23 @@
179
179
  *
180
180
  * Loop Extension Point Queries (ADR-857 phase 3c):
181
181
  * loop render-hooks <point> Resolve + render active Capability hooks at a loop point
182
+ * [--config-dir <path>] [--runtime <r>] [--active-cap <capId>]
182
183
  * Returns JSON envelope { point, activeHooks, rendered }
183
184
  * Valid points: discuss:pre/post, plan:pre/post,
184
185
  * execute:pre/wave:pre/wave:post/post, verify:pre/post, ship:pre/post
186
+ * --runtime: override the auto-detected runtime (#2003) so the config
187
+ * dir resolves to that runtime's home even when
188
+ * .planning/config.json persists a different runtime.
185
189
  *
186
190
  * Capability State (ADR-857 phase 4b):
187
- * capability state [--config-dir <path>] Resolve per-capability install/surface/hook-activation state
191
+ * capability state [--config-dir <path>] [--runtime <r>] Resolve per-capability install/surface/hook-activation state
188
192
  * Returns JSON envelope { runtimeConfigDir, capabilities[] }
189
193
  * --config-dir: runtime config dir (default: auto-detect current runtime)
194
+ * --runtime: override the auto-detected runtime (#2003); bypasses the
195
+ * GSD_RUNTIME → config.runtime → 'claude' precedence so a
196
+ * repo with a persisted runtime can still resolve another
197
+ * runtime's config dir (e.g. driving Claude Code from a
198
+ * repo that persists runtime:"codex").
190
199
  *
191
200
  * GSD-2 Migration:
192
201
  * from-gsd2 [--path <dir>] [--force] [--dry-run]
@@ -195,6 +204,24 @@
195
204
 
196
205
  const fs = require('fs');
197
206
  const path = require('path');
207
+
208
+ // #2002 — self-healing runtime build. The compiled ./lib/*.cjs modules this
209
+ // entrypoint require()s below are gitignored build artifacts (ADR-457), shipped
210
+ // prebuilt in the npm tarball. The Claude Code plugin-marketplace channel never
211
+ // runs `npm run build:lib` or bin/install.js, so on that path they can be
212
+ // absent and every command dies at module load. Compile them once (lock-guarded,
213
+ // idempotent, a no-op when already built) before the ./lib requires run.
214
+ const { ensureRuntimeBuild } = require('./ensure-runtime-build.cjs');
215
+ try {
216
+ ensureRuntimeBuild();
217
+ } catch (bootErr) {
218
+ process.stderr.write((bootErr && bootErr.message ? bootErr.message : String(bootErr)) + '\n');
219
+ // Fatal bootstrap failure before the CLI's ExitError/runMain machinery (which
220
+ // lives in ./lib) is available to load, so a direct exit is the only option.
221
+ // eslint-disable-next-line n/no-process-exit
222
+ process.exit(1);
223
+ }
224
+
198
225
  const { ExitError, runMain } = require('./lib/cli-exit.cjs');
199
226
  const io = require('./lib/io.cjs');
200
227
  const { error, ERROR_REASON, setJsonErrorMode, output } = io;
@@ -259,6 +286,7 @@ const { routePhasesCommand } = require('./lib/phases-command-router.cjs');
259
286
  const { routeValidateCommand } = require('./lib/validate-command-router.cjs');
260
287
  const { routeRoadmapCommand } = require('./lib/roadmap-command-router.cjs');
261
288
  const { routeAgentCommand } = require('./lib/agent-command-router.cjs');
289
+ const smartEntryMod = require('./lib/smart-entry.cjs');
262
290
  const { routeCheckCommand } = require('./lib/check-command-router.cjs');
263
291
  const { routeTaskCommand } = require('./lib/task-command-router.cjs');
264
292
  const { parseNamedArgs, parseMultiwordArg } = require('./lib/command-arg-projection.cjs');
@@ -665,7 +693,7 @@ async function main() {
665
693
  'from-gsd2, frontmatter, gap-analysis, generate-claude-md, generate-claude-profile, ' +
666
694
  'generate-dev-preferences, generate-slug, graphify, history-digest, init, intel, ' +
667
695
  'capability, classify-confidence, git, learnings, list-seeds, list-todos, loop, milestone, package-legitimacy, phase, phase-plan-index, phases, profile-questionnaire, ' +
668
- 'profile-sample, progress, project-instruction-file, prompt-budget, requirements, research-plan, research-store, resolve-granularity, resolve-model, roadmap, scaffold, state, ' +
696
+ 'profile-sample, progress, project-instruction-file, prompt-budget, requirements, research-plan, research-store, resolve-granularity, resolve-model, roadmap, scaffold, smart-entry, state, ' +
669
697
  'task, template, user-story, validate, verify, verify-path-exists, verify-summary, eval, workstream, worktree\n\n' +
670
698
  'Global flags:\n' +
671
699
  ' --raw Emit raw output without post-processing\n' +
@@ -833,6 +861,11 @@ async function runCommand(command, args, cwd, raw, defaultValue, originalCommand
833
861
  break;
834
862
  }
835
863
 
864
+ case 'smart-entry': {
865
+ smartEntryMod.runSmartEntry(cwd, args, raw);
866
+ break;
867
+ }
868
+
836
869
  case 'check': {
837
870
  routeCheckCommand({ args, cwd, raw });
838
871
  break;
@@ -1574,9 +1607,28 @@ async function runCommand(command, args, cwd, raw, defaultValue, originalCommand
1574
1607
  }
1575
1608
  loopActiveCap = value;
1576
1609
  }
1610
+ // --runtime <r> (#2003): explicit runtime override so the config-dir
1611
+ // resolution bypasses the persisted-runtime fallback (GSD_RUNTIME →
1612
+ // config.runtime). Mirrors the --config-dir dual-form (--runtime X /
1613
+ // --runtime=X) and the capability-set --runtime precedent.
1614
+ let loopRuntime = undefined;
1615
+ const runtimeEqArg = args.find(arg => arg.startsWith('--runtime='));
1616
+ const runtimeIdx = args.indexOf('--runtime');
1617
+ if (runtimeEqArg) {
1618
+ const value = runtimeEqArg.slice('--runtime='.length).trim();
1619
+ if (!value) error('Missing value for --runtime', ERROR_REASON ? ERROR_REASON.USAGE : undefined);
1620
+ loopRuntime = value;
1621
+ } else if (runtimeIdx !== -1) {
1622
+ const value = args[runtimeIdx + 1];
1623
+ if (!value || value.startsWith('--')) {
1624
+ error('Missing value for --runtime', ERROR_REASON ? ERROR_REASON.USAGE : undefined);
1625
+ }
1626
+ loopRuntime = value;
1627
+ }
1577
1628
  loopResolver.cmdLoopRenderHooks(cwd, args[2], raw, {
1578
1629
  configDir: loopConfigDir ? path.resolve(loopConfigDir) : undefined,
1579
1630
  activeCap: loopActiveCap,
1631
+ runtime: loopRuntime,
1580
1632
  });
1581
1633
  } else {
1582
1634
  error(
@@ -1728,7 +1780,24 @@ async function runCommand(command, args, cwd, raw, defaultValue, originalCommand
1728
1780
  configDir = configDirVal;
1729
1781
  }
1730
1782
  const resolvedConfigDir = configDir ? path.resolve(configDir) : null;
1731
- capabilityState.cmdCapabilityState(cwd, resolvedConfigDir, raw, {});
1783
+ // --runtime <r> (#2003): explicit runtime override so the config-dir
1784
+ // resolution bypasses the persisted-runtime fallback. Dual-form like
1785
+ // --config-dir (--runtime X / --runtime=X).
1786
+ let stateRuntime = undefined;
1787
+ const stateRuntimeEqArg = args.find(arg => arg.startsWith('--runtime='));
1788
+ const stateRuntimeIdx = args.indexOf('--runtime');
1789
+ if (stateRuntimeEqArg) {
1790
+ const value = stateRuntimeEqArg.slice('--runtime='.length).trim();
1791
+ if (!value) error('Missing value for --runtime', ERROR_REASON ? ERROR_REASON.USAGE : undefined);
1792
+ stateRuntime = value;
1793
+ } else if (stateRuntimeIdx !== -1) {
1794
+ const value = args[stateRuntimeIdx + 1];
1795
+ if (!value || value.startsWith('--')) {
1796
+ error('Missing value for --runtime', ERROR_REASON ? ERROR_REASON.USAGE : undefined);
1797
+ }
1798
+ stateRuntime = value;
1799
+ }
1800
+ capabilityState.cmdCapabilityState(cwd, resolvedConfigDir, raw, { runtime: stateRuntime });
1732
1801
  } else if (capSubcommand === 'set') {
1733
1802
  // capability set <id> [--on|--off|--enable|--disable] [--gate <key>=<bool>]... [--config-dir <dir>] [--runtime <r>] [--scope <s>]
1734
1803
  const capId = args[2];