@opengsd/gsd-core 1.14.0 → 1.15.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.
- package/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/README.ja-JP.md +3 -3
- package/README.ko-KR.md +3 -3
- package/README.pt-BR.md +3 -3
- package/README.zh-CN.md +3 -3
- package/agents/gsd-code-fixer.compact.md +7 -6
- package/agents/gsd-code-fixer.md +9 -8
- package/agents/gsd-debug-session-manager.compact.md +17 -2
- package/agents/gsd-debug-session-manager.md +17 -2
- package/agents/gsd-debugger.md +2 -2
- package/agents/gsd-eval-auditor.compact.md +1 -1
- package/agents/gsd-eval-auditor.md +1 -1
- package/agents/gsd-executor.md +13 -8
- package/agents/gsd-intel-updater.compact.md +1 -1
- package/agents/gsd-intel-updater.md +1 -1
- package/agents/gsd-phase-researcher.md +19 -11
- package/agents/gsd-plan-checker.md +8 -7
- package/agents/gsd-planner.md +12 -8
- package/agents/gsd-project-researcher.compact.md +1 -1
- package/agents/gsd-project-researcher.md +1 -1
- package/agents/gsd-research-synthesizer.compact.md +1 -1
- package/agents/gsd-research-synthesizer.md +1 -1
- package/agents/gsd-ui-auditor.md +155 -17
- package/agents/gsd-ui-researcher.compact.md +1 -1
- package/agents/gsd-ui-researcher.md +1 -1
- package/agents/gsd-verifier.md +10 -9
- package/bin/install.js +642 -95
- package/commands/gsd/autonomous.md +2 -2
- package/commands/gsd/capture.md +1 -1
- package/commands/gsd/mempalace-capture.md +7 -3
- package/commands/gsd/plan-review-convergence.md +6 -6
- package/commands/gsd/progress.md +1 -1
- package/commands/gsd/quick-batch.md +1 -1
- package/commands/gsd/review.md +2 -3
- package/gsd-core/bin/gsd-tools.cjs +335 -22
- package/gsd-core/bin/lib/adr-parser.cjs +3 -1
- package/gsd-core/bin/lib/audit.cjs +81 -13
- package/gsd-core/bin/lib/capability-registry.cjs +82 -187
- package/gsd-core/bin/lib/capability-validator.cjs +0 -1
- package/gsd-core/bin/lib/check-command-router.cjs +101 -14
- package/gsd-core/bin/lib/codex-agent-toml.cjs +21 -25
- package/gsd-core/bin/lib/commands.cjs +175 -42
- package/gsd-core/bin/lib/config-loader.cjs +65 -4
- package/gsd-core/bin/lib/config.cjs +33 -7
- package/gsd-core/bin/lib/decisions.cjs +30 -14
- package/gsd-core/bin/lib/frontmatter.cjs +13 -0
- package/gsd-core/bin/lib/graphify.cjs +10 -2
- package/gsd-core/bin/lib/host-runtime-detection.cjs +9 -0
- package/gsd-core/bin/lib/init.cjs +207 -41
- package/gsd-core/bin/lib/install-engine.cjs +13 -0
- package/gsd-core/bin/lib/installer-migrations.cjs +8 -1
- package/gsd-core/bin/lib/milestone.cjs +18 -5
- package/gsd-core/bin/lib/model-resolver.cjs +159 -50
- package/gsd-core/bin/lib/phase-command-router.cjs +9 -1
- package/gsd-core/bin/lib/phase-id-card.cjs +32 -0
- package/gsd-core/bin/lib/phase-id-display.cjs +78 -0
- package/gsd-core/bin/lib/phase-id.cjs +109 -7
- package/gsd-core/bin/lib/phase-locator.cjs +29 -10
- package/gsd-core/bin/lib/phase.cjs +227 -26
- package/gsd-core/bin/lib/plan-document.cjs +49 -1
- package/gsd-core/bin/lib/planning-document.cjs +459 -0
- package/gsd-core/bin/lib/planning-inspect.cjs +18 -1
- package/gsd-core/bin/lib/planning-workspace.cjs +8 -3
- package/gsd-core/bin/lib/pr-branch-patterns.cjs +57 -0
- package/gsd-core/bin/lib/probe-core.cjs +7 -1
- package/gsd-core/bin/lib/project-root.cjs +41 -2
- package/gsd-core/bin/lib/review-lane-descriptor.cjs +10 -30
- package/gsd-core/bin/lib/review-reviewer-selection.cjs +2 -2
- package/gsd-core/bin/lib/roadmap-command-router.cjs +12 -4
- package/gsd-core/bin/lib/roadmap-parser.cjs +163 -3
- package/gsd-core/bin/lib/roadmap-upgrade.cjs +1539 -13
- package/gsd-core/bin/lib/roadmap.cjs +251 -31
- package/gsd-core/bin/lib/runtime-artifact-conversion.cjs +283 -31
- package/gsd-core/bin/lib/runtime-artifact-install-plan.cjs +3 -1
- package/gsd-core/bin/lib/runtime-homes.cjs +4 -0
- package/gsd-core/bin/lib/runtime-hooks-surface.cjs +215 -33
- package/gsd-core/bin/lib/runtime-name-policy.cjs +111 -1
- package/gsd-core/bin/lib/shell-command-projection.cjs +10 -6
- package/gsd-core/bin/lib/state-transition.cjs +39 -2
- package/gsd-core/bin/lib/state.cjs +42 -0
- package/gsd-core/bin/lib/surface.cjs +17 -1
- package/gsd-core/bin/lib/tdd-red-evidence.cjs +78 -5
- package/gsd-core/bin/lib/uat-predicate.cjs +47 -4
- package/gsd-core/bin/lib/uat.cjs +8 -0
- package/gsd-core/bin/lib/ui-consideration-probe.cjs +15 -2
- package/gsd-core/bin/lib/ui-frontend-evidence.cjs +100 -9
- package/gsd-core/bin/lib/undo-commit-selection.cjs +131 -0
- package/gsd-core/bin/lib/verification.cjs +268 -15
- package/gsd-core/bin/lib/verify-command-grounding.cjs +46 -2
- package/gsd-core/bin/lib/verify.cjs +132 -25
- package/gsd-core/bin/lib/worktree-base-ref.cjs +482 -73
- package/gsd-core/bin/lib/worktree-safety.cjs +784 -51
- package/gsd-core/bin/shared/config-defaults.manifest.json +3 -0
- package/gsd-core/bin/shared/config-schema.manifest.json +1 -0
- package/gsd-core/references/checkpoints.md +5 -3
- package/gsd-core/references/edge-probe-fixtures/01-round-half-even/expected-coverage.json +28 -3
- package/gsd-core/references/edge-probe-fixtures/02-merge-intervals/expected-coverage.json +37 -4
- package/gsd-core/references/edge-probe-fixtures/03-truncate-graphemes/expected-coverage.json +28 -3
- package/gsd-core/references/edge-probe-fixtures/04-money-rounding/expected-coverage.json +28 -3
- package/gsd-core/references/edge-probe-fixtures/05-list-dedupe/expected-coverage.json +37 -4
- package/gsd-core/references/edge-probe-fixtures/06-resolved-mixed/expected-coverage.json +37 -4
- package/gsd-core/references/edge-probe.md +195 -21
- package/gsd-core/references/execute-phase-between-wave-reset.md +7 -6
- package/gsd-core/references/execute-phase-wave-guard.md +22 -11
- package/gsd-core/references/gsd-run-resolver.md +1 -1
- package/gsd-core/references/model-profiles.md +1 -1
- package/gsd-core/references/phase-argument-parsing.md +9 -7
- package/gsd-core/references/phase-id-convention.md +28 -0
- package/gsd-core/references/planner-gap-closure.md +2 -0
- package/gsd-core/references/planner-load-graph-context.md +24 -13
- package/gsd-core/references/planner-verify-command-grounding.md +14 -0
- package/gsd-core/references/planning-config.md +11 -2
- package/gsd-core/references/tdd.md +27 -4
- package/gsd-core/references/ui-consideration-probe.md +10 -5
- package/gsd-core/references/verify-command-path-resolvability.md +10 -2
- package/gsd-core/references/worktree-path-safety.md +321 -0
- package/gsd-core/templates/verification-report.md +1 -1
- package/gsd-core/workflows/_runtime-launcher.snippet.sh +1 -1
- package/gsd-core/workflows/add-backlog.md +1 -1
- package/gsd-core/workflows/add-phase.md +1 -1
- package/gsd-core/workflows/add-tests.md +2 -2
- package/gsd-core/workflows/add-todo.md +3 -3
- package/gsd-core/workflows/ai-integration-phase.md +11 -3
- package/gsd-core/workflows/audit-fix.md +1 -1
- package/gsd-core/workflows/audit-milestone.md +1 -1
- package/gsd-core/workflows/audit-uat.md +1 -1
- package/gsd-core/workflows/autonomous/steps/converge-fail-fast.md +9 -18
- package/gsd-core/workflows/autonomous.md +16 -6
- package/gsd-core/workflows/check-todos.md +2 -2
- package/gsd-core/workflows/cleanup.md +2 -2
- package/gsd-core/workflows/code-review/steps/dispatch-fix.md +4 -3
- package/gsd-core/workflows/code-review/steps/structural-pre-pass.md +1 -1
- package/gsd-core/workflows/code-review-fix.md +108 -22
- package/gsd-core/workflows/code-review.md +63 -46
- package/gsd-core/workflows/complete-milestone/detail/elaboration.md +1 -1
- package/gsd-core/workflows/complete-milestone.md +2 -2
- package/gsd-core/workflows/debug.md +3 -3
- package/gsd-core/workflows/diagnose-issues.md +1 -1
- package/gsd-core/workflows/discuss-phase/modes/advisor.md +1 -1
- package/gsd-core/workflows/discuss-phase/modes/chain.md +1 -1
- package/gsd-core/workflows/discuss-phase-assumptions.md +1 -1
- package/gsd-core/workflows/discuss-phase.md +1 -1
- package/gsd-core/workflows/do.md +2 -2
- package/gsd-core/workflows/docs-update.md +3 -3
- package/gsd-core/workflows/edit-phase.md +1 -1
- package/gsd-core/workflows/eval-review.md +10 -3
- package/gsd-core/workflows/execute-phase/detail/elaboration.md +2 -2
- package/gsd-core/workflows/execute-phase/steps/code-review-disposition.md +1017 -0
- package/gsd-core/workflows/execute-phase/steps/codebase-drift-gate.md +1 -1
- package/gsd-core/workflows/execute-phase/steps/completion-reconciliation.md +3 -3
- package/gsd-core/workflows/execute-phase/steps/executor-isolation-dispatch.md +37 -3
- package/gsd-core/workflows/execute-phase/steps/gap-closure-artifacts.md +1 -1
- package/gsd-core/workflows/execute-phase/steps/partial-wave.md +1 -1
- package/gsd-core/workflows/execute-phase/steps/per-plan-executor-routing.md +1 -1
- package/gsd-core/workflows/execute-phase/steps/per-plan-worktree-gate.md +1 -1
- package/gsd-core/workflows/execute-phase/steps/post-merge-gate.md +46 -9
- package/gsd-core/workflows/execute-phase/steps/protected-branch.md +1 -1
- package/gsd-core/workflows/execute-phase/steps/ready-wave-gate.md +37 -0
- package/gsd-core/workflows/execute-phase/steps/regression-gate-run.md +1 -1
- package/gsd-core/workflows/execute-phase/steps/stale-reverification.md +24 -0
- package/gsd-core/workflows/execute-phase/steps/tdd-applicability-resolution.md +1 -1
- package/gsd-core/workflows/execute-phase/steps/threat-id-gate.md +28 -0
- package/gsd-core/workflows/execute-phase/steps/wave-post-gate-hooks.md +1 -1
- package/gsd-core/workflows/execute-phase/steps/worktree-base-check.md +25 -0
- package/gsd-core/workflows/execute-phase.md +36 -26
- package/gsd-core/workflows/execute-plan.md +5 -4
- package/gsd-core/workflows/explore.md +3 -3
- package/gsd-core/workflows/extract-learnings.md +2 -1
- package/gsd-core/workflows/fast.md +1 -1
- package/gsd-core/workflows/forensics.md +1 -1
- package/gsd-core/workflows/graduation.md +1 -1
- package/gsd-core/workflows/health.md +2 -2
- package/gsd-core/workflows/help/modes/full.compact.md +3 -3
- package/gsd-core/workflows/help/modes/full.md +5 -5
- package/gsd-core/workflows/help/modes/topic.md +15 -5
- package/gsd-core/workflows/import.md +2 -2
- package/gsd-core/workflows/inbox.md +2 -2
- package/gsd-core/workflows/ingest-docs.md +3 -3
- package/gsd-core/workflows/insert-phase.md +1 -1
- package/gsd-core/workflows/list-seeds.md +1 -1
- package/gsd-core/workflows/list-workspaces.md +1 -1
- package/gsd-core/workflows/manager.md +2 -2
- package/gsd-core/workflows/map-codebase.md +2 -2
- package/gsd-core/workflows/milestone-summary.md +1 -1
- package/gsd-core/workflows/mvp-phase.md +1 -1
- package/gsd-core/workflows/new-milestone.md +2 -2
- package/gsd-core/workflows/new-project/steps/auto-mode-config.md +3 -3
- package/gsd-core/workflows/new-project/steps/codebase-map-offer.md +1 -1
- package/gsd-core/workflows/new-project.md +7 -7
- package/gsd-core/workflows/new-workspace.md +2 -2
- package/gsd-core/workflows/next.md +1 -1
- package/gsd-core/workflows/note.md +1 -1
- package/gsd-core/workflows/onboard.md +1 -1
- package/gsd-core/workflows/pause-work.md +1 -1
- package/gsd-core/workflows/plan-phase/detail/elaboration.md +1 -1
- package/gsd-core/workflows/plan-phase/steps/chunked-planning-mode.md +17 -5
- package/gsd-core/workflows/plan-phase/steps/prd-express-path.md +1 -1
- package/gsd-core/workflows/plan-phase/steps/stall-detection-helpers.md +23 -5
- package/gsd-core/workflows/plan-phase.md +24 -7
- package/gsd-core/workflows/plan-review-convergence.md +21 -5
- package/gsd-core/workflows/plant-seed.md +62 -20
- package/gsd-core/workflows/pr-branch.md +113 -13
- package/gsd-core/workflows/profile-user.md +2 -2
- package/gsd-core/workflows/progress.md +1 -1
- package/gsd-core/workflows/quick/steps/plan-checker-loop.md +25 -0
- package/gsd-core/workflows/quick/steps/quick-verification.md +1 -1
- package/gsd-core/workflows/quick/steps/worktree-pre-dispatch-commit.md +1 -1
- package/gsd-core/workflows/quick-batch/steps/batch-init.md +1 -1
- package/gsd-core/workflows/quick-batch/steps/completion.md +1 -1
- package/gsd-core/workflows/quick-batch/steps/merge-wave.md +1 -1
- package/gsd-core/workflows/quick-batch/steps/planner-wave.md +1 -1
- package/gsd-core/workflows/quick-batch/steps/research-phase.md +1 -1
- package/gsd-core/workflows/quick-batch/steps/resume-mode.md +1 -1
- package/gsd-core/workflows/quick-batch/steps/verification-wave.md +1 -1
- package/gsd-core/workflows/quick-batch/steps/worktree-dispatch.md +1 -1
- package/gsd-core/workflows/quick-batch.md +1 -1
- package/gsd-core/workflows/quick.md +21 -9
- package/gsd-core/workflows/reapply-patches.md +9 -3
- package/gsd-core/workflows/remove-phase.md +1 -1
- package/gsd-core/workflows/remove-workspace.md +2 -2
- package/gsd-core/workflows/resume-project.md +1 -1
- package/gsd-core/workflows/review.md +31 -16
- package/gsd-core/workflows/scan.md +1 -1
- package/gsd-core/workflows/secure-phase.md +3 -2
- package/gsd-core/workflows/settings-advanced.md +30 -10
- package/gsd-core/workflows/settings-integrations.md +2 -3
- package/gsd-core/workflows/settings.md +4 -4
- package/gsd-core/workflows/ship.md +3 -2
- package/gsd-core/workflows/sketch-wrap-up.md +1 -1
- package/gsd-core/workflows/sketch.md +1 -1
- package/gsd-core/workflows/smart-entry.md +2 -2
- package/gsd-core/workflows/spec-phase.md +15 -5
- package/gsd-core/workflows/spike-wrap-up.md +1 -1
- package/gsd-core/workflows/spike.md +1 -1
- package/gsd-core/workflows/stats.md +1 -1
- package/gsd-core/workflows/sync-skills.md +5 -5
- package/gsd-core/workflows/thread.md +1 -1
- package/gsd-core/workflows/transition.md +1 -1
- package/gsd-core/workflows/ui-phase.md +44 -8
- package/gsd-core/workflows/ui-review.md +18 -4
- package/gsd-core/workflows/ultraplan-phase.md +1 -1
- package/gsd-core/workflows/undo.md +339 -20
- package/gsd-core/workflows/update.md +7 -7
- package/gsd-core/workflows/validate-phase.md +3 -2
- package/gsd-core/workflows/verify-work/steps/automated-ui-verification.md +1 -1
- package/gsd-core/workflows/verify-work/steps/mvp-uat-framing.md +1 -1
- package/gsd-core/workflows/verify-work.md +81 -16
- package/hooks/dist/gsd-agent-isolation-guard.js +24 -0
- package/hooks/dist/gsd-secret-read-guard.js +27 -1
- package/hooks/dist/gsd-statusline.js +70 -13
- package/hooks/dist/gsd-validate-commit.sh +63 -4
- package/hooks/gsd-agent-isolation-guard.js +24 -0
- package/hooks/gsd-secret-read-guard.js +27 -1
- package/hooks/gsd-statusline.js +70 -13
- package/hooks/gsd-validate-commit.sh +63 -4
- package/package.json +3 -2
- package/scripts/build-hooks.js +15 -6
- package/scripts/check-contract-drift.cjs +127 -11
- package/scripts/command-contract-helpers.cjs +3 -0
- package/scripts/docs-guard-registry.cjs +28 -0
- package/scripts/gen-loop-host-contract.cjs +69 -0
- package/scripts/lib/macos-conformance-tier.generated.cjs +14 -0
- package/scripts/lib/ndjson-reporter.cjs +3 -2
- package/scripts/lib/platform-conformance-tier.generated.cjs +11 -0
- package/scripts/lint-docs-guard-registration.exempt-baseline.cjs +28 -1
- package/scripts/lint-phase-arg-assignment.cjs +257 -0
- package/scripts/lint-phase-id-drift.cjs +290 -5
- package/scripts/lint-pr-branch-pattern-drift.cjs +148 -0
- package/scripts/lint-retired-runtime-name.cjs +619 -0
- package/scripts/lint-state-write-path-drift.cjs +93 -0
- package/scripts/lint-test-file-count.allowlist.json +28 -9
- package/scripts/lint-workflow-shellcheck-baseline.json +15 -0
- package/scripts/prompt-injection-scan.sh +4 -0
- package/scripts/release-tarball-smoke.cjs +194 -1
- package/skills/gsd-autonomous/SKILL.md +2 -2
- package/skills/gsd-capture/SKILL.md +1 -1
- package/skills/gsd-mempalace-capture/SKILL.md +7 -3
- package/skills/gsd-plan-review-convergence/SKILL.md +5 -5
- package/skills/gsd-progress/SKILL.md +1 -1
- package/skills/gsd-quick-batch/SKILL.md +1 -1
- package/skills/gsd-review/SKILL.md +2 -3
- package/vscode/package.json +1 -1
|
@@ -162,6 +162,12 @@ const REASON = Object.freeze({
|
|
|
162
162
|
// Axis 2 (§8.6, retained): a raw `fs.writeFileSync(` call targeting the
|
|
163
163
|
// state path — see `findRawStateWrites`.
|
|
164
164
|
RAW_STATE_WRITE: 'raw_state_write',
|
|
165
|
+
// ADR-4629 §8.1 (epic #4629, C1): a residual `readModifyWriteStateMd(path,
|
|
166
|
+
// (content) => …)` call whose transform is an inline anonymous arrow/function
|
|
167
|
+
// — the opaque shape §8.1 replaces with a declared StateWriteIntent. Recognized
|
|
168
|
+
// by `findOpaqueStateTransforms`; a CAPABILITY in C1 (not wired into collect()),
|
|
169
|
+
// wired terminal in C2 as the residual callers migrate (ADR-3408 §6 phasing).
|
|
170
|
+
OPAQUE_STATE_TRANSFORM: 'opaque_state_transform',
|
|
165
171
|
// Axis 4 (§8.3, Decision 4(d)): prompt-layer prose shelling out to a
|
|
166
172
|
// write-side `gsd-tools` subcommand — see `findPromptSeamUses`.
|
|
167
173
|
PROMPT_LAYER_STATE_WRITE: 'prompt_layer_state_write',
|
|
@@ -645,6 +651,91 @@ function findRawStateWrites(rel, text) {
|
|
|
645
651
|
return out;
|
|
646
652
|
}
|
|
647
653
|
|
|
654
|
+
// ADR-4629 §8.1 (epic #4629, C1) — OPAQUE-TRANSFORM RECOGNITION.
|
|
655
|
+
//
|
|
656
|
+
// A residual `readModifyWriteStateMd(path, (content) => …)` call whose transform
|
|
657
|
+
// (2nd) argument is an inline anonymous arrow / function expression is the opaque
|
|
658
|
+
// shape §8.1 replaces with a declared StateWriteIntent: `readModifyWriteStateMd`
|
|
659
|
+
// goes THROUGH the seam (it is NOT a raw-write bypass — Axis 2's concern), but its
|
|
660
|
+
// opaque body transform is neither verified (§8.2) nor bounded (§8.3). This
|
|
661
|
+
// function RECOGNIZES that shape.
|
|
662
|
+
//
|
|
663
|
+
// C1 ships recognition as a CAPABILITY: it is exported and unit-tested (positive
|
|
664
|
+
// control on a seeded fixture) but is DELIBERATELY NOT wired into `collect()`'s
|
|
665
|
+
// failing scan. §8.1's caller-side rule is *Required — Phase 2*; wiring it now
|
|
666
|
+
// would turn the ~16 residual callers red at once, and ADR-3473 §8.6 retired the
|
|
667
|
+
// ratchet that would otherwise be needed to absorb them. C2 wires this terminal as
|
|
668
|
+
// the verifying executor lands and the callers migrate under ADR-3408 §6 phasing.
|
|
669
|
+
//
|
|
670
|
+
// String match, never an AST — same over-report-safe posture as every axis here.
|
|
671
|
+
const OPAQUE_RMW_CALL_RE = /\breadModifyWriteStateMd\s*\(/g;
|
|
672
|
+
// The transform arg is OPAQUE when it BEGINS an inline anonymous function: an
|
|
673
|
+
// arrow (`(…) =>`, `ident =>`, optionally `async`) or a `function` expression. A
|
|
674
|
+
// bare identifier / object (a declared StateWriteIntent, Phase 2+) is NOT opaque.
|
|
675
|
+
const ANON_TRANSFORM_RE =
|
|
676
|
+
/^\s*(?:async\s+)?(?:\([^)]*\)|[A-Za-z_$][\w$]*)\s*=>|^\s*(?:async\s+)?function\b/;
|
|
677
|
+
|
|
678
|
+
/**
|
|
679
|
+
* Capture the top-level, comma-separated argument list of a call, starting at
|
|
680
|
+
* `startIdx` (the index just AFTER the opening `(`) — across newlines and
|
|
681
|
+
* string-aware, tracking `()[]{}` depth. Returns the raw arg strings, or null if
|
|
682
|
+
* the parens never balance (a truncated arg list is never flagged). Generalizes
|
|
683
|
+
* `captureFirstArg`'s depth/inStr bookkeeping to every argument.
|
|
684
|
+
*/
|
|
685
|
+
function captureCallArgList(text, startIdx) {
|
|
686
|
+
let depth = 0;
|
|
687
|
+
let inStr = null;
|
|
688
|
+
const args = [];
|
|
689
|
+
let cur = '';
|
|
690
|
+
for (let i = startIdx; i < text.length; i++) {
|
|
691
|
+
const ch = text[i];
|
|
692
|
+
if (inStr) {
|
|
693
|
+
cur += ch;
|
|
694
|
+
if (ch === inStr && text[i - 1] !== '\\') inStr = null;
|
|
695
|
+
continue;
|
|
696
|
+
}
|
|
697
|
+
if (ch === '"' || ch === "'" || ch === '`') { inStr = ch; cur += ch; continue; }
|
|
698
|
+
if (ch === '(' || ch === '[' || ch === '{') { depth++; cur += ch; continue; }
|
|
699
|
+
if (ch === ')' || ch === ']' || ch === '}') {
|
|
700
|
+
if (ch === ')' && depth === 0) {
|
|
701
|
+
if (cur.trim() !== '' || args.length) args.push(cur);
|
|
702
|
+
return args;
|
|
703
|
+
}
|
|
704
|
+
depth--; cur += ch; continue;
|
|
705
|
+
}
|
|
706
|
+
if (ch === ',' && depth === 0) { args.push(cur); cur = ''; continue; }
|
|
707
|
+
cur += ch;
|
|
708
|
+
}
|
|
709
|
+
return null; // parens never balanced
|
|
710
|
+
}
|
|
711
|
+
|
|
712
|
+
/**
|
|
713
|
+
* Recognize residual opaque-transform STATE.md writes (ADR-4629 §8.1). Returns a
|
|
714
|
+
* finding per `readModifyWriteStateMd(` call whose 2nd argument is an inline
|
|
715
|
+
* anonymous transform. CAPABILITY only in C1 — not called by `collect()`.
|
|
716
|
+
*/
|
|
717
|
+
function findOpaqueStateTransforms(rel, text) {
|
|
718
|
+
const rawLines = text.split('\n');
|
|
719
|
+
const stripped = stripComments(text).join('\n');
|
|
720
|
+
const out = [];
|
|
721
|
+
let m;
|
|
722
|
+
OPAQUE_RMW_CALL_RE.lastIndex = 0;
|
|
723
|
+
while ((m = OPAQUE_RMW_CALL_RE.exec(stripped)) !== null) {
|
|
724
|
+
const args = captureCallArgList(stripped, m.index + m[0].length);
|
|
725
|
+
if (!args || args.length < 2) continue;
|
|
726
|
+
if (!ANON_TRANSFORM_RE.test(args[1])) continue;
|
|
727
|
+
const lineNo = stripped.slice(0, m.index).split('\n').length;
|
|
728
|
+
out.push({
|
|
729
|
+
reason: REASON.OPAQUE_STATE_TRANSFORM,
|
|
730
|
+
axis: 'opaque-transform',
|
|
731
|
+
file: sanitizeForReport(rel),
|
|
732
|
+
line: lineNo,
|
|
733
|
+
source: sanitizeForReport((rawLines[lineNo - 1] || '').trim()),
|
|
734
|
+
});
|
|
735
|
+
}
|
|
736
|
+
return out;
|
|
737
|
+
}
|
|
738
|
+
|
|
648
739
|
// The two write-seam STAGE functions, matched only as CALLS (`\(`
|
|
649
740
|
// immediately after, modulo whitespace) — never as bare mentions of the
|
|
650
741
|
// name. `writeStateMd(` is deliberately NOT included here (that arm is
|
|
@@ -941,6 +1032,8 @@ module.exports = {
|
|
|
941
1032
|
nearestPrecedingAssignment,
|
|
942
1033
|
findRawStateWrites,
|
|
943
1034
|
targetsStatePath,
|
|
1035
|
+
findOpaqueStateTransforms,
|
|
1036
|
+
captureCallArgList,
|
|
944
1037
|
findCompositionBypasses,
|
|
945
1038
|
findPromptSeamUses,
|
|
946
1039
|
isInsideCodeSpan,
|
|
@@ -1,6 +1,15 @@
|
|
|
1
1
|
{
|
|
2
|
-
"_doc": "Baseline of modules currently exceeding the 2-test-file limit. Each entry locks in TODAY's exact test filenames as the allowlisted set (identity ratchet). Adding a NEW test file to a capped module fails (novel). Removing one requires pruning this list (stale, ratchet-down). When a cluster drops to
|
|
2
|
+
"_doc": "Baseline of modules currently exceeding the 2-test-file limit. Each entry locks in TODAY's exact test filenames as the allowlisted set (identity ratchet). Adding a NEW test file to a capped module fails (novel). Removing one requires pruning this list (stale, ratchet-down). When a cluster drops to ≤ 2, remove its entry entirely. New entries require justification in PR description.",
|
|
3
3
|
"modules": {
|
|
4
|
+
"ui-consideration-probe": {
|
|
5
|
+
"files": [
|
|
6
|
+
"ui-consideration-probe-docs-fixtures.test.cjs",
|
|
7
|
+
"ui-consideration-probe-ui-phase-contract.test.cjs",
|
|
8
|
+
"ui-consideration-probe.test.cjs"
|
|
9
|
+
],
|
|
10
|
+
"issue": "4657",
|
|
11
|
+
"justification": "The ui-consideration-probe cluster gains its workflow-prose contract file (tests/ui-consideration-probe-ui-phase-contract.test.cjs, #4657), mirroring the edge probe's split (edge-probe.test.cjs / edge-probe-docs-fixtures.test.cjs / edge-probe-spec-phase-contract.test.cjs). The contract file reads shipped gsd-core/workflows/ui-phase.md under the source-text-is-the-product exception, which the unit file deliberately does not carry (it asserts typed returns only)."
|
|
12
|
+
},
|
|
4
13
|
"adr-parser": {
|
|
5
14
|
"files": [
|
|
6
15
|
"adr-parser.property.test.cjs",
|
|
@@ -40,7 +49,7 @@
|
|
|
40
49
|
"frontmatter.unit.test.cjs"
|
|
41
50
|
],
|
|
42
51
|
"issue": "3881",
|
|
43
|
-
"justification": "Grandfathered by #3227 for the original 4-file cluster (pre-existing over-cap, not new sprawl). #3881 (ADR-3473
|
|
52
|
+
"justification": "Grandfathered by #3227 for the original 4-file cluster (pre-existing over-cap, not new sprawl). #3881 (ADR-3473 §8.1, the js-yaml parser migration) adds two more: frontmatter-golden-parity.test.cjs (D-series golden-corpus diff against the legacy parser, ~900 real documents — cannot be folded into an existing file without losing its independent-of-current-parser provenance) and frontmatter-roundtrip.property.test.cjs (fast-check property coverage the migration's bijective-contract rule requires). Both are migration-specific, not incidental sprawl."
|
|
44
53
|
},
|
|
45
54
|
"graphify": {
|
|
46
55
|
"files": [
|
|
@@ -137,10 +146,11 @@
|
|
|
137
146
|
"verify-npm-publish.test.cjs",
|
|
138
147
|
"verify-test-quality.test.cjs",
|
|
139
148
|
"verify-work-auto-transition.test.cjs",
|
|
149
|
+
"verify-work-deferred-promotion.test.cjs",
|
|
140
150
|
"verify.test.cjs"
|
|
141
151
|
],
|
|
142
|
-
"issue": "#3813
|
|
143
|
-
"justification": "verify-command-grounding added by #2401/#3678; allowlist follow-up landed with #3606 (base was red on this lane)."
|
|
152
|
+
"issue": "#3813 — the live-path #1883 suite drives buildPlanningSnapshot in-process with an fs fault; the verify module suites are CLI-driving and cannot host an fs monkeypatch",
|
|
153
|
+
"justification": "verify-command-grounding added by #2401/#3678; allowlist follow-up landed with #3606 (base was red on this lane). #4546 adds verify-work-deferred-promotion (deferred-follow-up promotion writer contract + parity)."
|
|
144
154
|
},
|
|
145
155
|
"install": {
|
|
146
156
|
"files": [
|
|
@@ -154,7 +164,7 @@
|
|
|
154
164
|
"install-write-confinement.test.cjs",
|
|
155
165
|
"install.test.cjs"
|
|
156
166
|
],
|
|
157
|
-
"issue": "#3798
|
|
167
|
+
"issue": "#3798 — the profile-closure spawn test reads the real repo surface (commands+workflows+agents); consolidating it into install.test.cjs would put a whole-repo scan behind the suite's heaviest file"
|
|
158
168
|
},
|
|
159
169
|
"edge-probe": {
|
|
160
170
|
"files": [
|
|
@@ -252,8 +262,8 @@
|
|
|
252
262
|
"docs-state-md-locale-parity.test.cjs",
|
|
253
263
|
"docs-update.test.cjs"
|
|
254
264
|
],
|
|
255
|
-
"issue": "3873 | #3839
|
|
256
|
-
"justification": "ADR-3473
|
|
265
|
+
"issue": "3873 | #3839 — the hook-event parity suite cross-checks the four docs hook tables against src/runtime-hooks-surface.cts registrations; a generated-docs concern distinct from content freshness and registry parity",
|
|
266
|
+
"justification": "ADR-3473 §8.8 makes docs/reference/state-md.md and its four locale siblings generated-and-committed and adds the repo's first locale-parity check (verified: no locale-parity lint precedent exists here). That check is a distinct concern from docs-update (content freshness) and docs-parity-live-registry (registry parity); folding it into either would place an unrelated subject inside them purely to satisfy a count. The section it guards is absent from all four translations today and documents the status enum behind #3853."
|
|
257
267
|
},
|
|
258
268
|
"audit": {
|
|
259
269
|
"files": [
|
|
@@ -265,7 +275,7 @@
|
|
|
265
275
|
"audit-uat-summary-segmentation.test.cjs",
|
|
266
276
|
"audit-workstream-layouts.test.cjs"
|
|
267
277
|
],
|
|
268
|
-
"issue": "#3804/#3805
|
|
278
|
+
"issue": "#3804/#3805 — audit-layout and acknowledged-marker suites drive the real audit-uat CLI against on-disk fixtures | #3817 — regression suite proving countReal counts the truncation remainder marker instead of treating it as one phantom item | #3783 — dedicated suite for the summary.current_milestone/archived segmentation, matching this module's one-file-per-feature-slice precedent (e.g. audit-uat-acknowledged.test.cjs) rather than growing the unrelated 6900+ line tests/uat.test.cjs (a different module, keyed off uat.cjs)"
|
|
269
279
|
},
|
|
270
280
|
"shell-command-projection": {
|
|
271
281
|
"files": [
|
|
@@ -273,7 +283,16 @@
|
|
|
273
283
|
"shell-command-projection-md-normalize.test.cjs",
|
|
274
284
|
"shell-command-projection-path-sep.test.cjs"
|
|
275
285
|
],
|
|
276
|
-
"issue": "#3854
|
|
286
|
+
"issue": "#3854 — the tight-list suite pins the markdown write-normalizer's blank-line policy through the exported normalizeContent/platformWriteSync seam; a distinct concern from dispatch routing and path separation"
|
|
287
|
+
},
|
|
288
|
+
"ui-consideration-probe": {
|
|
289
|
+
"files": [
|
|
290
|
+
"ui-consideration-probe-docs-fixtures.test.cjs",
|
|
291
|
+
"ui-consideration-probe-ui-phase-contract.test.cjs",
|
|
292
|
+
"ui-consideration-probe.test.cjs"
|
|
293
|
+
],
|
|
294
|
+
"issue": "4657",
|
|
295
|
+
"justification": "The ui-consideration-probe cluster gains its workflow-prose contract file (tests/ui-consideration-probe-ui-phase-contract.test.cjs, #4657), mirroring the edge probe's split (edge-probe.test.cjs / edge-probe-docs-fixtures.test.cjs / edge-probe-spec-phase-contract.test.cjs). The contract file reads shipped gsd-core/workflows/ui-phase.md under the source-text-is-the-product exception, which the unit file deliberately does not carry (it asserts typed returns only)."
|
|
277
296
|
}
|
|
278
297
|
}
|
|
279
298
|
}
|
|
@@ -1108,5 +1108,20 @@
|
|
|
1108
1108
|
"file": "gsd-core/workflows/verify-work/steps/mvp-uat-framing.md",
|
|
1109
1109
|
"code": "2086",
|
|
1110
1110
|
"message": "Double quote to prevent globbing and word splitting."
|
|
1111
|
+
},
|
|
1112
|
+
{
|
|
1113
|
+
"file": "gsd-core/workflows/execute-phase/steps/code-review-disposition.md",
|
|
1114
|
+
"code": "2317",
|
|
1115
|
+
"message": "Command appears to be unreachable. Check usage (or ignore if invoked indirectly)."
|
|
1116
|
+
},
|
|
1117
|
+
{
|
|
1118
|
+
"file": "gsd-core/workflows/execute-phase/steps/code-review-disposition.md",
|
|
1119
|
+
"code": "2317",
|
|
1120
|
+
"message": "Command appears to be unreachable. Check usage (or ignore if invoked indirectly)."
|
|
1121
|
+
},
|
|
1122
|
+
{
|
|
1123
|
+
"file": "gsd-core/workflows/execute-phase/steps/code-review-disposition.md",
|
|
1124
|
+
"code": "2317",
|
|
1125
|
+
"message": "Command appears to be unreachable. Check usage (or ignore if invoked indirectly)."
|
|
1111
1126
|
}
|
|
1112
1127
|
]
|
|
@@ -171,6 +171,10 @@ ALLOWLIST=(
|
|
|
171
171
|
# allowlist cannot reach it either, because the literal `child_process` is
|
|
172
172
|
# not adjacent to `.exec`. See the note at the pattern itself.
|
|
173
173
|
'tests/continuation-grammar-parity.test.cjs'
|
|
174
|
+
# #4906 Phase 5 — regex.exec('### Phase 03: ...') fixtures.
|
|
175
|
+
# Same DEFECT.PROMPT-INJECTION-SCAN-COLLISION class as above:
|
|
176
|
+
# RegExp.prototype.exec, not code execution.
|
|
177
|
+
'tests/phase-id.test.cjs'
|
|
174
178
|
# #3676 row 11b — quick-batch's task-list parser must treat a
|
|
175
179
|
# prompt-injection-shaped task description as inert data, never
|
|
176
180
|
# interpreted. The fixture has to be a real "ignore all previous
|
|
@@ -37,6 +37,12 @@
|
|
|
37
37
|
* colon-namespace leaks (WORKFLOW_BODY_COLON_LEAK).
|
|
38
38
|
* This check populates result.details with counters but does NOT return a
|
|
39
39
|
* failure code by default; it is informational until enforcement is enabled.
|
|
40
|
+
*
|
|
41
|
+
* Configured-entrypoint checks (Cycle 4 — #4154):
|
|
42
|
+
* For each runtime in entrypointRuntimes, runs the tarball-installed
|
|
43
|
+
* installer into a throwaway HOME, then re-reads that runtime's own written
|
|
44
|
+
* config files and asserts every GSD-managed script path they name resolves
|
|
45
|
+
* to a file (ENTRYPOINT_UNRESOLVED). Requires fixtureDir.
|
|
40
46
|
*/
|
|
41
47
|
|
|
42
48
|
'use strict';
|
|
@@ -47,6 +53,8 @@ const os = require('os');
|
|
|
47
53
|
const path = require('path');
|
|
48
54
|
const { PACKAGE_NAME } = require('../gsd-core/bin/lib/package-identity.cjs');
|
|
49
55
|
const { ExitError, runMain } = require('./lib/cli-exit.cjs');
|
|
56
|
+
const shellCmdProjection = require('../gsd-core/bin/lib/shell-command-projection.cjs');
|
|
57
|
+
const { escapeRegex } = require('../gsd-core/bin/lib/pattern.cjs');
|
|
50
58
|
// 120 s proved too tight for cold-cache `npm install -g` of a 1499-file tarball:
|
|
51
59
|
// spawnSync fires SIGTERM at the deadline and returns { status: null, stdout: '',
|
|
52
60
|
// stderr: '' } (Node docs: status is null when a subprocess is terminated by a
|
|
@@ -86,6 +94,8 @@ const SMOKE = Object.freeze({
|
|
|
86
94
|
INIT_FAILED: 'init_failed',
|
|
87
95
|
// Cycle 3 code
|
|
88
96
|
WORKFLOW_BODY_COLON_LEAK: 'workflow_body_colon_leak',
|
|
97
|
+
// Cycle 4 code (#4154)
|
|
98
|
+
ENTRYPOINT_UNRESOLVED: 'entrypoint_unresolved',
|
|
89
99
|
});
|
|
90
100
|
|
|
91
101
|
// ---------------------------------------------------------------------------
|
|
@@ -274,6 +284,106 @@ function scanWorkflowColonLeak(filePath, cmdNames) {
|
|
|
274
284
|
return null;
|
|
275
285
|
}
|
|
276
286
|
|
|
287
|
+
// ---------------------------------------------------------------------------
|
|
288
|
+
// Cycle 4 helpers: configured-entrypoint resolution (#4154)
|
|
289
|
+
// ---------------------------------------------------------------------------
|
|
290
|
+
|
|
291
|
+
/**
|
|
292
|
+
* Top-level config files this scan reads. These are the surfaces that carry
|
|
293
|
+
* every GSD-managed launch path for the runtimes Cycle 4 actually installs
|
|
294
|
+
* (`entrypointRuntimes`, default claude + codex): claude registers into
|
|
295
|
+
* settings.json, codex into hooks.json and config.toml.
|
|
296
|
+
*
|
|
297
|
+
* This is NOT an exhaustive map of where GSD writes launch paths across all
|
|
298
|
+
* runtimes, and the scan is top-level only by design. Two known surfaces sit
|
|
299
|
+
* outside it: Cline registers its hook at `.clinerules/hooks/PreToolUse` (a
|
|
300
|
+
* subdirectory, and not one of these names — see writeClineArtifacts in
|
|
301
|
+
* src/runtime-hooks-surface.cts), and Kimi's native `[[hooks]]` config.toml
|
|
302
|
+
* lives under `resolveKimiHooksTomlDir()` (`~/.kimi`), a directory separate
|
|
303
|
+
* from Kimi's own GSD configDir. Adding either runtime to entrypointRuntimes
|
|
304
|
+
* requires teaching scanConfiguredEntrypoints about its surface first,
|
|
305
|
+
* otherwise the scan reports zero entrypoints and silently proves nothing.
|
|
306
|
+
*/
|
|
307
|
+
const RUNTIME_CONFIG_FILES = Object.freeze(['settings.json', 'hooks.json', 'config.toml']);
|
|
308
|
+
|
|
309
|
+
/**
|
|
310
|
+
* Extract every script path `text` names underneath `configDir`.
|
|
311
|
+
*
|
|
312
|
+
* #4249 (antigravity review): anchored on the literal, already-known
|
|
313
|
+
* `configDir` prefix instead of a generic "any absolute path" character
|
|
314
|
+
* class. The prior version excluded whitespace from the match to avoid
|
|
315
|
+
* swallowing a shell command's trailing args, which also truncated any
|
|
316
|
+
* legitimate path containing a space (e.g. `/Users/John Doe/.claude`) —
|
|
317
|
+
* `scanConfiguredEntrypoints` would then silently report zero checked
|
|
318
|
+
* paths. Anchoring on `configDir` removes the ambiguity outright: a match
|
|
319
|
+
* can only start where the known prefix literally occurs in the text, so
|
|
320
|
+
* an interpreter path concatenated ahead of it (`"/usr/bin/node
|
|
321
|
+
* /configDir/hooks/foo.js"`) is never swallowed either, and interior
|
|
322
|
+
* whitespace inside `configDir` or the script's own path segments is safe
|
|
323
|
+
* to allow. This still scans raw, unparsed config text on purpose (see
|
|
324
|
+
* scanConfiguredEntrypoints's doc comment) — it catches a writer that
|
|
325
|
+
* embeds a launch path without registering it, which a structured
|
|
326
|
+
* JSON.parse of the expected schema would miss entirely.
|
|
327
|
+
*
|
|
328
|
+
* Windows configs store paths with backslashes, which JSON/TOML doubles on
|
|
329
|
+
* write; collapsing `\\` to `\` first makes the raw text scan work on both
|
|
330
|
+
* platforms without parsing each config format separately (POSIX text has no
|
|
331
|
+
* backslashes, so the collapse is a no-op there).
|
|
332
|
+
*
|
|
333
|
+
* Every writer bakes `configDir` through the same posixNormalize seam
|
|
334
|
+
* (src/runtime-hooks-surface.cts) before writing it into config text, on
|
|
335
|
+
* every platform — so the anchor must match that projection, not the
|
|
336
|
+
* OS-native `configDir` string this function receives.
|
|
337
|
+
*/
|
|
338
|
+
function configuredEntrypointsIn(text, configDir) {
|
|
339
|
+
const normalizedPrefix = shellCmdProjection.posixNormalize(configDir).replace(/\/+$/, '') + '/';
|
|
340
|
+
const scriptPathRe = new RegExp(`${escapeRegex(normalizedPrefix)}[^"']{0,400}?\\.(?:js|cjs|mjs|sh|cmd|ps1)`, 'g');
|
|
341
|
+
const found = new Set();
|
|
342
|
+
for (const match of text.replace(/\\\\/g, '\\').matchAll(scriptPathRe)) {
|
|
343
|
+
found.add(path.resolve(match[0]));
|
|
344
|
+
}
|
|
345
|
+
return [...found];
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
/**
|
|
349
|
+
* Throwaway HOME the Cycle 4 install for `runtime` runs against. Exported so a
|
|
350
|
+
* test can seed that runtime's config before the install rather than
|
|
351
|
+
* hard-coding the layout runSmoke picks.
|
|
352
|
+
*/
|
|
353
|
+
function entrypointFixtureHome(fixtureDir, runtime) {
|
|
354
|
+
return path.join(fixtureDir, `entrypoints-${runtime}`);
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
/**
|
|
358
|
+
* Re-derive the configured entrypoints a completed install wrote into a
|
|
359
|
+
* runtime's own config files and report the ones that do not resolve to a
|
|
360
|
+
* file. Internal to Cycle 4; the smoke's verdict is the exported contract.
|
|
361
|
+
*
|
|
362
|
+
* This deliberately does NOT consult the installer's own entrypoint list (the
|
|
363
|
+
* assertConfiguredEntrypoints gate in bin/install.js). That gate can only
|
|
364
|
+
* validate paths a config writer remembered to register; reading the written
|
|
365
|
+
* config back is what catches a writer that emits a launch path without
|
|
366
|
+
* registering it, and a stale registration an install left behind.
|
|
367
|
+
*
|
|
368
|
+
* @param {string} configDir - Absolute path to the runtime config dir.
|
|
369
|
+
* @returns {{ checked: string[], unresolved: { configPath: string, scriptPath: string }[] }}
|
|
370
|
+
*/
|
|
371
|
+
function scanConfiguredEntrypoints(configDir) {
|
|
372
|
+
const checked = [];
|
|
373
|
+
const unresolved = [];
|
|
374
|
+
for (const name of RUNTIME_CONFIG_FILES) {
|
|
375
|
+
const configPath = path.join(configDir, name);
|
|
376
|
+
if (!fs.existsSync(configPath) || !fs.statSync(configPath).isFile()) continue;
|
|
377
|
+
const text = fs.readFileSync(configPath, 'utf-8');
|
|
378
|
+
for (const scriptPath of configuredEntrypointsIn(text, configDir)) {
|
|
379
|
+
checked.push(scriptPath);
|
|
380
|
+
if (fs.existsSync(scriptPath) && fs.statSync(scriptPath).isFile()) continue;
|
|
381
|
+
unresolved.push({ configPath, scriptPath });
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
return { checked, unresolved };
|
|
385
|
+
}
|
|
386
|
+
|
|
277
387
|
// ---------------------------------------------------------------------------
|
|
278
388
|
// Pure function: runSmoke
|
|
279
389
|
// ---------------------------------------------------------------------------
|
|
@@ -285,6 +395,8 @@ function scanWorkflowColonLeak(filePath, cmdNames) {
|
|
|
285
395
|
* @param {string} opts.expectedVersion - semver string to assert (e.g. "1.50.0")
|
|
286
396
|
* @param {string} [opts.fixtureDir] - Temp dir to run `init` into (must NOT be HOME)
|
|
287
397
|
* @param {string[]} [opts.lifecycleCommands] - Commands to file-check (default: see below)
|
|
398
|
+
* @param {string[]} [opts.entrypointRuntimes] - Runtime profiles whose configured entrypoints are
|
|
399
|
+
* re-checked after a real install (default: see below). Requires fixtureDir; pass [] to skip.
|
|
288
400
|
* @param {boolean} [opts.dryRun=false] - If true, skip actual npm install; validate input only
|
|
289
401
|
* @param {object} [opts.npmEnv] - Optional env dict for the internal npm install
|
|
290
402
|
* spawnSync call. Pass an isolated HOME env (e.g. from isolatedNpmEnv() in tests/helpers.cjs)
|
|
@@ -298,6 +410,11 @@ function runSmoke({
|
|
|
298
410
|
expectedVersion,
|
|
299
411
|
fixtureDir,
|
|
300
412
|
lifecycleCommands = ['init', 'discuss-phase', 'plan-phase', 'execute-phase'],
|
|
413
|
+
// claude and codex cover the two top-level config surfaces this scan knows
|
|
414
|
+
// how to read (settings.json, and hooks.json + config.toml). Most other
|
|
415
|
+
// runtimes reuse one of those two shapes; Cline and Kimi do not (see
|
|
416
|
+
// RUNTIME_CONFIG_FILES), so they are out of scope here rather than covered.
|
|
417
|
+
entrypointRuntimes = ['claude', 'codex'],
|
|
301
418
|
dryRun = false,
|
|
302
419
|
npmEnv = undefined,
|
|
303
420
|
}) {
|
|
@@ -551,6 +668,75 @@ function runSmoke({
|
|
|
551
668
|
// NOTE: colonLeakCount is informational here. Once the backlog is fixed,
|
|
552
669
|
// a future enforcement mode can fail on non-zero counts.
|
|
553
670
|
|
|
671
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
672
|
+
// Cycle 4: configured-entrypoint resolution (#4154)
|
|
673
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
674
|
+
|
|
675
|
+
// The installer's own gate (assertConfiguredEntrypoints) runs in-process and
|
|
676
|
+
// only sees the paths a config writer registered with it. Installing the
|
|
677
|
+
// packed tarball for real and reading each runtime's written config back is
|
|
678
|
+
// what proves the launch paths a user's runtime will actually invoke exist
|
|
679
|
+
// in the shipped layout.
|
|
680
|
+
const entrypointProfiles = [];
|
|
681
|
+
if (fixtureDir && entrypointRuntimes.length > 0) {
|
|
682
|
+
for (const runtime of entrypointRuntimes) {
|
|
683
|
+
// Own HOME per runtime so a --global install cannot reach the real one.
|
|
684
|
+
const runtimeHome = entrypointFixtureHome(fixtureDir, runtime);
|
|
685
|
+
const configDir = path.join(runtimeHome, `.${runtime}`);
|
|
686
|
+
fs.mkdirSync(runtimeHome, { recursive: true });
|
|
687
|
+
|
|
688
|
+
const installResult = spawnSync(
|
|
689
|
+
process.execPath,
|
|
690
|
+
[path.join(pkg, 'bin', 'install.js'), `--${runtime}`, '--global', '--config-dir', configDir],
|
|
691
|
+
{
|
|
692
|
+
encoding: 'utf-8',
|
|
693
|
+
cwd: runtimeHome,
|
|
694
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
695
|
+
env: {
|
|
696
|
+
...effectiveNpmEnv,
|
|
697
|
+
HOME: runtimeHome,
|
|
698
|
+
USERPROFILE: runtimeHome,
|
|
699
|
+
// Same reason as the init check above: install.js skips its main()
|
|
700
|
+
// block when GSD_TEST_MODE is set and would exit 0 writing nothing.
|
|
701
|
+
GSD_TEST_MODE: '',
|
|
702
|
+
NO_UPDATE_NOTIFIER: '1',
|
|
703
|
+
},
|
|
704
|
+
timeout: CHILD_TIMEOUT_MS,
|
|
705
|
+
},
|
|
706
|
+
);
|
|
707
|
+
|
|
708
|
+
if (installResult.status !== 0) {
|
|
709
|
+
// #4249 (antigravity review): this is the Cycle 4 per-runtime install,
|
|
710
|
+
// not Cycle 1's `gsd init` — SMOKE.INSTALL_FAILED is the code Cycle 2's
|
|
711
|
+
// identical spawnSync-failure check already uses for the same failure
|
|
712
|
+
// class; reusing SMOKE.INIT_FAILED here conflated the two lifecycle
|
|
713
|
+
// stages in the reported code.
|
|
714
|
+
return {
|
|
715
|
+
code: SMOKE.INSTALL_FAILED,
|
|
716
|
+
details: {
|
|
717
|
+
...details,
|
|
718
|
+
runtime,
|
|
719
|
+
configDir,
|
|
720
|
+
stderr: installResult.stderr,
|
|
721
|
+
stdout: installResult.stdout,
|
|
722
|
+
},
|
|
723
|
+
};
|
|
724
|
+
}
|
|
725
|
+
|
|
726
|
+
const scan = scanConfiguredEntrypoints(configDir);
|
|
727
|
+
if (scan.unresolved.length > 0) {
|
|
728
|
+
return {
|
|
729
|
+
code: SMOKE.ENTRYPOINT_UNRESOLVED,
|
|
730
|
+
details: { ...details, runtime, configDir, unresolved: scan.unresolved },
|
|
731
|
+
};
|
|
732
|
+
}
|
|
733
|
+
|
|
734
|
+
entrypointProfiles.push({ runtime, configDir, entrypointsChecked: scan.checked.length });
|
|
735
|
+
}
|
|
736
|
+
}
|
|
737
|
+
|
|
738
|
+
details.entrypointProfiles = entrypointProfiles;
|
|
739
|
+
|
|
554
740
|
return { code: SMOKE.OK, details };
|
|
555
741
|
}
|
|
556
742
|
|
|
@@ -635,7 +821,14 @@ function cleanup(...dirs) {
|
|
|
635
821
|
// Exports
|
|
636
822
|
// ---------------------------------------------------------------------------
|
|
637
823
|
|
|
638
|
-
module.exports = {
|
|
824
|
+
module.exports = {
|
|
825
|
+
SMOKE,
|
|
826
|
+
runSmoke,
|
|
827
|
+
binInvocation,
|
|
828
|
+
entrypointFixtureHome,
|
|
829
|
+
CHILD_TIMEOUT_MS,
|
|
830
|
+
configuredEntrypointsIn,
|
|
831
|
+
};
|
|
639
832
|
|
|
640
833
|
if (require.main === module) {
|
|
641
834
|
runMain(cliMain);
|
|
@@ -36,10 +36,10 @@ Optional flags:
|
|
|
36
36
|
- `--to N` — stop after phase N completes (halt instead of advancing to next phase).
|
|
37
37
|
- `--only N` — execute only phase N (single-phase mode).
|
|
38
38
|
- `--interactive` — run discuss inline with questions (not auto-answered), then dispatch plan→execute as background agents. Keeps the main context lean while preserving user input on decisions.
|
|
39
|
-
- `--converge` — run each phase's planning step through `gsd-plan-review-convergence` instead of plain `gsd-plan-phase`.
|
|
39
|
+
- `--converge` — run each phase's planning step through `gsd-plan-review-convergence` instead of plain `gsd-plan-phase`. Works even when `workflow.plan_review_convergence` is `false` — the explicit flag overrides the gate; the gate (`workflow.plan_review_convergence=true` enables it) governs the standalone `gsd-plan-review-convergence` command. Without the flag, planning runs `gsd-plan-phase`.
|
|
40
40
|
- `--cross-ai` — compatibility alias for `--converge`.
|
|
41
41
|
|
|
42
|
-
When `--converge` or `--cross-ai` is set, reviewer selector flags supported by `gsd-plan-review-convergence` may be passed through: `--codex`, `--
|
|
42
|
+
When `--converge` or `--cross-ai` is set, reviewer selector flags supported by `gsd-plan-review-convergence` may be passed through: `--codex`, `--claude`, `--opencode`, `--ollama`, `--lm-studio`, `--llama-cpp`, `--all`, and `--max-cycles N`.
|
|
43
43
|
|
|
44
44
|
Project context, phase list, and state are resolved inside the workflow using init commands (`gsd-tools query init.milestone-op`, `gsd-tools query roadmap.analyze`). No upfront context loading needed.
|
|
45
45
|
</context>
|
|
@@ -32,7 +32,7 @@ Mode routing:
|
|
|
32
32
|
| (none) | Structured todo in .planning/todos/ | add-todo |
|
|
33
33
|
| --note | Timestamped note file, list, or promote | note |
|
|
34
34
|
| --backlog | ROADMAP.md backlog section (999.x) | add-backlog |
|
|
35
|
-
| --seed | .planning/seeds/SEED-
|
|
35
|
+
| --seed | .planning/seeds/SEED-YYMMDD-xxx-slug.md | plant-seed |
|
|
36
36
|
| --list | Interactive todo browser + action router | check-todos |
|
|
37
37
|
| --list-seeds | Read-only seed list/audit (optional status filter) | list-seeds |
|
|
38
38
|
|
|
@@ -84,15 +84,19 @@ On any error or timeout, stop and let the phase continue -- capture is best-effo
|
|
|
84
84
|
ROOM_DIR="$STAGE/<room>/<phase-id>"
|
|
85
85
|
mkdir -p "$ROOM_DIR"
|
|
86
86
|
cp "<artifact-path>" "$ROOM_DIR/<basename>"
|
|
87
|
-
# Mine with --wing only — no --room flag; detect_room() assigns from the folder path
|
|
88
|
-
|
|
87
|
+
# Mine with --wing only — no --room flag; detect_room() assigns from the folder path.
|
|
88
|
+
# --daemon --background (#4700): MemPalace wraps every mine in a per-palace
|
|
89
|
+
# lock; a concurrent writer would make a foreground mine exit 1
|
|
90
|
+
# (MineAlreadyRunning) and this onError: skip step would silently drop the
|
|
91
|
+
# capture. The background queue defers the job until the lock frees.
|
|
92
|
+
mempalace mine "$STAGE" --wing <wing> --daemon --background
|
|
89
93
|
```
|
|
90
94
|
3. **Mirror KG facts** unless `config.mempalace.mirror_kg === false` (registry default is true — an absent key means enabled): 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.
|
|
91
95
|
4. Re-running a phase MUST NOT create duplicate drawers (deterministic ids + `check_duplicate`).
|
|
92
96
|
|
|
93
97
|
## Step 4 -- Report
|
|
94
98
|
|
|
95
|
-
Print a one-line summary: `Filed <artifact> → <wing>/<room> (<n> KG facts)` or `MemPalace
|
|
99
|
+
Print a one-line summary: `Filed <artifact> → <wing>/<room> (<n> KG facts)`, `Capture queued — palace busy; MemPalace will file it when the lock frees` (the background mine was deferred behind another writer), or `MemPalace capture skipped — <reason>` (#4700: a skipped capture is never silent).
|
|
96
100
|
|
|
97
101
|
## Anti-Patterns
|
|
98
102
|
|
|
@@ -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> [--
|
|
4
|
+
argument-hint: "<phase> [--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
|
|
@@ -20,7 +20,7 @@ Repeatedly: review plans with external AI CLIs → if HIGH or actionable non-HIG
|
|
|
20
20
|
|
|
21
21
|
**Flow:** Skill("gsd-plan-phase") → Agent→Skill("gsd-review") → check unresolved HIGH + actionable non-HIGH → Skill("gsd-plan-phase --reviews") → Agent→Skill("gsd-review") → ... → Converge or escalate
|
|
22
22
|
|
|
23
|
-
Replaces gsd-plan-phase's internal gsd-plan-checker with external AI reviewers (codex,
|
|
23
|
+
Replaces gsd-plan-phase's internal gsd-plan-checker with external AI reviewers (codex, claude, etc.). Plan-phase runs **inline** (bare Skill at depth 0) so it can spawn gsd-planner/gsd-plan-checker at depth 1. Review runs inside an isolated Agent (gsd-review is a Bash leaf — no sub-agents needed). Orchestrator only does loop control.
|
|
24
24
|
|
|
25
25
|
**Orchestrator role:** Parse arguments, validate phase, run plan-phase inline (Skill at depth 0), spawn an Agent for gsd-review, check unresolved HIGH and actionable non-HIGH counts, stall detection, escalation gate.
|
|
26
26
|
</objective>
|
|
@@ -41,8 +41,7 @@ Phase number: extracted from $ARGUMENTS (required)
|
|
|
41
41
|
|
|
42
42
|
**Flags:**
|
|
43
43
|
- `--codex` — Use Codex CLI as reviewer (default if no reviewer flag given AND `review.default_reviewers` is unset; otherwise `review.default_reviewers` wins per ADR-0011 — #2315)
|
|
44
|
-
- `--
|
|
45
|
-
- `--agy` / `--antigravity` — Use Antigravity CLI as reviewer (successor to the discontinued Gemini CLI)
|
|
44
|
+
- `--agy` / `--antigravity` — Use Antigravity CLI as reviewer
|
|
46
45
|
- `--claude` — Use Claude CLI as reviewer (separate session)
|
|
47
46
|
- `--coderabbit` — Use CodeRabbit as reviewer (reviews the working-tree diff, not the source tree)
|
|
48
47
|
- `--opencode` — Use OpenCode as reviewer
|
|
@@ -56,7 +55,8 @@ Phase number: extracted from $ARGUMENTS (required)
|
|
|
56
55
|
- `--max-cycles N` — Maximum replan→review cycles (default: 3)
|
|
57
56
|
|
|
58
57
|
**Feature gate:** This command requires `workflow.plan_review_convergence=true`. Enable with:
|
|
59
|
-
`gsd config-set workflow.plan_review_convergence true`
|
|
58
|
+
`gsd config-set workflow.plan_review_convergence true`. A dispatch carrying `--override-gate` —
|
|
59
|
+
how `/gsd-autonomous --converge` invokes this workflow (#4600) — bypasses the gate for that run.
|
|
60
60
|
</context>
|
|
61
61
|
|
|
62
62
|
<process>
|
|
@@ -24,7 +24,7 @@ Three modes:
|
|
|
24
24
|
<flags>
|
|
25
25
|
- **--next**: Detect current project state and automatically invoke the next logical GSD workflow step. Scans all prior phases for incomplete work before routing. `--next --force` bypasses safety gates.
|
|
26
26
|
- **--next --auto**: Like `--next`, but after the determined step completes, automatically re-invokes `/gsd-progress --next --auto` to continue chaining steps until completion or a blocking decision. Enables hands-free plan→execute→verify→complete progression.
|
|
27
|
-
- **--next --converge**: When the next action is planning (Route 3), route it through the plan-review **convergence** loop instead of the standard planner. Requires `workflow.plan_review_convergence=true` (enable with `gsd config-set workflow.plan_review_convergence true`). `--cross-ai` is an alias. Reviewer flags (`--codex`, `--
|
|
27
|
+
- **--next --converge**: When the next action is planning (Route 3), route it through the plan-review **convergence** loop instead of the standard planner. Requires `workflow.plan_review_convergence=true` (enable with `gsd config-set workflow.plan_review_convergence true`). `--cross-ai` is an alias. Reviewer flags (`--codex`, `--claude`, `--opencode`, `--ollama`, `--lm-studio`, `--llama-cpp`, `--all`) and `--max-cycles N` are forwarded to the convergence loop.
|
|
28
28
|
- **--do "..."**: Smart dispatcher — match freeform intent to the best GSD command using routing rules, confirm the match, then hand off.
|
|
29
29
|
- **--forensic**: Run 6-check integrity audit after the standard progress report.
|
|
30
30
|
- **(no flag)**: Standard progress check + intelligent routing (Routes A through F).
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: gsd-quick-batch
|
|
3
|
-
description: "Batch several
|
|
3
|
+
description: "Batch several `/gsd-quick`-shaped tasks together — planned, dispatched, and merged as one run"
|
|
4
4
|
argument-hint: "[--file <path>] [--jobs auto|N] [--validate] [--research] [--resume <batch-id>] [task list]"
|
|
5
5
|
allowed-tools:
|
|
6
6
|
- Read
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: gsd-review
|
|
3
3
|
description: "Request cross-AI peer review of phase plans from external AI CLIs"
|
|
4
|
-
argument-hint: "--phase N [--
|
|
4
|
+
argument-hint: "--phase N [--claude] [--codex] [--opencode] [--qwen] [--cursor] [--agy] [--all]"
|
|
5
5
|
allowed-tools:
|
|
6
6
|
- Read
|
|
7
7
|
- Write
|
|
@@ -12,7 +12,7 @@ allowed-tools:
|
|
|
12
12
|
|
|
13
13
|
|
|
14
14
|
<objective>
|
|
15
|
-
Invoke external AI CLIs (
|
|
15
|
+
Invoke external AI CLIs (Claude, Codex, OpenCode, Qwen Code, Cursor, Antigravity) to independently review phase plans.
|
|
16
16
|
Produces a structured REVIEWS.md with per-reviewer feedback that can be fed back into
|
|
17
17
|
planning via /gsd-plan-phase --reviews.
|
|
18
18
|
|
|
@@ -27,7 +27,6 @@ planning via /gsd-plan-phase --reviews.
|
|
|
27
27
|
Phase number: extracted from $ARGUMENTS (required)
|
|
28
28
|
|
|
29
29
|
**Flags:**
|
|
30
|
-
- `--gemini` — Include Gemini CLI review
|
|
31
30
|
- `--claude` — Include Claude CLI review (uses separate session)
|
|
32
31
|
- `--codex` — Include Codex CLI review
|
|
33
32
|
- `--opencode` — Include OpenCode review (uses model from user's OpenCode config)
|
package/vscode/package.json
CHANGED