@opengsd/gsd-core 1.10.0 → 1.12.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/agents/gsd-code-fixer.md +1 -1
- package/agents/gsd-debug-session-manager.md +12 -1
- package/agents/gsd-debugger.md +1 -1
- package/agents/gsd-doc-synthesizer.md +2 -4
- package/agents/gsd-dom-verifier.md +169 -0
- package/agents/gsd-eval-auditor.md +1 -1
- package/agents/gsd-executor.md +22 -14
- package/agents/gsd-framework-selector.md +1 -3
- package/agents/gsd-intel-updater.md +1 -1
- package/agents/gsd-mempalace-curator.md +5 -3
- package/agents/gsd-pattern-mapper.md +11 -0
- package/agents/gsd-phase-researcher.md +23 -2
- package/agents/gsd-plan-checker.md +50 -53
- package/agents/gsd-planner.md +50 -50
- package/agents/gsd-project-researcher.md +1 -1
- package/agents/gsd-research-synthesizer.md +2 -2
- package/agents/gsd-roadmapper.md +15 -11
- package/agents/gsd-ui-checker.md +63 -4
- package/agents/gsd-ui-researcher.md +41 -3
- package/agents/gsd-user-profiler.md +3 -0
- package/agents/gsd-verifier.md +13 -4
- package/bin/install.js +1448 -1103
- package/commands/gsd/code-review.md +1 -1
- package/commands/gsd/discuss-phase.md +1 -1
- package/commands/gsd/execute-phase.md +1 -1
- package/commands/gsd/import.md +1 -1
- package/commands/gsd/map-codebase.md +1 -1
- package/commands/gsd/mempalace-capture.md +1 -1
- package/commands/gsd/mempalace-recall.md +1 -1
- package/commands/gsd/new-milestone.md +1 -1
- package/commands/gsd/quick.md +9 -5
- package/commands/gsd/review-backlog.md +2 -1
- package/commands/gsd/verify-work.md +1 -1
- package/gsd-core/bin/gsd-tools.cjs +1035 -138
- package/gsd-core/bin/lib/active-workstream-store.cjs +146 -22
- package/gsd-core/bin/lib/adr-parser.cjs +13 -7
- package/gsd-core/bin/lib/agent-install-check.cjs +392 -32
- package/gsd-core/bin/lib/api-coverage.cjs +33 -14
- package/gsd-core/bin/lib/artifacts.cjs +5 -0
- package/gsd-core/bin/lib/assumption-delta.cjs +32 -15
- package/gsd-core/bin/lib/audit-command-router.cjs +9 -2
- package/gsd-core/bin/lib/audit.cjs +1026 -268
- package/gsd-core/bin/lib/broken-windows.cjs +306 -28
- package/gsd-core/bin/lib/capability-consent.cjs +149 -15
- package/gsd-core/bin/lib/capability-lifecycle.cjs +45 -0
- package/gsd-core/bin/lib/capability-lock.cjs +10 -4
- package/gsd-core/bin/lib/capability-registry.cjs +845 -130
- package/gsd-core/bin/lib/capability-source.cjs +92 -0
- package/gsd-core/bin/lib/capability-state.cjs +18 -3
- package/gsd-core/bin/lib/capability-trust.cjs +444 -25
- package/gsd-core/bin/lib/capability-validator.cjs +700 -40
- package/gsd-core/bin/lib/capability-writer.cjs +3 -2
- package/gsd-core/bin/lib/check-command-router.cjs +216 -42
- package/gsd-core/bin/lib/claude-orchestration.cjs +56 -3
- package/gsd-core/bin/lib/cli-exit.cjs +496 -10
- package/gsd-core/bin/lib/code-review-depth.cjs +288 -0
- package/gsd-core/bin/lib/codex-agent-toml.cjs +735 -0
- package/gsd-core/bin/lib/command-aliases.cjs +22 -0
- package/gsd-core/bin/lib/command-arg-projection.cjs +144 -14
- package/gsd-core/bin/lib/command-roster.cjs +44 -1
- package/gsd-core/bin/lib/command-routing-hub.cjs +31 -2
- package/gsd-core/bin/lib/commands.cjs +1172 -108
- package/gsd-core/bin/lib/commonjs-marker.cjs +12 -6
- package/gsd-core/bin/lib/complexity-trigger.cjs +1192 -0
- package/gsd-core/bin/lib/config-loader.cjs +187 -23
- package/gsd-core/bin/lib/config.cjs +102 -3
- package/gsd-core/bin/lib/configuration.cjs +129 -37
- package/gsd-core/bin/lib/core-utils.cjs +208 -33
- package/gsd-core/bin/lib/decisions.cjs +23 -0
- package/gsd-core/bin/lib/edge-probe.cjs +9 -1
- package/gsd-core/bin/lib/estimate-cli.cjs +55 -11
- package/gsd-core/bin/lib/exit-code-registry.cjs +98 -0
- package/gsd-core/bin/lib/fallow-runner.cjs +20 -44
- package/gsd-core/bin/lib/frontmatter.cjs +899 -229
- package/gsd-core/bin/lib/gap-checker.cjs +95 -10
- package/gsd-core/bin/lib/git-base-branch.cjs +276 -39
- package/gsd-core/bin/lib/gsd2-import.cjs +10 -1
- package/gsd-core/bin/lib/health-diagnostic-rules/agent-install.cjs +101 -0
- package/gsd-core/bin/lib/health-diagnostic-rules/config-validation.cjs +348 -0
- package/gsd-core/bin/lib/health-diagnostic-rules/consistency.cjs +149 -0
- package/gsd-core/bin/lib/health-diagnostic-rules/install-surface-shadowing.cjs +98 -0
- package/gsd-core/bin/lib/health-diagnostic-rules/milestone-archive-hygiene.cjs +100 -0
- package/gsd-core/bin/lib/health-diagnostic-rules/phase-structure.cjs +222 -0
- package/gsd-core/bin/lib/health-diagnostic-rules/roadmap-disk-consistency.cjs +268 -0
- package/gsd-core/bin/lib/health-diagnostic-rules/root-existence.cjs +161 -0
- package/gsd-core/bin/lib/health-diagnostic-rules/state-consistency.cjs +303 -0
- package/gsd-core/bin/lib/health-diagnostic-rules/worktree-health.cjs +187 -0
- package/gsd-core/bin/lib/health-diagnostic-types.cjs +68 -0
- package/gsd-core/bin/lib/health-diagnostic.cjs +451 -0
- package/gsd-core/bin/lib/host-integration.cjs +39 -6
- package/gsd-core/bin/lib/host-runtime-detection.cjs +134 -0
- package/gsd-core/bin/lib/init-command-router.cjs +118 -21
- package/gsd-core/bin/lib/init.cjs +439 -168
- package/gsd-core/bin/lib/install-effort-resolver.cjs +73 -30
- package/gsd-core/bin/lib/install-engine.cjs +811 -259
- package/gsd-core/bin/lib/install-fs-adapter.cjs +262 -0
- package/gsd-core/bin/lib/install-model-override-resolver.cjs +235 -0
- package/gsd-core/bin/lib/install-profiles.cjs +212 -61
- package/gsd-core/bin/lib/install-scope.cjs +270 -0
- package/gsd-core/bin/lib/install-shadow-report.cjs +385 -0
- package/gsd-core/bin/lib/installed-surface-resolver.cjs +381 -0
- package/gsd-core/bin/lib/installer-migration-report.cjs +3 -0
- package/gsd-core/bin/lib/installer-migrations/010-antigravity-retire-confighome-artifacts.cjs +169 -0
- package/gsd-core/bin/lib/installer-migrations.cjs +148 -38
- package/gsd-core/bin/lib/intel.cjs +101 -26
- package/gsd-core/bin/lib/io.cjs +170 -15
- package/gsd-core/bin/lib/learnings.cjs +85 -14
- package/gsd-core/bin/lib/legacy-cleanup.cjs +8 -2
- package/gsd-core/bin/lib/markdown-sectionizer.cjs +2 -1
- package/gsd-core/bin/lib/markdown-table.cjs +183 -22
- package/gsd-core/bin/lib/milestone-lock.cjs +248 -0
- package/gsd-core/bin/lib/milestone.cjs +842 -73
- package/gsd-core/bin/lib/model-catalog.cjs +232 -16
- package/gsd-core/bin/lib/model-resolver.cjs +193 -68
- package/gsd-core/bin/lib/normalize-test-command.cjs +1 -1
- package/gsd-core/bin/lib/onboard-projection.cjs +5 -1
- package/gsd-core/bin/lib/pattern.cjs +122 -0
- package/gsd-core/bin/lib/phase-estimation.cjs +18 -9
- package/gsd-core/bin/lib/phase-id.cjs +514 -40
- package/gsd-core/bin/lib/phase-lifecycle.cjs +52 -19
- package/gsd-core/bin/lib/phase-locator.cjs +262 -34
- package/gsd-core/bin/lib/phase.cjs +1038 -214
- package/gsd-core/bin/lib/plan-dependency-graph.cjs +72 -1
- package/gsd-core/bin/lib/plan-document.cjs +263 -0
- package/gsd-core/bin/lib/plan-drift-guard.cjs +120 -0
- package/gsd-core/bin/lib/plan-scan.cjs +98 -3
- package/gsd-core/bin/lib/planning-command-router.cjs +61 -0
- package/gsd-core/bin/lib/planning-inspect.cjs +1168 -0
- package/gsd-core/bin/lib/planning-scope.cjs +31 -0
- package/gsd-core/bin/lib/planning-snapshot.cjs +894 -0
- package/gsd-core/bin/lib/planning-workspace.cjs +112 -6
- package/gsd-core/bin/lib/probe-core.cjs +5 -2
- package/gsd-core/bin/lib/profile-output.cjs +1 -1
- package/gsd-core/bin/lib/profile-pipeline-command-router.cjs +50 -7
- package/gsd-core/bin/lib/profile-pipeline.cjs +6 -3
- package/gsd-core/bin/lib/real-home-guard.cjs +419 -0
- package/gsd-core/bin/lib/refactor-trigger-command-router.cjs +766 -0
- package/gsd-core/bin/lib/retired-artifact-cleanup.cjs +11 -6
- package/gsd-core/bin/lib/review-lane-descriptor.cjs +22 -13
- package/gsd-core/bin/lib/review-lane-invocation.cjs +30 -0
- package/gsd-core/bin/lib/review-lane-runner.cjs +421 -66
- package/gsd-core/bin/lib/review-reviewer-selection.cjs +13 -18
- package/gsd-core/bin/lib/roadmap-command-router.cjs +59 -11
- package/gsd-core/bin/lib/roadmap-parser.cjs +1006 -184
- package/gsd-core/bin/lib/roadmap-upgrade.cjs +37 -10
- package/gsd-core/bin/lib/roadmap.cjs +442 -96
- package/gsd-core/bin/lib/runtime-artifact-conversion.cjs +702 -52
- package/gsd-core/bin/lib/runtime-artifact-install-plan.cjs +14 -2
- package/gsd-core/bin/lib/runtime-artifact-layout.cjs +459 -55
- package/gsd-core/bin/lib/runtime-config-adapter-registry.cjs +3 -2
- package/gsd-core/bin/lib/runtime-homes.cjs +69 -3
- package/gsd-core/bin/lib/runtime-hooks-surface.cjs +402 -58
- package/gsd-core/bin/lib/runtime-identity.cjs +234 -0
- package/gsd-core/bin/lib/runtime-name-policy.cjs +3 -1
- package/gsd-core/bin/lib/runtime-slash.cjs +96 -8
- package/gsd-core/bin/lib/security.cjs +104 -5
- package/gsd-core/bin/lib/shell-command-projection.cjs +342 -7
- package/gsd-core/bin/lib/smart-entry.cjs +133 -23
- package/gsd-core/bin/lib/spec-section.cjs +12 -7
- package/gsd-core/bin/lib/state-command-router.cjs +52 -19
- package/gsd-core/bin/lib/state-contract.cjs +359 -0
- package/gsd-core/bin/lib/state-document.cjs +338 -8
- package/gsd-core/bin/lib/state-md-schema.cjs +221 -0
- package/gsd-core/bin/lib/state-transition.cjs +846 -176
- package/gsd-core/bin/lib/state.cjs +2589 -369
- package/gsd-core/bin/lib/surface.cjs +33 -11
- package/gsd-core/bin/lib/task-command-router.cjs +111 -1
- package/gsd-core/bin/lib/task-content-resolution.cjs +368 -0
- package/gsd-core/bin/lib/teams-status.cjs +4 -1
- package/gsd-core/bin/lib/text-lines.cjs +80 -0
- package/gsd-core/bin/lib/token-scanner.cjs +76 -0
- package/gsd-core/bin/lib/uat-predicate.cjs +67 -23
- package/gsd-core/bin/lib/uat.cjs +1761 -167
- package/gsd-core/bin/lib/ui-consideration-probe.cjs +9 -1
- package/gsd-core/bin/lib/ui-frontend-evidence.cjs +157 -0
- package/gsd-core/bin/lib/ui-safety-gate.cjs +51 -12
- package/gsd-core/bin/lib/unusable-input.cjs +37 -0
- package/gsd-core/bin/lib/update-context.cjs +8 -2
- package/gsd-core/bin/lib/user-artifact-staging.cjs +705 -0
- package/gsd-core/bin/lib/validate-command-router.cjs +2 -2
- package/gsd-core/bin/lib/validate.cjs +20 -6
- package/gsd-core/bin/lib/vendor/README.md +75 -0
- package/gsd-core/bin/lib/vendor/js-yaml.cjs +3014 -0
- package/gsd-core/bin/lib/vendor/re2js.cjs +6480 -0
- package/gsd-core/bin/lib/vendor/re2js.d.cts +938 -0
- package/gsd-core/bin/lib/verification-command-router.cjs +2 -1
- package/gsd-core/bin/lib/verification.cjs +272 -9
- package/gsd-core/bin/lib/verify-command-grounding.cjs +846 -0
- package/gsd-core/bin/lib/verify.cjs +453 -918
- package/gsd-core/bin/lib/workstream-inventory-builder.cjs +53 -32
- package/gsd-core/bin/lib/workstream-inventory.cjs +63 -10
- package/gsd-core/bin/lib/workstream-name-policy.cjs +25 -4
- package/gsd-core/bin/lib/workstream.cjs +2 -2
- package/gsd-core/bin/lib/worktree-base-ref.cjs +66 -12
- package/gsd-core/bin/lib/worktree-safety.cjs +341 -18
- package/gsd-core/bin/shared/config-defaults.manifest.json +8 -1
- package/gsd-core/bin/shared/config-schema.manifest.json +12 -1
- package/gsd-core/bin/shared/exit-codes.json +8 -0
- package/gsd-core/bin/shared/exit-codes.sh +20 -0
- package/gsd-core/bin/shared/model-catalog.json +8 -1
- package/gsd-core/references/agent-contracts.md +44 -26
- package/gsd-core/references/api-coverage.md +24 -2
- package/gsd-core/references/autonomous-smart-discuss.md +3 -3
- package/gsd-core/references/checkpoints.md +39 -21
- package/gsd-core/references/context-budget.md +1 -1
- package/gsd-core/references/decimal-phase-calculation.md +5 -5
- package/gsd-core/references/dispatch-isolation-gate.md +138 -0
- package/gsd-core/references/doc-conflict-engine.md +1 -1
- package/gsd-core/references/edge-probe.md +8 -0
- package/gsd-core/references/execute-mvp-tdd.md +4 -6
- package/gsd-core/references/execute-phase-between-wave-reset.md +15 -14
- package/gsd-core/references/execute-phase-context-guard.md +1 -1
- package/gsd-core/references/execute-phase-response-language.md +1 -1
- package/gsd-core/references/execute-phase-wave-guard.md +17 -11
- package/gsd-core/references/failing-direction.md +78 -0
- package/gsd-core/references/gate-prompts.md +1 -1
- package/gsd-core/references/git-integration.md +5 -5
- package/gsd-core/references/git-planning-commit.md +5 -4
- package/gsd-core/references/gsd-run-resolver.md +1 -1
- package/gsd-core/references/loop-hook-dispatch.md +61 -2
- package/gsd-core/references/model-profiles.md +12 -4
- package/gsd-core/references/mvp-concepts.md +9 -9
- package/gsd-core/references/nyquist-compliance.md +74 -0
- package/gsd-core/references/offer-next.md +3 -5
- package/gsd-core/references/phase-argument-parsing.md +3 -3
- package/gsd-core/references/planner-failing-direction.md +53 -0
- package/gsd-core/references/planner-guidance.md +3 -9
- package/gsd-core/references/planner-human-verify-mode.md +15 -1
- package/gsd-core/references/planner-preconditions.md +1 -1
- package/gsd-core/references/planner-reviews.md +1 -1
- package/gsd-core/references/planner-revision.md +1 -1
- package/gsd-core/references/planner-verify-command-grounding.md +17 -0
- package/gsd-core/references/planning-config.md +44 -13
- package/gsd-core/references/reviewer-instances.md +31 -0
- package/gsd-core/references/revision-loop.md +1 -1
- package/gsd-core/references/runtime-aware-dispatch.md +1 -1
- package/gsd-core/references/specless-probe-fallback.md +1 -1
- package/gsd-core/references/tdd.md +1 -3
- package/gsd-core/references/ui-brand.md +65 -21
- package/gsd-core/references/ui-consideration-probe.md +1 -1
- package/gsd-core/references/universal-anti-patterns.md +5 -5
- package/gsd-core/references/verifier-phase-gates.md +192 -0
- package/gsd-core/references/verify-command-path-resolvability.md +42 -0
- package/gsd-core/references/verify-mvp-mode.md +2 -2
- package/gsd-core/references/workstream-flag.md +33 -17
- package/gsd-core/templates/README.md +1 -1
- package/gsd-core/templates/SECURITY.md +3 -3
- package/gsd-core/templates/UI-SPEC.md +25 -3
- package/gsd-core/templates/VALIDATION.md +3 -3
- package/gsd-core/templates/discussion-log.md +1 -1
- package/gsd-core/templates/phase-prompt.md +5 -4
- package/gsd-core/templates/state.md +11 -4
- package/gsd-core/templates/verification-report.md +9 -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 +3 -3
- package/gsd-core/workflows/add-tests.md +3 -8
- package/gsd-core/workflows/add-todo.md +1 -1
- package/gsd-core/workflows/ai-integration-phase.md +13 -20
- package/gsd-core/workflows/audit-fix.md +12 -3
- package/gsd-core/workflows/audit-milestone.md +9 -9
- package/gsd-core/workflows/audit-uat.md +17 -2
- package/gsd-core/workflows/autonomous/steps/converge-fail-fast.md +2 -2
- package/gsd-core/workflows/autonomous.md +11 -27
- package/gsd-core/workflows/check-todos.md +1 -1
- package/gsd-core/workflows/cleanup.md +64 -5
- package/gsd-core/workflows/code-review/steps/structural-pre-pass.md +14 -4
- package/gsd-core/workflows/code-review-fix.md +38 -11
- package/gsd-core/workflows/code-review.md +159 -52
- package/gsd-core/workflows/complete-milestone.md +151 -23
- package/gsd-core/workflows/debug.md +12 -8
- package/gsd-core/workflows/diagnose-issues.md +47 -15
- package/gsd-core/workflows/discuss-phase/modes/advisor.md +1 -1
- package/gsd-core/workflows/discuss-phase/modes/chain.md +5 -8
- package/gsd-core/workflows/discuss-phase/modes/default.md +1 -1
- package/gsd-core/workflows/discuss-phase/modes/text.md +1 -1
- package/gsd-core/workflows/discuss-phase-assumptions/steps/auto-advance-dispatch.md +1 -3
- package/gsd-core/workflows/discuss-phase-assumptions.md +4 -3
- package/gsd-core/workflows/discuss-phase.md +1 -1
- package/gsd-core/workflows/do.md +3 -6
- package/gsd-core/workflows/docs-update.md +5 -4
- package/gsd-core/workflows/edit-phase.md +27 -2
- package/gsd-core/workflows/eval-review.md +7 -14
- package/gsd-core/workflows/execute-phase/steps/codebase-drift-gate.md +1 -1
- package/gsd-core/workflows/execute-phase/steps/executor-isolation-dispatch.md +142 -15
- package/gsd-core/workflows/execute-phase/steps/gap-closure-artifacts.md +1 -1
- package/gsd-core/workflows/execute-phase/steps/partial-wave.md +1 -1
- package/gsd-core/workflows/execute-phase/steps/per-plan-executor-routing.md +77 -0
- package/gsd-core/workflows/execute-phase/steps/per-plan-worktree-gate.md +24 -4
- package/gsd-core/workflows/execute-phase/steps/post-merge-gate.md +2 -2
- package/gsd-core/workflows/execute-phase/steps/protected-branch.md +21 -0
- package/gsd-core/workflows/execute-phase/steps/regression-gate-run.md +2 -2
- package/gsd-core/workflows/execute-phase/steps/wave-post-gate-hooks.md +39 -0
- package/gsd-core/workflows/execute-phase.md +72 -100
- package/gsd-core/workflows/execute-plan.md +52 -15
- package/gsd-core/workflows/explore.md +131 -4
- package/gsd-core/workflows/extract-learnings.md +1 -1
- package/gsd-core/workflows/fast.md +10 -2
- package/gsd-core/workflows/forensics.md +1 -1
- package/gsd-core/workflows/graduation.md +5 -5
- package/gsd-core/workflows/health.md +76 -10
- package/gsd-core/workflows/import.md +18 -15
- package/gsd-core/workflows/inbox.md +4 -5
- package/gsd-core/workflows/ingest-docs.md +49 -16
- package/gsd-core/workflows/insert-phase.md +5 -5
- package/gsd-core/workflows/list-seeds.md +5 -3
- package/gsd-core/workflows/list-workspaces.md +1 -1
- package/gsd-core/workflows/manager.md +12 -23
- package/gsd-core/workflows/map-codebase.md +1 -1
- package/gsd-core/workflows/milestone-summary.md +1 -1
- package/gsd-core/workflows/mvp-phase.md +8 -5
- package/gsd-core/workflows/new-milestone.md +22 -29
- package/gsd-core/workflows/new-project/steps/auto-mode-config.md +1 -1
- package/gsd-core/workflows/new-project.md +26 -40
- package/gsd-core/workflows/new-workspace.md +1 -1
- package/gsd-core/workflows/next.md +14 -2
- package/gsd-core/workflows/pause-work.md +1 -1
- package/gsd-core/workflows/plan-phase/steps/adr-ingest-express-path.md +1 -1
- package/gsd-core/workflows/plan-phase/steps/chunked-planning-mode.md +1 -1
- package/gsd-core/workflows/plan-phase/steps/prd-express-path.md +2 -4
- package/gsd-core/workflows/plan-phase/steps/stall-detection-helpers.md +3 -3
- package/gsd-core/workflows/plan-phase.md +162 -59
- package/gsd-core/workflows/plan-review-convergence.md +96 -11
- package/gsd-core/workflows/plant-seed.md +2 -2
- package/gsd-core/workflows/pr-branch.md +187 -51
- package/gsd-core/workflows/profile-user.md +16 -14
- package/gsd-core/workflows/progress.md +61 -18
- package/gsd-core/workflows/quick/steps/discussion-phase.md +1 -3
- package/gsd-core/workflows/quick/steps/plan-checker-loop.md +5 -7
- package/gsd-core/workflows/quick/steps/quick-verification.md +28 -9
- package/gsd-core/workflows/quick/steps/research-phase.md +4 -6
- package/gsd-core/workflows/quick/steps/worktree-pre-dispatch-commit.md +3 -3
- package/gsd-core/workflows/quick.md +55 -44
- package/gsd-core/workflows/remove-phase.md +4 -4
- package/gsd-core/workflows/remove-workspace.md +2 -2
- package/gsd-core/workflows/resume-project.md +8 -12
- package/gsd-core/workflows/review.md +219 -20
- package/gsd-core/workflows/scan.md +1 -1
- package/gsd-core/workflows/secure-phase.md +3 -3
- package/gsd-core/workflows/session-report.md +2 -1
- package/gsd-core/workflows/settings-advanced.md +7 -9
- package/gsd-core/workflows/settings-integrations.md +64 -31
- package/gsd-core/workflows/settings.md +69 -7
- package/gsd-core/workflows/ship.md +116 -50
- package/gsd-core/workflows/sketch-wrap-up.md +11 -17
- package/gsd-core/workflows/sketch.md +12 -18
- package/gsd-core/workflows/smart-entry.md +3 -5
- package/gsd-core/workflows/spec-phase.md +53 -13
- package/gsd-core/workflows/spike-wrap-up.md +7 -11
- package/gsd-core/workflows/spike.md +20 -31
- package/gsd-core/workflows/stats.md +2 -2
- package/gsd-core/workflows/sync-skills.md +64 -9
- package/gsd-core/workflows/thread.md +11 -7
- package/gsd-core/workflows/transition.md +49 -14
- package/gsd-core/workflows/ui-phase.md +15 -21
- package/gsd-core/workflows/ui-review.md +8 -12
- package/gsd-core/workflows/ultraplan-phase.md +5 -13
- package/gsd-core/workflows/undo.md +8 -16
- package/gsd-core/workflows/update.md +7 -11
- package/gsd-core/workflows/validate-phase.md +3 -3
- package/gsd-core/workflows/verify-work/steps/automated-ui-verification.md +25 -1
- package/gsd-core/workflows/verify-work/steps/mvp-uat-framing.md +1 -1
- package/gsd-core/workflows/verify-work.md +66 -25
- package/hooks/dist/gsd-agent-isolation-guard.js +158 -30
- package/hooks/dist/gsd-check-update-worker.js +56 -13
- package/hooks/dist/gsd-check-update.js +19 -1
- package/hooks/dist/gsd-config-reload.js +18 -12
- package/hooks/dist/gsd-context-monitor.js +19 -10
- package/hooks/dist/gsd-cursor-post-tool.js +3 -1
- package/hooks/dist/gsd-cursor-pre-tool.js +2 -3
- package/hooks/dist/gsd-cursor-session-start.js +2 -1
- package/hooks/dist/gsd-cursor-stop.js +2 -1
- package/hooks/dist/gsd-cursor-subagent-start.js +83 -3
- package/hooks/dist/gsd-cursor-subagent-stop.js +6 -3
- package/hooks/dist/gsd-ensure-canonical-path.js +2 -1
- package/hooks/dist/gsd-graphify-update.sh +22 -18
- package/hooks/dist/gsd-node-runner.sh +76 -0
- package/hooks/dist/gsd-phase-boundary.sh +1 -0
- package/hooks/dist/gsd-prompt-guard.js +37 -27
- package/hooks/dist/gsd-read-guard.js +16 -7
- package/hooks/dist/gsd-read-injection-scanner.js +55 -32
- package/hooks/dist/gsd-session-state.sh +1 -0
- package/hooks/dist/gsd-statusline.js +231 -24
- package/hooks/dist/gsd-update-banner.js +22 -1
- package/hooks/dist/gsd-validate-commit.sh +80 -6
- package/hooks/dist/gsd-windsurf-pre-command.js +16 -11
- package/hooks/dist/gsd-windsurf-pre-write.js +22 -13
- package/hooks/dist/gsd-workflow-guard.js +162 -46
- package/hooks/dist/gsd-worktree-path-guard.js +36 -21
- package/hooks/dist/gsd-write-guard.js +35 -25
- package/hooks/dist/lib/cli-exit.js +560 -0
- package/hooks/dist/lib/exit-code-registry.js +98 -0
- package/hooks/dist/lib/git-cmd.js +92 -59
- package/hooks/dist/lib/git-probe.js +84 -0
- package/hooks/dist/lib/hook-exit.js +81 -0
- package/hooks/dist/lib/injection-patterns.js +45 -0
- package/hooks/dist/lib/isolation-deny-reason.js +39 -0
- package/hooks/dist/lib/isolation-sentinel.js +9 -0
- package/hooks/dist/managed-hooks-registry.cjs +3 -0
- package/hooks/gsd-agent-isolation-guard.js +158 -30
- package/hooks/gsd-check-update-worker.js +56 -13
- package/hooks/gsd-check-update.js +19 -1
- package/hooks/gsd-config-reload.js +18 -12
- package/hooks/gsd-context-monitor.js +19 -10
- package/hooks/gsd-cursor-post-tool.js +3 -1
- package/hooks/gsd-cursor-pre-tool.js +2 -3
- package/hooks/gsd-cursor-session-start.js +2 -1
- package/hooks/gsd-cursor-stop.js +2 -1
- package/hooks/gsd-cursor-subagent-start.js +83 -3
- package/hooks/gsd-cursor-subagent-stop.js +6 -3
- package/hooks/gsd-ensure-canonical-path.js +2 -1
- package/hooks/gsd-graphify-update.sh +22 -18
- package/hooks/gsd-node-runner.sh +76 -0
- package/hooks/gsd-phase-boundary.sh +1 -0
- package/hooks/gsd-prompt-guard.js +37 -27
- package/hooks/gsd-read-guard.js +16 -7
- package/hooks/gsd-read-injection-scanner.js +55 -32
- package/hooks/gsd-session-state.sh +1 -0
- package/hooks/gsd-statusline.js +231 -24
- package/hooks/gsd-update-banner.js +22 -1
- package/hooks/gsd-validate-commit.sh +80 -6
- package/hooks/gsd-windsurf-pre-command.js +16 -11
- package/hooks/gsd-windsurf-pre-write.js +22 -13
- package/hooks/gsd-workflow-guard.js +162 -46
- package/hooks/gsd-worktree-path-guard.js +36 -21
- package/hooks/gsd-write-guard.js +35 -25
- package/hooks/lib/cli-exit.js +560 -0
- package/hooks/lib/exit-code-registry.js +98 -0
- package/hooks/lib/git-cmd.js +92 -59
- package/hooks/lib/git-probe.js +84 -0
- package/hooks/lib/hook-exit.js +81 -0
- package/hooks/lib/injection-patterns.js +45 -0
- package/hooks/lib/isolation-deny-reason.js +39 -0
- package/hooks/lib/isolation-sentinel.js +9 -0
- package/hooks/managed-hooks-registry.cjs +3 -0
- package/package.json +28 -11
- package/pi/gsd.cjs +19 -5
- package/scripts/base64-scan.sh +74 -12
- package/scripts/baselines/planning-prompt-drift-baseline.json +4 -0
- package/scripts/baselines/planning-snapshot-bypass-baseline.json +12 -0
- package/scripts/baselines/unreachable-guard-drift-baseline.json +4 -0
- package/scripts/build-hooks.js +5 -0
- package/scripts/changeset/lint.cjs +60 -5
- package/scripts/check-alias-drift.cjs +7 -43
- package/scripts/check-contract-drift.cjs +297 -0
- package/scripts/check-glossary-refs.cjs +77 -15
- package/scripts/check-mutation-score-ratchet.cjs +156 -0
- package/scripts/ci-check-job-near-cap.cjs +49 -0
- package/scripts/ci-pr-mergeability.cjs +262 -0
- package/scripts/ci-test-scope.cjs +64 -14
- package/scripts/ci-timeout-report.cjs +230 -0
- package/scripts/command-contract-helpers.cjs +903 -1
- package/scripts/docs-guard-registry.cjs +396 -0
- package/scripts/gen-adr-index.cjs +728 -38
- package/scripts/gen-capability-registry.cjs +11 -21
- package/scripts/gen-context-index.cjs +2 -11
- package/scripts/gen-exit-code-docs.cjs +318 -0
- package/scripts/gen-exit-code-registry.cjs +891 -0
- package/scripts/gen-features.cjs +836 -0
- package/scripts/gen-health-docs.cjs +390 -0
- package/scripts/gen-hooks-cli-exit.cjs +239 -0
- package/scripts/gen-install-tree-fixtures.cjs +2 -2
- package/scripts/gen-inventory-manifest.cjs +50 -4
- package/scripts/gen-loop-host-contract.cjs +138 -25
- package/scripts/gen-registry.cjs +3 -14
- package/scripts/gen-scripts-cli-exit.cjs +185 -0
- package/scripts/gen-state-md-docs.cjs +727 -0
- package/scripts/{test-failure-reasons.cjs → gsd-test-gate-reasons.cjs} +6 -0
- package/scripts/lib/alias-drift-families.cjs +46 -0
- package/scripts/lib/ci-job-timing.cjs +72 -0
- package/scripts/lib/cli-exit.cjs +546 -44
- package/scripts/lib/drift-scan.cjs +308 -0
- package/scripts/lib/exit-code-registry.cjs +98 -0
- package/scripts/lib/ndjson-reporter.cjs +119 -0
- package/scripts/lint-allow-test-rule-refs.allowlist.json +1 -26
- package/scripts/lint-allow-test-rule-refs.effective-ceiling.json +4 -0
- package/scripts/lint-allow-test-rule-refs.unverified-ceiling.json +3 -0
- package/scripts/lint-canary-version-leak.cjs +73 -0
- package/scripts/lint-command-contract.cjs +96 -13
- package/scripts/lint-completion-predicate-drift.cjs +933 -0
- package/scripts/lint-completion-ratio-drift.cjs +214 -0
- package/scripts/lint-default-flip-documentation.cjs +193 -0
- package/scripts/lint-docs-guard-registration.cjs +495 -0
- package/scripts/lint-docs-guard-registration.exempt-baseline.cjs +193 -0
- package/scripts/lint-eslint-glob-coverage.allowlist.json +38 -0
- package/scripts/lint-eslint-glob-coverage.cjs +340 -0
- package/scripts/{lint-fix-has-regression-test.cjs → lint-fix-has-regression-tests.cjs} +12 -6
- package/scripts/lint-frontmatter-scalar-broad-grep.cjs +237 -0
- package/scripts/lint-health-diagnostic-rule-table.cjs +461 -0
- package/scripts/lint-hooks-runtime-build-seam.cjs +262 -0
- package/scripts/lint-milestone-window-drift.cjs +468 -0
- package/scripts/lint-mutation-test-derivation-drift.cjs +86 -0
- package/scripts/lint-phase-enumeration-drift.cjs +492 -0
- package/scripts/lint-plan-count-drift.cjs +318 -0
- package/scripts/lint-planning-artifact-writer-drift.cjs +398 -0
- package/scripts/lint-planning-prompt-drift.cjs +471 -0
- package/scripts/lint-planning-snapshot-bypass-drift.cjs +544 -0
- package/scripts/lint-regression-test-names.cjs +15 -13
- package/scripts/lint-removed-but-needed.cjs +488 -0
- package/scripts/lint-seam-enforcement.cjs +182 -0
- package/scripts/lint-slug-derivation-drift.cjs +921 -0
- package/scripts/lint-source-test-name-collision.cjs +241 -0
- package/scripts/lint-state-field-drift.cjs +805 -0
- package/scripts/lint-state-write-path-drift.cjs +950 -0
- package/scripts/lint-test-file-count.allowlist.json +137 -8
- package/scripts/lint-test-file-count.cjs +25 -3
- package/scripts/lint-unreachable-guard-drift.cjs +830 -0
- package/scripts/lint-vendored-deps.cjs +297 -0
- package/scripts/mutation-matrix.cjs +599 -50
- package/scripts/pr-changed-files.cjs +63 -0
- package/scripts/pr-template-policy.cjs +14 -4
- package/scripts/prompt-injection-scan.sh +100 -14
- package/scripts/require-issue-link-policy.cjs +192 -0
- package/scripts/secret-scan.sh +75 -13
- package/scripts/select-docs-guards.cjs +56 -0
- package/scripts/sync-runtime-launcher.cjs +24 -7
- package/skills/gsd-autonomous/SKILL.md +0 -1
- package/skills/gsd-code-review/SKILL.md +1 -1
- package/skills/gsd-discuss-phase/SKILL.md +1 -1
- package/skills/gsd-execute-phase/SKILL.md +1 -2
- package/skills/gsd-import/SKILL.md +1 -1
- package/skills/gsd-map-codebase/SKILL.md +1 -1
- package/skills/gsd-mempalace-capture/SKILL.md +1 -1
- package/skills/gsd-mempalace-recall/SKILL.md +1 -1
- package/skills/gsd-new-milestone/SKILL.md +1 -1
- package/skills/gsd-next/SKILL.md +0 -1
- package/skills/gsd-plan-phase/SKILL.md +0 -1
- package/skills/gsd-progress/SKILL.md +0 -1
- package/skills/gsd-quick/SKILL.md +9 -5
- package/skills/gsd-review-backlog/SKILL.md +2 -1
- package/skills/gsd-stats/SKILL.md +0 -1
- package/skills/gsd-verify-work/SKILL.md +1 -1
- package/vscode/package.json +1 -1
- package/bin/lib/ui-safety-gate.cjs +0 -107
- package/gsd-core/workflows/discovery-phase.md +0 -298
- package/gsd-core/workflows/plan-milestone-gaps.md +0 -281
- package/gsd-core/workflows/verify-phase.md +0 -574
- package/scripts/affected-tests-lib.cjs +0 -554
- package/scripts/lint-allow-test-rule-refs.cjs +0 -162
- package/scripts/lint-emitted-drift-ack.cjs +0 -344
- package/scripts/run-affected-tests.cjs +0 -7
- package/scripts/run-tests.cjs +0 -1051
|
@@ -17,7 +17,7 @@ Read all files referenced by the invoking prompt's execution_context before star
|
|
|
17
17
|
Parse arguments and load project state:
|
|
18
18
|
|
|
19
19
|
```bash
|
|
20
|
-
_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}"; if [ -f "$
|
|
20
|
+
_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; }; 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 unset -f gsd_run; _G="$(command -v gsd_run)"; then GSD_TOOLS="$_G"; gsd_run() { "$GSD_TOOLS" "$@"; }; elif _gsd_at "${CLAUDE_CONFIG_DIR:-$HOME/.claude}/gsd-core/bin/${_GSD_SHIM_NAME}" "${HERMES_HOME:-$HOME/.hermes}/gsd-core/bin/${_GSD_SHIM_NAME}" "${CURSOR_CONFIG_DIR:-$HOME/.cursor}/gsd-core/bin/${_GSD_SHIM_NAME}" "${CODEX_HOME:-$HOME/.codex}/gsd-core/bin/${_GSD_SHIM_NAME}" "${GEMINI_CONFIG_DIR:-$HOME/.gemini}/gsd-core/bin/${_GSD_SHIM_NAME}" "${COPILOT_CONFIG_DIR:-$HOME/.copilot}/gsd-core/bin/${_GSD_SHIM_NAME}" "${WINDSURF_CONFIG_DIR:-$HOME/.codeium/windsurf}/gsd-core/bin/${_GSD_SHIM_NAME}" "${AUGMENT_CONFIG_DIR:-$HOME/.augment}/gsd-core/bin/${_GSD_SHIM_NAME}" "${TRAE_CONFIG_DIR:-$HOME/.trae}/gsd-core/bin/${_GSD_SHIM_NAME}" "${QWEN_CONFIG_DIR:-$HOME/.qwen}/gsd-core/bin/${_GSD_SHIM_NAME}" "${CODEBUDDY_CONFIG_DIR:-$HOME/.codebuddy}/gsd-core/bin/${_GSD_SHIM_NAME}" "${CLINE_CONFIG_DIR:-$HOME/.cline}/gsd-core/bin/${_GSD_SHIM_NAME}" "${GROK_AGENTS_HOME:-$HOME/.agents}/gsd-core/bin/${_GSD_SHIM_NAME}" "${ANTIGRAVITY_CONFIG_DIR:-$HOME/.gemini/antigravity}/gsd-core/bin/${_GSD_SHIM_NAME}" "${OPENCODE_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/opencode}/gsd-core/bin/${_GSD_SHIM_NAME}" "${KILO_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/kilo}/gsd-core/bin/${_GSD_SHIM_NAME}"; then gsd_run() { node "$GSD_TOOLS" "$@"; }; else echo "ERROR: gsd-tools.cjs not found at $GSD_TOOLS and gsd_run is not on PATH. Run: npx -y @opengsd/gsd-core@latest --claude --local" >&2; exit 1; fi; GSD_IDENTITY_STATUS=unverified; case "$(gsd_run runtime-identity --raw 2>/dev/null || true)" in '{"packageName":"@opengsd/gsd-core"'*'}') GSD_IDENTITY_STATUS=ok;; esac; 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
|
|
21
21
|
PHASE_ARG="${1}"
|
|
22
22
|
|
|
23
23
|
# Parse all code-review flags into a structured IR via code-review-flags.cjs.
|
|
@@ -98,36 +98,6 @@ Exit workflow.
|
|
|
98
98
|
Default is active through the Capability Registry schema — only skip when the registry resolves no active code-review step hook. This check runs AFTER phase validation so invalid phase errors are shown first.
|
|
99
99
|
</step>
|
|
100
100
|
|
|
101
|
-
<step name="resolve_depth">
|
|
102
|
-
Determine review depth with priority order:
|
|
103
|
-
|
|
104
|
-
1. DEPTH_OVERRIDE from --depth flag (highest priority)
|
|
105
|
-
2. Config value: `gsd-tools.cjs query config-get workflow.code_review_depth 2>/dev/null`
|
|
106
|
-
3. Default: "standard"
|
|
107
|
-
|
|
108
|
-
```bash
|
|
109
|
-
if [ -n "$DEPTH_OVERRIDE" ]; then
|
|
110
|
-
REVIEW_DEPTH="$DEPTH_OVERRIDE"
|
|
111
|
-
else
|
|
112
|
-
CONFIG_DEPTH=$(gsd_run query config-get workflow.code_review_depth 2>/dev/null || echo "")
|
|
113
|
-
REVIEW_DEPTH="${CONFIG_DEPTH:-standard}"
|
|
114
|
-
fi
|
|
115
|
-
```
|
|
116
|
-
|
|
117
|
-
**Validate depth value:**
|
|
118
|
-
```bash
|
|
119
|
-
case "$REVIEW_DEPTH" in
|
|
120
|
-
quick|standard|deep)
|
|
121
|
-
# Valid
|
|
122
|
-
;;
|
|
123
|
-
*)
|
|
124
|
-
echo "Warning: Invalid depth '${REVIEW_DEPTH}'. Valid values: quick, standard, deep. Using 'standard'."
|
|
125
|
-
REVIEW_DEPTH="standard"
|
|
126
|
-
;;
|
|
127
|
-
esac
|
|
128
|
-
```
|
|
129
|
-
</step>
|
|
130
|
-
|
|
131
101
|
<step name="compute_file_scope">
|
|
132
102
|
Three-tier scoping with explicit precedence:
|
|
133
103
|
|
|
@@ -237,12 +207,26 @@ against the diff and warn about (then add) any changed files the SUMMARY extract
|
|
|
237
207
|
surface — so a partial SUMMARY result can no longer silently mask the rest of the phase.
|
|
238
208
|
```bash
|
|
239
209
|
# Compute diff base from phase commits — fail closed if no reliable base found.
|
|
240
|
-
# #
|
|
241
|
-
#
|
|
242
|
-
#
|
|
243
|
-
#
|
|
244
|
-
#
|
|
245
|
-
|
|
210
|
+
# #3503: anchor the grep to GSD's own conventional-commit phase scopes — the
|
|
211
|
+
# subject-line formats this system itself emits (docs(phase-N): from
|
|
212
|
+
# execute-phase.md, plan scopes feat(N-MM):/test(N-MM): from references/tdd.md,
|
|
213
|
+
# bare phase scopes docs(N):). The #2989/#3191 prose anchor "[Pp]hase N"
|
|
214
|
+
# matched free prose in ANY commit body — planning commits forward-reference
|
|
215
|
+
# later phases ("deferred to Phase N per D-09"), doc commits use "### Phase N"
|
|
216
|
+
# as a format example — and tail -1 (oldest match) turned each false positive
|
|
217
|
+
# into a base unboundedly before the phase, while GSD's own scope commits
|
|
218
|
+
# never contain the literal "Phase N" at all. The ^ anchor makes this a
|
|
219
|
+
# subject-line match, so commit-body prose can never capture the base.
|
|
220
|
+
# Workflows emit the UNPADDED roadmap phase number (docs(phase-6):) while
|
|
221
|
+
# PADDED_PHASE is zero-padded ("06") — accept both spellings.
|
|
222
|
+
# #3191: stay POSIX-ERE portable — the boundary is the closing paren + colon,
|
|
223
|
+
# never \b (not a POSIX ERE token; under --extended-regexp it silently matches
|
|
224
|
+
# nothing on macOS regex(3), making this fallback dead on Apple platforms).
|
|
225
|
+
PHASE_SCOPE_NUM="${PADDED_PHASE}"
|
|
226
|
+
case "${PADDED_PHASE}" in
|
|
227
|
+
0[0-9]*) PHASE_SCOPE_NUM="${PADDED_PHASE#0}|${PADDED_PHASE}" ;;
|
|
228
|
+
esac
|
|
229
|
+
PHASE_COMMITS=$(git log --oneline --all --extended-regexp --grep="^[[:alpha:]]+!?\((phase-)?(${PHASE_SCOPE_NUM})(-[0-9]+)?\)!?:" --format="%H" 2>/dev/null)
|
|
246
230
|
DIFF_BASE=""
|
|
247
231
|
if [ -n "$PHASE_COMMITS" ]; then
|
|
248
232
|
DIFF_BASE=$(echo "$PHASE_COMMITS" | tail -1)^
|
|
@@ -306,7 +290,7 @@ fi
|
|
|
306
290
|
|
|
307
291
|
**Post-processing (all tiers):**
|
|
308
292
|
|
|
309
|
-
1. **Expand tilde paths:** SUMMARY.md `key-files` entries may record a `~/...`-prefixed path (e.g. `~/.claude/gsd-core/workflows/verify-
|
|
293
|
+
1. **Expand tilde paths:** SUMMARY.md `key-files` entries may record a `~/...`-prefixed path (e.g. `~/.claude/gsd-core/workflows/verify-work.md`). 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.
|
|
310
294
|
```bash
|
|
311
295
|
EXPANDED_FILES=()
|
|
312
296
|
for file in "${REVIEW_FILES[@]}"; do
|
|
@@ -380,12 +364,122 @@ echo "File scope: ${#REVIEW_FILES[@]} files from ${TIER}"
|
|
|
380
364
|
if [ ${#REVIEW_FILES[@]} -gt 50 ]; then
|
|
381
365
|
echo "Warning: ${#REVIEW_FILES[@]} files is a large review scope."
|
|
382
366
|
echo "Consider using --files to narrow scope, or --depth=quick for a faster pass."
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
367
|
+
fi
|
|
368
|
+
```
|
|
369
|
+
</step>
|
|
370
|
+
|
|
371
|
+
<step name="resolve_depth">
|
|
372
|
+
Determine review depth via the path-scoped depth resolver (`code-review-depth.cjs`). This step runs after `compute_file_scope` because rule matching needs the final `REVIEW_FILES` set.
|
|
373
|
+
|
|
374
|
+
```bash
|
|
375
|
+
CONFIG_DEPTH=$(gsd_run query config-get workflow.code_review_depth --raw 2>/dev/null || echo "")
|
|
376
|
+
DEPTH_OVERRIDES=$(gsd_run query config-get workflow.code_review_depth_overrides --default '[]' 2>/dev/null || echo '[]')
|
|
377
|
+
REPO_ROOT=$(git rev-parse --show-toplevel 2>/dev/null)
|
|
378
|
+
|
|
379
|
+
# Files travel on stdin, never argv — a 50+-file scope with long paths approaches the
|
|
380
|
+
# Windows execFileSync 32,767-char argv ceiling; stdin has no such bound.
|
|
381
|
+
DEPTH_PAYLOAD=$(printf '%s\n' "${REVIEW_FILES[@]}" | FLAG_DEPTH="$DEPTH_OVERRIDE" CONFIG_DEPTH="$CONFIG_DEPTH" DEPTH_OVERRIDES="$DEPTH_OVERRIDES" REPO_ROOT="$REPO_ROOT" node -e "
|
|
382
|
+
const files = require('fs').readFileSync('/dev/stdin', 'utf-8').split('\n').filter(Boolean);
|
|
383
|
+
process.stdout.write(JSON.stringify({
|
|
384
|
+
flagDepth: process.env.FLAG_DEPTH || '',
|
|
385
|
+
configDepth: process.env.CONFIG_DEPTH || '',
|
|
386
|
+
overrides: JSON.parse(process.env.DEPTH_OVERRIDES || '[]'),
|
|
387
|
+
files,
|
|
388
|
+
repoRoot: process.env.REPO_ROOT || '',
|
|
389
|
+
}));
|
|
390
|
+
")
|
|
391
|
+
|
|
392
|
+
DEPTH_JSON=$(echo "$DEPTH_PAYLOAD" | node -e "
|
|
393
|
+
const { resolveCodeReviewDepth } = require('./gsd-core/bin/lib/code-review-depth.cjs');
|
|
394
|
+
const input = JSON.parse(require('fs').readFileSync('/dev/stdin', 'utf-8'));
|
|
395
|
+
process.stdout.write(JSON.stringify(resolveCodeReviewDepth(input)));
|
|
396
|
+
")
|
|
397
|
+
|
|
398
|
+
DEPTH_OK=$(echo "$DEPTH_JSON" | node -e "process.stdout.write(String(JSON.parse(require('fs').readFileSync('/dev/stdin','utf-8')).ok))")
|
|
399
|
+
```
|
|
400
|
+
|
|
401
|
+
The guard and the extraction it protects must run as one shell control-flow decision — a prose sentence between two fenced blocks is not a guard, since fenced blocks do not share shell state. Anything other than the literal string `true` (including an empty `DEPTH_OK`, which is what a crashed or missing resolver produces) is treated as failure, and the failure branch exits before any extraction can run:
|
|
402
|
+
|
|
403
|
+
```bash
|
|
404
|
+
if [ "$DEPTH_OK" = "true" ]; then
|
|
405
|
+
# Single spawn: emit all seven fields as Unit-Separator-delimited (U+001F) values,
|
|
406
|
+
# fixed order. Field '\x1f' (not '\n') is deliberate: bash's `read` treats '\n' as
|
|
407
|
+
# "IFS whitespace" and collapses runs of it, silently dropping an empty field (e.g.
|
|
408
|
+
# DEPTH_MATCHED_RULE_PATH when matchedRule is null) — '\x1f' is not IFS-whitespace,
|
|
409
|
+
# so each empty field survives as its own zero-length token. This is safe only
|
|
410
|
+
# because validateRulePath (src/code-review-depth.cts) rejects any rule path
|
|
411
|
+
# carrying an interior control character, including U+001F itself — so
|
|
412
|
+
# DEPTH_MATCHED_RULE_PATH below can never collide with the delimiter. Do not
|
|
413
|
+
# remove that validation without revisiting this split.
|
|
414
|
+
DEPTH_FIELDS=$(echo "$DEPTH_JSON" | node -e "
|
|
415
|
+
const d = JSON.parse(require('fs').readFileSync('/dev/stdin', 'utf-8'));
|
|
416
|
+
const r = d.matchedRule;
|
|
417
|
+
process.stdout.write([
|
|
418
|
+
d.depth,
|
|
419
|
+
d.source,
|
|
420
|
+
r ? String(r.index) : '',
|
|
421
|
+
r ? r.path : '',
|
|
422
|
+
String(!!d.invalidFlagDepth),
|
|
423
|
+
String(!!d.invalidConfigDepth),
|
|
424
|
+
String(!!d.downgraded),
|
|
425
|
+
].join('\x1f'));
|
|
426
|
+
")
|
|
427
|
+
IFS=$'\x1f' read -r -d '' REVIEW_DEPTH DEPTH_SOURCE DEPTH_MATCHED_RULE_INDEX DEPTH_MATCHED_RULE_PATH \
|
|
428
|
+
DEPTH_INVALID_FLAG DEPTH_INVALID_CONFIG DEPTH_DOWNGRADED <<< "$DEPTH_FIELDS" || true
|
|
429
|
+
# <<< always appends a trailing newline to its input; strip it from the last field.
|
|
430
|
+
DEPTH_DOWNGRADED="${DEPTH_DOWNGRADED%$'\n'}"
|
|
431
|
+
|
|
432
|
+
case "$DEPTH_SOURCE" in
|
|
433
|
+
flag) DEPTH_PROVENANCE="from --depth flag" ;;
|
|
434
|
+
rule) DEPTH_PROVENANCE="matched rule ${DEPTH_MATCHED_RULE_INDEX}: ${DEPTH_MATCHED_RULE_PATH}" ;;
|
|
435
|
+
config) DEPTH_PROVENANCE="from workflow.code_review_depth" ;;
|
|
436
|
+
*) DEPTH_PROVENANCE="default" ;;
|
|
437
|
+
esac
|
|
438
|
+
echo "Review depth: ${REVIEW_DEPTH} (${DEPTH_PROVENANCE})"
|
|
439
|
+
|
|
440
|
+
if [ "$DEPTH_INVALID_FLAG" = "true" ]; then
|
|
441
|
+
echo "Warning: Invalid depth '${DEPTH_OVERRIDE}'. Valid values: quick, standard, deep. Using 'standard'."
|
|
442
|
+
fi
|
|
443
|
+
if [ "$DEPTH_INVALID_CONFIG" = "true" ]; then
|
|
444
|
+
echo "Warning: Invalid depth '${CONFIG_DEPTH}'. Valid values: quick, standard, deep. Using 'standard'."
|
|
445
|
+
fi
|
|
446
|
+
|
|
447
|
+
if [ "$DEPTH_DOWNGRADED" = "true" ]; then
|
|
448
|
+
if [ -n "$DEPTH_MATCHED_RULE_INDEX" ]; then
|
|
449
|
+
echo "Switching from deep to standard depth for large file count (overrides matched rule ${DEPTH_MATCHED_RULE_INDEX}: ${DEPTH_MATCHED_RULE_PATH})."
|
|
450
|
+
else
|
|
451
|
+
echo "Switching from deep to standard depth for large file count."
|
|
452
|
+
fi
|
|
386
453
|
fi
|
|
454
|
+
else
|
|
455
|
+
# DEPTH_OK is anything but the literal string "true" — including empty, which is
|
|
456
|
+
# what a crashed or missing resolver produces. workflow.code_review_depth_overrides
|
|
457
|
+
# is misconfigured. Print every collected error — never fall back to a default
|
|
458
|
+
# depth, since silently reviewing a misconfigured sensitive-path policy at
|
|
459
|
+
# `standard` is the exact hole this feature closes — then hard-stop before
|
|
460
|
+
# REVIEW_DEPTH can be read by any later step.
|
|
461
|
+
echo "$DEPTH_JSON" | node -e "
|
|
462
|
+
let parsed;
|
|
463
|
+
try {
|
|
464
|
+
parsed = JSON.parse(require('fs').readFileSync('/dev/stdin', 'utf-8'));
|
|
465
|
+
} catch {
|
|
466
|
+
parsed = {};
|
|
467
|
+
}
|
|
468
|
+
const errors = Array.isArray(parsed.errors) ? parsed.errors : [];
|
|
469
|
+
for (const err of errors) {
|
|
470
|
+
const parts = [];
|
|
471
|
+
if (err.ruleIndex !== undefined) parts.push('rule ' + err.ruleIndex);
|
|
472
|
+
if (err.path !== undefined) parts.push('path \"' + err.path + '\"');
|
|
473
|
+
if (err.value !== undefined) parts.push('depth \"' + err.value + '\"');
|
|
474
|
+
console.error('Error: workflow.code_review_depth_overrides' + (parts.length ? ' (' + parts.join(', ') + ')' : '') + ': ' + err.reason);
|
|
475
|
+
}
|
|
476
|
+
"
|
|
477
|
+
echo "Error: Fix workflow.code_review_depth_overrides and retry."
|
|
478
|
+
echo "Error: Depth resolution failed (DEPTH_OK=\"${DEPTH_OK}\"). Halting before agent spawn."
|
|
479
|
+
exit 1
|
|
387
480
|
fi
|
|
388
481
|
```
|
|
482
|
+
This `if`/`else`/`fi` is the entire guard: when `DEPTH_OK` is not the literal string `true`, execution never reaches the `DEPTH_FIELDS`/`REVIEW_DEPTH` extraction — the `else` branch prints the errors, prints the final `Error:` line above, and `exit 1`s out of the fenced block, so `REVIEW_DEPTH` is never set. Exit workflow. Do NOT spawn agent or create REVIEW.md.
|
|
389
483
|
</step>
|
|
390
484
|
|
|
391
485
|
<step name="check_empty_scope">
|
|
@@ -423,17 +517,29 @@ Compute the review output path:
|
|
|
423
517
|
REVIEW_PATH="${PHASE_DIR}/${PADDED_PHASE}-REVIEW.md"
|
|
424
518
|
```
|
|
425
519
|
|
|
426
|
-
Compute DIFF_BASE for agent context (in case agent needs it):
|
|
520
|
+
Compute DIFF_BASE for agent context (in case agent needs it). #3191/#3503: this
|
|
521
|
+
must be the SAME anchored, POSIX-portable conventional-commit-scope derivation
|
|
522
|
+
the Tier-3 scope step uses — the reviewer agent consumes `diff_base` exactly
|
|
523
|
+
when `files:` is empty, i.e. the same fail-closed scenario Tier 3 protects, so
|
|
524
|
+
a divergent recomputation here re-arms the mis-scoping one tier down:
|
|
427
525
|
```bash
|
|
428
|
-
|
|
526
|
+
PHASE_SCOPE_NUM="${PADDED_PHASE}"
|
|
527
|
+
case "${PADDED_PHASE}" in
|
|
528
|
+
0[0-9]*) PHASE_SCOPE_NUM="${PADDED_PHASE#0}|${PADDED_PHASE}" ;;
|
|
529
|
+
esac
|
|
530
|
+
PHASE_COMMITS=$(git log --oneline --all --extended-regexp --grep="^[[:alpha:]]+!?\((phase-)?(${PHASE_SCOPE_NUM})(-[0-9]+)?\)!?:" --format="%H" 2>/dev/null)
|
|
429
531
|
if [ -n "$PHASE_COMMITS" ]; then
|
|
430
532
|
DIFF_BASE=$(echo "$PHASE_COMMITS" | tail -1)^
|
|
533
|
+
# Verify the parent commit exists (first commit in repo has no parent)
|
|
534
|
+
if ! git rev-parse "${DIFF_BASE}" >/dev/null 2>&1; then
|
|
535
|
+
DIFF_BASE=$(echo "$PHASE_COMMITS" | tail -1)
|
|
536
|
+
fi
|
|
431
537
|
else
|
|
432
538
|
DIFF_BASE=""
|
|
433
539
|
fi
|
|
434
540
|
```
|
|
435
541
|
|
|
436
|
-
Build
|
|
542
|
+
Build required_reading block for agent:
|
|
437
543
|
```bash
|
|
438
544
|
FILES_TO_READ=""
|
|
439
545
|
for file in "${REVIEW_FILES[@]}"; do
|
|
@@ -488,9 +594,9 @@ Print: `◆ Spawning code reviewer... (runs in a subagent — no output until it
|
|
|
488
594
|
|
|
489
595
|
```
|
|
490
596
|
Agent(subagent_type="gsd-code-reviewer", model="{REVIEWER_MODEL}", prompt="
|
|
491
|
-
<
|
|
597
|
+
<required_reading>
|
|
492
598
|
${FILES_TO_READ}
|
|
493
|
-
</
|
|
599
|
+
</required_reading>
|
|
494
600
|
|
|
495
601
|
${STRUCTURAL_FINDINGS_BLOCK}
|
|
496
602
|
|
|
@@ -584,23 +690,24 @@ TOTAL=$(echo "$FRONTMATTER" | grep "total:" | head -1 | cut -d: -f2 | xargs)
|
|
|
584
690
|
Display inline summary to user:
|
|
585
691
|
|
|
586
692
|
```
|
|
587
|
-
|
|
693
|
+
---
|
|
588
694
|
|
|
589
695
|
Code Review Complete: Phase ${PHASE_NUMBER} (${PHASE_NAME})
|
|
590
696
|
|
|
591
|
-
|
|
697
|
+
---
|
|
592
698
|
|
|
593
|
-
Depth: ${REVIEW_DEPTH}
|
|
699
|
+
Depth: ${REVIEW_DEPTH} (${DEPTH_PROVENANCE})
|
|
594
700
|
Files Reviewed: ${FILES_REVIEWED}
|
|
595
701
|
|
|
596
702
|
Findings:
|
|
597
703
|
Critical: ${CRITICAL}
|
|
598
704
|
Warning: ${WARNING}
|
|
599
705
|
Info: ${INFO}
|
|
600
|
-
|
|
706
|
+
|
|
707
|
+
---
|
|
601
708
|
Total: ${TOTAL}
|
|
602
709
|
|
|
603
|
-
|
|
710
|
+
---
|
|
604
711
|
```
|
|
605
712
|
|
|
606
713
|
If status is "clean":
|
|
@@ -629,7 +736,7 @@ grep -A 3 "^### CR-\|^### BL-\|^### WR-" "${REVIEW_PATH}" | head -n 12
|
|
|
629
736
|
|
|
630
737
|
**Note on tests:** Automated tests for this command and workflow are planned for Phase 4 (Pipeline Integration & Testing, requirement INFR-03). Phase 2 focuses on correct implementation; Phase 4 adds regression coverage across platforms.
|
|
631
738
|
|
|
632
|
-
|
|
739
|
+
---
|
|
633
740
|
</step>
|
|
634
741
|
|
|
635
742
|
</process>
|
|
@@ -41,8 +41,8 @@ When a milestone completes:
|
|
|
41
41
|
Before proceeding with milestone close, run the comprehensive open artifact audit.
|
|
42
42
|
|
|
43
43
|
```bash
|
|
44
|
-
_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}"; if [ -f "$
|
|
45
|
-
RESPONSE_LANGUAGE=$(gsd_run query config-get response_language --default "" 2>/dev/null || echo "")
|
|
44
|
+
_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; }; 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 unset -f gsd_run; _G="$(command -v gsd_run)"; then GSD_TOOLS="$_G"; gsd_run() { "$GSD_TOOLS" "$@"; }; elif _gsd_at "${CLAUDE_CONFIG_DIR:-$HOME/.claude}/gsd-core/bin/${_GSD_SHIM_NAME}" "${HERMES_HOME:-$HOME/.hermes}/gsd-core/bin/${_GSD_SHIM_NAME}" "${CURSOR_CONFIG_DIR:-$HOME/.cursor}/gsd-core/bin/${_GSD_SHIM_NAME}" "${CODEX_HOME:-$HOME/.codex}/gsd-core/bin/${_GSD_SHIM_NAME}" "${GEMINI_CONFIG_DIR:-$HOME/.gemini}/gsd-core/bin/${_GSD_SHIM_NAME}" "${COPILOT_CONFIG_DIR:-$HOME/.copilot}/gsd-core/bin/${_GSD_SHIM_NAME}" "${WINDSURF_CONFIG_DIR:-$HOME/.codeium/windsurf}/gsd-core/bin/${_GSD_SHIM_NAME}" "${AUGMENT_CONFIG_DIR:-$HOME/.augment}/gsd-core/bin/${_GSD_SHIM_NAME}" "${TRAE_CONFIG_DIR:-$HOME/.trae}/gsd-core/bin/${_GSD_SHIM_NAME}" "${QWEN_CONFIG_DIR:-$HOME/.qwen}/gsd-core/bin/${_GSD_SHIM_NAME}" "${CODEBUDDY_CONFIG_DIR:-$HOME/.codebuddy}/gsd-core/bin/${_GSD_SHIM_NAME}" "${CLINE_CONFIG_DIR:-$HOME/.cline}/gsd-core/bin/${_GSD_SHIM_NAME}" "${GROK_AGENTS_HOME:-$HOME/.agents}/gsd-core/bin/${_GSD_SHIM_NAME}" "${ANTIGRAVITY_CONFIG_DIR:-$HOME/.gemini/antigravity}/gsd-core/bin/${_GSD_SHIM_NAME}" "${OPENCODE_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/opencode}/gsd-core/bin/${_GSD_SHIM_NAME}" "${KILO_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/kilo}/gsd-core/bin/${_GSD_SHIM_NAME}"; then gsd_run() { node "$GSD_TOOLS" "$@"; }; else echo "ERROR: gsd-tools.cjs not found at $GSD_TOOLS and gsd_run is not on PATH. Run: npx -y @opengsd/gsd-core@latest --claude --local" >&2; exit 1; fi; GSD_IDENTITY_STATUS=unverified; case "$(gsd_run runtime-identity --raw 2>/dev/null || true)" in '{"packageName":"@opengsd/gsd-core"'*'}') GSD_IDENTITY_STATUS=ok;; esac; 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
|
|
45
|
+
RESPONSE_LANGUAGE=$(gsd_run query config-get response_language --raw --default "" 2>/dev/null || echo "")
|
|
46
46
|
gsd_run query audit-open
|
|
47
47
|
```
|
|
48
48
|
|
|
@@ -61,26 +61,135 @@ These items are open. Choose an action:
|
|
|
61
61
|
```
|
|
62
62
|
|
|
63
63
|
If user chooses [A] (Acknowledge):
|
|
64
|
-
1. Re-run `
|
|
65
|
-
2.
|
|
64
|
+
1. Re-run `gsd_run query audit-open --json` to get structured data.
|
|
65
|
+
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:
|
|
66
|
+
```bash
|
|
67
|
+
AUDIT_JSON=$(gsd_run query audit-open --json)
|
|
68
|
+
if [[ "$AUDIT_JSON" == @file:* ]]; then AUDIT_JSON=$(cat "${AUDIT_JSON#@file:}"); fi
|
|
69
|
+
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
|
|
70
|
+
|
|
71
|
+
ACK_FAILURES=0
|
|
72
|
+
ACK_FAILURE_LOG=""
|
|
73
|
+
record_ack_failure() {
|
|
74
|
+
ACK_FAILURES=$((ACK_FAILURES + 1))
|
|
75
|
+
ACK_FAILURE_LOG="${ACK_FAILURE_LOG}
|
|
76
|
+
- $1"
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
# debug_sessions / threads (--slug)
|
|
80
|
+
# NOTE: `< <(...)` process substitution, not `... | while`, so the loop
|
|
81
|
+
# runs in THIS shell — a `| while` pipeline puts the loop in a subshell
|
|
82
|
+
# and any ACK_FAILURES/ACK_FAILURE_LOG update inside it is lost the
|
|
83
|
+
# moment the pipeline exits.
|
|
84
|
+
for cat in debug_sessions threads; do
|
|
85
|
+
while IFS= read -r slug; do
|
|
86
|
+
[ -z "$slug" ] && continue
|
|
87
|
+
if ! gsd_run query audit-open acknowledge --category "$cat" --milestone "$MILESTONE_VERSION" --slug "$slug"; then
|
|
88
|
+
record_ack_failure "$cat slug=$slug"
|
|
89
|
+
fi
|
|
90
|
+
done < <(printf '%s' "$AUDIT_JSON" | jq -r --arg cat "$cat" '.items[$cat][] | select(.scan_error | not) | .slug')
|
|
91
|
+
done
|
|
92
|
+
|
|
93
|
+
# seeds (--seed-id)
|
|
94
|
+
while IFS= read -r seed_id; do
|
|
95
|
+
[ -z "$seed_id" ] && continue
|
|
96
|
+
if ! gsd_run query audit-open acknowledge --category seeds --milestone "$MILESTONE_VERSION" --seed-id "$seed_id"; then
|
|
97
|
+
record_ack_failure "seeds seed_id=$seed_id"
|
|
98
|
+
fi
|
|
99
|
+
done < <(printf '%s' "$AUDIT_JSON" | jq -r '.items.seeds[] | select(.scan_error | not) | .seed_id')
|
|
100
|
+
|
|
101
|
+
# todos (--filename) — the scanner caps its list to 5 entries per scan
|
|
102
|
+
# (remainder items carry `_remainder_count`, no `filename`, and are skipped)
|
|
103
|
+
while IFS= read -r filename; do
|
|
104
|
+
[ -z "$filename" ] && continue
|
|
105
|
+
if ! gsd_run query audit-open acknowledge --category todos --milestone "$MILESTONE_VERSION" --filename "$filename"; then
|
|
106
|
+
record_ack_failure "todos filename=$filename"
|
|
107
|
+
fi
|
|
108
|
+
done < <(printf '%s' "$AUDIT_JSON" | jq -r '.items.todos[] | select((.scan_error or ._remainder_count) | not) | .filename')
|
|
109
|
+
|
|
110
|
+
# quick_tasks (--dir) — the scanner's `slug` strips a leading
|
|
111
|
+
# YYYYMMDD-/YYYY-MM-DD- date prefix for display; `--dir` needs the
|
|
112
|
+
# ORIGINAL .planning/quick/<dir>/ name, so reconstruct it from `date`+`slug`.
|
|
113
|
+
while IFS= read -r dir; do
|
|
114
|
+
[ -z "$dir" ] && continue
|
|
115
|
+
if ! gsd_run query audit-open acknowledge --category quick_tasks --milestone "$MILESTONE_VERSION" --dir "$dir"; then
|
|
116
|
+
record_ack_failure "quick_tasks dir=$dir"
|
|
117
|
+
fi
|
|
118
|
+
done < <(printf '%s' "$AUDIT_JSON" | jq -r '.items.quick_tasks[] | select(.scan_error | not) | if .date != "" then "\(.date)-\(.slug)" else .slug end')
|
|
119
|
+
|
|
120
|
+
# uat_gaps / verification_gaps / context_questions — phase-scoped
|
|
121
|
+
# (--phase --file [--archived-milestone] when the item was found in an archived phase)
|
|
122
|
+
for cat in uat_gaps verification_gaps context_questions; do
|
|
123
|
+
while IFS= read -r item; do
|
|
124
|
+
[ -z "$item" ] && continue
|
|
125
|
+
phase=$(printf '%s' "$item" | jq -r '.phase')
|
|
126
|
+
file=$(printf '%s' "$item" | jq -r '.file')
|
|
127
|
+
archived=$(printf '%s' "$item" | jq -r '.archived_milestone // empty')
|
|
128
|
+
if [ -n "$archived" ]; then
|
|
129
|
+
if ! gsd_run query audit-open acknowledge --category "$cat" --milestone "$MILESTONE_VERSION" --phase "$phase" --file "$file" --archived-milestone "$archived"; then
|
|
130
|
+
record_ack_failure "$cat phase=$phase file=$file archived-milestone=$archived"
|
|
131
|
+
fi
|
|
132
|
+
else
|
|
133
|
+
if ! gsd_run query audit-open acknowledge --category "$cat" --milestone "$MILESTONE_VERSION" --phase "$phase" --file "$file"; then
|
|
134
|
+
record_ack_failure "$cat phase=$phase file=$file"
|
|
135
|
+
fi
|
|
136
|
+
fi
|
|
137
|
+
done < <(printf '%s' "$AUDIT_JSON" | jq -c --arg cat "$cat" '.items[$cat][] | select(.scan_error | not)')
|
|
138
|
+
done
|
|
139
|
+
|
|
140
|
+
# deferred_items — same phase-scoped identification, plus --text (the
|
|
141
|
+
# exact bullet the audit read, which uniquely identifies the entry)
|
|
142
|
+
while IFS= read -r item; do
|
|
143
|
+
[ -z "$item" ] && continue
|
|
144
|
+
phase=$(printf '%s' "$item" | jq -r '.phase')
|
|
145
|
+
file=$(printf '%s' "$item" | jq -r '.file')
|
|
146
|
+
text=$(printf '%s' "$item" | jq -r '.text')
|
|
147
|
+
archived=$(printf '%s' "$item" | jq -r '.archived_milestone // empty')
|
|
148
|
+
if [ -n "$archived" ]; then
|
|
149
|
+
if ! gsd_run query audit-open acknowledge --category deferred_items --milestone "$MILESTONE_VERSION" --phase "$phase" --file "$file" --text "$text" --archived-milestone "$archived"; then
|
|
150
|
+
record_ack_failure "deferred_items phase=$phase file=$file archived-milestone=$archived"
|
|
151
|
+
fi
|
|
152
|
+
else
|
|
153
|
+
if ! gsd_run query audit-open acknowledge --category deferred_items --milestone "$MILESTONE_VERSION" --phase "$phase" --file "$file" --text "$text"; then
|
|
154
|
+
record_ack_failure "deferred_items phase=$phase file=$file"
|
|
155
|
+
fi
|
|
156
|
+
fi
|
|
157
|
+
done < <(printf '%s' "$AUDIT_JSON" | jq -c '.items.deferred_items[] | select(.scan_error | not)')
|
|
158
|
+
|
|
159
|
+
if [ "$ACK_FAILURES" -gt 0 ]; then
|
|
160
|
+
echo "ERROR: $ACK_FAILURES acknowledge call(s) failed — HALTING before milestone close. Resolve each listed item manually (e.g. edit the file directly for unsupported_heading_shape/ambiguous, or re-run the audit if a --text/--file target has since changed) and re-run /gsd:complete-milestone:" >&2
|
|
161
|
+
printf '%s\n' "$ACK_FAILURE_LOG" >&2
|
|
162
|
+
exit 1
|
|
163
|
+
fi
|
|
164
|
+
```
|
|
165
|
+
`todos` is the only category the scanner caps (5 entries per scan, with a remainder count for the rest). Re-run `gsd_run query audit-open --json` (through the same `@file:` handling above) and repeat the `todos` block until it reports no `todos` items — every other category always returns its full open set in one pass.
|
|
166
|
+
3. Re-run `gsd_run query audit-open --json` once more and write the items just acknowledged as new rows to STATE.md under `## Deferred Items` — append to the existing table (creating the section if absent) rather than overwriting it, preserving rows recorded at earlier milestone closes:
|
|
66
167
|
```markdown
|
|
67
168
|
## Deferred Items
|
|
68
169
|
|
|
69
|
-
Items acknowledged and deferred at milestone close
|
|
70
|
-
|
|
71
|
-
| Category | Item | Status |
|
|
72
|
-
|
|
73
|
-
|
|
|
74
|
-
|
|
|
75
|
-
|
|
170
|
+
Items acknowledged and deferred at milestone close, most recent first:
|
|
171
|
+
|
|
172
|
+
| Category | Item | Status | Deferred At | Milestone |
|
|
173
|
+
|----------|------|--------|-------------|-----------|
|
|
174
|
+
| debug_sessions | {slug} | {status} | {date} | {milestone} |
|
|
175
|
+
| quick_tasks | {slug} | {status} | {date} | {milestone} |
|
|
176
|
+
| threads | {slug} | {status} | {date} | {milestone} |
|
|
177
|
+
| seeds | {seed_id} | {status} | {date} | {milestone} |
|
|
178
|
+
| todos | {filename} | (presence-only) | {date} | {milestone} |
|
|
179
|
+
| uat_gaps | {phase}/{file} | {status} | {date} | {milestone} |
|
|
180
|
+
| verification_gaps | {phase}/{file} | {status} | {date} | {milestone} |
|
|
181
|
+
| context_questions | {phase}/{file} | {question_count} questions | {date} | {milestone} |
|
|
182
|
+
| deferred_items | {phase}/{file}: {text} | acknowledged | {date} | {milestone} |
|
|
76
183
|
```
|
|
77
|
-
Sanitize all slug
|
|
78
|
-
|
|
79
|
-
|
|
184
|
+
One row per item actually acknowledged in step 2 (omit categories with nothing to disclose this close). `{date}` is today's date; `{milestone}` is `MILESTONE_VERSION`. Sanitize all slug/status/text values via `sanitizeForDisplay()` before writing. Never inject raw file content into STATE.md.
|
|
185
|
+
4. Set `closeout_type=override_closeout` and record in the MILESTONES.md entry: `Known verification overrides: {N} newly acknowledged, {M} carried forward from a prior close (see STATE.md Deferred Items)` — `{N}` is the count of items acknowledged in step 2 (the pre-acknowledgment audit JSON's `counts.total`) and `{M}` is that same audit JSON's `acknowledged.total` (items a PRIOR close already suppressed and still are).
|
|
186
|
+
5. Proceed with milestone close.
|
|
80
187
|
|
|
81
|
-
|
|
188
|
+
Acknowledging is verdict-preserving and self-invalidating: it never rewrites the artifact's own `status:` field (except `deferred_items`, whose entry has no other meaning for that field), and the suppression it grants lapses automatically the moment the artifact's observed state changes again — a reopened debug session, an edited UAT gap, a re-triggered seed, etc. resurfaces on its own at the next audit and must be acknowledged again.
|
|
82
189
|
|
|
83
|
-
|
|
190
|
+
If output shows all clear (no open items): set `closeout_type=verified_closeout`. If the audit JSON's `acknowledged.total` is `0`, print `All artifact types clear.` and proceed. Otherwise the close is clean only because `{acknowledged.total}` item(s) acknowledged at an earlier milestone close are still being suppressed, not because everything was fixed this time — print `All artifact types clear ({acknowledged.total} previously acknowledged item(s) still suppressed — see STATE.md Deferred Items).` and record `Known verification overrides: 0 newly acknowledged, {acknowledged.total} carried forward from a prior close (see STATE.md Deferred Items)` in the MILESTONES.md entry before proceeding.
|
|
191
|
+
|
|
192
|
+
SECURITY: Audit JSON output is structured data from the `audit-open` query handler (same JSON contract as legacy `gsd_run audit-open`) — validated and sanitized at source. The `audit-open acknowledge` writer is the only path that sets the `audit_acknowledged` suppression marker — it snapshots each artifact's current state itself from the identifiers passed on the command line, so this workflow never hand-authors the marker. When writing the STATE.md disclosure table, item identifiers, statuses, and deferred-item text are sanitized via `sanitizeForDisplay()` before inclusion. Never inject raw user-supplied content into STATE.md without sanitization.
|
|
84
193
|
</step>
|
|
85
194
|
|
|
86
195
|
<step name="verify_readiness">
|
|
@@ -244,7 +353,7 @@ Key accomplishments for this milestone:
|
|
|
244
353
|
|
|
245
354
|
<step name="create_milestone_entry">
|
|
246
355
|
|
|
247
|
-
**Note:** MILESTONES.md entry is now created automatically by `
|
|
356
|
+
**Note:** MILESTONES.md entry is now created automatically by `gsd_run query milestone.complete` in the archive_milestone step. The entry includes version, date, phase/plan/task counts, and accomplishments extracted from SUMMARY.md files.
|
|
248
357
|
|
|
249
358
|
If additional details are needed (e.g., user-provided "Delivered" summary, git range, LOC stats), add them manually after the CLI creates the base entry.
|
|
250
359
|
|
|
@@ -257,7 +366,8 @@ Full PROJECT.md evolution review at milestone completion.
|
|
|
257
366
|
Read all phase summaries:
|
|
258
367
|
|
|
259
368
|
```bash
|
|
260
|
-
|
|
369
|
+
_SUMMARIES=( .planning/phases/*-*/*-SUMMARY.md )
|
|
370
|
+
if [ -e "${_SUMMARIES[0]}" ]; then cat "${_SUMMARIES[@]}"; fi
|
|
261
371
|
```
|
|
262
372
|
|
|
263
373
|
**Full review checklist:**
|
|
@@ -397,12 +507,27 @@ Initial user testing showed demand for shape tools.
|
|
|
397
507
|
|
|
398
508
|
<step name="archive_milestone">
|
|
399
509
|
|
|
400
|
-
**
|
|
510
|
+
**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, Gemini CLI, etc.) where `AskUserQuestion` is not available.
|
|
511
|
+
|
|
512
|
+
**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.
|
|
513
|
+
|
|
514
|
+
If `.planning/quick/` contains at least one directory, ask:
|
|
515
|
+
|
|
516
|
+
AskUserQuestion: "Archive completed quick tasks into this milestone too?" with options: "Yes — archive quick tasks into v[X.Y]" | "Skip"
|
|
517
|
+
|
|
518
|
+
If "Yes": set `ARCHIVE_QUICK_FLAG="--archive-quick"`. If "Skip" (or `.planning/quick/` is empty): set `ARCHIVE_QUICK_FLAG=""`.
|
|
519
|
+
|
|
520
|
+
**Delegate archival to `gsd_run query milestone.complete`:**
|
|
401
521
|
|
|
402
522
|
```bash
|
|
403
|
-
ARCHIVE=$(gsd_run query milestone.complete "v[X.Y]" --name "[Milestone Name]")
|
|
523
|
+
ARCHIVE=$(gsd_run query milestone.complete "v[X.Y]" --name "[Milestone Name]" --confirm $ARCHIVE_QUICK_FLAG)
|
|
404
524
|
```
|
|
405
525
|
|
|
526
|
+
`--confirm` is required (#3726): the archive is irreversible (ROADMAP/REQUIREMENTS archived, phase
|
|
527
|
+
directories MOVED, STATE.md rewritten), so `milestone complete` refuses to mutate without it. This
|
|
528
|
+
workflow has already gathered the user's explicit intent by this step, so passing the flag here is
|
|
529
|
+
correct; `--dry-run` previews the exact move list without mutating if a preview is ever needed first.
|
|
530
|
+
|
|
406
531
|
The CLI handles:
|
|
407
532
|
- Creating `.planning/milestones/` directory
|
|
408
533
|
- Archiving ROADMAP.md to `milestones/v[X.Y]-ROADMAP.md`
|
|
@@ -410,23 +535,26 @@ The CLI handles:
|
|
|
410
535
|
- Moving audit file to milestones if it exists
|
|
411
536
|
- Creating/appending MILESTONES.md entry with accomplishments from SUMMARY.md files
|
|
412
537
|
- Updating STATE.md (status, last activity)
|
|
538
|
+
- When `ARCHIVE_QUICK_FLAG` is `--archive-quick`: moving every directory under `.planning/quick/` into `.planning/milestones/v[X.Y]-quick/`, writing a `README.md` index into that archive directory (generated by scanning the archive directory itself), and clearing the data rows of STATE.md's `### Quick Tasks Completed` table — preserving the table's header and whichever column variant (with/without a Status column) was detected
|
|
413
539
|
|
|
414
540
|
Extract from result: `version`, `date`, `phases`, `plans`, `tasks`, `accomplishments`, `archived`.
|
|
415
541
|
|
|
416
542
|
Verify: `✅ Milestone archived to .planning/milestones/`
|
|
417
543
|
|
|
544
|
+
**Known limit (quick-task archival):** there is no on-disk provenance recording which milestone a given quick task belonged to. Archival buckets **all** remaining `.planning/quick/*` into the completing milestone — a quick task that predates an earlier, unarchived milestone lands in the current bucket regardless.
|
|
545
|
+
|
|
546
|
+
Verify after `--archive-quick` was passed: `✅ Quick tasks archived to .planning/milestones/v[X.Y]-quick/`
|
|
547
|
+
|
|
418
548
|
**Phase archival (default-on):** `milestone complete` archives phase directories to `milestones/v[X.Y]-phases/` by default (#1871), so the next `/gsd:new-milestone` never inherits un-archived dirs. No manual `mkdir`/`mv` or `--archive-phases` flag is needed.
|
|
419
549
|
|
|
420
550
|
If the user explicitly wants to keep phase directories in place as raw execution history, invoke `milestone complete` with `--no-archive-phases`:
|
|
421
551
|
|
|
422
552
|
```bash
|
|
423
|
-
gsd_run query milestone complete v[X.Y] --no-archive-phases
|
|
553
|
+
gsd_run query milestone complete v[X.Y] --no-archive-phases --confirm
|
|
424
554
|
```
|
|
425
555
|
|
|
426
556
|
Verify after a default (archived) completion: `✅ Phase directories archived to .planning/milestones/v[X.Y]-phases/`
|
|
427
557
|
|
|
428
|
-
**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, Gemini CLI, etc.) where `AskUserQuestion` is not available.
|
|
429
|
-
|
|
430
558
|
After archival, the AI still handles:
|
|
431
559
|
- Reorganizing ROADMAP.md with milestone grouping (requires judgment) — overwrite in place after extracting Backlog section, with the write-guard's single-use sentinel armed first (a per-step env var cannot reach a hook — see the reorganize step for the sentinel mechanics)
|
|
432
560
|
- Full PROJECT.md evolution review (requires understanding)
|