@opengsd/gsd-core 1.6.0-rc.1 → 1.6.0-rc.2

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 (48) hide show
  1. package/.claude-plugin/plugin.json +1 -1
  2. package/agents/gsd-roadmapper.md +6 -0
  3. package/bin/install.js +92 -332
  4. package/commands/gsd/capture.md +5 -1
  5. package/gemini-extension.json +1 -1
  6. package/gsd-core/bin/gsd-tools.cjs +18 -3
  7. package/gsd-core/bin/lib/adr-parser.cjs +21 -6
  8. package/gsd-core/bin/lib/capability-registry.cjs +48 -48
  9. package/gsd-core/bin/lib/commands.cjs +247 -0
  10. package/gsd-core/bin/lib/config-loader.cjs +6 -0
  11. package/gsd-core/bin/lib/config.cjs +6 -0
  12. package/gsd-core/bin/lib/frontmatter.cjs +7 -3
  13. package/gsd-core/bin/lib/phase-id.cjs +25 -11
  14. package/gsd-core/bin/lib/phase.cjs +4 -4
  15. package/gsd-core/bin/lib/probe-core.cjs +7 -0
  16. package/gsd-core/bin/lib/prohibition-enforcement.cjs +59 -26
  17. package/gsd-core/bin/lib/roadmap-command-router.cjs +16 -3
  18. package/gsd-core/bin/lib/roadmap-parser.cjs +29 -8
  19. package/gsd-core/bin/lib/roadmap-upgrade.cjs +47 -17
  20. package/gsd-core/bin/lib/roadmap.cjs +5 -2
  21. package/gsd-core/bin/lib/runtime-artifact-conversion.cjs +423 -3
  22. package/gsd-core/bin/lib/runtime-artifact-install-plan.cjs +77 -0
  23. package/gsd-core/bin/lib/runtime-artifact-layout.cjs +1 -28
  24. package/gsd-core/bin/lib/runtime-name-policy.cjs +44 -0
  25. package/gsd-core/bin/lib/shell-command-projection.cjs +55 -1
  26. package/gsd-core/bin/lib/surface.cjs +12 -19
  27. package/gsd-core/bin/lib/validate.cjs +5 -2
  28. package/gsd-core/bin/lib/verify.cjs +11 -2
  29. package/gsd-core/bin/lib/worktree-safety.cjs +202 -0
  30. package/gsd-core/bin/shared/config-defaults.manifest.json +2 -1
  31. package/gsd-core/bin/shared/config-schema.manifest.json +1 -0
  32. package/gsd-core/references/context-budget.md +8 -8
  33. package/gsd-core/references/execute-phase-context-guard.md +16 -0
  34. package/gsd-core/references/planning-config.md +1 -0
  35. package/gsd-core/references/prohibition-probe.md +15 -9
  36. package/gsd-core/workflows/autonomous.md +33 -33
  37. package/gsd-core/workflows/diagnose-issues.md +6 -1
  38. package/gsd-core/workflows/execute-phase.md +8 -6
  39. package/gsd-core/workflows/help/modes/full.md +10 -0
  40. package/gsd-core/workflows/list-seeds.md +63 -0
  41. package/gsd-core/workflows/manager.md +37 -37
  42. package/gsd-core/workflows/pr-branch.md +156 -0
  43. package/gsd-core/workflows/quick.md +6 -1
  44. package/gsd-core/workflows/review.md +10 -2
  45. package/gsd-core/workflows/spec-phase.md +8 -3
  46. package/gsd-core/workflows/verify-phase.md +2 -2
  47. package/package.json +4 -1
  48. package/scripts/prompt-injection-scan.sh +1 -0
@@ -157,6 +157,14 @@ Provide structured feedback on plan quality, completeness, and risks.
157
157
 
158
158
  ## Review Instructions
159
159
 
160
+ **Verify against source — do not review the plan text in isolation.** You are running inside the project's git working tree (the current directory). The plans reference real files, migrations, routes, and tests that exist in this repo now.
161
+ 1. Open the referenced files and check each claim against the actual code.
162
+ 2. For every strength or concern, cite concrete `path/to/file:line` evidence plus the mechanism.
163
+ 3. When a plan asserts a mechanism works (a guard, a query filter, a test that exercises a path), trace whether it actually does what is claimed — do not take the plan's word for it.
164
+ 4. If you cannot read the repo (no file access), say so and downgrade that finding to an open question rather than asserting it.
165
+
166
+ Findings citing `file:line` evidence are weighted far more heavily than impressionistic ones; a review that only restates the plan's own claims has low value.
167
+
160
168
  Analyze each plan and provide:
