@opengsd/gsd-core 1.7.0-rc.3 → 1.7.0-rc.5

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 (115) 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 +20 -0
  4. package/README.ja-JP.md +4 -3
  5. package/README.ko-KR.md +4 -3
  6. package/README.md +4 -3
  7. package/README.pt-BR.md +4 -3
  8. package/README.zh-CN.md +4 -3
  9. package/agents/gsd-doc-classifier.md +105 -0
  10. package/agents/gsd-doc-synthesizer.md +61 -0
  11. package/agents/gsd-ui-checker.md +28 -0
  12. package/bin/install.js +652 -466
  13. package/commands/gsd/map-codebase.md +4 -4
  14. package/commands/gsd/ns-project.md +2 -1
  15. package/commands/gsd/onboard.md +46 -0
  16. package/gsd-core/bin/gsd-tools.cjs +87 -3
  17. package/gsd-core/bin/lib/api-coverage.cjs +466 -0
  18. package/gsd-core/bin/lib/audit.cjs +6 -3
  19. package/gsd-core/bin/lib/capability-loader.cjs +11 -9
  20. package/gsd-core/bin/lib/capability-registry.cjs +741 -62
  21. package/gsd-core/bin/lib/capability-state.cjs +117 -18
  22. package/gsd-core/bin/lib/capability-validator.cjs +1 -1
  23. package/gsd-core/bin/lib/capability-writer.cjs +21 -2
  24. package/gsd-core/bin/lib/check-command-router.cjs +242 -3
  25. package/gsd-core/bin/lib/claude-orchestration-command-router.cjs +136 -0
  26. package/gsd-core/bin/lib/claude-orchestration.cjs +404 -0
  27. package/gsd-core/bin/lib/clusters.cjs +1 -0
  28. package/gsd-core/bin/lib/command-aliases.cjs +8 -0
  29. package/gsd-core/bin/lib/commands.cjs +7 -5
  30. package/gsd-core/bin/lib/config-loader.cjs +1 -0
  31. package/gsd-core/bin/lib/config.cjs +96 -0
  32. package/gsd-core/bin/lib/core-utils.cjs +4 -1
  33. package/gsd-core/bin/lib/host-integration-adapters/cline-sdk-binding.cjs +234 -0
  34. package/gsd-core/bin/lib/host-integration-adapters/imperative-hook-bus.cjs +145 -0
  35. package/gsd-core/bin/lib/host-integration.cjs +16 -0
  36. package/gsd-core/bin/lib/init-command-router.cjs +4 -0
  37. package/gsd-core/bin/lib/init.cjs +99 -99
  38. package/gsd-core/bin/lib/install-effort-resolver.cjs +213 -0
  39. package/gsd-core/bin/lib/install-engine.cjs +159 -16
  40. package/gsd-core/bin/lib/install-profiles.cjs +2 -0
  41. package/gsd-core/bin/lib/installer-migration-report.cjs +4 -0
  42. package/gsd-core/bin/lib/loop-resolver.cjs +75 -18
  43. package/gsd-core/bin/lib/markdown-sectionizer.cjs +50 -11
  44. package/gsd-core/bin/lib/milestone.cjs +3 -3
  45. package/gsd-core/bin/lib/model-resolver.cjs +69 -4
  46. package/gsd-core/bin/lib/normalize-test-command.cjs +187 -0
  47. package/gsd-core/bin/lib/onboard-projection.cjs +309 -0
  48. package/gsd-core/bin/lib/phase-id.cjs +132 -3
  49. package/gsd-core/bin/lib/phase.cjs +78 -16
  50. package/gsd-core/bin/lib/planning-workspace.cjs +17 -0
  51. package/gsd-core/bin/lib/roadmap-command-router.cjs +5 -4
  52. package/gsd-core/bin/lib/roadmap-parser.cjs +21 -30
  53. package/gsd-core/bin/lib/roadmap-upgrade.cjs +9 -9
  54. package/gsd-core/bin/lib/roadmap.cjs +42 -56
  55. package/gsd-core/bin/lib/runtime-artifact-conversion.cjs +13 -6
  56. package/gsd-core/bin/lib/runtime-artifact-install-plan.cjs +2 -2
  57. package/gsd-core/bin/lib/runtime-artifact-layout.cjs +17 -10
  58. package/gsd-core/bin/lib/runtime-homes.cjs +8 -0
  59. package/gsd-core/bin/lib/runtime-hooks-surface.cjs +33 -25
  60. package/gsd-core/bin/lib/runtime-name-policy.cjs +3 -1
  61. package/gsd-core/bin/lib/spec-section.cjs +111 -0
  62. package/gsd-core/bin/lib/state-transition.cjs +1 -1
  63. package/gsd-core/bin/lib/state.cjs +24 -24
  64. package/gsd-core/bin/lib/surface.cjs +81 -30
  65. package/gsd-core/bin/lib/uat.cjs +4 -1
  66. package/gsd-core/bin/lib/validate.cjs +15 -6
  67. package/gsd-core/bin/lib/verify.cjs +33 -37
  68. package/gsd-core/bin/shared/config-schema.manifest.json +2 -0
  69. package/gsd-core/bin/shared/model-catalog.json +11 -6
  70. package/gsd-core/references/api-coverage.md +104 -0
  71. package/gsd-core/references/gsd-run-resolver.md +8 -0
  72. package/gsd-core/references/model-profiles.md +2 -2
  73. package/gsd-core/references/planning-config.md +2 -0
  74. package/gsd-core/references/specless-probe-fallback.md +172 -0
  75. package/gsd-core/templates/config.json +2 -1
  76. package/gsd-core/templates/project.md +1 -1
  77. package/gsd-core/workflows/audit-fix.md +9 -1
  78. package/gsd-core/workflows/code-review-fix.md +7 -3
  79. package/gsd-core/workflows/code-review.md +4 -1
  80. package/gsd-core/workflows/discuss-phase-assumptions.md +4 -1
  81. package/gsd-core/workflows/do.md +4 -3
  82. package/gsd-core/workflows/execute-phase/steps/post-merge-gate.md +8 -4
  83. package/gsd-core/workflows/execute-phase/steps/regression-gate.md +42 -0
  84. package/gsd-core/workflows/execute-phase.md +1 -25
  85. package/gsd-core/workflows/help/modes/brief.md +2 -1
  86. package/gsd-core/workflows/help/modes/default.md +2 -1
  87. package/gsd-core/workflows/help/modes/full.md +11 -1
  88. package/gsd-core/workflows/help/modes/topic.md +1 -1
  89. package/gsd-core/workflows/onboard.md +277 -0
  90. package/gsd-core/workflows/plan-phase.md +31 -2
  91. package/gsd-core/workflows/quick.md +22 -2
  92. package/gsd-core/workflows/review.md +59 -13
  93. package/gsd-core/workflows/settings-advanced.md +5 -5
  94. package/gsd-core/workflows/settings.md +2 -2
  95. package/gsd-core/workflows/verify-phase.md +3 -2
  96. package/gsd-core/workflows/verify-work.md +38 -0
  97. package/hooks/dist/gsd-cursor-pre-tool.js +76 -0
  98. package/hooks/dist/gsd-cursor-stop.js +48 -0
  99. package/hooks/dist/gsd-cursor-subagent-start.js +50 -0
  100. package/hooks/dist/gsd-cursor-subagent-stop.js +40 -0
  101. package/hooks/dist/managed-hooks-registry.cjs +4 -0
  102. package/hooks/gsd-cursor-pre-tool.js +76 -0
  103. package/hooks/gsd-cursor-stop.js +48 -0
  104. package/hooks/gsd-cursor-subagent-start.js +50 -0
  105. package/hooks/gsd-cursor-subagent-stop.js +40 -0
  106. package/hooks/managed-hooks-registry.cjs +4 -0
  107. package/package.json +2 -1
  108. package/scripts/build-hooks.js +5 -1
  109. package/scripts/gen-golden-install-parity-zcode.cjs +77 -0
  110. package/scripts/lint-phase-id-drift.cjs +150 -0
  111. package/scripts/run-tests.cjs +26 -4
  112. package/scripts/sync-runtime-launcher.cjs +20 -2
  113. package/skills/gsd-map-codebase/SKILL.md +3 -3
  114. package/skills/gsd-ns-project/SKILL.md +1 -0
  115. package/skills/gsd-onboard/SKILL.md +46 -0
