@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
@@ -36,6 +36,11 @@
36
36
  * (`{ namedDispatch, nested, maxDepth, background, subagentToolkit }`) —
37
37
  * this registry accepts a free-form human summary string instead, so it
38
38
  * carries the `AXES_FREE_STRING` sentinel rather than an enum array.
39
+ * `OPTIONAL_AXES` adds one further, OPTIONAL key on top of those eight:
40
+ * `effortSurface` (ADR-1239 amendment #2481). An entry may omit it
41
+ * (every entry published before the amendment stays valid) or declare
42
+ * it as `argv` | `none`, mirroring `HOST_INTEGRATION_AXES.effortSurface`
43
+ * in `src/host-integration.cts`.
39
44
  * - `CAPABILITY_REQUIRED` / `EOS_REQUIRED` mirror the required top-level
40
45
  * fields for each entry type, including `enginesGsd` (ADR-1244 D1
41
46
  * "Versioned capability manifest" — the `engines.gsd` semver-range gate,
@@ -90,6 +95,18 @@ const AXES = Object.freeze({
90
95
  runtime: Object.freeze(['node', 'bun', 'sandboxed-web', 'python', 'go', 'rust', 'electron', 'other']),
91
96
  });
92
97
 
98
+ // ─── ADR-1239 amendment #2481 — one additional, OPTIONAL negotiated axis ─────
99
+ // `effortSurface` was added to the runtime-descriptor vocabulary AFTER the
100
+ // original eight (`HOST_INTEGRATION_AXES.effortSurface` in
101
+ // `src/host-integration.cts`). It is kept OPTIONAL here — not folded into
102
+ // `AXES` — because registry entries mirror their upstream
103
+ // `registry/eos-entry.json` byte-for-byte, and requiring it would
104
+ // retroactively invalidate every entry published before the amendment.
105
+ // Values must match `HOST_INTEGRATION_AXES.effortSurface` exactly.
106
+ const OPTIONAL_AXES = Object.freeze({
107
+ effortSurface: Object.freeze(['argv', 'none']),
108
+ });
109
+
93
110
  // ─── Required top-level fields ───────────────────────────────────────────────
94
111
  const CAPABILITY_REQUIRED = Object.freeze([
95
112
  'id',
@@ -246,15 +263,39 @@ function validateEosInteractions(interactions, addError) {
246
263
  if (typeof axes !== 'object' || axes === null || Array.isArray(axes)) {
247
264
  addError('interactions.axes', 'axes must be an object');
248
265
  } else {
249
- const expectedKeys = Object.keys(AXES);
266
+ const requiredKeys = Object.keys(AXES);
267
+ const optionalKeys = Object.keys(OPTIONAL_AXES);
250
268
  const actualKeys = Object.keys(axes);
251
269
  const actualKeySet = new Set(actualKeys);
252
- const keysMatch = expectedKeys.length === actualKeys.length && expectedKeys.every((k) => actualKeySet.has(k));
253
- if (!keysMatch) {
254
- addError('interactions.axes', 'axes key set must exactly match the eight negotiated axes');
255
- } else {
256
- for (const key of expectedKeys) {
257
- const allowedValues = AXES[key];
270
+
271
+ // Every AXES key is mandatory; an extra key is tolerated ONLY when it is
272
+ // a recognized OPTIONAL_AXES key (currently just `effortSurface`) — any
273
+ // other extra key is still rejected as unknown.
274
+ const missingRequiredKeys = requiredKeys.filter((k) => !actualKeySet.has(k));
275
+ const unknownKeys = actualKeys.filter((k) => !requiredKeys.includes(k) && !optionalKeys.includes(k));
276
+
277
+ if (missingRequiredKeys.length > 0) {
278
+ addError('interactions.axes', `axes is missing required key(s): ${missingRequiredKeys.join(', ')}`);
279
+ }
280
+ if (unknownKeys.length > 0) {
281
+ addError('interactions.axes', `axes has unknown key(s): ${unknownKeys.join(', ')}`);
282
+ }
283
+
284
+ // Only validate individual values once the key set itself is sound —
285
+ // mirrors the original gate (values were never checked against a
286
+ // malformed key set either).
287
+ if (missingRequiredKeys.length === 0 && unknownKeys.length === 0) {
288
+ for (const key of actualKeys) {
289
+ // Inline literal guards — CodeQL barrier pattern. Reaching here already
290
+ // implies `key` is one of the nine literal axis names (the unknown-key
291
+ // gate above rejected everything else), so this is unreachable in
292
+ // practice; it is written inline anyway because CodeQL cannot follow
293
+ // that gate across the `.includes()` filter and would otherwise flag
294
+ // the bracket reads below as prototype-pollution sinks.
295
+ if (key === '__proto__') continue;
296
+ if (key === 'constructor') continue;
297
+ if (key === 'prototype') continue;
298
+ const allowedValues = Object.hasOwn(AXES, key) ? AXES[key] : OPTIONAL_AXES[key];
258
299
  const v = axes[key];
259
300
  if (allowedValues === AXES_FREE_STRING) {
260
301
  if (typeof v !== 'string' || v.trim() === '') {
@@ -496,7 +537,14 @@ function renderMarkdown(entries, opts) {
496
537
  lines.push(`- **Author:** ${mdInline(entry.author)}`);
497
538
 
498
539
  if (isEos) {
499
- const axesSummary = Object.keys(AXES)
540
+ // Required AXES keys always render, in their fixed order; an OPTIONAL_AXES
541
+ // key (e.g. `effortSurface`) renders ONLY when the entry actually carries
542
+ // it — an entry that omits it must render byte-identical to before
543
+ // OPTIONAL_AXES existed (no `effortSurface=undefined` noise).
544
+ const presentOptionalKeys = Object.keys(OPTIONAL_AXES).filter(
545
+ (key) => interactions.axes && Object.hasOwn(interactions.axes, key),
546
+ );
547
+ const axesSummary = [...Object.keys(AXES), ...presentOptionalKeys]
500
548
  .map((key) => `${key}=${interactions.axes ? interactions.axes[key] : undefined}`)
501
549
  .join(', ');
502
550
  const summary =
@@ -556,6 +604,7 @@ module.exports = {
556
604
  INTERFACE_POINTS,
557
605
  PROFILES,
558
606
  AXES,
607
+ OPTIONAL_AXES,
559
608
  AXES_FREE_STRING,
560
609
  CAPABILITY_REQUIRED,
561
610
  EOS_REQUIRED,
@@ -30,18 +30,36 @@ const HEADER_RE = /^([a-z]+)(\([^)]*\))?(!)?:/i;
30
30
  // An issue reference inside a scope: `(#123)`, `(#123, core)`, etc.
31
31
  const ISSUE_REF_IN_SCOPE_RE = /#\d+/;
32
32
 
33
+ // #2716: recognized non-user-facing conventional-commit types. A title whose
34
+ // START-anchored type prefix is one of these is internal work (tests, chores,
35
+ // CI, docs, refactors, perf, reverts) and must NOT render under the user-facing
36
+ // "Enhancement" heading in release notes. Only a CLEAN prefix match qualifies —
37
+ // untyped or anchor-defeated titles fall through to the visible Enhancement
38
+ // fallback (a safety net so possibly-user-facing content is never hidden).
39
+ const NON_USER_FACING_TYPES = new Set([
40
+ 'docs', 'refactor', 'test', 'ci', 'chore', 'perf', 'revert',
41
+ ]);
42
+
33
43
  /**
34
44
  * Classify a clean conventional title into a changelog bucket.
35
45
  * Callers that hold a full changelog bullet line (with a `* ` marker and a
36
46
  * ` by @author` suffix) must strip those first; this operates on the title.
37
47
  *
38
48
  * @param {string} title
39
- * @returns {'Feature'|'Fix'|'Enhancement'}
49
+ * @returns {'Feature'|'Fix'|'Enhancement'|'Internal'}
40
50
  */
41
51
  function classifyBucket(title) {
42
52
  const t = String(title == null ? '' : title).trim();
43
53
  if (FEATURE_RE.test(t)) return 'Feature';
44
54
  if (FIX_RE.test(t)) return 'Fix';
55
+ // #2716: a clean non-user-facing type prefix → Internal (omitted from user-facing
56
+ // release-note sections). The HEADER_RE anchor ensures a leading tag/prefix
57
+ // (e.g. `[security] fix(...)`) does NOT match here — those keep falling through
58
+ // to the visible Enhancement fallback.
59
+ const headerMatch = HEADER_RE.exec(t);
60
+ if (headerMatch && NON_USER_FACING_TYPES.has(headerMatch[1].toLowerCase())) {
61
+ return 'Internal';
62
+ }
45
63
  return 'Enhancement';
46
64
  }
47
65
 
@@ -8,9 +8,9 @@ const { runMain, ExitError } = require('../lib/cli-exit.cjs');
8
8
  const { classifyBucket } = require('./conventional-title.cjs');
9
9
 
10
10
  /**
11
- * Classify a What's-Changed bullet line into 'Feature', 'Fix', or 'Enhancement'.
11
+ * Classify a What's-Changed bullet line into 'Feature', 'Fix', 'Enhancement', or 'Internal'.
12
12
  * @param {string} bulletLine - Full bullet line including the leading `* ` or `- ` marker.
13
- * @returns {'Feature'|'Fix'|'Enhancement'}
13
+ * @returns {'Feature'|'Fix'|'Enhancement'|'Internal'}
14
14
  */
15
15
  function classifyTitle(bulletLine) {
16
16
  // Strip leading `* ` or `- ` marker
@@ -83,7 +83,11 @@ function formatReleaseNotes({ generatedBody, version, prerelease, packageName })
83
83
  const category = classifyTitle(trimmed);
84
84
  if (category === 'Feature') featureBullets.push(trimmed);
85
85
  else if (category === 'Fix') fixBullets.push(trimmed);
86
- else enhancementBullets.push(trimmed);
86
+ else if (category === 'Internal') {
87
+ // #2716: non-user-facing work (test/chore/ci/docs/refactor/perf/revert)
88
+ // is omitted from the user-facing "What's Changed" section entirely.
89
+ continue;
90
+ } else enhancementBullets.push(trimmed);
87
91
  continue;
88
92
  }
89
93
 
@@ -5,10 +5,13 @@
5
5
  *
6
6
  * Single source of truth for measuring workflow `.md` file sizes in bytes.
7
7
  *
8
- * Shared by `tests/workflow-size-budget.test.cjs` (the CI guard) and
9
- * `scripts/update-size-baseline.cjs` (the baseline generator) so the two can
10
- * never disagree on HOW a file is measured. A divergence between the generator
11
- * and the guard would silently mis-record the baseline (issue #1074).
8
+ * Shared by `tests/workflow-size-budget.test.cjs` / `tests/agent-size-budget.test.cjs`
9
+ * (the tier hard-cap guards), `tests/helpers/emitted-runtime.cjs`'s `currentSizes()`
10
+ * (the differential attribution check's size ratchet, ADR-2719 Phase 4), and
11
+ * `scripts/gen-emitted-baseline.cjs` (the baseline publisher) so none of them can
12
+ * disagree on HOW a file is measured (issue #1074). `scripts/update-size-baseline.cjs`,
13
+ * the original third consumer, was removed by #2724 along with the per-file baseline
14
+ * it generated.
12
15
  */
13
16
 
14
17
  const fs = require('fs');
@@ -19,11 +22,16 @@ const WORKFLOWS_DIR = path.join(__dirname, '..', 'gsd-core', 'workflows');
19
22
  /**
20
23
  * Byte size of a file, counted as on an LF (Unix) checkout.
21
24
  *
22
- * The size budget is calibrated against `wc -c` on a Unix (LF) checkout, but
23
- * these `.md` files have no `eol=lf` in `.gitattributes`, so Windows checks
24
- * them out as CRLF. Counting raw on-disk bytes there adds one byte per line,
25
- * a Windows-only false positive that diverges from the LF calibration basis
25
+ * The size budget is calibrated against `wc -c` on a Unix (LF) checkout.
26
+ * Counting raw on-disk bytes on a CRLF checkout adds one byte per line, a
27
+ * Windows-only false positive that diverges from the LF calibration basis
26
28
  * (issue #683). Stripping CR yields the same LF byte count on every platform.
29
+ *
30
+ * `.gitattributes:2` (`* text=auto eol=lf`, added in #1088) now normalizes these
31
+ * files to LF on checkout everywhere, so the CRLF case should not arise from a
32
+ * normal clone — but this stays unconditional because it also covers a working
33
+ * tree produced some other way (an unpacked archive, an editor that rewrites
34
+ * line endings, a checkout predating that attribute).
27
35
  * This is still a raw byte count (not a trailing-newline-stripping line count).
28
36
  *
29
37
  * @param {string} filePath - Absolute or relative path to the file.
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: gsd-plan-review-convergence
3
3
  description: "Cross-AI plan convergence - replan until review concerns are resolved."
4
- argument-hint: "<phase> [--codex] [--gemini] [--claude] [--opencode] [--ollama] [--lm-studio] [--llama-cpp] [--agy] [--text] [--ws <name>] [--all] [--max-cycles N]"
4
+ argument-hint: "<phase> [--gemini] [--claude] [--codex] [--coderabbit] [--opencode] [--qwen] [--cursor] [--antigravity] [--agy] [--ollama] [--lm-studio] [--llama-cpp] [--kimi-code] [--text] [--ws <name>] [--all] [--max-cycles N]"
5
5
  allowed-tools:
6
6
  - Read
7
7
  - Write
@@ -44,10 +44,14 @@ Phase number: extracted from $ARGUMENTS (required)
44
44
  - `--gemini` — Use Gemini CLI as reviewer
45
45
  - `--agy` / `--antigravity` — Use Antigravity CLI as reviewer (successor to the discontinued Gemini CLI)
46
46
  - `--claude` — Use Claude CLI as reviewer (separate session)
47
+ - `--coderabbit` — Use CodeRabbit as reviewer (reviews the working-tree diff, not the source tree)
47
48
  - `--opencode` — Use OpenCode as reviewer
49
+ - `--qwen` — Use Qwen Code CLI as reviewer (Alibaba Qwen models)
50
+ - `--cursor` — Use Cursor agent as reviewer
48
51
  - `--ollama` — Use local Ollama server as reviewer (OpenAI-compatible, default host `http://localhost:11434`; configure model via `review.models.ollama`)
49
52
  - `--lm-studio` — Use local LM Studio server as reviewer (OpenAI-compatible, default host `http://localhost:1234`; configure model via `review.models.lm_studio`)
50
53
  - `--llama-cpp` — Use local llama.cpp server as reviewer (OpenAI-compatible, default host `http://localhost:8080`; configure model via `review.models.llama_cpp`)
54
+ - `--kimi-code` — Use Kimi Code CLI as reviewer (Moonshot AI)
51
55
  - `--all` — Use all available CLIs and running local model servers
52
56
  - `--max-cycles N` — Maximum replan→review cycles (default: 3)
53
57
 
@@ -2,7 +2,7 @@
2
2
  "name": "gsd-core-vscode",
3
3
  "displayName": "GSD Core",
4
4
  "description": "GSD orchestration engine embedded in VS Code (ADR-1239 IDE profile).",
5
- "version": "1.8.0",
5
+ "version": "1.9.0",
6
6
  "publisher": "opengsd",
7
7
  "engines": {
8
8
  "vscode": "^1.105.0"
@@ -1,77 +0,0 @@
1
- #!/usr/bin/env node
2
- 'use strict';
3
- /**
4
- * Standalone golden-fixture generator for tests/golden-install-parity.
5
- *
6
- * This is a BUILD-TIME generation script — NOT a test run. It imports the
7
- * canonical buildParityManifest builder from tests/helpers/install-shared.cjs
8
- * (issue #2266 — single source of truth shared with
9
- * tests/golden-install-parity.test.cjs) and captures the zcode fixture so the
10
- * parity test (which the gsd-test gate runs) has a committed artifact to
11
- * compare against. The authoritative test gate remains `gsd-test run`, never
12
- * a local `node --test`.
13
- *
14
- * Usage: node scripts/gen-golden-install-parity-zcode.cjs
15
- */
16
- const fs = require('node:fs');
17
- const path = require('node:path');
18
- const { execFileSync } = require('node:child_process');
19
-
20
- const ROOT = path.resolve(__dirname, '..');
21
- // buildParityManifest (and its exclusion constants) is the canonical single
22
- // source of truth in tests/helpers/install-shared.cjs (issue #2266) — the
23
- // generator no longer keeps its own inline copy, which had drifted from the
24
- // test harness's copy (missing the realpath/`<HOME>` normalization) and
25
- // mis-generated the claude-local fixture (#2100).
26
- const { runMinimalInstall, RUNTIME_META, buildParityManifest, BUILD_SCRIPT } = require(path.join(ROOT, 'tests', 'helpers', 'install-shared.cjs'));
27
- const FIXTURE_DIR = path.join(ROOT, 'tests', 'fixtures', 'golden-install-parity');
28
-
29
- function cleanup(root) {
30
- try { fs.rmSync(root, { recursive: true, force: true }); } catch { /* best effort */ }
31
- }
32
-
33
- // Regenerate the fixture for every runtime in RUNTIME_META. Needed when a
34
- // SHARED gsd-core payload file (e.g. model-catalog.json, capability-registry)
35
- // changes content — its hash appears in every runtime's manifest, so all
36
- // fixtures must be recaptured together. Usage:
37
- // node scripts/gen-golden-install-parity-zcode.cjs [runtime ...]
38
- // With no args, regenerates ALL runtimes. With args, only the named runtimes.
39
- const targets = process.argv.slice(2).length > 0 ? process.argv.slice(2) : Object.keys(RUNTIME_META);
40
- fs.mkdirSync(FIXTURE_DIR, { recursive: true });
41
-
42
- // Build hooks/dist before capturing so fixtures are complete even in a clean
43
- // checkout (hooks/dist is gitignored + built; DEFECT.HOOKS-DIST-SCOPED-CI). The
44
- // test harness's before() hook does the same; without it a fresh checkout omits
45
- // every hooks/* path and this generator silently writes short fixtures.
46
- execFileSync(process.execPath, [BUILD_SCRIPT], { stdio: 'pipe' });
47
-
48
- for (const runtime of targets) {
49
- if (!Object.prototype.hasOwnProperty.call(RUNTIME_META, runtime)) {
50
- process.stderr.write(`[gen] unknown runtime '${runtime}' (not in RUNTIME_META) — skipping\n`);
51
- continue;
52
- }
53
- const { configDir, root } = runMinimalInstall({ runtime, scope: 'global' });
54
- let actual;
55
- try {
56
- actual = buildParityManifest(configDir, root);
57
- } finally {
58
- cleanup(root);
59
- }
60
- const fixturePath = path.join(FIXTURE_DIR, `${runtime}.json`);
61
- fs.writeFileSync(fixturePath, JSON.stringify(actual, null, 2) + '\n', 'utf8');
62
- process.stdout.write(`[gen] ${runtime}: wrote ${Object.keys(actual).length} file hashes -> ${fixturePath}\n`);
63
- }
64
-
65
- // Also regenerate the claude LOCAL legacy-layout fixture (claude-local.json).
66
- // This layout is distinct from the global install (commands/gsd-*.md +
67
- // agents/gsd-*.md) and has its own parity assertion in the test harness.
68
- const { configDir: localConfigDir, root: localRoot } = runMinimalInstall({ runtime: 'claude', scope: 'local' });
69
- let localActual;
70
- try {
71
- localActual = buildParityManifest(localConfigDir, localRoot);
72
- } finally {
73
- cleanup(localRoot);
74
- }
75
- const localFixturePath = path.join(FIXTURE_DIR, 'claude-local.json');
76
- fs.writeFileSync(localFixturePath, JSON.stringify(localActual, null, 2) + '\n', 'utf8');
77
- process.stdout.write(`[gen] claude-local: wrote ${Object.keys(localActual).length} file hashes -> ${localFixturePath}\n`);
@@ -1,68 +0,0 @@
1
- #!/usr/bin/env node
2
- 'use strict';
3
-
4
- /**
5
- * @file update-size-baseline.cjs
6
- *
7
- * Regenerates the committed per-file workflow size baseline
8
- * (`tests/workflow-size-baseline.json`) from the current workflow files.
9
- *
10
- * Run via `npm run size:baseline` whenever a workflow file legitimately grows
11
- * or shrinks. Growth must still be justified in the PR; this script only
12
- * records the new reality so the CI guard (issue #1074) can diff against it.
13
- *
14
- * Idempotent: running it twice with no file changes produces no diff.
15
- */
16
-
17
- const fs = require('fs');
18
- const path = require('path');
19
- const { measureMdFiles, WORKFLOWS_DIR } = require('./workflow-size.cjs');
20
-
21
- const BASELINE_PATH = path.join(__dirname, '..', 'tests', 'workflow-size-baseline.json');
22
- const AGENTS_DIR = path.join(__dirname, '..', 'agents');
23
- const AGENT_BASELINE_PATH = path.join(__dirname, '..', 'tests', 'agent-size-baseline.json');
24
- const isGsdAgent = (f) => f.startsWith('gsd-');
25
-
26
- /**
27
- * Serialize a size map to the on-disk baseline format: keys sorted, 2-space
28
- * indent, trailing newline (so the file is a stable, minimal-diff artifact).
29
- *
30
- * @param {Object<string, number>} sizes
31
- * @returns {string}
32
- */
33
- function serializeBaseline(sizes) {
34
- const sorted = {};
35
- for (const key of Object.keys(sizes).sort()) sorted[key] = sizes[key];
36
- return JSON.stringify(sorted, null, 2) + '\n';
37
- }
38
-
39
- /**
40
- * Write a baseline file from the measured `.md` sizes in a directory.
41
- *
42
- * @param {object} [opts]
43
- * @param {string} [opts.dir] - Directory to measure (default: workflows).
44
- * @param {string} [opts.outPath] - Baseline file to write (default: workflow).
45
- * @param {function(string): boolean} [opts.predicate] - Filename filter.
46
- * @returns {{ outPath: string, count: number, content: string }}
47
- */
48
- function generateBaseline({ dir = WORKFLOWS_DIR, outPath = BASELINE_PATH, predicate } = {}) {
49
- const sizes = measureMdFiles(dir, predicate);
50
- const content = serializeBaseline(sizes);
51
- fs.writeFileSync(outPath, content);
52
- return { outPath, count: Object.keys(sizes).length, content };
53
- }
54
-
55
- if (require.main === module) {
56
- const targets = [
57
- { label: 'workflow', dir: WORKFLOWS_DIR, outPath: BASELINE_PATH },
58
- { label: 'agent', dir: AGENTS_DIR, outPath: AGENT_BASELINE_PATH, predicate: isGsdAgent },
59
- ];
60
- for (const t of targets) {
61
- const { outPath, count } = generateBaseline(t);
62
- process.stdout.write(
63
- `Wrote ${count} ${t.label} sizes to ${path.relative(process.cwd(), outPath)}\n`
64
- );
65
- }
66
- }
67
-
68
- module.exports = { generateBaseline, serializeBaseline, BASELINE_PATH, AGENT_BASELINE_PATH };