@opengsd/gsd-core 1.14.0 → 1.16.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/.opencode/plugins/gsd-core.js +85 -5
- 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-code-reviewer.compact.md +5 -3
- package/agents/gsd-code-reviewer.md +8 -6
- package/agents/gsd-debug-session-manager.compact.md +17 -2
- package/agents/gsd-debug-session-manager.md +17 -2
- package/agents/gsd-debugger.md +3 -3
- package/agents/gsd-eval-auditor.compact.md +1 -1
- package/agents/gsd-eval-auditor.md +1 -1
- package/agents/gsd-executor.md +17 -12
- package/agents/gsd-intel-updater.compact.md +1 -1
- package/agents/gsd-intel-updater.md +1 -1
- package/agents/gsd-mempalace-curator.md +2 -2
- package/agents/gsd-phase-researcher.md +19 -11
- package/agents/gsd-plan-checker.md +15 -9
- package/agents/gsd-planner.md +15 -11
- 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.compact.md +21 -30
- package/agents/gsd-ui-auditor.md +166 -37
- package/agents/gsd-ui-researcher.compact.md +1 -1
- package/agents/gsd-ui-researcher.md +1 -1
- package/agents/gsd-verifier.md +37 -14
- package/bin/install.js +764 -287
- package/commands/gsd/add-tests.md +6 -1
- package/commands/gsd/ai-integration-phase.md +6 -1
- package/commands/gsd/audit-fix.md +5 -0
- package/commands/gsd/audit-milestone.md +6 -1
- package/commands/gsd/autonomous.md +7 -2
- package/commands/gsd/capture.md +9 -5
- package/commands/gsd/code-review.md +7 -2
- package/commands/gsd/complete-milestone.md +4 -0
- package/commands/gsd/config.md +7 -3
- package/commands/gsd/debug.md +11 -7
- package/commands/gsd/discuss-phase.md +7 -3
- package/commands/gsd/docs-update.md +12 -7
- package/commands/gsd/eval-review.md +6 -1
- package/commands/gsd/execute-phase.md +12 -7
- package/commands/gsd/extract-learnings.md +5 -0
- package/commands/gsd/fast.md +4 -0
- package/commands/gsd/forensics.md +5 -1
- package/commands/gsd/graphify.md +10 -6
- package/commands/gsd/health.md +5 -0
- package/commands/gsd/help.md +7 -2
- package/commands/gsd/import.md +7 -3
- package/commands/gsd/inbox.md +5 -0
- package/commands/gsd/ingest-docs.md +5 -1
- package/commands/gsd/manager.md +6 -1
- package/commands/gsd/map-codebase.md +7 -3
- package/commands/gsd/mempalace-capture.md +12 -4
- package/commands/gsd/mempalace-recall.md +5 -1
- package/commands/gsd/milestone-summary.md +5 -1
- package/commands/gsd/mvp-phase.md +8 -3
- package/commands/gsd/new-milestone.md +6 -1
- package/commands/gsd/new-project.md +5 -0
- package/commands/gsd/next.md +6 -1
- package/commands/gsd/ns-context.md +4 -0
- package/commands/gsd/ns-ideate.md +4 -0
- package/commands/gsd/ns-manage.md +4 -0
- package/commands/gsd/ns-project.md +4 -0
- package/commands/gsd/ns-review.md +4 -0
- package/commands/gsd/ns-workflow.md +4 -0
- package/commands/gsd/onboard.md +6 -1
- package/commands/gsd/pause-work.md +5 -1
- package/commands/gsd/phase.md +8 -4
- package/commands/gsd/plan-phase.md +6 -1
- package/commands/gsd/plan-review-convergence.md +11 -7
- package/commands/gsd/pr-branch.md +4 -0
- package/commands/gsd/profile-user.md +5 -1
- package/commands/gsd/progress.md +7 -2
- package/commands/gsd/quick-batch.md +21 -9
- package/commands/gsd/quick.md +12 -7
- package/commands/gsd/review.md +7 -4
- package/commands/gsd/secure-phase.md +6 -1
- package/commands/gsd/ship.md +5 -0
- package/commands/gsd/sketch.md +7 -2
- package/commands/gsd/spec-phase.md +5 -1
- package/commands/gsd/spike.md +8 -3
- package/commands/gsd/surface.md +5 -1
- package/commands/gsd/thread.md +4 -0
- package/commands/gsd/ui-phase.md +6 -1
- package/commands/gsd/ui-review.md +6 -1
- package/commands/gsd/ultraplan-phase.md +5 -1
- package/commands/gsd/undo.md +5 -1
- package/commands/gsd/update.md +6 -2
- package/commands/gsd/validate-phase.md +6 -1
- package/commands/gsd/verify-work.md +6 -1
- package/commands/gsd/workspace.md +7 -3
- package/gsd-core/bin/gsd-tools.cjs +477 -78
- package/gsd-core/bin/lib/active-workstream-store.cjs +15 -0
- package/gsd-core/bin/lib/adr-parser.cjs +3 -1
- package/gsd-core/bin/lib/agent-install-check.cjs +4 -1
- package/gsd-core/bin/lib/audit.cjs +144 -42
- package/gsd-core/bin/lib/broken-windows.cjs +13 -13
- package/gsd-core/bin/lib/capability-activation.cjs +9 -4
- package/gsd-core/bin/lib/capability-registry.cjs +197 -222
- package/gsd-core/bin/lib/capability-validator.cjs +16 -1
- package/gsd-core/bin/lib/check-auto-mode.cjs +35 -0
- package/gsd-core/bin/lib/check-command-router.cjs +164 -1625
- package/gsd-core/bin/lib/cjs-command-router-adapter.cjs +13 -2
- package/gsd-core/bin/lib/cli-exit.cjs +12 -0
- package/gsd-core/bin/lib/codex-agent-toml.cjs +32 -33
- package/gsd-core/bin/lib/command-aliases.cjs +7 -0
- package/gsd-core/bin/lib/command-routing-hub.cjs +48 -1
- package/gsd-core/bin/lib/commands.cjs +343 -207
- package/gsd-core/bin/lib/complexity-trigger.cjs +8 -7
- package/gsd-core/bin/lib/config-loader.cjs +65 -4
- package/gsd-core/bin/lib/config.cjs +76 -19
- package/gsd-core/bin/lib/core-utils.cjs +6 -1
- package/gsd-core/bin/lib/coverage.cjs +4 -8
- package/gsd-core/bin/lib/decision-coverage-support.cjs +259 -0
- package/gsd-core/bin/lib/decisions.cjs +30 -14
- package/gsd-core/bin/lib/drift.cjs +177 -42
- package/gsd-core/bin/lib/frontmatter-fence.cjs +90 -0
- package/gsd-core/bin/lib/frontmatter-splice.cjs +494 -0
- package/gsd-core/bin/lib/frontmatter.cjs +426 -234
- package/gsd-core/bin/lib/gap-checker.cjs +72 -29
- package/gsd-core/bin/lib/gate-api-coverage-verify-pre.cjs +381 -0
- package/gsd-core/bin/lib/gate-args.cjs +53 -0
- package/gsd-core/bin/lib/gate-codebase-drift.cjs +285 -0
- package/gsd-core/bin/lib/gate-config.cjs +46 -0
- package/gsd-core/bin/lib/gate-context-drift.cjs +141 -0
- package/gsd-core/bin/lib/gate-decision-coverage-plan.cjs +169 -0
- package/gsd-core/bin/lib/gate-decision-coverage-verify.cjs +126 -0
- package/gsd-core/bin/lib/gate-evaluation-scope.cjs +555 -0
- package/gsd-core/bin/lib/gate-evidence.cjs +138 -0
- package/gsd-core/bin/lib/gate-exit.cjs +27 -0
- package/gsd-core/bin/lib/gate-gap-analysis-plan-post.cjs +61 -0
- package/gsd-core/bin/lib/gate-phase-context.cjs +170 -0
- package/gsd-core/bin/lib/gate-predicate-evaluator.cjs +1 -1
- package/gsd-core/bin/lib/gate-predicate.cjs +165 -0
- package/gsd-core/bin/lib/gate-prohibition-enforcement.cjs +94 -0
- package/gsd-core/bin/lib/gate-schema-drift.cjs +165 -0
- package/gsd-core/bin/lib/gate-tdd-red-evidence.cjs +100 -0
- package/gsd-core/bin/lib/gate-tdd-review-checkpoint.cjs +182 -0
- package/gsd-core/bin/lib/gate-ui-plan.cjs +86 -0
- package/gsd-core/bin/lib/gate-ui-safety.cjs +80 -0
- package/gsd-core/bin/lib/gate-verdict.cjs +64 -0
- package/gsd-core/bin/lib/gate-verify-command-paths.cjs +78 -0
- package/gsd-core/bin/lib/gate-verify-failure-directions.cjs +41 -0
- package/gsd-core/bin/lib/graphify.cjs +10 -2
- package/gsd-core/bin/lib/health-diagnostic-rules/phase-structure.cjs +43 -47
- package/gsd-core/bin/lib/health-diagnostic.cjs +45 -8
- package/gsd-core/bin/lib/host-runtime-detection.cjs +9 -0
- package/gsd-core/bin/lib/init.cjs +364 -132
- package/gsd-core/bin/lib/install-engine.cjs +30 -33
- package/gsd-core/bin/lib/install-profiles.cjs +7 -4
- package/gsd-core/bin/lib/installer-migrations.cjs +8 -1
- package/gsd-core/bin/lib/io.cjs +122 -3
- package/gsd-core/bin/lib/loop-resolver.cjs +95 -0
- package/gsd-core/bin/lib/markdown-sectionizer.cjs +75 -1
- package/gsd-core/bin/lib/milestone.cjs +37 -6
- package/gsd-core/bin/lib/model-resolver.cjs +171 -62
- package/gsd-core/bin/lib/observability/event.cjs +1 -1
- package/gsd-core/bin/lib/observability/logger.cjs +46 -1
- package/gsd-core/bin/lib/pattern.cjs +10 -0
- package/gsd-core/bin/lib/phase-command-router.cjs +20 -5
- package/gsd-core/bin/lib/phase-estimation.cjs +5 -4
- 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 +110 -8
- package/gsd-core/bin/lib/phase-lifecycle.cjs +9 -2
- package/gsd-core/bin/lib/phase-locator.cjs +29 -10
- package/gsd-core/bin/lib/phase-status.cjs +360 -0
- package/gsd-core/bin/lib/phase.cjs +489 -88
- package/gsd-core/bin/lib/plan-document.cjs +142 -20
- package/gsd-core/bin/lib/plan-drift-guard.cjs +5 -0
- package/gsd-core/bin/lib/planning-document.cjs +692 -0
- package/gsd-core/bin/lib/planning-inspect.cjs +60 -9
- package/gsd-core/bin/lib/planning-snapshot.cjs +18 -0
- package/gsd-core/bin/lib/planning-workspace.cjs +83 -55
- package/gsd-core/bin/lib/pr-branch-patterns.cjs +57 -0
- package/gsd-core/bin/lib/pristine-baseline.cjs +10 -0
- package/gsd-core/bin/lib/probe-core.cjs +7 -1
- package/gsd-core/bin/lib/profile-output.cjs +6 -3
- package/gsd-core/bin/lib/prohibition-enforcement.cjs +0 -55
- package/gsd-core/bin/lib/project-root.cjs +41 -2
- package/gsd-core/bin/lib/quick-batch-command-router.cjs +35 -9
- package/gsd-core/bin/lib/quick-batch-dispatch.cjs +11 -8
- package/gsd-core/bin/lib/real-home-guard.cjs +9 -1
- package/gsd-core/bin/lib/report-parser.cjs +269 -0
- 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 +25 -19
- package/gsd-core/bin/lib/roadmap-parser.cjs +242 -15
- package/gsd-core/bin/lib/roadmap-upgrade.cjs +1653 -65
- package/gsd-core/bin/lib/roadmap.cjs +405 -88
- package/gsd-core/bin/lib/runtime-artifact-conversion.cjs +373 -187
- package/gsd-core/bin/lib/runtime-artifact-install-plan.cjs +5 -2
- package/gsd-core/bin/lib/runtime-artifact-layout.cjs +57 -1
- package/gsd-core/bin/lib/runtime-homes.cjs +14 -7
- package/gsd-core/bin/lib/runtime-hooks-surface.cjs +522 -624
- package/gsd-core/bin/lib/runtime-name-policy.cjs +246 -21
- package/gsd-core/bin/lib/runtime-slash.cjs +47 -30
- package/gsd-core/bin/lib/shell-command-projection.cjs +47 -8
- package/gsd-core/bin/lib/smart-entry.cjs +19 -3
- package/gsd-core/bin/lib/stale-bake-guard.cjs +32 -48
- package/gsd-core/bin/lib/state-contract.cjs +15 -18
- package/gsd-core/bin/lib/state-document.cjs +100 -22
- package/gsd-core/bin/lib/state-transition.cjs +39 -2
- package/gsd-core/bin/lib/state.cjs +256 -105
- package/gsd-core/bin/lib/surface.cjs +19 -2
- package/gsd-core/bin/lib/tdd-red-evidence.cjs +48 -79
- package/gsd-core/bin/lib/uat-predicate.cjs +359 -38
- package/gsd-core/bin/lib/uat.cjs +432 -7
- package/gsd-core/bin/lib/ui-consideration-probe.cjs +15 -2
- package/gsd-core/bin/lib/ui-frontend-evidence.cjs +167 -40
- package/gsd-core/bin/lib/undo-commit-selection.cjs +131 -0
- package/gsd-core/bin/lib/vendor/README.md +31 -9
- package/gsd-core/bin/lib/vendor/saxes.cjs +1934 -0
- package/gsd-core/bin/lib/vendor/saxes.cjs.LICENSE.txt +92 -0
- package/gsd-core/bin/lib/vendor/tap-parser.cjs +8927 -0
- package/gsd-core/bin/lib/vendor/tap-parser.cjs.LICENSE.txt +152 -0
- package/gsd-core/bin/lib/verification-command-router.cjs +2 -1
- package/gsd-core/bin/lib/verification.cjs +1378 -274
- package/gsd-core/bin/lib/verify-command-grounding.cjs +46 -2
- package/gsd-core/bin/lib/verify-command-router.cjs +18 -7
- package/gsd-core/bin/lib/verify.cjs +357 -531
- package/gsd-core/bin/lib/workstream-inventory-builder.cjs +14 -6
- package/gsd-core/bin/lib/workstream-inventory.cjs +31 -21
- package/gsd-core/bin/lib/workstream-name-policy.cjs +31 -1
- package/gsd-core/bin/lib/workstream.cjs +11 -2
- 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 +8 -0
- package/gsd-core/bin/shared/config-schema.manifest.json +5 -0
- package/gsd-core/references/autonomous-smart-discuss.md +2 -1
- package/gsd-core/references/autonomous-ui-design-contract.md +3 -3
- 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-mvp-tdd.md +5 -10
- package/gsd-core/references/execute-phase-between-wave-reset.md +10 -6
- package/gsd-core/references/execute-phase-response-language.md +1 -1
- 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/loop-hook-dispatch.md +7 -1
- package/gsd-core/references/model-profiles.md +1 -1
- package/gsd-core/references/offer-next.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 +12 -3
- package/gsd-core/references/spidr-splitting.md +1 -1
- package/gsd-core/references/tdd.md +37 -8
- package/gsd-core/references/ui-consideration-probe.md +10 -5
- package/gsd-core/references/verifier-phase-gates.md +5 -2
- package/gsd-core/references/verify-command-path-resolvability.md +10 -2
- package/gsd-core/references/verify-mvp-mode.md +2 -2
- package/gsd-core/references/workstream-flag.md +33 -3
- package/gsd-core/references/worktree-path-safety.md +321 -0
- package/gsd-core/templates/README.md +1 -1
- package/gsd-core/templates/UAT.md +17 -1
- package/gsd-core/templates/config.json +2 -11
- 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 +8 -7
- package/gsd-core/workflows/add-tests.md +4 -3
- package/gsd-core/workflows/add-todo.md +6 -5
- package/gsd-core/workflows/ai-integration-phase.md +13 -4
- package/gsd-core/workflows/audit-fix.md +1 -1
- package/gsd-core/workflows/audit-milestone.md +4 -3
- 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 +43 -23
- package/gsd-core/workflows/check-todos.md +7 -6
- 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 +20 -13
- package/gsd-core/workflows/code-review-fix.md +112 -25
- package/gsd-core/workflows/code-review.md +146 -135
- package/gsd-core/workflows/complete-milestone/detail/elaboration.md +4 -3
- package/gsd-core/workflows/complete-milestone.md +13 -8
- package/gsd-core/workflows/debug.md +32 -7
- package/gsd-core/workflows/diagnose-issues.md +3 -2
- 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 +4 -3
- package/gsd-core/workflows/discuss-phase.md +4 -3
- package/gsd-core/workflows/do.md +2 -2
- package/gsd-core/workflows/docs-update.md +6 -5
- package/gsd-core/workflows/edit-phase.md +4 -3
- package/gsd-core/workflows/eval-review.md +14 -5
- package/gsd-core/workflows/execute-phase/detail/elaboration.md +2 -2
- package/gsd-core/workflows/execute-phase/steps/code-review-disposition.md +1019 -0
- package/gsd-core/workflows/execute-phase/steps/codebase-drift-gate.md +15 -4
- package/gsd-core/workflows/execute-phase/steps/completion-reconciliation.md +10 -7
- package/gsd-core/workflows/execute-phase/steps/executor-isolation-dispatch.md +37 -3
- package/gsd-core/workflows/execute-phase/steps/gap-closure-artifacts.md +3 -1
- package/gsd-core/workflows/execute-phase/steps/partial-wave.md +2 -2
- 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/regression-gate.md +2 -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/verify-phase-goal.md +187 -0
- package/gsd-core/workflows/execute-phase/steps/wave-post-gate-hooks.md +2 -3
- package/gsd-core/workflows/execute-phase/steps/worktree-base-check.md +25 -0
- package/gsd-core/workflows/execute-phase.md +96 -178
- package/gsd-core/workflows/execute-plan.md +18 -23
- package/gsd-core/workflows/explore.md +4 -4
- package/gsd-core/workflows/extract-learnings.md +4 -2
- 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 +3 -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 +4 -3
- package/gsd-core/workflows/inbox.md +2 -2
- package/gsd-core/workflows/ingest-docs.md +3 -3
- package/gsd-core/workflows/insert-phase.md +4 -3
- package/gsd-core/workflows/list-seeds.md +1 -1
- package/gsd-core/workflows/list-workspaces.md +1 -1
- package/gsd-core/workflows/manager.md +6 -4
- package/gsd-core/workflows/map-codebase.md +5 -4
- package/gsd-core/workflows/milestone-summary.md +3 -2
- package/gsd-core/workflows/mvp-phase.md +14 -14
- package/gsd-core/workflows/new-milestone.md +11 -11
- 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 +2 -2
- 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/closed-phase-gate.md +1 -1
- 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 +50 -24
- 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 +19 -49
- package/gsd-core/workflows/quick/steps/plan-checker-loop.md +27 -0
- package/gsd-core/workflows/quick/steps/quick-verification.md +4 -4
- package/gsd-core/workflows/quick/steps/worktree-pre-dispatch-commit.md +30 -11
- 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 +9 -3
- package/gsd-core/workflows/quick-batch/steps/worktree-dispatch.md +1 -1
- package/gsd-core/workflows/quick-batch.md +15 -10
- package/gsd-core/workflows/quick.md +62 -39
- package/gsd-core/workflows/reapply-patches.md +9 -3
- package/gsd-core/workflows/remove-phase.md +3 -2
- package/gsd-core/workflows/remove-workspace.md +2 -2
- package/gsd-core/workflows/resume-project.md +3 -2
- package/gsd-core/workflows/review.md +33 -17
- package/gsd-core/workflows/scan.md +3 -2
- package/gsd-core/workflows/secure-phase.md +13 -13
- 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 +14 -13
- 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 +2 -2
- package/gsd-core/workflows/transition.md +13 -23
- package/gsd-core/workflows/ui-phase.md +48 -11
- package/gsd-core/workflows/ui-review.md +21 -6
- package/gsd-core/workflows/ultraplan-phase.md +3 -2
- package/gsd-core/workflows/undo.md +339 -20
- package/gsd-core/workflows/update.md +7 -7
- package/gsd-core/workflows/validate-phase.md +12 -13
- package/gsd-core/workflows/verify-work/detail/elaboration.md +43 -3
- package/gsd-core/workflows/verify-work/steps/automated-ui-verification.md +1 -1
- package/gsd-core/workflows/verify-work/steps/mvp-uat-framing.md +5 -3
- package/gsd-core/workflows/verify-work.md +129 -55
- package/hooks/dist/gsd-agent-isolation-guard.js +32 -0
- package/hooks/dist/gsd-check-update-worker.js +8 -0
- package/hooks/dist/gsd-check-update.js +8 -0
- package/hooks/dist/gsd-context-monitor.js +31 -8
- package/hooks/dist/gsd-cursor-subagent-start.js +8 -0
- package/hooks/dist/gsd-secret-read-guard.js +161 -4
- package/hooks/dist/gsd-statusline.js +85 -20
- package/hooks/dist/gsd-update-banner.js +8 -0
- package/hooks/dist/gsd-validate-commit.sh +63 -4
- package/hooks/dist/gsd-windsurf-pre-write.js +11 -2
- package/hooks/dist/gsd-workflow-guard.js +5 -4
- package/hooks/dist/gsd-worktree-path-guard.js +6 -2
- package/hooks/dist/lib/cli-exit.js +12 -0
- package/hooks/dist/lib/git-probe.js +17 -1
- package/hooks/dist/lib/isolation-sentinel.js +2 -2
- package/hooks/gsd-agent-isolation-guard.js +32 -0
- package/hooks/gsd-check-update-worker.js +8 -0
- package/hooks/gsd-check-update.js +8 -0
- package/hooks/gsd-context-monitor.js +31 -8
- package/hooks/gsd-cursor-subagent-start.js +8 -0
- package/hooks/gsd-secret-read-guard.js +161 -4
- package/hooks/gsd-statusline.js +85 -20
- package/hooks/gsd-update-banner.js +8 -0
- package/hooks/gsd-validate-commit.sh +63 -4
- package/hooks/gsd-windsurf-pre-write.js +11 -2
- package/hooks/gsd-workflow-guard.js +5 -4
- package/hooks/gsd-worktree-path-guard.js +6 -2
- package/hooks/hooks.json +5 -5
- package/hooks/lib/cli-exit.js +12 -0
- package/hooks/lib/git-probe.js +17 -1
- package/hooks/lib/isolation-sentinel.js +2 -2
- package/package.json +22 -4
- package/scripts/build-hooks.js +15 -6
- package/scripts/changeset/parse.cjs +52 -4
- package/scripts/check-contract-drift.cjs +127 -11
- package/scripts/ci-timeout-report.cjs +770 -4
- package/scripts/command-contract-helpers.cjs +15 -8
- package/scripts/docs-guard-registry.cjs +34 -0
- package/scripts/gen-features.cjs +13 -8
- package/scripts/gen-hooks-cli-exit.cjs +12 -28
- package/scripts/gen-loop-host-contract.cjs +79 -1
- package/scripts/gen-platform-conformance-tier.cjs +187 -1
- package/scripts/gen-plugin-skills.cjs +87 -1
- package/scripts/gen-research-agents.cjs +24 -31
- package/scripts/gen-scripts-cli-exit.cjs +30 -3
- package/scripts/gen-test-timings.cjs +32 -7
- package/scripts/lib/cli-exit.cjs +12 -0
- package/scripts/lib/macos-conformance-tier.generated.cjs +34 -2
- package/scripts/lib/ndjson-reporter.cjs +31 -5
- package/scripts/lib/platform-conformance-tier.generated.cjs +45 -5
- package/scripts/lib/registration-ledger-preload.cjs +155 -0
- package/scripts/lib/vendor-bundle.cjs +59 -0
- package/scripts/lib/vendor-licenses/saxes-6.0.0.txt +64 -0
- package/scripts/lint-allow-test-rule-refs.effective-ceiling.json +1 -1
- package/scripts/lint-allow-test-rule-refs.unverified-ceiling.json +1 -1
- package/scripts/lint-completion-predicate-drift.cjs +18 -19
- package/scripts/lint-descriptions.cjs +7 -3
- package/scripts/lint-docs-guard-registration.exempt-baseline.cjs +38 -1
- package/scripts/lint-eslint-glob-coverage.allowlist.json +20 -0
- package/scripts/lint-frontmatter-fence-drift.cjs +313 -0
- package/scripts/lint-frontmatter-scalar-broad-grep.cjs +122 -16
- package/scripts/lint-phase-arg-assignment.cjs +257 -0
- package/scripts/lint-phase-enumeration-drift.cjs +12 -8
- package/scripts/lint-phase-id-drift.cjs +319 -5
- package/scripts/lint-planning-document-positive-control.cjs +329 -0
- package/scripts/lint-pr-branch-pattern-drift.cjs +148 -0
- package/scripts/lint-response-language-coverage.cjs +3 -0
- package/scripts/lint-retired-runtime-name.cjs +619 -0
- package/scripts/lint-skill-deps.cjs +7 -3
- package/scripts/lint-state-write-path-drift.cjs +93 -0
- package/scripts/lint-test-file-count.allowlist.json +38 -9
- package/scripts/lint-test-file-count.cjs +34 -1
- package/scripts/lint-vendored-deps.cjs +41 -5
- package/scripts/lint-workflow-shellcheck-baseline.json +25 -10
- package/scripts/mutation-matrix.cjs +50 -5
- package/scripts/prompt-injection-scan.sh +4 -0
- package/scripts/release-tarball-smoke.cjs +194 -1
- package/scripts/require-issue-link-policy.cjs +6 -2
- package/scripts/sync-runtime-launcher.cjs +184 -2
- package/scripts/verify-npm-publish.cjs +76 -20
- package/skills/gsd-add-tests/SKILL.md +6 -1
- package/skills/gsd-ai-integration-phase/SKILL.md +6 -1
- package/skills/gsd-audit-fix/SKILL.md +5 -0
- package/skills/gsd-audit-milestone/SKILL.md +6 -1
- package/skills/gsd-autonomous/SKILL.md +7 -2
- package/skills/gsd-capture/SKILL.md +9 -5
- package/skills/gsd-code-review/SKILL.md +7 -2
- package/skills/gsd-complete-milestone/SKILL.md +4 -0
- package/skills/gsd-config/SKILL.md +8 -4
- package/skills/gsd-debug/SKILL.md +11 -7
- package/skills/gsd-discuss-phase/SKILL.md +7 -3
- package/skills/gsd-docs-update/SKILL.md +12 -7
- package/skills/gsd-eval-review/SKILL.md +6 -1
- package/skills/gsd-execute-phase/SKILL.md +12 -7
- package/skills/gsd-extract-learnings/SKILL.md +5 -0
- package/skills/gsd-fast/SKILL.md +4 -0
- package/skills/gsd-forensics/SKILL.md +5 -1
- package/skills/gsd-graphify/SKILL.md +10 -6
- package/skills/gsd-health/SKILL.md +5 -0
- package/skills/gsd-help/SKILL.md +7 -2
- package/skills/gsd-import/SKILL.md +7 -3
- package/skills/gsd-inbox/SKILL.md +5 -0
- package/skills/gsd-ingest-docs/SKILL.md +5 -1
- package/skills/gsd-manager/SKILL.md +6 -1
- package/skills/gsd-map-codebase/SKILL.md +7 -3
- package/skills/gsd-mempalace-capture/SKILL.md +12 -4
- package/skills/gsd-mempalace-recall/SKILL.md +5 -1
- package/skills/gsd-milestone-summary/SKILL.md +5 -1
- package/skills/gsd-mvp-phase/SKILL.md +8 -3
- package/skills/gsd-new-milestone/SKILL.md +6 -1
- package/skills/gsd-new-project/SKILL.md +5 -0
- package/skills/gsd-next/SKILL.md +6 -1
- package/skills/gsd-ns-context/SKILL.md +4 -0
- package/skills/gsd-ns-ideate/SKILL.md +4 -0
- package/skills/gsd-ns-manage/SKILL.md +4 -0
- package/skills/gsd-ns-project/SKILL.md +4 -0
- package/skills/gsd-ns-review/SKILL.md +4 -0
- package/skills/gsd-ns-workflow/SKILL.md +4 -0
- package/skills/gsd-onboard/SKILL.md +6 -1
- package/skills/gsd-pause-work/SKILL.md +5 -1
- package/skills/gsd-phase/SKILL.md +8 -4
- package/skills/gsd-plan-phase/SKILL.md +6 -1
- package/skills/gsd-plan-review-convergence/SKILL.md +10 -6
- package/skills/gsd-pr-branch/SKILL.md +4 -0
- package/skills/gsd-profile-user/SKILL.md +5 -1
- package/skills/gsd-progress/SKILL.md +7 -2
- package/skills/gsd-quick/SKILL.md +16 -10
- package/skills/gsd-quick-batch/SKILL.md +21 -9
- package/skills/gsd-review/SKILL.md +7 -4
- package/skills/gsd-review-backlog/SKILL.md +3 -2
- package/skills/gsd-secure-phase/SKILL.md +6 -1
- package/skills/gsd-ship/SKILL.md +5 -0
- package/skills/gsd-sketch/SKILL.md +7 -2
- package/skills/gsd-spec-phase/SKILL.md +5 -1
- package/skills/gsd-spike/SKILL.md +8 -3
- package/skills/gsd-surface/SKILL.md +5 -1
- package/skills/gsd-thread/SKILL.md +4 -0
- package/skills/gsd-ui-phase/SKILL.md +6 -1
- package/skills/gsd-ui-review/SKILL.md +6 -1
- package/skills/gsd-ultraplan-phase/SKILL.md +5 -1
- package/skills/gsd-undo/SKILL.md +5 -1
- package/skills/gsd-update/SKILL.md +6 -2
- package/skills/gsd-validate-phase/SKILL.md +6 -1
- package/skills/gsd-verify-work/SKILL.md +6 -1
- package/skills/gsd-workspace/SKILL.md +7 -3
- package/skills/gsd-workstreams/SKILL.md +6 -6
- package/vscode/package.json +1 -1
|
@@ -0,0 +1,329 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* PlanningDoc positive-control lint (ADR-4910 §7, "Every parser ships a
|
|
6
|
+
* positive control per accepted grammar", epic #4906 Phase 6 / #5007).
|
|
7
|
+
*
|
|
8
|
+
* `NodeKind` (`src/planning-document.cts`, compiled to
|
|
9
|
+
* `gsd-core/bin/lib/planning-document.cjs`) is the single-source union naming
|
|
10
|
+
* every grammar `parsePlanningDoc` accepts: `frontmatter` / `section` /
|
|
11
|
+
* `boldField` / `table` / `checklist`. This lint asserts one positive-control
|
|
12
|
+
* fixture per declared grammar, under `tests/fixtures/planning-document/`,
|
|
13
|
+
* each of which must round-trip through the real `parsePlanningDoc` and
|
|
14
|
+
* actually produce a node of that kind — not merely "the parser didn't
|
|
15
|
+
* throw". Per CONTRIBUTING.md's fixture-provenance rule (#2371), every
|
|
16
|
+
* fixture here is authored independently, never copied from
|
|
17
|
+
* `src/planning-document.cts`'s own docstring examples or from
|
|
18
|
+
* `tests/planning-document.test.cjs`'s existing fixtures.
|
|
19
|
+
*
|
|
20
|
+
* The `accepted` set (`NodeKind`) is a TypeScript-only type, erased by
|
|
21
|
+
* compilation — it carries no runtime value in the built `.cjs` seam. So this
|
|
22
|
+
* lint reads it directly out of `src/planning-document.cts`'s own source
|
|
23
|
+
* text (the `export type NodeKind = ...;` declaration), the same way
|
|
24
|
+
* `scripts/lint-phase-id-drift.cjs` reads source text for its own literal
|
|
25
|
+
* checks — NOT by importing a type, which is impossible from a `.cjs`
|
|
26
|
+
* script. This is what makes the guarantee live: a NEW grammar kind added to
|
|
27
|
+
* `NodeKind` with no registry entry fails this lint immediately, before any
|
|
28
|
+
* fixture is even written, closing the "parser without one fails the build"
|
|
29
|
+
* requirement in ADR-4910 §7.
|
|
30
|
+
*
|
|
31
|
+
* Modeled on `scripts/lint-table-schema-drift.cjs`'s registry/exit-code/
|
|
32
|
+
* error-message structure — a hardcoded `{grammar -> fixture file}` map,
|
|
33
|
+
* exit 0 clean / exit 1 with a per-entry reason on drift, wired into
|
|
34
|
+
* `lint:ci` — but the ASSERTION is stricter than that script's verbatim-
|
|
35
|
+
* substring check: proof the grammar is genuinely *accepted* (the fixture
|
|
36
|
+
* parses without error and yields a node of that kind), per ADR-4910 §7's
|
|
37
|
+
* own text, not just "a string appears somewhere".
|
|
38
|
+
*/
|
|
39
|
+
|
|
40
|
+
const fs = require('node:fs');
|
|
41
|
+
const path = require('node:path');
|
|
42
|
+
|
|
43
|
+
const PLANNING_DOCUMENT_SRC = path.join('src', 'planning-document.cts');
|
|
44
|
+
const PLANNING_DOCUMENT_LIB = path.join('gsd-core', 'bin', 'lib', 'planning-document.cjs');
|
|
45
|
+
const FIXTURE_DIR = path.join('tests', 'fixtures', 'planning-document');
|
|
46
|
+
|
|
47
|
+
// grammar kind (must match a `NodeKind` union member verbatim) -> the ONE
|
|
48
|
+
// canonical positive-control fixture file (relative to FIXTURE_DIR) that
|
|
49
|
+
// proves that grammar is accepted (ADR-4910 §7).
|
|
50
|
+
const POSITIVE_CONTROL_REGISTRY = {
|
|
51
|
+
frontmatter: 'frontmatter.md',
|
|
52
|
+
section: 'section.md',
|
|
53
|
+
boldField: 'boldfield.md',
|
|
54
|
+
table: 'table.md',
|
|
55
|
+
checklist: 'checklist.md',
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
// Any real entry from `PLANNING_ARTIFACTS` satisfies `parsePlanningDoc`'s
|
|
59
|
+
// artifact-kind gate equally — the specific name does not affect which
|
|
60
|
+
// grammars a fixture's BODY is recognised as containing.
|
|
61
|
+
const FIXTURE_ARTIFACT_NAME = 'ROADMAP.md';
|
|
62
|
+
|
|
63
|
+
// Test-only env var name. `resolveRegistry` below JSON-parses this (when set)
|
|
64
|
+
// and shallow-merges it over `POSITIVE_CONTROL_REGISTRY`, so a test can spawn
|
|
65
|
+
// THIS SAME, otherwise-unmodified, script file as a real child process
|
|
66
|
+
// against a deliberately broken registry entry (a missing entry, or one
|
|
67
|
+
// pointed at a nonexistent fixture) — proving the lint genuinely fails the
|
|
68
|
+
// build, per ADR-4910 §7's "a parser without one fails the build" guarantee
|
|
69
|
+
// — without ever touching the real registry or fixture files.
|
|
70
|
+
//
|
|
71
|
+
// This env var alone is NEVER sufficient to activate the override — a bare
|
|
72
|
+
// `process.env` lookup would mean a stray, accidentally-inherited copy of
|
|
73
|
+
// this variable (a leftover shell `export`, a misconfigured CI environment,
|
|
74
|
+
// a compromised dependency's postinstall script) could silently swap the
|
|
75
|
+
// registry in a REAL `npm run lint:ci` / `npm run lint:planning-document-
|
|
76
|
+
// positive-control` invocation, with nothing in the code enforcing otherwise
|
|
77
|
+
// (flagged by both the security review and the code-review Standards axis
|
|
78
|
+
// on #5007 Phase 6: the old comment asserted "no real invocation ever sets
|
|
79
|
+
// this" as a convention, not a fact the code made true).
|
|
80
|
+
//
|
|
81
|
+
// What now makes it true, by construction: `scanRepo` only reads this env
|
|
82
|
+
// var via `resolveRegistry` when its caller ALSO passes `allowOverride ===
|
|
83
|
+
// true`, which `main()` only does when the `--test-registry-override` CLI
|
|
84
|
+
// flag is present in argv (see `parseArgs`). The test file spawns this
|
|
85
|
+
// script as a real child process (`tests/helpers/process-seam.cjs`'s
|
|
86
|
+
// `runNode`, over `spawnSync`) — a process boundary that can only carry data
|
|
87
|
+
// in via `env`/`argv`, so the override cannot be passed as an in-process
|
|
88
|
+
// function parameter here the way it can be for the pure functions below.
|
|
89
|
+
// Requiring BOTH the env var and the CLI flag closes the gap: neither
|
|
90
|
+
// `lint:ci` nor `lint:planning-document-positive-control` (see package.json)
|
|
91
|
+
// ever passes `--test-registry-override` in their fixed argv, and unlike an
|
|
92
|
+
// env var, a CLI flag is never accidentally "leaked" into a fixed npm-script
|
|
93
|
+
// invocation. See tests/lint-planning-document-positive-control.test.cjs.
|
|
94
|
+
const TEST_REGISTRY_OVERRIDE_ENV_VAR = 'LINT_PLANNING_DOCUMENT_POSITIVE_CONTROL_TEST_REGISTRY_OVERRIDE';
|
|
95
|
+
|
|
96
|
+
/** CLI flag gate for the test-only override (see `TEST_REGISTRY_OVERRIDE_ENV_VAR`
|
|
97
|
+
* above). Must be passed explicitly in argv — never inferred from env — for
|
|
98
|
+
* `resolveRegistry`'s env-var override to be honored at all. */
|
|
99
|
+
const TEST_REGISTRY_OVERRIDE_CLI_FLAG = '--test-registry-override';
|
|
100
|
+
|
|
101
|
+
/** Resolve the registry to scan against: the real hardcoded registry, unless
|
|
102
|
+
* BOTH `allowOverride` is `true` (only ever set by the
|
|
103
|
+
* `--test-registry-override` CLI flag, see `TEST_REGISTRY_OVERRIDE_CLI_FLAG`)
|
|
104
|
+
* AND the test-only override env var is set and parses as JSON, in which
|
|
105
|
+
* case its keys are shallow-merged on top (see
|
|
106
|
+
* `TEST_REGISTRY_OVERRIDE_ENV_VAR`). Without `allowOverride === true`, the
|
|
107
|
+
* env var is never even read. */
|
|
108
|
+
function resolveRegistry(env, allowOverride) {
|
|
109
|
+
if (!allowOverride) return POSITIVE_CONTROL_REGISTRY;
|
|
110
|
+
const override = env[TEST_REGISTRY_OVERRIDE_ENV_VAR];
|
|
111
|
+
if (!override) return POSITIVE_CONTROL_REGISTRY;
|
|
112
|
+
try {
|
|
113
|
+
const parsed = JSON.parse(override);
|
|
114
|
+
return { ...POSITIVE_CONTROL_REGISTRY, ...parsed };
|
|
115
|
+
} catch {
|
|
116
|
+
return POSITIVE_CONTROL_REGISTRY;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Extract the live `NodeKind` union members from `planning-document.cts`'s
|
|
122
|
+
* own source text — the "accepted grammars" set (ADR-4910 §4a) — read
|
|
123
|
+
* directly from source (never from the compiled seam, which erases the TS
|
|
124
|
+
* type) so a newly added grammar kind is detected even before any registry
|
|
125
|
+
* entry or fixture exists for it.
|
|
126
|
+
*
|
|
127
|
+
* Pure: takes a `readFile(relPath) -> string|null` accessor so tests can
|
|
128
|
+
* inject a scratch source file without touching the real repo tree.
|
|
129
|
+
*/
|
|
130
|
+
function readLiveGrammarKinds(readFile) {
|
|
131
|
+
const text = readFile(PLANNING_DOCUMENT_SRC);
|
|
132
|
+
if (text == null) {
|
|
133
|
+
return { ok: false, reason: `cannot read ${PLANNING_DOCUMENT_SRC}` };
|
|
134
|
+
}
|
|
135
|
+
const m = /export type NodeKind\s*=\s*([^;]+);/.exec(text);
|
|
136
|
+
if (!m) {
|
|
137
|
+
return {
|
|
138
|
+
ok: false,
|
|
139
|
+
reason: `could not find 'export type NodeKind = ...;' in ${PLANNING_DOCUMENT_SRC} — has the type been renamed or removed?`,
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
const kinds = [...m[1].matchAll(/'([^']+)'/g)].map((mm) => mm[1]);
|
|
143
|
+
if (kinds.length === 0) {
|
|
144
|
+
return {
|
|
145
|
+
ok: false,
|
|
146
|
+
reason: `the 'NodeKind' union in ${PLANNING_DOCUMENT_SRC} matched but contained no string-literal members`,
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
return { ok: true, value: kinds };
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Pure: given the live grammar-kind list, the hardcoded registry, a
|
|
154
|
+
* `readFixture(fileName) -> string|null` accessor, the real `parsePlanningDoc`
|
|
155
|
+
* function, and the artifact name to parse fixtures as, find every gap.
|
|
156
|
+
* Returns `[{ kind, fixture?, reason }]`; empty when clean.
|
|
157
|
+
*
|
|
158
|
+
* Checks, per live grammar kind:
|
|
159
|
+
* 1. a registry entry exists at all (the §7 "parser without one fails the
|
|
160
|
+
* build" guarantee — this fires even with an EMPTY registry);
|
|
161
|
+
* 2. the registered fixture file exists and is readable;
|
|
162
|
+
* 3. the fixture parses successfully via the real parser;
|
|
163
|
+
* 4. the parsed document actually contains a node of that kind (proof the
|
|
164
|
+
* grammar was recognised, not just "didn't throw").
|
|
165
|
+
* Also flags a registry entry naming a grammar the parser no longer
|
|
166
|
+
* declares (a stale entry), so the registry cannot silently drift wider
|
|
167
|
+
* than the parser either.
|
|
168
|
+
*/
|
|
169
|
+
function findPositiveControlGaps(liveKinds, registry, readFixture, parsePlanningDocFn, artifactName) {
|
|
170
|
+
const violations = [];
|
|
171
|
+
|
|
172
|
+
for (const kind of liveKinds) {
|
|
173
|
+
const fixtureName = registry[kind];
|
|
174
|
+
if (!fixtureName) {
|
|
175
|
+
violations.push({
|
|
176
|
+
kind,
|
|
177
|
+
reason:
|
|
178
|
+
`parser declares grammar '${kind}' (NodeKind) but POSITIVE_CONTROL_REGISTRY has no entry for it — ` +
|
|
179
|
+
'add one and a matching fixture under tests/fixtures/planning-document/',
|
|
180
|
+
});
|
|
181
|
+
continue;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
const content = readFixture(fixtureName);
|
|
185
|
+
if (content == null) {
|
|
186
|
+
violations.push({
|
|
187
|
+
kind,
|
|
188
|
+
fixture: fixtureName,
|
|
189
|
+
reason: `fixture file not found or unreadable: ${path.join(FIXTURE_DIR, fixtureName)}`,
|
|
190
|
+
});
|
|
191
|
+
continue;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
const result = parsePlanningDocFn(content, artifactName);
|
|
195
|
+
if (!result.ok) {
|
|
196
|
+
violations.push({
|
|
197
|
+
kind,
|
|
198
|
+
fixture: fixtureName,
|
|
199
|
+
reason: `fixture failed to parse via parsePlanningDoc: ${result.reason}`,
|
|
200
|
+
});
|
|
201
|
+
continue;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
const hasKind = result.value.nodes.some((n) => n.kind === kind);
|
|
205
|
+
if (!hasKind) {
|
|
206
|
+
violations.push({
|
|
207
|
+
kind,
|
|
208
|
+
fixture: fixtureName,
|
|
209
|
+
reason: `fixture parsed successfully but produced no '${kind}' node — it does not actually exercise this grammar`,
|
|
210
|
+
});
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
for (const kind of Object.keys(registry)) {
|
|
215
|
+
if (!liveKinds.includes(kind)) {
|
|
216
|
+
violations.push({
|
|
217
|
+
kind,
|
|
218
|
+
fixture: registry[kind],
|
|
219
|
+
reason: `registry entry names grammar '${kind}', which is not in the parser's live NodeKind union — stale entry, remove it`,
|
|
220
|
+
});
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
return violations;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
/**
|
|
228
|
+
* Load the built seam and the real source/fixture tree rooted at `root`, and
|
|
229
|
+
* run `findPositiveControlGaps` against them. Returns the same shape as
|
|
230
|
+
* `findPositiveControlGaps`. If the seam hasn't been built yet, or the
|
|
231
|
+
* `NodeKind` union can't be located, reports a single actionable violation
|
|
232
|
+
* rather than throwing.
|
|
233
|
+
*
|
|
234
|
+
* `allowOverride` (default `false`) must be explicitly `true` for the
|
|
235
|
+
* test-only env-var registry override to be honored at all — see
|
|
236
|
+
* `resolveRegistry` and `TEST_REGISTRY_OVERRIDE_ENV_VAR`'s header comment.
|
|
237
|
+
*/
|
|
238
|
+
function scanRepo(root, env, allowOverride = false) {
|
|
239
|
+
const readFile = (relPath) => {
|
|
240
|
+
try {
|
|
241
|
+
return fs.readFileSync(path.join(root, relPath), 'utf8');
|
|
242
|
+
} catch {
|
|
243
|
+
return null;
|
|
244
|
+
}
|
|
245
|
+
};
|
|
246
|
+
const readFixture = (fileName) => readFile(path.join(FIXTURE_DIR, fileName));
|
|
247
|
+
|
|
248
|
+
const live = readLiveGrammarKinds(readFile);
|
|
249
|
+
if (!live.ok) {
|
|
250
|
+
return [{ kind: null, reason: live.reason }];
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
const libPath = path.join(root, PLANNING_DOCUMENT_LIB);
|
|
254
|
+
let seam;
|
|
255
|
+
try {
|
|
256
|
+
seam = require(libPath);
|
|
257
|
+
} catch (e) {
|
|
258
|
+
return [
|
|
259
|
+
{
|
|
260
|
+
kind: null,
|
|
261
|
+
reason: `cannot load the planning-document seam at ${path.relative(root, libPath)} — run 'npm run build:lib' first (${e.message})`,
|
|
262
|
+
},
|
|
263
|
+
];
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
const registry = resolveRegistry(env || process.env, allowOverride);
|
|
267
|
+
return findPositiveControlGaps(live.value, registry, readFixture, seam.parsePlanningDoc, FIXTURE_ARTIFACT_NAME);
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
/** Parse a bare `--root <path>` CLI override (defaults to the real repo root)
|
|
271
|
+
* and the `--test-registry-override` flag that gates `resolveRegistry`'s
|
|
272
|
+
* env-var override (see `TEST_REGISTRY_OVERRIDE_CLI_FLAG`'s header comment).
|
|
273
|
+
* No real invocation (`npm run lint:ci`, `npm run lint:planning-document-
|
|
274
|
+
* positive-control`) ever passes this flag. */
|
|
275
|
+
function parseArgs(argv) {
|
|
276
|
+
let root = path.join(__dirname, '..');
|
|
277
|
+
let allowTestRegistryOverride = false;
|
|
278
|
+
for (let i = 0; i < argv.length; i++) {
|
|
279
|
+
if (argv[i] === '--root' && argv[i + 1]) {
|
|
280
|
+
root = path.resolve(argv[i + 1]);
|
|
281
|
+
i += 1;
|
|
282
|
+
} else if (argv[i] === TEST_REGISTRY_OVERRIDE_CLI_FLAG) {
|
|
283
|
+
allowTestRegistryOverride = true;
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
return { root, allowTestRegistryOverride };
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
function main() {
|
|
290
|
+
const { root, allowTestRegistryOverride } = parseArgs(process.argv.slice(2));
|
|
291
|
+
const violations = scanRepo(root, process.env, allowTestRegistryOverride);
|
|
292
|
+
if (violations.length === 0) {
|
|
293
|
+
process.stdout.write(
|
|
294
|
+
'ok planning-document-positive-control: every declared PlanningDoc grammar has a passing positive-control fixture\n',
|
|
295
|
+
);
|
|
296
|
+
return;
|
|
297
|
+
}
|
|
298
|
+
process.stderr.write(
|
|
299
|
+
'planning-document-positive-control: PlanningDoc grammar(s) missing or failing a positive-control fixture (ADR-4910 §7).\n',
|
|
300
|
+
);
|
|
301
|
+
process.stderr.write(
|
|
302
|
+
'Add/fix a fixture under tests/fixtures/planning-document/ and register it in POSITIVE_CONTROL_REGISTRY in\n' +
|
|
303
|
+
'scripts/lint-planning-document-positive-control.cjs — each fixture must round-trip through parsePlanningDoc\n' +
|
|
304
|
+
'and yield a node of the declared kind.\n',
|
|
305
|
+
);
|
|
306
|
+
for (const v of violations) {
|
|
307
|
+
const id = v.kind ?? '?';
|
|
308
|
+
const loc = v.fixture ? ` (${path.join(FIXTURE_DIR, v.fixture)})` : '';
|
|
309
|
+
process.stderr.write(` ${id}${loc}: ${v.reason}\n`);
|
|
310
|
+
}
|
|
311
|
+
process.exitCode = 1;
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
if (require.main === module) main();
|
|
315
|
+
|
|
316
|
+
module.exports = {
|
|
317
|
+
findPositiveControlGaps,
|
|
318
|
+
readLiveGrammarKinds,
|
|
319
|
+
resolveRegistry,
|
|
320
|
+
scanRepo,
|
|
321
|
+
parseArgs,
|
|
322
|
+
POSITIVE_CONTROL_REGISTRY,
|
|
323
|
+
FIXTURE_ARTIFACT_NAME,
|
|
324
|
+
PLANNING_DOCUMENT_SRC,
|
|
325
|
+
PLANNING_DOCUMENT_LIB,
|
|
326
|
+
FIXTURE_DIR,
|
|
327
|
+
TEST_REGISTRY_OVERRIDE_ENV_VAR,
|
|
328
|
+
TEST_REGISTRY_OVERRIDE_CLI_FLAG,
|
|
329
|
+
};
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* PR-branch `.planning/` path-classification drift guard (ADR-4910 §8, epic
|
|
6
|
+
* #4906 Phase 5; issues #4605, #4606).
|
|
7
|
+
*
|
|
8
|
+
* `src/pr-branch-patterns.cts` (compiled to
|
|
9
|
+
* `gsd-core/bin/lib/pr-branch-patterns.cjs`) is the single-source-of-truth
|
|
10
|
+
* registry for the three `.planning/` path-classification values
|
|
11
|
+
* `gsd-core/workflows/pr-branch.md` needs: `TRANSIENT_DIRS_SRC`,
|
|
12
|
+
* `STRUCTURAL_RE_SRC`, and `MILESTONE_PHASES_RE_SRC`. A workflow markdown
|
|
13
|
+
* file has no module system — it cannot `require()` that `.cts` source at
|
|
14
|
+
* runtime — so its `create_pr_branch`/`verify` steps carry a hand-copied
|
|
15
|
+
* mirror of each value inside a `NAME="..."` bash assignment. This guard
|
|
16
|
+
* asserts each mirror still matches its canonical value VERBATIM, so the two
|
|
17
|
+
* copies can never silently drift apart (the exact bug class ADR-2143 §3
|
|
18
|
+
* names for markdown-mirrored source-of-truth values, applied here to a
|
|
19
|
+
* bash-variable mirror instead of a pipe-table header).
|
|
20
|
+
*
|
|
21
|
+
* Modeled directly on `scripts/lint-table-schema-drift.cjs`: a standalone
|
|
22
|
+
* node script (not a node:test), pure detector function + `scanRepo` seam,
|
|
23
|
+
* wired into `lint:ci`, exit 0 clean / exit 1 + message on drift.
|
|
24
|
+
*/
|
|
25
|
+
|
|
26
|
+
const fs = require('node:fs');
|
|
27
|
+
const path = require('node:path');
|
|
28
|
+
|
|
29
|
+
// Canonical-source-constant name -> the exact bash variable name it mirrors
|
|
30
|
+
// inside gsd-core/workflows/pr-branch.md.
|
|
31
|
+
const PATTERN_VARS = {
|
|
32
|
+
TRANSIENT_DIRS_SRC: 'TRANSIENT_DIRS',
|
|
33
|
+
STRUCTURAL_RE_SRC: 'STRUCTURAL_RE',
|
|
34
|
+
MILESTONE_PHASES_RE_SRC: 'MILESTONE_PHASES_RE',
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
const WORKFLOW_REL_PATH = path.join('gsd-core', 'workflows', 'pr-branch.md');
|
|
38
|
+
|
|
39
|
+
/** Build the exact `NAME="value"` bash assignment line for one pattern. */
|
|
40
|
+
function buildAssignment(bashVar, value) {
|
|
41
|
+
return `${bashVar}="${value}"`;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Pure: given `patterns` (a `{ SRC_CONST_NAME: value }` map, shaped like the
|
|
46
|
+
* `pr-branch-patterns.cjs` seam) and a `readFile(relPath) -> string|null`
|
|
47
|
+
* accessor, find every pattern whose exact `NAME="value"` assignment does
|
|
48
|
+
* not appear verbatim in the canonical workflow file. Returns
|
|
49
|
+
* `[{ constName, bashVar, expected, reason }]`; empty when clean.
|
|
50
|
+
*/
|
|
51
|
+
function findPrBranchPatternDrift(patterns, readFile, vars = PATTERN_VARS, workflowPath = WORKFLOW_REL_PATH) {
|
|
52
|
+
const violations = [];
|
|
53
|
+
const content = readFile(workflowPath);
|
|
54
|
+
|
|
55
|
+
for (const [constName, bashVar] of Object.entries(vars)) {
|
|
56
|
+
const value = patterns[constName];
|
|
57
|
+
if (typeof value !== 'string') {
|
|
58
|
+
violations.push({
|
|
59
|
+
constName,
|
|
60
|
+
bashVar,
|
|
61
|
+
expected: null,
|
|
62
|
+
reason: `${constName} missing or not a string in the pr-branch-patterns seam`,
|
|
63
|
+
});
|
|
64
|
+
continue;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
if (content == null) {
|
|
68
|
+
violations.push({
|
|
69
|
+
constName,
|
|
70
|
+
bashVar,
|
|
71
|
+
expected: buildAssignment(bashVar, value),
|
|
72
|
+
reason: 'source file not found or unreadable',
|
|
73
|
+
});
|
|
74
|
+
continue;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const expected = buildAssignment(bashVar, value);
|
|
78
|
+
if (!content.includes(expected)) {
|
|
79
|
+
violations.push({
|
|
80
|
+
constName,
|
|
81
|
+
bashVar,
|
|
82
|
+
expected,
|
|
83
|
+
reason: 'assignment not found verbatim in canonical workflow file',
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
return violations;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Load the built seam and scan the real repo tree. Returns the same shape as
|
|
92
|
+
* `findPrBranchPatternDrift`. If the seam hasn't been built yet (`npm run
|
|
93
|
+
* build:lib`), reports a single actionable violation rather than throwing.
|
|
94
|
+
*/
|
|
95
|
+
function scanRepo(root) {
|
|
96
|
+
const seamPath = path.join(root, 'gsd-core', 'bin', 'lib', 'pr-branch-patterns.cjs');
|
|
97
|
+
let seam;
|
|
98
|
+
try {
|
|
99
|
+
seam = require(seamPath);
|
|
100
|
+
} catch (e) {
|
|
101
|
+
return [{
|
|
102
|
+
constName: null,
|
|
103
|
+
bashVar: null,
|
|
104
|
+
expected: null,
|
|
105
|
+
reason: `cannot load the pr-branch-patterns seam at ${path.relative(root, seamPath)} — run 'npm run build:lib' first (${e.message})`,
|
|
106
|
+
}];
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
const readFile = (relPath) => {
|
|
110
|
+
try {
|
|
111
|
+
return fs.readFileSync(path.join(root, relPath), 'utf8');
|
|
112
|
+
} catch {
|
|
113
|
+
return null;
|
|
114
|
+
}
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
return findPrBranchPatternDrift(seam, readFile);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
function main() {
|
|
121
|
+
const root = path.join(__dirname, '..');
|
|
122
|
+
const violations = scanRepo(root);
|
|
123
|
+
if (violations.length === 0) {
|
|
124
|
+
process.stdout.write(
|
|
125
|
+
'ok pr-branch-pattern-drift: every pr-branch-patterns.cts constant appears verbatim in gsd-core/workflows/pr-branch.md\n',
|
|
126
|
+
);
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
process.stderr.write(
|
|
130
|
+
'pr-branch-pattern-drift: pr-branch-patterns.cts constant(s) whose assignment is absent from gsd-core/workflows/pr-branch.md (ADR-4910 §8, #4605).\n',
|
|
131
|
+
);
|
|
132
|
+
process.stderr.write(
|
|
133
|
+
'Either update gsd-core/workflows/pr-branch.md to mirror the canonical value verbatim, or update\n'
|
|
134
|
+
+ 'src/pr-branch-patterns.cts to match — the two must never drift.\n',
|
|
135
|
+
);
|
|
136
|
+
for (const v of violations) {
|
|
137
|
+
const id = v.bashVar ? `${v.constName} (${v.bashVar})` : (v.constName ?? '?');
|
|
138
|
+
const expected = v.expected ? ` — expected ${JSON.stringify(v.expected)}` : '';
|
|
139
|
+
process.stderr.write(` ${id}: ${v.reason}${expected}\n`);
|
|
140
|
+
}
|
|
141
|
+
process.exitCode = 1;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
if (require.main === module) main();
|
|
145
|
+
|
|
146
|
+
module.exports = {
|
|
147
|
+
findPrBranchPatternDrift, scanRepo, buildAssignment, PATTERN_VARS, WORKFLOW_REL_PATH,
|
|
148
|
+
};
|
|
@@ -78,7 +78,10 @@ const EXACT_INLINE_DIRECTIVE_WORKFLOWS = new Set([
|
|
|
78
78
|
'discuss-phase/modes/text.md',
|
|
79
79
|
'discuss-phase/templates/context.md',
|
|
80
80
|
'discuss-phase/templates/discussion-log.md',
|
|
81
|
+
'execute-phase/steps/code-review-disposition.md',
|
|
81
82
|
'execute-phase/steps/codebase-drift-gate.md',
|
|
83
|
+
'execute-phase/steps/gap-closure-artifacts.md',
|
|
84
|
+
'execute-phase/steps/regression-gate.md',
|
|
82
85
|
'execute-phase/steps/regression-gate-run.md',
|
|
83
86
|
'execute-phase/steps/worktree-recovery-policy.md',
|
|
84
87
|
'help/modes/brief.md',
|