@opengsd/gsd-pi 1.1.1-dev.b2556262 → 1.2.0-dev.0b870afa
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/dist/cli-style.d.ts +17 -0
- package/dist/cli-style.js +28 -0
- package/dist/cli-web-branch.d.ts +2 -0
- package/dist/cli-web-branch.js +9 -2
- package/dist/cli.js +1 -1
- package/dist/headless-events.d.ts +4 -2
- package/dist/headless-events.js +14 -34
- package/dist/help-text.js +5 -0
- package/dist/mcp-server.js +2 -1
- package/dist/models-resolver.d.ts +3 -13
- package/dist/models-resolver.js +3 -22
- package/dist/project-sessions.js +4 -2
- package/dist/resource-loader.js +2 -14
- package/dist/resources/.managed-resources-content-hash +1 -1
- package/dist/resources/GSD-WORKFLOW.md +5 -4
- package/dist/resources/extensions/ask-user-questions.js +78 -23
- package/dist/resources/extensions/async-jobs/async-bash-tool.js +30 -64
- package/dist/resources/extensions/async-jobs/await-tool.js +80 -12
- package/dist/resources/extensions/async-jobs/index.js +65 -0
- package/dist/resources/extensions/async-jobs/job-manager.js +12 -1
- package/dist/resources/extensions/bg-shell/bg-shell-command.js +6 -6
- package/dist/resources/extensions/bg-shell/bg-shell-tool.js +10 -7
- package/dist/resources/extensions/bg-shell/overlay.js +9 -6
- package/dist/resources/extensions/bg-shell/process-manager.js +54 -25
- package/dist/resources/extensions/bg-shell/readiness-detector.js +11 -0
- package/dist/resources/extensions/bg-shell/utilities.js +5 -2
- package/dist/resources/extensions/browser-tools/engine/managed-gsd-browser.js +209 -88
- package/dist/resources/extensions/browser-tools/engine/selection.js +73 -5
- package/dist/resources/extensions/browser-tools/index.js +69 -12
- package/dist/resources/extensions/claude-code-cli/models.js +9 -0
- package/dist/resources/extensions/claude-code-cli/stream-adapter.js +139 -243
- package/dist/resources/extensions/claude-code-cli/turn-assembler.js +224 -0
- package/dist/resources/extensions/github-sync/templates.js +3 -3
- package/dist/resources/extensions/gsd/artifact-projection.js +14 -0
- package/dist/resources/extensions/gsd/auto/contracts.js +8 -1
- package/dist/resources/extensions/gsd/auto/custom-verify-retry-store.js +17 -2
- package/dist/resources/extensions/gsd/auto/detect-stuck.js +33 -13
- package/dist/resources/extensions/gsd/auto/dispatch-history.js +105 -0
- package/dist/resources/extensions/gsd/auto/dispatch-key.js +37 -0
- package/dist/resources/extensions/gsd/auto/loop.js +77 -56
- package/dist/resources/extensions/gsd/auto/orchestrator.js +860 -96
- package/dist/resources/extensions/gsd/auto/phases.js +81 -8
- package/dist/resources/extensions/gsd/auto/run-unit.js +2 -1
- package/dist/resources/extensions/gsd/auto/session.js +6 -0
- package/dist/resources/extensions/gsd/auto-dashboard.js +16 -4
- package/dist/resources/extensions/gsd/auto-direct-dispatch.js +11 -34
- package/dist/resources/extensions/gsd/auto-dispatch.js +56 -63
- package/dist/resources/extensions/gsd/auto-model-selection.js +44 -13
- package/dist/resources/extensions/gsd/auto-post-unit.js +47 -17
- package/dist/resources/extensions/gsd/auto-prompts.js +271 -27
- package/dist/resources/extensions/gsd/auto-recovery.js +48 -49
- package/dist/resources/extensions/gsd/auto-runtime-state.js +17 -0
- package/dist/resources/extensions/gsd/auto-start.js +36 -49
- package/dist/resources/extensions/gsd/auto-timers.js +16 -2
- package/dist/resources/extensions/gsd/auto-tool-tracking.js +55 -0
- package/dist/resources/extensions/gsd/auto-unit-closeout.js +45 -21
- package/dist/resources/extensions/gsd/auto-unit-tool-scope.js +33 -37
- package/dist/resources/extensions/gsd/auto-verification.js +30 -37
- package/dist/resources/extensions/gsd/auto-worktree-repair.js +10 -2
- package/dist/resources/extensions/gsd/auto-worktree.js +67 -375
- package/dist/resources/extensions/gsd/auto.js +112 -486
- package/dist/resources/extensions/gsd/blocked-models.js +28 -0
- package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +29 -8
- package/dist/resources/extensions/gsd/bootstrap/db-tools.js +28 -37
- package/dist/resources/extensions/gsd/bootstrap/dynamic-tools.js +43 -49
- package/dist/resources/extensions/gsd/bootstrap/exec-tools.js +2 -2
- package/dist/resources/extensions/gsd/bootstrap/query-tools.js +2 -2
- package/dist/resources/extensions/gsd/bootstrap/register-extension.js +19 -0
- package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +319 -161
- package/dist/resources/extensions/gsd/bootstrap/write-gate.js +365 -58
- package/dist/resources/extensions/gsd/branch-patterns.js +2 -0
- package/dist/resources/extensions/gsd/browser-daemon-auto-prep.js +83 -0
- package/dist/resources/extensions/gsd/browser-evidence.js +8 -2
- package/dist/resources/extensions/gsd/captures.js +5 -15
- package/dist/resources/extensions/gsd/closeout-consistency-gate.js +21 -4
- package/dist/resources/extensions/gsd/closeout-recovery.js +3 -2
- package/dist/resources/extensions/gsd/closeout-wizard.js +92 -0
- package/dist/resources/extensions/gsd/codebase-generator.js +8 -4
- package/dist/resources/extensions/gsd/commands/catalog.js +6 -62
- package/dist/resources/extensions/gsd/commands/context.js +16 -2
- package/dist/resources/extensions/gsd/commands/handlers/auto.js +3 -0
- package/dist/resources/extensions/gsd/commands-handlers.js +66 -3
- package/dist/resources/extensions/gsd/commands-inspect.js +4 -8
- package/dist/resources/extensions/gsd/commands-maintenance.js +61 -41
- package/dist/resources/extensions/gsd/commands-ship.js +2 -2
- package/dist/resources/extensions/gsd/commands-verdict.js +12 -2
- package/dist/resources/extensions/gsd/consent-question.js +353 -0
- package/dist/resources/extensions/gsd/consent-verdict.js +63 -0
- package/dist/resources/extensions/gsd/constants.js +0 -2
- package/dist/resources/extensions/gsd/crash-recovery.js +12 -15
- package/dist/resources/extensions/gsd/db/engine.js +755 -0
- package/dist/resources/extensions/gsd/db/queries.js +398 -0
- package/dist/resources/extensions/gsd/db/sql-constants.js +11 -0
- package/dist/resources/extensions/gsd/db/writers/cascades.js +194 -0
- package/dist/resources/extensions/gsd/db/writers/import-restore.js +182 -0
- package/dist/resources/extensions/gsd/db/writers/memory.js +149 -0
- package/dist/resources/extensions/gsd/db/writers/reconcile.js +458 -0
- package/dist/resources/extensions/gsd/db/writers/status.js +70 -0
- package/dist/resources/extensions/gsd/db-workspace.js +103 -0
- package/dist/resources/extensions/gsd/debug-logger.js +10 -0
- package/dist/resources/extensions/gsd/delegation-policy.js +2 -10
- package/dist/resources/extensions/gsd/discussion-handoff.js +218 -0
- package/dist/resources/extensions/gsd/dispatch-guard.js +10 -35
- package/dist/resources/extensions/gsd/docs/preferences-reference.md +9 -0
- package/dist/resources/extensions/gsd/doctor-engine-checks.js +5 -5
- package/dist/resources/extensions/gsd/doctor-environment.js +5 -11
- package/dist/resources/extensions/gsd/doctor-format.js +9 -6
- package/dist/resources/extensions/gsd/doctor-git-checks.js +6 -21
- package/dist/resources/extensions/gsd/doctor-proactive.js +7 -2
- package/dist/resources/extensions/gsd/doctor-runtime-checks.js +21 -16
- package/dist/resources/extensions/gsd/doctor.js +16 -9
- package/dist/resources/extensions/gsd/engine-hook-contract.js +70 -0
- package/dist/resources/extensions/gsd/error-classifier.js +10 -1
- package/dist/resources/extensions/gsd/exec-sandbox.js +30 -10
- package/dist/resources/extensions/gsd/files.js +33 -19
- package/dist/resources/extensions/gsd/git-conflict-state.js +16 -1
- package/dist/resources/extensions/gsd/git-service.js +1 -0
- package/dist/resources/extensions/gsd/gitignore.js +3 -0
- package/dist/resources/extensions/gsd/gsd-command-home.js +22 -12
- package/dist/resources/extensions/gsd/gsd-db.js +184 -2048
- package/dist/resources/extensions/gsd/guidance.js +158 -0
- package/dist/resources/extensions/gsd/guided-flow.js +91 -476
- package/dist/resources/extensions/gsd/guided-unit-completion.js +225 -0
- package/dist/resources/extensions/gsd/markdown-renderer.js +43 -33
- package/dist/resources/extensions/gsd/mcp-filter.js +10 -20
- package/dist/resources/extensions/gsd/mcp-tool-name.js +18 -0
- package/dist/resources/extensions/gsd/md-importer.js +4 -3
- package/dist/resources/extensions/gsd/memory-consolidation-scanner.js +1 -1
- package/dist/resources/extensions/gsd/migrate/safety.js +22 -11
- package/dist/resources/extensions/gsd/migration-auto-check.js +27 -5
- package/dist/resources/extensions/gsd/milestone-closeout-proof.js +72 -0
- package/dist/resources/extensions/gsd/milestone-closeout.js +97 -28
- package/dist/resources/extensions/gsd/milestone-merge-transaction.js +10 -0
- package/dist/resources/extensions/gsd/milestone-planning-persistence.js +156 -0
- package/dist/resources/extensions/gsd/milestone-readiness.js +77 -0
- package/dist/resources/extensions/gsd/milestone-reopen-events.js +3 -5
- package/dist/resources/extensions/gsd/milestone-settlement.js +50 -0
- package/dist/resources/extensions/gsd/milestone-validation-evidence.js +73 -0
- package/dist/resources/extensions/gsd/milestone-validation-verdict.js +57 -0
- package/dist/resources/extensions/gsd/model-cost-table.js +1 -0
- package/dist/resources/extensions/gsd/model-router.js +3 -0
- package/dist/resources/extensions/gsd/native-git-bridge.js +45 -0
- package/dist/resources/extensions/gsd/notification-store.js +11 -4
- package/dist/resources/extensions/gsd/parallel-eligibility.js +3 -6
- package/dist/resources/extensions/gsd/parallel-merge.js +14 -11
- package/dist/resources/extensions/gsd/parallel-monitor-overlay.js +11 -7
- package/dist/resources/extensions/gsd/parallel-orchestrator.js +3 -2
- package/dist/resources/extensions/gsd/parsers-legacy.js +16 -4
- package/dist/resources/extensions/gsd/paths.js +37 -24
- package/dist/resources/extensions/gsd/pre-execution-checks.js +91 -3
- package/dist/resources/extensions/gsd/preferences-diagnostics.js +67 -0
- package/dist/resources/extensions/gsd/preferences-models.js +14 -48
- package/dist/resources/extensions/gsd/preferences.js +161 -29
- package/dist/resources/extensions/gsd/projection-flush.js +7 -0
- package/dist/resources/extensions/gsd/prompts/complete-slice.md +4 -3
- package/dist/resources/extensions/gsd/prompts/discuss.md +6 -7
- package/dist/resources/extensions/gsd/prompts/execute-task.md +3 -1
- package/dist/resources/extensions/gsd/prompts/guided-discuss-milestone.md +5 -7
- package/dist/resources/extensions/gsd/prompts/guided-discuss-project.md +6 -6
- package/dist/resources/extensions/gsd/prompts/guided-discuss-requirements.md +1 -2
- package/dist/resources/extensions/gsd/prompts/guided-discuss-slice.md +5 -6
- package/dist/resources/extensions/gsd/prompts/plan-milestone.md +3 -1
- package/dist/resources/extensions/gsd/prompts/plan-slice.md +4 -3
- package/dist/resources/extensions/gsd/prompts/quick-task.md +1 -1
- package/dist/resources/extensions/gsd/prompts/reassess-roadmap.md +1 -1
- package/dist/resources/extensions/gsd/prompts/refine-slice.md +3 -2
- package/dist/resources/extensions/gsd/prompts/replan-slice.md +2 -2
- package/dist/resources/extensions/gsd/prompts/research-milestone.md +3 -3
- package/dist/resources/extensions/gsd/prompts/research-slice.md +1 -1
- package/dist/resources/extensions/gsd/prompts/rewrite-docs.md +1 -1
- package/dist/resources/extensions/gsd/prompts/run-uat.md +7 -5
- package/dist/resources/extensions/gsd/prompts/system.md +6 -3
- package/dist/resources/extensions/gsd/prompts/triage-captures.md +1 -1
- package/dist/resources/extensions/gsd/prompts/validate-milestone.md +6 -4
- package/dist/resources/extensions/gsd/provider-error-guidance.js +1 -5
- package/dist/resources/extensions/gsd/provider-payload-policy.js +83 -0
- package/dist/resources/extensions/gsd/provider-switch-observer.js +1 -1
- package/dist/resources/extensions/gsd/publication.js +87 -0
- package/dist/resources/extensions/gsd/pull-request-process.js +13 -0
- package/dist/resources/extensions/gsd/quality-gate-closure.js +109 -0
- package/dist/resources/extensions/gsd/question-transport.js +86 -0
- package/dist/resources/extensions/gsd/reactive-graph.js +8 -1
- package/dist/resources/extensions/gsd/recovery-classification.js +41 -87
- package/dist/resources/extensions/gsd/roadmap-slices.js +33 -5
- package/dist/resources/extensions/gsd/safety/destructive-confirmation.js +108 -0
- package/dist/resources/extensions/gsd/safety/evidence-collector.js +37 -4
- package/dist/resources/extensions/gsd/safety/evidence-cross-ref.js +7 -2
- package/dist/resources/extensions/gsd/safety/file-change-validator.js +10 -0
- package/dist/resources/extensions/gsd/schemas/parsers.js +6 -1
- package/dist/resources/extensions/gsd/session-lock.js +1 -1
- package/dist/resources/extensions/gsd/slice-parallel-orchestrator.js +3 -2
- package/dist/resources/extensions/gsd/state-reconciliation/drift/artifact-db.js +21 -1
- package/dist/resources/extensions/gsd/state-transition-matrix.js +38 -0
- package/dist/resources/extensions/gsd/state.js +19 -25
- package/dist/resources/extensions/gsd/status-guards.js +56 -8
- package/dist/resources/extensions/gsd/stop-notice.js +57 -0
- package/dist/resources/extensions/gsd/templates/plan.md +7 -0
- package/dist/resources/extensions/gsd/templates/project.md +1 -0
- package/dist/resources/extensions/gsd/templates/roadmap.md +1 -1
- package/dist/resources/extensions/gsd/templates/uat.md +5 -1
- package/dist/resources/extensions/gsd/tool-contract.js +66 -11
- package/dist/resources/extensions/gsd/tool-presentation-plan.js +17 -36
- package/dist/resources/extensions/gsd/tool-surface-readiness.js +56 -0
- package/dist/resources/extensions/gsd/tool-surface-snapshot.js +17 -0
- package/dist/resources/extensions/gsd/tools/complete-milestone.js +3 -2
- package/dist/resources/extensions/gsd/tools/complete-slice.js +46 -55
- package/dist/resources/extensions/gsd/tools/complete-task.js +3 -2
- package/dist/resources/extensions/gsd/tools/exec-tool.js +10 -8
- package/dist/resources/extensions/gsd/tools/plan-milestone.js +15 -143
- package/dist/resources/extensions/gsd/tools/plan-slice.js +14 -8
- package/dist/resources/extensions/gsd/tools/plan-task.js +2 -2
- package/dist/resources/extensions/gsd/tools/reassess-roadmap.js +41 -2
- package/dist/resources/extensions/gsd/tools/reopen-milestone.js +13 -31
- package/dist/resources/extensions/gsd/tools/reopen-slice.js +16 -35
- package/dist/resources/extensions/gsd/tools/reopen-task.js +2 -2
- package/dist/resources/extensions/gsd/tools/replan-slice.js +2 -2
- package/dist/resources/extensions/gsd/tools/skip-slice.js +18 -36
- package/dist/resources/extensions/gsd/tools/validate-milestone.js +15 -78
- package/dist/resources/extensions/gsd/tools/workflow-tool-executors.js +236 -22
- package/dist/resources/extensions/gsd/uat-policy.js +57 -25
- package/dist/resources/extensions/gsd/uat-run.js +9 -14
- package/dist/resources/extensions/gsd/undo.js +8 -7
- package/dist/resources/extensions/gsd/unit-closeout.js +138 -0
- package/dist/resources/extensions/gsd/unit-context-composer.js +114 -21
- package/dist/resources/extensions/gsd/unit-context-manifest.js +4 -27
- package/dist/resources/extensions/gsd/unit-registry.js +337 -0
- package/dist/resources/extensions/gsd/unit-runtime.js +3 -2
- package/dist/resources/extensions/gsd/unit-tool-contracts.js +9 -181
- package/dist/resources/extensions/gsd/validation-block-guard.js +2 -0
- package/dist/resources/extensions/gsd/verdict-parser.js +1 -1
- package/dist/resources/extensions/gsd/verification-verdict.js +2 -1
- package/dist/resources/extensions/gsd/web-app-uat.js +117 -0
- package/dist/resources/extensions/gsd/workflow-event-ledger.js +91 -0
- package/dist/resources/extensions/gsd/workflow-event-vocabulary.js +46 -0
- package/dist/resources/extensions/gsd/workflow-events.js +6 -18
- package/dist/resources/extensions/gsd/workflow-mcp.js +15 -102
- package/dist/resources/extensions/gsd/workflow-reconcile.js +25 -59
- package/dist/resources/extensions/gsd/workflow-tool-surface.js +46 -0
- package/dist/resources/extensions/gsd/workspace-git-guard.js +2 -0
- package/dist/resources/extensions/gsd/worktree-git-recovery.js +293 -0
- package/dist/resources/extensions/gsd/worktree-lifecycle.js +12 -3
- package/dist/resources/extensions/gsd/worktree-manager.js +45 -28
- package/dist/resources/extensions/gsd/worktree-placement.js +59 -0
- package/dist/resources/extensions/gsd/worktree-reentry.js +12 -8
- package/dist/resources/extensions/gsd/worktree-root.js +28 -6
- package/dist/resources/extensions/gsd/worktree-safety.js +8 -5
- package/dist/resources/extensions/gsd/worktree-session-state.js +12 -11
- package/dist/resources/extensions/gsd/worktree-state-projection.js +33 -4
- package/dist/resources/extensions/gsd/worktree-telemetry.js +12 -0
- package/dist/resources/extensions/search-the-web/native-search.js +5 -3
- package/dist/resources/extensions/shared/browser-contract.js +59 -0
- package/dist/resources/extensions/shared/gsd-browser-cli.js +116 -6
- package/dist/resources/extensions/shared/interview-ui.js +2 -2
- package/dist/resources/shared/claude-runtime-floor.js +182 -0
- package/dist/resources/shared/gsd-browser-path-sync.js +214 -0
- package/dist/resources/shared/package-manager-detection.js +1 -1
- package/dist/resources/shared/package.json +3 -0
- package/dist/resources/skills/create-skill/references/executable-code.md +1 -1
- package/dist/resources/skills/create-skill/workflows/add-reference.md +8 -3
- package/dist/resources/skills/create-skill/workflows/add-script.md +4 -2
- package/dist/resources/skills/create-skill/workflows/add-template.md +3 -1
- package/dist/resources/skills/create-skill/workflows/add-workflow.md +8 -3
- package/dist/resources/skills/create-skill/workflows/upgrade-to-router.md +10 -5
- package/dist/resources/skills/create-skill/workflows/verify-skill.md +9 -4
- package/dist/resources/skills/gsd-browser/SKILL.md +1 -1
- package/dist/resources/skills/spike-wrap-up/SKILL.md +9 -9
- package/dist/tsconfig.extensions.tsbuildinfo +1 -0
- package/dist/update-check.d.ts +2 -0
- package/dist/update-check.js +24 -1
- package/dist/update-cmd.js +40 -3
- package/dist/web/standalone/.next/BUILD_ID +1 -1
- package/dist/web/standalone/.next/app-path-routes-manifest.json +5 -5
- package/dist/web/standalone/.next/build-manifest.json +3 -3
- package/dist/web/standalone/.next/prerender-manifest.json +3 -3
- package/dist/web/standalone/.next/react-loadable-manifest.json +8 -8
- package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/api/boot/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/captures/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/cleanup/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/doctor/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/export-data/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/files/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/forensics/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/git/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/history/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/hooks/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/inspect/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/knowledge/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/live-state/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/mcp-connections/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/notifications/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/onboarding/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/projects/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/recovery/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/session/browser/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/session/command/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/session/events/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/session/manage/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/settings-data/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/shutdown/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/skill-health/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/steer/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/switch-root/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/undo/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/update/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/visualizer/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/index.html +1 -1
- package/dist/web/standalone/.next/server/app/index.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app-paths-manifest.json +5 -5
- package/dist/web/standalone/.next/server/chunks/5124.js +1 -0
- package/dist/web/standalone/.next/server/chunks/5942.js +2 -0
- package/dist/web/standalone/.next/server/chunks/8357.js +3 -3
- package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
- package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
- package/dist/web/standalone/.next/server/pages/404.html +1 -1
- package/dist/web/standalone/.next/server/pages/500.html +1 -1
- package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
- package/dist/web/standalone/.next/static/chunks/2659.b7b129ee6a769448.js +1 -0
- package/dist/web/standalone/.next/static/chunks/2772.bfa657f49f955239.js +1 -0
- package/dist/web/standalone/.next/static/chunks/{3616.4113d484a994e411.js → 3616.3c60753b8ffcbd2e.js} +1 -1
- package/dist/web/standalone/.next/static/chunks/4283.e4873b058df143a1.js +2 -0
- package/dist/web/standalone/.next/static/chunks/5826.a46ecdd1cfe8dabc.js +1 -0
- package/dist/web/standalone/.next/static/chunks/796.e0bdc932325d7e03.js +10 -0
- package/dist/web/standalone/.next/static/chunks/8785.2e5a118797fb2dd2.js +1 -0
- package/dist/web/standalone/.next/static/chunks/{webpack-dda80a1ef5587410.js → webpack-f0285ce91d4ec9ef.js} +1 -1
- package/dist/web/standalone/node_modules/@gsd/native/package.json +1 -1
- package/dist/web/standalone/node_modules/node-pty/build/Makefile +1 -1
- package/dist/web/standalone/node_modules/postcss/lib/container.js +26 -18
- package/dist/web/standalone/node_modules/postcss/lib/css-syntax-error.js +47 -14
- package/dist/web/standalone/node_modules/postcss/lib/declaration.js +4 -4
- package/dist/web/standalone/node_modules/postcss/lib/fromJSON.js +3 -3
- package/dist/web/standalone/node_modules/postcss/lib/input.js +54 -29
- package/dist/web/standalone/node_modules/postcss/lib/lazy-result.js +47 -37
- package/dist/web/standalone/node_modules/postcss/lib/map-generator.js +26 -9
- package/dist/web/standalone/node_modules/postcss/lib/no-work-result.js +57 -55
- package/dist/web/standalone/node_modules/postcss/lib/node.js +99 -31
- package/dist/web/standalone/node_modules/postcss/lib/parse.js +1 -1
- package/dist/web/standalone/node_modules/postcss/lib/parser.js +10 -9
- package/dist/web/standalone/node_modules/postcss/lib/postcss.js +12 -12
- package/dist/web/standalone/node_modules/postcss/lib/previous-map.js +30 -11
- package/dist/web/standalone/node_modules/postcss/lib/processor.js +7 -7
- package/dist/web/standalone/node_modules/postcss/lib/result.js +5 -5
- package/dist/web/standalone/node_modules/postcss/lib/rule.js +6 -6
- package/dist/web/standalone/node_modules/postcss/lib/stringifier.js +69 -28
- package/dist/web/standalone/node_modules/postcss/lib/tokenize.js +6 -2
- package/dist/web/standalone/node_modules/postcss/package.json +48 -48
- package/dist/web/standalone/package.json +1 -1
- package/dist/web-mode.d.ts +2 -0
- package/dist/web-mode.js +20 -8
- package/dist/worktree-cli.js +3 -6
- package/dist/worktree-status-banner.js +7 -11
- package/package.json +17 -11
- package/packages/cloud-mcp-gateway/package.json +2 -2
- package/packages/contracts/dist/rpc.d.ts +1 -0
- package/packages/contracts/dist/rpc.d.ts.map +1 -1
- package/packages/contracts/dist/rpc.js.map +1 -1
- package/packages/contracts/dist/workflow.d.ts +4 -0
- package/packages/contracts/dist/workflow.d.ts.map +1 -1
- package/packages/contracts/dist/workflow.js.map +1 -1
- package/packages/contracts/package.json +1 -1
- package/packages/daemon/package.json +4 -4
- package/packages/gsd-agent-core/dist/session/agent-session-extensions.d.ts +2 -0
- package/packages/gsd-agent-core/dist/session/agent-session-extensions.d.ts.map +1 -1
- package/packages/gsd-agent-core/dist/session/agent-session-extensions.js +14 -0
- package/packages/gsd-agent-core/dist/session/agent-session-extensions.js.map +1 -1
- package/packages/gsd-agent-core/package.json +5 -5
- package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.d.ts +5 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.js +8 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/transcript-design.js +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/transcript-design.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.js +113 -40
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/input-controller.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/input-controller.js +8 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/input-controller.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-chat-render.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-chat-render.js +11 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-chat-render.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-extension-widgets.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-extension-widgets.js +6 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-extension-widgets.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-auth.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-auth.js +4 -4
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-auth.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/rpc/rpc-mode.js +3 -1
- package/packages/gsd-agent-modes/dist/modes/rpc/rpc-mode.js.map +1 -1
- package/packages/gsd-agent-modes/package.json +7 -7
- package/packages/mcp-server/dist/cli.js +9 -1
- package/packages/mcp-server/dist/cli.js.map +1 -1
- package/packages/mcp-server/dist/moonshot-tool-schema.d.ts +29 -0
- package/packages/mcp-server/dist/moonshot-tool-schema.d.ts.map +1 -0
- package/packages/mcp-server/dist/moonshot-tool-schema.js +50 -0
- package/packages/mcp-server/dist/moonshot-tool-schema.js.map +1 -0
- package/packages/mcp-server/dist/server.d.ts +10 -0
- package/packages/mcp-server/dist/server.d.ts.map +1 -1
- package/packages/mcp-server/dist/server.js +12 -0
- package/packages/mcp-server/dist/server.js.map +1 -1
- package/packages/mcp-server/dist/workflow-tools.d.ts +49 -0
- package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
- package/packages/mcp-server/dist/workflow-tools.js +147 -60
- package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
- package/packages/mcp-server/package.json +5 -4
- package/packages/native/package.json +1 -1
- package/packages/pi-agent-core/dist/harness/env/nodejs.d.ts +1 -0
- package/packages/pi-agent-core/dist/harness/env/nodejs.d.ts.map +1 -1
- package/packages/pi-agent-core/dist/harness/env/nodejs.js +34 -3
- package/packages/pi-agent-core/dist/harness/env/nodejs.js.map +1 -1
- package/packages/pi-agent-core/dist/index.d.ts +1 -0
- package/packages/pi-agent-core/dist/index.d.ts.map +1 -1
- package/packages/pi-agent-core/dist/index.js +3 -0
- package/packages/pi-agent-core/dist/index.js.map +1 -1
- package/packages/pi-agent-core/package.json +1 -1
- package/packages/pi-ai/README.md +1 -0
- package/packages/pi-ai/dist/index.d.ts +2 -0
- package/packages/pi-ai/dist/index.d.ts.map +1 -1
- package/packages/pi-ai/dist/index.js +2 -0
- package/packages/pi-ai/dist/index.js.map +1 -1
- package/packages/pi-ai/dist/models.generated.d.ts +183 -110
- package/packages/pi-ai/dist/models.generated.d.ts.map +1 -1
- package/packages/pi-ai/dist/models.generated.js +205 -158
- package/packages/pi-ai/dist/models.generated.js.map +1 -1
- package/packages/pi-ai/dist/providers/anthropic.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/anthropic.js +12 -7
- package/packages/pi-ai/dist/providers/anthropic.js.map +1 -1
- package/packages/pi-ai/dist/providers/google-shared.d.ts +5 -0
- package/packages/pi-ai/dist/providers/google-shared.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/google-shared.js +12 -3
- package/packages/pi-ai/dist/providers/google-shared.js.map +1 -1
- package/packages/pi-ai/dist/providers/openai-completions.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/openai-completions.js +7 -3
- package/packages/pi-ai/dist/providers/openai-completions.js.map +1 -1
- package/packages/pi-ai/dist/utils/moonshot-tool-schema.d.ts +9 -0
- package/packages/pi-ai/dist/utils/moonshot-tool-schema.d.ts.map +1 -0
- package/packages/pi-ai/dist/utils/moonshot-tool-schema.js +34 -0
- package/packages/pi-ai/dist/utils/moonshot-tool-schema.js.map +1 -0
- package/packages/pi-ai/dist/utils/oauth/github-copilot.d.ts.map +1 -1
- package/packages/pi-ai/dist/utils/oauth/github-copilot.js +6 -2
- package/packages/pi-ai/dist/utils/oauth/github-copilot.js.map +1 -1
- package/packages/pi-ai/package.json +3 -2
- package/packages/pi-coding-agent/dist/core/auth-storage.d.ts +2 -2
- package/packages/pi-coding-agent/dist/core/auth-storage.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/auth-storage.js +29 -15
- package/packages/pi-coding-agent/dist/core/auth-storage.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/capability-patches.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/capability-patches.js +3 -1
- package/packages/pi-coding-agent/dist/core/capability-patches.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/provider-readiness.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/provider-readiness.js +13 -6
- package/packages/pi-coding-agent/dist/core/provider-readiness.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/bash.d.ts +11 -0
- package/packages/pi-coding-agent/dist/core/tools/bash.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/bash.js +53 -11
- package/packages/pi-coding-agent/dist/core/tools/bash.js.map +1 -1
- package/packages/pi-coding-agent/dist/index.d.ts +1 -1
- package/packages/pi-coding-agent/dist/index.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/index.js +1 -1
- package/packages/pi-coding-agent/dist/index.js.map +1 -1
- package/packages/pi-coding-agent/dist/utils/shell.d.ts +28 -2
- package/packages/pi-coding-agent/dist/utils/shell.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/utils/shell.js +56 -10
- package/packages/pi-coding-agent/dist/utils/shell.js.map +1 -1
- package/packages/pi-coding-agent/package.json +7 -7
- package/packages/pi-tui/dist/components/input.js +1 -1
- package/packages/pi-tui/dist/components/input.js.map +1 -1
- package/packages/pi-tui/dist/keys.d.ts.map +1 -1
- package/packages/pi-tui/dist/keys.js +39 -30
- package/packages/pi-tui/dist/keys.js.map +1 -1
- package/packages/pi-tui/dist/stdin-buffer.d.ts.map +1 -1
- package/packages/pi-tui/dist/stdin-buffer.js +22 -0
- package/packages/pi-tui/dist/stdin-buffer.js.map +1 -1
- package/packages/pi-tui/dist/tui.d.ts.map +1 -1
- package/packages/pi-tui/dist/tui.js +9 -0
- package/packages/pi-tui/dist/tui.js.map +1 -1
- package/packages/pi-tui/package.json +2 -2
- package/packages/rpc-client/package.json +2 -2
- package/pkg/package.json +1 -1
- package/scripts/install/deps.js +10 -0
- package/scripts/link-workspace-packages.cjs +7 -40
- package/src/resources/GSD-WORKFLOW.md +5 -4
- package/src/resources/extensions/ask-user-questions.ts +87 -24
- package/src/resources/extensions/async-jobs/async-bash-cancel.test.ts +360 -0
- package/src/resources/extensions/async-jobs/async-bash-tool.ts +33 -56
- package/src/resources/extensions/async-jobs/await-tool.test.ts +139 -0
- package/src/resources/extensions/async-jobs/await-tool.ts +82 -12
- package/src/resources/extensions/async-jobs/index.ts +79 -0
- package/src/resources/extensions/async-jobs/job-manager.ts +21 -1
- package/src/resources/extensions/bg-shell/bg-shell-command.ts +6 -6
- package/src/resources/extensions/bg-shell/bg-shell-tool.ts +10 -6
- package/src/resources/extensions/bg-shell/overlay.ts +9 -5
- package/src/resources/extensions/bg-shell/process-manager.ts +50 -25
- package/src/resources/extensions/bg-shell/readiness-detector.ts +12 -0
- package/src/resources/extensions/bg-shell/tests/lifecycle-and-utilities.test.ts +48 -1
- package/src/resources/extensions/bg-shell/utilities.ts +5 -2
- package/src/resources/extensions/browser-tools/engine/managed-gsd-browser.ts +265 -98
- package/src/resources/extensions/browser-tools/engine/selection.ts +90 -4
- package/src/resources/extensions/browser-tools/index.ts +71 -13
- package/src/resources/extensions/browser-tools/tests/browser-engine-selection.test.mjs +83 -13
- package/src/resources/extensions/browser-tools/tests/gsd-browser-launch-config.test.mjs +40 -1
- package/src/resources/extensions/browser-tools/tests/managed-gsd-browser-tools.test.mjs +136 -0
- package/src/resources/extensions/claude-code-cli/models.ts +9 -0
- package/src/resources/extensions/claude-code-cli/stream-adapter.ts +166 -293
- package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +270 -2
- package/src/resources/extensions/claude-code-cli/turn-assembler.ts +287 -0
- package/src/resources/extensions/github-sync/templates.ts +3 -3
- package/src/resources/extensions/github-sync/tests/templates.test.ts +2 -2
- package/src/resources/extensions/gsd/artifact-projection.ts +31 -0
- package/src/resources/extensions/gsd/auto/contracts.ts +40 -121
- package/src/resources/extensions/gsd/auto/custom-verify-retry-store.ts +21 -3
- package/src/resources/extensions/gsd/auto/detect-stuck.ts +32 -9
- package/src/resources/extensions/gsd/auto/dispatch-history.ts +152 -0
- package/src/resources/extensions/gsd/auto/dispatch-key.ts +39 -0
- package/src/resources/extensions/gsd/auto/loop-deps.ts +3 -1
- package/src/resources/extensions/gsd/auto/loop.ts +86 -61
- package/src/resources/extensions/gsd/auto/orchestrator.ts +1023 -98
- package/src/resources/extensions/gsd/auto/phases.ts +108 -28
- package/src/resources/extensions/gsd/auto/run-unit.ts +2 -1
- package/src/resources/extensions/gsd/auto/session.ts +7 -0
- package/src/resources/extensions/gsd/auto-dashboard.ts +18 -4
- package/src/resources/extensions/gsd/auto-direct-dispatch.ts +18 -48
- package/src/resources/extensions/gsd/auto-dispatch.ts +68 -68
- package/src/resources/extensions/gsd/auto-model-selection.ts +49 -12
- package/src/resources/extensions/gsd/auto-post-unit.ts +56 -16
- package/src/resources/extensions/gsd/auto-prompts.ts +338 -44
- package/src/resources/extensions/gsd/auto-recovery.ts +50 -50
- package/src/resources/extensions/gsd/auto-runtime-state.ts +30 -0
- package/src/resources/extensions/gsd/auto-start.ts +41 -49
- package/src/resources/extensions/gsd/auto-timers.ts +16 -2
- package/src/resources/extensions/gsd/auto-tool-tracking.ts +59 -0
- package/src/resources/extensions/gsd/auto-unit-closeout.ts +83 -28
- package/src/resources/extensions/gsd/auto-unit-tool-scope.ts +43 -38
- package/src/resources/extensions/gsd/auto-verification.ts +33 -36
- package/src/resources/extensions/gsd/auto-worktree-repair.ts +13 -2
- package/src/resources/extensions/gsd/auto-worktree.ts +83 -391
- package/src/resources/extensions/gsd/auto.ts +151 -524
- package/src/resources/extensions/gsd/blocked-models.ts +49 -0
- package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +37 -10
- package/src/resources/extensions/gsd/bootstrap/db-tools.ts +29 -37
- package/src/resources/extensions/gsd/bootstrap/dynamic-tools.ts +43 -49
- package/src/resources/extensions/gsd/bootstrap/exec-tools.ts +2 -2
- package/src/resources/extensions/gsd/bootstrap/query-tools.ts +2 -2
- package/src/resources/extensions/gsd/bootstrap/register-extension.ts +24 -0
- package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +379 -177
- package/src/resources/extensions/gsd/bootstrap/write-gate.ts +452 -58
- package/src/resources/extensions/gsd/branch-patterns.ts +3 -0
- package/src/resources/extensions/gsd/browser-daemon-auto-prep.ts +108 -0
- package/src/resources/extensions/gsd/browser-evidence.ts +18 -2
- package/src/resources/extensions/gsd/captures.ts +5 -16
- package/src/resources/extensions/gsd/closeout-consistency-gate.ts +27 -5
- package/src/resources/extensions/gsd/closeout-recovery.ts +2 -1
- package/src/resources/extensions/gsd/closeout-wizard.ts +102 -0
- package/src/resources/extensions/gsd/codebase-generator.ts +9 -5
- package/src/resources/extensions/gsd/commands/catalog.ts +6 -68
- package/src/resources/extensions/gsd/commands/context.ts +16 -2
- package/src/resources/extensions/gsd/commands/handlers/auto.ts +3 -0
- package/src/resources/extensions/gsd/commands-handlers.ts +64 -3
- package/src/resources/extensions/gsd/commands-inspect.ts +7 -8
- package/src/resources/extensions/gsd/commands-maintenance.ts +74 -40
- package/src/resources/extensions/gsd/commands-ship.ts +2 -2
- package/src/resources/extensions/gsd/commands-verdict.ts +19 -2
- package/src/resources/extensions/gsd/consent-question.ts +431 -0
- package/src/resources/extensions/gsd/consent-verdict.ts +86 -0
- package/src/resources/extensions/gsd/constants.ts +0 -3
- package/src/resources/extensions/gsd/crash-recovery.ts +13 -11
- package/src/resources/extensions/gsd/db/engine.ts +809 -0
- package/src/resources/extensions/gsd/db/queries.ts +490 -0
- package/src/resources/extensions/gsd/db/sql-constants.ts +12 -0
- package/src/resources/extensions/gsd/db/writers/cascades.ts +237 -0
- package/src/resources/extensions/gsd/db/writers/import-restore.ts +310 -0
- package/src/resources/extensions/gsd/db/writers/memory.ts +220 -0
- package/src/resources/extensions/gsd/db/writers/reconcile.ts +500 -0
- package/src/resources/extensions/gsd/db/writers/status.ts +88 -0
- package/src/resources/extensions/gsd/db-workspace.ts +170 -0
- package/src/resources/extensions/gsd/debug-logger.ts +11 -0
- package/src/resources/extensions/gsd/delegation-policy.ts +3 -11
- package/src/resources/extensions/gsd/discussion-handoff.ts +276 -0
- package/src/resources/extensions/gsd/dispatch-guard.ts +8 -31
- package/src/resources/extensions/gsd/docs/preferences-reference.md +9 -0
- package/src/resources/extensions/gsd/doctor-engine-checks.ts +5 -4
- package/src/resources/extensions/gsd/doctor-environment.ts +5 -13
- package/src/resources/extensions/gsd/doctor-format.ts +12 -7
- package/src/resources/extensions/gsd/doctor-git-checks.ts +5 -22
- package/src/resources/extensions/gsd/doctor-proactive.ts +8 -2
- package/src/resources/extensions/gsd/doctor-runtime-checks.ts +22 -17
- package/src/resources/extensions/gsd/doctor.ts +15 -5
- package/src/resources/extensions/gsd/engine-hook-contract.ts +79 -0
- package/src/resources/extensions/gsd/error-classifier.ts +12 -1
- package/src/resources/extensions/gsd/exec-sandbox.ts +49 -9
- package/src/resources/extensions/gsd/files.ts +33 -12
- package/src/resources/extensions/gsd/git-conflict-state.ts +17 -1
- package/src/resources/extensions/gsd/git-service.ts +1 -0
- package/src/resources/extensions/gsd/gitignore.ts +3 -0
- package/src/resources/extensions/gsd/gsd-command-home.ts +13 -3
- package/src/resources/extensions/gsd/gsd-db.ts +188 -2375
- package/src/resources/extensions/gsd/guidance.ts +217 -0
- package/src/resources/extensions/gsd/guided-flow.ts +118 -589
- package/src/resources/extensions/gsd/guided-unit-completion.ts +275 -0
- package/src/resources/extensions/gsd/markdown-renderer.ts +51 -20
- package/src/resources/extensions/gsd/mcp-filter.ts +11 -24
- package/src/resources/extensions/gsd/mcp-tool-name.ts +30 -0
- package/src/resources/extensions/gsd/md-importer.ts +3 -3
- package/src/resources/extensions/gsd/memory-consolidation-scanner.ts +1 -1
- package/src/resources/extensions/gsd/migrate/safety.ts +20 -9
- package/src/resources/extensions/gsd/migration-auto-check.ts +30 -5
- package/src/resources/extensions/gsd/milestone-closeout-proof.ts +131 -0
- package/src/resources/extensions/gsd/milestone-closeout.ts +121 -28
- package/src/resources/extensions/gsd/milestone-merge-transaction.ts +47 -0
- package/src/resources/extensions/gsd/milestone-planning-persistence.ts +224 -0
- package/src/resources/extensions/gsd/milestone-readiness.ts +125 -0
- package/src/resources/extensions/gsd/milestone-reopen-events.ts +3 -6
- package/src/resources/extensions/gsd/milestone-settlement.ts +81 -0
- package/src/resources/extensions/gsd/milestone-validation-evidence.ts +95 -0
- package/src/resources/extensions/gsd/milestone-validation-verdict.ts +80 -0
- package/src/resources/extensions/gsd/model-cost-table.ts +1 -0
- package/src/resources/extensions/gsd/model-router.ts +3 -0
- package/src/resources/extensions/gsd/native-git-bridge.ts +48 -0
- package/src/resources/extensions/gsd/notification-store.ts +26 -3
- package/src/resources/extensions/gsd/parallel-eligibility.ts +4 -5
- package/src/resources/extensions/gsd/parallel-merge.ts +12 -9
- package/src/resources/extensions/gsd/parallel-monitor-overlay.ts +10 -7
- package/src/resources/extensions/gsd/parallel-orchestrator.ts +6 -2
- package/src/resources/extensions/gsd/parsers-legacy.ts +16 -4
- package/src/resources/extensions/gsd/paths.ts +42 -22
- package/src/resources/extensions/gsd/pre-execution-checks.ts +109 -3
- package/src/resources/extensions/gsd/preferences-diagnostics.ts +98 -0
- package/src/resources/extensions/gsd/preferences-models.ts +12 -47
- package/src/resources/extensions/gsd/preferences-types.ts +16 -0
- package/src/resources/extensions/gsd/preferences.ts +191 -28
- package/src/resources/extensions/gsd/projection-flush.ts +20 -0
- package/src/resources/extensions/gsd/prompts/complete-slice.md +4 -3
- package/src/resources/extensions/gsd/prompts/discuss.md +6 -7
- package/src/resources/extensions/gsd/prompts/execute-task.md +3 -1
- package/src/resources/extensions/gsd/prompts/guided-discuss-milestone.md +5 -7
- package/src/resources/extensions/gsd/prompts/guided-discuss-project.md +6 -6
- package/src/resources/extensions/gsd/prompts/guided-discuss-requirements.md +1 -2
- package/src/resources/extensions/gsd/prompts/guided-discuss-slice.md +5 -6
- package/src/resources/extensions/gsd/prompts/plan-milestone.md +3 -1
- package/src/resources/extensions/gsd/prompts/plan-slice.md +4 -3
- package/src/resources/extensions/gsd/prompts/quick-task.md +1 -1
- package/src/resources/extensions/gsd/prompts/reassess-roadmap.md +1 -1
- package/src/resources/extensions/gsd/prompts/refine-slice.md +3 -2
- package/src/resources/extensions/gsd/prompts/replan-slice.md +2 -2
- package/src/resources/extensions/gsd/prompts/research-milestone.md +3 -3
- package/src/resources/extensions/gsd/prompts/research-slice.md +1 -1
- package/src/resources/extensions/gsd/prompts/rewrite-docs.md +1 -1
- package/src/resources/extensions/gsd/prompts/run-uat.md +7 -5
- package/src/resources/extensions/gsd/prompts/system.md +6 -3
- package/src/resources/extensions/gsd/prompts/triage-captures.md +1 -1
- package/src/resources/extensions/gsd/prompts/validate-milestone.md +6 -4
- package/src/resources/extensions/gsd/provider-error-guidance.ts +4 -9
- package/src/resources/extensions/gsd/provider-payload-policy.ts +140 -0
- package/src/resources/extensions/gsd/provider-switch-observer.ts +1 -1
- package/src/resources/extensions/gsd/publication.ts +122 -0
- package/src/resources/extensions/gsd/pull-request-process.ts +41 -0
- package/src/resources/extensions/gsd/quality-gate-closure.ts +140 -0
- package/src/resources/extensions/gsd/question-transport.ts +138 -0
- package/src/resources/extensions/gsd/reactive-graph.ts +11 -1
- package/src/resources/extensions/gsd/recovery-classification.ts +47 -88
- package/src/resources/extensions/gsd/roadmap-slices.ts +36 -5
- package/src/resources/extensions/gsd/safety/destructive-confirmation.ts +134 -0
- package/src/resources/extensions/gsd/safety/evidence-collector.ts +36 -4
- package/src/resources/extensions/gsd/safety/evidence-cross-ref.ts +7 -2
- package/src/resources/extensions/gsd/safety/file-change-validator.ts +14 -0
- package/src/resources/extensions/gsd/schemas/parsers.ts +6 -1
- package/src/resources/extensions/gsd/session-lock.ts +1 -1
- package/src/resources/extensions/gsd/slice-parallel-orchestrator.ts +6 -2
- package/src/resources/extensions/gsd/state-reconciliation/drift/artifact-db.ts +31 -10
- package/src/resources/extensions/gsd/state-transition-matrix.ts +42 -0
- package/src/resources/extensions/gsd/state.ts +24 -26
- package/src/resources/extensions/gsd/status-guards.ts +59 -8
- package/src/resources/extensions/gsd/stop-notice.ts +75 -0
- package/src/resources/extensions/gsd/templates/plan.md +7 -0
- package/src/resources/extensions/gsd/templates/project.md +1 -0
- package/src/resources/extensions/gsd/templates/roadmap.md +1 -1
- package/src/resources/extensions/gsd/templates/uat.md +5 -1
- package/src/resources/extensions/gsd/tests/artifact-db-drift-memo.test.ts +66 -0
- package/src/resources/extensions/gsd/tests/ask-user-questions-render.test.ts +92 -0
- package/src/resources/extensions/gsd/tests/auto-dashboard.test.ts +29 -1
- package/src/resources/extensions/gsd/tests/auto-dispatch-baseline-harness.test.ts +53 -0
- package/src/resources/extensions/gsd/tests/auto-loop.test.ts +444 -5
- package/src/resources/extensions/gsd/tests/auto-milestone-target.test.ts +23 -0
- package/src/resources/extensions/gsd/tests/auto-model-selection-tool-poisoning.test.ts +18 -0
- package/src/resources/extensions/gsd/tests/auto-model-selection.test.ts +91 -0
- package/src/resources/extensions/gsd/tests/auto-orchestrator.test.ts +894 -858
- package/src/resources/extensions/gsd/tests/auto-paused-ui-cleanup.test.ts +41 -11
- package/src/resources/extensions/gsd/tests/auto-post-unit-evidence-crossref-4909.test.ts +46 -0
- package/src/resources/extensions/gsd/tests/auto-remote-session-lock-cleanup.test.ts +65 -3
- package/src/resources/extensions/gsd/tests/auto-runtime-state.test.ts +34 -0
- package/src/resources/extensions/gsd/tests/auto-worktree-registry.test.ts +2 -2
- package/src/resources/extensions/gsd/tests/auto-worktree-repair.test.ts +4 -2
- package/src/resources/extensions/gsd/tests/blocked-models.test.ts +19 -0
- package/src/resources/extensions/gsd/tests/browser-automation-contract-fixture.ts +39 -0
- package/src/resources/extensions/gsd/tests/browser-contract.test.ts +44 -0
- package/src/resources/extensions/gsd/tests/browser-daemon-auto-prep.test.ts +144 -0
- package/src/resources/extensions/gsd/tests/canonical-milestone-root.test.ts +20 -0
- package/src/resources/extensions/gsd/tests/checkout-branch-stash-guard.test.ts +66 -1
- package/src/resources/extensions/gsd/tests/clear-stale-autostart.test.ts +44 -0
- package/src/resources/extensions/gsd/tests/codebase-generator.test.ts +22 -0
- package/src/resources/extensions/gsd/tests/commands-dispatcher-workspace-git.test.ts +11 -0
- package/src/resources/extensions/gsd/tests/commands-verdict.test.ts +46 -8
- package/src/resources/extensions/gsd/tests/complete-slice-verification-gate.test.ts +42 -0
- package/src/resources/extensions/gsd/tests/consent-question.test.ts +351 -0
- package/src/resources/extensions/gsd/tests/custom-verify-retry-store.test.ts +67 -0
- package/src/resources/extensions/gsd/tests/debug-logger.test.ts +15 -0
- package/src/resources/extensions/gsd/tests/deep-project-auto-loop.test.ts +10 -10
- package/src/resources/extensions/gsd/tests/destructive-confirmation.test.ts +303 -0
- package/src/resources/extensions/gsd/tests/dispatch-complete-milestone-guard.test.ts +34 -3
- package/src/resources/extensions/gsd/tests/dispatch-history.test.ts +273 -0
- package/src/resources/extensions/gsd/tests/dispatch-run-uat-browser-tools.test.ts +89 -0
- package/src/resources/extensions/gsd/tests/doctor-git-checks-terminal.test.ts +73 -0
- package/src/resources/extensions/gsd/tests/doctor-scope-db-unavailable.test.ts +18 -0
- package/src/resources/extensions/gsd/tests/dynamic-bash-no-cap.test.ts +132 -0
- package/src/resources/extensions/gsd/tests/engine-hook-contract.test.ts +148 -0
- package/src/resources/extensions/gsd/tests/evidence-xref-gsd-exec.test.ts +157 -0
- package/src/resources/extensions/gsd/tests/exec-graceful-kill.test.ts +193 -0
- package/src/resources/extensions/gsd/tests/exec-tool.test.ts +29 -1
- package/src/resources/extensions/gsd/tests/execute-summary-save-empty-project.test.ts +64 -1
- package/src/resources/extensions/gsd/tests/execute-task-rendering.test.ts +1 -0
- package/src/resources/extensions/gsd/tests/extension-bootstrap-isolation.test.ts +35 -1
- package/src/resources/extensions/gsd/tests/file-change-validator.test.ts +33 -1
- package/src/resources/extensions/gsd/tests/fixtures/pr-body/swarm-lane-no-blockers.md +1 -5
- package/src/resources/extensions/gsd/tests/fixtures/pr-body/swarm-lane-with-blockers.md +1 -5
- package/src/resources/extensions/gsd/tests/gate-state-canonicalization.test.ts +48 -1
- package/src/resources/extensions/gsd/tests/gsd-command-home.test.ts +120 -0
- package/src/resources/extensions/gsd/tests/gsd-db.test.ts +27 -0
- package/src/resources/extensions/gsd/tests/guidance.test.ts +148 -0
- package/src/resources/extensions/gsd/tests/guided-dispatch-root.test.ts +2 -6
- package/src/resources/extensions/gsd/tests/integration/auto-worktree-milestone-merge.test.ts +58 -15
- package/src/resources/extensions/gsd/tests/integration/auto-worktree.test.ts +74 -59
- package/src/resources/extensions/gsd/tests/integration/git-service.test.ts +3 -2
- package/src/resources/extensions/gsd/tests/integration/gsd-integration-fixture.ts +80 -0
- package/src/resources/extensions/gsd/tests/integration/merge-strategy-regular.test.ts +157 -0
- package/src/resources/extensions/gsd/tests/integration/run-uat.test.ts +199 -0
- package/src/resources/extensions/gsd/tests/markdown-renderer-parse-cache.test.ts +75 -0
- package/src/resources/extensions/gsd/tests/mcp-project-config.test.ts +3 -1
- package/src/resources/extensions/gsd/tests/mcp-tool-name.test.ts +34 -0
- package/src/resources/extensions/gsd/tests/migration-auto-check.test.ts +143 -1
- package/src/resources/extensions/gsd/tests/milestone-closeout-proof.test.ts +99 -0
- package/src/resources/extensions/gsd/tests/milestone-closeout.test.ts +120 -4
- package/src/resources/extensions/gsd/tests/milestone-merge-transaction.test.ts +46 -0
- package/src/resources/extensions/gsd/tests/milestone-readiness.test.ts +65 -0
- package/src/resources/extensions/gsd/tests/milestone-validation-evidence.test.ts +41 -0
- package/src/resources/extensions/gsd/tests/milestone-validation-verdict.test.ts +55 -0
- package/src/resources/extensions/gsd/tests/model-unittype-mapping.test.ts +32 -1
- package/src/resources/extensions/gsd/tests/native-merge-regular.test.ts +139 -0
- package/src/resources/extensions/gsd/tests/notification-store.test.ts +32 -0
- package/src/resources/extensions/gsd/tests/oauth-api-model-routing.test.ts +167 -0
- package/src/resources/extensions/gsd/tests/orchestrator-legacy-parity.test.ts +127 -0
- package/src/resources/extensions/gsd/tests/parallel-research-dispatch.test.ts +18 -0
- package/src/resources/extensions/gsd/tests/parse-project-milestone-bridge.test.ts +77 -0
- package/src/resources/extensions/gsd/tests/parsers-legacy-importers.test.ts +138 -0
- package/src/resources/extensions/gsd/tests/phases-terminal-complete-idempotent.test.ts +242 -0
- package/src/resources/extensions/gsd/tests/plan-milestone.test.ts +45 -0
- package/src/resources/extensions/gsd/tests/plan-slice-prompt.test.ts +6 -2
- package/src/resources/extensions/gsd/tests/planning-crossval.test.ts +45 -0
- package/src/resources/extensions/gsd/tests/post-exec-retry-bypass.test.ts +63 -2
- package/src/resources/extensions/gsd/tests/pre-execution-checks.test.ts +193 -1
- package/src/resources/extensions/gsd/tests/preferences-diagnostics.test.ts +67 -0
- package/src/resources/extensions/gsd/tests/preferences.test.ts +183 -0
- package/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +75 -2
- package/src/resources/extensions/gsd/tests/prompt-db.test.ts +124 -6
- package/src/resources/extensions/gsd/tests/provider-error-guidance.test.ts +3 -3
- package/src/resources/extensions/gsd/tests/provider-errors.test.ts +9 -0
- package/src/resources/extensions/gsd/tests/provider-payload-policy.test.ts +165 -0
- package/src/resources/extensions/gsd/tests/publication.test.ts +120 -0
- package/src/resources/extensions/gsd/tests/pull-request-process.test.ts +47 -0
- package/src/resources/extensions/gsd/tests/recovery-classification-illegal-transition.test.ts +30 -0
- package/src/resources/extensions/gsd/tests/register-hooks-depth-verification.test.ts +342 -1
- package/src/resources/extensions/gsd/tests/research-milestone-composer.test.ts +65 -0
- package/src/resources/extensions/gsd/tests/roadmap-parse-regression.test.ts +40 -0
- package/src/resources/extensions/gsd/tests/roadmap-slices.test.ts +68 -0
- package/src/resources/extensions/gsd/tests/runtime-invariant-modules.test.ts +44 -1
- package/src/resources/extensions/gsd/tests/safety-harness-false-positives.test.ts +38 -0
- package/src/resources/extensions/gsd/tests/session-start-footer.test.ts +80 -0
- package/src/resources/extensions/gsd/tests/session-switch-clears-pending-autostart.test.ts +108 -0
- package/src/resources/extensions/gsd/tests/single-writer-invariant.test.ts +144 -7
- package/src/resources/extensions/gsd/tests/stale-queued-milestone.test.ts +27 -0
- package/src/resources/extensions/gsd/tests/start-auto-detached.test.ts +21 -6
- package/src/resources/extensions/gsd/tests/state-transition-matrix.test.ts +36 -0
- package/src/resources/extensions/gsd/tests/status-guards.test.ts +38 -0
- package/src/resources/extensions/gsd/tests/stop-notice.test.ts +70 -0
- package/src/resources/extensions/gsd/tests/token-tool-gating.test.ts +114 -0
- package/src/resources/extensions/gsd/tests/tool-availability-audit.test.ts +35 -0
- package/src/resources/extensions/gsd/tests/tool-invocation-error-loop-break.test.ts +8 -0
- package/src/resources/extensions/gsd/tests/tool-naming.test.ts +35 -42
- package/src/resources/extensions/gsd/tests/tool-surface-readiness.test.ts +155 -0
- package/src/resources/extensions/gsd/tests/tool-unavailable-retry.test.ts +33 -0
- package/src/resources/extensions/gsd/tests/transport-gate-double-complete.test.ts +139 -0
- package/src/resources/extensions/gsd/tests/uat-policy.test.ts +112 -6
- package/src/resources/extensions/gsd/tests/unit-closeout.test.ts +209 -0
- package/src/resources/extensions/gsd/tests/unit-context-composer.test.ts +114 -2
- package/src/resources/extensions/gsd/tests/unit-registry.test.ts +163 -0
- package/src/resources/extensions/gsd/tests/uok-audit-unified.test.ts +8 -0
- package/src/resources/extensions/gsd/tests/validate-milestone-stuck-guard.test.ts +39 -0
- package/src/resources/extensions/gsd/tests/verification-verdict.test.ts +2 -0
- package/src/resources/extensions/gsd/tests/web-app-uat.test.ts +193 -0
- package/src/resources/extensions/gsd/tests/workflow-events.test.ts +19 -0
- package/src/resources/extensions/gsd/tests/workflow-mcp.test.ts +128 -11
- package/src/resources/extensions/gsd/tests/workflow-reconcile.test.ts +20 -0
- package/src/resources/extensions/gsd/tests/workflow-tool-executors.test.ts +275 -40
- package/src/resources/extensions/gsd/tests/workspace-git-preflight.test.ts +15 -0
- package/src/resources/extensions/gsd/tests/worktree-lifecycle.test.ts +41 -4
- package/src/resources/extensions/gsd/tests/worktree-manager.test.ts +43 -1
- package/src/resources/extensions/gsd/tests/worktree-placement.test.ts +113 -0
- package/src/resources/extensions/gsd/tests/worktree-projection-writers.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/worktree-reentry.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/worktree-safety.test.ts +27 -1
- package/src/resources/extensions/gsd/tests/worktree-symlink-removal.test.ts +12 -6
- package/src/resources/extensions/gsd/tests/worktree-teardown-safety.test.ts +2 -2
- package/src/resources/extensions/gsd/tests/worktree-telemetry.test.ts +22 -0
- package/src/resources/extensions/gsd/tests/write-gate-planning-unit.test.ts +15 -3
- package/src/resources/extensions/gsd/tests/write-gate-seam.test.ts +358 -0
- package/src/resources/extensions/gsd/tests/write-gate.test.ts +188 -1
- package/src/resources/extensions/gsd/tool-contract.ts +124 -11
- package/src/resources/extensions/gsd/tool-presentation-plan.ts +18 -35
- package/src/resources/extensions/gsd/tool-surface-readiness.ts +76 -0
- package/src/resources/extensions/gsd/tool-surface-snapshot.ts +47 -0
- package/src/resources/extensions/gsd/tools/complete-milestone.ts +3 -2
- package/src/resources/extensions/gsd/tools/complete-slice.ts +45 -70
- package/src/resources/extensions/gsd/tools/complete-task.ts +3 -2
- package/src/resources/extensions/gsd/tools/exec-tool.ts +9 -8
- package/src/resources/extensions/gsd/tools/plan-milestone.ts +19 -160
- package/src/resources/extensions/gsd/tools/plan-slice.ts +14 -8
- package/src/resources/extensions/gsd/tools/plan-task.ts +2 -2
- package/src/resources/extensions/gsd/tools/reassess-roadmap.ts +45 -2
- package/src/resources/extensions/gsd/tools/reopen-milestone.ts +13 -40
- package/src/resources/extensions/gsd/tools/reopen-slice.ts +16 -44
- package/src/resources/extensions/gsd/tools/reopen-task.ts +2 -2
- package/src/resources/extensions/gsd/tools/replan-slice.ts +2 -2
- package/src/resources/extensions/gsd/tools/skip-slice.ts +18 -44
- package/src/resources/extensions/gsd/tools/validate-milestone.ts +25 -84
- package/src/resources/extensions/gsd/tools/workflow-tool-executors.ts +264 -23
- package/src/resources/extensions/gsd/uat-policy.ts +80 -25
- package/src/resources/extensions/gsd/uat-run.ts +10 -14
- package/src/resources/extensions/gsd/undo.ts +9 -8
- package/src/resources/extensions/gsd/unit-closeout.ts +201 -0
- package/src/resources/extensions/gsd/unit-context-composer.ts +196 -21
- package/src/resources/extensions/gsd/unit-context-manifest.ts +4 -28
- package/src/resources/extensions/gsd/unit-registry.ts +412 -0
- package/src/resources/extensions/gsd/unit-runtime.ts +3 -2
- package/src/resources/extensions/gsd/unit-tool-contracts.ts +27 -191
- package/src/resources/extensions/gsd/validation-block-guard.ts +2 -0
- package/src/resources/extensions/gsd/verdict-parser.ts +1 -1
- package/src/resources/extensions/gsd/verification-verdict.ts +4 -2
- package/src/resources/extensions/gsd/web-app-uat.ts +144 -0
- package/src/resources/extensions/gsd/workflow-event-ledger.ts +131 -0
- package/src/resources/extensions/gsd/workflow-event-vocabulary.ts +59 -0
- package/src/resources/extensions/gsd/workflow-events.ts +12 -20
- package/src/resources/extensions/gsd/workflow-mcp.ts +22 -110
- package/src/resources/extensions/gsd/workflow-reconcile.ts +32 -65
- package/src/resources/extensions/gsd/workflow-tool-surface.ts +76 -0
- package/src/resources/extensions/gsd/workspace-git-guard.ts +1 -0
- package/src/resources/extensions/gsd/worktree-git-recovery.ts +314 -0
- package/src/resources/extensions/gsd/worktree-lifecycle.ts +20 -25
- package/src/resources/extensions/gsd/worktree-manager.ts +47 -28
- package/src/resources/extensions/gsd/worktree-placement.ts +63 -0
- package/src/resources/extensions/gsd/worktree-reentry.ts +10 -7
- package/src/resources/extensions/gsd/worktree-root.ts +29 -6
- package/src/resources/extensions/gsd/worktree-safety.ts +8 -5
- package/src/resources/extensions/gsd/worktree-session-state.ts +11 -11
- package/src/resources/extensions/gsd/worktree-state-projection.ts +55 -7
- package/src/resources/extensions/gsd/worktree-telemetry.ts +16 -0
- package/src/resources/extensions/search-the-web/native-search.ts +5 -3
- package/src/resources/extensions/shared/browser-contract.ts +66 -0
- package/src/resources/extensions/shared/gsd-browser-cli.ts +141 -6
- package/src/resources/extensions/shared/interview-ui.ts +15 -2
- package/src/resources/shared/claude-runtime-floor.ts +248 -0
- package/src/resources/shared/gsd-browser-path-sync.ts +273 -0
- package/src/resources/shared/package-manager-detection.ts +1 -1
- package/src/resources/shared/package.json +3 -0
- package/src/resources/skills/create-skill/references/executable-code.md +1 -1
- package/src/resources/skills/create-skill/workflows/add-reference.md +8 -3
- package/src/resources/skills/create-skill/workflows/add-script.md +4 -2
- package/src/resources/skills/create-skill/workflows/add-template.md +3 -1
- package/src/resources/skills/create-skill/workflows/add-workflow.md +8 -3
- package/src/resources/skills/create-skill/workflows/upgrade-to-router.md +10 -5
- package/src/resources/skills/create-skill/workflows/verify-skill.md +9 -4
- package/src/resources/skills/gsd-browser/SKILL.md +1 -1
- package/src/resources/skills/spike-wrap-up/SKILL.md +9 -9
- package/dist/resources/extensions/gsd/user-input-boundary.js +0 -157
- package/dist/web/standalone/.next/server/chunks/678.js +0 -2
- package/dist/web/standalone/.next/static/chunks/2659.feb6499ca863ebfc.js +0 -1
- package/dist/web/standalone/.next/static/chunks/2772.151789db0edea835.js +0 -1
- package/dist/web/standalone/.next/static/chunks/4283.10a065467b5340d8.js +0 -2
- package/dist/web/standalone/.next/static/chunks/5826.960dc4634cc9b0d3.js +0 -1
- package/dist/web/standalone/.next/static/chunks/796.46f811c0fac23aab.js +0 -10
- package/dist/web/standalone/.next/static/chunks/8785.d32f7a61f55c1600.js +0 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/__prototype__/gsd-widget-prototype.d.ts +0 -21
- package/packages/gsd-agent-modes/dist/modes/interactive/components/__prototype__/gsd-widget-prototype.d.ts.map +0 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/__prototype__/gsd-widget-prototype.js +0 -213
- package/packages/gsd-agent-modes/dist/modes/interactive/components/__prototype__/gsd-widget-prototype.js.map +0 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/__prototype__/transcript-density-prototype.d.ts +0 -28
- package/packages/gsd-agent-modes/dist/modes/interactive/components/__prototype__/transcript-density-prototype.d.ts.map +0 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/__prototype__/transcript-density-prototype.js +0 -249
- package/packages/gsd-agent-modes/dist/modes/interactive/components/__prototype__/transcript-density-prototype.js.map +0 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/__prototype__/transcript-design-prototype.d.ts +0 -19
- package/packages/gsd-agent-modes/dist/modes/interactive/components/__prototype__/transcript-design-prototype.d.ts.map +0 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/__prototype__/transcript-design-prototype.js +0 -797
- package/packages/gsd-agent-modes/dist/modes/interactive/components/__prototype__/transcript-design-prototype.js.map +0 -1
- package/scripts/ensure-workspace-builds.cjs +0 -129
- package/src/resources/extensions/gsd/tests/user-input-boundary.test.ts +0 -26
- package/src/resources/extensions/gsd/user-input-boundary.ts +0 -166
- /package/dist/web/standalone/.next/static/{tJOKQbQRO-9MiFDO8DIDS → T-LTxEw5wir5Lm5T3qEVd}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{tJOKQbQRO-9MiFDO8DIDS → T-LTxEw5wir5Lm5T3qEVd}/_ssgManifest.js +0 -0
|
@@ -1,28 +1,334 @@
|
|
|
1
1
|
// Project/App: gsd-pi
|
|
2
2
|
// File Purpose: Auto Orchestration module implementation and ADR-015 invariant pipeline owner.
|
|
3
|
+
//
|
|
4
|
+
// Phase 2 of #442 collapsed the nine single-implementation adapter seams
|
|
5
|
+
// (DispatchAdapter, RecoveryAdapter, StateReconciliationAdapter,
|
|
6
|
+
// ToolContractAdapter, WorktreeAdapter, HealthAdapter, UokGateAdapter,
|
|
7
|
+
// RuntimePersistenceAdapter, NotificationAdapter) into this class. The
|
|
8
|
+
// orchestrator now constructs from the concrete extension context and calls
|
|
9
|
+
// the real collaborators (state-reconciliation, doctor-proactive,
|
|
10
|
+
// auto-dispatch, recovery-classification, tool-contract, worktree-safety,
|
|
11
|
+
// uok/gate-runner, journal, session-lock, ctx.ui.notify) directly.
|
|
3
12
|
|
|
4
|
-
import type {
|
|
5
|
-
|
|
13
|
+
import type { ExtensionAPI, ExtensionContext } from "@gsd/pi-coding-agent";
|
|
14
|
+
|
|
15
|
+
import type { AutoAdvanceResult, AutoOrchestrationModule, AutoSessionContext, AutoStatus, AutoTerminalOutcome } from "./contracts.js";
|
|
16
|
+
import type { AutoSession, PendingOrchestrationDispatch } from "./session.js";
|
|
17
|
+
import type { GSDState, Phase } from "../types.js";
|
|
18
|
+
import type { MinimalModelRegistry } from "../context-budget.js";
|
|
19
|
+
|
|
20
|
+
type BlockedAdvanceResult = Extract<AutoAdvanceResult, { kind: "blocked" }>;
|
|
21
|
+
|
|
22
|
+
import { debugCount, debugLog, debugTime } from "../debug-logger.js";
|
|
23
|
+
import { reconcileBeforeDispatch } from "../state-reconciliation.js";
|
|
24
|
+
import { isLegalEdge, IllegalPhaseTransitionError } from "../state-transition-matrix.js";
|
|
25
|
+
import { hasPendingDeepStage, resolveDispatch } from "../auto-dispatch.js";
|
|
26
|
+
import { classifyFailure } from "../recovery-classification.js";
|
|
27
|
+
import { verifyExpectedArtifact, refreshRecoveryDbForArtifact } from "../auto-recovery.js";
|
|
28
|
+
import { invalidateAllCaches } from "../cache.js";
|
|
29
|
+
import { compileUnitToolContract } from "../tool-contract.js";
|
|
30
|
+
import { createWorktreeSafetyModule } from "../worktree-safety.js";
|
|
31
|
+
import { repairAutoWorktreeSafetyFailure } from "../auto-worktree-repair.js";
|
|
32
|
+
import { resolveManifest } from "../unit-context-manifest.js";
|
|
33
|
+
import {
|
|
34
|
+
preDispatchHealthGate,
|
|
35
|
+
recordHealthSnapshot,
|
|
36
|
+
} from "../doctor-proactive.js";
|
|
37
|
+
import { checkResourcesStale, autoWorktreeBranch, mergeMilestoneToMain } from "../auto-worktree.js";
|
|
38
|
+
import { getSessionLockStatus } from "../session-lock.js";
|
|
39
|
+
import { resolveUokFlags } from "../uok/flags.js";
|
|
40
|
+
import { emitJournalEvent as _emitJournalEvent } from "../journal.js";
|
|
41
|
+
import { loadEffectiveGSDPreferences, getIsolationMode, resolveEffectiveUnitIsolationMode } from "../preferences.js";
|
|
42
|
+
import {
|
|
43
|
+
detectWorktreeName,
|
|
44
|
+
getMainBranch,
|
|
45
|
+
resolveProjectRoot,
|
|
46
|
+
resolveWorktreeProjectRoot,
|
|
47
|
+
} from "../worktree.js";
|
|
48
|
+
import { getPriorSliceCompletionBlocker } from "../dispatch-guard.js";
|
|
49
|
+
import { GitServiceImpl } from "../git-service.js";
|
|
50
|
+
import { WorktreeStateProjection } from "../worktree-state-projection.js";
|
|
51
|
+
import { WorktreeLifecycle } from "../worktree-lifecycle.js";
|
|
52
|
+
import { createMilestoneMergeTransaction } from "../milestone-merge-transaction.js";
|
|
53
|
+
import { createWorkspace, scopeMilestone } from "../workspace.js";
|
|
54
|
+
import { supportsStructuredQuestions } from "../workflow-mcp.js";
|
|
55
|
+
import { getRegisteredToolSnapshot, getToolBaselineSnapshot } from "../auto-model-selection.js";
|
|
56
|
+
import { deriveState } from "../state.js";
|
|
57
|
+
import { parseUnitId } from "../unit-id.js";
|
|
58
|
+
import { isClosedStatus } from "../status-guards.js";
|
|
59
|
+
import {
|
|
60
|
+
isDbAvailable,
|
|
61
|
+
getSlice,
|
|
62
|
+
getTask,
|
|
63
|
+
} from "../gsd-db.js";
|
|
64
|
+
import { refreshWorkflowDatabaseFromDisk } from "../db-workspace.js";
|
|
65
|
+
import { getErrorMessage } from "../error-utils.js";
|
|
66
|
+
import { logWarning } from "../workflow-logger.js";
|
|
67
|
+
import { normalizeRealPath } from "../paths.js";
|
|
68
|
+
import {
|
|
69
|
+
buildDispatchKey,
|
|
70
|
+
createDispatchHistory,
|
|
71
|
+
STUCK_WINDOW_SIZE,
|
|
72
|
+
type DispatchHistory,
|
|
73
|
+
} from "./dispatch-history.js";
|
|
74
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
75
|
+
import { join } from "node:path";
|
|
76
|
+
import { evaluateAllCompleteSettlement } from "../milestone-settlement.js";
|
|
6
77
|
|
|
7
78
|
function now(): number {
|
|
8
79
|
return Date.now();
|
|
9
80
|
}
|
|
10
81
|
|
|
82
|
+
function noRemainingUnitsOutcome(stateSnapshot: GSDState): AutoTerminalOutcome {
|
|
83
|
+
if (stateSnapshot.phase === "complete") {
|
|
84
|
+
return {
|
|
85
|
+
code: "all-complete",
|
|
86
|
+
displayReason: "All milestones complete",
|
|
87
|
+
allMilestonesComplete: true,
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
return {
|
|
91
|
+
code: "no-remaining-units",
|
|
92
|
+
displayReason: "No remaining units",
|
|
93
|
+
allMilestonesComplete: false,
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
|
|
11
97
|
/**
|
|
12
|
-
*
|
|
13
|
-
* module's stuck-loop detector. When the same `${unitType}:${unitId}` key
|
|
14
|
-
* fills the window, advance() blocks with `action: "stop"`.
|
|
98
|
+
* Concrete construction context for the Auto Orchestrator.
|
|
15
99
|
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
100
|
+
* Phase 2 of #442 replaced the nine adapter interfaces with this bundle of the
|
|
101
|
+
* real values the wiring factory used to close over: the extension context and
|
|
102
|
+
* API, the dispatch/runtime base paths, and the shared {@link AutoSession}
|
|
103
|
+
* singleton.
|
|
18
104
|
*/
|
|
19
|
-
export
|
|
105
|
+
export interface OrchestratorContext {
|
|
106
|
+
ctx: ExtensionContext;
|
|
107
|
+
pi: ExtensionAPI;
|
|
108
|
+
dispatchBasePath: string;
|
|
109
|
+
runtimeBasePath: string;
|
|
110
|
+
session: AutoSession;
|
|
111
|
+
}
|
|
20
112
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
113
|
+
/** Result type of a single dispatch decision. */
|
|
114
|
+
export type DispatchDecision =
|
|
115
|
+
| { kind: "blocked"; reason: string; action: "pause" | "stop" }
|
|
116
|
+
| { kind: "skipped"; reason: string }
|
|
117
|
+
| { unitType: string; unitId: string; reason: string; preconditions: string[] }
|
|
118
|
+
| null;
|
|
119
|
+
|
|
120
|
+
/** Inputs to a dispatch decision. Caller-supplied fields override ctx-derived ones. */
|
|
121
|
+
export interface DispatchDecisionInput {
|
|
122
|
+
stateSnapshot: GSDState;
|
|
123
|
+
/** Optional live session context, forwarded to dispatch rules that need session-derived state. */
|
|
124
|
+
session?: AutoSession;
|
|
125
|
+
/** Mirrors `DispatchContext.structuredQuestionsAvailable` — "true"/"false" string per the dispatch contract. */
|
|
126
|
+
structuredQuestionsAvailable?: "true" | "false";
|
|
127
|
+
/** Session model context window in tokens, forwarded to the budget engine. */
|
|
128
|
+
sessionContextWindow?: number;
|
|
129
|
+
/** Session model provider, used for provider-specific effective context windows. */
|
|
130
|
+
sessionProvider?: string;
|
|
131
|
+
/** Model registry for executor-model lookups inside the budget engine. */
|
|
132
|
+
modelRegistry?: MinimalModelRegistry;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
function getAlreadyClosedDispatchReason(unitType: string, unitId: string): string | null {
|
|
136
|
+
if (!isDbAvailable()) return null;
|
|
137
|
+
refreshWorkflowDatabaseFromDisk();
|
|
138
|
+
const { milestone, slice, task } = parseUnitId(unitId);
|
|
139
|
+
if (unitType === "execute-task" && milestone && slice && task) {
|
|
140
|
+
const row = getTask(milestone, slice, task);
|
|
141
|
+
return row && isClosedStatus(row.status)
|
|
142
|
+
? `execute-task ${unitId} is already ${row.status}`
|
|
143
|
+
: null;
|
|
144
|
+
}
|
|
145
|
+
if (unitType === "complete-slice" && milestone && slice) {
|
|
146
|
+
const row = getSlice(milestone, slice);
|
|
147
|
+
return row && isClosedStatus(row.status)
|
|
148
|
+
? `complete-slice ${unitId} is already ${row.status}`
|
|
149
|
+
: null;
|
|
150
|
+
}
|
|
151
|
+
return null;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
function shouldAdoptActiveMilestone(
|
|
155
|
+
state: GSDState,
|
|
156
|
+
activeSession: AutoSession | undefined,
|
|
157
|
+
activeDispatchBasePath: string,
|
|
158
|
+
): boolean {
|
|
159
|
+
const activeMilestoneId = state.activeMilestone?.id;
|
|
160
|
+
const currentMilestoneId = activeSession?.currentMilestoneId;
|
|
161
|
+
if (!activeSession || !activeMilestoneId || !currentMilestoneId || activeMilestoneId === currentMilestoneId) {
|
|
162
|
+
return false;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
const scopedWorktreeMilestone =
|
|
166
|
+
(activeSession.basePath ? detectWorktreeName(activeSession.basePath) : null) ??
|
|
167
|
+
detectWorktreeName(activeDispatchBasePath);
|
|
168
|
+
if (scopedWorktreeMilestone && scopedWorktreeMilestone !== activeMilestoneId) {
|
|
169
|
+
return false;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
const currentMilestone = state.registry.find((milestone) => milestone.id === currentMilestoneId);
|
|
173
|
+
return !!currentMilestone && isClosedStatus(currentMilestone.status);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* Pure dispatch-decision function — formerly `createWiredDispatchAdapter`'s
|
|
178
|
+
* `decideNextUnit`. Folded out of the closure so the orchestrator can call it
|
|
179
|
+
* directly and tests can drive the exact dispatch decision logic against real
|
|
180
|
+
* fixtures without re-introducing an adapter seam.
|
|
181
|
+
*
|
|
182
|
+
* Derives session-derived dispatch inputs the same way phases.ts:runDispatch
|
|
183
|
+
* does (#5789): prefers caller-supplied values when present so test harnesses
|
|
184
|
+
* and alternative wirings can inject deterministic snapshots; otherwise pulls
|
|
185
|
+
* from the captured pi/ctx references.
|
|
186
|
+
*/
|
|
187
|
+
export async function decideOrchestratorDispatch(
|
|
188
|
+
ctx: ExtensionContext,
|
|
189
|
+
pi: ExtensionAPI,
|
|
190
|
+
dispatchBasePath: string,
|
|
191
|
+
session: AutoSession | undefined,
|
|
192
|
+
input: DispatchDecisionInput,
|
|
193
|
+
): Promise<DispatchDecision> {
|
|
194
|
+
const state = input.stateSnapshot;
|
|
195
|
+
const active = state.activeMilestone;
|
|
196
|
+
const activeSession = input.session ?? session;
|
|
197
|
+
const activeDispatchBasePath = activeSession?.basePath || dispatchBasePath;
|
|
198
|
+
const prefs = loadEffectiveGSDPreferences(activeDispatchBasePath)?.preferences;
|
|
199
|
+
if (!active) {
|
|
200
|
+
if (state.phase !== "pre-planning") return null;
|
|
201
|
+
if (!hasPendingDeepStage(prefs, activeDispatchBasePath)) {
|
|
202
|
+
return {
|
|
203
|
+
kind: "blocked",
|
|
204
|
+
reason: state.nextAction || "No active milestone. Run /gsd unpark <id> or create a new milestone.",
|
|
205
|
+
action: "stop",
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
if (active && activeSession && shouldAdoptActiveMilestone(state, activeSession, activeDispatchBasePath)) {
|
|
211
|
+
activeSession.currentMilestoneId = active.id;
|
|
212
|
+
}
|
|
213
|
+
const dispatchMid = active?.id ?? activeSession?.currentMilestoneId ?? "";
|
|
214
|
+
const dispatchMidTitle = active?.title ?? "";
|
|
215
|
+
|
|
216
|
+
// Derive session-derived dispatch inputs the same way phases.ts:runDispatch does
|
|
217
|
+
// (#5789). Prefer caller-supplied values when present so test harnesses and
|
|
218
|
+
// alternative wirings can inject deterministic snapshots; otherwise pull from
|
|
219
|
+
// the captured pi/ctx references.
|
|
220
|
+
const sessionProvider = input.sessionProvider ?? ctx.model?.provider;
|
|
221
|
+
const sessionContextWindow = input.sessionContextWindow ?? ctx.model?.contextWindow;
|
|
222
|
+
const modelRegistry = input.modelRegistry ?? (ctx.modelRegistry as MinimalModelRegistry | undefined);
|
|
223
|
+
const authMode =
|
|
224
|
+
sessionProvider && typeof ctx.modelRegistry?.getProviderAuthMode === "function"
|
|
225
|
+
? ctx.modelRegistry.getProviderAuthMode(sessionProvider)
|
|
226
|
+
: undefined;
|
|
227
|
+
// Use baseline snapshot — same reason as phases.ts:runDispatch: the live
|
|
228
|
+
// active set may be narrowed by the prior unit before selectAndApplyModel
|
|
229
|
+
// restores it, causing false transport-preflight failures (#477 follow-up).
|
|
230
|
+
const activeTools = getToolBaselineSnapshot(pi);
|
|
231
|
+
const registeredTools = getRegisteredToolSnapshot(pi);
|
|
232
|
+
// Mirrors runDispatch: deep-planning keeps approval gates in plain chat
|
|
233
|
+
// because structured questions can be cancelled outside the chat turn on
|
|
234
|
+
// some transports.
|
|
235
|
+
const structuredQuestionsAvailable =
|
|
236
|
+
input.structuredQuestionsAvailable ??
|
|
237
|
+
(prefs?.planning_depth === "deep"
|
|
238
|
+
? "false"
|
|
239
|
+
: supportsStructuredQuestions(activeTools, {
|
|
240
|
+
authMode,
|
|
241
|
+
baseUrl: ctx.model?.baseUrl,
|
|
242
|
+
})
|
|
243
|
+
? "true"
|
|
244
|
+
: "false");
|
|
245
|
+
|
|
246
|
+
// Only replay a milestone-scoped verification retry when a milestone is
|
|
247
|
+
// active. Pre-PR (#712 fix), `!active` returned null before reaching this
|
|
248
|
+
// block, so the retry was preserved for a future tick. The new
|
|
249
|
+
// pre-planning + deep-pending fall-through must keep that contract:
|
|
250
|
+
// otherwise a stale execute-task / complete-slice / complete-milestone
|
|
251
|
+
// retry whose target milestone has since been parked would preempt
|
|
252
|
+
// project-level deep rules like `discuss-project`.
|
|
253
|
+
const pendingRetry = session?.pendingVerificationRetryDispatch;
|
|
254
|
+
if (session && pendingRetry && active) {
|
|
255
|
+
session.pendingVerificationRetryDispatch = null;
|
|
256
|
+
const alreadyClosedReason = getAlreadyClosedDispatchReason(
|
|
257
|
+
pendingRetry.unitType,
|
|
258
|
+
pendingRetry.unitId,
|
|
259
|
+
);
|
|
260
|
+
if (alreadyClosedReason) {
|
|
261
|
+
session.pendingOrchestrationDispatch = null;
|
|
262
|
+
session.pendingVerificationRetry = null;
|
|
263
|
+
return { kind: "skipped", reason: alreadyClosedReason };
|
|
264
|
+
}
|
|
265
|
+
session.pendingOrchestrationDispatch = pendingRetry;
|
|
266
|
+
return {
|
|
267
|
+
unitType: pendingRetry.unitType,
|
|
268
|
+
unitId: pendingRetry.unitId,
|
|
269
|
+
reason: "verification-retry",
|
|
270
|
+
preconditions: [],
|
|
271
|
+
};
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
const action = await resolveDispatch({
|
|
275
|
+
basePath: activeDispatchBasePath,
|
|
276
|
+
mid: dispatchMid,
|
|
277
|
+
midTitle: dispatchMidTitle,
|
|
278
|
+
state,
|
|
279
|
+
prefs,
|
|
280
|
+
session: activeSession,
|
|
281
|
+
structuredQuestionsAvailable,
|
|
282
|
+
sessionContextWindow,
|
|
283
|
+
sessionProvider,
|
|
284
|
+
modelRegistry,
|
|
285
|
+
activeTools,
|
|
286
|
+
registeredTools,
|
|
287
|
+
sessionAuthMode: authMode,
|
|
288
|
+
sessionBaseUrl: ctx.model?.baseUrl,
|
|
289
|
+
});
|
|
290
|
+
|
|
291
|
+
if (action.action === "stop") {
|
|
292
|
+
if (session) session.pendingOrchestrationDispatch = null;
|
|
293
|
+
return {
|
|
294
|
+
kind: "blocked",
|
|
295
|
+
reason: action.reason,
|
|
296
|
+
action: action.level === "warning" ? "pause" : "stop",
|
|
297
|
+
};
|
|
24
298
|
}
|
|
25
|
-
|
|
299
|
+
if (action.action !== "dispatch") {
|
|
300
|
+
if (session) session.pendingOrchestrationDispatch = null;
|
|
301
|
+
return {
|
|
302
|
+
kind: "skipped",
|
|
303
|
+
reason: action.matchedRule ?? "dispatch-skip",
|
|
304
|
+
};
|
|
305
|
+
}
|
|
306
|
+
const alreadyClosedReason = getAlreadyClosedDispatchReason(action.unitType, action.unitId);
|
|
307
|
+
if (alreadyClosedReason) {
|
|
308
|
+
if (session) {
|
|
309
|
+
session.pendingOrchestrationDispatch = null;
|
|
310
|
+
session.pendingVerificationRetry = null;
|
|
311
|
+
}
|
|
312
|
+
return { kind: "skipped", reason: alreadyClosedReason };
|
|
313
|
+
}
|
|
314
|
+
if (session) {
|
|
315
|
+
const pending: PendingOrchestrationDispatch = {
|
|
316
|
+
unitType: action.unitType,
|
|
317
|
+
unitId: action.unitId,
|
|
318
|
+
prompt: action.prompt,
|
|
319
|
+
pauseAfterUatDispatch: action.pauseAfterDispatch ?? false,
|
|
320
|
+
state,
|
|
321
|
+
mid: dispatchMid,
|
|
322
|
+
midTitle: dispatchMidTitle,
|
|
323
|
+
};
|
|
324
|
+
session.pendingOrchestrationDispatch = pending;
|
|
325
|
+
}
|
|
326
|
+
return {
|
|
327
|
+
unitType: action.unitType,
|
|
328
|
+
unitId: action.unitId,
|
|
329
|
+
reason: action.matchedRule ?? "dispatch",
|
|
330
|
+
preconditions: [],
|
|
331
|
+
};
|
|
26
332
|
}
|
|
27
333
|
|
|
28
334
|
export class AutoOrchestrator implements AutoOrchestrationModule {
|
|
@@ -30,33 +336,529 @@ export class AutoOrchestrator implements AutoOrchestrationModule {
|
|
|
30
336
|
phase: "idle",
|
|
31
337
|
transitionCount: 0,
|
|
32
338
|
};
|
|
33
|
-
private readonly
|
|
339
|
+
private readonly ctx: ExtensionContext;
|
|
340
|
+
private readonly pi: ExtensionAPI;
|
|
341
|
+
private readonly dispatchBasePath: string;
|
|
342
|
+
private readonly runtimeBasePath: string;
|
|
343
|
+
private readonly s: AutoSession;
|
|
344
|
+
private readonly flowId: string;
|
|
345
|
+
private seq = 0;
|
|
34
346
|
private lastAdvanceKey: string | null = null;
|
|
35
347
|
private lastFinalizedUnitKey: string | null = null;
|
|
36
|
-
|
|
348
|
+
// Dispatch History module (#482): the dispatch-decision window with
|
|
349
|
+
// cross-session DB rehydration and full detect-stuck rules.
|
|
350
|
+
private readonly dispatchHistory: DispatchHistory;
|
|
351
|
+
// ADR-030 Phase Transition Invariant: the prior advance's reconciled Phase,
|
|
352
|
+
// the "from" endpoint of the edge check. In-memory; reset on start/resume/stop
|
|
353
|
+
// so the first advance of a session has no edge to assert.
|
|
354
|
+
private lastDerivedPhase: Phase | null = null;
|
|
355
|
+
// #442: the unit key we last attempted graduated stuck-recovery for. Bounds
|
|
356
|
+
// recovery to one attempt per stuck episode per run (reset on start/resume/
|
|
357
|
+
// stop), mirroring the legacy Level-1-then-Level-2 escalation in phases.ts.
|
|
358
|
+
private lastStuckRecoveryKey: string | null = null;
|
|
37
359
|
|
|
38
|
-
public constructor(
|
|
39
|
-
this.
|
|
360
|
+
public constructor(context: OrchestratorContext) {
|
|
361
|
+
this.ctx = context.ctx;
|
|
362
|
+
this.pi = context.pi;
|
|
363
|
+
this.dispatchBasePath = context.dispatchBasePath;
|
|
364
|
+
this.runtimeBasePath = context.runtimeBasePath;
|
|
365
|
+
this.s = context.session;
|
|
366
|
+
this.flowId = `auto-orchestrator-${Date.now()}`;
|
|
367
|
+
this.dispatchHistory = createDispatchHistory({
|
|
368
|
+
windowSize: STUCK_WINDOW_SIZE,
|
|
369
|
+
// Same stable scope the auto-loop uses for stuck-state persistence so
|
|
370
|
+
// rehydration reads the rows the dispatch ledger wrote for this project.
|
|
371
|
+
resolveScopeId: () =>
|
|
372
|
+
normalizeRealPath(
|
|
373
|
+
this.s.scope?.workspace.projectRoot ??
|
|
374
|
+
(this.s.originalBasePath || this.s.basePath || this.runtimeBasePath),
|
|
375
|
+
) || null,
|
|
376
|
+
});
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
// ── Live base-path resolution (was the wiring factory's getLiveDispatchBasePath) ──
|
|
380
|
+
|
|
381
|
+
private getLiveDispatchBasePath(): string {
|
|
382
|
+
return resolveLiveOrchestratorBasePath({
|
|
383
|
+
capturedBasePath: this.dispatchBasePath,
|
|
384
|
+
runtimeBasePath: this.runtimeBasePath,
|
|
385
|
+
sessionBasePath: this.s.basePath,
|
|
386
|
+
originalBasePath: this.s.originalBasePath,
|
|
387
|
+
});
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
// ── RuntimePersistenceAdapter (folded) ───────────────────────────────────
|
|
391
|
+
|
|
392
|
+
private ensureLockOwnership(): void {
|
|
393
|
+
const status = getSessionLockStatus(this.runtimeBasePath);
|
|
394
|
+
if (!status.valid || status.failureReason === "pid-mismatch") {
|
|
395
|
+
throw new Error("session lock held by another process");
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
/**
|
|
400
|
+
* Map an orchestrator lifecycle event name to its journal eventType and emit
|
|
401
|
+
* it. The name→eventType ternary is preserved byte-for-byte from the legacy
|
|
402
|
+
* wired RuntimePersistenceAdapter.journalTransition.
|
|
403
|
+
*/
|
|
404
|
+
private journalTransition(event: {
|
|
405
|
+
name: string;
|
|
406
|
+
reason?: string;
|
|
407
|
+
unitType?: string;
|
|
408
|
+
unitId?: string;
|
|
409
|
+
}): void {
|
|
410
|
+
const eventType = event.name === "start"
|
|
411
|
+
? "orchestrator-iteration-start"
|
|
412
|
+
: event.name === "resume"
|
|
413
|
+
? "orchestrator-iteration-start"
|
|
414
|
+
: event.name === "advance"
|
|
415
|
+
? "orchestrator-dispatch-match"
|
|
416
|
+
: event.name === "advance-blocked"
|
|
417
|
+
? "orchestrator-guard-block"
|
|
418
|
+
: event.name === "advance-stopped"
|
|
419
|
+
? "orchestrator-dispatch-stop"
|
|
420
|
+
: event.name === "advance-error"
|
|
421
|
+
? "orchestrator-iteration-end"
|
|
422
|
+
: event.name === "advance-paused" || event.name === "advance-retry"
|
|
423
|
+
? "orchestrator-guard-block"
|
|
424
|
+
: event.name === "stop"
|
|
425
|
+
? "orchestrator-terminal"
|
|
426
|
+
: "orchestrator-iteration-end";
|
|
427
|
+
|
|
428
|
+
_emitJournalEvent(this.runtimeBasePath, {
|
|
429
|
+
ts: new Date().toISOString(),
|
|
430
|
+
flowId: this.flowId,
|
|
431
|
+
seq: ++this.seq,
|
|
432
|
+
eventType,
|
|
433
|
+
data: {
|
|
434
|
+
source: "auto-orchestrator",
|
|
435
|
+
name: event.name,
|
|
436
|
+
reason: event.reason,
|
|
437
|
+
unitType: event.unitType,
|
|
438
|
+
unitId: event.unitId,
|
|
439
|
+
},
|
|
440
|
+
});
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
// ── NotificationAdapter (folded) ─────────────────────────────────────────
|
|
444
|
+
|
|
445
|
+
private notifyLifecycle(event: { name: string; detail?: string }): void {
|
|
446
|
+
if (event.name === "error") {
|
|
447
|
+
this.ctx.ui.notify(event.detail ?? "auto orchestration error", "error");
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
// ── HealthAdapter (folded) ───────────────────────────────────────────────
|
|
452
|
+
|
|
453
|
+
private checkResourcesStale(): string | null {
|
|
454
|
+
return checkResourcesStale(this.s.resourceVersionOnStart);
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
private async preAdvanceGate(): Promise<
|
|
458
|
+
| { kind: "pass"; fixesApplied?: readonly string[] }
|
|
459
|
+
| { kind: "fail"; reason: string; action?: "pause" | "stop" }
|
|
460
|
+
| { kind: "threw"; error: unknown }
|
|
461
|
+
> {
|
|
462
|
+
try {
|
|
463
|
+
const gate = await preDispatchHealthGate(this.getLiveDispatchBasePath());
|
|
464
|
+
if (gate.proceed) {
|
|
465
|
+
return {
|
|
466
|
+
kind: "pass",
|
|
467
|
+
fixesApplied: gate.fixesApplied,
|
|
468
|
+
};
|
|
469
|
+
}
|
|
470
|
+
return {
|
|
471
|
+
kind: "fail",
|
|
472
|
+
reason: gate.reason ?? "Pre-dispatch health check failed — run /gsd doctor for details.",
|
|
473
|
+
action: gate.severity ?? "pause",
|
|
474
|
+
};
|
|
475
|
+
} catch (error) {
|
|
476
|
+
return { kind: "threw", error };
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
private postAdvanceRecord(result: AutoAdvanceResult): void {
|
|
481
|
+
if (result.kind === "error") {
|
|
482
|
+
recordHealthSnapshot(1, 0, 0, [{
|
|
483
|
+
code: "orchestration-error",
|
|
484
|
+
message: result.reason ?? "orchestration error",
|
|
485
|
+
severity: "error",
|
|
486
|
+
unitId: "orchestration",
|
|
487
|
+
}], [], "orchestration");
|
|
488
|
+
} else if (result.kind === "blocked") {
|
|
489
|
+
recordHealthSnapshot(0, 1, 0, [{
|
|
490
|
+
code: "orchestration-blocked",
|
|
491
|
+
message: result.reason ?? "orchestration blocked",
|
|
492
|
+
severity: "warning",
|
|
493
|
+
unitId: "orchestration",
|
|
494
|
+
}], [], "orchestration");
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
// ── UokGateAdapter (folded) ──────────────────────────────────────────────
|
|
499
|
+
|
|
500
|
+
private async emitUokGate(input: {
|
|
501
|
+
gateId: string;
|
|
502
|
+
gateType: "policy" | "execution";
|
|
503
|
+
outcome: "pass" | "fail" | "manual-attention";
|
|
504
|
+
failureClass: "none" | "policy" | "manual-attention";
|
|
505
|
+
rationale: string;
|
|
506
|
+
findings?: string;
|
|
507
|
+
milestoneId?: string;
|
|
508
|
+
}): Promise<void> {
|
|
509
|
+
const activeBasePath = this.getLiveDispatchBasePath();
|
|
510
|
+
const prefs = loadEffectiveGSDPreferences(activeBasePath)?.preferences;
|
|
511
|
+
const uokFlags = resolveUokFlags(prefs);
|
|
512
|
+
if (!uokFlags.gates) return;
|
|
513
|
+
const milestoneId = input.milestoneId ?? this.s.currentMilestoneId ?? undefined;
|
|
514
|
+
try {
|
|
515
|
+
const { UokGateRunner } = await import("../uok/gate-runner.js");
|
|
516
|
+
const runner = new UokGateRunner();
|
|
517
|
+
runner.register({
|
|
518
|
+
id: input.gateId,
|
|
519
|
+
type: input.gateType,
|
|
520
|
+
execute: async () => ({
|
|
521
|
+
outcome: input.outcome,
|
|
522
|
+
failureClass: input.failureClass,
|
|
523
|
+
rationale: input.rationale,
|
|
524
|
+
findings: input.findings ?? "",
|
|
525
|
+
}),
|
|
526
|
+
});
|
|
527
|
+
await runner.run(input.gateId, {
|
|
528
|
+
basePath: activeBasePath,
|
|
529
|
+
traceId: `pre-dispatch:${this.flowId}`,
|
|
530
|
+
turnId: `orch-${this.seq}`,
|
|
531
|
+
milestoneId,
|
|
532
|
+
unitType: "pre-dispatch",
|
|
533
|
+
unitId: `orch-${this.seq}`,
|
|
534
|
+
});
|
|
535
|
+
} catch (err) {
|
|
536
|
+
logWarning("engine", `uok gate emit failed: ${getErrorMessage(err)}`, {
|
|
537
|
+
file: "orchestrator.ts",
|
|
538
|
+
gateId: input.gateId,
|
|
539
|
+
gateType: input.gateType,
|
|
540
|
+
...(milestoneId ? { milestoneId } : {}),
|
|
541
|
+
});
|
|
542
|
+
}
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
// ── StateReconciliationAdapter (folded) ──────────────────────────────────
|
|
546
|
+
|
|
547
|
+
private async reconcileBeforeDispatch(): Promise<
|
|
548
|
+
{ ok: true; reason: string; stateSnapshot?: GSDState }
|
|
549
|
+
| { ok: false; reason: string; stateSnapshot?: GSDState }
|
|
550
|
+
> {
|
|
551
|
+
const activeBasePath = this.getLiveDispatchBasePath();
|
|
552
|
+
const result = await reconcileBeforeDispatch(activeBasePath);
|
|
553
|
+
// Failure-path summaries written by gsd_summary_save create
|
|
554
|
+
// artifact-db-status-divergence blockers for tasks that are still
|
|
555
|
+
// pending (gsd_task_complete never ran). These tasks can still be
|
|
556
|
+
// dispatched and the drift self-heals once they complete successfully.
|
|
557
|
+
const hardBlockers = result.blockers.filter(
|
|
558
|
+
(b) =>
|
|
559
|
+
!b.includes("has SUMMARY artifact while DB status is") &&
|
|
560
|
+
!b.includes("has SUMMARY on disk while DB status is") &&
|
|
561
|
+
!b.includes("has task SUMMARY artifacts but no DB tasks"),
|
|
562
|
+
);
|
|
563
|
+
if (hardBlockers.length > 0) {
|
|
564
|
+
return {
|
|
565
|
+
ok: false,
|
|
566
|
+
reason: hardBlockers[0],
|
|
567
|
+
stateSnapshot: result.stateSnapshot,
|
|
568
|
+
};
|
|
569
|
+
}
|
|
570
|
+
const repairedKinds = result.repaired.map((d) => d.kind);
|
|
571
|
+
return {
|
|
572
|
+
ok: true,
|
|
573
|
+
reason:
|
|
574
|
+
repairedKinds.length > 0
|
|
575
|
+
? `repaired: ${repairedKinds.join(", ")}`
|
|
576
|
+
: "clean",
|
|
577
|
+
stateSnapshot: result.stateSnapshot,
|
|
578
|
+
};
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
// ── DispatchAdapter (folded) ─────────────────────────────────────────────
|
|
582
|
+
|
|
583
|
+
private decideNextUnit(input: DispatchDecisionInput): Promise<DispatchDecision> {
|
|
584
|
+
return decideOrchestratorDispatch(this.ctx, this.pi, this.dispatchBasePath, this.s, input);
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
private evaluateNoRemainingUnitsSettlement(stateSnapshot: GSDState): BlockedAdvanceResult | null {
|
|
588
|
+
const settlement = evaluateAllCompleteSettlement({
|
|
589
|
+
milestoneId: this.s.currentMilestoneId ?? stateSnapshot.activeMilestone?.id,
|
|
590
|
+
statePhase: stateSnapshot.phase,
|
|
591
|
+
basePath: this.s.basePath || this.getLiveDispatchBasePath(),
|
|
592
|
+
originalBasePath: this.s.originalBasePath || this.runtimeBasePath,
|
|
593
|
+
milestoneMerged: this.s.milestoneMergedInPhases,
|
|
594
|
+
});
|
|
595
|
+
this.s.milestoneSettlement = settlement;
|
|
596
|
+
if (settlement.ok) return null;
|
|
597
|
+
return {
|
|
598
|
+
kind: "blocked",
|
|
599
|
+
reason: settlement.message,
|
|
600
|
+
action: settlement.action,
|
|
601
|
+
stateSnapshot,
|
|
602
|
+
terminalOutcome: {
|
|
603
|
+
code: "settlement-blocked",
|
|
604
|
+
displayReason: settlement.message,
|
|
605
|
+
nextAction: settlement.nextAction,
|
|
606
|
+
milestoneId: settlement.milestoneId,
|
|
607
|
+
allMilestonesComplete: false,
|
|
608
|
+
},
|
|
609
|
+
};
|
|
610
|
+
}
|
|
611
|
+
|
|
612
|
+
private clearPendingDispatch(): void {
|
|
613
|
+
this.s.pendingOrchestrationDispatch = null;
|
|
614
|
+
}
|
|
615
|
+
|
|
616
|
+
private findPriorSliceCompletionBlocker(unitType: string, unitId: string): string | null {
|
|
617
|
+
const guardBasePath = resolveWorktreeProjectRoot(
|
|
618
|
+
this.getLiveDispatchBasePath(),
|
|
619
|
+
this.s.originalBasePath,
|
|
620
|
+
);
|
|
621
|
+
let mainBranch = "main";
|
|
622
|
+
try {
|
|
623
|
+
mainBranch = getMainBranch(guardBasePath);
|
|
624
|
+
} catch (err) {
|
|
625
|
+
// Preserve legacy dispatch behavior: fall back to main when branch
|
|
626
|
+
// discovery fails, then let the guard make the progression decision.
|
|
627
|
+
logWarning(
|
|
628
|
+
"engine",
|
|
629
|
+
`branch discovery failed, falling back to main: ${getErrorMessage(err)}`,
|
|
630
|
+
{ file: "orchestrator.ts" },
|
|
631
|
+
);
|
|
632
|
+
}
|
|
633
|
+
return getPriorSliceCompletionBlocker(guardBasePath, mainBranch, unitType, unitId);
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
// ── ToolContractAdapter (folded) ─────────────────────────────────────────
|
|
637
|
+
|
|
638
|
+
private compileUnitToolContract(unitType: string): { ok: true; reason: string } | { ok: false; reason: string } {
|
|
639
|
+
const result = compileUnitToolContract(unitType);
|
|
640
|
+
if (!result.ok) return { ok: false, reason: result.detail };
|
|
641
|
+
return { ok: true, reason: result.contract.validationRules.join(", ") };
|
|
642
|
+
}
|
|
643
|
+
|
|
644
|
+
// ── WorktreeAdapter (folded) ─────────────────────────────────────────────
|
|
645
|
+
|
|
646
|
+
private getEffectiveUnitIsolationMode(basePath: string): ReturnType<typeof getIsolationMode> {
|
|
647
|
+
return resolveEffectiveUnitIsolationMode(
|
|
648
|
+
getIsolationMode(basePath),
|
|
649
|
+
this.s.isolationDegraded,
|
|
650
|
+
this.s.strandedRecoveryIsolationMode,
|
|
651
|
+
);
|
|
652
|
+
}
|
|
653
|
+
|
|
654
|
+
private buildLifecycle(): WorktreeLifecycle {
|
|
655
|
+
return new WorktreeLifecycle(this.s, {
|
|
656
|
+
gitServiceFactory: (basePath: string) => {
|
|
657
|
+
const gitConfig = loadEffectiveGSDPreferences()?.preferences?.git ?? {};
|
|
658
|
+
return new GitServiceImpl(basePath, gitConfig);
|
|
659
|
+
},
|
|
660
|
+
worktreeProjection: new WorktreeStateProjection(),
|
|
661
|
+
mergeMilestoneToMain: createMilestoneMergeTransaction(mergeMilestoneToMain),
|
|
662
|
+
});
|
|
663
|
+
}
|
|
664
|
+
|
|
665
|
+
private rebuildScope(rawPath: string, milestoneId: string | null): void {
|
|
666
|
+
if (!milestoneId) {
|
|
667
|
+
this.s.scope = null;
|
|
668
|
+
return;
|
|
669
|
+
}
|
|
670
|
+
try {
|
|
671
|
+
const workspace = createWorkspace(rawPath);
|
|
672
|
+
this.s.scope = scopeMilestone(workspace, milestoneId);
|
|
673
|
+
} catch {
|
|
674
|
+
// Non-fatal — scope is additive. Existing readers still use basePath.
|
|
675
|
+
this.s.scope = null;
|
|
676
|
+
}
|
|
677
|
+
}
|
|
678
|
+
|
|
679
|
+
private async prepareWorktreeForUnit(
|
|
680
|
+
unitType: string,
|
|
681
|
+
unitId: string,
|
|
682
|
+
): Promise<{ ok: true; reason: string } | { ok: false; reason: string }> {
|
|
683
|
+
const isolationMode = this.getEffectiveUnitIsolationMode(this.runtimeBasePath);
|
|
684
|
+
const manifest = resolveManifest(unitType);
|
|
685
|
+
if (!manifest) {
|
|
686
|
+
return {
|
|
687
|
+
ok: false,
|
|
688
|
+
reason: `No Unit manifest is registered for ${unitType}`,
|
|
689
|
+
};
|
|
690
|
+
}
|
|
691
|
+
if (isolationMode !== "worktree") {
|
|
692
|
+
return { ok: true, reason: "not-required" };
|
|
693
|
+
}
|
|
694
|
+
const writeScope =
|
|
695
|
+
manifest.tools.mode === "all" || manifest.tools.mode === "docs"
|
|
696
|
+
? "source-writing"
|
|
697
|
+
: "planning-only";
|
|
698
|
+
const safety = createWorktreeSafetyModule();
|
|
699
|
+
const activeBasePath = this.getLiveDispatchBasePath();
|
|
700
|
+
const snapshot = await deriveState(activeBasePath);
|
|
701
|
+
const milestoneId = snapshot.activeMilestone?.id ?? null;
|
|
702
|
+
const expectedBranch = milestoneId ? autoWorktreeBranch(milestoneId) : null;
|
|
703
|
+
let result = safety.validateUnitRoot({
|
|
704
|
+
unitType,
|
|
705
|
+
unitId,
|
|
706
|
+
writeScope,
|
|
707
|
+
projectRoot: this.runtimeBasePath,
|
|
708
|
+
unitRoot: activeBasePath,
|
|
709
|
+
milestoneId,
|
|
710
|
+
isolationMode,
|
|
711
|
+
expectedBranch,
|
|
712
|
+
});
|
|
713
|
+
if (!result.ok) {
|
|
714
|
+
const repaired = await repairAutoWorktreeSafetyFailure({
|
|
715
|
+
safetyResult: result,
|
|
716
|
+
projectRoot: this.runtimeBasePath,
|
|
717
|
+
activeRoot: activeBasePath,
|
|
718
|
+
milestoneId,
|
|
719
|
+
enterMilestone: async (id) => {
|
|
720
|
+
this.buildLifecycle().adoptSessionRoot(this.runtimeBasePath, this.s.originalBasePath || this.runtimeBasePath);
|
|
721
|
+
const enterResult = this.buildLifecycle().enterMilestone(id, {
|
|
722
|
+
notify: this.ctx.ui.notify.bind(this.ctx.ui),
|
|
723
|
+
});
|
|
724
|
+
if (!enterResult.ok) return { ok: false, reason: enterResult.reason };
|
|
725
|
+
this.rebuildScope(this.s.basePath, this.s.currentMilestoneId);
|
|
726
|
+
return { ok: true };
|
|
727
|
+
},
|
|
728
|
+
revalidate: () => safety.validateUnitRoot({
|
|
729
|
+
unitType,
|
|
730
|
+
unitId,
|
|
731
|
+
writeScope,
|
|
732
|
+
projectRoot: this.runtimeBasePath,
|
|
733
|
+
unitRoot: this.getLiveDispatchBasePath(),
|
|
734
|
+
milestoneId,
|
|
735
|
+
isolationMode: this.getEffectiveUnitIsolationMode(this.runtimeBasePath),
|
|
736
|
+
expectedBranch,
|
|
737
|
+
}),
|
|
738
|
+
});
|
|
739
|
+
result = repaired.result;
|
|
740
|
+
if (result.ok) {
|
|
741
|
+
return { ok: true, reason: repaired.repaired ? `repaired-${result.kind}` : result.kind };
|
|
742
|
+
}
|
|
743
|
+
const repairDetail = repaired.repairReason
|
|
744
|
+
? ` (repair skipped: ${repaired.repairReason})`
|
|
745
|
+
: "";
|
|
746
|
+
return { ok: false, reason: `${result.kind}: ${result.reason}${repairDetail}` };
|
|
747
|
+
}
|
|
748
|
+
return { ok: true, reason: result.kind };
|
|
749
|
+
}
|
|
750
|
+
|
|
751
|
+
// ── RecoveryAdapter (folded) ─────────────────────────────────────────────
|
|
752
|
+
|
|
753
|
+
private classifyAndRecover(input: {
|
|
754
|
+
error: unknown;
|
|
755
|
+
unitType?: string;
|
|
756
|
+
unitId?: string;
|
|
757
|
+
}): { action: "retry" | "escalate" | "stop"; reason: string } {
|
|
758
|
+
const recovery = classifyFailure(input);
|
|
759
|
+
return { action: recovery.action, reason: recovery.reason };
|
|
760
|
+
}
|
|
761
|
+
|
|
762
|
+
/**
|
|
763
|
+
* ADR-030 Phase Transition Invariant (advisory mode). The matrix is an
|
|
764
|
+
* assertion, not a decision-maker — deriveState already chose the phase; we
|
|
765
|
+
* only observe illegal *derived* edges that survived reconciliation. The
|
|
766
|
+
* matrix is still a sparse hardening spec, so this is telemetry-only (no
|
|
767
|
+
* block) until it is expanded into a validated legal-edge graph. To enforce:
|
|
768
|
+
* `throw violation;` instead of logging — recovery-classification maps
|
|
769
|
+
* IllegalPhaseTransitionError to kind "illegal-transition" (escalate).
|
|
770
|
+
*/
|
|
771
|
+
private observePhaseTransition(from: Phase, to: Phase): void {
|
|
772
|
+
if (isLegalEdge(from, to)) return;
|
|
773
|
+
const violation = new IllegalPhaseTransitionError(from, to);
|
|
774
|
+
debugLog("phase-transition-advisory", { from, to, message: violation.message });
|
|
775
|
+
}
|
|
776
|
+
|
|
777
|
+
// ── Lifecycle verbs ──────────────────────────────────────────────────────
|
|
778
|
+
|
|
779
|
+
/**
|
|
780
|
+
* #442: graduated stuck recovery, ported from the legacy
|
|
781
|
+
* auto/phases.ts:runDispatch path that Phase 3 retires. The ring-buffer
|
|
782
|
+
* hard-stops (stuck-loop saturation and finalized-repeat) would otherwise
|
|
783
|
+
* KILL a unit that actually completed on disk but whose DB row is still
|
|
784
|
+
* stale. Before hard-stopping, verify the expected artifact exists; if so,
|
|
785
|
+
* refresh the DB from it, invalidate caches and reset the dispatch ring so
|
|
786
|
+
* the next advance picks the correct next unit. Bounded to one attempt per
|
|
787
|
+
* stuck key per episode (reset on lifecycle + genuine finalize) to avoid an
|
|
788
|
+
* unbounded recover→re-saturate→recover loop — mirrors the legacy
|
|
789
|
+
* Level-1-recover-then-Level-2-hard-stop escalation.
|
|
790
|
+
*
|
|
791
|
+
* Returns true when recovery succeeded; the caller should re-loop (return a
|
|
792
|
+
* skipped result) instead of stopping.
|
|
793
|
+
*/
|
|
794
|
+
private tryStuckArtifactRecovery(unitType: string, unitId: string): boolean {
|
|
795
|
+
const key = buildDispatchKey(unitType, unitId);
|
|
796
|
+
if (this.lastStuckRecoveryKey === key) return false; // already tried this episode
|
|
797
|
+
const basePath = this.getLiveDispatchBasePath();
|
|
798
|
+
if (!verifyExpectedArtifact(unitType, unitId, basePath)) return false;
|
|
799
|
+
const refreshed = refreshRecoveryDbForArtifact(unitType, unitId, basePath);
|
|
800
|
+
// Fatal failures cannot be recovered — hard-stop. Non-fatal (e.g. plan-slice
|
|
801
|
+
// DB refresh hiccup) still fall through: invalidating caches and resetting
|
|
802
|
+
// the ring gives the next advance a clean slate to pick up the correct state,
|
|
803
|
+
// mirroring the legacy Level-1 "continue" escalation path.
|
|
804
|
+
if (!refreshed.ok && refreshed.fatal) return false;
|
|
805
|
+
this.lastStuckRecoveryKey = key;
|
|
806
|
+
invalidateAllCaches();
|
|
807
|
+
this.dispatchHistory.clearOnRecovery();
|
|
808
|
+
this.lastAdvanceKey = null;
|
|
809
|
+
this.lastFinalizedUnitKey = null;
|
|
810
|
+
return true;
|
|
811
|
+
}
|
|
812
|
+
|
|
813
|
+
private stuckRecovered(
|
|
814
|
+
decision: { unitType: string; unitId: string },
|
|
815
|
+
stateSnapshot: GSDState,
|
|
816
|
+
): AutoAdvanceResult {
|
|
817
|
+
const recovered: AutoAdvanceResult = {
|
|
818
|
+
kind: "skipped",
|
|
819
|
+
reason: `stuck-recovery: ${decision.unitType} ${decision.unitId} artifact found on disk; DB refreshed`,
|
|
820
|
+
stateSnapshot,
|
|
821
|
+
};
|
|
822
|
+
this.status.phase = "running";
|
|
823
|
+
this.status.activeUnit = undefined;
|
|
824
|
+
this.bumpTransition();
|
|
825
|
+
this.journalTransition({
|
|
826
|
+
name: "advance-skipped",
|
|
827
|
+
reason: recovered.reason,
|
|
828
|
+
unitType: decision.unitType,
|
|
829
|
+
unitId: decision.unitId,
|
|
830
|
+
});
|
|
831
|
+
this.postAdvanceRecord(recovered);
|
|
832
|
+
return recovered;
|
|
40
833
|
}
|
|
41
834
|
|
|
42
835
|
public async start(_sessionContext: AutoSessionContext): Promise<AutoAdvanceResult> {
|
|
43
836
|
this.lastAdvanceKey = null;
|
|
44
837
|
this.lastFinalizedUnitKey = null;
|
|
45
|
-
|
|
838
|
+
// #482: the DB dispatch ledger is the source of truth across sessions.
|
|
839
|
+
// Discard any in-memory window and rebuild it from the ledger so a unit
|
|
840
|
+
// that was re-dispatched in previous sessions is detected as stuck here
|
|
841
|
+
// instead of silently re-dispatching forever.
|
|
842
|
+
this.dispatchHistory.clearOnRecovery();
|
|
843
|
+
this.dispatchHistory.rehydrate();
|
|
844
|
+
this.lastStuckRecoveryKey = null;
|
|
845
|
+
this.lastDerivedPhase = null;
|
|
46
846
|
this.status.phase = "running";
|
|
47
847
|
this.bumpTransition();
|
|
48
|
-
|
|
49
|
-
|
|
848
|
+
this.journalTransition({ name: "start" });
|
|
849
|
+
this.notifyLifecycle({ name: "start" });
|
|
50
850
|
return { kind: "started" };
|
|
51
851
|
}
|
|
52
852
|
|
|
53
853
|
public async advance(): Promise<AutoAdvanceResult> {
|
|
854
|
+
debugCount("dispatches");
|
|
855
|
+
const stopAdvanceTimer = debugTime("orchestrator-advance");
|
|
54
856
|
try {
|
|
55
|
-
|
|
857
|
+
this.ensureLockOwnership();
|
|
56
858
|
|
|
57
|
-
const staleMsg = this.
|
|
859
|
+
const staleMsg = this.checkResourcesStale();
|
|
58
860
|
if (staleMsg) {
|
|
59
|
-
await this.
|
|
861
|
+
await this.emitUokGate({
|
|
60
862
|
gateId: "resource-version-guard",
|
|
61
863
|
gateType: "policy",
|
|
62
864
|
outcome: "fail",
|
|
@@ -65,11 +867,11 @@ export class AutoOrchestrator implements AutoOrchestrationModule {
|
|
|
65
867
|
findings: staleMsg,
|
|
66
868
|
});
|
|
67
869
|
const blocked: AutoAdvanceResult = { kind: "blocked", reason: staleMsg, action: "pause" };
|
|
68
|
-
|
|
69
|
-
|
|
870
|
+
this.journalTransition({ name: "advance-blocked", reason: blocked.reason });
|
|
871
|
+
this.postAdvanceRecord(blocked);
|
|
70
872
|
return blocked;
|
|
71
873
|
}
|
|
72
|
-
await this.
|
|
874
|
+
await this.emitUokGate({
|
|
73
875
|
gateId: "resource-version-guard",
|
|
74
876
|
gateType: "policy",
|
|
75
877
|
outcome: "pass",
|
|
@@ -77,9 +879,9 @@ export class AutoOrchestrator implements AutoOrchestrationModule {
|
|
|
77
879
|
rationale: "resource version guard passed",
|
|
78
880
|
});
|
|
79
881
|
|
|
80
|
-
const gate = await this.
|
|
882
|
+
const gate = await this.preAdvanceGate();
|
|
81
883
|
if (gate.kind === "fail") {
|
|
82
|
-
await this.
|
|
884
|
+
await this.emitUokGate({
|
|
83
885
|
gateId: "pre-dispatch-health-gate",
|
|
84
886
|
gateType: "execution",
|
|
85
887
|
outcome: "manual-attention",
|
|
@@ -92,12 +894,12 @@ export class AutoOrchestrator implements AutoOrchestrationModule {
|
|
|
92
894
|
reason: gate.reason,
|
|
93
895
|
action: gate.action ?? "pause",
|
|
94
896
|
};
|
|
95
|
-
|
|
96
|
-
|
|
897
|
+
this.journalTransition({ name: "advance-blocked", reason: blocked.reason });
|
|
898
|
+
this.postAdvanceRecord(blocked);
|
|
97
899
|
return blocked;
|
|
98
900
|
}
|
|
99
901
|
if (gate.kind === "threw") {
|
|
100
|
-
await this.
|
|
902
|
+
await this.emitUokGate({
|
|
101
903
|
gateId: "pre-dispatch-health-gate",
|
|
102
904
|
gateType: "execution",
|
|
103
905
|
outcome: "manual-attention",
|
|
@@ -107,7 +909,7 @@ export class AutoOrchestrator implements AutoOrchestrationModule {
|
|
|
107
909
|
});
|
|
108
910
|
// intentional fall-through: matches runPreDispatch behaviour
|
|
109
911
|
} else {
|
|
110
|
-
await this.
|
|
912
|
+
await this.emitUokGate({
|
|
111
913
|
gateId: "pre-dispatch-health-gate",
|
|
112
914
|
gateType: "execution",
|
|
113
915
|
outcome: "pass",
|
|
@@ -117,7 +919,7 @@ export class AutoOrchestrator implements AutoOrchestrationModule {
|
|
|
117
919
|
});
|
|
118
920
|
}
|
|
119
921
|
|
|
120
|
-
const reconciliation = await this.
|
|
922
|
+
const reconciliation = await this.reconcileBeforeDispatch();
|
|
121
923
|
if (!reconciliation.ok || !reconciliation.stateSnapshot) {
|
|
122
924
|
const blocked: AutoAdvanceResult = {
|
|
123
925
|
kind: "blocked",
|
|
@@ -125,25 +927,44 @@ export class AutoOrchestrator implements AutoOrchestrationModule {
|
|
|
125
927
|
action: "pause",
|
|
126
928
|
stateSnapshot: reconciliation.stateSnapshot,
|
|
127
929
|
};
|
|
128
|
-
|
|
129
|
-
|
|
930
|
+
this.journalTransition({ name: "advance-blocked", reason: blocked.reason });
|
|
931
|
+
this.postAdvanceRecord(blocked);
|
|
130
932
|
return blocked;
|
|
131
933
|
}
|
|
132
934
|
|
|
133
|
-
const
|
|
935
|
+
const reconciledPhase = reconciliation.stateSnapshot.phase;
|
|
936
|
+
if (this.lastDerivedPhase !== null) {
|
|
937
|
+
this.observePhaseTransition(this.lastDerivedPhase, reconciledPhase);
|
|
938
|
+
}
|
|
939
|
+
this.lastDerivedPhase = reconciledPhase;
|
|
940
|
+
|
|
941
|
+
const decision = await this.decideNextUnit({ stateSnapshot: reconciliation.stateSnapshot });
|
|
134
942
|
if (!decision) {
|
|
943
|
+
const settlementBlock = this.evaluateNoRemainingUnitsSettlement(reconciliation.stateSnapshot);
|
|
944
|
+
if (settlementBlock) {
|
|
945
|
+
this.status.phase = "paused";
|
|
946
|
+
this.status.activeUnit = undefined;
|
|
947
|
+
this.lastAdvanceKey = null;
|
|
948
|
+
this.dispatchHistory.clearOnRecovery();
|
|
949
|
+
this.bumpTransition();
|
|
950
|
+
this.journalTransition({ name: "advance-blocked", reason: settlementBlock.reason });
|
|
951
|
+
this.postAdvanceRecord(settlementBlock);
|
|
952
|
+
return settlementBlock;
|
|
953
|
+
}
|
|
954
|
+
const terminalOutcome = noRemainingUnitsOutcome(reconciliation.stateSnapshot);
|
|
135
955
|
const stopped: AutoAdvanceResult = {
|
|
136
956
|
kind: "stopped",
|
|
137
|
-
reason:
|
|
957
|
+
reason: terminalOutcome.displayReason,
|
|
138
958
|
stateSnapshot: reconciliation.stateSnapshot,
|
|
959
|
+
terminalOutcome,
|
|
139
960
|
};
|
|
140
961
|
this.status.phase = "stopped";
|
|
141
962
|
this.status.activeUnit = undefined;
|
|
142
963
|
this.lastAdvanceKey = null;
|
|
143
|
-
this.
|
|
964
|
+
this.dispatchHistory.clearOnRecovery();
|
|
144
965
|
this.bumpTransition();
|
|
145
|
-
|
|
146
|
-
|
|
966
|
+
this.journalTransition({ name: "advance-stopped", reason: stopped.reason });
|
|
967
|
+
this.postAdvanceRecord(stopped);
|
|
147
968
|
return stopped;
|
|
148
969
|
}
|
|
149
970
|
if ("kind" in decision && decision.kind === "skipped") {
|
|
@@ -155,8 +976,8 @@ export class AutoOrchestrator implements AutoOrchestrationModule {
|
|
|
155
976
|
this.status.phase = "running";
|
|
156
977
|
this.status.activeUnit = undefined;
|
|
157
978
|
this.bumpTransition();
|
|
158
|
-
|
|
159
|
-
|
|
979
|
+
this.journalTransition({ name: "advance-skipped", reason: skipped.reason });
|
|
980
|
+
this.postAdvanceRecord(skipped);
|
|
160
981
|
return skipped;
|
|
161
982
|
}
|
|
162
983
|
if (!("unitType" in decision)) {
|
|
@@ -166,37 +987,59 @@ export class AutoOrchestrator implements AutoOrchestrationModule {
|
|
|
166
987
|
action: decision.action,
|
|
167
988
|
stateSnapshot: reconciliation.stateSnapshot,
|
|
168
989
|
};
|
|
169
|
-
|
|
170
|
-
|
|
990
|
+
this.journalTransition({ name: "advance-blocked", reason: blocked.reason });
|
|
991
|
+
this.postAdvanceRecord(blocked);
|
|
171
992
|
return blocked;
|
|
172
993
|
}
|
|
173
994
|
|
|
174
|
-
const
|
|
995
|
+
const priorSliceBlocker = this.findPriorSliceCompletionBlocker(decision.unitType, decision.unitId);
|
|
996
|
+
if (priorSliceBlocker) {
|
|
997
|
+
this.clearPendingDispatch();
|
|
998
|
+
const blocked: AutoAdvanceResult = {
|
|
999
|
+
kind: "blocked",
|
|
1000
|
+
reason: priorSliceBlocker,
|
|
1001
|
+
action: "stop",
|
|
1002
|
+
stateSnapshot: reconciliation.stateSnapshot,
|
|
1003
|
+
};
|
|
1004
|
+
this.journalTransition({
|
|
1005
|
+
name: "advance-blocked",
|
|
1006
|
+
reason: blocked.reason,
|
|
1007
|
+
unitType: decision.unitType,
|
|
1008
|
+
unitId: decision.unitId,
|
|
1009
|
+
});
|
|
1010
|
+
this.postAdvanceRecord(blocked);
|
|
1011
|
+
return blocked;
|
|
1012
|
+
}
|
|
175
1013
|
|
|
176
|
-
// Record every dispatch decision in the
|
|
1014
|
+
// Record every dispatch decision in the history window before pre-flight
|
|
177
1015
|
// checks so the stuck-loop detector observes the full decision history
|
|
178
1016
|
// (including decisions that idempotency would otherwise short-circuit).
|
|
179
|
-
// The
|
|
180
|
-
this.
|
|
181
|
-
if (this.dispatchKeyWindow.length > STUCK_WINDOW_SIZE) {
|
|
182
|
-
this.dispatchKeyWindow.shift();
|
|
183
|
-
}
|
|
1017
|
+
// The window is capped at STUCK_WINDOW_SIZE and evicts oldest-first.
|
|
1018
|
+
const nextKey = this.dispatchHistory.recordDispatch(decision.unitType, decision.unitId);
|
|
184
1019
|
|
|
185
|
-
const matchingCount = this.
|
|
1020
|
+
const matchingCount = this.dispatchHistory.countMatching(nextKey);
|
|
186
1021
|
if (this.lastFinalizedUnitKey === nextKey) {
|
|
1022
|
+
// #442: the unit re-dispatched immediately after finalizing may have
|
|
1023
|
+
// actually completed on disk with a stale DB. Verify + recover before
|
|
1024
|
+
// hard-stopping (legacy graduated stuck-recovery parity).
|
|
1025
|
+
if (this.tryStuckArtifactRecovery(decision.unitType, decision.unitId)) {
|
|
1026
|
+
this.clearPendingDispatch();
|
|
1027
|
+
return this.stuckRecovered(decision, reconciliation.stateSnapshot);
|
|
1028
|
+
}
|
|
1029
|
+
this.clearPendingDispatch();
|
|
187
1030
|
const blocked: AutoAdvanceResult = {
|
|
188
1031
|
kind: "blocked",
|
|
189
1032
|
reason: `state did not advance after finalized ${decision.unitType} ${decision.unitId}`,
|
|
190
1033
|
action: "stop",
|
|
191
1034
|
stateSnapshot: reconciliation.stateSnapshot,
|
|
192
1035
|
};
|
|
193
|
-
|
|
1036
|
+
this.journalTransition({
|
|
194
1037
|
name: "advance-blocked",
|
|
195
1038
|
reason: blocked.reason,
|
|
196
1039
|
unitType: decision.unitType,
|
|
197
1040
|
unitId: decision.unitId,
|
|
198
1041
|
});
|
|
199
|
-
|
|
1042
|
+
this.postAdvanceRecord(blocked);
|
|
200
1043
|
return blocked;
|
|
201
1044
|
}
|
|
202
1045
|
|
|
@@ -207,70 +1050,90 @@ export class AutoOrchestrator implements AutoOrchestrationModule {
|
|
|
207
1050
|
// checks coexist: idempotency for the common immediate-repeat case,
|
|
208
1051
|
// stuck-loop for the saturated-window case.
|
|
209
1052
|
if (this.lastAdvanceKey === nextKey && matchingCount < STUCK_WINDOW_SIZE) {
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
1053
|
+
// Unit already active — benign no-op. Return skipped so the loop re-polls
|
|
1054
|
+
// without cancelling the in-flight unit (blocked+pause would force-cancel it).
|
|
1055
|
+
this.clearPendingDispatch();
|
|
1056
|
+
const skipped: AutoAdvanceResult = { kind: "skipped", reason: "idempotent advance: unit already active" };
|
|
1057
|
+
this.journalTransition({
|
|
1058
|
+
name: "advance-skipped",
|
|
1059
|
+
reason: skipped.reason,
|
|
214
1060
|
unitType: decision.unitType,
|
|
215
1061
|
unitId: decision.unitId,
|
|
216
1062
|
});
|
|
217
|
-
|
|
218
|
-
return
|
|
1063
|
+
this.postAdvanceRecord(skipped);
|
|
1064
|
+
return skipped;
|
|
219
1065
|
}
|
|
220
1066
|
|
|
221
|
-
// Stuck-loop detection: when the
|
|
222
|
-
// `nextKey` (count >= STUCK_WINDOW_SIZE), the
|
|
223
|
-
//
|
|
224
|
-
//
|
|
225
|
-
|
|
1067
|
+
// Stuck-loop detection: when the window is saturated with copies of
|
|
1068
|
+
// `nextKey` (count >= STUCK_WINDOW_SIZE), consult the Dispatch History
|
|
1069
|
+
// module's full detect-stuck rule set for the verdict instead of the old
|
|
1070
|
+
// bare saturation count. This keeps the saturation threshold (the window
|
|
1071
|
+
// deliberately records benign idempotent repeats, so earlier-firing
|
|
1072
|
+
// rules would false-positive on pause/resume re-advances) while gaining
|
|
1073
|
+
// retry-budget suppression and diagnosable rule reasons. A saturated
|
|
1074
|
+
// window with no verdict means the dispatch ledger says we are inside
|
|
1075
|
+
// the unit's retry-backoff budget — let the retry proceed.
|
|
1076
|
+
const stuckVerdict =
|
|
1077
|
+
matchingCount >= STUCK_WINDOW_SIZE ? this.dispatchHistory.detectStuck() : null;
|
|
1078
|
+
if (stuckVerdict) {
|
|
1079
|
+
// #442: before declaring a stuck loop, verify the unit didn't actually
|
|
1080
|
+
// complete on disk (stale DB) and recover if so — legacy graduated
|
|
1081
|
+
// stuck-recovery parity. Otherwise hard-stop with a diagnosable reason.
|
|
1082
|
+
if (this.tryStuckArtifactRecovery(decision.unitType, decision.unitId)) {
|
|
1083
|
+
this.clearPendingDispatch();
|
|
1084
|
+
return this.stuckRecovered(decision, reconciliation.stateSnapshot);
|
|
1085
|
+
}
|
|
1086
|
+
this.clearPendingDispatch();
|
|
226
1087
|
const blocked: AutoAdvanceResult = {
|
|
227
1088
|
kind: "blocked",
|
|
228
|
-
reason: `stuck-loop: ${
|
|
1089
|
+
reason: `stuck-loop: ${stuckVerdict.reason}`,
|
|
229
1090
|
action: "stop",
|
|
230
1091
|
};
|
|
231
|
-
|
|
1092
|
+
this.journalTransition({
|
|
232
1093
|
name: "advance-blocked",
|
|
233
1094
|
reason: blocked.reason,
|
|
234
1095
|
unitType: decision.unitType,
|
|
235
1096
|
unitId: decision.unitId,
|
|
236
1097
|
});
|
|
237
|
-
|
|
1098
|
+
this.postAdvanceRecord(blocked);
|
|
238
1099
|
return blocked;
|
|
239
1100
|
}
|
|
240
1101
|
|
|
241
|
-
const contract =
|
|
1102
|
+
const contract = this.compileUnitToolContract(decision.unitType);
|
|
242
1103
|
if (!contract.ok) {
|
|
1104
|
+
this.clearPendingDispatch();
|
|
243
1105
|
const blocked: AutoAdvanceResult = {
|
|
244
1106
|
kind: "blocked",
|
|
245
1107
|
reason: contract.reason,
|
|
246
1108
|
action: "pause",
|
|
247
1109
|
stateSnapshot: reconciliation.stateSnapshot,
|
|
248
1110
|
};
|
|
249
|
-
|
|
1111
|
+
this.journalTransition({
|
|
250
1112
|
name: "advance-blocked",
|
|
251
1113
|
reason: blocked.reason,
|
|
252
1114
|
unitType: decision.unitType,
|
|
253
1115
|
unitId: decision.unitId,
|
|
254
1116
|
});
|
|
255
|
-
|
|
1117
|
+
this.postAdvanceRecord(blocked);
|
|
256
1118
|
return blocked;
|
|
257
1119
|
}
|
|
258
1120
|
|
|
259
|
-
const worktree = await this.
|
|
1121
|
+
const worktree = await this.prepareWorktreeForUnit(decision.unitType, decision.unitId);
|
|
260
1122
|
if (!worktree.ok) {
|
|
1123
|
+
this.clearPendingDispatch();
|
|
261
1124
|
const blocked: AutoAdvanceResult = {
|
|
262
1125
|
kind: "blocked",
|
|
263
1126
|
reason: worktree.reason,
|
|
264
1127
|
action: "pause",
|
|
265
1128
|
stateSnapshot: reconciliation.stateSnapshot,
|
|
266
1129
|
};
|
|
267
|
-
|
|
1130
|
+
this.journalTransition({
|
|
268
1131
|
name: "advance-blocked",
|
|
269
1132
|
reason: blocked.reason,
|
|
270
1133
|
unitType: decision.unitType,
|
|
271
1134
|
unitId: decision.unitId,
|
|
272
1135
|
});
|
|
273
|
-
|
|
1136
|
+
this.postAdvanceRecord(blocked);
|
|
274
1137
|
return blocked;
|
|
275
1138
|
}
|
|
276
1139
|
|
|
@@ -279,23 +1142,23 @@ export class AutoOrchestrator implements AutoOrchestrationModule {
|
|
|
279
1142
|
this.lastAdvanceKey = nextKey;
|
|
280
1143
|
this.bumpTransition();
|
|
281
1144
|
|
|
282
|
-
|
|
1145
|
+
this.journalTransition({
|
|
283
1146
|
name: "advance",
|
|
284
1147
|
reason: decision.reason,
|
|
285
1148
|
unitType: decision.unitType,
|
|
286
1149
|
unitId: decision.unitId,
|
|
287
1150
|
});
|
|
288
|
-
|
|
1151
|
+
// syncAfterUnit was a no-op in the wired WorktreeAdapter.
|
|
289
1152
|
|
|
290
1153
|
const advanced: AutoAdvanceResult = {
|
|
291
1154
|
kind: "advanced",
|
|
292
1155
|
unit: { unitType: decision.unitType, unitId: decision.unitId },
|
|
293
1156
|
stateSnapshot: reconciliation.stateSnapshot,
|
|
294
1157
|
};
|
|
295
|
-
|
|
1158
|
+
this.postAdvanceRecord(advanced);
|
|
296
1159
|
return advanced;
|
|
297
1160
|
} catch (error) {
|
|
298
|
-
const recovery =
|
|
1161
|
+
const recovery = this.classifyAndRecover({
|
|
299
1162
|
error,
|
|
300
1163
|
unitType: this.status.activeUnit?.unitType,
|
|
301
1164
|
unitId: this.status.activeUnit?.unitId,
|
|
@@ -317,7 +1180,7 @@ export class AutoOrchestrator implements AutoOrchestrationModule {
|
|
|
317
1180
|
if (result.kind === "stopped") {
|
|
318
1181
|
this.lastAdvanceKey = null;
|
|
319
1182
|
this.lastFinalizedUnitKey = null;
|
|
320
|
-
this.
|
|
1183
|
+
this.dispatchHistory.clearOnRecovery();
|
|
321
1184
|
this.status.activeUnit = undefined;
|
|
322
1185
|
}
|
|
323
1186
|
this.bumpTransition();
|
|
@@ -327,28 +1190,41 @@ export class AutoOrchestrator implements AutoOrchestrationModule {
|
|
|
327
1190
|
: result.kind === "stopped"
|
|
328
1191
|
? "advance-stopped"
|
|
329
1192
|
: "advance-error";
|
|
330
|
-
|
|
1193
|
+
this.journalTransition({ name: journalName, reason: recovery.reason });
|
|
331
1194
|
|
|
332
1195
|
if (result.kind === "paused") {
|
|
333
|
-
|
|
1196
|
+
this.notifyLifecycle({ name: "pause", detail: recovery.reason });
|
|
334
1197
|
} else if (result.kind === "stopped") {
|
|
335
|
-
|
|
1198
|
+
this.notifyLifecycle({ name: "stopped", detail: recovery.reason });
|
|
336
1199
|
} else if (result.kind === "error") {
|
|
337
|
-
|
|
1200
|
+
this.notifyLifecycle({ name: "error", detail: recovery.reason });
|
|
338
1201
|
}
|
|
339
|
-
|
|
1202
|
+
this.postAdvanceRecord(result);
|
|
340
1203
|
return result;
|
|
1204
|
+
} finally {
|
|
1205
|
+
stopAdvanceTimer();
|
|
341
1206
|
}
|
|
342
1207
|
}
|
|
343
1208
|
|
|
344
1209
|
public async resume(): Promise<AutoAdvanceResult> {
|
|
345
1210
|
this.lastAdvanceKey = null;
|
|
346
1211
|
this.lastFinalizedUnitKey = null;
|
|
347
|
-
|
|
1212
|
+
// Preserve the dispatch-history window across an in-process resume so
|
|
1213
|
+
// stuck-loop detection accumulates across pause/resume cycles rather than
|
|
1214
|
+
// resetting each time (#572 regression). When the window is empty (fresh
|
|
1215
|
+
// orchestrator resuming a prior session), rehydrate it from the DB
|
|
1216
|
+
// dispatch ledger so cross-session re-dispatch loops are detected (#482).
|
|
1217
|
+
if (this.dispatchHistory.getRecentWindow().length === 0) {
|
|
1218
|
+
this.dispatchHistory.rehydrate();
|
|
1219
|
+
}
|
|
1220
|
+
this.lastStuckRecoveryKey = null;
|
|
1221
|
+
// ADR-030: drop the prior "from" — the first advance after resume has no
|
|
1222
|
+
// edge to assert (avoids a false illegal-edge across the pause boundary).
|
|
1223
|
+
this.lastDerivedPhase = null;
|
|
348
1224
|
this.status.phase = "running";
|
|
349
1225
|
this.bumpTransition();
|
|
350
|
-
|
|
351
|
-
|
|
1226
|
+
this.journalTransition({ name: "resume" });
|
|
1227
|
+
this.notifyLifecycle({ name: "resume" });
|
|
352
1228
|
return { kind: "resumed" };
|
|
353
1229
|
}
|
|
354
1230
|
|
|
@@ -356,15 +1232,21 @@ export class AutoOrchestrator implements AutoOrchestrationModule {
|
|
|
356
1232
|
if (this.status.phase === "stopped") {
|
|
357
1233
|
return { kind: "stopped", reason };
|
|
358
1234
|
}
|
|
359
|
-
|
|
1235
|
+
// cleanupOnStop was a no-op in the wired WorktreeAdapter.
|
|
360
1236
|
this.status.phase = "stopped";
|
|
361
1237
|
this.status.activeUnit = undefined;
|
|
362
1238
|
this.lastAdvanceKey = null;
|
|
363
1239
|
this.lastFinalizedUnitKey = null;
|
|
364
|
-
this.
|
|
1240
|
+
this.lastDerivedPhase = null;
|
|
1241
|
+
// Preserve the dispatch-history window on pause so stuck-loop detection
|
|
1242
|
+
// accumulates across pause/resume cycles. Only clear on a hard stop.
|
|
1243
|
+
if (reason !== "pause") {
|
|
1244
|
+
this.dispatchHistory.clearOnRecovery();
|
|
1245
|
+
}
|
|
1246
|
+
this.lastStuckRecoveryKey = null;
|
|
365
1247
|
this.bumpTransition();
|
|
366
|
-
|
|
367
|
-
|
|
1248
|
+
this.journalTransition({ name: "stop", reason });
|
|
1249
|
+
this.notifyLifecycle({ name: "stop", detail: reason });
|
|
368
1250
|
return { kind: "stopped", reason };
|
|
369
1251
|
}
|
|
370
1252
|
|
|
@@ -373,17 +1255,19 @@ export class AutoOrchestrator implements AutoOrchestrationModule {
|
|
|
373
1255
|
}
|
|
374
1256
|
|
|
375
1257
|
public async completeActiveUnit(unit: { unitType: string; unitId: string }): Promise<void> {
|
|
376
|
-
const unitKey =
|
|
1258
|
+
const unitKey = buildDispatchKey(unit.unitType, unit.unitId);
|
|
377
1259
|
const activeUnitKey = this.status.activeUnit
|
|
378
|
-
?
|
|
1260
|
+
? buildDispatchKey(this.status.activeUnit.unitType, this.status.activeUnit.unitId)
|
|
379
1261
|
: null;
|
|
380
1262
|
if (activeUnitKey !== unitKey) return;
|
|
381
1263
|
|
|
382
1264
|
this.status.activeUnit = undefined;
|
|
383
1265
|
this.lastAdvanceKey = null;
|
|
384
1266
|
this.lastFinalizedUnitKey = unitKey;
|
|
1267
|
+
// Genuine progress — re-enable graduated stuck recovery for future episodes.
|
|
1268
|
+
this.lastStuckRecoveryKey = null;
|
|
385
1269
|
this.bumpTransition();
|
|
386
|
-
|
|
1270
|
+
this.journalTransition({
|
|
387
1271
|
name: "unit-finalized",
|
|
388
1272
|
unitType: unit.unitType,
|
|
389
1273
|
unitId: unit.unitId,
|
|
@@ -391,9 +1275,9 @@ export class AutoOrchestrator implements AutoOrchestrationModule {
|
|
|
391
1275
|
}
|
|
392
1276
|
|
|
393
1277
|
public async retryActiveUnit(unit: { unitType: string; unitId: string }): Promise<void> {
|
|
394
|
-
const unitKey =
|
|
1278
|
+
const unitKey = buildDispatchKey(unit.unitType, unit.unitId);
|
|
395
1279
|
const activeUnitKey = this.status.activeUnit
|
|
396
|
-
?
|
|
1280
|
+
? buildDispatchKey(this.status.activeUnit.unitType, this.status.activeUnit.unitId)
|
|
397
1281
|
: null;
|
|
398
1282
|
if (activeUnitKey !== unitKey && this.lastFinalizedUnitKey !== unitKey) return;
|
|
399
1283
|
|
|
@@ -403,7 +1287,7 @@ export class AutoOrchestrator implements AutoOrchestrationModule {
|
|
|
403
1287
|
this.lastAdvanceKey = null;
|
|
404
1288
|
this.lastFinalizedUnitKey = null;
|
|
405
1289
|
this.bumpTransition();
|
|
406
|
-
|
|
1290
|
+
this.journalTransition({
|
|
407
1291
|
name: "unit-retry",
|
|
408
1292
|
reason: "finalize-retry",
|
|
409
1293
|
unitType: unit.unitType,
|
|
@@ -417,6 +1301,47 @@ export class AutoOrchestrator implements AutoOrchestrationModule {
|
|
|
417
1301
|
}
|
|
418
1302
|
}
|
|
419
1303
|
|
|
420
|
-
|
|
421
|
-
|
|
1304
|
+
function isUsableLiveOrchestratorBasePath(basePath: string): boolean {
|
|
1305
|
+
if (!basePath || !existsSync(basePath)) return false;
|
|
1306
|
+
if (!detectWorktreeName(basePath)) return true;
|
|
1307
|
+
|
|
1308
|
+
try {
|
|
1309
|
+
return readFileSync(join(basePath, ".git"), "utf8").trim().startsWith("gitdir: ");
|
|
1310
|
+
} catch {
|
|
1311
|
+
return false;
|
|
1312
|
+
}
|
|
1313
|
+
}
|
|
1314
|
+
|
|
1315
|
+
/**
|
|
1316
|
+
* Resolve the base path the live orchestrator should dispatch from, falling
|
|
1317
|
+
* back to the project root when the captured worktree path has been removed
|
|
1318
|
+
* (e.g. after milestone-merge cleanup). Exported for the closeout-regression
|
|
1319
|
+
* tests and reused by the orchestrator's getLiveDispatchBasePath.
|
|
1320
|
+
*/
|
|
1321
|
+
export function resolveLiveOrchestratorBasePath(input: {
|
|
1322
|
+
capturedBasePath: string;
|
|
1323
|
+
runtimeBasePath: string;
|
|
1324
|
+
sessionBasePath?: string | null;
|
|
1325
|
+
originalBasePath?: string | null;
|
|
1326
|
+
}): string {
|
|
1327
|
+
const primary = input.sessionBasePath || input.capturedBasePath;
|
|
1328
|
+
if (isUsableLiveOrchestratorBasePath(primary)) return primary;
|
|
1329
|
+
|
|
1330
|
+
const fallbacks = [
|
|
1331
|
+
input.originalBasePath,
|
|
1332
|
+
input.runtimeBasePath,
|
|
1333
|
+
resolveProjectRoot(input.capturedBasePath),
|
|
1334
|
+
];
|
|
1335
|
+
|
|
1336
|
+
for (const candidate of fallbacks) {
|
|
1337
|
+
if (candidate && isUsableLiveOrchestratorBasePath(candidate)) {
|
|
1338
|
+
return candidate;
|
|
1339
|
+
}
|
|
1340
|
+
}
|
|
1341
|
+
|
|
1342
|
+
return input.runtimeBasePath || input.capturedBasePath;
|
|
1343
|
+
}
|
|
1344
|
+
|
|
1345
|
+
export function createAutoOrchestrator(context: OrchestratorContext): AutoOrchestrationModule {
|
|
1346
|
+
return new AutoOrchestrator(context);
|
|
422
1347
|
}
|