@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
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
@~/.claude/gsd-core/references/response-language-directive.md
|
|
2
2
|
|
|
3
3
|
<purpose>
|
|
4
|
-
Review source files changed during a phase for bugs, security issues, and code quality problems. Computes file scope (--files override > SUMMARY.md >
|
|
4
|
+
Review source files changed during a phase for bugs, security issues, and code quality problems. Computes file scope (--files override > SUMMARY.md > phase evaluation scope), checks config gate, spawns gsd-code-reviewer agent, commits REVIEW.md, and presents results to user. When --fix is passed, delegates to code-review-fix.md after review to auto-apply findings via gsd-code-fixer.
|
|
5
5
|
</purpose>
|
|
6
6
|
|
|
7
7
|
<required_reading>
|
|
@@ -19,7 +19,7 @@ Read all files referenced by the invoking prompt's execution_context before star
|
|
|
19
19
|
Parse arguments and load project state:
|
|
20
20
|
|
|
21
21
|
```bash
|
|
22
|
-
_GSD_SHIM_NAME="gsd-tools.cjs"; _GSD_RUNTIME_ROOT="${RUNTIME_DIR:-$(git rev-parse --show-toplevel 2>/dev/null || pwd)}"; GSD_TOOLS="${_GSD_RUNTIME_ROOT}/gsd-core/bin/${_GSD_SHIM_NAME}"; _gsd_at() { for _p; do if [ -f "$_p" ]; then GSD_TOOLS="$_p"; return 0; fi; done; return 1; };
|
|
22
|
+
_GSD_SHIM_NAME="gsd-tools.cjs"; _GSD_RUNTIME_ROOT="${RUNTIME_DIR:-$(git rev-parse --show-toplevel 2>/dev/null || pwd)}"; GSD_TOOLS="${_GSD_RUNTIME_ROOT}/gsd-core/bin/${_GSD_SHIM_NAME}"; _gsd_at() { for _p; do if [ -f "$_p" ]; then GSD_TOOLS="$_p"; return 0; fi; done; return 1; }; _gsd_id_ok() { case "$("$1" runtime-identity --raw 2>/dev/null || true)" in '{"packageName":"@opengsd/gsd-core"'*'}') return 0;; *) return 1;; esac; }; _gsd_homes() { set -- "${CLAUDE_CONFIG_DIR:-$HOME/.claude}" "${ANTIGRAVITY_CONFIG_DIR:-$HOME/.gemini/antigravity}" "$HOME/.gemini/antigravity-ide" "$HOME/.gemini/antigravity-cli" "${AUGMENT_CONFIG_DIR:-$HOME/.augment}" "${CLINE_CONFIG_DIR:-$HOME/.cline}" "${CODEBUDDY_CONFIG_DIR:-$HOME/.codebuddy}" "${CODEX_HOME:-$HOME/.codex}" "${COPILOT_CONFIG_DIR:-${COPILOT_HOME:-$HOME/.copilot}}" "${CURSOR_CONFIG_DIR:-$HOME/.cursor}" "${HERMES_HOME:-$HOME/.hermes}" "${KILO_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/kilo}" "${KIMI_CONFIG_DIR:-$HOME/.config/agents}" "$HOME/.agents" "${KIMI_CODE_HOME:-$HOME/.kimi-code}" "${OPENCODE_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/opencode}" "${PI_CODING_AGENT_DIR:-$HOME/.pi/agent}" "${QWEN_CONFIG_DIR:-$HOME/.qwen}" "${TRAE_CONFIG_DIR:-$HOME/.trae}" "${WINDSURF_CONFIG_DIR:-$HOME/.codeium/windsurf}" "${ZCODE_CONFIG_DIR:-$HOME/.zcode}" "${GROK_AGENTS_HOME:-$HOME/.agents}"; for _h; do _gsd_at "$_h/gsd-core/bin/${_GSD_SHIM_NAME}" && return 0; done; return 1; }; if _gsd_at "${_GSD_RUNTIME_ROOT}/gsd-core/bin/${_GSD_SHIM_NAME}" "${_GSD_RUNTIME_ROOT}/.claude/gsd-core/bin/${_GSD_SHIM_NAME}" "${_GSD_RUNTIME_ROOT}/.codex/gsd-core/bin/${_GSD_SHIM_NAME}"; then gsd_run() { node "$GSD_TOOLS" "$@"; }; elif _gsd_homes; then gsd_run() { node "$GSD_TOOLS" "$@"; }; elif unset -f gsd_run; _G="$(command -v gsd_run)"; [ -n "$_G" ] && _gsd_id_ok "$_G"; then GSD_TOOLS="$_G"; gsd_run() { "$GSD_TOOLS" "$@"; }; else echo "ERROR: gsd-tools.cjs not found at $GSD_TOOLS and no identity-proving gsd_run is on PATH. Run: npx -y @opengsd/gsd-core@latest --claude --local" >&2; exit 1; fi; GSD_IDENTITY_STATUS=unverified; _gsd_id_ok gsd_run && GSD_IDENTITY_STATUS=ok; export GSD_IDENTITY_STATUS; [ "$GSD_IDENTITY_STATUS" = ok ] || echo "WARNING: \"$GSD_TOOLS\" did not prove it is @opengsd/gsd-core - it is either a different package or an @opengsd/gsd-core older than the runtime-identity verb. See docs/how-to/diagnose-a-foreign-gsd-tools.md" >&2; if [ -n "${CLAUDE_ENV_FILE:-}" ] && [ -n "${GSD_TOOLS:-}" ]; then printf "export PATH='%s':\"\$PATH\"\n" "${GSD_TOOLS%/*}" >> "$CLAUDE_ENV_FILE" 2>/dev/null || true; fi
|
|
23
23
|
PHASE_ARG="${1}"
|
|
24
24
|
|
|
25
25
|
# Parse all code-review flags into a structured IR via code-review-flags.cjs.
|
|
@@ -47,9 +47,10 @@ FILES_OVERRIDE=$(echo "$FLAGS_JSON" | node -e "process.stdout.write(JSON.parse(r
|
|
|
47
47
|
FIX_PARAM=""
|
|
48
48
|
if [ "$FIX_FLAG" = "true" ]; then FIX_PARAM="--fix"; fi
|
|
49
49
|
|
|
50
|
-
|
|
50
|
+
GSD_WS=$(echo " $ARGUMENTS" | sed -nE 's/.* --ws +([A-Za-z0-9][A-Za-z0-9._-]*).*/--ws \1/p' | head -n 1)
|
|
51
|
+
INIT=$(gsd_run query init.code-review ${GSD_WS:+--ws=${GSD_WS##* }} "${PHASE_ARG}" $FIX_PARAM)
|
|
51
52
|
if [[ "$INIT" == @file:* ]]; then INIT=$(cat "${INIT#@file:}"); fi
|
|
52
|
-
AGENT_SKILLS_REVIEWER=$(gsd_run query agent-skills gsd-code-reviewer)
|
|
53
|
+
AGENT_SKILLS_REVIEWER=$(gsd_run query agent-skills gsd-code-reviewer ${GSD_WS:+--ws=${GSD_WS##* }})
|
|
53
54
|
# #2072: resolve the routed model so model_overrides / models.verification are honored
|
|
54
55
|
# (the resolver maps gsd-code-reviewer → phaseType "verification"); thread it below.
|
|
55
56
|
REVIEWER_MODEL=$(gsd_run query resolve-model gsd-code-reviewer --raw)
|
|
@@ -59,9 +60,10 @@ Parse from init JSON: `phase_found`, `phase_dir`, `phase_number`, `phase_name`,
|
|
|
59
60
|
|
|
60
61
|
**Input sanitization (defense-in-depth):**
|
|
61
62
|
```bash
|
|
62
|
-
# Validate PADDED_PHASE
|
|
63
|
-
|
|
64
|
-
|
|
63
|
+
# Validate PADDED_PHASE matches the canonical phase-number grammar (src/phase-id.cts): digits,
|
|
64
|
+
# an optional single uppercase letter, then dotted segments (e.g., "02", "03.1", "23.1.2", "12A")
|
|
65
|
+
if ! [[ "$PADDED_PHASE" =~ ^[0-9]+[A-Z]?(\.[0-9]+)*$ ]]; then
|
|
66
|
+
echo "Error: Invalid phase number format: '${PADDED_PHASE}'. Expected digits with an optional letter suffix (e.g., 02, 03.1, 23.1.2, 12A)."
|
|
65
67
|
# Exit workflow
|
|
66
68
|
fi
|
|
67
69
|
```
|
|
@@ -150,6 +152,49 @@ If --files NOT provided:
|
|
|
150
152
|
if [ -z "$FILES_OVERRIDE" ]; then
|
|
151
153
|
SUMMARIES=$(ls "${PHASE_DIR}"/*-SUMMARY.md 2>/dev/null)
|
|
152
154
|
REVIEW_FILES=()
|
|
155
|
+
|
|
156
|
+
# Keep the literal heredoc outside command substitution: Bash 3.2 (the
|
|
157
|
+
# system Bash on macOS) reparses heredoc bodies nested directly in $(...).
|
|
158
|
+
extract_summary_files() {
|
|
159
|
+
node - "$1" 2>/dev/null <<'NODE'
|
|
160
|
+
const fs = require('fs');
|
|
161
|
+
const content = fs.readFileSync(process.argv[2], 'utf-8');
|
|
162
|
+
const match = content.replace(/\r\n/g, '\n').match(/^---\n([\s\S]*?)\n---/);
|
|
163
|
+
if (!match) { process.exit(0); }
|
|
164
|
+
const yaml = match[1];
|
|
165
|
+
const files = [];
|
|
166
|
+
let inSection = null;
|
|
167
|
+
for (const line of yaml.split('\n')) {
|
|
168
|
+
if (/^\s+created:/.test(line)) { inSection = 'created'; continue; }
|
|
169
|
+
if (/^\s+modified:/.test(line)) { inSection = 'modified'; continue; }
|
|
170
|
+
if (/^\s*[\w-]+:/.test(line) && !/^\s*-/.test(line)) { inSection = null; continue; }
|
|
171
|
+
if (inSection && /^\s+-\s+(.+)/.test(line)) {
|
|
172
|
+
let raw = line.match(/^\s+-\s+(.+)/)[1].trim();
|
|
173
|
+
raw = raw.replace(/^['"]|['"]$/g, '');
|
|
174
|
+
raw = raw.replace(/\s+\([^)]*\)\s*$/, '');
|
|
175
|
+
raw = raw.split(/\s+—\s/)[0].trim();
|
|
176
|
+
// #2666: accept root-level paths (no `/`) and known extensionless build
|
|
177
|
+
// files, not only nested paths with a trailing extension. The pre-fix
|
|
178
|
+
// guard required BOTH a directory separator AND a trailing dot-extension,
|
|
179
|
+
// which silently dropped every repository-root file (Dockerfile,
|
|
180
|
+
// renovate.json, AGENTS.md, package.json, .gitlab-ci.yml, …) and every
|
|
181
|
+
// extensionless build file anywhere in the tree (**/Dockerfile, **/Makefile).
|
|
182
|
+
// Prose bullets are rejected by the known-filename / has-extension
|
|
183
|
+
// distinction, with the post-processing existence check (`[ -f ]`) as a
|
|
184
|
+
// backstop — a prose string is never a real file on disk.
|
|
185
|
+
const KNOWN_EXTENSIONLESS_BUILD_FILES = new Set([
|
|
186
|
+
'dockerfile', 'containerfile', 'makefile', 'justfile', 'procfile',
|
|
187
|
+
]);
|
|
188
|
+
const hasExtension = /\.[A-Za-z0-9]+$/.test(raw);
|
|
189
|
+
const basename = raw.split('/').pop().toLowerCase();
|
|
190
|
+
if (hasExtension || KNOWN_EXTENSIONLESS_BUILD_FILES.has(basename)) {
|
|
191
|
+
files.push(raw);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
if (files.length) console.log(files.join('\n'));
|
|
196
|
+
NODE
|
|
197
|
+
}
|
|
153
198
|
|
|
154
199
|
if [ -n "$SUMMARIES" ]; then
|
|
155
200
|
# Rewrapped through unquoted command substitution (gsd-core#4109): a bare
|
|
@@ -166,44 +211,7 @@ if [ -z "$FILES_OVERRIDE" ]; then
|
|
|
166
211
|
|
|
167
212
|
# Extract key_files.created and key_files.modified using node for reliable YAML parsing
|
|
168
213
|
# This avoids fragile awk parsing that breaks on indentation differences
|
|
169
|
-
EXTRACTED=$(
|
|
170
|
-
const fs = require('fs');
|
|
171
|
-
const content = fs.readFileSync('$summary', 'utf-8');
|
|
172
|
-
const match = content.replace(/\r\n/g, '\n').match(/^---\n([\s\S]*?)\n---/);
|
|
173
|
-
if (!match) { process.exit(0); }
|
|
174
|
-
const yaml = match[1];
|
|
175
|
-
const files = [];
|
|
176
|
-
let inSection = null;
|
|
177
|
-
for (const line of yaml.split('\n')) {
|
|
178
|
-
if (/^\s+created:/.test(line)) { inSection = 'created'; continue; }
|
|
179
|
-
if (/^\s+modified:/.test(line)) { inSection = 'modified'; continue; }
|
|
180
|
-
if (/^\s*[\w-]+:/.test(line) && !/^\s*-/.test(line)) { inSection = null; continue; }
|
|
181
|
-
if (inSection && /^\s+-\s+(.+)/.test(line)) {
|
|
182
|
-
let raw = line.match(/^\s+-\s+(.+)/)[1].trim();
|
|
183
|
-
raw = raw.replace(/^['"]|['"]$/g, '');
|
|
184
|
-
raw = raw.replace(/\s+\([^)]*\)\s*$/, '');
|
|
185
|
-
raw = raw.split(/\s+—\s/)[0].trim();
|
|
186
|
-
// #2666: accept root-level paths (no `/`) and known extensionless build
|
|
187
|
-
// files, not only nested paths with a trailing extension. The pre-fix
|
|
188
|
-
// guard required BOTH a directory separator AND a trailing dot-extension,
|
|
189
|
-
// which silently dropped every repository-root file (Dockerfile,
|
|
190
|
-
// renovate.json, AGENTS.md, package.json, .gitlab-ci.yml, …) and every
|
|
191
|
-
// extensionless build file anywhere in the tree (**/Dockerfile, **/Makefile).
|
|
192
|
-
// Prose bullets are rejected by the known-filename / has-extension
|
|
193
|
-
// distinction, with the post-processing existence check (`[ -f ]`) as a
|
|
194
|
-
// backstop — a prose string is never a real file on disk.
|
|
195
|
-
const KNOWN_EXTENSIONLESS_BUILD_FILES = new Set([
|
|
196
|
-
'dockerfile', 'containerfile', 'makefile', 'justfile', 'procfile',
|
|
197
|
-
]);
|
|
198
|
-
const hasExtension = /\.[A-Za-z0-9]+$/.test(raw);
|
|
199
|
-
const basename = raw.split('/').pop().toLowerCase();
|
|
200
|
-
if (hasExtension || KNOWN_EXTENSIONLESS_BUILD_FILES.has(basename)) {
|
|
201
|
-
files.push(raw);
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
if (files.length) console.log(files.join('\n'));
|
|
206
|
-
" 2>/dev/null)
|
|
214
|
+
EXTRACTED=$(extract_summary_files "$summary")
|
|
207
215
|
|
|
208
216
|
# Add extracted files to REVIEW_FILES array
|
|
209
217
|
if [ -n "$EXTRACTED" ]; then
|
|
@@ -216,116 +224,106 @@ if [ -z "$FILES_OVERRIDE" ]; then
|
|
|
216
224
|
done
|
|
217
225
|
|
|
218
226
|
if [ ${#REVIEW_FILES[@]} -eq 0 ]; then
|
|
219
|
-
echo "Warning: SUMMARY artifacts found but contained no file paths. Falling back to
|
|
227
|
+
echo "Warning: SUMMARY artifacts found but contained no file paths. Falling back to the phase evaluation scope."
|
|
220
228
|
fi
|
|
221
229
|
fi
|
|
222
230
|
fi
|
|
223
231
|
```
|
|
224
232
|
|
|
225
|
-
**Tier 3 —
|
|
226
|
-
|
|
227
|
-
If no SUMMARY.md files found OR no files extracted from them, fall back to the
|
|
228
|
-
Additionally, whenever
|
|
229
|
-
|
|
230
|
-
|
|
233
|
+
**Tier 3 — Phase evaluation scope (per D-02, #5164) and SUMMARY/scope cross-check (per #2666):**
|
|
234
|
+
|
|
235
|
+
If no SUMMARY.md files found OR no files extracted from them, fall back to the phase's evaluation scope.
|
|
236
|
+
Additionally, whenever the resolver returns a scope, cross-check the SUMMARY scope against it and warn
|
|
237
|
+
about (then add) any in-scope files the SUMMARY extractor did not surface — so a partial SUMMARY result
|
|
238
|
+
can no longer silently mask the rest of the phase.
|
|
239
|
+
|
|
240
|
+
The scope is computed by the ONE resolver, `check evaluation-scope` (ADR-5057 §4, #5164) — this step
|
|
241
|
+
derives no commit range of its own. The resolver returns the UNION of the phase's own commits' file
|
|
242
|
+
sets (the `## Task Commits` rows of the phase's SUMMARYs), restricted to commits reachable from `HEAD`
|
|
243
|
+
(a commit that lives only on another branch is named, never counted), with planning artifacts and
|
|
244
|
+
lockfiles excluded. A range (`base..HEAD`) is deliberately not used: it keeps every interleaved
|
|
245
|
+
non-phase commit in its window (#3926, #4563). The resolver also reports, by name rather than by
|
|
246
|
+
count, what the union dropped: `outsideUnion` (changed in the phase window by other commits) and
|
|
247
|
+
`unreachable` (task commits not on this branch). When the union is empty — a phase with no SUMMARY,
|
|
248
|
+
no task rows, or only planning paths — the resolver widens to the phase-directory range and says so
|
|
249
|
+
(`status: degraded`, `reason`); an unreadable phase or repository is `unresolvable`, never an empty
|
|
250
|
+
scope that reports success. Its `rangeBase` (the parent of the commit that first added the phase
|
|
251
|
+
directory, or `LAST_REVIEW_COMMIT` when a prior review exists — #3661) is `DIFF_BASE`, kept only for
|
|
252
|
+
the reviewer lanes that need an anchor sha.
|
|
231
253
|
```bash
|
|
232
|
-
#
|
|
233
|
-
#
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
#
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
if [ -n "$LAST_REVIEW_COMMIT" ]; then
|
|
265
|
-
# #3661: a prior review exists — narrow the diff base to since that review
|
|
266
|
-
# (wave-scoped) instead of the whole phase.
|
|
267
|
-
DIFF_BASE="$LAST_REVIEW_COMMIT"
|
|
268
|
-
elif [ -n "$PHASE_START" ]; then
|
|
269
|
-
if git rev-parse "${PHASE_START}^" >/dev/null 2>&1; then
|
|
270
|
-
DIFF_BASE="${PHASE_START}^"
|
|
271
|
-
else
|
|
272
|
-
DIFF_BASE="${PHASE_START}"
|
|
273
|
-
fi
|
|
254
|
+
# Exit 69 (UNAVAILABLE) is the resolver saying "could not look" (`status: unresolvable`): its JSON
|
|
255
|
+
# carries the reason and is kept. Any other non-zero status means the command did not run: no JSON.
|
|
256
|
+
SCOPE_RC=0
|
|
257
|
+
SCOPE_JSON=$(gsd_run check evaluation-scope --phase "${PADDED_PHASE}" ${LAST_REVIEW_COMMIT:+--since "$LAST_REVIEW_COMMIT"} --raw 2>/dev/null) || SCOPE_RC=$?
|
|
258
|
+
if [ "$SCOPE_RC" -ne 0 ] && [ "$SCOPE_RC" -ne 69 ]; then SCOPE_JSON=""; fi
|
|
259
|
+
# One field of the resolver's JSON; arrays print one element per line, an absent field prints nothing.
|
|
260
|
+
scope_field() {
|
|
261
|
+
printf '%s' "$SCOPE_JSON" | node -e 'let s="";process.stdin.on("data",d=>s+=d).on("end",()=>{try{const v=JSON.parse(s)[process.argv[1]];process.stdout.write(Array.isArray(v)?v.join("\n"):v==null?"":String(v))}catch{process.exit(1)}})' "$1" 2>/dev/null
|
|
262
|
+
}
|
|
263
|
+
SCOPE_STATUS=$(scope_field status); [ -n "$SCOPE_STATUS" ] || SCOPE_STATUS="unresolvable"
|
|
264
|
+
SCOPE_REASON=$(scope_field reason)
|
|
265
|
+
SCOPE_SOURCE=$(scope_field source)
|
|
266
|
+
DIFF_BASE=$(scope_field rangeBase)
|
|
267
|
+
SCOPE_FILES=$(scope_field files)
|
|
268
|
+
|
|
269
|
+
if [ "$SCOPE_STATUS" != "resolved" ]; then
|
|
270
|
+
echo "Warning: evaluation scope is ${SCOPE_STATUS}${SCOPE_REASON:+ (${SCOPE_REASON})}; the file scope below comes from wider evidence or is unavailable."
|
|
271
|
+
fi
|
|
272
|
+
SCOPE_OUTSIDE=$(scope_field outsideUnion)
|
|
273
|
+
if [ -n "$SCOPE_OUTSIDE" ]; then
|
|
274
|
+
echo "Changed in the phase window by commits that are NOT this phase's task commits (not in scope):"
|
|
275
|
+
printf '%s\n' "$SCOPE_OUTSIDE" | sed 's/^/ - /'
|
|
276
|
+
fi
|
|
277
|
+
SCOPE_UNREACHABLE=$(scope_field unreachable)
|
|
278
|
+
if [ -n "$SCOPE_UNREACHABLE" ]; then
|
|
279
|
+
echo "Task commits not reachable from HEAD (another branch, or dropped by a rebase):"
|
|
280
|
+
printf '%s\n' "$SCOPE_UNREACHABLE" | sed 's/^/ - /'
|
|
281
|
+
fi
|
|
282
|
+
SCOPE_MISSING=$(scope_field missingOnDisk)
|
|
283
|
+
if [ -n "$SCOPE_MISSING" ]; then
|
|
284
|
+
echo "Scoped paths that no longer exist on disk (not reviewed):"
|
|
285
|
+
printf '%s\n' "$SCOPE_MISSING" | sed 's/^/ - /'
|
|
274
286
|
fi
|
|
275
287
|
|
|
276
288
|
if [ ${#REVIEW_FILES[@]} -eq 0 ]; then
|
|
277
|
-
# Full
|
|
278
|
-
if [ -n "$
|
|
279
|
-
# Run git diff with specific exclusions (per D-03)
|
|
280
|
-
DIFF_FILES=$(git diff --name-only "${DIFF_BASE}..HEAD" -- . \
|
|
281
|
-
':!.planning/' ':!ROADMAP.md' ':!STATE.md' \
|
|
282
|
-
':!*-SUMMARY.md' ':!*-VERIFICATION.md' ':!*-PLAN.md' \
|
|
283
|
-
':!package-lock.json' ':!yarn.lock' ':!Gemfile.lock' ':!poetry.lock' 2>/dev/null)
|
|
284
|
-
|
|
289
|
+
# Full fallback (per D-02): SUMMARY scoping yielded nothing.
|
|
290
|
+
if [ -n "$SCOPE_FILES" ]; then
|
|
285
291
|
while IFS= read -r file; do
|
|
286
292
|
[ -n "$file" ] && REVIEW_FILES+=("$file")
|
|
287
|
-
done <<< "$
|
|
293
|
+
done <<< "$SCOPE_FILES"
|
|
288
294
|
|
|
289
|
-
echo "File scope: ${#REVIEW_FILES[@]} files from
|
|
295
|
+
echo "File scope: ${#REVIEW_FILES[@]} files from ${SCOPE_SOURCE} (base: ${DIFF_BASE:-<none>})"
|
|
290
296
|
else
|
|
291
|
-
# Fail closed —
|
|
292
|
-
echo "Warning: No
|
|
297
|
+
# Fail closed — the resolver found no reviewable files. Do not use arbitrary HEAD~N.
|
|
298
|
+
echo "Warning: No evaluation scope found for '${PADDED_PHASE}' (${SCOPE_STATUS}${SCOPE_REASON:+: ${SCOPE_REASON}}). Cannot determine reliable scope."
|
|
293
299
|
echo "Use --files flag to specify files explicitly: /gsd:code-review ${PHASE_ARG} --files=file1,file2,..."
|
|
294
300
|
fi
|
|
295
|
-
elif [ -z "$FILES_OVERRIDE" ] && [ -n "$
|
|
301
|
+
elif [ -z "$FILES_OVERRIDE" ] && [ -n "$SCOPE_FILES" ]; then
|
|
296
302
|
# #4460: gated on FILES_OVERRIDE being unset — without this, REVIEW_FILES is
|
|
297
303
|
# already non-empty under --files (Tier 1 filled it), so this elif was
|
|
298
304
|
# reached anyway and the #2666 cross-check below appended the whole phase
|
|
299
|
-
#
|
|
300
|
-
#
|
|
301
|
-
# own --files guard
|
|
305
|
+
# scope onto an explicit user-supplied file list, contradicting "Skip
|
|
306
|
+
# SUMMARY/git scoping entirely when --files is provided" and Tier 2's
|
|
307
|
+
# own --files guard.
|
|
302
308
|
# #2666 cross-check: SUMMARY yielded a non-empty (possibly partial) scope.
|
|
303
|
-
# Warn about — and add — any
|
|
309
|
+
# Warn about — and add — any in-scope files the SUMMARY extractor did not surface,
|
|
304
310
|
# so a partial result can no longer silently ship an incomplete review scope.
|
|
305
|
-
DIFF_FILES=$(git diff --name-only "${DIFF_BASE}..HEAD" -- . \
|
|
306
|
-
':!.planning/' ':!ROADMAP.md' ':!STATE.md' \
|
|
307
|
-
':!*-SUMMARY.md' ':!*-VERIFICATION.md' ':!*-PLAN.md' \
|
|
308
|
-
':!package-lock.json' ':!yarn.lock' ':!Gemfile.lock' ':!poetry.lock' 2>/dev/null)
|
|
309
|
-
|
|
310
|
-
# Build a newline-delimited list of already-scoped files for exact membership
|
|
311
|
-
# testing (portable — bash 3.2 on macOS has no associative arrays). grep -Fxq
|
|
312
|
-
# matches the WHOLE line exactly, so a short basename (e.g. root `Dockerfile`)
|
|
313
|
-
# does NOT substring-match a longer scoped path (e.g. `docker/Dockerfile`).
|
|
314
|
-
IN_SCOPE=$(printf '%s\n' "${REVIEW_FILES[@]}")
|
|
315
311
|
|
|
312
|
+
# Exact whole-line membership (portable — bash 3.2 has no associative arrays). grep -Fxq
|
|
313
|
+
# matches the WHOLE line, so a short basename (e.g. root `Dockerfile`) does NOT
|
|
314
|
+
# substring-match a longer scoped path (e.g. `docker/Dockerfile`).
|
|
316
315
|
MISSING_FROM_SUMMARY=()
|
|
317
316
|
while IFS= read -r file; do
|
|
318
317
|
[ -z "$file" ] && continue
|
|
319
|
-
# Exact whole-line match; grep nonzero-exit => not in scope.
|
|
320
318
|
if printf '%s\n' "${REVIEW_FILES[@]}" | grep -Fxq -- "$file" 2>/dev/null; then
|
|
321
319
|
: # already scoped
|
|
322
320
|
else
|
|
323
321
|
MISSING_FROM_SUMMARY+=("$file"); REVIEW_FILES+=("$file")
|
|
324
322
|
fi
|
|
325
|
-
done <<< "$
|
|
323
|
+
done <<< "$SCOPE_FILES"
|
|
326
324
|
|
|
327
325
|
if [ ${#MISSING_FROM_SUMMARY[@]} -gt 0 ]; then
|
|
328
|
-
echo "Warning: SUMMARY scope was missing ${#MISSING_FROM_SUMMARY[@]}
|
|
326
|
+
echo "Warning: SUMMARY scope was missing ${#MISSING_FROM_SUMMARY[@]} in-scope file(s) the evaluation scope surfaced; adding them to the review scope:"
|
|
329
327
|
printf ' - %s\n' "${MISSING_FROM_SUMMARY[@]}"
|
|
330
328
|
fi
|
|
331
329
|
fi
|
|
@@ -333,7 +331,7 @@ fi
|
|
|
333
331
|
|
|
334
332
|
**Post-processing (all tiers):**
|
|
335
333
|
|
|
336
|
-
1. **Expand tilde paths:** SUMMARY.md `key-files` entries may record a `~/...`-prefixed path
|
|
334
|
+
1. **Expand tilde paths:** SUMMARY.md `key-files` entries may record a `~/...`-prefixed path. Bash only tilde-expands a literal `~` written in source text, never one arriving as the value of an already-expanded variable, so every later `[ -f "$file" ]` check must see a real, expanded path or it misclassifies the file as deleted.
|
|
337
335
|
```bash
|
|
338
336
|
EXPANDED_FILES=()
|
|
339
337
|
for file in "${REVIEW_FILES[@]}"; do
|
|
@@ -363,21 +361,24 @@ done
|
|
|
363
361
|
REVIEW_FILES=("${FILTERED_FILES[@]}")
|
|
364
362
|
```
|
|
365
363
|
|
|
366
|
-
3. **Filter deleted files:** Remove paths that don't exist on disk
|
|
364
|
+
3. **Filter deleted files:** Remove paths that don't exist on disk, and name each one (#5164) — a count hides whether the dropped file held the phase's entire deliverable
|
|
367
365
|
```bash
|
|
368
366
|
EXISTING_FILES=()
|
|
367
|
+
DELETED_FILES=()
|
|
369
368
|
DELETED_COUNT=0
|
|
370
369
|
for file in "${REVIEW_FILES[@]}"; do
|
|
371
370
|
if [ -f "$file" ]; then
|
|
372
371
|
EXISTING_FILES+=("$file")
|
|
373
372
|
else
|
|
374
373
|
DELETED_COUNT=$((DELETED_COUNT + 1))
|
|
374
|
+
DELETED_FILES+=("$file")
|
|
375
375
|
fi
|
|
376
376
|
done
|
|
377
377
|
REVIEW_FILES=("${EXISTING_FILES[@]}")
|
|
378
378
|
|
|
379
379
|
if [ $DELETED_COUNT -gt 0 ]; then
|
|
380
|
-
echo "Filtered $DELETED_COUNT deleted files from review scope"
|
|
380
|
+
echo "Filtered $DELETED_COUNT deleted files from review scope:"
|
|
381
|
+
printf ' - %s\n' "${DELETED_FILES[@]}"
|
|
381
382
|
fi
|
|
382
383
|
```
|
|
383
384
|
|
|
@@ -399,7 +400,7 @@ if [ -n "$FILES_OVERRIDE" ]; then
|
|
|
399
400
|
elif [ -n "$SUMMARIES" ] && [ ${#REVIEW_FILES[@]} -gt 0 ]; then
|
|
400
401
|
TIER="SUMMARY.md"
|
|
401
402
|
else
|
|
402
|
-
TIER="
|
|
403
|
+
TIER="${SCOPE_SOURCE:-evaluation scope}"
|
|
403
404
|
fi
|
|
404
405
|
echo "File scope: ${#REVIEW_FILES[@]} files from ${TIER}"
|
|
405
406
|
|
|
@@ -522,21 +523,31 @@ else
|
|
|
522
523
|
exit 1
|
|
523
524
|
fi
|
|
524
525
|
```
|
|
525
|
-
This `if`/`else`/`fi` is the entire guard:
|
|
526
|
+
This `if`/`else`/`fi` is the entire guard: unless `DEPTH_OK` is the literal string `true`, the `else` branch prints the errors and `exit 1`s out of the fenced block, so the `DEPTH_FIELDS`/`REVIEW_DEPTH` extraction is never reached and `REVIEW_DEPTH` is never set. Exit workflow. Do NOT spawn agent or create REVIEW.md.
|
|
526
527
|
</step>
|
|
527
528
|
|
|
528
529
|
<step name="check_empty_scope">
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
530
|
+
An empty `REVIEW_FILES` (#3661) means nothing new to re-review — NOT a phase with no standing findings. #4665: with `--fix` + an existing REVIEW.md, route to `dispatch-fix` (the flag covers "if REVIEW.md already exists"):
|
|
531
|
+
|
|
532
|
+
```bash
|
|
533
|
+
REVIEW_PATH="${PHASE_DIR}/${PADDED_PHASE}-REVIEW.md"
|
|
534
|
+
if [ "${#REVIEW_FILES[@]}" -ne 0 ]; then
|
|
535
|
+
# non-empty scope: no-op
|
|
536
|
+
true
|
|
537
|
+
elif [ "$FIX_FLAG" != "true" ] || [ ! -f "${REVIEW_PATH}" ]; then
|
|
538
|
+
echo "No source files changed in phase ${PHASE_ARG}. Skipping review."
|
|
539
|
+
# Exit workflow. Do NOT spawn agent or create REVIEW.md.
|
|
540
|
+
exit 0
|
|
541
|
+
fi
|
|
532
542
|
```
|
|
533
|
-
|
|
543
|
+
|
|
544
|
+
**`--fix` recovery:** proceed DIRECTLY to `dispatch-fix`, skipping `structural_pre_pass`, `dispatch_reviewer_lanes`, `spawn_reviewer`, `commit_review` — no fresh review, nothing to commit; `code-review-fix.md` resolves the existing REVIEW.md and owns the fix logic. The reviewer agent is not dispatched here.
|
|
534
545
|
</step>
|
|
535
546
|
|
|
536
547
|
<step name="structural_pre_pass">
|
|
537
548
|
Optional structural cross-module pass powered by fallow.
|
|
538
549
|
|
|
539
|
-
Parse `fallow_enabled`, `fallow_scope`, `fallow_profile`, `fallow_mcp`, `fallow_max_crap` from the init JSON as `FALLOW_ENABLED`, `FALLOW_SCOPE`, `FALLOW_PROFILE`, `FALLOW_MCP`, `FALLOW_MAX_CRAP`. These are resolved once by `init.code-review` at init time — consuming the pre-resolved values here
|
|
550
|
+
Parse `fallow_enabled`, `fallow_scope`, `fallow_profile`, `fallow_mcp`, `fallow_max_crap` from the init JSON as `FALLOW_ENABLED`, `FALLOW_SCOPE`, `FALLOW_PROFILE`, `FALLOW_MCP`, `FALLOW_MAX_CRAP`. These are resolved once by `init.code-review` at init time — consuming the pre-resolved values here avoids gating this section's own inclusion on a fact its own body would compute (see `state:fallow-enabled` in docs/reference/workflow-fragments.md).
|
|
540
551
|
|
|
541
552
|
Defaults are fail-closed and opt-in:
|
|
542
553
|
- `enabled=false` (skip entirely)
|
|
@@ -927,7 +938,7 @@ If `--files` validation fails unexpectedly on macOS, install coreutils or use ab
|
|
|
927
938
|
- [ ] Capability gate checked (`workflow.code_review` config key)
|
|
928
939
|
- [ ] --fix/--all/--auto flags parsed via code-review-flags.cjs typed IR (not ad-hoc bash)
|
|
929
940
|
- [ ] Depth resolved with validation (quick|standard|deep)
|
|
930
|
-
- [ ] File scope computed with 3 tiers: --files > SUMMARY.md >
|
|
941
|
+
- [ ] File scope computed with 3 tiers: --files > SUMMARY.md > phase evaluation scope
|
|
931
942
|
- [ ] Malformed/missing SUMMARY.md handled gracefully with fallback
|
|
932
943
|
- [ ] Deleted files filtered from scope
|
|
933
944
|
- [ ] Files deduplicated and sorted
|
|
@@ -11,7 +11,7 @@ If user chooses [A] (Acknowledge):
|
|
|
11
11
|
1. Re-run `gsd_run query audit-open --json` to get structured data.
|
|
12
12
|
2. Acknowledge every open item through the `audit-open acknowledge` CLI writer — this is what actually suppresses each item starting at the NEXT `audit-open` scan; the STATE.md table in step 3 is a disclosure record only, it is no longer the suppression mechanism. Every acknowledge call's exit status is accumulated (`ACK_FAILURES`); the step HALTS before closing if any failed — a refusal (`unsupported_heading_shape`, `ambiguous`, `not_found`, missing file, etc.) must never be silently discarded and let the close proceed as if everything were suppressed. `AUDIT_JSON` uses the same `@file:` large-payload sentinel handling `INIT_MANAGER` uses in `verify_readiness` below — `io.output` swaps any JSON payload over 50000 chars for a `@file:<path>` marker, and feeding that literal string to `jq` would silently make every loop body below iterate zero times:
|
|
13
13
|
```bash
|
|
14
|
-
_GSD_SHIM_NAME="gsd-tools.cjs"; _GSD_RUNTIME_ROOT="${RUNTIME_DIR:-$(git rev-parse --show-toplevel 2>/dev/null || pwd)}"; GSD_TOOLS="${_GSD_RUNTIME_ROOT}/gsd-core/bin/${_GSD_SHIM_NAME}"; _gsd_at() { for _p; do if [ -f "$_p" ]; then GSD_TOOLS="$_p"; return 0; fi; done; return 1; };
|
|
14
|
+
_GSD_SHIM_NAME="gsd-tools.cjs"; _GSD_RUNTIME_ROOT="${RUNTIME_DIR:-$(git rev-parse --show-toplevel 2>/dev/null || pwd)}"; GSD_TOOLS="${_GSD_RUNTIME_ROOT}/gsd-core/bin/${_GSD_SHIM_NAME}"; _gsd_at() { for _p; do if [ -f "$_p" ]; then GSD_TOOLS="$_p"; return 0; fi; done; return 1; }; _gsd_id_ok() { case "$("$1" runtime-identity --raw 2>/dev/null || true)" in '{"packageName":"@opengsd/gsd-core"'*'}') return 0;; *) return 1;; esac; }; _gsd_homes() { set -- "${CLAUDE_CONFIG_DIR:-$HOME/.claude}" "${ANTIGRAVITY_CONFIG_DIR:-$HOME/.gemini/antigravity}" "$HOME/.gemini/antigravity-ide" "$HOME/.gemini/antigravity-cli" "${AUGMENT_CONFIG_DIR:-$HOME/.augment}" "${CLINE_CONFIG_DIR:-$HOME/.cline}" "${CODEBUDDY_CONFIG_DIR:-$HOME/.codebuddy}" "${CODEX_HOME:-$HOME/.codex}" "${COPILOT_CONFIG_DIR:-${COPILOT_HOME:-$HOME/.copilot}}" "${CURSOR_CONFIG_DIR:-$HOME/.cursor}" "${HERMES_HOME:-$HOME/.hermes}" "${KILO_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/kilo}" "${KIMI_CONFIG_DIR:-$HOME/.config/agents}" "$HOME/.agents" "${KIMI_CODE_HOME:-$HOME/.kimi-code}" "${OPENCODE_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/opencode}" "${PI_CODING_AGENT_DIR:-$HOME/.pi/agent}" "${QWEN_CONFIG_DIR:-$HOME/.qwen}" "${TRAE_CONFIG_DIR:-$HOME/.trae}" "${WINDSURF_CONFIG_DIR:-$HOME/.codeium/windsurf}" "${ZCODE_CONFIG_DIR:-$HOME/.zcode}" "${GROK_AGENTS_HOME:-$HOME/.agents}"; for _h; do _gsd_at "$_h/gsd-core/bin/${_GSD_SHIM_NAME}" && return 0; done; return 1; }; if _gsd_at "${_GSD_RUNTIME_ROOT}/gsd-core/bin/${_GSD_SHIM_NAME}" "${_GSD_RUNTIME_ROOT}/.claude/gsd-core/bin/${_GSD_SHIM_NAME}" "${_GSD_RUNTIME_ROOT}/.codex/gsd-core/bin/${_GSD_SHIM_NAME}"; then gsd_run() { node "$GSD_TOOLS" "$@"; }; elif _gsd_homes; then gsd_run() { node "$GSD_TOOLS" "$@"; }; elif unset -f gsd_run; _G="$(command -v gsd_run)"; [ -n "$_G" ] && _gsd_id_ok "$_G"; then GSD_TOOLS="$_G"; gsd_run() { "$GSD_TOOLS" "$@"; }; else echo "ERROR: gsd-tools.cjs not found at $GSD_TOOLS and no identity-proving gsd_run is on PATH. Run: npx -y @opengsd/gsd-core@latest --claude --local" >&2; exit 1; fi; GSD_IDENTITY_STATUS=unverified; _gsd_id_ok gsd_run && GSD_IDENTITY_STATUS=ok; export GSD_IDENTITY_STATUS; [ "$GSD_IDENTITY_STATUS" = ok ] || echo "WARNING: \"$GSD_TOOLS\" did not prove it is @opengsd/gsd-core - it is either a different package or an @opengsd/gsd-core older than the runtime-identity verb. See docs/how-to/diagnose-a-foreign-gsd-tools.md" >&2; if [ -n "${CLAUDE_ENV_FILE:-}" ] && [ -n "${GSD_TOOLS:-}" ]; then printf "export PATH='%s':\"\$PATH\"\n" "${GSD_TOOLS%/*}" >> "$CLAUDE_ENV_FILE" 2>/dev/null || true; fi
|
|
15
15
|
AUDIT_JSON=$(gsd_run query audit-open --json)
|
|
16
16
|
if [[ "$AUDIT_JSON" == @file:* ]]; then AUDIT_JSON=$(cat "${AUDIT_JSON#@file:}"); fi
|
|
17
17
|
MILESTONE_VERSION="v[X.Y]" # already known from ROADMAP.md's active milestone header — the same identifier `milestone.complete` uses in the archive_milestone step
|
|
@@ -146,9 +146,10 @@ Check branching strategy and offer merge options.
|
|
|
146
146
|
Use `init milestone-op` for context, or load config directly:
|
|
147
147
|
|
|
148
148
|
```bash
|
|
149
|
-
|
|
149
|
+
GSD_WS=$(echo " $ARGUMENTS" | sed -nE 's/.* --ws +([A-Za-z0-9][A-Za-z0-9._-]*).*/--ws \1/p' | head -n 1) # Read-loaded file: write the command's original argument string in place of $ARGUMENTS
|
|
150
|
+
INIT=$(gsd_run query init.execute-phase ${GSD_WS:+--ws=${GSD_WS##* }} "1")
|
|
150
151
|
if [[ "$INIT" == @file:* ]]; then INIT=$(cat "${INIT#@file:}"); fi
|
|
151
|
-
INIT_CM=$(gsd_run query init.complete-milestone)
|
|
152
|
+
INIT_CM=$(gsd_run query init.complete-milestone ${GSD_WS:+--ws=${GSD_WS##* }})
|
|
152
153
|
if [[ "$INIT_CM" == @file:* ]]; then INIT_CM=$(cat "${INIT_CM#@file:}"); fi
|
|
153
154
|
```
|
|
154
155
|
|
|
@@ -43,7 +43,7 @@ When a milestone completes:
|
|
|
43
43
|
Before proceeding with milestone close, run the comprehensive open artifact audit.
|
|
44
44
|
|
|
45
45
|
```bash
|
|
46
|
-
_GSD_SHIM_NAME="gsd-tools.cjs"; _GSD_RUNTIME_ROOT="${RUNTIME_DIR:-$(git rev-parse --show-toplevel 2>/dev/null || pwd)}"; GSD_TOOLS="${_GSD_RUNTIME_ROOT}/gsd-core/bin/${_GSD_SHIM_NAME}"; _gsd_at() { for _p; do if [ -f "$_p" ]; then GSD_TOOLS="$_p"; return 0; fi; done; return 1; };
|
|
46
|
+
_GSD_SHIM_NAME="gsd-tools.cjs"; _GSD_RUNTIME_ROOT="${RUNTIME_DIR:-$(git rev-parse --show-toplevel 2>/dev/null || pwd)}"; GSD_TOOLS="${_GSD_RUNTIME_ROOT}/gsd-core/bin/${_GSD_SHIM_NAME}"; _gsd_at() { for _p; do if [ -f "$_p" ]; then GSD_TOOLS="$_p"; return 0; fi; done; return 1; }; _gsd_id_ok() { case "$("$1" runtime-identity --raw 2>/dev/null || true)" in '{"packageName":"@opengsd/gsd-core"'*'}') return 0;; *) return 1;; esac; }; _gsd_homes() { set -- "${CLAUDE_CONFIG_DIR:-$HOME/.claude}" "${ANTIGRAVITY_CONFIG_DIR:-$HOME/.gemini/antigravity}" "$HOME/.gemini/antigravity-ide" "$HOME/.gemini/antigravity-cli" "${AUGMENT_CONFIG_DIR:-$HOME/.augment}" "${CLINE_CONFIG_DIR:-$HOME/.cline}" "${CODEBUDDY_CONFIG_DIR:-$HOME/.codebuddy}" "${CODEX_HOME:-$HOME/.codex}" "${COPILOT_CONFIG_DIR:-${COPILOT_HOME:-$HOME/.copilot}}" "${CURSOR_CONFIG_DIR:-$HOME/.cursor}" "${HERMES_HOME:-$HOME/.hermes}" "${KILO_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/kilo}" "${KIMI_CONFIG_DIR:-$HOME/.config/agents}" "$HOME/.agents" "${KIMI_CODE_HOME:-$HOME/.kimi-code}" "${OPENCODE_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/opencode}" "${PI_CODING_AGENT_DIR:-$HOME/.pi/agent}" "${QWEN_CONFIG_DIR:-$HOME/.qwen}" "${TRAE_CONFIG_DIR:-$HOME/.trae}" "${WINDSURF_CONFIG_DIR:-$HOME/.codeium/windsurf}" "${ZCODE_CONFIG_DIR:-$HOME/.zcode}" "${GROK_AGENTS_HOME:-$HOME/.agents}"; for _h; do _gsd_at "$_h/gsd-core/bin/${_GSD_SHIM_NAME}" && return 0; done; return 1; }; if _gsd_at "${_GSD_RUNTIME_ROOT}/gsd-core/bin/${_GSD_SHIM_NAME}" "${_GSD_RUNTIME_ROOT}/.claude/gsd-core/bin/${_GSD_SHIM_NAME}" "${_GSD_RUNTIME_ROOT}/.codex/gsd-core/bin/${_GSD_SHIM_NAME}"; then gsd_run() { node "$GSD_TOOLS" "$@"; }; elif _gsd_homes; then gsd_run() { node "$GSD_TOOLS" "$@"; }; elif unset -f gsd_run; _G="$(command -v gsd_run)"; [ -n "$_G" ] && _gsd_id_ok "$_G"; then GSD_TOOLS="$_G"; gsd_run() { "$GSD_TOOLS" "$@"; }; else echo "ERROR: gsd-tools.cjs not found at $GSD_TOOLS and no identity-proving gsd_run is on PATH. Run: npx -y @opengsd/gsd-core@latest --claude --local" >&2; exit 1; fi; GSD_IDENTITY_STATUS=unverified; _gsd_id_ok gsd_run && GSD_IDENTITY_STATUS=ok; export GSD_IDENTITY_STATUS; [ "$GSD_IDENTITY_STATUS" = ok ] || echo "WARNING: \"$GSD_TOOLS\" did not prove it is @opengsd/gsd-core - it is either a different package or an @opengsd/gsd-core older than the runtime-identity verb. See docs/how-to/diagnose-a-foreign-gsd-tools.md" >&2; if [ -n "${CLAUDE_ENV_FILE:-}" ] && [ -n "${GSD_TOOLS:-}" ]; then printf "export PATH='%s':\"\$PATH\"\n" "${GSD_TOOLS%/*}" >> "$CLAUDE_ENV_FILE" 2>/dev/null || true; fi
|
|
47
47
|
RESPONSE_LANGUAGE=$(gsd_run query config-get response_language --raw --default "" 2>/dev/null || echo "")
|
|
48
48
|
gsd_run query audit-open
|
|
49
49
|
```
|
|
@@ -77,7 +77,8 @@ Exact per-category bash (including the `@file:` large-payload handling, the `tod
|
|
|
77
77
|
**Use `init.manager` for canonical readiness check:**
|
|
78
78
|
|
|
79
79
|
```bash
|
|
80
|
-
|
|
80
|
+
GSD_WS=$(echo " $ARGUMENTS" | sed -nE 's/.* --ws +([A-Za-z0-9][A-Za-z0-9._-]*).*/--ws \1/p' | head -n 1)
|
|
81
|
+
INIT_MANAGER=$(gsd_run query init.manager ${GSD_WS:+--ws=${GSD_WS##* }})
|
|
81
82
|
if [[ "$INIT_MANAGER" == @file:* ]]; then INIT_MANAGER=$(cat "${INIT_MANAGER#@file:}"); fi
|
|
82
83
|
```
|
|
83
84
|
|
|
@@ -161,7 +162,7 @@ Proceed to gather_stats.
|
|
|
161
162
|
|
|
162
163
|
</if>
|
|
163
164
|
|
|
164
|
-
<if mode="interactive"
|
|
165
|
+
<if mode="interactive" AND="gates.confirm_milestone_scope != false">
|
|
165
166
|
|
|
166
167
|
```
|
|
167
168
|
Ready to mark this milestone as shipped?
|
|
@@ -387,7 +388,7 @@ Initial user testing showed demand for shape tools.
|
|
|
387
388
|
|
|
388
389
|
<step name="archive_milestone">
|
|
389
390
|
|
|
390
|
-
**Text mode (`workflow.text_mode: true` in config or `--text` flag):** Set `TEXT_MODE=true` if `--text` is present in `$ARGUMENTS` OR `text_mode` from init JSON is `true`. When TEXT_MODE is active, replace every `AskUserQuestion` call with a plain-text numbered list and ask the user to type their choice number. This is required for non-Claude runtimes (OpenAI Codex,
|
|
391
|
+
**Text mode (`workflow.text_mode: true` in config or `--text` flag):** Set `TEXT_MODE=true` if `--text` is present in `$ARGUMENTS` OR `text_mode` from init JSON is `true`. When TEXT_MODE is active, replace every `AskUserQuestion` call with a plain-text numbered list and ask the user to type their choice number. This is required for non-Claude runtimes (OpenAI Codex, Antigravity, etc.) where `AskUserQuestion` is not available.
|
|
391
392
|
|
|
392
393
|
**Quick-task archival (opt-in — NOT symmetrical with phase archival below, #2142):** unlike phase archival, quick-task archival is **opt-in, default OFF**. Doing nothing leaves `.planning/quick/` untouched, exactly like today's behavior. Decide this BEFORE calling `milestone complete` below, so the flag can be folded into that single invocation rather than issuing a second, redundant call.
|
|
393
394
|
|
|
@@ -452,7 +453,8 @@ After `milestone complete` has archived, reorganize ROADMAP.md with milestone gr
|
|
|
452
453
|
Extract the Backlog section from the current ROADMAP.md before making any changes:
|
|
453
454
|
|
|
454
455
|
```bash
|
|
455
|
-
|
|
456
|
+
GSD_WS=$(echo " $ARGUMENTS" | sed -nE 's/.* --ws +([A-Za-z0-9][A-Za-z0-9._-]*).*/--ws \1/p' | head -n 1)
|
|
457
|
+
INIT_REORG=$(gsd_run query init.complete-milestone ${GSD_WS:+--ws=${GSD_WS##* }})
|
|
456
458
|
if [[ "$INIT_REORG" == @file:* ]]; then INIT_REORG=$(cat "${INIT_REORG#@file:}"); fi
|
|
457
459
|
_gsd_field() { node -e "const o=JSON.parse(process.argv[1]); const v=o[process.argv[2]]; process.stdout.write(v==null?'':String(v))" "$1" "$2"; }
|
|
458
460
|
ROADMAP_PATH=$(_gsd_field "$INIT_REORG" roadmap_path)
|
|
@@ -469,7 +471,8 @@ This rewrite is an *intentional* catastrophic shrink: phase detail was just arch
|
|
|
469
471
|
1. Arm the sentinel (single-use; the guard checks it is fresh — within 15 minutes — and names exactly this file, then consumes it):
|
|
470
472
|
|
|
471
473
|
```bash
|
|
472
|
-
|
|
474
|
+
GSD_WS=$(echo " $ARGUMENTS" | sed -nE 's/.* --ws +([A-Za-z0-9][A-Za-z0-9._-]*).*/--ws \1/p' | head -n 1)
|
|
475
|
+
INIT_REORG=$(gsd_run query init.complete-milestone ${GSD_WS:+--ws=${GSD_WS##* }})
|
|
473
476
|
if [[ "$INIT_REORG" == @file:* ]]; then INIT_REORG=$(cat "${INIT_REORG#@file:}"); fi
|
|
474
477
|
_gsd_field() { node -e "const o=JSON.parse(process.argv[1]); const v=o[process.argv[2]]; process.stdout.write(v==null?'':String(v))" "$1" "$2"; }
|
|
475
478
|
ROADMAP_PATH=$(_gsd_field "$INIT_REORG" roadmap_path)
|
|
@@ -507,7 +510,8 @@ Append the extracted Backlog content verbatim to the end of the newly written RO
|
|
|
507
510
|
**Safety commit — commit archive files BEFORE deleting any originals:**
|
|
508
511
|
|
|
509
512
|
```bash
|
|
510
|
-
|
|
513
|
+
GSD_WS=$(echo " $ARGUMENTS" | sed -nE 's/.* --ws +([A-Za-z0-9][A-Za-z0-9._-]*).*/--ws \1/p' | head -n 1)
|
|
514
|
+
INIT_REORG=$(gsd_run query init.complete-milestone ${GSD_WS:+--ws=${GSD_WS##* }})
|
|
511
515
|
if [[ "$INIT_REORG" == @file:* ]]; then INIT_REORG=$(cat "${INIT_REORG#@file:}"); fi
|
|
512
516
|
_gsd_field() { node -e "const o=JSON.parse(process.argv[1]); const v=o[process.argv[2]]; process.stdout.write(v==null?'':String(v))" "$1" "$2"; }
|
|
513
517
|
STATE_PATH=$(_gsd_field "$INIT_REORG" state_path)
|
|
@@ -525,7 +529,8 @@ MILESTONES.md and PROJECT.md are workstream-scoped the same way STATE.md/ROADMAP
|
|
|
525
529
|
**Remove REQUIREMENTS.md via git rm** (preserves history, stages deletion atomically):
|
|
526
530
|
|
|
527
531
|
```bash
|
|
528
|
-
|
|
532
|
+
GSD_WS=$(echo " $ARGUMENTS" | sed -nE 's/.* --ws +([A-Za-z0-9][A-Za-z0-9._-]*).*/--ws \1/p' | head -n 1)
|
|
533
|
+
INIT_REORG=$(gsd_run query init.complete-milestone ${GSD_WS:+--ws=${GSD_WS##* }})
|
|
529
534
|
if [[ "$INIT_REORG" == @file:* ]]; then INIT_REORG=$(cat "${INIT_REORG#@file:}"); fi
|
|
530
535
|
_gsd_field() { node -e "const o=JSON.parse(process.argv[1]); const v=o[process.argv[2]]; process.stdout.write(v==null?'':String(v))" "$1" "$2"; }
|
|
531
536
|
REQUIREMENTS_PATH=$(_gsd_field "$INIT_REORG" requirements_path)
|