@@ -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>
@@ -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 |
@@ -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>
@@ -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]
@@ -679,7 +688,7 @@ async function main() {
679
688
  // phase / roadmap / milestone / progress / etc.
680
689
  const TOP_LEVEL_USAGE = 'Usage: gsd-tools <command> [args] [--raw] [--pick <field>] [--cwd <path>] [--ws <name>] [--json-errors]\n' +
681
690
  'Commands: agent, agent-skills, assumption-delta, audit-open, audit-uat, check, check-commit, commit, commit-to-subrepo, pr-subrepo, ' +
682
- 'config-ensure-section, config-get, config-new-project, config-path, config-set, migrate-config, ' +
691
+ 'config-ensure-section, config-get, config-new-project, config-path, config-set, migrate-config, normalize-test-command, ' +
683
692
  'current-timestamp, detect-custom-files, docs-init, drift-guard, effort, extract-messages, find-phase, ' +
684
693
  'from-gsd2, frontmatter, gap-analysis, generate-claude-md, generate-claude-profile, ' +
685
694
  'generate-dev-preferences, generate-slug, graphify, history-digest, init, intel, ' +
@@ -1282,6 +1291,16 @@ async function runCommand(command, args, cwd, raw, defaultValue, originalCommand
1282
1291
  break;
1283
1292
  }
1284
1293
 
1294
+ case 'normalize-test-command': {
1295
+ // #1857: rewrite a resolved test command to a one-shot form so a
1296
+ // watch-mode runner (vitest/jest) cannot hang a verification gate. Shared
1297
+ // by the regression gate and the post-merge gate. args[1] is the raw
1298
+ // resolved command; --cwd (already parsed into `cwd`) locates package.json.
1299
+ const testCommandNormalizer = require('./lib/normalize-test-command.cjs');
1300
+ testCommandNormalizer.cmdNormalizeTestCommand(cwd, args[1]);
1301
+ break;
1302
+ }
1303
+
1285
1304
  case 'dispatch-should-flatten': {
1286
1305
  // #1708 / #853: typed query replacing the `RUNTIME === 'codex'` prose rule.
1287
1306
  //
@@ -1598,9 +1617,28 @@ async function runCommand(command, args, cwd, raw, defaultValue, originalCommand
1598
1617
  }
1599
1618
  loopActiveCap = value;
1600
1619
  }
1620
+ // --runtime <r> (#2003): explicit runtime override so the config-dir
1621
+ // resolution bypasses the persisted-runtime fallback (GSD_RUNTIME →
1622
+ // config.runtime). Mirrors the --config-dir dual-form (--runtime X /
1623
+ // --runtime=X) and the capability-set --runtime precedent.
1624
+ let loopRuntime = undefined;
1625
+ const runtimeEqArg = args.find(arg => arg.startsWith('--runtime='));
1626
+ const runtimeIdx = args.indexOf('--runtime');
1627
+ if (runtimeEqArg) {
1628
+ const value = runtimeEqArg.slice('--runtime='.length).trim();
1629
+ if (!value) error('Missing value for --runtime', ERROR_REASON ? ERROR_REASON.USAGE : undefined);
1630
+ loopRuntime = value;
1631
+ } else if (runtimeIdx !== -1) {
1632
+ const value = args[runtimeIdx + 1];
1633
+ if (!value || value.startsWith('--')) {
1634
+ error('Missing value for --runtime', ERROR_REASON ? ERROR_REASON.USAGE : undefined);
1635
+ }
1636
+ loopRuntime = value;
1637
+ }
1601
1638
  loopResolver.cmdLoopRenderHooks(cwd, args[2], raw, {
1602
1639
  configDir: loopConfigDir ? path.resolve(loopConfigDir) : undefined,
1603
1640
  activeCap: loopActiveCap,
1641
+ runtime: loopRuntime,
1604
1642
  });
1605
1643
  } else {
1606
1644
  error(
@@ -1752,7 +1790,24 @@ async function runCommand(command, args, cwd, raw, defaultValue, originalCommand
1752
1790
  configDir = configDirVal;
1753
1791
  }
1754
1792
  const resolvedConfigDir = configDir ? path.resolve(configDir) : null;
1755
- capabilityState.cmdCapabilityState(cwd, resolvedConfigDir, raw, {});
1793
+ // --runtime <r> (#2003): explicit runtime override so the config-dir
1794
+ // resolution bypasses the persisted-runtime fallback. Dual-form like
1795
+ // --config-dir (--runtime X / --runtime=X).
1796
+ let stateRuntime = undefined;
1797
+ const stateRuntimeEqArg = args.find(arg => arg.startsWith('--runtime='));
1798
+ const stateRuntimeIdx = args.indexOf('--runtime');
1799
+ if (stateRuntimeEqArg) {
1800
+ const value = stateRuntimeEqArg.slice('--runtime='.length).trim();
1801
+ if (!value) error('Missing value for --runtime', ERROR_REASON ? ERROR_REASON.USAGE : undefined);
1802
+ stateRuntime = value;
1803
+ } else if (stateRuntimeIdx !== -1) {
1804
+ const value = args[stateRuntimeIdx + 1];
1805
+ if (!value || value.startsWith('--')) {
1806
+ error('Missing value for --runtime', ERROR_REASON ? ERROR_REASON.USAGE : undefined);
1807
+ }
1808
+ stateRuntime = value;
1809
+ }
1810
+ capabilityState.cmdCapabilityState(cwd, resolvedConfigDir, raw, { runtime: stateRuntime });
1756
1811
  } else if (capSubcommand === 'set') {
1757
1812
  // capability set <id> [--on|--off|--enable|--disable] [--gate <key>=<bool>]... [--config-dir <dir>] [--runtime <r>] [--scope <s>]
1758
1813
  const capId = args[2];
@@ -2095,6 +2150,28 @@ async function runCommand(command, args, cwd, raw, defaultValue, originalCommand
2095
2150
  }
2096
2151
  }
2097
2152
  } catch { /* best-effort — list still works without the inactive annotation */ }
