@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,257 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* lint-phase-arg-assignment.cjs — a workflow that READS `${PHASE_ARG}` must
|
|
6
|
+
* also SAY where it comes from (#4777).
|
|
7
|
+
*
|
|
8
|
+
* ## Why
|
|
9
|
+
*
|
|
10
|
+
* Seven workflows shipped an `init.phase-op "${PHASE_ARG}"` call with no
|
|
11
|
+
* assignment anywhere in the file and no instruction to derive one. The
|
|
12
|
+
* variable expanded to the empty string on every run, `init.phase-op ""`
|
|
13
|
+
* resolved `phase_found: false` unconditionally, and each workflow fell
|
|
14
|
+
* through to its own "phase not executed" exit with a blank phase number —
|
|
15
|
+
* so `/gsd:secure-phase 4` reported that phase *nothing* was not executed.
|
|
16
|
+
* Two of them had carried the defect since the files were created in March.
|
|
17
|
+
*
|
|
18
|
+
* Nothing caught it because the working pattern lived in a *different* file:
|
|
19
|
+
* `verify-work.md` derives the value correctly, and a copy of an init block
|
|
20
|
+
* that leaves the derivation line behind is indistinguishable, on review,
|
|
21
|
+
* from one that never needed it.
|
|
22
|
+
*
|
|
23
|
+
* ## The rule
|
|
24
|
+
*
|
|
25
|
+
* A workflow whose bash blocks read `$PHASE_ARG` must carry one of:
|
|
26
|
+
*
|
|
27
|
+
* 1. a **shell assignment** matching one of the frozen `CANONICAL_FORMS`
|
|
28
|
+
* below, textually before the first read; or
|
|
29
|
+
* 2. a **prose derivation step** — a line outside the bash blocks that
|
|
30
|
+
* tells the model to parse `$ARGUMENTS` into `$PHASE_ARG`
|
|
31
|
+
* (`execute-phase.md`: "First positional token → `PHASE_ARG`"); or
|
|
32
|
+
* 3. an entry in `EXEMPT`, with a reason.
|
|
33
|
+
*
|
|
34
|
+
* ## Why the forms are frozen
|
|
35
|
+
*
|
|
36
|
+
* Requiring *an* assignment would be satisfied by a seventh hand-rolled sed
|
|
37
|
+
* pipeline, which is how the two grammars in this tree already drifted apart.
|
|
38
|
+
* The rule therefore pins the exact text. There are three legitimate ways a
|
|
39
|
+
* workflow learns its phase — `$ARGUMENTS` positional, `--phase N`, and a
|
|
40
|
+
* positional `$1` passed by a skill dispatch — and each has exactly one
|
|
41
|
+
* spelling. A new grammar is a deliberate one-line addition here, reviewed
|
|
42
|
+
* once, rather than a copy that diverges silently.
|
|
43
|
+
*
|
|
44
|
+
* Detection only: this lint never edits a workflow.
|
|
45
|
+
*/
|
|
46
|
+
|
|
47
|
+
const fs = require('fs');
|
|
48
|
+
const path = require('path');
|
|
49
|
+
const { ExitError, runMain } = require('./lib/cli-exit.cjs');
|
|
50
|
+
|
|
51
|
+
const ROOT = path.resolve(__dirname, '..');
|
|
52
|
+
const DEFAULT_ROOT = path.join(ROOT, 'gsd-core', 'workflows');
|
|
53
|
+
const SECTIONIZER_PATH = path.join(ROOT, 'gsd-core', 'bin', 'lib', 'markdown-sectionizer.cjs');
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Fenced-block extraction goes through the Markdown Sectionizer seam
|
|
57
|
+
* (ADR-1372) rather than a local fence regex — `local/no-adhoc-markdown-parsing`
|
|
58
|
+
* enforces that, and it is right to: a `~~~` block, an indented fence, or a
|
|
59
|
+
* nested fence inside another would each be misread by a hand-rolled pattern,
|
|
60
|
+
* and this rule's whole job is to know which lines are shell.
|
|
61
|
+
*/
|
|
62
|
+
function loadSectionizer() {
|
|
63
|
+
try {
|
|
64
|
+
return require(SECTIONIZER_PATH);
|
|
65
|
+
} catch (e) {
|
|
66
|
+
throw new ExitError(
|
|
67
|
+
1,
|
|
68
|
+
'lint-phase-arg-assignment: cannot load the markdown-sectionizer seam at ' +
|
|
69
|
+
`${path.relative(ROOT, SECTIONIZER_PATH)} — run 'npm run build:lib' first (${e.message})`,
|
|
70
|
+
);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const SHELL_INFO_STRINGS = new Set(['bash', 'sh', 'shell']);
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* The only accepted spellings of a PHASE_ARG assignment, keyed by grammar.
|
|
78
|
+
* Compared after collapsing runs of whitespace, so indentation inside a
|
|
79
|
+
* block is free but the pipeline itself is not.
|
|
80
|
+
*
|
|
81
|
+
* Known limitation (#4777 review): neither `positional` nor `phaseFlag`
|
|
82
|
+
* strips a surrounding quote — `positional('4 --ws "my team"')` leaves
|
|
83
|
+
* `--ws`/`my`/`team` tokens in PHASE_ARG instead of stripping the flag, and
|
|
84
|
+
* `phaseFlag('--phase "4"')` yields an empty PHASE_ARG, reproducing this
|
|
85
|
+
* issue's own defect for that input shape. Every `argument-hint` in the
|
|
86
|
+
* repo documents unquoted usage as primary, and `positional` is copied
|
|
87
|
+
* verbatim from verify-work.md's pre-existing shipped form rather than
|
|
88
|
+
* "improved" here — hardening the regex would mean changing production
|
|
89
|
+
* bash text in all 7 shipped workflows this exact-match check compares
|
|
90
|
+
* against. See tests/lint-phase-arg-assignment.test.cjs's dedicated
|
|
91
|
+
* describe block for a live repro.
|
|
92
|
+
*/
|
|
93
|
+
const CANONICAL_FORMS = Object.freeze({
|
|
94
|
+
/** `/gsd:secure-phase 4` — the phase is the whole argument string, minus a `--ws <name>` pair. */
|
|
95
|
+
positional:
|
|
96
|
+
'PHASE_ARG=$(echo "$ARGUMENTS" | sed -E \'s/--ws[[:space:]]+[A-Za-z0-9._-]+//g\' | xargs)',
|
|
97
|
+
/** `/gsd:review --phase 4 --codex` — the phase is the value of a named flag. */
|
|
98
|
+
phaseFlag:
|
|
99
|
+
'PHASE_ARG=$(echo "$ARGUMENTS" | sed -nE \'s/.*--phase[[:space:]]+([A-Za-z0-9._-]+).*/\\1/p\')',
|
|
100
|
+
/** Skill dispatch passes the phase as `$1` (`Skill(skill="gsd-code-review", args="4")`). */
|
|
101
|
+
firstPositional: 'PHASE_ARG="${1}"',
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Files that read `$PHASE_ARG` and legitimately do not assign it. Each entry
|
|
106
|
+
* is checked for staleness: one whose file stopped reading the variable, or
|
|
107
|
+
* started assigning it, fails just as loudly as a missing assignment — an
|
|
108
|
+
* exemption nobody can remove is how a list like this becomes a place to
|
|
109
|
+
* hide the next defect.
|
|
110
|
+
*/
|
|
111
|
+
const EXEMPT = new Map([
|
|
112
|
+
[
|
|
113
|
+
'code-review/steps/dispatch-fix.md',
|
|
114
|
+
'step fragment of code-review.md, which assigns PHASE_ARG="${1}" before dispatching it',
|
|
115
|
+
],
|
|
116
|
+
]);
|
|
117
|
+
|
|
118
|
+
const READ_RE = /\$\{?PHASE_ARG\b/;
|
|
119
|
+
const ASSIGN_RE = /^[ \t]*PHASE_ARG=(?!=).*$/gm;
|
|
120
|
+
/**
|
|
121
|
+
* A prose derivation step: a non-bash line that routes `$ARGUMENTS` into
|
|
122
|
+
* `PHASE_ARG`. Matches both shapes in the tree — an arrow ("First positional
|
|
123
|
+
* token → `PHASE_ARG`") and a "store as `$PHASE_ARG`" instruction.
|
|
124
|
+
*/
|
|
125
|
+
const PROSE_ASSIGN_RE = /(?:→|->|store as)\s*`?\$?\{?PHASE_ARG/;
|
|
126
|
+
|
|
127
|
+
/** Collapse whitespace runs so indentation does not decide the verdict. */
|
|
128
|
+
function normalize(line) {
|
|
129
|
+
return line.trim().replace(/\s+/g, ' ');
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
const CANONICAL_SET = new Set(Object.values(CANONICAL_FORMS).map(normalize));
|
|
133
|
+
|
|
134
|
+
/** Every `*.md` under `dir`, recursively, as paths relative to `dir`. */
|
|
135
|
+
function collectWorkflows(dir) {
|
|
136
|
+
const out = [];
|
|
137
|
+
const walk = (current, prefix) => {
|
|
138
|
+
for (const entry of fs.readdirSync(current, { withFileTypes: true })) {
|
|
139
|
+
const abs = path.join(current, entry.name);
|
|
140
|
+
const rel = prefix ? `${prefix}/${entry.name}` : entry.name;
|
|
141
|
+
if (entry.isDirectory()) walk(abs, rel);
|
|
142
|
+
else if (entry.isFile() && entry.name.endsWith('.md')) out.push(rel);
|
|
143
|
+
}
|
|
144
|
+
};
|
|
145
|
+
walk(dir, '');
|
|
146
|
+
return out.sort();
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Classify one workflow's PHASE_ARG handling.
|
|
151
|
+
*
|
|
152
|
+
* `reads` counts bash-block reads only: `${PHASE_ARG}` inside prose is a
|
|
153
|
+
* mention (an error message being described, an example invocation), not a
|
|
154
|
+
* consumption, and requiring an assignment for those would make the rule fire
|
|
155
|
+
* on documentation.
|
|
156
|
+
*/
|
|
157
|
+
function inspect(text, sectionizer = loadSectionizer()) {
|
|
158
|
+
const lines = text.split('\n');
|
|
159
|
+
const shell = sectionizer
|
|
160
|
+
.scanFencedBlocks(lines)
|
|
161
|
+
.filter((b) => SHELL_INFO_STRINGS.has(b.infoString.trim().split(/\s+/)[0]))
|
|
162
|
+
// closeLineIdx === -1 marks an unterminated fence: take the rest of the
|
|
163
|
+
// file rather than dropping the block, so a workflow whose last fence is
|
|
164
|
+
// missing its closer is still scanned instead of silently exempted.
|
|
165
|
+
.map((b) => lines.slice(b.openLineIdx + 1, b.closeLineIdx === -1 ? lines.length : b.closeLineIdx).join('\n'))
|
|
166
|
+
.join('\n');
|
|
167
|
+
|
|
168
|
+
const assignments = [...shell.matchAll(ASSIGN_RE)].map((m) => m[0]);
|
|
169
|
+
const firstAssignIdx = shell.search(/^[ \t]*PHASE_ARG=(?!=)/m);
|
|
170
|
+
const firstReadIdx = shell.search(READ_RE);
|
|
171
|
+
|
|
172
|
+
// The prose search deliberately runs over the WHOLE file rather than the
|
|
173
|
+
// non-bash remainder: a derivation step is a prose line, and stripping
|
|
174
|
+
// blocks first would only add a way for the two to disagree.
|
|
175
|
+
const hasProse = text.split('\n').some((line) => PROSE_ASSIGN_RE.test(line));
|
|
176
|
+
|
|
177
|
+
return {
|
|
178
|
+
reads: firstReadIdx !== -1,
|
|
179
|
+
assignments,
|
|
180
|
+
nonCanonical: assignments.filter((a) => !CANONICAL_SET.has(normalize(a))),
|
|
181
|
+
// An assignment that lands after the first read is the same defect with
|
|
182
|
+
// extra steps — the read still expands to nothing.
|
|
183
|
+
assignsBeforeRead: firstAssignIdx !== -1 && firstReadIdx !== -1 && firstAssignIdx <= firstReadIdx,
|
|
184
|
+
hasProse,
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
/** Scan a workflows directory. Returns `{ scanned, violations, staleExemptions }`. */
|
|
189
|
+
function scan(rootDir = DEFAULT_ROOT, exempt = EXEMPT) {
|
|
190
|
+
const violations = [];
|
|
191
|
+
const seenExempt = new Set();
|
|
192
|
+
const sectionizer = loadSectionizer();
|
|
193
|
+
let scanned = 0;
|
|
194
|
+
|
|
195
|
+
for (const rel of collectWorkflows(rootDir)) {
|
|
196
|
+
const report = inspect(fs.readFileSync(path.join(rootDir, rel), 'utf8'), sectionizer);
|
|
197
|
+
if (!report.reads && report.assignments.length === 0) continue;
|
|
198
|
+
scanned += 1;
|
|
199
|
+
|
|
200
|
+
// Decide the verdict FIRST, then consult the exemption list. Marking an
|
|
201
|
+
// entry used before knowing whether the file would actually fail lets an
|
|
202
|
+
// exemption outlive its reason: the file gets fixed, the entry stays, and
|
|
203
|
+
// it silently pre-forgives the NEXT unassigned read in that same file.
|
|
204
|
+
let violation = null;
|
|
205
|
+
if (report.nonCanonical.length > 0) {
|
|
206
|
+
violation = { file: rel, kind: 'non-canonical', detail: normalize(report.nonCanonical[0]) };
|
|
207
|
+
} else if (!report.reads) {
|
|
208
|
+
violation = null;
|
|
209
|
+
} else if (report.assignments.length === 0 && !report.hasProse) {
|
|
210
|
+
violation = { file: rel, kind: 'unassigned', detail: 'reads ${PHASE_ARG} with no assignment and no derivation step' };
|
|
211
|
+
} else if (report.assignments.length > 0 && !report.assignsBeforeRead) {
|
|
212
|
+
violation = { file: rel, kind: 'late-assignment', detail: 'PHASE_ARG is assigned after its first use' };
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
if (!violation) continue;
|
|
216
|
+
if (exempt.has(rel)) { seenExempt.add(rel); continue; }
|
|
217
|
+
violations.push(violation);
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
const staleExemptions = [...exempt.keys()]
|
|
221
|
+
.filter((rel) => !seenExempt.has(rel))
|
|
222
|
+
.map((rel) => ({ file: rel, reason: exempt.get(rel) }));
|
|
223
|
+
|
|
224
|
+
return { scanned, violations, staleExemptions };
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
function main() {
|
|
228
|
+
const { scanned, violations, staleExemptions } = scan();
|
|
229
|
+
const parts = [];
|
|
230
|
+
|
|
231
|
+
if (violations.length > 0) {
|
|
232
|
+
parts.push(
|
|
233
|
+
'lint-phase-arg-assignment: these workflows do not say where ${PHASE_ARG} comes from (#4777).\n' +
|
|
234
|
+
'An unassigned PHASE_ARG expands to the empty string, init.phase-op resolves\n' +
|
|
235
|
+
'phase_found:false for every invocation, and the workflow exits reporting that a blank\n' +
|
|
236
|
+
'phase was not executed. Add one of the canonical forms in this script — or, for a model-\n' +
|
|
237
|
+
'derived value, a prose derivation step — before the first read:\n' +
|
|
238
|
+
violations.map((v) => ` gsd-core/workflows/${v.file} [${v.kind}] ${v.detail}`).join('\n'),
|
|
239
|
+
);
|
|
240
|
+
}
|
|
241
|
+
if (staleExemptions.length > 0) {
|
|
242
|
+
parts.push(
|
|
243
|
+
'lint-phase-arg-assignment: these EXEMPT entries are stale — delete them so the next\n' +
|
|
244
|
+
'unassigned read in those files is caught rather than silently pre-forgiven:\n' +
|
|
245
|
+
staleExemptions.map((s) => ` ${s.file}: ${s.reason}`).join('\n'),
|
|
246
|
+
);
|
|
247
|
+
}
|
|
248
|
+
if (parts.length > 0) throw new ExitError(1, parts.join('\n\n'));
|
|
249
|
+
|
|
250
|
+
console.log(
|
|
251
|
+
`ok lint-phase-arg-assignment: ${scanned} workflow(s) checked, ${EXEMPT.size} exemption(s) all still needed`,
|
|
252
|
+
);
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
module.exports = { CANONICAL_FORMS, EXEMPT, DEFAULT_ROOT, inspect, scan };
|
|
256
|
+
|
|
257
|
+
if (require.main === module) runMain(main);
|
|
@@ -84,13 +84,16 @@
|
|
|
84
84
|
* shape as `collectDiskPhases` and the `audit.cts` scanners; it must see
|
|
85
85
|
* every phase directory regardless of milestone window to catch a
|
|
86
86
|
* naming/duplicate defect wherever it lives.
|
|
87
|
-
* - `src/
|
|
88
|
-
* `phase` argument to its directory (falling back to an
|
|
89
|
-
* match) — a single-phase LOOKUP, not a current-milestone
|
|
90
|
-
* Originally `cmdVerifySchemaDrift`'s own inline block;
|
|
91
|
-
* into this shared helper (also used by the
|
|
92
|
-
* without changing what question it asks, so the exemption moved
|
|
93
|
-
* the call site rather than multiplying.
|
|
87
|
+
* - `src/gate-phase-context.cts` `resolvePhaseDirByToken`: resolves ONE
|
|
88
|
+
* caller-supplied `phase` argument to its directory (falling back to an
|
|
89
|
+
* exact-name match) — a single-phase LOOKUP, not a current-milestone
|
|
90
|
+
* enumeration. Originally `cmdVerifySchemaDrift`'s own inline block;
|
|
91
|
+
* #3348 lifted it into this shared helper (also used by the context-drift
|
|
92
|
+
* check) without changing what question it asks, so the exemption moved
|
|
93
|
+
* with the call site rather than multiplying. #5219 (ADR-5057 §4) moved
|
|
94
|
+
* both checks into gate modules and the helper beside `resolvePhaseDir`
|
|
95
|
+
* in the gate phase-context module (it is not `resolvePhaseDir`: it
|
|
96
|
+
* lists ONE given phases directory and nothing else).
|
|
94
97
|
* - `src/init.cts` `detectHasPriorPhases`: answers "has this project EVER
|
|
95
98
|
* completed a phase", explicitly excluding the current one. A history
|
|
96
99
|
* probe across all milestones, not a current-milestone enumeration.
|
|
@@ -309,7 +312,8 @@ const OWNER_FILES = new Set([
|
|
|
309
312
|
// `lint-milestone-window-drift.cjs`'s FUNCTION_SCOPED_EXEMPTIONS mechanism.
|
|
310
313
|
// See the header comment for the full written reason behind each entry.
|
|
311
314
|
const FUNCTION_SCOPED_EXEMPTIONS = new Map([
|
|
312
|
-
[path.join('src', 'verify.cts'), new Set(['cmdValidateHealth'
|
|
315
|
+
[path.join('src', 'verify.cts'), new Set(['cmdValidateHealth'])],
|
|
316
|
+
[path.join('src', 'gate-phase-context.cts'), new Set(['resolvePhaseDirByToken'])],
|
|
313
317
|
[path.join('src', 'init.cts'), new Set(['detectHasPriorPhases', 'detectUiPhaseActive'])],
|
|
314
318
|
[path.join('src', 'milestone.cts'), new Set(['archivePhaseDirectories', 'cmdMilestoneComplete', 'cmdPhasesClear'])],
|
|
315
319
|
// #3849: collectSiblingWorktreePhaseNums reads a SIBLING worktree's phases dir —
|