161
169
 
162
170
  1. **Summary** — One-paragraph assessment
@@ -273,7 +281,7 @@ fi
273
281
 
274
282
  **CodeRabbit:**
275
283
 
276
- Note: CodeRabbit reviews the current git diff/working tree — it does not accept a prompt or model flag. It may take up to 5 minutes. Use `timeout: 360000` on the Bash tool call.
284
+ Note: CodeRabbit reviews the current git diff/working tree — it does not accept a prompt or model flag. It may take up to 5 minutes. Use `timeout: 360000` on the Bash tool call. The source-grounding requirement in the build_prompt Review Instructions applies only to the prompt-fed reviewers above; CodeRabbit is a diff-only reviewer and never receives it. Treat its output as a diff observation, not a grounded plan-level verdict.
277
285
 
278
286
  ```bash
279
287
  coderabbit review --prompt-only 2>/dev/null > /tmp/gsd-review-coderabbit-{phase}.md
@@ -714,7 +722,7 @@ trimmed_reviewers: # only present if at least one reviewer was trimmed
714
722
 
715
723
  ## Consensus Summary
716
724
 
717
- {synthesize common concerns across all reviewers}
725
+ {synthesize common concerns across all reviewers. CodeRabbit is a diff-only reviewer (it never received the source-grounding prompt), so do not weight its verdict as a grounded plan review — fold in its diff findings, but base plan-level consensus on the prompt-fed reviewers.}
718
726
 
719
727
  ### Agreed Strengths
720
728
  {strengths mentioned by 2+ reviewers}
@@ -365,10 +365,15 @@ For each Requirement gathered so far, run the two-stage recall→precision pass:
365
365
  - `check_target` — the negative-test file path (for `node-test`), or the path to lint
366
366
  (for `lint-rule`).
367
367
  - `check_rule` — the eslint rule id (e.g. `local/no-source-grep`); `lint-rule` only.
368
- - `check_violation_fixture` (#1346) — path to a KNOWN-BAD subject the wired check is run
368
+ - `check_violation_fixture` (#1279) — path to a KNOWN-BAD subject the wired check is run
369
369
  against to **machine-prove fail-first**; rides BOTH kinds. Capture it to let the item green
370
370
  end-to-end with zero hand-authoring at verify time; for `node-test` the negative test should
371
371
  read its subject from the `GSD_PROHIB_SUBJECT` env var so the prover can inject this fixture.
372
+ - `check_clean_fixture` (#1346) — **optional** path to a KNOWN-CLEAN control subject. When
373
+ captured, the `node-test` prover also runs the check against it and requires GREEN — proving
374
+ the violation's RED is caused by the subject's *content*, not by `GSD_PROHIB_SUBJECT` merely
375
+ being set. Capture it for a stronger guarantee; omit it and the check still proves fail-first
376
+ on the violation alone (the content-causation residual stays documented for that case).
372
377
  This is a **SOFT capture (CHK-04): a `test`-tier prohibition WITHOUT a descriptor is still
373
378
  allowed** — if the author cannot yet name the wired check, leave the descriptor empty and
374
379
  proceed. It is NOT a hard authoring block; the item simply stays fail-closed/flagged
@@ -395,7 +400,7 @@ For each Requirement gathered so far, run the two-stage recall→precision pass:
395
400
  written (test or judgment tier); otherwise leave `unresolved`. **`--auto` NEVER auto-dismisses
396
401
  a prohibition** — a wrong dismissal is the exact silent failure this probe eliminates (PROB-06,
397
402
  the load-bearing safety property). On a `test`-tier auto-resolution, capture the `check_kind` /
398
- `check_target` / `check_rule` / `check_violation_fixture` descriptor **only when a wired check is unambiguous**; otherwise
403
+ `check_target` / `check_rule` / `check_violation_fixture` / `check_clean_fixture` descriptor **only when a wired check is unambiguous**; otherwise
399
404
  leave it empty — `--auto` NEVER fabricates a check path or fixture (a wrong locate is re-validated and
400
405
  fails closed at the producer, but a fabricated path is still noise to avoid). Log:
401
406
  `[auto] prohibitions: R resolved, U unresolved`.
@@ -408,7 +413,7 @@ Populate the `## Prohibitions` section of SPEC.md from the resolved prohibitions
408
413
  `resolved`/`test` row is a checkable negative acceptance criterion; `resolved`/`judgment`