2153
+ // Issue #2045 (DEFECT 3): derive each capability's SURFACED state from the
2154
+ // SAME resolver `capability state` uses (resolveCapabilityRuntimeState), so
2155
+ // `list` and `state` stop disagreeing. `list` previously derived `status`
2156
+ // purely from ledger-entry existence — an installed-but-not-surfaced cap
2157
+ // reported active in `list` and absent in `state`. Surfaced is evaluated at
2158
+ // the default runtime config dir (the resolver resolves it when undefined),
2159
+ // matching `capability state <id>` with no --config-dir. Best-effort: a
2160
+ // resolver failure leaves surfacedById empty (rows report surfaced:null).
2161
+ const surfacedById = {};
2162
+ // surfacedById is keyed by capId only (NOT `${scope} ${capId}`): surface
2163
+ // state is single-source — one runtime config dir → one .gsd-surface.json
2164
+ // → one surfaced truth per capId — and the loader dedupes overlay caps to
2165
+ // one registry entry per id (first-party-wins). So a cap installed in both
2166
+ // scopes correctly shares one surfaced value across its list rows.
2167
+ try {
2168
+ const surfaceState = capabilityState.resolveCapabilityRuntimeState(cwd, undefined);
2169
+ for (const cap of (surfaceState && surfaceState.capabilities) || []) {
2170
+ if (cap && typeof cap.id === 'string') {
2171
+ surfacedById[cap.id] = cap.surfaced === true;
2172
+ }
2173
+ }
2174
+ } catch { /* best-effort — list still works without the surfaced annotation */ }
2098
2175
  for (const capId of Object.keys(fp)) {
2099
2176
  const cap = fp[capId] || {};
2100
2177
  rows.push({
@@ -2105,6 +2182,7 @@ async function runCommand(command, args, cwd, raw, defaultValue, originalCommand
2105
2182
  source: 'first-party',
2106
2183
  scope: 'first-party',
2107
2184
  status: 'active',
2185
+ surfaced: Object.prototype.hasOwnProperty.call(surfacedById, capId) ? surfacedById[capId] === true : null,
2108
2186
  title: cap.title || null,
2109
2187
  });
2110
2188
  }
@@ -2154,6 +2232,12 @@ async function runCommand(command, args, cwd, raw, defaultValue, originalCommand
2154
2232
  scope: sc,
2155
2233
  status,
2156
2234
  reason,
2235
+ // Issue #2045 (DEFECT 3): surfaced reflects surface composition, so
2236
+ // list and state agree. An inactive (unconsented/incompatible) cap is
2237
+ // surfaced:false by definition; otherwise defer to the resolver.
2238
+ surfaced: status === 'active'
2239
+ ? (Object.prototype.hasOwnProperty.call(surfacedById, capId) ? surfacedById[capId] === true : null)
2240
+ : false,
2157
2241
  title: manifest.title || null,
2158
2242
  });
2159
2243
  }