@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
|
@@ -22,8 +22,13 @@ const { planningDir } = planningWorkspaceMod;
|
|
|
22
22
|
const phaseLocatorMod = require("./phase-locator.cjs");
|
|
23
23
|
const { findPhaseInternal } = phaseLocatorMod;
|
|
24
24
|
const decisions_cjs_1 = require("./decisions.cjs");
|
|
25
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
26
|
+
const frontmatterMod = require("./frontmatter.cjs");
|
|
27
|
+
const { extractFrontmatter } = frontmatterMod;
|
|
25
28
|
const markdown_sectionizer_cjs_1 = require("./markdown-sectionizer.cjs");
|
|
29
|
+
const security_cjs_1 = require("./security.cjs");
|
|
26
30
|
const ui_safety_gate_cjs_1 = require("./ui-safety-gate.cjs");
|
|
31
|
+
const ui_frontend_evidence_cjs_1 = require("./ui-frontend-evidence.cjs");
|
|
27
32
|
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
28
33
|
const verifyModule = require("./verify.cjs");
|
|
29
34
|
const { cmdVerifySchemaDrift, cmdVerifyCodebaseDrift } = verifyModule;
|
|
@@ -41,6 +46,12 @@ const { evaluatePredicate } = gatePredicateEval;
|
|
|
41
46
|
const apiCoverageMod = require("./api-coverage.cjs");
|
|
42
47
|
const { detectApiIntegration, validateCoverageMatrix } = apiCoverageMod;
|
|
43
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;
|
|
44
55
|
// ─── Helpers ──────────────────────────────────────────────────────────────────
|
|
45
56
|
function normalizePhrase(text) {
|
|
46
57
|
// eslint-disable-next-line @typescript-eslint/no-base-to-string
|
|
@@ -124,14 +135,13 @@ function gateEnabled(projectDir) {
|
|
|
124
135
|
function loadPlanContents(phaseDir) {
|
|
125
136
|
if (!node_fs_1.default.existsSync(phaseDir))
|
|
126
137
|
return [];
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
}
|
|
138
|
+
// #3183 (lint-plan-count-drift): source live plan files from the single
|
|
139
|
+
// owner (scanPhasePlans) instead of a local `-PLAN.md` readdirSync filter
|
|
140
|
+
// — picks up bare PLAN.md and nested plans/, and excludes plans marked
|
|
141
|
+
// `status: superseded`, which the prior root-only exact-suffix filter did
|
|
142
|
+
// neither for.
|
|
143
|
+
return scanPhasePlans(phaseDir).planFiles
|
|
144
|
+
.map((entry) => readIfExists(node_path_1.default.join(phaseDir, entry)));
|
|
135
145
|
}
|
|
136
146
|
const DESIGNATED_HEADINGS_RE = /^#{1,6}\s+(?:must[_ ]haves?|truths?|tasks?|objective)\b/i;
|
|
137
147
|
// #2372: scanned-tag set must match the planner-canonical surfaces where a D-NN citation
|
|
@@ -333,6 +343,7 @@ function recentCommitMessages(projectDir) {
|
|
|
333
343
|
encoding: 'utf-8',
|
|
334
344
|
maxBuffer: 4 * 1024 * 1024,
|
|
335
345
|
windowsHide: true,
|
|
346
|
+
timeout: 15_000,
|
|
336
347
|
});
|
|
337
348
|
}
|
|
338
349
|
catch {
|
|
@@ -407,8 +418,11 @@ function cmdDecisionCoverageVerify(projectDir, args, raw) {
|
|
|
407
418
|
return;
|
|
408
419
|
}
|
|
409
420
|
const planContents = loadPlanContents(phaseDir);
|
|
421
|
+
// #3183 (lint-plan-count-drift): same single-owner sourcing as
|
|
422
|
+
// loadPlanContents above — scanPhasePlans's summaryFiles instead of a
|
|
423
|
+
// local `-SUMMARY.md` readdirSync filter.
|
|
410
424
|
const summaryParts = node_fs_1.default.existsSync(phaseDir)
|
|
411
|
-
?
|
|
425
|
+
? scanPhasePlans(phaseDir).summaryFiles.map((entry) => readIfExists(node_path_1.default.join(phaseDir, entry)))
|
|
412
426
|
: [];
|
|
413
427
|
const haystack = [
|
|
414
428
|
planContents.join('\n\n'),
|
|
@@ -438,8 +452,9 @@ function cmdDecisionCoverageVerify(projectDir, args, raw) {
|
|
|
438
452
|
* ui-plan-gate: given a phase number, checks whether the phase has frontend
|
|
439
453
|
* indicators and whether a *-UI-SPEC.md already exists in the phase directory.
|
|
440
454
|
*
|
|
441
|
-
* Returns JSON: { frontend
|
|
442
|
-
* block = frontend && !hasUiSpec (gate fires when
|
|
455
|
+
* Returns JSON: { frontend, hasFrontendEvidence, hasUiSpec, block, uiSpecPath, matchedToken, matchedLine }
|
|
456
|
+
* block = frontend && hasFrontendEvidence && !hasUiSpec (#3312: gate fires when
|
|
457
|
+
* UI work is detected AND the repo has static frontend evidence but no spec exists)
|
|
443
458
|
*
|
|
444
459
|
* Invocable as: gsd_run check ui-plan-gate <phase>
|
|
445
460
|
*
|
|
@@ -473,10 +488,21 @@ function findUiSpecInDir(phaseDir) {
|
|
|
473
488
|
* (b) Runs checkUiPresence (frontend detection) — no reimplementation.
|
|
474
489
|
* (c) Resolves the phase directory via findPhaseInternal (phase-locator.cjs); checks for *-UI-SPEC.md.
|
|
475
490
|
*
|
|
476
|
-
* Returns: { frontend, hasUiSpec, block, uiSpecPath, phaseLookupFailed }
|
|
477
|
-
* block = frontend && !hasUiSpec
|
|
491
|
+
* Returns: { frontend, hasFrontendEvidence, hasUiSpec, block, uiSpecPath, matchedToken, matchedLine, phaseLookupFailed }
|
|
492
|
+
* block = frontend && hasFrontendEvidence && !hasUiSpec (#3312)
|
|
478
493
|
* phaseLookupFailed = ROADMAP.md present but phase header not found (surfaced for
|
|
479
494
|
* onError:halt gates so a missing phase doesn't silently bypass)
|
|
495
|
+
*
|
|
496
|
+
* #3312 — structural corroboration: `frontend` is a vocabulary signal only. A
|
|
497
|
+
* hyphen is a word boundary, so a phase naming the repo `dashboard-financeiro`
|
|
498
|
+
* matches the token `dashboard` exactly like the real compound `micro-frontend`
|
|
499
|
+
* (the boundary rule of #3718 is intentional and untouched). The gate therefore
|
|
500
|
+
* blocks only when the token match is corroborated by static frontend evidence
|
|
501
|
+
* in the repo tree (hasStaticFrontendEvidence: package.json UI-framework dep or
|
|
502
|
+
* a component-framework file). This mirrors the sibling post-wave gate
|
|
503
|
+
* computeUiSafetyGate, which requires `hasUiFiles` (git diff) before blocking.
|
|
504
|
+
* matchedToken/matchedLine surface what tripped the sniffer so an operator can
|
|
505
|
+
* judge the flag in one second instead of reaching for --skip-ui.
|
|
480
506
|
*/
|
|
481
507
|
function computeUiPlanGate(projectDir, phase) {
|
|
482
508
|
// (a) Read the phase section text using the same two-pass lookup as roadmap.get-phase.
|
|
@@ -505,6 +531,9 @@ function computeUiPlanGate(projectDir, phase) {
|
|
|
505
531
|
// (b) Run checkUiPresence (frontend detection) — reuse existing helper; no reimplementation
|
|
506
532
|
const presenceResult = (0, ui_safety_gate_cjs_1.checkUiPresence)(phaseSection);
|
|
507
533
|
const frontend = presenceResult.hasUI;
|
|
534
|
+
// (b') #3312 — static structural corroboration. Only probed when the sniffer
|
|
535
|
+
// matched (evidence is irrelevant otherwise); failures degrade to false.
|
|
536
|
+
const hasFrontendEvidence = frontend ? (0, ui_frontend_evidence_cjs_1.hasStaticFrontendEvidence)(projectDir) : false;
|
|
508
537
|
// (c) Resolve phase directory via findPhaseInternal and check for *-UI-SPEC.md
|
|
509
538
|
let phaseDir = '';
|
|
510
539
|
try {
|
|
@@ -524,10 +553,13 @@ function computeUiPlanGate(projectDir, phase) {
|
|
|
524
553
|
catch { /* phase dir lookup failure → hasUiSpec=false */ }
|
|
525
554
|
const uiSpecPath = findUiSpecInDir(phaseDir);
|
|
526
555
|
const hasUiSpec = uiSpecPath !== '';
|
|
527
|
-
// block = frontend phase with no UI-SPEC
|
|
528
|
-
const block = frontend && !hasUiSpec;
|
|
556
|
+
// block = frontend phase with structural frontend evidence and no UI-SPEC (#3312)
|
|
557
|
+
const block = frontend && hasFrontendEvidence && !hasUiSpec;
|
|
529
558
|
const result = {
|
|
530
|
-
frontend, hasUiSpec, block,
|
|
559
|
+
frontend, hasFrontendEvidence, hasUiSpec, block,
|
|
560
|
+
uiSpecPath: hasUiSpec ? uiSpecPath : null,
|
|
561
|
+
matchedToken: presenceResult.matchedToken,
|
|
562
|
+
matchedLine: presenceResult.matchedLine,
|
|
531
563
|
};
|
|
532
564
|
if (phaseLookupFailed)
|
|
533
565
|
result.phaseLookupFailed = true;
|
|
@@ -609,6 +641,7 @@ function computeUiSafetyGate(projectDir, phase) {
|
|
|
609
641
|
encoding: 'utf-8',
|
|
610
642
|
maxBuffer: 2 * 1024 * 1024,
|
|
611
643
|
windowsHide: true,
|
|
644
|
+
timeout: 10_000,
|
|
612
645
|
});
|
|
613
646
|
hasUiFiles = changed.split('\n').some((f) => f.trim() && (UI_FILE_EXTENSIONS_RE.test(f) || UI_PATH_PATTERNS_RE.test(f)));
|
|
614
647
|
}
|
|
@@ -675,7 +708,9 @@ function cmdTddReviewCheckpoint(projectDir, args, raw) {
|
|
|
675
708
|
const tddPlanFiles = [];
|
|
676
709
|
if (phaseDir) {
|
|
677
710
|
try {
|
|
678
|
-
|
|
711
|
+
// #3183: canonical plan set (root+nested, superseded-excluded) from the
|
|
712
|
+
// single owner, rather than a root-only hand-rolled readdirSync filter.
|
|
713
|
+
const files = scanPhasePlans(phaseDir).planFiles;
|
|
679
714
|
for (const file of files) {
|
|
680
715
|
const planPath = node_path_1.default.join(phaseDir, file);
|
|
681
716
|
const content = readIfExists(planPath);
|
|
@@ -724,17 +759,17 @@ function cmdTddReviewCheckpoint(projectDir, args, raw) {
|
|
|
724
759
|
let green = false;
|
|
725
760
|
let refactor = false;
|
|
726
761
|
try {
|
|
727
|
-
const redCommit = (0, node_child_process_1.execFileSync)('git', ['log', '--oneline', `--grep=^test(${planId}):`, '--', '.'], { cwd: projectDir, encoding: 'utf-8', maxBuffer: 1024 * 1024, windowsHide: true });
|
|
762
|
+
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 });
|
|
728
763
|
red = redCommit.trim().length > 0;
|
|
729
764
|
}
|
|
730
765
|
catch { /* git unavailable or no match */ }
|
|
731
766
|
try {
|
|
732
|
-
const greenCommit = (0, node_child_process_1.execFileSync)('git', ['log', '--oneline', `--grep=^feat(${planId}):`, '--', '.'], { cwd: projectDir, encoding: 'utf-8', maxBuffer: 1024 * 1024, windowsHide: true });
|
|
767
|
+
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 });
|
|
733
768
|
green = greenCommit.trim().length > 0;
|
|
734
769
|
}
|
|
735
770
|
catch { /* git unavailable or no match */ }
|
|
736
771
|
try {
|
|
737
|
-
const refactorCommit = (0, node_child_process_1.execFileSync)('git', ['log', '--oneline', `--grep=^refactor(${planId}):`, '--', '.'], { cwd: projectDir, encoding: 'utf-8', maxBuffer: 1024 * 1024, windowsHide: true });
|
|
772
|
+
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 });
|
|
738
773
|
refactor = refactorCommit.trim().length > 0;
|
|
739
774
|
}
|
|
740
775
|
catch { /* git unavailable or no match */ }
|
|
@@ -849,9 +884,47 @@ function buildPredicateDeps() {
|
|
|
849
884
|
stdout: r.stdout,
|
|
850
885
|
stderr: r.stderr,
|
|
851
886
|
signal: r.signal,
|
|
852
|
-
timedOut: r.
|
|
887
|
+
timedOut: r.timedOut,
|
|
853
888
|
};
|
|
854
889
|
},
|
|
890
|
+
findPhaseArtifact(phaseDir, artifactSuffix) {
|
|
891
|
+
if (!node_fs_1.default.existsSync(phaseDir))
|
|
892
|
+
return null;
|
|
893
|
+
if (artifactSuffix === '.' ||
|
|
894
|
+
artifactSuffix === '..' ||
|
|
895
|
+
artifactSuffix.includes('\0') ||
|
|
896
|
+
node_path_1.default.basename(artifactSuffix) !== artifactSuffix ||
|
|
897
|
+
node_path_1.default.win32.basename(artifactSuffix) !== artifactSuffix) {
|
|
898
|
+
return null;
|
|
899
|
+
}
|
|
900
|
+
const directPath = (0, security_cjs_1.validatePath)(artifactSuffix, phaseDir);
|
|
901
|
+
if (directPath.safe && node_fs_1.default.existsSync(directPath.resolved) && node_fs_1.default.statSync(directPath.resolved).isFile()) {
|
|
902
|
+
return directPath.resolved;
|
|
903
|
+
}
|
|
904
|
+
const planningPath = (0, security_cjs_1.validatePath)(node_path_1.default.join('.planning', artifactSuffix), phaseDir);
|
|
905
|
+
if (planningPath.safe && node_fs_1.default.existsSync(planningPath.resolved) && node_fs_1.default.statSync(planningPath.resolved).isFile()) {
|
|
906
|
+
return planningPath.resolved;
|
|
907
|
+
}
|
|
908
|
+
try {
|
|
909
|
+
const files = node_fs_1.default.readdirSync(phaseDir);
|
|
910
|
+
for (const f of files) {
|
|
911
|
+
if (f.endsWith('-' + artifactSuffix) || f === artifactSuffix) {
|
|
912
|
+
const candidate = (0, security_cjs_1.validatePath)(f, phaseDir);
|
|
913
|
+
if (candidate.safe && node_fs_1.default.statSync(candidate.resolved).isFile())
|
|
914
|
+
return candidate.resolved;
|
|
915
|
+
}
|
|
916
|
+
}
|
|
917
|
+
}
|
|
918
|
+
catch { /* ignore */ }
|
|
919
|
+
return null;
|
|
920
|
+
},
|
|
921
|
+
readFrontmatter(filePath) {
|
|
922
|
+
const content = (0, shell_command_projection_cjs_1.platformReadSync)(filePath);
|
|
923
|
+
if (content === null)
|
|
924
|
+
throw new Error(`predicate artifact disappeared before it could be read: ${filePath}`);
|
|
925
|
+
const parsed = extractFrontmatter(content, filePath);
|
|
926
|
+
return parsed;
|
|
927
|
+
}
|
|
855
928
|
};
|
|
856
929
|
}
|
|
857
930
|
/** Parse `--flag value` pairs from an args array into a map (last write wins). */
|
|
@@ -1165,12 +1238,26 @@ function isRealReadFailure(err) {
|
|
|
1165
1238
|
function readPhaseScope(projectDir, phaseDir, phaseNumber) {
|
|
1166
1239
|
const chunks = [];
|
|
1167
1240
|
let readError = null;
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1241
|
+
// A MISSING phase directory is fine (no plans yet → fall through to the
|
|
1242
|
+
// roadmap). Checked up front (rather than via a readdirSync catch) because
|
|
1243
|
+
// #3183 (lint-plan-count-drift) now sources the plan-file list from the
|
|
1244
|
+
// single owner (scanPhasePlans) instead of a local `-PLAN\.md$` readdirSync
|
|
1245
|
+
// filter — picks up bare PLAN.md and nested plans/, and excludes
|
|
1246
|
+
// superseded plans, none of which the prior root-only exact-suffix filter
|
|
1247
|
+
// did.
|
|
1248
|
+
if (node_fs_1.default.existsSync(phaseDir)) {
|
|
1249
|
+
const scan = scanPhasePlans(phaseDir);
|
|
1250
|
+
if (scan.scope === SCOPE.UNREADABLE) {
|
|
1251
|
+
// Directory exists but scanPhasePlans's own readdirSync(phaseDir) call
|
|
1252
|
+
// failed (EACCES/EIO race) — a real read failure the gate must not
|
|
1253
|
+
// silently pass (#2365 review), mirroring the prior isRealReadFailure
|
|
1254
|
+
// branch below for the readdirSync-throws case.
|
|
1255
|
+
return {
|
|
1256
|
+
text: '',
|
|
1257
|
+
readError: 'could not read the phase directory: scanPhasePlans reported scope UNREADABLE',
|
|
1258
|
+
};
|
|
1259
|
+
}
|
|
1260
|
+
const plans = [...scan.planFiles].sort();
|
|
1174
1261
|
for (const p of plans) {
|
|
1175
1262
|
try {
|
|
1176
1263
|
chunks.push(node_fs_1.default.readFileSync(node_path_1.default.join(phaseDir, p), 'utf8'));
|
|
@@ -1184,17 +1271,6 @@ function readPhaseScope(projectDir, phaseDir, phaseNumber) {
|
|
|
1184
1271
|
}
|
|
1185
1272
|
}
|
|
1186
1273
|
}
|
|
1187
|
-
catch (err) {
|
|
1188
|
-
// A MISSING phase directory is fine (no plans yet → fall through to the
|
|
1189
|
-
// roadmap). A directory that exists but cannot be enumerated (EACCES/EIO)
|
|
1190
|
-
// is a real read failure the gate must not silently pass (#2365 review).
|
|
1191
|
-
if (isRealReadFailure(err)) {
|
|
1192
|
-
return {
|
|
1193
|
-
text: '',
|
|
1194
|
-
readError: `could not read the phase directory: ${err instanceof Error ? err.message : String(err)}`,
|
|
1195
|
-
};
|
|
1196
|
-
}
|
|
1197
|
-
}
|
|
1198
1274
|
if (readError)
|
|
1199
1275
|
return { text: chunks.join('\n\n'), readError };
|
|
1200
1276
|
if (chunks.join('').trim().length > 0)
|
|
@@ -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,
|