409
414
  rows route to judgment review; `⚠ UNRESOLVED` rows are flagged as assumptions). A
410
415
  `resolved`/`test` row ALSO carries its captured `check_kind` / `check_target` / `check_rule` /
411
- `check_violation_fixture` descriptor when present (so the projection feeds `verify-phase`'s deterministic locate + machine-proof, #1278 + #1346);
416
+ `check_violation_fixture` / `check_clean_fixture` descriptor when present (so the projection feeds `verify-phase`'s deterministic locate + machine-proof + causation control, #1278 + #1279 + #1346);
412
417
  a `test` row with no captured descriptor is still valid — it stays fail-closed/flagged
413
418
  downstream rather than blocking authoring.
414
419
 
@@ -76,11 +76,11 @@ Aggregate all must_haves across plans for phase-level verification.
76
76
  gsd_run check prohibition-enforcement <request.json>
77
77
  ```
78
78
 
79
- where `<request.json>` carries `{ prohibition, check, mode }` — `check` being the wired mechanical-check descriptor `{ kind: 'node-test' | 'lint-rule', target, rule?, violationFixture, failFirst? }`, with `kind`/`target`/`rule`/`violationFixture` now sourced from the projected `check_*` scalars (not author/verifier invention — #1278 + #1346). For `node-test`, `target` (from `check_target`) is the negative-test file path; for `lint-rule`, `target` is the PATH to lint and `rule` (from `check_rule`) is the eslint rule id (e.g. `local/no-source-grep`) — both required (a lint-rule without `rule` is not a valid wired check). `violationFixture` (from `check_violation_fixture`) is the path to a KNOWN-BAD subject the producer runs the check against to **machine-prove fail-first** (for `node-test`, injected via the `GSD_PROHIB_SUBJECT` env convention — #1279); `failFirst` is a DEMOTED, non-authoritative hint kept only for backward route-JSON shape (no path greens on it alone — FF-08). The producer LOCATES the wired check from the projection, **machine-proves it is fail-first** by running it against the violation and confirming it goes RED, RUNS it for a genuine non-vacuous pass, builds `enforcementEvidence`, and emits the `dispositionForProhibition()` verdict (#1259 + #1278 + #1279, ADR-550 D5d). Fail-first is **machine-proven, not caller-attested** — absent a provable violation the producer fails closed, never falling back to attestation. Route the result by its typed fields:
79
+ where `<request.json>` carries `{ prohibition, check, mode }` — `check` being the wired mechanical-check descriptor `{ kind: 'node-test' | 'lint-rule', target, rule?, violationFixture, cleanFixture?, failFirst? }`, with `kind`/`target`/`rule`/`violationFixture`/`cleanFixture` now sourced from the projected `check_*` scalars (not author/verifier invention — #1278 + #1279 + #1346). For `node-test`, `target` (from `check_target`) is the negative-test file path; for `lint-rule`, `target` is the PATH to lint and `rule` (from `check_rule`) is the eslint rule id (e.g. `local/no-source-grep`) — both required (a lint-rule without `rule` is not a valid wired check). `violationFixture` (from `check_violation_fixture`) is the path to a KNOWN-BAD subject the producer runs the check against to **machine-prove fail-first** (for `node-test`, injected via the `GSD_PROHIB_SUBJECT` env convention — #1279); the optional `cleanFixture` (from `check_clean_fixture`) is a KNOWN-CLEAN control subject the `node-test` prover ALSO requires to stay GREEN, proving the RED is content-caused (#1346); `failFirst` is a DEMOTED, non-authoritative hint kept only for backward route-JSON shape (no path greens on it alone — FF-08). The producer LOCATES the wired check from the projection, **machine-proves it is fail-first** by running it against the violation and confirming it goes RED, RUNS it for a genuine non-vacuous pass, builds `enforcementEvidence`, and emits the `dispositionForProhibition()` verdict (#1259 + #1278 + #1279, ADR-550 D5d). Fail-first is **machine-proven, not caller-attested** — absent a provable violation the producer fails closed, never falling back to attestation. Route the result by its typed fields:
80
80
  - **`status: 'green'`, `flagged: false`** (a genuinely-passing wired negative test / lint rule, `located: true`, non-empty `evidence`) → the item is satisfiable → it can reach **passed**.
81
81
  - **missing, non-attested, or genuinely-non-passing check** (`located: false` OR `status: 'unverified'`, `flagged: true`) → **hard-gate**: disposes flagged-unverified, NEVER green, routing to `gaps_found` in BOTH interactive and autonomous modes (a failing mechanical check blocks even AFK; ADR-550 D4 / D3). The deterministic fail-closed default backing every miss/fail is `dispositionForProhibition()` in probe-core (`status: 'unverified'`, `flagged: true` on empty `enforcementEvidence`).
82
82
 
83
- > **Descriptor source — deterministic locate + machine-proof compose (#1278 + #1346, DELIVERED).** The `check` descriptor's `{ kind, target, rule, violationFixture }` is now sourced **deterministically from the projected `check_kind` / `check_target` / `check_rule` / `check_violation_fixture` scalars** on the `must_haves.prohibitions` item (authored at `/gsd:spec-phase`, projected by `projectProhibitions`, read back via the `descriptorFromProjection` adapter). So both halves close with **zero manual descriptor authoring** — the verifier neither invents the locate (#1278) nor hand-supplies the violation fixture (#1346): a prohibition authored with all four scalars machine-proves fail-first and greens end-to-end through the projection alone (removing the spoofable invent-at-verify-time surface; ADR-857 §147 exogenous grading). **Fail-closed is preserved:** an item with NO projected descriptor, a PARTIAL one (e.g. a `lint-rule` missing `check_rule`), OR a descriptor with **no `check_violation_fixture`** makes `descriptorFromProjection` return `null` / an under-specified or fixture-less descriptor, which falls through to the producer's fail-closed paths (`located: false`, or located-but-unprovable) → flagged-unverified, NEVER green, in BOTH modes. `failFirst` is demoted and greens nothing on its own (#1279, FF-08). Residual (tracked **#1346**): the node-test proof confirms the fixture exists and the check goes RED, but cannot generically prove the red was *caused by* the subject's content vs the env merely being set.
83
+ > **Descriptor source — deterministic locate + machine-proof compose (#1278 + #1346, DELIVERED).** The `check` descriptor's `{ kind, target, rule, violationFixture }` is now sourced **deterministically from the projected `check_kind` / `check_target` / `check_rule` / `check_violation_fixture` scalars** on the `must_haves.prohibitions` item (authored at `/gsd:spec-phase`, projected by `projectProhibitions`, read back via the `descriptorFromProjection` adapter). So both halves close with **zero manual descriptor authoring** — the verifier neither invents the locate (#1278) nor hand-supplies the violation fixture (#1346): a prohibition authored with all four scalars machine-proves fail-first and greens end-to-end through the projection alone (removing the spoofable invent-at-verify-time surface; ADR-857 §147 exogenous grading). **Fail-closed is preserved:** an item with NO projected descriptor, a PARTIAL one (e.g. a `lint-rule` missing `check_rule`), OR a descriptor with **no `check_violation_fixture`** makes `descriptorFromProjection` return `null` / an under-specified or fixture-less descriptor, which falls through to the producer's fail-closed paths (`located: false`, or located-but-unprovable) → flagged-unverified, NEVER green, in BOTH modes. `failFirst` is demoted and greens nothing on its own (#1279, FF-08). Causation (**#1346**): supplying `check_clean_fixture` adds an opt-in control — the `node-test` prover also requires GREEN on a known-clean subject, proving the RED is content-caused; with no clean fixture that one residual case (a deceptive test reding merely because the env var is set) stays a documented constraint, an author opting into the stronger proof by wiring a clean control.
84
84
 
85
85
  **Option B: Use Success Criteria from ROADMAP.md**
86
86
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@opengsd/gsd-core",
3
- "version": "1.6.0-rc.1",
3
+ "version": "1.6.0-rc.2",
4
4
  "description": "GSD Core is a meta-prompting, context engineering, and spec-driven development system for AI coding agents.",
5
5
  "bin": {
6
6
  "gsd-core": "bin/install.js",
@@ -120,5 +120,8 @@
120
120
  "test:coverage:all": "npm run test:coverage",
121
121
  "test:mutation": "stryker run",
122
122
  "test:mutation:since": "stryker run --incremental --since origin/next"
123
+ },
124
+ "allowScripts": {
125
+ "fallow@2.70.0": true
123
126
  }
124
127
  }
@@ -78,6 +78,7 @@ ALLOWLIST=(
78
78
  'hooks/gsd-read-injection-scanner.js'
79
79
  'tests/read-injection-scanner.security.test.cjs'
80
80
  'tests/security-prompt-injection.security.test.cjs'
81
+ 'tests/list-seeds.test.cjs'
81
82
  'tests/fixtures/adversarial/security/'
82
83
  'SECURITY.md'
83
84
  # These files contain intentional injection examples / security-model prose