@opengsd/gsd-core 1.9.1 → 1.11.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 +2 -3
- package/.opencode/plugins/gsd-core.js +8 -1
- package/agents/gsd-code-fixer.md +27 -3
- package/agents/gsd-debug-session-manager.md +11 -0
- package/agents/gsd-debugger.md +12 -246
- package/agents/gsd-doc-synthesizer.md +2 -4
- package/agents/gsd-executor.md +12 -10
- package/agents/gsd-integration-checker.md +3 -0
- package/agents/gsd-mempalace-curator.md +5 -2
- package/agents/gsd-phase-researcher.md +20 -1
- package/agents/gsd-plan-checker.md +46 -0
- package/agents/gsd-planner.md +49 -54
- package/agents/gsd-roadmapper.md +21 -3
- package/agents/gsd-user-profiler.md +3 -0
- package/agents/gsd-verifier.md +26 -73
- package/bin/install.js +1272 -1238
- package/bin/lib/ui-safety-gate.cjs +2 -0
- package/commands/gsd/code-review.md +1 -1
- package/commands/gsd/execute-phase.md +1 -1
- package/commands/gsd/map-codebase.md +1 -1
- package/commands/gsd/mempalace-capture.md +2 -2
- package/commands/gsd/mempalace-recall.md +1 -1
- package/commands/gsd/new-milestone.md +2 -2
- package/commands/gsd/plan-phase.md +1 -1
- package/commands/gsd/quick.md +1 -1
- package/commands/gsd/review-backlog.md +2 -1
- package/commands/gsd/verify-work.md +1 -1
- package/gsd-core/bin/gsd-tools.cjs +1009 -115
- package/gsd-core/bin/lib/active-workstream-store.cjs +153 -12
- package/gsd-core/bin/lib/agent-install-check.cjs +268 -38
- package/gsd-core/bin/lib/api-coverage.cjs +123 -5
- package/gsd-core/bin/lib/artifacts.cjs +3 -0
- package/gsd-core/bin/lib/assumption-delta.cjs +2 -4
- package/gsd-core/bin/lib/audit-command-router.cjs +9 -2
- package/gsd-core/bin/lib/audit.cjs +926 -202
- package/gsd-core/bin/lib/broken-windows.cjs +36 -6
- 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-registry.cjs +608 -148
- package/gsd-core/bin/lib/capability-source.cjs +92 -0
- package/gsd-core/bin/lib/capability-trust.cjs +444 -25
- package/gsd-core/bin/lib/capability-validator.cjs +507 -24
- package/gsd-core/bin/lib/capability-writer.cjs +3 -2
- package/gsd-core/bin/lib/check-command-router.cjs +114 -38
- package/gsd-core/bin/lib/claude-orchestration.cjs +56 -3
- package/gsd-core/bin/lib/codex-agent-toml.cjs +329 -0
- package/gsd-core/bin/lib/command-aliases.cjs +94 -0
- package/gsd-core/bin/lib/command-roster.cjs +44 -1
- package/gsd-core/bin/lib/commands.cjs +665 -99
- package/gsd-core/bin/lib/commonjs-marker.cjs +142 -0
- package/gsd-core/bin/lib/complexity-trigger.cjs +1172 -0
- package/gsd-core/bin/lib/config-loader.cjs +76 -0
- package/gsd-core/bin/lib/config.cjs +22 -2
- package/gsd-core/bin/lib/context-composer.cjs +278 -0
- package/gsd-core/bin/lib/context-predicates.cjs +506 -0
- package/gsd-core/bin/lib/core-utils.cjs +217 -40
- package/gsd-core/bin/lib/decisions.cjs +23 -0
- package/gsd-core/bin/lib/docs.cjs +3 -2
- package/gsd-core/bin/lib/external-job.cjs +19 -4
- package/gsd-core/bin/lib/fallow-runner.cjs +20 -44
- package/gsd-core/bin/lib/frontmatter.cjs +239 -32
- package/gsd-core/bin/lib/gap-checker.cjs +68 -7
- package/gsd-core/bin/lib/gate-predicate-evaluator.cjs +57 -6
- package/gsd-core/bin/lib/git-base-branch.cjs +160 -15
- package/gsd-core/bin/lib/graphify.cjs +142 -27
- package/gsd-core/bin/lib/gsd2-import.cjs +37 -5
- 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 +145 -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 +265 -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 +173 -0
- package/gsd-core/bin/lib/health-diagnostic-types.cjs +68 -0
- package/gsd-core/bin/lib/health-diagnostic.cjs +431 -0
- package/gsd-core/bin/lib/host-integration.cjs +13 -1
- package/gsd-core/bin/lib/host-runtime-detection.cjs +134 -0
- package/gsd-core/bin/lib/init-command-router.cjs +83 -8
- package/gsd-core/bin/lib/init.cjs +1325 -169
- package/gsd-core/bin/lib/install-effort-resolver.cjs +73 -30
- package/gsd-core/bin/lib/install-engine.cjs +805 -264
- package/gsd-core/bin/lib/install-fs-adapter.cjs +262 -0
- package/gsd-core/bin/lib/install-model-override-resolver.cjs +203 -0
- package/gsd-core/bin/lib/install-profiles.cjs +160 -57
- 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-authoring.cjs +3 -1
- package/gsd-core/bin/lib/installer-migration-report.cjs +4 -0
- package/gsd-core/bin/lib/installer-migrations/007-retire-config-root-commonjs-marker.cjs +149 -0
- package/gsd-core/bin/lib/installer-migrations/008-cursor-retire-commands-surface.cjs +55 -0
- package/gsd-core/bin/lib/installer-migrations/009-pi-retire-reserved-hooks-dir.cjs +199 -0
- package/gsd-core/bin/lib/installer-migrations.cjs +206 -13
- package/gsd-core/bin/lib/io.cjs +38 -3
- package/gsd-core/bin/lib/markdown-sectionizer.cjs +8 -1
- package/gsd-core/bin/lib/markdown-table.cjs +133 -20
- package/gsd-core/bin/lib/mcp-catalog.cjs +518 -0
- package/gsd-core/bin/lib/mcp-server.cjs +135 -3
- package/gsd-core/bin/lib/milestone-lock.cjs +248 -0
- package/gsd-core/bin/lib/milestone.cjs +821 -109
- package/gsd-core/bin/lib/model-catalog.cjs +59 -1
- package/gsd-core/bin/lib/model-resolver.cjs +183 -40
- package/gsd-core/bin/lib/normalize-test-command.cjs +1 -1
- package/gsd-core/bin/lib/pattern.cjs +122 -0
- package/gsd-core/bin/lib/phase-estimation.cjs +1 -1
- package/gsd-core/bin/lib/phase-id.cjs +507 -36
- package/gsd-core/bin/lib/phase-lifecycle.cjs +28 -3
- package/gsd-core/bin/lib/phase-locator.cjs +258 -58
- package/gsd-core/bin/lib/phase.cjs +891 -156
- package/gsd-core/bin/lib/plan-dependency-graph.cjs +303 -0
- package/gsd-core/bin/lib/plan-drift-guard.cjs +120 -0
- package/gsd-core/bin/lib/plan-scan.cjs +86 -2
- package/gsd-core/bin/lib/planning-scope.cjs +31 -0
- package/gsd-core/bin/lib/planning-snapshot.cjs +890 -0
- package/gsd-core/bin/lib/planning-workspace.cjs +60 -6
- package/gsd-core/bin/lib/probe-core.cjs +1 -1
- package/gsd-core/bin/lib/profile-output.cjs +1 -1
- package/gsd-core/bin/lib/prompt-budget.cjs +128 -165
- package/gsd-core/bin/lib/refactor-trigger-command-router.cjs +740 -0
- package/gsd-core/bin/lib/retired-artifact-cleanup.cjs +85 -0
- package/gsd-core/bin/lib/review-lane-descriptor.cjs +108 -0
- package/gsd-core/bin/lib/review-lane-invocation.cjs +30 -0
- package/gsd-core/bin/lib/review-lane-runner.cjs +447 -68
- package/gsd-core/bin/lib/review-reviewer-selection.cjs +13 -18
- package/gsd-core/bin/lib/roadmap-command-router.cjs +76 -9
- package/gsd-core/bin/lib/roadmap-parser.cjs +1035 -194
- package/gsd-core/bin/lib/roadmap-upgrade.cjs +37 -10
- package/gsd-core/bin/lib/roadmap.cjs +405 -84
- package/gsd-core/bin/lib/runtime-artifact-conversion.cjs +795 -100
- package/gsd-core/bin/lib/runtime-artifact-install-plan.cjs +14 -2
- package/gsd-core/bin/lib/runtime-artifact-layout.cjs +440 -57
- package/gsd-core/bin/lib/runtime-config-adapter-registry.cjs +3 -2
- package/gsd-core/bin/lib/runtime-homes.cjs +220 -41
- package/gsd-core/bin/lib/runtime-hooks-surface.cjs +220 -44
- package/gsd-core/bin/lib/runtime-name-policy.cjs +3 -1
- package/gsd-core/bin/lib/runtime-slash.cjs +27 -9
- package/gsd-core/bin/lib/section-manifest.cjs +209 -0
- package/gsd-core/bin/lib/security.cjs +104 -5
- package/gsd-core/bin/lib/shell-command-projection.cjs +388 -30
- package/gsd-core/bin/lib/smart-entry.cjs +154 -22
- package/gsd-core/bin/lib/state-command-router.cjs +5 -1
- package/gsd-core/bin/lib/state-document.cjs +152 -8
- package/gsd-core/bin/lib/state-transition.cjs +424 -105
- package/gsd-core/bin/lib/state.cjs +1927 -401
- package/gsd-core/bin/lib/surface.cjs +35 -10
- 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 +20 -4
- package/gsd-core/bin/lib/uat.cjs +706 -64
- package/gsd-core/bin/lib/ui-frontend-evidence.cjs +157 -0
- package/gsd-core/bin/lib/ui-safety-gate.cjs +14 -5
- package/gsd-core/bin/lib/unusable-input.cjs +33 -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.cjs +20 -6
- package/gsd-core/bin/lib/vendor/README.md +37 -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 +287 -20
- package/gsd-core/bin/lib/verify.cjs +368 -880
- package/gsd-core/bin/lib/workflow-fragments.cjs +557 -0
- package/gsd-core/bin/lib/workstream-inventory-builder.cjs +203 -19
- package/gsd-core/bin/lib/workstream-inventory.cjs +576 -31
- package/gsd-core/bin/lib/workstream.cjs +8 -2
- package/gsd-core/bin/lib/worktree-base-ref.cjs +50 -6
- package/gsd-core/bin/lib/worktree-safety.cjs +450 -125
- package/gsd-core/bin/shared/config-defaults.manifest.json +1 -0
- package/gsd-core/bin/shared/config-schema.manifest.json +9 -1
- package/gsd-core/references/agent-contracts.md +43 -26
- package/gsd-core/references/artifact-types.md +10 -3
- package/gsd-core/references/autonomous-ui-design-contract.md +42 -0
- package/gsd-core/references/checkpoints.md +2 -2
- package/gsd-core/references/context-budget.md +1 -1
- package/gsd-core/references/debugger-techniques.md +255 -0
- package/gsd-core/references/dispatch-isolation-gate.md +138 -0
- package/gsd-core/references/doc-conflict-engine.md +1 -1
- package/gsd-core/references/execute-mvp-tdd.md +3 -3
- package/gsd-core/references/execute-phase-between-wave-reset.md +6 -2
- 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 +6 -2
- package/gsd-core/references/gate-prompts.md +1 -1
- package/gsd-core/references/git-planning-commit.md +2 -1
- package/gsd-core/references/loop-hook-dispatch.md +39 -2
- package/gsd-core/references/model-profiles.md +12 -4
- package/gsd-core/references/mvp-concepts.md +9 -9
- package/gsd-core/references/planner-guidance.md +3 -9
- package/gsd-core/references/planner-preconditions.md +1 -1
- package/gsd-core/references/planner-reviews.md +1 -1
- package/gsd-core/references/planning-config.md +8 -6
- package/gsd-core/references/research-documentation-lookup.md +5 -3
- package/gsd-core/references/revision-loop.md +1 -1
- package/gsd-core/references/specless-probe-fallback.md +8 -7
- package/gsd-core/references/universal-anti-patterns.md +3 -3
- package/gsd-core/references/verifier-phase-gates.md +192 -0
- package/gsd-core/references/verifier-wiring-patterns.md +100 -0
- package/gsd-core/references/verify-mvp-mode.md +1 -1
- package/gsd-core/references/workstream-flag.md +22 -6
- package/gsd-core/references/worktree-branch-check.md +2 -2
- package/gsd-core/templates/discussion-log.md +1 -1
- package/gsd-core/templates/phase-prompt.md +2 -4
- package/gsd-core/templates/state.md +4 -4
- package/gsd-core/templates/summary-complex.md +2 -0
- package/gsd-core/templates/summary-minimal.md +2 -0
- package/gsd-core/templates/summary-standard.md +2 -0
- package/gsd-core/templates/summary.md +2 -0
- package/gsd-core/templates/verification-report.md +9 -1
- package/gsd-core/workflows/ai-integration-phase.md +9 -11
- package/gsd-core/workflows/audit-milestone.md +3 -0
- package/gsd-core/workflows/autonomous/steps/converge-banner.md +1 -0
- package/gsd-core/workflows/autonomous/steps/converge-dispatch-bg.md +11 -0
- package/gsd-core/workflows/autonomous/steps/converge-dispatch-inline.md +7 -0
- package/gsd-core/workflows/autonomous/steps/converge-fail-fast.md +21 -0
- package/gsd-core/workflows/autonomous/steps/converge-loop.md +7 -0
- package/gsd-core/workflows/autonomous.md +33 -70
- package/gsd-core/workflows/cleanup.md +62 -3
- package/gsd-core/workflows/code-review/steps/dispatch-fix.md +39 -0
- package/gsd-core/workflows/code-review/steps/structural-pre-pass.md +93 -0
- package/gsd-core/workflows/code-review-fix.md +37 -10
- package/gsd-core/workflows/code-review.md +74 -166
- package/gsd-core/workflows/complete-milestone/steps/git-tag.md +29 -0
- package/gsd-core/workflows/complete-milestone.md +160 -95
- package/gsd-core/workflows/debug.md +16 -17
- package/gsd-core/workflows/diagnose-issues.md +56 -8
- package/gsd-core/workflows/discuss-phase/modes/chain.md +2 -1
- package/gsd-core/workflows/discuss-phase/modes/default.md +1 -1
- package/gsd-core/workflows/discuss-phase-assumptions/steps/auto-advance-dispatch.md +15 -0
- package/gsd-core/workflows/discuss-phase-assumptions.md +7 -17
- package/gsd-core/workflows/docs-update/steps/dispatch-monorepo-packages.md +51 -0
- package/gsd-core/workflows/docs-update.md +8 -51
- package/gsd-core/workflows/edit-phase.md +26 -1
- package/gsd-core/workflows/eval-review.md +3 -5
- package/gsd-core/workflows/execute-phase/steps/executor-isolation-dispatch.md +64 -7
- package/gsd-core/workflows/execute-phase/steps/gap-closure-artifacts.md +50 -0
- package/gsd-core/workflows/execute-phase/steps/partial-wave.md +31 -0
- 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 +21 -0
- package/gsd-core/workflows/execute-phase/steps/regression-gate-run.md +42 -0
- package/gsd-core/workflows/execute-phase/steps/regression-gate.md +43 -37
- package/gsd-core/workflows/execute-phase.md +103 -187
- package/gsd-core/workflows/execute-plan.md +36 -4
- package/gsd-core/workflows/explore.md +131 -4
- package/gsd-core/workflows/fast.md +10 -2
- package/gsd-core/workflows/health.md +73 -4
- package/gsd-core/workflows/help/modes/full.md +6 -1
- package/gsd-core/workflows/import.md +4 -4
- package/gsd-core/workflows/ingest-docs.md +7 -6
- package/gsd-core/workflows/mvp-phase.md +6 -3
- package/gsd-core/workflows/new-milestone/steps/project-md-milestone-write.md +16 -0
- package/gsd-core/workflows/new-milestone/steps/reset-phase-safety.md +19 -0
- package/gsd-core/workflows/new-milestone.md +35 -47
- package/gsd-core/workflows/new-project/steps/auto-mode-config.md +176 -0
- package/gsd-core/workflows/new-project/steps/auto-mode-detection.md +32 -0
- package/gsd-core/workflows/new-project/steps/codebase-map-offer.md +18 -0
- package/gsd-core/workflows/new-project.md +27 -240
- package/gsd-core/workflows/next.md +12 -0
- package/gsd-core/workflows/plan-phase/steps/adr-ingest-express-path.md +15 -0
- package/gsd-core/workflows/plan-phase/steps/chunked-planning-mode.md +110 -0
- package/gsd-core/workflows/plan-phase/steps/prd-express-gate.md +8 -0
- package/gsd-core/workflows/plan-phase/steps/research-only-early-exit.md +17 -0
- package/gsd-core/workflows/plan-phase/steps/research-only-modifiers.md +16 -0
- package/gsd-core/workflows/plan-phase/steps/reviews-prerequisite.md +17 -0
- package/gsd-core/workflows/plan-phase/steps/stall-detection-helpers.md +149 -0
- package/gsd-core/workflows/plan-phase.md +89 -209
- package/gsd-core/workflows/plan-review-convergence.md +50 -2
- package/gsd-core/workflows/progress/steps/forensic-audit.md +125 -0
- package/gsd-core/workflows/progress/steps/mvp-display.md +18 -0
- package/gsd-core/workflows/progress.md +45 -159
- package/gsd-core/workflows/quick/steps/discussion-phase.md +124 -0
- package/gsd-core/workflows/quick/steps/plan-checker-loop.md +111 -0
- package/gsd-core/workflows/quick/steps/quick-verification.md +67 -0
- package/gsd-core/workflows/quick/steps/research-phase.md +72 -0
- package/gsd-core/workflows/quick/steps/worktree-pre-dispatch-commit.md +37 -0
- package/gsd-core/workflows/quick.md +55 -405
- package/gsd-core/workflows/resume-project.md +3 -0
- package/gsd-core/workflows/review/steps/reviewer-instances-note-1.md +4 -0
- package/gsd-core/workflows/review/steps/reviewer-instances-note-2.md +3 -0
- package/gsd-core/workflows/review.md +41 -13
- package/gsd-core/workflows/section-manifest.json +219 -0
- package/gsd-core/workflows/secure-phase.md +1 -1
- package/gsd-core/workflows/session-report.md +2 -1
- package/gsd-core/workflows/settings.md +66 -2
- package/gsd-core/workflows/ship.md +104 -44
- package/gsd-core/workflows/sketch.md +1 -1
- package/gsd-core/workflows/spec-phase.md +41 -20
- package/gsd-core/workflows/spike-wrap-up.md +20 -5
- package/gsd-core/workflows/spike.md +50 -16
- package/gsd-core/workflows/sync-skills.md +106 -13
- package/gsd-core/workflows/transition/steps/workstream-collision-check.md +17 -0
- package/gsd-core/workflows/transition.md +53 -31
- package/gsd-core/workflows/ui-phase.md +13 -12
- package/gsd-core/workflows/ui-review.md +2 -2
- package/gsd-core/workflows/update/steps/channel-banner.md +7 -0
- package/gsd-core/workflows/update.md +19 -8
- package/gsd-core/workflows/validate-phase.md +1 -1
- package/gsd-core/workflows/verify-work/steps/automated-ui-verification.md +36 -0
- package/gsd-core/workflows/verify-work/steps/mvp-uat-framing.md +21 -0
- package/gsd-core/workflows/verify-work.md +17 -65
- package/hooks/dist/gsd-agent-isolation-guard.js +517 -0
- package/hooks/dist/gsd-check-update-worker.js +64 -12
- package/hooks/dist/gsd-check-update.js +19 -1
- package/hooks/dist/gsd-cursor-pre-tool.js +0 -3
- package/hooks/dist/gsd-cursor-subagent-start.js +607 -26
- package/hooks/dist/gsd-cursor-subagent-stop.js +3 -2
- package/hooks/dist/gsd-prompt-guard.js +21 -20
- package/hooks/dist/gsd-read-injection-scanner.js +45 -24
- package/hooks/dist/gsd-statusline.js +90 -6
- package/hooks/dist/gsd-update-banner.js +22 -1
- package/hooks/dist/gsd-workflow-guard.js +134 -36
- package/hooks/dist/gsd-worktree-path-guard.js +2 -1
- package/hooks/dist/gsd-write-guard.js +359 -0
- package/hooks/dist/lib/git-cmd.js +92 -59
- 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 +277 -0
- package/hooks/dist/managed-hooks-registry.cjs +2 -0
- package/hooks/gsd-agent-isolation-guard.js +517 -0
- package/hooks/gsd-check-update-worker.js +64 -12
- package/hooks/gsd-check-update.js +19 -1
- package/hooks/gsd-cursor-pre-tool.js +0 -3
- package/hooks/gsd-cursor-subagent-start.js +607 -26
- package/hooks/gsd-cursor-subagent-stop.js +3 -2
- package/hooks/gsd-prompt-guard.js +21 -20
- package/hooks/gsd-read-injection-scanner.js +45 -24
- package/hooks/gsd-statusline.js +90 -6
- package/hooks/gsd-update-banner.js +22 -1
- package/hooks/gsd-workflow-guard.js +134 -36
- package/hooks/gsd-worktree-path-guard.js +2 -1
- package/hooks/gsd-write-guard.js +359 -0
- package/hooks/hooks.json +12 -0
- package/hooks/lib/git-cmd.js +92 -59
- package/hooks/lib/injection-patterns.js +45 -0
- package/hooks/lib/isolation-deny-reason.js +39 -0
- package/hooks/lib/isolation-sentinel.js +277 -0
- package/hooks/managed-hooks-registry.cjs +2 -0
- package/package.json +31 -10
- package/pi/gsd.cjs +71 -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 +9 -0
- package/scripts/changeset/lint.cjs +68 -6
- package/scripts/changeset/serialize.cjs +5 -1
- package/scripts/check-alias-drift.cjs +7 -43
- package/scripts/check-contract-drift.cjs +297 -0
- package/scripts/ci-test-scope.cjs +19 -2
- package/scripts/command-contract-helpers.cjs +903 -1
- package/scripts/gen-adr-index.cjs +728 -38
- package/scripts/gen-capability-matrix.cjs +1 -1
- package/scripts/gen-capability-registry.cjs +3 -15
- package/scripts/gen-context-index.cjs +439 -0
- package/scripts/gen-health-docs.cjs +390 -0
- package/scripts/gen-inventory-manifest.cjs +150 -4
- package/scripts/gen-loop-host-contract.cjs +4 -24
- package/scripts/gen-prompt-budget-parity-corpus.cjs +645 -0
- package/scripts/gen-registry.cjs +3 -14
- package/scripts/gen-section-manifest.cjs +638 -0
- package/scripts/generate-package-identity.cjs +4 -2
- package/scripts/lib/alias-drift-families.cjs +46 -0
- package/scripts/lib/drift-scan.cjs +278 -0
- package/scripts/lint-allow-test-rule-refs.allowlist.json +15 -54
- 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-compiled-artifact-sync.cjs +6 -1
- 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-command-form.cjs +195 -0
- package/scripts/lint-docs-required.cjs +9 -1
- package/scripts/lint-emitted-drift-ack.cjs +215 -20
- package/scripts/lint-eslint-glob-coverage.allowlist.json +34 -0
- package/scripts/lint-eslint-glob-coverage.cjs +340 -0
- package/scripts/lint-example-parser-parity.cjs +395 -0
- package/scripts/lint-frontmatter-scalar-broad-grep.cjs +237 -0
- package/scripts/lint-health-diagnostic-rule-table.cjs +404 -0
- package/scripts/lint-hooks-runtime-build-seam.cjs +262 -0
- package/scripts/lint-milestone-window-drift.cjs +468 -0
- package/scripts/lint-phase-enumeration-drift.cjs +479 -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 +434 -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 +320 -0
- package/scripts/lint-state-field-drift.cjs +805 -0
- package/scripts/lint-state-write-path-drift.cjs +1045 -0
- package/scripts/lint-test-file-count.allowlist.json +40 -3
- package/scripts/lint-unreachable-guard-drift.cjs +843 -0
- package/scripts/lint-vendored-deps.cjs +124 -0
- package/scripts/mutation-matrix.cjs +13 -0
- package/scripts/pr-changed-files.cjs +63 -0
- package/scripts/pr-template-policy.cjs +14 -4
- package/scripts/prompt-injection-scan.sh +52 -6
- package/scripts/require-issue-link-policy.cjs +192 -0
- package/scripts/state-write-path-drift-baseline.json +19 -0
- package/scripts/sync-runtime-launcher.cjs +2 -4
- package/skills/gsd-autonomous/SKILL.md +0 -1
- package/skills/gsd-code-review/SKILL.md +1 -1
- package/skills/gsd-execute-phase/SKILL.md +1 -2
- package/skills/gsd-map-codebase/SKILL.md +1 -1
- package/skills/gsd-mempalace-capture/SKILL.md +2 -2
- package/skills/gsd-mempalace-recall/SKILL.md +1 -1
- package/skills/gsd-new-milestone/SKILL.md +2 -2
- package/skills/gsd-next/SKILL.md +0 -1
- package/skills/gsd-plan-phase/SKILL.md +1 -2
- package/skills/gsd-progress/SKILL.md +0 -1
- package/skills/gsd-quick/SKILL.md +1 -1
- 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/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 -577
- package/scripts/affected-tests-lib.cjs +0 -554
- package/scripts/gen-emitted-baseline.cjs +0 -145
- package/scripts/lint-allow-test-rule-refs.cjs +0 -162
- package/scripts/run-affected-tests.cjs +0 -7
- package/scripts/run-tests.cjs +0 -1050
|
@@ -44,6 +44,15 @@ PLAN_STRATEGY="local"
|
|
|
44
44
|
if echo "$ARGUMENTS" | grep -qE '(^|[[:space:]])\-\-(converge|cross-ai)([[:space:]]|$)'; then
|
|
45
45
|
PLAN_STRATEGY="converge"
|
|
46
46
|
fi
|
|
47
|
+
|
|
48
|
+
CONVERGE_PARAM=""
|
|
49
|
+
if echo "$ARGUMENTS" | grep -qE '(^|[[:space:]])\-\-converge([[:space:]]|$)'; then
|
|
50
|
+
CONVERGE_PARAM="--converge"
|
|
51
|
+
fi
|
|
52
|
+
CROSS_AI_PARAM=""
|
|
53
|
+
if echo "$ARGUMENTS" | grep -qE '(^|[[:space:]])\-\-cross-ai([[:space:]]|$)'; then
|
|
54
|
+
CROSS_AI_PARAM="--cross-ai"
|
|
55
|
+
fi
|
|
47
56
|
```
|
|
48
57
|
|
|
49
58
|
When `--only` is set, also set `FROM_PHASE` to the same value so existing filter logic applies.
|
|
@@ -58,8 +67,12 @@ Bootstrap via milestone-level init:
|
|
|
58
67
|
_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 "$GSD_TOOLS" ]; then gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${_GSD_RUNTIME_ROOT}/.claude/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${_GSD_RUNTIME_ROOT}/.claude/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${_GSD_RUNTIME_ROOT}/.codex/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${_GSD_RUNTIME_ROOT}/.codex/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif command -v gsd-tools >/dev/null 2>&1; then GSD_TOOLS="$(command -v gsd-tools)"; gsd_run() { "$GSD_TOOLS" "$@"; }; elif [ -f "${CLAUDE_CONFIG_DIR:-$HOME/.claude}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${CLAUDE_CONFIG_DIR:-$HOME/.claude}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${HERMES_HOME:-$HOME/.hermes}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${HERMES_HOME:-$HOME/.hermes}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${CURSOR_CONFIG_DIR:-$HOME/.cursor}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${CURSOR_CONFIG_DIR:-$HOME/.cursor}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${CODEX_HOME:-$HOME/.codex}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${CODEX_HOME:-$HOME/.codex}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${GEMINI_CONFIG_DIR:-$HOME/.gemini}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${GEMINI_CONFIG_DIR:-$HOME/.gemini}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${COPILOT_CONFIG_DIR:-$HOME/.copilot}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${COPILOT_CONFIG_DIR:-$HOME/.copilot}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${WINDSURF_CONFIG_DIR:-$HOME/.codeium/windsurf}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${WINDSURF_CONFIG_DIR:-$HOME/.codeium/windsurf}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${AUGMENT_CONFIG_DIR:-$HOME/.augment}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${AUGMENT_CONFIG_DIR:-$HOME/.augment}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${TRAE_CONFIG_DIR:-$HOME/.trae}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${TRAE_CONFIG_DIR:-$HOME/.trae}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${QWEN_CONFIG_DIR:-$HOME/.qwen}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${QWEN_CONFIG_DIR:-$HOME/.qwen}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${CODEBUDDY_CONFIG_DIR:-$HOME/.codebuddy}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${CODEBUDDY_CONFIG_DIR:-$HOME/.codebuddy}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${CLINE_CONFIG_DIR:-$HOME/.cline}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${CLINE_CONFIG_DIR:-$HOME/.cline}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${GROK_AGENTS_HOME:-$HOME/.agents}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${GROK_AGENTS_HOME:-$HOME/.agents}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${ANTIGRAVITY_CONFIG_DIR:-$HOME/.gemini/antigravity}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${ANTIGRAVITY_CONFIG_DIR:-$HOME/.gemini/antigravity}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${OPENCODE_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/opencode}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${OPENCODE_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/opencode}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${KILO_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/kilo}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${KILO_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/kilo}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; else echo "ERROR: gsd-tools.cjs not found at $GSD_TOOLS and gsd-tools is not on PATH. Run: npx -y @opengsd/gsd-core@latest --claude --local" >&2; exit 1; fi; 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
|
|
59
68
|
INIT=$(gsd_run query init.milestone-op)
|
|
60
69
|
if [[ "$INIT" == @file:* ]]; then INIT=$(cat "${INIT#@file:}"); fi
|
|
70
|
+
INIT_AUTONOMOUS=$(gsd_run query init.autonomous $CONVERGE_PARAM $CROSS_AI_PARAM)
|
|
71
|
+
if [[ "$INIT_AUTONOMOUS" == @file:* ]]; then INIT_AUTONOMOUS=$(cat "${INIT_AUTONOMOUS#@file:}"); fi
|
|
61
72
|
```
|
|
62
73
|
|
|
74
|
+
Extract `section_manifest` from `INIT_AUTONOMOUS` (used by the `converge-*` sections below and in step 3).
|
|
75
|
+
|
|
63
76
|
If `PLAN_STRATEGY` is `converge`, fail fast unless the existing convergence feature gate is enabled:
|
|
64
77
|
|
|
65
78
|
```bash
|
|
@@ -79,23 +92,12 @@ if echo "$ARGUMENTS" | grep -qE '\-\-max-cycles\s+[0-9]+'; then
|
|
|
79
92
|
MAX_CYCLES_ARG=$(echo "$ARGUMENTS" | grep -oE '\-\-max-cycles\s+[0-9]+' | awk '{print $2}')
|
|
80
93
|
CONVERGENCE_ARGS="${CONVERGENCE_ARGS} --max-cycles ${MAX_CYCLES_ARG}"
|
|
81
94
|
fi
|
|
82
|
-
|
|
83
|
-
if [ "$PLAN_STRATEGY" = "converge" ]; then
|
|
84
|
-
CONVERGENCE_ENABLED=$(gsd_run query config-get workflow.plan_review_convergence 2>/dev/null || echo "false")
|
|
85
|
-
if [ "$CONVERGENCE_ENABLED" != "true" ]; then
|
|
86
|
-
printf '%s\n' \
|
|
87
|
-
'gsd-autonomous --converge is disabled (workflow.plan_review_convergence=false).' \
|
|
88
|
-
'' \
|
|
89
|
-
'Enable plan convergence with:' \
|
|
90
|
-
'' \
|
|
91
|
-
' gsd config-set workflow.plan_review_convergence true' \
|
|
92
|
-
'' \
|
|
93
|
-
'Then re-run the autonomous command with --converge.'
|
|
94
|
-
exit 1
|
|
95
|
-
fi
|
|
96
|
-
fi
|
|
97
95
|
```
|
|
98
96
|
|
|
97
|
+
<!-- gsd:section id="converge-fail-fast" when="state:plan-strategy-converge" -->
|
|
98
|
+
If `section_manifest` is `null` or `"converge-fail-fast"` is in its `included` list: read and execute `gsd-core/workflows/autonomous/steps/converge-fail-fast.md`. Otherwise skip — do not read the file.
|
|
99
|
+
<!-- /gsd:section -->
|
|
100
|
+
|
|
99
101
|
Parse JSON for: `milestone_version`, `milestone_name`, `phase_count`, `completed_phases`, `roadmap_exists`, `state_exists`, `commit_docs`.
|
|
100
102
|
|
|
101
103
|
**If `roadmap_exists` is false:** Error — "No ROADMAP.md found. Run `/gsd:new-milestone` first."
|
|
@@ -116,7 +118,9 @@ If `ONLY_PHASE` is set, display: `Single phase mode: Phase ${ONLY_PHASE}`
|
|
|
116
118
|
Else if `FROM_PHASE` is set, display: `Starting from phase ${FROM_PHASE}`
|
|
117
119
|
If `TO_PHASE` is set, display: `Stopping after phase ${TO_PHASE}`
|
|
118
120
|
If `INTERACTIVE` is set, display: `Mode: Interactive (discuss inline, plan+execute inline — background on Codex only)`
|
|
119
|
-
|
|
121
|
+
<!-- gsd:section id="converge-banner" when="state:plan-strategy-converge" -->
|
|
122
|
+
If `section_manifest` is `null` or `"converge-banner"` is in its `included` list: read and execute `gsd-core/workflows/autonomous/steps/converge-banner.md`. Otherwise skip — do not read the file.
|
|
123
|
+
<!-- /gsd:section -->
|
|
120
124
|
|
|
121
125
|
**Agent skills (delegated agents self-load):** This workflow delegates plan/execute/review via flat `Skill()` invocations rather than resolving `agent_skills` itself. Each consumer agent (`gsd-planner`, `gsd-executor`, `gsd-plan-checker`, `gsd-verifier`, …) self-loads its configured `.planning/config.json` `agent_skills` in its own mandatory init step per `@~/.claude/gsd-core/references/agent-skills-bootstrap.md`. This is the durable path that works on every runtime — including Cursor, where `Skill()`-delegated workflow bash init does not reliably execute. No per-delegation injection is needed here. See open-gsd/gsd-core#1866.
|
|
122
126
|
|
|
@@ -332,42 +336,11 @@ Check `has_context`. If false → go to handle_blocker: "Discuss for phase ${PHA
|
|
|
332
336
|
|
|
333
337
|
**3a.5. UI Design Contract (Frontend Phases)**
|
|
334
338
|
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
```bash
|
|
338
|
-
UI_SPEC_FILE=$(ls "${PHASE_DIR}"/*-UI-SPEC.md 2>/dev/null | head -1)
|
|
339
|
-
HOOKS_JSON=$(gsd_run loop render-hooks plan:pre --raw)
|
|
340
|
-
```
|
|
341
|
-
|
|
342
|
-
Read the `activeHooks` array directly from `HOOKS_JSON` (in-context — do NOT invoke a shell pipeline). **Compute the active UI step hooks** = entries from `activeHooks` where `kind == "step"` and `ref.skill` is set. **If there are NO active step hooks → skip silently to 3b.** (This covers `workflow.ui_phase=false` — including configurations where only a gate-only entry is present, e.g. `ui_phase=false` + `ui_safety_gate=true` produces `activeHooks=[{kind:"gate"}]`. Autonomous never runs the plan:pre gate — it is always pipeline mode — so a gate-only active set is equivalent to no active step and is silently skipped here. This matches OLD §3a.5 behaviour.)
|
|
343
|
-
|
|
344
|
-
(At least one active step hook ⇒ `workflow.ui_phase` is on.) Run the UI-SPEC gate:
|
|
345
|
-
|
|
346
|
-
```bash
|
|
347
|
-
GATE=$(gsd_run check ui-plan-gate "${PHASE_NUM}" --raw)
|
|
348
|
-
```
|
|
349
|
-
|
|
350
|
-
Read `frontend` and `hasUiSpec` from `GATE` (in-context).
|
|
351
|
-
|
|
352
|
-
**If `frontend` is false:** Skip silently to 3b.
|
|
353
|
-
|
|
354
|
-
**If `hasUiSpec` is true (UI-SPEC already exists):** Skip silently to 3b.
|
|
355
|
-
|
|
356
|
-
**Otherwise (frontend phase + no UI-SPEC):** For each active step hook (the `kind == "step"` set from above, in array order):
|
|
339
|
+
> Full instructions are in `gsd-core/references/autonomous-ui-design-contract.md`. Read that file now and follow it exactly.
|
|
357
340
|
|
|
358
|
-
|
|
359
|
-
Skill(skill="gsd-${ref.skill}", args="${PHASE_NUM}")
|
|
360
|
-
```
|
|
341
|
+
**Inputs:** `PHASE_NUM`, `PHASE_DIR` from execute_phase. Resolves whether the phase needs a UI-SPEC.md generated before planning via active `plan:pre` step hooks. Always non-blocking — proceeds to 3b regardless of outcome.
|
|
361
342
|
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
After all step hooks return, re-read:
|
|
365
|
-
|
|
366
|
-
```bash
|
|
367
|
-
UI_SPEC_FILE=$(ls "${PHASE_DIR}"/*-UI-SPEC.md 2>/dev/null | head -1)
|
|
368
|
-
```
|
|
369
|
-
|
|
370
|
-
**If `UI_SPEC_FILE` is still empty:** Display warning `Phase ${PHASE_NUM}: UI-SPEC generation did not produce output — continuing without design contract.` and proceed to 3b. NON-BLOCKING.
|
|
343
|
+
Read and execute: `$HOME/.claude/gsd-core/references/autonomous-ui-design-contract.md`
|
|
371
344
|
|
|
372
345
|
**3b. Plan**
|
|
373
346
|
|
|
@@ -379,15 +352,9 @@ FLATTEN=$(gsd_run query dispatch-should-flatten --raw 2>/dev/null || echo "true"
|
|
|
379
352
|
|
|
380
353
|
- **If `FLATTEN` is `false`:** Dispatch plan as a background agent to keep the main context lean. While plan runs, the workflow can immediately start discussing the next phase (see step 4).
|
|
381
354
|
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
Agent(
|
|
386
|
-
description="Plan convergence phase ${PHASE_NUM}: ${PHASE_NAME}",
|
|
387
|
-
run_in_background=true,
|
|
388
|
-
prompt="Run plan convergence for phase ${PHASE_NUM}: Skill(skill=\"gsd-plan-review-convergence\", args=\"${PHASE_NUM} ${CONVERGENCE_ARGS}\")"
|
|
389
|
-
)
|
|
390
|
-
```
|
|
355
|
+
<!-- gsd:section id="converge-dispatch-bg" when="state:plan-strategy-converge" -->
|
|
356
|
+
If `section_manifest` is `null` or `"converge-dispatch-bg"` is in its `included` list: read and execute `gsd-core/workflows/autonomous/steps/converge-dispatch-bg.md`. Otherwise skip — do not read the file.
|
|
357
|
+
<!-- /gsd:section -->
|
|
391
358
|
|
|
392
359
|
- Otherwise, print: `◆ Spawning background planner for phase ${PHASE_NUM}... (runs in a subagent — no output until it returns, ~1–5 min; expected, not a freeze)`
|
|
393
360
|
|
|
@@ -403,11 +370,9 @@ FLATTEN=$(gsd_run query dispatch-should-flatten --raw 2>/dev/null || echo "true"
|
|
|
403
370
|
|
|
404
371
|
- **Otherwise (`FLATTEN` is `true` — run inline):** Run plan **inline** (do NOT background) so the plan-checker runs. The next phase's discuss does not overlap planning here — correctness over overlap.
|
|
405
372
|
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
Skill(skill="gsd-plan-review-convergence", args="${PHASE_NUM} ${CONVERGENCE_ARGS}")
|
|
410
|
-
```
|
|
373
|
+
<!-- gsd:section id="converge-dispatch-inline" when="state:plan-strategy-converge" -->
|
|
374
|
+
If `section_manifest` is `null` or `"converge-dispatch-inline"` is in its `included` list: read and execute `gsd-core/workflows/autonomous/steps/converge-dispatch-inline.md`. Otherwise skip — do not read the file.
|
|
375
|
+
<!-- /gsd:section -->
|
|
411
376
|
|
|
412
377
|
- Otherwise (local planning):
|
|
413
378
|
|
|
@@ -417,11 +382,9 @@ FLATTEN=$(gsd_run query dispatch-should-flatten --raw 2>/dev/null || echo "true"
|
|
|
417
382
|
|
|
418
383
|
**If `INTERACTIVE` is NOT set (default):** Run plan inline.
|
|
419
384
|
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
Skill(skill="gsd-plan-review-convergence", args="${PHASE_NUM} ${CONVERGENCE_ARGS}")
|
|
424
|
-
```
|
|
385
|
+
<!-- gsd:section id="converge-loop" when="state:plan-strategy-converge" -->
|
|
386
|
+
If `section_manifest` is `null` or `"converge-loop"` is in its `included` list: read and execute `gsd-core/workflows/autonomous/steps/converge-loop.md`. Otherwise skip — do not read the file.
|
|
387
|
+
<!-- /gsd:section -->
|
|
425
388
|
|
|
426
389
|
If `PLAN_STRATEGY=local`, run the regular planner:
|
|
427
390
|
|
|
@@ -818,7 +781,7 @@ When any phase operation fails or a blocker is detected, present 3 options via A
|
|
|
818
781
|
2. **"Skip this phase"** — Mark phase as skipped, continue to the next incomplete phase
|
|
819
782
|
3. **"Stop autonomous mode"** — Display summary of progress so far and exit cleanly
|
|
820
783
|
|
|
821
|
-
**On "Fix and retry":** Loop back to the failed step within execute_phase. If the same step fails again after retry, re-present these options.
|
|
784
|
+
**On "Fix and retry":** Loop back to the failed step within execute_phase. Track the retry count per phase + step (`RETRY_COUNT`, kept in memory for the run). If the same step fails again after retry, re-present these options. **Retry ceiling (#3210):** once the same phase step has failed 3 "Fix and retry" attempts, do NOT re-present the options — escalate to a terminal `needs_human` halt: display `Phase {N} ⛔ {Name} — needs_human`, list the unmet items (the blocker description from each attempt), append/update a `## Needs Human` section in STATE.md (`| ${PHASE_NUM} | needs_human | resolve blocker, then /gsd:autonomous --from ${PHASE_NUM} |`), and stop autonomous mode with the standard stopped-summary banner. A blocker that survives 3 fix attempts is an operator gate, not an executable gap — retrying it again just burns hours.
|
|
822
785
|
|
|
823
786
|
**On "Skip this phase":** Log `Phase {N} ⏭ {Name} — Skipped by user` and proceed to iterate.
|
|
824
787
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<purpose>
|
|
2
2
|
|
|
3
|
-
Archive accumulated phase directories from completed milestones into `.planning/milestones/v{X.Y}-phases/`. Identifies which phases belong to each completed milestone, shows a dry-run summary, and moves directories on confirmation.
|
|
3
|
+
Archive accumulated phase directories from completed milestones into `.planning/milestones/v{X.Y}-phases/`. Identifies which phases belong to each completed milestone, shows a dry-run summary, and moves directories on confirmation. Also offers retroactive archival of `.planning/quick/` (#2142) when it is non-empty.
|
|
4
4
|
|
|
5
5
|
</purpose>
|
|
6
6
|
|
|
@@ -9,6 +9,7 @@ Archive accumulated phase directories from completed milestones into `.planning/
|
|
|
9
9
|
1. `.planning/MILESTONES.md`
|
|
10
10
|
2. `.planning/milestones/` directory listing
|
|
11
11
|
3. `.planning/phases/` directory listing
|
|
12
|
+
4. `.planning/quick/` directory listing
|
|
12
13
|
|
|
13
14
|
</required_reading>
|
|
14
15
|
|
|
@@ -69,6 +70,26 @@ Match phase directories to milestone membership. Only include directories that s
|
|
|
69
70
|
|
|
70
71
|
</step>
|
|
71
72
|
|
|
73
|
+
<step name="identify_quick_tasks">
|
|
74
|
+
|
|
75
|
+
Check whether `.planning/quick/` has anything to retroactively archive (#2142):
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
ls -d .planning/quick/*/ 2>/dev/null || true
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
**If no directories are found:** `.planning/quick/` is empty (or absent) — say nothing about quick-task archival and do not offer the step. Skip straight to `show_dry_run` with no quick-task summary or prompt.
|
|
82
|
+
|
|
83
|
+
**If at least one directory is found:** determine the target milestone. Unlike phase directories — whose milestone membership is derivable from the archived ROADMAP snapshot each completed milestone already has — quick tasks carry **no on-disk provenance** at all; there is no way to tell which milestone any given quick task directory belongs to. The target is therefore the single most recent completed milestone (from `.planning/MILESTONES.md`, already read in `identify_completed_milestones`, listed newest-first) that does not yet have a `-quick` archive directory:
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
ls -d .planning/milestones/v*-quick 2>/dev/null || true
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
Walk `.planning/MILESTONES.md`'s entries newest-first and pick the first version with no matching `v{version}-quick` directory above. If every completed milestone already has a `-quick` archive, or `.planning/MILESTONES.md` has no entries, there is no valid target — say so and skip the quick-task step entirely (do not prompt).
|
|
90
|
+
|
|
91
|
+
</step>
|
|
92
|
+
|
|
72
93
|
<step name="show_dry_run">
|
|
73
94
|
|
|
74
95
|
Present a dry-run summary for each milestone:
|
|
@@ -92,6 +113,19 @@ These phase directories will be archived:
|
|
|
92
113
|
Destination: .planning/milestones/v{X.Z}-phases/
|
|
93
114
|
```
|
|
94
115
|
|
|
116
|
+
**If a quick-task target milestone was determined in `identify_quick_tasks`**, add:
|
|
117
|
+
|
|
118
|
+
```
|
|
119
|
+
### Quick tasks — bucket-all into v{X.Y}
|
|
120
|
+
{N} directories under .planning/quick/ will ALL be archived into this ONE milestone
|
|
121
|
+
(v{X.Y} — {Milestone Name}), regardless of when each was actually completed.
|
|
122
|
+
Quick tasks carry no on-disk record of which milestone they belong to, so this is
|
|
123
|
+
a bucket-all, not a per-milestone split — unlike the phase archival above, which
|
|
124
|
+
is derived per-milestone from each archived ROADMAP snapshot.
|
|
125
|
+
|
|
126
|
+
Destination: .planning/milestones/v{X.Y}-quick/
|
|
127
|
+
```
|
|
128
|
+
|
|
95
129
|
**Stale local branches (upstream gone):**
|
|
96
130
|
|
|
97
131
|
First, update remote-tracking refs so the candidate list matches the execution list exactly:
|
|
@@ -112,11 +146,12 @@ Show each branch name. If none, show:
|
|
|
112
146
|
No stale local branches detected.
|
|
113
147
|
```
|
|
114
148
|
|
|
115
|
-
If no phase directories remain to archive (all already moved or deleted) AND no stale branches exist:
|
|
149
|
+
If no phase directories remain to archive (all already moved or deleted) AND no stale branches exist AND no quick-task target milestone was determined:
|
|
116
150
|
|
|
117
151
|
```
|
|
118
152
|
No phase directories found to archive. Phases may have been removed or archived previously.
|
|
119
153
|
No stale local branches detected either.
|
|
154
|
+
No quick tasks to archive either.
|
|
120
155
|
```
|
|
121
156
|
|
|
122
157
|
Stop here.
|
|
@@ -127,6 +162,12 @@ AskUserQuestion: "Proceed with archiving and pruning?" with options: "Yes — ar
|
|
|
127
162
|
|
|
128
163
|
If "Cancel": Stop.
|
|
129
164
|
|
|
165
|
+
**If a quick-task target milestone was determined in `identify_quick_tasks`**, ask a separate, explicit question — this is a distinct, bucket-all action and must not be silently folded into the "Yes" above:
|
|
166
|
+
|
|
167
|
+
AskUserQuestion: "Archive ALL {N} quick-task directories into v{X.Y} — {Milestone Name}? This buckets every remaining quick task into this ONE milestone; there is no way to split them per-milestone." with options: "Yes — archive quick tasks into v{X.Y}" | "Skip"
|
|
168
|
+
|
|
169
|
+
If "Skip": do not run `archive_quick_tasks` — proceed to `archive_phases` (or `report`, if there were no phase directories to archive) with quick-task archival omitted.
|
|
170
|
+
|
|
130
171
|
</step>
|
|
131
172
|
|
|
132
173
|
<step name="archive_phases">
|
|
@@ -147,6 +188,20 @@ Repeat for all milestones in the cleanup set.
|
|
|
147
188
|
|
|
148
189
|
</step>
|
|
149
190
|
|
|
191
|
+
<step name="archive_quick_tasks">
|
|
192
|
+
|
|
193
|
+
Only run this step when the "Yes — archive quick tasks into v{X.Y}" option was confirmed in `show_dry_run`.
|
|
194
|
+
|
|
195
|
+
Uses the narrow `milestone.archive-quick` command (#2142 escalation) rather than `milestone.complete --archive-quick`: cleanup runs against milestones that are typically ALREADY completed, and `milestone.complete` is the full close-out — it archives ROADMAP/REQUIREMENTS and writes a MILESTONES.md entry, so re-running it against an already-completed milestone would clobber that milestone's archived ROADMAP/REQUIREMENTS snapshot (the very snapshot this cleanup depends on) and duplicate its MILESTONES.md entry. `milestone.archive-quick` shares the same move/README-index/table-reset logic as `milestone.complete --archive-quick` (same underlying helper) without any of that.
|
|
196
|
+
|
|
197
|
+
```bash
|
|
198
|
+
gsd_run query milestone.archive-quick "v{X.Y}"
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
This moves every directory under `.planning/quick/` into `.planning/milestones/v{X.Y}-quick/`, (re)writes that directory's `README.md` index, and clears STATE.md's `### Quick Tasks Completed` table rows — identical move/index/reset behavior to the `--archive-quick` flag documented in `complete-milestone.md`'s `archive_milestone` step, without touching ROADMAP.md, REQUIREMENTS.md, MILESTONES.md, or milestone-completion guards. Extract `archived` from the result to confirm.
|
|
202
|
+
|
|
203
|
+
</step>
|
|
204
|
+
|
|
150
205
|
<step name="prune_local_branches">
|
|
151
206
|
|
|
152
207
|
After phase archival, prune local branches whose upstream has been deleted. Use the same filter as the dry-run so the execution list matches exactly what the user confirmed:
|
|
@@ -168,7 +223,7 @@ Notes:
|
|
|
168
223
|
Commit the changes:
|
|
169
224
|
|
|
170
225
|
```bash
|
|
171
|
-
gsd_run query commit "chore: archive phase directories from completed milestones" --files .planning/milestones/ .planning/phases/
|
|
226
|
+
gsd_run query commit "chore: archive phase directories from completed milestones" --files .planning/milestones/ .planning/phases/ .planning/quick/ .planning/STATE.md
|
|
172
227
|
```
|
|
173
228
|
|
|
174
229
|
</step>
|
|
@@ -179,6 +234,8 @@ gsd_run query commit "chore: archive phase directories from completed milestones
|
|
|
179
234
|
Archived:
|
|
180
235
|
{For each milestone}
|
|
181
236
|
- v{X.Y}: {N} phase directories → .planning/milestones/v{X.Y}-phases/
|
|
237
|
+
{If quick-task archival ran}
|
|
238
|
+
- v{X.Y}: {N} quick-task directories → .planning/milestones/v{X.Y}-quick/ (bucket-all — see known limit)
|
|
182
239
|
|
|
183
240
|
Pruned: {N} local branches whose upstream is gone.
|
|
184
241
|
|
|
@@ -196,6 +253,8 @@ Pruned: {N} local branches whose upstream is gone.
|
|
|
196
253
|
- [ ] Dry-run summary shown and user confirmed (covers both archival and pruning)
|
|
197
254
|
- [ ] Phase directories moved to `.planning/milestones/v{X.Y}-phases/`
|
|
198
255
|
- [ ] Stale local branches pruned (branches whose upstream is gone)
|
|
256
|
+
- [ ] `.planning/quick/` checked; quick-task archival offered only when non-empty
|
|
257
|
+
- [ ] When offered and confirmed, ALL remaining quick-task directories archived into the single named target milestone (bucket-all, not per-milestone) via `milestone.archive-quick`
|
|
199
258
|
- [ ] Changes committed
|
|
200
259
|
|
|
201
260
|
</success_criteria>
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
<step name="dispatch_fix">
|
|
2
|
+
If the `--fix` flag was passed (`FIX_FLAG=true`), delegate to the `code-review-fix.md` workflow
|
|
3
|
+
to auto-apply findings from the REVIEW.md that was just written (or that already existed).
|
|
4
|
+
|
|
5
|
+
This step runs AFTER `commit_review` so REVIEW.md is guaranteed to be on disk before the fixer
|
|
6
|
+
is invoked. If REVIEW.md was not created (agent failed, scope was empty, etc.), the `code-review-fix.md`
|
|
7
|
+
workflow handles the missing-review error and exits cleanly.
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
if [ "$FIX_FLAG" = "true" ]; then
|
|
11
|
+
echo ""
|
|
12
|
+
echo "─────────────────────────────────────────────────────────────────"
|
|
13
|
+
echo " --fix: delegating to code-review-fix.md"
|
|
14
|
+
echo "─────────────────────────────────────────────────────────────────"
|
|
15
|
+
echo ""
|
|
16
|
+
|
|
17
|
+
# Build the fix sub-arguments: pass phase arg plus any --all/--auto flags
|
|
18
|
+
FIX_ARGS="${PHASE_ARG}"
|
|
19
|
+
if [ "$FIX_ALL" = "true" ]; then
|
|
20
|
+
FIX_ARGS="${FIX_ARGS} --all"
|
|
21
|
+
fi
|
|
22
|
+
if [ "$FIX_AUTO" = "true" ]; then
|
|
23
|
+
FIX_ARGS="${FIX_ARGS} --auto"
|
|
24
|
+
fi
|
|
25
|
+
|
|
26
|
+
# Load and execute the code-review-fix workflow.
|
|
27
|
+
# The fix workflow is the canonical implementation for all fix logic:
|
|
28
|
+
# gsd-code-fixer agent dispatch, --auto iteration loop, REVIEW-FIX.md commit,
|
|
29
|
+
# and result presentation. Do not duplicate that logic here.
|
|
30
|
+
Workflow(workflow="gsd-core/workflows/code-review-fix.md", args="${FIX_ARGS}")
|
|
31
|
+
|
|
32
|
+
# Exit after fix workflow completes — present_results is for review-only output.
|
|
33
|
+
# The fix workflow has its own present_results step.
|
|
34
|
+
# Exit workflow.
|
|
35
|
+
fi
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
If `FIX_FLAG` is false, skip this step entirely and proceed to `present_results`.
|
|
39
|
+
</step>
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
When `FALLOW_ENABLED=true`:
|
|
2
|
+
|
|
3
|
+
1) Resolve binary via `node_modules/.bin/fallow` first, then PATH.
|
|
4
|
+
```bash
|
|
5
|
+
FALLOW_BIN=$(FALLOW_CWD="$(pwd)" node -e "
|
|
6
|
+
const { resolveFallowBinary } = require('./gsd-core/bin/lib/fallow-runner.cjs');
|
|
7
|
+
const resolved = resolveFallowBinary({ cwd: process.env.FALLOW_CWD });
|
|
8
|
+
if (resolved) process.stdout.write(resolved);
|
|
9
|
+
")
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
2) If binary is missing, fail with actionable message:
|
|
13
|
+
```bash
|
|
14
|
+
if [ -z \"$FALLOW_BIN\" ]; then
|
|
15
|
+
echo \"Error: fallow is enabled but no binary was found.\"
|
|
16
|
+
echo \"Install fallow via \`npm install -D fallow\` or \`cargo install fallow\`.\"
|
|
17
|
+
# Exit workflow
|
|
18
|
+
fi
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
3) Execute structural pass and persist JSON (bounded at 120s). Note: `fallow audit` exits 0 when clean and 1 when issues are found — BOTH are successful runs. Only a timeout (124), usage error (2), or crash yields no usable JSON; success is decided by whether the output parses as a valid fallow report, not by exit code:
|
|
22
|
+
```bash
|
|
23
|
+
_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 "$GSD_TOOLS" ]; then gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${_GSD_RUNTIME_ROOT}/.claude/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${_GSD_RUNTIME_ROOT}/.claude/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${_GSD_RUNTIME_ROOT}/.codex/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${_GSD_RUNTIME_ROOT}/.codex/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif command -v gsd-tools >/dev/null 2>&1; then GSD_TOOLS="$(command -v gsd-tools)"; gsd_run() { "$GSD_TOOLS" "$@"; }; elif [ -f "${CLAUDE_CONFIG_DIR:-$HOME/.claude}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${CLAUDE_CONFIG_DIR:-$HOME/.claude}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${HERMES_HOME:-$HOME/.hermes}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${HERMES_HOME:-$HOME/.hermes}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${CURSOR_CONFIG_DIR:-$HOME/.cursor}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${CURSOR_CONFIG_DIR:-$HOME/.cursor}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${CODEX_HOME:-$HOME/.codex}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${CODEX_HOME:-$HOME/.codex}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${GEMINI_CONFIG_DIR:-$HOME/.gemini}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${GEMINI_CONFIG_DIR:-$HOME/.gemini}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${COPILOT_CONFIG_DIR:-$HOME/.copilot}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${COPILOT_CONFIG_DIR:-$HOME/.copilot}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${WINDSURF_CONFIG_DIR:-$HOME/.codeium/windsurf}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${WINDSURF_CONFIG_DIR:-$HOME/.codeium/windsurf}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${AUGMENT_CONFIG_DIR:-$HOME/.augment}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${AUGMENT_CONFIG_DIR:-$HOME/.augment}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${TRAE_CONFIG_DIR:-$HOME/.trae}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${TRAE_CONFIG_DIR:-$HOME/.trae}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${QWEN_CONFIG_DIR:-$HOME/.qwen}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${QWEN_CONFIG_DIR:-$HOME/.qwen}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${CODEBUDDY_CONFIG_DIR:-$HOME/.codebuddy}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${CODEBUDDY_CONFIG_DIR:-$HOME/.codebuddy}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${CLINE_CONFIG_DIR:-$HOME/.cline}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${CLINE_CONFIG_DIR:-$HOME/.cline}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${GROK_AGENTS_HOME:-$HOME/.agents}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${GROK_AGENTS_HOME:-$HOME/.agents}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${ANTIGRAVITY_CONFIG_DIR:-$HOME/.gemini/antigravity}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${ANTIGRAVITY_CONFIG_DIR:-$HOME/.gemini/antigravity}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${OPENCODE_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/opencode}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${OPENCODE_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/opencode}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${KILO_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/kilo}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${KILO_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/kilo}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; else echo "ERROR: gsd-tools.cjs not found at $GSD_TOOLS and gsd-tools is not on PATH. Run: npx -y @opengsd/gsd-core@latest --claude --local" >&2; exit 1; fi; 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
|
|
24
|
+
FALLOW_JSON_PATH="${PHASE_DIR}/FALLOW.json"
|
|
25
|
+
FALLOW_STDERR_TMP=$(mktemp)
|
|
26
|
+
|
|
27
|
+
# Phase scope uses fallow's native changed-files scoping (--changed-since <base>).
|
|
28
|
+
# Derive the phase base commit; if none is found, fall back to repo scope (fallow
|
|
29
|
+
# auto-detects the base branch). #3191/#3503: the grep is the SAME anchored,
|
|
30
|
+
# POSIX-portable conventional-commit-scope derivation the workflow's Tier-3
|
|
31
|
+
# scope step uses (subject-line `type((phase-)?N(-plan)?):`, padded or unpadded
|
|
32
|
+
# phase spelling). Free prose in commit bodies — "deferred to Phase N per
|
|
33
|
+
# D-09", "### Phase N" format examples — never captures the base, and a bare
|
|
34
|
+
# digit substring matches version strings, dates, and other phases; the oldest
|
|
35
|
+
# such false match would silently widen --changed-since far past the phase.
|
|
36
|
+
FALLOW_SCOPE_ARGS=()
|
|
37
|
+
if [ \"$FALLOW_SCOPE\" = \"phase\" ]; then
|
|
38
|
+
PHASE_SCOPE_NUM=\"${PADDED_PHASE}\"
|
|
39
|
+
case \"$PADDED_PHASE\" in
|
|
40
|
+
0[0-9]*) PHASE_SCOPE_NUM=\"${PADDED_PHASE#0}|${PADDED_PHASE}\" ;;
|
|
41
|
+
esac
|
|
42
|
+
FALLOW_PHASE_COMMITS=$(git log --oneline --all --extended-regexp --grep=\"^[[:alpha:]]+!?\((phase-)?(${PHASE_SCOPE_NUM})(-[0-9]+)?\)!?:\" --format=\"%H\" 2>/dev/null)
|
|
43
|
+
if [ -n \"$FALLOW_PHASE_COMMITS\" ]; then
|
|
44
|
+
FALLOW_BASE=$(echo \"$FALLOW_PHASE_COMMITS\" | tail -1)^
|
|
45
|
+
FALLOW_SCOPE_ARGS=(--changed-since \"$FALLOW_BASE\")
|
|
46
|
+
fi
|
|
47
|
+
fi
|
|
48
|
+
|
|
49
|
+
gsd_run run-with-timeout 120 -- \"$FALLOW_BIN\" audit --format json --quiet --max-crap \"$FALLOW_MAX_CRAP\" \"${FALLOW_SCOPE_ARGS[@]+\"${FALLOW_SCOPE_ARGS[@]}\"}\" > \"${FALLOW_JSON_PATH}.tmp\" 2>\"$FALLOW_STDERR_TMP\"
|
|
50
|
+
FALLOW_EXIT=$?
|
|
51
|
+
|
|
52
|
+
# fallow exits 0 (clean) or 1 (issues found) — BOTH are successful runs that produce a
|
|
53
|
+
# valid JSON report. Only a timeout (124), usage error (2), or crash yields no usable JSON.
|
|
54
|
+
# Decide success by whether the output parses as a fallow report, not by exit code.
|
|
55
|
+
FALLOW_OK=$(FALLOW_TMP=\"${FALLOW_JSON_PATH}.tmp\" node -e \"
|
|
56
|
+
try {
|
|
57
|
+
const fs = require('fs');
|
|
58
|
+
const txt = fs.readFileSync(process.env.FALLOW_TMP, 'utf8');
|
|
59
|
+
const o = JSON.parse(txt);
|
|
60
|
+
process.stdout.write(o && typeof o === 'object' && 'verdict' in o ? '1' : '0');
|
|
61
|
+
} catch { process.stdout.write('0'); }
|
|
62
|
+
\")
|
|
63
|
+
if [ \"$FALLOW_OK\" != \"1\" ]; then
|
|
64
|
+
FALLOW_STDERR_SUMMARY=$(head -5 \"$FALLOW_STDERR_TMP\")
|
|
65
|
+
rm -f \"${FALLOW_JSON_PATH}.tmp\" \"$FALLOW_STDERR_TMP\"
|
|
66
|
+
# #2667: distinguish a hard EXECUTION failure (the binary was found at step 1
|
|
67
|
+
# but would not run) from the binary-missing path (step 2). Exit 124 = timeout,
|
|
68
|
+
# 2 = usage error, 125 = spawn failure (e.g. Windows EINVAL on a .cmd shim —
|
|
69
|
+
# CVE-2024-27980, now mediated by run-with-timeout), 126/127 = not executable /
|
|
70
|
+
# not found. A non-zero exit here with a resolved binary means fallow is
|
|
71
|
+
# installed but did not produce a report — surface that loudly so a Windows
|
|
72
|
+
# user does not mistake it for "fallow absent".
|
|
73
|
+
case \"$FALLOW_EXIT\" in
|
|
74
|
+
124) FALLOW_FAIL_KIND=\"timed out\" ;;
|
|
75
|
+
2) FALLOW_FAIL_KIND=\"usage error\" ;;
|
|
76
|
+
125) FALLOW_FAIL_KIND=\"spawn failure (the binary was found but did not start — e.g. a Windows .cmd shim; run-with-timeout mediates this)\" ;;
|
|
77
|
+
126) FALLOW_FAIL_KIND=\"not executable\" ;;
|
|
78
|
+
127) FALLOW_FAIL_KIND=\"not found\" ;;
|
|
79
|
+
*) FALLOW_FAIL_KIND=\"crashed\" ;;
|
|
80
|
+
esac
|
|
81
|
+
echo \"WARNING: fallow structural pre-pass failed (${FALLOW_FAIL_KIND}, exit ${FALLOW_EXIT}): ${FALLOW_STDERR_SUMMARY}\"
|
|
82
|
+
FALLOW_JSON_PATH=\"\"
|
|
83
|
+
else
|
|
84
|
+
mv \"${FALLOW_JSON_PATH}.tmp\" \"$FALLOW_JSON_PATH\"
|
|
85
|
+
rm -f \"$FALLOW_STDERR_TMP\"
|
|
86
|
+
fi
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
On any failure of the structural pre-pass (binary missing at step 2, or an execution failure here — timeout, spawn failure, crash, empty output, or unparseable JSON), the workflow continues with no `<structural_findings>` injection; the reviewer agent receives a normal review request. The WARNING above names the failure KIND so a hard execution failure (e.g. a Windows `.cmd` spawn failure) is not mistaken for an absent optional dependency.
|
|
90
|
+
|
|
91
|
+
4) Optional MCP bridge path (runtime-dependent):
|
|
92
|
+
- If `FALLOW_MCP=true`, set reviewer input mode to MCP-backed structural findings.
|
|
93
|
+
- Otherwise pass static JSON findings from `FALLOW.json`.
|
|
@@ -207,9 +207,9 @@ Use Agent() to spawn agent:
|
|
|
207
207
|
|
|
208
208
|
```text
|
|
209
209
|
Agent(subagent_type="gsd-code-fixer", model="{FIXER_MODEL}", prompt="
|
|
210
|
-
<
|
|
210
|
+
<required_reading>
|
|
211
211
|
${REVIEW_PATH}
|
|
212
|
-
</
|
|
212
|
+
</required_reading>
|
|
213
213
|
|
|
214
214
|
<config>
|
|
215
215
|
phase_dir: ${PHASE_DIR}
|
|
@@ -256,7 +256,11 @@ if [ "$AUTO_MODE" = "true" ]; then
|
|
|
256
256
|
# Total fix passes = MAX_ITERATIONS. Loop uses -lt (not -le) intentionally.
|
|
257
257
|
ITERATION=1
|
|
258
258
|
MAX_ITERATIONS=3
|
|
259
|
-
|
|
259
|
+
# #3190: track whether the loop converged (re-review came back clean) vs
|
|
260
|
+
# degraded (hit the cap). Convergence determines whether the .iterN.md backups
|
|
261
|
+
# are spent scratch (cleaned below) or retained for post-mortem analysis.
|
|
262
|
+
CONVERGED=false
|
|
263
|
+
|
|
260
264
|
while [ $ITERATION -lt $MAX_ITERATIONS ]; do
|
|
261
265
|
ITERATION=$((ITERATION + 1))
|
|
262
266
|
|
|
@@ -315,6 +319,7 @@ ${AGENT_SKILLS_REVIEWER}")
|
|
|
315
319
|
" 2>/dev/null)
|
|
316
320
|
|
|
317
321
|
if [ "$NEW_STATUS" = "clean" ]; then
|
|
322
|
+
CONVERGED=true
|
|
318
323
|
echo ""
|
|
319
324
|
echo "✓ All issues resolved after iteration ${ITERATION}."
|
|
320
325
|
break
|
|
@@ -324,9 +329,9 @@ ${AGENT_SKILLS_REVIEWER}")
|
|
|
324
329
|
echo "Issues remain. Applying fixes for iteration ${ITERATION}..."
|
|
325
330
|
|
|
326
331
|
Agent(subagent_type="gsd-code-fixer", model="{FIXER_MODEL}", prompt="
|
|
327
|
-
<
|
|
332
|
+
<required_reading>
|
|
328
333
|
${REVIEW_PATH}
|
|
329
|
-
</
|
|
334
|
+
</required_reading>
|
|
330
335
|
|
|
331
336
|
<config>
|
|
332
337
|
phase_dir: ${PHASE_DIR}
|
|
@@ -353,14 +358,24 @@ ${AGENT_SKILLS_FIXER}")
|
|
|
353
358
|
echo ""
|
|
354
359
|
echo "⚠ Reached maximum iterations (${MAX_ITERATIONS}). Remaining issues documented in REVIEW-FIX.md."
|
|
355
360
|
fi
|
|
361
|
+
|
|
362
|
+
# #3190: on convergence the .iterN.md backups are spent scratch — their
|
|
363
|
+
# stated purpose is post-mortem analysis "if iterations degrade", and
|
|
364
|
+
# convergence means no degradation. Remove them so the phase directory is
|
|
365
|
+
# clean (no dirty REVIEW.md or backup files after the run). They are RETAINED
|
|
366
|
+
# when the loop degraded (hit MAX_ITERATIONS / fixer failure) so the
|
|
367
|
+
# post-mortem trail survives. Backup CREATION (cp … .iterN.md) is unchanged.
|
|
368
|
+
if [ "$CONVERGED" = "true" ]; then
|
|
369
|
+
rm -f "${REVIEW_PATH%.md}.iter"*.md "${FIX_REPORT_PATH%.md}.iter"*.md 2>/dev/null || true
|
|
370
|
+
fi
|
|
356
371
|
fi
|
|
357
372
|
```
|
|
358
373
|
|
|
359
374
|
Key design decisions for --auto (addresses ALL review HIGH concerns):
|
|
360
375
|
1. **Re-review scope**: Uses REVIEW_FILES_ARRAY from original REVIEW.md frontmatter, falling back to full phase scope. Scope is NOT lost between iterations. Uses portable while-read loop (bash 3.2+ compatible, handles spaces in paths).
|
|
361
376
|
2. **Artifact semantics**: REVIEW.md is overwritten by each re-review (latest review state). REVIEW-FIX.md is overwritten by each fixer iteration (latest fix state with iteration count). There is ONE final version of each artifact, not per-iteration copies.
|
|
362
|
-
Backup files (.iterN.md) preserve history for post-mortem analysis if iterations degrade.
|
|
363
|
-
3. **Commit timing**: Fix commits happen per-finding inside the agent. REVIEW-FIX.md is NOT committed until step 7 (after ALL iterations complete). Only ONE docs commit
|
|
377
|
+
Backup files (.iterN.md) preserve history for post-mortem analysis if iterations degrade. On successful convergence (#3190) the backups are spent scratch and removed; on degradation (hit MAX_ITERATIONS / fixer failure) they are retained for post-mortem.
|
|
378
|
+
3. **Commit timing**: Fix commits happen per-finding inside the agent. REVIEW-FIX.md is NOT committed until step 7 (after ALL iterations complete). Only ONE docs commit, not one per iteration. In --auto that single commit also stages the converged REVIEW.md alongside REVIEW-FIX.md (#3190), so the two committed artifacts agree — the initial code-review commit held iteration-1 REVIEW.md content, and the --auto re-review loop overwrote it each iteration.
|
|
364
379
|
</step>
|
|
365
380
|
|
|
366
381
|
<step name="commit_fix_report">
|
|
@@ -369,7 +384,8 @@ After ALL iterations complete (or single pass in non-auto mode), validate and co
|
|
|
369
384
|
```bash
|
|
370
385
|
if [ -f "${FIX_REPORT_PATH}" ]; then
|
|
371
386
|
# Validate REVIEW-FIX.md has valid YAML frontmatter with status field
|
|
372
|
-
|
|
387
|
+
# #3190: export FIX_REPORT_PATH (the var the body reads), not REVIEW_PATH.
|
|
388
|
+
HAS_STATUS=$(FIX_REPORT_PATH="${FIX_REPORT_PATH}" node -e "
|
|
373
389
|
const fs = require('fs');
|
|
374
390
|
const content = fs.readFileSync(process.env.FIX_REPORT_PATH, 'utf-8');
|
|
375
391
|
const match = content.replace(/\r\n/g, '\n').match(/^---\n([\s\S]*?)\n---/);
|
|
@@ -380,9 +396,19 @@ if [ -f "${FIX_REPORT_PATH}" ]; then
|
|
|
380
396
|
echo "REVIEW-FIX.md created at ${FIX_REPORT_PATH}"
|
|
381
397
|
|
|
382
398
|
if [ "$COMMIT_DOCS" = "true" ]; then
|
|
399
|
+
# #3190: --auto's re-review loop overwrote REVIEW.md each iteration
|
|
400
|
+
# (auto_iteration_loop), but the only prior REVIEW.md commit is the
|
|
401
|
+
# initial code-review pass (iteration-1 content). Stage the converged
|
|
402
|
+
# REVIEW.md alongside REVIEW-FIX.md in this single docs commit so the two
|
|
403
|
+
# committed artifacts agree. Non-auto single-pass runs never rewrite
|
|
404
|
+
# REVIEW.md, so it is left untouched (guarded on AUTO_MODE).
|
|
405
|
+
COMMIT_FILES=("${FIX_REPORT_PATH}")
|
|
406
|
+
if [ "$AUTO_MODE" = "true" ] && [ -f "${REVIEW_PATH}" ]; then
|
|
407
|
+
COMMIT_FILES+=("${REVIEW_PATH}")
|
|
408
|
+
fi
|
|
383
409
|
gsd_run query commit \
|
|
384
410
|
"docs(${PADDED_PHASE}): add code review fix report" \
|
|
385
|
-
--files "${
|
|
411
|
+
--files "${COMMIT_FILES[@]}"
|
|
386
412
|
fi
|
|
387
413
|
else
|
|
388
414
|
echo "Warning: REVIEW-FIX.md has invalid frontmatter (no status field). Not committing."
|
|
@@ -426,7 +452,8 @@ Extract frontmatter fields:
|
|
|
426
452
|
|
|
427
453
|
```bash
|
|
428
454
|
# Extract only the YAML frontmatter block (between first two --- lines)
|
|
429
|
-
|
|
455
|
+
# #3190: export FIX_REPORT_PATH (the var the body reads), not REVIEW_PATH.
|
|
456
|
+
FIX_FRONTMATTER=$(FIX_REPORT_PATH="${FIX_REPORT_PATH}" node -e "
|
|
430
457
|
const fs = require('fs');
|
|
431
458
|
const content = fs.readFileSync(process.env.FIX_REPORT_PATH, 'utf-8');
|
|
432
459
|
const match = content.replace(/\r\n/g, '\n').match(/^---\n([\s\S]*?)\n---/);
|