@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
|
@@ -270,8 +270,9 @@ function setCapabilityState(cwd, runtimeConfigDir, desired, opts) {
|
|
|
270
270
|
// access to getCommitAttribution (which lives in bin/install.js). Until that
|
|
271
271
|
// is refactored into a shared module, surface-path agents for descriptor-
|
|
272
272
|
// driven runtimes will lack the Co-Authored-By trailer that install adds.
|
|
273
|
-
// Parity is proven when resolveAttribution IS provided (see
|
|
274
|
-
//
|
|
273
|
+
// Parity is proven when resolveAttribution IS provided (see the
|
|
274
|
+
// folded:issue-1575-agent-descriptor-parity describe block in
|
|
275
|
+
// tests/golden-parity-single-source.test.cjs).
|
|
275
276
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
|
276
277
|
applySurface(resolvedConfigDir, layout, manifest, undefined, registry, opts?.materialize?.resolveAttribution
|
|
277
278
|
? { resolveAttribution: opts.materialize.resolveAttribution }
|
|
@@ -28,6 +28,7 @@ const { extractFrontmatter } = frontmatterMod;
|
|
|
28
28
|
const markdown_sectionizer_cjs_1 = require("./markdown-sectionizer.cjs");
|
|
29
29
|
const security_cjs_1 = require("./security.cjs");
|
|
30
30
|
const ui_safety_gate_cjs_1 = require("./ui-safety-gate.cjs");
|
|
31
|
+
const ui_frontend_evidence_cjs_1 = require("./ui-frontend-evidence.cjs");
|
|
31
32
|
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
32
33
|
const verifyModule = require("./verify.cjs");
|
|
33
34
|
const { cmdVerifySchemaDrift, cmdVerifyCodebaseDrift } = verifyModule;
|
|
@@ -45,6 +46,15 @@ const { evaluatePredicate } = gatePredicateEval;
|
|
|
45
46
|
const apiCoverageMod = require("./api-coverage.cjs");
|
|
46
47
|
const { detectApiIntegration, validateCoverageMatrix } = apiCoverageMod;
|
|
47
48
|
const shell_command_projection_cjs_1 = require("./shell-command-projection.cjs");
|
|
49
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
50
|
+
const planScanMod = require("./plan-scan.cjs");
|
|
51
|
+
const { scanPhasePlans } = planScanMod;
|
|
52
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
53
|
+
const planningScopeMod = require("./planning-scope.cjs");
|
|
54
|
+
const { SCOPE } = planningScopeMod;
|
|
55
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
56
|
+
const verifyCommandGroundingMod = require("./verify-command-grounding.cjs");
|
|
57
|
+
const { probePhaseVerifyCommands, probePhaseFailingDirections } = verifyCommandGroundingMod;
|
|
48
58
|
// ─── Helpers ──────────────────────────────────────────────────────────────────
|
|
49
59
|
function normalizePhrase(text) {
|
|
50
60
|
// eslint-disable-next-line @typescript-eslint/no-base-to-string
|
|
@@ -128,14 +138,13 @@ function gateEnabled(projectDir) {
|
|
|
128
138
|
function loadPlanContents(phaseDir) {
|
|
129
139
|
if (!node_fs_1.default.existsSync(phaseDir))
|
|
130
140
|
return [];
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
}
|
|
141
|
+
// #3183 (lint-plan-count-drift): source live plan files from the single
|
|
142
|
+
// owner (scanPhasePlans) instead of a local `-PLAN.md` readdirSync filter
|
|
143
|
+
// — picks up bare PLAN.md and nested plans/, and excludes plans marked
|
|
144
|
+
// `status: superseded`, which the prior root-only exact-suffix filter did
|
|
145
|
+
// neither for.
|
|
146
|
+
return scanPhasePlans(phaseDir).planFiles
|
|
147
|
+
.map((entry) => readIfExists(node_path_1.default.join(phaseDir, entry)));
|
|
139
148
|
}
|
|
140
149
|
const DESIGNATED_HEADINGS_RE = /^#{1,6}\s+(?:must[_ ]haves?|truths?|tasks?|objective)\b/i;
|
|
141
150
|
// #2372: scanned-tag set must match the planner-canonical surfaces where a D-NN citation
|
|
@@ -337,6 +346,7 @@ function recentCommitMessages(projectDir) {
|
|
|
337
346
|
encoding: 'utf-8',
|
|
338
347
|
maxBuffer: 4 * 1024 * 1024,
|
|
339
348
|
windowsHide: true,
|
|
349
|
+
timeout: 15_000,
|
|
340
350
|
});
|
|
341
351
|
}
|
|
342
352
|
catch {
|
|
@@ -411,8 +421,11 @@ function cmdDecisionCoverageVerify(projectDir, args, raw) {
|
|
|
411
421
|
return;
|
|
412
422
|
}
|
|
413
423
|
const planContents = loadPlanContents(phaseDir);
|
|
424
|
+
// #3183 (lint-plan-count-drift): same single-owner sourcing as
|
|
425
|
+
// loadPlanContents above — scanPhasePlans's summaryFiles instead of a
|
|
426
|
+
// local `-SUMMARY.md` readdirSync filter.
|
|
414
427
|
const summaryParts = node_fs_1.default.existsSync(phaseDir)
|
|
415
|
-
?
|
|
428
|
+
? scanPhasePlans(phaseDir).summaryFiles.map((entry) => readIfExists(node_path_1.default.join(phaseDir, entry)))
|
|
416
429
|
: [];
|
|
417
430
|
const haystack = [
|
|
418
431
|
planContents.join('\n\n'),
|
|
@@ -442,8 +455,9 @@ function cmdDecisionCoverageVerify(projectDir, args, raw) {
|
|
|
442
455
|
* ui-plan-gate: given a phase number, checks whether the phase has frontend
|
|
443
456
|
* indicators and whether a *-UI-SPEC.md already exists in the phase directory.
|
|
444
457
|
*
|
|
445
|
-
* Returns JSON: { frontend
|
|
446
|
-
* block = frontend && !hasUiSpec (gate fires when
|
|
458
|
+
* Returns JSON: { frontend, hasFrontendEvidence, hasUiSpec, block, uiSpecPath, matchedToken, matchedLine }
|
|
459
|
+
* block = frontend && hasFrontendEvidence && !hasUiSpec (#3312: gate fires when
|
|
460
|
+
* UI work is detected AND the repo has static frontend evidence but no spec exists)
|
|
447
461
|
*
|
|
448
462
|
* Invocable as: gsd_run check ui-plan-gate <phase>
|
|
449
463
|
*
|
|
@@ -477,10 +491,21 @@ function findUiSpecInDir(phaseDir) {
|
|
|
477
491
|
* (b) Runs checkUiPresence (frontend detection) — no reimplementation.
|
|
478
492
|
* (c) Resolves the phase directory via findPhaseInternal (phase-locator.cjs); checks for *-UI-SPEC.md.
|
|
479
493
|
*
|
|
480
|
-
* Returns: { frontend, hasUiSpec, block, uiSpecPath, phaseLookupFailed }
|
|
481
|
-
* block = frontend && !hasUiSpec
|
|
494
|
+
* Returns: { frontend, hasFrontendEvidence, hasUiSpec, block, uiSpecPath, matchedToken, matchedLine, phaseLookupFailed }
|
|
495
|
+
* block = frontend && hasFrontendEvidence && !hasUiSpec (#3312)
|
|
482
496
|
* phaseLookupFailed = ROADMAP.md present but phase header not found (surfaced for
|
|
483
497
|
* onError:halt gates so a missing phase doesn't silently bypass)
|
|
498
|
+
*
|
|
499
|
+
* #3312 — structural corroboration: `frontend` is a vocabulary signal only. A
|
|
500
|
+
* hyphen is a word boundary, so a phase naming the repo `dashboard-financeiro`
|
|
501
|
+
* matches the token `dashboard` exactly like the real compound `micro-frontend`
|
|
502
|
+
* (the boundary rule of #3718 is intentional and untouched). The gate therefore
|
|
503
|
+
* blocks only when the token match is corroborated by static frontend evidence
|
|
504
|
+
* in the repo tree (hasStaticFrontendEvidence: package.json UI-framework dep or
|
|
505
|
+
* a component-framework file). This mirrors the sibling post-wave gate
|
|
506
|
+
* computeUiSafetyGate, which requires `hasUiFiles` (git diff) before blocking.
|
|
507
|
+
* matchedToken/matchedLine surface what tripped the sniffer so an operator can
|
|
508
|
+
* judge the flag in one second instead of reaching for --skip-ui.
|
|
484
509
|
*/
|
|
485
510
|
function computeUiPlanGate(projectDir, phase) {
|
|
486
511
|
// (a) Read the phase section text using the same two-pass lookup as roadmap.get-phase.
|
|
@@ -509,6 +534,9 @@ function computeUiPlanGate(projectDir, phase) {
|
|
|
509
534
|
// (b) Run checkUiPresence (frontend detection) — reuse existing helper; no reimplementation
|
|
510
535
|
const presenceResult = (0, ui_safety_gate_cjs_1.checkUiPresence)(phaseSection);
|
|
511
536
|
const frontend = presenceResult.hasUI;
|
|
537
|
+
// (b') #3312 — static structural corroboration. Only probed when the sniffer
|
|
538
|
+
// matched (evidence is irrelevant otherwise); failures degrade to false.
|
|
539
|
+
const hasFrontendEvidence = frontend ? (0, ui_frontend_evidence_cjs_1.hasStaticFrontendEvidence)(projectDir) : false;
|
|
512
540
|
// (c) Resolve phase directory via findPhaseInternal and check for *-UI-SPEC.md
|
|
513
541
|
let phaseDir = '';
|
|
514
542
|
try {
|
|
@@ -528,10 +556,13 @@ function computeUiPlanGate(projectDir, phase) {
|
|
|
528
556
|
catch { /* phase dir lookup failure → hasUiSpec=false */ }
|
|
529
557
|
const uiSpecPath = findUiSpecInDir(phaseDir);
|
|
530
558
|
const hasUiSpec = uiSpecPath !== '';
|
|
531
|
-
// block = frontend phase with no UI-SPEC
|
|
532
|
-
const block = frontend && !hasUiSpec;
|
|
559
|
+
// block = frontend phase with structural frontend evidence and no UI-SPEC (#3312)
|
|
560
|
+
const block = frontend && hasFrontendEvidence && !hasUiSpec;
|
|
533
561
|
const result = {
|
|
534
|
-
frontend, hasUiSpec, block,
|
|
562
|
+
frontend, hasFrontendEvidence, hasUiSpec, block,
|
|
563
|
+
uiSpecPath: hasUiSpec ? uiSpecPath : null,
|
|
564
|
+
matchedToken: presenceResult.matchedToken,
|
|
565
|
+
matchedLine: presenceResult.matchedLine,
|
|
535
566
|
};
|
|
536
567
|
if (phaseLookupFailed)
|
|
537
568
|
result.phaseLookupFailed = true;
|
|
@@ -613,6 +644,7 @@ function computeUiSafetyGate(projectDir, phase) {
|
|
|
613
644
|
encoding: 'utf-8',
|
|
614
645
|
maxBuffer: 2 * 1024 * 1024,
|
|
615
646
|
windowsHide: true,
|
|
647
|
+
timeout: 10_000,
|
|
616
648
|
});
|
|
617
649
|
hasUiFiles = changed.split('\n').some((f) => f.trim() && (UI_FILE_EXTENSIONS_RE.test(f) || UI_PATH_PATTERNS_RE.test(f)));
|
|
618
650
|
}
|
|
@@ -679,7 +711,9 @@ function cmdTddReviewCheckpoint(projectDir, args, raw) {
|
|
|
679
711
|
const tddPlanFiles = [];
|
|
680
712
|
if (phaseDir) {
|
|
681
713
|
try {
|
|
682
|
-
|
|
714
|
+
// #3183: canonical plan set (root+nested, superseded-excluded) from the
|
|
715
|
+
// single owner, rather than a root-only hand-rolled readdirSync filter.
|
|
716
|
+
const files = scanPhasePlans(phaseDir).planFiles;
|
|
683
717
|
for (const file of files) {
|
|
684
718
|
const planPath = node_path_1.default.join(phaseDir, file);
|
|
685
719
|
const content = readIfExists(planPath);
|
|
@@ -728,17 +762,17 @@ function cmdTddReviewCheckpoint(projectDir, args, raw) {
|
|
|
728
762
|
let green = false;
|
|
729
763
|
let refactor = false;
|
|
730
764
|
try {
|
|
731
|
-
const redCommit = (0, node_child_process_1.execFileSync)('git', ['log', '--oneline', `--grep=^test(${planId}):`, '--', '.'], { cwd: projectDir, encoding: 'utf-8', maxBuffer: 1024 * 1024, windowsHide: true });
|
|
765
|
+
const redCommit = (0, node_child_process_1.execFileSync)('git', ['log', '--oneline', `--grep=^test(${planId}):`, '--', '.'], { cwd: projectDir, encoding: 'utf-8', maxBuffer: 1024 * 1024, windowsHide: true, timeout: 10_000 });
|
|
732
766
|
red = redCommit.trim().length > 0;
|
|
733
767
|
}
|
|
734
768
|
catch { /* git unavailable or no match */ }
|
|
735
769
|
try {
|
|
736
|
-
const greenCommit = (0, node_child_process_1.execFileSync)('git', ['log', '--oneline', `--grep=^feat(${planId}):`, '--', '.'], { cwd: projectDir, encoding: 'utf-8', maxBuffer: 1024 * 1024, windowsHide: true });
|
|
770
|
+
const greenCommit = (0, node_child_process_1.execFileSync)('git', ['log', '--oneline', `--grep=^feat(${planId}):`, '--', '.'], { cwd: projectDir, encoding: 'utf-8', maxBuffer: 1024 * 1024, windowsHide: true, timeout: 10_000 });
|
|
737
771
|
green = greenCommit.trim().length > 0;
|
|
738
772
|
}
|
|
739
773
|
catch { /* git unavailable or no match */ }
|
|
740
774
|
try {
|
|
741
|
-
const refactorCommit = (0, node_child_process_1.execFileSync)('git', ['log', '--oneline', `--grep=^refactor(${planId}):`, '--', '.'], { cwd: projectDir, encoding: 'utf-8', maxBuffer: 1024 * 1024, windowsHide: true });
|
|
775
|
+
const refactorCommit = (0, node_child_process_1.execFileSync)('git', ['log', '--oneline', `--grep=^refactor(${planId}):`, '--', '.'], { cwd: projectDir, encoding: 'utf-8', maxBuffer: 1024 * 1024, windowsHide: true, timeout: 10_000 });
|
|
742
776
|
refactor = refactorCommit.trim().length > 0;
|
|
743
777
|
}
|
|
744
778
|
catch { /* git unavailable or no match */ }
|
|
@@ -752,14 +786,11 @@ function cmdTddReviewCheckpoint(projectDir, args, raw) {
|
|
|
752
786
|
}
|
|
753
787
|
const violations = rows.filter(r => r.status === 'FAIL').length;
|
|
754
788
|
// Build review table
|
|
755
|
-
const sep = '━'.repeat(53);
|
|
756
789
|
const tableHeader = '| Plan | RED | GREEN | REFACTOR | Status |';
|
|
757
790
|
const tableDivider = '|------|-----|-------|----------|--------|';
|
|
758
791
|
const tableRows = rows.map(r => `| ${r.planId.padEnd(4)} | ${r.red ? ' ✓ ' : ' ✗ '} | ${r.green ? ' ✓ ' : ' ✗ '} | ${r.refactor ? ' ✓ ' : ' — '} | ${r.status.padEnd(6)} |`);
|
|
759
792
|
let table = [
|
|
760
|
-
|
|
761
|
-
` TDD REVIEW — Phase ${phase}`,
|
|
762
|
-
sep,
|
|
793
|
+
`### TDD REVIEW — Phase ${phase}`,
|
|
763
794
|
'',
|
|
764
795
|
`TDD Plans: ${tddPlanFiles.length} | Gate violations: ${violations}`,
|
|
765
796
|
'',
|
|
@@ -794,6 +825,111 @@ function cmdTddReviewCheckpoint(projectDir, args, raw) {
|
|
|
794
825
|
// the host-loop dispatch's advisory branch can surface it.
|
|
795
826
|
output(result, raw, undefined);
|
|
796
827
|
}
|
|
828
|
+
/**
|
|
829
|
+
* Resolve a phase argument to an absolute phase directory, or '' when it
|
|
830
|
+
* cannot be resolved. Shared by every `check` arm that probes a phase's
|
|
831
|
+
* PLAN.md files, so the two never drift (DEFECT.GENERATIVE-FIX-DIVERGENCE).
|
|
832
|
+
* Never throws — the callers emit a degraded JSON payload instead, because
|
|
833
|
+
* a consumer must be able to tell "nothing to report" from "could not look".
|
|
834
|
+
*/
|
|
835
|
+
function resolvePhaseDirOrEmpty(projectDir, phase) {
|
|
836
|
+
try {
|
|
837
|
+
const result = findPhaseInternal(projectDir, phase);
|
|
838
|
+
if (result && typeof result === 'object') {
|
|
839
|
+
// findPhaseInternal returns { directory: '<relative-posix-path>', ... }
|
|
840
|
+
// directory is relative to cwd — resolve it to absolute.
|
|
841
|
+
const relDir = typeof result['directory'] === 'string' ? result['directory'] : '';
|
|
842
|
+
if (relDir) {
|
|
843
|
+
return node_path_1.default.resolve(projectDir, relDir);
|
|
844
|
+
}
|
|
845
|
+
}
|
|
846
|
+
else if (typeof result === 'string') {
|
|
847
|
+
return result;
|
|
848
|
+
}
|
|
849
|
+
}
|
|
850
|
+
catch { /* phase dir lookup failure → caller emits degraded payload */ }
|
|
851
|
+
return '';
|
|
852
|
+
}
|
|
853
|
+
// ─── verify-command-paths (#2401) ──────────────────────────────────────────────
|
|
854
|
+
/**
|
|
855
|
+
* verify-command-paths: probes every `<automated>` verify command declared in a
|
|
856
|
+
* phase's `-PLAN.md` files against the filesystem WITHOUT executing anything —
|
|
857
|
+
* see verify-command-grounding.cjs for the recognizer contract.
|
|
858
|
+
*
|
|
859
|
+
* Args: check verify-command-paths <phase>
|
|
860
|
+
* Invocable as: gsd_run check verify-command-paths <phase>
|
|
861
|
+
*
|
|
862
|
+
* When the phase cannot be resolved to a directory, this emits a non-throwing
|
|
863
|
+
* degraded JSON payload (status/commands/counts all zeroed, `readError`
|
|
864
|
+
* populated) rather than calling `error()` — the plan-checker parses this
|
|
865
|
+
* result and must be able to distinguish "nothing to report" from "could not
|
|
866
|
+
* look", which a non-zero exit / thrown error would collapse.
|
|
867
|
+
*/
|
|
868
|
+
function cmdVerifyCommandPaths(projectDir, args, raw) {
|
|
869
|
+
// args[0] = 'check', args[1] = 'verify-command-paths', args[2] = phase
|
|
870
|
+
const phase = args[2] || '';
|
|
871
|
+
if (!phase) {
|
|
872
|
+
output({
|
|
873
|
+
status: 'unresolvable',
|
|
874
|
+
commands: [],
|
|
875
|
+
counts: { blocker: 0, warning: 0, total: 0 },
|
|
876
|
+
readError: 'verify-command-paths requires a phase argument: check verify-command-paths <phase>',
|
|
877
|
+
}, raw, undefined);
|
|
878
|
+
return;
|
|
879
|
+
}
|
|
880
|
+
const phaseDir = resolvePhaseDirOrEmpty(projectDir, phase);
|
|
881
|
+
if (!phaseDir) {
|
|
882
|
+
output({
|
|
883
|
+
status: 'unresolvable',
|
|
884
|
+
commands: [],
|
|
885
|
+
counts: { blocker: 0, warning: 0, total: 0 },
|
|
886
|
+
readError: `could not resolve phase directory for phase ${phase}`,
|
|
887
|
+
}, raw, undefined);
|
|
888
|
+
return;
|
|
889
|
+
}
|
|
890
|
+
const probed = probePhaseVerifyCommands({ phaseDir, projectRoot: projectDir });
|
|
891
|
+
output(probed, raw, undefined);
|
|
892
|
+
}
|
|
893
|
+
// ─── verify-failure-directions (#3172) ─────────────────────────────────────────
|
|
894
|
+
/**
|
|
895
|
+
* verify-failure-directions: probes every `<automated>` verify command
|
|
896
|
+
* declared in a phase's `-PLAN.md` files for a stated `<fails_when>` failing
|
|
897
|
+
* direction — see verify-command-grounding.cjs for the recognizer contract.
|
|
898
|
+
*
|
|
899
|
+
* Args: check verify-failure-directions <phase>
|
|
900
|
+
* Invocable as: gsd_run check verify-failure-directions <phase>
|
|
901
|
+
*
|
|
902
|
+
* When the phase cannot be resolved to a directory, this emits a non-throwing
|
|
903
|
+
* degraded JSON payload (status/commands/counts all zeroed, `readError`
|
|
904
|
+
* populated) rather than calling `error()` — the plan-checker parses this
|
|
905
|
+
* result and must be able to distinguish "nothing to report" from "could not
|
|
906
|
+
* look", which a non-zero exit / thrown error would collapse.
|
|
907
|
+
*/
|
|
908
|
+
function cmdVerifyFailureDirections(projectDir, args, raw) {
|
|
909
|
+
// args[0] = 'check', args[1] = 'verify-failure-directions', args[2] = phase
|
|
910
|
+
const phase = args[2] || '';
|
|
911
|
+
if (!phase) {
|
|
912
|
+
output({
|
|
913
|
+
status: 'unresolvable',
|
|
914
|
+
commands: [],
|
|
915
|
+
counts: { blocker: 0, warning: 0, total: 0 },
|
|
916
|
+
readError: 'verify-failure-directions requires a phase argument: check verify-failure-directions <phase>',
|
|
917
|
+
}, raw, undefined);
|
|
918
|
+
return;
|
|
919
|
+
}
|
|
920
|
+
const phaseDir = resolvePhaseDirOrEmpty(projectDir, phase);
|
|
921
|
+
if (!phaseDir) {
|
|
922
|
+
output({
|
|
923
|
+
status: 'unresolvable',
|
|
924
|
+
commands: [],
|
|
925
|
+
counts: { blocker: 0, warning: 0, total: 0 },
|
|
926
|
+
readError: `could not resolve phase directory for phase ${phase}`,
|
|
927
|
+
}, raw, undefined);
|
|
928
|
+
return;
|
|
929
|
+
}
|
|
930
|
+
const result = probePhaseFailingDirections({ phaseDir });
|
|
931
|
+
output(result, raw, undefined);
|
|
932
|
+
}
|
|
797
933
|
// ─── gap-analysis-plan-post ───────────────────────────────────────────────────
|
|
798
934
|
/**
|
|
799
935
|
* gap-analysis-plan-post: non-blocking advisory check that runs the post-planning
|
|
@@ -1172,6 +1308,27 @@ function cmdApiCoverageVerifyPre(projectDir, args, raw) {
|
|
|
1172
1308
|
}, raw, undefined);
|
|
1173
1309
|
return;
|
|
1174
1310
|
}
|
|
1311
|
+
// An EMPTY scope is not a negative verdict. This gate's neighbouring arms
|
|
1312
|
+
// already fail closed (unresolvable phase → block; unreadable plan → block),
|
|
1313
|
+
// but a phase with no plan body AND no roadmap section fell through to
|
|
1314
|
+
// detection over zero bytes and CERTIFIED "no external-API integration" —
|
|
1315
|
+
// clearing a blocking seal gate on a probe that examined nothing
|
|
1316
|
+
// (ADR-3889 failure class (c), #3909). The discriminator is BYTES EXAMINED,
|
|
1317
|
+
// never SIGNALS FOUND: a phase with real plans and no API vocabulary still
|
|
1318
|
+
// reaches the pass below unchanged.
|
|
1319
|
+
if (scope.text.trim() === '') {
|
|
1320
|
+
output({
|
|
1321
|
+
block: true,
|
|
1322
|
+
passed: false,
|
|
1323
|
+
coverage_present: false,
|
|
1324
|
+
detected: false,
|
|
1325
|
+
scope_unavailable: true,
|
|
1326
|
+
message: 'api-coverage: the phase scope is empty — no plan body and no roadmap section were ' +
|
|
1327
|
+
'found, so nothing was examined. Refusing to certify no external-API integration ' +
|
|
1328
|
+
'from an unestablished scope. Add the phase plan, or add a COVERAGE.md declaration.',
|
|
1329
|
+
}, raw, undefined);
|
|
1330
|
+
return;
|
|
1331
|
+
}
|
|
1175
1332
|
const detection = detectApiIntegration(scope.text);
|
|
1176
1333
|
if (detection.detected) {
|
|
1177
1334
|
// Surface only verb/noun (typed, bounded) — NOT raw prose snippets — so the
|
|
@@ -1207,12 +1364,26 @@ function isRealReadFailure(err) {
|
|
|
1207
1364
|
function readPhaseScope(projectDir, phaseDir, phaseNumber) {
|
|
1208
1365
|
const chunks = [];
|
|
1209
1366
|
let readError = null;
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1367
|
+
// A MISSING phase directory is fine (no plans yet → fall through to the
|
|
1368
|
+
// roadmap). Checked up front (rather than via a readdirSync catch) because
|
|
1369
|
+
// #3183 (lint-plan-count-drift) now sources the plan-file list from the
|
|
1370
|
+
// single owner (scanPhasePlans) instead of a local `-PLAN\.md$` readdirSync
|
|
1371
|
+
// filter — picks up bare PLAN.md and nested plans/, and excludes
|
|
1372
|
+
// superseded plans, none of which the prior root-only exact-suffix filter
|
|
1373
|
+
// did.
|
|
1374
|
+
if (node_fs_1.default.existsSync(phaseDir)) {
|
|
1375
|
+
const scan = scanPhasePlans(phaseDir);
|
|
1376
|
+
if (scan.scope === SCOPE.UNREADABLE) {
|
|
1377
|
+
// Directory exists but scanPhasePlans's own readdirSync(phaseDir) call
|
|
1378
|
+
// failed (EACCES/EIO race) — a real read failure the gate must not
|
|
1379
|
+
// silently pass (#2365 review), mirroring the prior isRealReadFailure
|
|
1380
|
+
// branch below for the readdirSync-throws case.
|
|
1381
|
+
return {
|
|
1382
|
+
text: '',
|
|
1383
|
+
readError: 'could not read the phase directory: scanPhasePlans reported scope UNREADABLE',
|
|
1384
|
+
};
|
|
1385
|
+
}
|
|
1386
|
+
const plans = [...scan.planFiles].sort();
|
|
1216
1387
|
for (const p of plans) {
|
|
1217
1388
|
try {
|
|
1218
1389
|
chunks.push(node_fs_1.default.readFileSync(node_path_1.default.join(phaseDir, p), 'utf8'));
|
|
@@ -1226,17 +1397,6 @@ function readPhaseScope(projectDir, phaseDir, phaseNumber) {
|
|
|
1226
1397
|
}
|
|
1227
1398
|
}
|
|
1228
1399
|
}
|
|
1229
|
-
catch (err) {
|
|
1230
|
-
// A MISSING phase directory is fine (no plans yet → fall through to the
|
|
1231
|
-
// roadmap). A directory that exists but cannot be enumerated (EACCES/EIO)
|
|
1232
|
-
// is a real read failure the gate must not silently pass (#2365 review).
|
|
1233
|
-
if (isRealReadFailure(err)) {
|
|
1234
|
-
return {
|
|
1235
|
-
text: '',
|
|
1236
|
-
readError: `could not read the phase directory: ${err instanceof Error ? err.message : String(err)}`,
|
|
1237
|
-
};
|
|
1238
|
-
}
|
|
1239
|
-
}
|
|
1240
1400
|
if (readError)
|
|
1241
1401
|
return { text: chunks.join('\n\n'), readError };
|
|
1242
1402
|
if (chunks.join('').trim().length > 0)
|
|
@@ -1290,6 +1450,18 @@ function routeCheckCommand({ args, cwd, raw }) {
|
|
|
1290
1450
|
cmdGapAnalysisPlanPost(cwd, args, raw);
|
|
1291
1451
|
return;
|
|
1292
1452
|
}
|
|
1453
|
+
if (subcommand === 'verify-command-paths') {
|
|
1454
|
+
// Deterministic filesystem probe for <automated> verify commands (#2401) —
|
|
1455
|
+
// never executes anything; see verify-command-grounding.cjs.
|
|
1456
|
+
cmdVerifyCommandPaths(cwd, args, raw);
|
|
1457
|
+
return;
|
|
1458
|
+
}
|
|
1459
|
+
if (subcommand === 'verify-failure-directions') {
|
|
1460
|
+
// Presence probe for a stated <fails_when> per <automated> command
|
|
1461
|
+
// (#3172) — never executes anything; see verify-command-grounding.cjs.
|
|
1462
|
+
cmdVerifyFailureDirections(cwd, args, raw);
|
|
1463
|
+
return;
|
|
1464
|
+
}
|
|
1293
1465
|
if (subcommand === 'api-coverage-verify-pre') {
|
|
1294
1466
|
// ai-integration capability blocking gate at verify:pre (#1562). Dot-to-
|
|
1295
1467
|
// hyphen normalization means query "api-coverage.verify-pre" routes here.
|
|
@@ -1336,7 +1508,7 @@ function routeCheckCommand({ args, cwd, raw }) {
|
|
|
1336
1508
|
(0, prohibition_enforcement_cjs_1.routeProhibitionEnforcement)(args, raw);
|
|
1337
1509
|
return;
|
|
1338
1510
|
}
|
|
1339
|
-
error('Unknown check subcommand. Available: api-coverage-verify-pre, auto-mode, decision-coverage-plan, decision-coverage-verify, gap-analysis-plan-post, predicate, prohibition-enforcement, tdd-review-checkpoint, ui-plan-gate, ui-safety-gate, verify-schema-drift, verify-codebase-drift', ERROR_REASON.SDK_UNKNOWN_COMMAND);
|
|
1511
|
+
error('Unknown check subcommand. Available: api-coverage-verify-pre, auto-mode, decision-coverage-plan, decision-coverage-verify, gap-analysis-plan-post, predicate, prohibition-enforcement, tdd-review-checkpoint, ui-plan-gate, ui-safety-gate, verify-command-paths, verify-failure-directions, verify-schema-drift, verify-codebase-drift', ERROR_REASON.SDK_UNKNOWN_COMMAND);
|
|
1340
1512
|
}
|
|
1341
1513
|
module.exports = {
|
|
1342
1514
|
routeCheckCommand,
|
|
@@ -1345,6 +1517,8 @@ module.exports = {
|
|
|
1345
1517
|
computeUiPlanGate,
|
|
1346
1518
|
computeUiSafetyGate,
|
|
1347
1519
|
cmdGapAnalysisPlanPost,
|
|
1520
|
+
cmdVerifyCommandPaths,
|
|
1521
|
+
cmdVerifyFailureDirections,
|
|
1348
1522
|
cmdTddReviewCheckpoint,
|
|
1349
1523
|
cmdCheckPredicate,
|
|
1350
1524
|
buildPredicateDeps,
|
|
@@ -470,13 +470,43 @@ function emitWorkflowScript(input) {
|
|
|
470
470
|
lines.push('// read-only in a Workflow script — set it via the caller\'s token directive.');
|
|
471
471
|
}
|
|
472
472
|
lines.push('');
|
|
473
|
+
// #3302: the generated script must hand the per-agent executor results back
|
|
474
|
+
// to the orchestrator so it can feed the wave merge chain. Emitted right
|
|
475
|
+
// after the header comments (meta stays the first statement): a helper that
|
|
476
|
+
// extracts the executor's <worktree_metadata> JSON (agents/gsd-executor.md
|
|
477
|
+
// <worktree_metadata_capture>) from one agent() result, plus the outcomes
|
|
478
|
+
// accumulator the stage barriers below push into. `metadata` is null when
|
|
479
|
+
// the result carried no parseable block — the LOUD-failure input the
|
|
480
|
+
// orchestrator halts on for expects_worktree plans (never a silent skip).
|
|
481
|
+
lines.push('// #3302: extract the executor-returned <worktree_metadata> JSON so the');
|
|
482
|
+
lines.push('// orchestrator can record it into WAVE_WORKTREE_MANIFEST after the run');
|
|
483
|
+
lines.push('// (worktree.record-agent -> worktree.cleanup-wave, the same manifest-scoped');
|
|
484
|
+
lines.push('// merge chain inline dispatch feeds). null = absent/unparseable/interrupted.');
|
|
485
|
+
lines.push('function gsdWorktreeMetadata(agentResult) {');
|
|
486
|
+
lines.push(' if (typeof agentResult !== \'string\') return null;');
|
|
487
|
+
lines.push(' const m = agentResult.match(/<worktree_metadata>([\\s\\S]*?)<\\/worktree_metadata>/);');
|
|
488
|
+
lines.push(' if (m === null) return null;');
|
|
489
|
+
lines.push(' try {');
|
|
490
|
+
lines.push(' const parsed = JSON.parse(m[1]);');
|
|
491
|
+
lines.push(' return (parsed !== null && typeof parsed === \'object\') ? parsed : null;');
|
|
492
|
+
lines.push(' } catch (e) {');
|
|
493
|
+
lines.push(' return null;');
|
|
494
|
+
lines.push(' }');
|
|
495
|
+
lines.push('}');
|
|
496
|
+
lines.push('const gsdAgentOutcomes = [];');
|
|
497
|
+
lines.push('');
|
|
473
498
|
const stagesByWave = [];
|
|
474
499
|
let totalPlans = 0;
|
|
500
|
+
let worktreePlans = 0;
|
|
475
501
|
for (let wi = 0; wi < waves.length; wi++) {
|
|
476
502
|
const wave = waves[wi];
|
|
477
503
|
const stages = partitionStages(wave.plans);
|
|
478
504
|
stagesByWave.push(stages);
|
|
479
505
|
totalPlans += wave.plans.length;
|
|
506
|
+
for (const p of wave.plans) {
|
|
507
|
+
if (p.use_worktree !== false)
|
|
508
|
+
worktreePlans += 1;
|
|
509
|
+
}
|
|
480
510
|
lines.push('// Wave ' + wave.id);
|
|
481
511
|
// Title must match this wave's meta.phases entry EXACTLY.
|
|
482
512
|
lines.push('phase(' + quoteString('Wave ' + wave.id) + ')');
|
|
@@ -491,17 +521,37 @@ function emitWorkflowScript(input) {
|
|
|
491
521
|
// threw "parallel() expects an array of functions" (#2590). Passing
|
|
492
522
|
// agent() results directly would also start every agent eagerly, before
|
|
493
523
|
// parallel() could bound concurrency.
|
|
494
|
-
|
|
524
|
+
// #3302: capture the barrier's resolved results (one per thunk, in thunk
|
|
525
|
+
// order — the documented parallel() contract) so each plan's outcome can
|
|
526
|
+
// be tagged and returned below. Discarding them stranded every
|
|
527
|
+
// worktree-wf_* branch: the merge chain had no input (#3302).
|
|
528
|
+
lines.push('const gsdStage_' + wi + '_' + si + ' = await parallel([');
|
|
495
529
|
for (const p of stagePlans) {
|
|
496
530
|
lines.push(' () => agent(' + quoteString(p.brief) + ', ' + agentOptions(p, executorModel) + '),');
|
|
497
531
|
}
|
|
498
532
|
lines.push('])');
|
|
533
|
+
// Positional tagging is decided at EMIT time from the validated manifest,
|
|
534
|
+
// so attribution survives out-of-order completion and needs no runtime
|
|
535
|
+
// introspection. expects_worktree mirrors agentOptions' own per-plan
|
|
536
|
+
// decision (use_worktree !== false).
|
|
537
|
+
lines.push('gsdAgentOutcomes.push(');
|
|
538
|
+
for (let pi = 0; pi < stagePlans.length; pi++) {
|
|
539
|
+
const p = stagePlans[pi];
|
|
540
|
+
const tail = pi < stagePlans.length - 1 ? ',' : '';
|
|
541
|
+
lines.push(' { plan: ' + quoteString(p.id) + ', expects_worktree: ' + (p.use_worktree !== false) + ', metadata: gsdWorktreeMetadata(gsdStage_' + wi + '_' + si + '[' + pi + ']) }' + tail);
|
|
542
|
+
}
|
|
543
|
+
lines.push(')');
|
|
499
544
|
}
|
|
500
545
|
if (wi < waves.length - 1)
|
|
501
546
|
lines.push('');
|
|
502
547
|
}
|
|
503
|
-
|
|
504
|
-
|
|
548
|
+
// #3302: the script's top-level return value is what the Workflow tool hands
|
|
549
|
+
// back to the orchestrator. One { plan, expects_worktree, metadata } entry
|
|
550
|
+
// per dispatched plan; the orchestrator records every worktree entry via
|
|
551
|
+
// `gsd_run query worktree.record-agent` and HALTS on a null metadata entry
|
|
552
|
+
// for an expects_worktree plan (see the execute:wave:pre fragment) — a
|
|
553
|
+
// silently-empty manifest is the exact #3302 failure mode.
|
|
554
|
+
lines.push('return gsdAgentOutcomes');
|
|
505
555
|
const script = lines.join('\n');
|
|
506
556
|
return {
|
|
507
557
|
ok: true,
|
|
@@ -509,6 +559,9 @@ function emitWorkflowScript(input) {
|
|
|
509
559
|
summary: {
|
|
510
560
|
waves: waves.length,
|
|
511
561
|
plans: totalPlans,
|
|
562
|
+
// #3302: the number of record-agent entries the orchestrator must end up
|
|
563
|
+
// with in WAVE_WORKTREE_MANIFEST after the run — the loud count check.
|
|
564
|
+
worktreePlans,
|
|
512
565
|
stagesByWave,
|
|
513
566
|
resumeRunId: runId,
|
|
514
567
|
budgetTokens,
|