gsd-pi 2.80.0-dev.c5f2443b3 → 2.80.0-dev.e51d2c88c
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/README.md +4 -2
- package/dist/resources/.managed-resources-content-hash +1 -1
- package/dist/resources/GSD-WORKFLOW.md +2 -2
- package/dist/resources/extensions/github-sync/templates.js +39 -8
- package/dist/resources/extensions/gsd/auto/loop.js +48 -10
- package/dist/resources/extensions/gsd/auto/phases.js +66 -45
- package/dist/resources/extensions/gsd/auto/resolve.js +17 -0
- package/dist/resources/extensions/gsd/auto/run-unit.js +32 -16
- package/dist/resources/extensions/gsd/auto-dashboard.js +51 -15
- package/dist/resources/extensions/gsd/auto-dispatch.js +10 -0
- package/dist/resources/extensions/gsd/auto-post-unit.js +10 -10
- package/dist/resources/extensions/gsd/auto-prompts.js +124 -2
- package/dist/resources/extensions/gsd/auto-recovery.js +197 -9
- package/dist/resources/extensions/gsd/auto-start.js +2 -3
- package/dist/resources/extensions/gsd/auto-supervisor.js +8 -1
- package/dist/resources/extensions/gsd/auto-timeout-recovery.js +2 -2
- package/dist/resources/extensions/gsd/auto.js +75 -5
- package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +36 -3
- package/dist/resources/extensions/gsd/bootstrap/exec-tools.js +27 -20
- package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +32 -1
- package/dist/resources/extensions/gsd/bootstrap/write-gate.js +129 -1
- package/dist/resources/extensions/gsd/clean-root-preflight.js +42 -4
- package/dist/resources/extensions/gsd/commands/dispatcher.js +5 -0
- package/dist/resources/extensions/gsd/commands-extract-learnings.js +17 -12
- package/dist/resources/extensions/gsd/context-budget.js +37 -2
- package/dist/resources/extensions/gsd/crash-recovery.js +56 -10
- package/dist/resources/extensions/gsd/custom-workflow-engine.js +22 -2
- package/dist/resources/extensions/gsd/db/unit-dispatches.js +39 -0
- package/dist/resources/extensions/gsd/db-base-schema.js +18 -2
- package/dist/resources/extensions/gsd/db-migration-steps.js +22 -0
- package/dist/resources/extensions/gsd/detection.js +106 -0
- package/dist/resources/extensions/gsd/graph.js +9 -3
- package/dist/resources/extensions/gsd/gsd-db.js +146 -13
- package/dist/resources/extensions/gsd/guided-flow.js +82 -16
- package/dist/resources/extensions/gsd/memory-store.js +69 -12
- package/dist/resources/extensions/gsd/migrate/command.js +40 -1
- package/dist/resources/extensions/gsd/migration-auto-check.js +87 -0
- package/dist/resources/extensions/gsd/planning-path-scope.js +26 -0
- package/dist/resources/extensions/gsd/pr-evidence.js +57 -16
- package/dist/resources/extensions/gsd/prompt-loader.js +28 -2
- package/dist/resources/extensions/gsd/prompts/complete-milestone.md +19 -19
- package/dist/resources/extensions/gsd/prompts/parallel-research-slices.md +1 -1
- package/dist/resources/extensions/gsd/prompts/plan-milestone.md +3 -1
- package/dist/resources/extensions/gsd/prompts/plan-slice.md +1 -1
- package/dist/resources/extensions/gsd/prompts/quick-task.md +1 -5
- package/dist/resources/extensions/gsd/prompts/validate-milestone.md +2 -2
- package/dist/resources/extensions/gsd/quick.js +34 -2
- package/dist/resources/extensions/gsd/safety/evidence-collector.js +10 -2
- package/dist/resources/extensions/gsd/tools/context-mode-tool-result.js +15 -0
- package/dist/resources/extensions/gsd/tools/exec-search-tool.js +5 -0
- package/dist/resources/extensions/gsd/tools/exec-tool.js +3 -15
- package/dist/resources/extensions/gsd/tools/memory-tools.js +1 -0
- package/dist/resources/extensions/gsd/tools/plan-slice.js +9 -0
- package/dist/resources/extensions/gsd/tools/plan-task.js +9 -0
- package/dist/resources/extensions/gsd/tools/resume-tool.js +5 -0
- package/dist/resources/extensions/gsd/tools/workflow-tool-executors.js +1 -1
- package/dist/resources/extensions/gsd/unit-context-composer.js +12 -3
- package/dist/resources/extensions/gsd/unit-runtime.js +22 -0
- package/dist/resources/extensions/gsd/working-output-messages.js +64 -0
- package/dist/resources/extensions/gsd/worktree-manager.js +16 -14
- package/dist/tsconfig.extensions.tsbuildinfo +1 -1
- package/dist/web/standalone/.next/BUILD_ID +1 -1
- package/dist/web/standalone/.next/app-path-routes-manifest.json +11 -11
- 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 +1 -1
- 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/onboarding/route.js +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 +11 -11
- package/dist/web/standalone/.next/server/chunks/6897.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/{8336.6f6f30e410419aff.js → 8336.631939fb583761fa.js} +1 -1
- package/dist/web/standalone/.next/static/chunks/{webpack-d82dbee6356c1733.js → webpack-0481f1221120a7c6.js} +1 -1
- package/package.json +12 -8
- package/packages/contracts/package.json +1 -1
- package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
- package/packages/mcp-server/dist/workflow-tools.js +22 -17
- package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
- package/packages/mcp-server/src/workflow-tools.test.ts +75 -2
- package/packages/mcp-server/src/workflow-tools.ts +30 -16
- package/packages/mcp-server/tsconfig.tsbuildinfo +1 -1
- package/packages/native/tsconfig.tsbuildinfo +1 -1
- package/packages/pi-ai/dist/models/fake-model.d.ts +12 -0
- package/packages/pi-ai/dist/models/fake-model.d.ts.map +1 -0
- package/packages/pi-ai/dist/models/fake-model.js +27 -0
- package/packages/pi-ai/dist/models/fake-model.js.map +1 -0
- package/packages/pi-ai/dist/models/index.d.ts.map +1 -1
- package/packages/pi-ai/dist/models/index.js +8 -0
- package/packages/pi-ai/dist/models/index.js.map +1 -1
- package/packages/pi-ai/dist/providers/fake.d.ts +42 -0
- package/packages/pi-ai/dist/providers/fake.d.ts.map +1 -0
- package/packages/pi-ai/dist/providers/fake.js +319 -0
- package/packages/pi-ai/dist/providers/fake.js.map +1 -0
- package/packages/pi-ai/dist/providers/register-builtins.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/register-builtins.js +24 -0
- package/packages/pi-ai/dist/providers/register-builtins.js.map +1 -1
- package/packages/pi-ai/src/models/fake-model.ts +30 -0
- package/packages/pi-ai/src/models/index.ts +9 -0
- package/packages/pi-ai/src/providers/fake.ts +376 -0
- package/packages/pi-ai/src/providers/register-builtins.ts +23 -0
- package/packages/pi-ai/tsconfig.tsbuildinfo +1 -1
- package/packages/pi-coding-agent/dist/core/agent-session-abort-order.test.js +32 -0
- package/packages/pi-coding-agent/dist/core/agent-session-abort-order.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/agent-session.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/agent-session.js +8 -0
- package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/chat-controller-ordering.test.js +76 -0
- package/packages/pi-coding-agent/dist/core/chat-controller-ordering.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/compaction/compaction.d.ts +11 -0
- package/packages/pi-coding-agent/dist/core/compaction/compaction.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/compaction/compaction.js +9 -0
- package/packages/pi-coding-agent/dist/core/compaction/compaction.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/compaction-threshold.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/compaction-threshold.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/compaction-threshold.test.js +103 -0
- package/packages/pi-coding-agent/dist/core/compaction-threshold.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/db-snapshot.d.ts +15 -0
- package/packages/pi-coding-agent/dist/core/db-snapshot.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/db-snapshot.js +66 -0
- package/packages/pi-coding-agent/dist/core/db-snapshot.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/db-snapshot.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/db-snapshot.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/db-snapshot.test.js +24 -0
- package/packages/pi-coding-agent/dist/core/db-snapshot.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/extensions/runner.d.ts +3 -0
- package/packages/pi-coding-agent/dist/core/extensions/runner.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/runner.js +17 -1
- package/packages/pi-coding-agent/dist/core/extensions/runner.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/runner.test.js +99 -0
- package/packages/pi-coding-agent/dist/core/extensions/runner.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/types.d.ts +7 -0
- package/packages/pi-coding-agent/dist/core/extensions/types.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/types.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/model-registry.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/model-registry.js +5 -0
- package/packages/pi-coding-agent/dist/core/model-registry.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/settings-manager.d.ts +24 -0
- package/packages/pi-coding-agent/dist/core/settings-manager.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/settings-manager.js +33 -0
- package/packages/pi-coding-agent/dist/core/settings-manager.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/slash-commands.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/slash-commands.js +1 -0
- package/packages/pi-coding-agent/dist/core/slash-commands.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/chat-frame-compaction-tone.test.js +6 -4
- package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/chat-frame-compaction-tone.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-execution.test.js +54 -15
- package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-execution.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/adaptive-layout.d.ts +26 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/adaptive-layout.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/adaptive-layout.js +112 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/adaptive-layout.js.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/adaptive-layout.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/adaptive-layout.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/adaptive-layout.test.js +51 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/adaptive-layout.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/chat-frame.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/chat-frame.js +10 -9
- package/packages/pi-coding-agent/dist/modes/interactive/components/chat-frame.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.d.ts +3 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.js +11 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-card-cleanup-and-success-runtime.test.js +7 -6
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-card-cleanup-and-success-runtime.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts +17 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js +109 -17
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js +69 -2
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.test.js +93 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.test.js +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-state.d.ts +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-state.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-state.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts +3 -0
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js +26 -0
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.js +20 -0
- package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.test.js +79 -0
- package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/theme/theme-schema.d.ts +12 -0
- package/packages/pi-coding-agent/dist/modes/interactive/theme/theme-schema.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/theme/theme-schema.js +13 -0
- package/packages/pi-coding-agent/dist/modes/interactive/theme/theme-schema.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/theme/theme.d.ts +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/theme/theme.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/theme/theme.js +18 -1
- package/packages/pi-coding-agent/dist/modes/interactive/theme/theme.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/theme/themes.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/theme/themes.js +36 -27
- package/packages/pi-coding-agent/dist/modes/interactive/theme/themes.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/tui-mode.d.ts +11 -0
- package/packages/pi-coding-agent/dist/modes/interactive/tui-mode.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/tui-mode.js +18 -0
- package/packages/pi-coding-agent/dist/modes/interactive/tui-mode.js.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/tui-mode.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/modes/interactive/tui-mode.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/tui-mode.test.js +48 -0
- package/packages/pi-coding-agent/dist/modes/interactive/tui-mode.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/resources/extensions/memory/storage-safety-guard.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/resources/extensions/memory/storage-safety-guard.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/resources/extensions/memory/storage-safety-guard.test.js +10 -0
- package/packages/pi-coding-agent/dist/resources/extensions/memory/storage-safety-guard.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/resources/extensions/memory/storage.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/resources/extensions/memory/storage.js +3 -2
- package/packages/pi-coding-agent/dist/resources/extensions/memory/storage.js.map +1 -1
- package/packages/pi-coding-agent/src/core/agent-session-abort-order.test.ts +36 -0
- package/packages/pi-coding-agent/src/core/agent-session.ts +8 -0
- package/packages/pi-coding-agent/src/core/chat-controller-ordering.test.ts +89 -0
- package/packages/pi-coding-agent/src/core/compaction/compaction.ts +18 -0
- package/packages/pi-coding-agent/src/core/compaction-threshold.test.ts +121 -0
- package/packages/pi-coding-agent/src/core/db-snapshot.test.ts +32 -0
- package/packages/pi-coding-agent/src/core/db-snapshot.ts +66 -0
- package/packages/pi-coding-agent/src/core/extensions/runner.test.ts +110 -0
- package/packages/pi-coding-agent/src/core/extensions/runner.ts +19 -1
- package/packages/pi-coding-agent/src/core/extensions/types.ts +7 -0
- package/packages/pi-coding-agent/src/core/model-registry.ts +4 -0
- package/packages/pi-coding-agent/src/core/settings-manager.ts +51 -1
- package/packages/pi-coding-agent/src/core/slash-commands.ts +1 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/chat-frame-compaction-tone.test.ts +7 -5
- package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/tool-execution.test.ts +78 -15
- package/packages/pi-coding-agent/src/modes/interactive/components/adaptive-layout.test.ts +59 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/adaptive-layout.ts +160 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/assistant-message.ts +1 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/chat-frame.ts +10 -9
- package/packages/pi-coding-agent/src/modes/interactive/components/settings-selector.ts +15 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/tool-card-cleanup-and-success-runtime.test.ts +10 -9
- package/packages/pi-coding-agent/src/modes/interactive/components/tool-execution.ts +122 -17
- package/packages/pi-coding-agent/src/modes/interactive/controllers/chat-controller.test.ts +99 -1
- package/packages/pi-coding-agent/src/modes/interactive/controllers/chat-controller.ts +92 -3
- package/packages/pi-coding-agent/src/modes/interactive/controllers/input-controller.test.ts +1 -0
- package/packages/pi-coding-agent/src/modes/interactive/interactive-mode-state.ts +1 -1
- package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +28 -0
- package/packages/pi-coding-agent/src/modes/interactive/slash-command-handlers.test.ts +95 -0
- package/packages/pi-coding-agent/src/modes/interactive/slash-command-handlers.ts +24 -1
- package/packages/pi-coding-agent/src/modes/interactive/theme/theme-schema.ts +13 -0
- package/packages/pi-coding-agent/src/modes/interactive/theme/theme.ts +32 -2
- package/packages/pi-coding-agent/src/modes/interactive/theme/themes.ts +36 -27
- package/packages/pi-coding-agent/src/modes/interactive/tui-mode.test.ts +65 -0
- package/packages/pi-coding-agent/src/modes/interactive/tui-mode.ts +29 -0
- package/packages/pi-coding-agent/src/resources/extensions/memory/storage-safety-guard.test.ts +14 -0
- package/packages/pi-coding-agent/src/resources/extensions/memory/storage.ts +3 -2
- package/packages/pi-coding-agent/tsconfig.tsbuildinfo +1 -1
- package/packages/pi-tui/dist/__tests__/style.test.d.ts +2 -0
- package/packages/pi-tui/dist/__tests__/style.test.d.ts.map +1 -0
- package/packages/pi-tui/dist/__tests__/style.test.js +63 -0
- package/packages/pi-tui/dist/__tests__/style.test.js.map +1 -0
- package/packages/pi-tui/dist/__tests__/tui.test.js +24 -3
- package/packages/pi-tui/dist/__tests__/tui.test.js.map +1 -1
- package/packages/pi-tui/dist/index.d.ts +1 -0
- package/packages/pi-tui/dist/index.d.ts.map +1 -1
- package/packages/pi-tui/dist/index.js +2 -0
- package/packages/pi-tui/dist/index.js.map +1 -1
- package/packages/pi-tui/dist/style.d.ts +41 -0
- package/packages/pi-tui/dist/style.d.ts.map +1 -0
- package/packages/pi-tui/dist/style.js +158 -0
- package/packages/pi-tui/dist/style.js.map +1 -0
- package/packages/pi-tui/dist/tui.d.ts +0 -1
- package/packages/pi-tui/dist/tui.d.ts.map +1 -1
- package/packages/pi-tui/dist/tui.js +21 -16
- package/packages/pi-tui/dist/tui.js.map +1 -1
- package/packages/pi-tui/src/__tests__/style.test.ts +76 -0
- package/packages/pi-tui/src/__tests__/tui.test.ts +29 -3
- package/packages/pi-tui/src/index.ts +9 -0
- package/packages/pi-tui/src/style.ts +225 -0
- package/packages/pi-tui/src/tui.ts +23 -16
- package/packages/pi-tui/tsconfig.tsbuildinfo +1 -1
- package/pkg/dist/modes/interactive/theme/theme-schema.d.ts +12 -0
- package/pkg/dist/modes/interactive/theme/theme-schema.d.ts.map +1 -1
- package/pkg/dist/modes/interactive/theme/theme-schema.js +13 -0
- package/pkg/dist/modes/interactive/theme/theme-schema.js.map +1 -1
- package/pkg/dist/modes/interactive/theme/theme.d.ts +1 -1
- package/pkg/dist/modes/interactive/theme/theme.d.ts.map +1 -1
- package/pkg/dist/modes/interactive/theme/theme.js +18 -1
- package/pkg/dist/modes/interactive/theme/theme.js.map +1 -1
- package/pkg/dist/modes/interactive/theme/themes.d.ts.map +1 -1
- package/pkg/dist/modes/interactive/theme/themes.js +36 -27
- package/pkg/dist/modes/interactive/theme/themes.js.map +1 -1
- package/src/resources/GSD-WORKFLOW.md +2 -2
- package/src/resources/extensions/github-sync/templates.ts +38 -8
- package/src/resources/extensions/github-sync/tests/inline-code.test.ts +66 -0
- package/src/resources/extensions/gsd/auto/loop-deps.ts +1 -0
- package/src/resources/extensions/gsd/auto/loop.ts +67 -18
- package/src/resources/extensions/gsd/auto/phases.ts +77 -48
- package/src/resources/extensions/gsd/auto/resolve.ts +23 -1
- package/src/resources/extensions/gsd/auto/run-unit.ts +42 -15
- package/src/resources/extensions/gsd/auto-dashboard.ts +57 -8
- package/src/resources/extensions/gsd/auto-dispatch.ts +17 -0
- package/src/resources/extensions/gsd/auto-post-unit.ts +10 -10
- package/src/resources/extensions/gsd/auto-prompts.ts +133 -2
- package/src/resources/extensions/gsd/auto-recovery.ts +207 -7
- package/src/resources/extensions/gsd/auto-start.ts +7 -6
- package/src/resources/extensions/gsd/auto-supervisor.ts +7 -0
- package/src/resources/extensions/gsd/auto-timeout-recovery.ts +2 -2
- package/src/resources/extensions/gsd/auto.ts +90 -4
- package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +37 -2
- package/src/resources/extensions/gsd/bootstrap/exec-tools.ts +27 -19
- package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +39 -1
- package/src/resources/extensions/gsd/bootstrap/write-gate.ts +135 -1
- package/src/resources/extensions/gsd/clean-root-preflight.ts +41 -3
- package/src/resources/extensions/gsd/commands/dispatcher.ts +6 -0
- package/src/resources/extensions/gsd/commands-extract-learnings.ts +17 -12
- package/src/resources/extensions/gsd/context-budget.ts +44 -2
- package/src/resources/extensions/gsd/crash-recovery.ts +67 -10
- package/src/resources/extensions/gsd/custom-workflow-engine.ts +24 -1
- package/src/resources/extensions/gsd/db/unit-dispatches.ts +41 -0
- package/src/resources/extensions/gsd/db-base-schema.ts +19 -2
- package/src/resources/extensions/gsd/db-migration-steps.ts +25 -0
- package/src/resources/extensions/gsd/detection.ts +128 -0
- package/src/resources/extensions/gsd/graph.ts +12 -5
- package/src/resources/extensions/gsd/gsd-db.ts +168 -13
- package/src/resources/extensions/gsd/guided-flow.ts +98 -16
- package/src/resources/extensions/gsd/memory-store.ts +77 -12
- package/src/resources/extensions/gsd/migrate/command.ts +47 -1
- package/src/resources/extensions/gsd/migration-auto-check.ts +129 -0
- package/src/resources/extensions/gsd/planning-path-scope.ts +35 -0
- package/src/resources/extensions/gsd/pr-evidence.ts +63 -5
- package/src/resources/extensions/gsd/preferences-types.ts +1 -1
- package/src/resources/extensions/gsd/prompt-loader.ts +27 -2
- package/src/resources/extensions/gsd/prompts/complete-milestone.md +19 -19
- package/src/resources/extensions/gsd/prompts/parallel-research-slices.md +1 -1
- package/src/resources/extensions/gsd/prompts/plan-milestone.md +3 -1
- package/src/resources/extensions/gsd/prompts/plan-slice.md +1 -1
- package/src/resources/extensions/gsd/prompts/quick-task.md +1 -5
- package/src/resources/extensions/gsd/prompts/validate-milestone.md +2 -2
- package/src/resources/extensions/gsd/quick.ts +37 -2
- package/src/resources/extensions/gsd/safety/evidence-collector.ts +11 -2
- package/src/resources/extensions/gsd/tests/auto-abort-pause-regression.test.ts +7 -1
- package/src/resources/extensions/gsd/tests/auto-dashboard.test.ts +33 -0
- package/src/resources/extensions/gsd/tests/auto-loop.test.ts +155 -5
- package/src/resources/extensions/gsd/tests/auto-phases-lifecycle.test.ts +56 -13
- package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +184 -2
- package/src/resources/extensions/gsd/tests/clean-root-preflight.test.ts +88 -2
- package/src/resources/extensions/gsd/tests/commands-extract-learnings.test.ts +9 -0
- package/src/resources/extensions/gsd/tests/compaction-snapshot.test.ts +14 -1
- package/src/resources/extensions/gsd/tests/context-budget.test.ts +10 -1
- package/src/resources/extensions/gsd/tests/crash-handler-secondary.test.ts +55 -0
- package/src/resources/extensions/gsd/tests/crash-recovery-via-db.test.ts +22 -0
- package/src/resources/extensions/gsd/tests/custom-engine-loop-integration.test.ts +112 -6
- package/src/resources/extensions/gsd/tests/custom-workflow-engine.test.ts +40 -2
- package/src/resources/extensions/gsd/tests/db-migration-steps.integration.test.ts +428 -0
- package/src/resources/extensions/gsd/tests/db-schema-metadata.test.ts +2 -2
- package/src/resources/extensions/gsd/tests/detection.test.ts +140 -0
- package/src/resources/extensions/gsd/tests/dispatch-rule-coverage.test.ts +313 -0
- package/src/resources/extensions/gsd/tests/exec-history.test.ts +15 -0
- package/src/resources/extensions/gsd/tests/exec-sandbox.test.ts +65 -0
- package/src/resources/extensions/gsd/tests/fixtures/pr-body/commands-ship-basic.md +52 -0
- package/src/resources/extensions/gsd/tests/fixtures/pr-body/commands-ship-empty-optionals.md +42 -0
- package/src/resources/extensions/gsd/tests/fixtures/pr-body/swarm-lane-no-blockers.md +55 -0
- package/src/resources/extensions/gsd/tests/fixtures/pr-body/swarm-lane-with-blockers.md +60 -0
- package/src/resources/extensions/gsd/tests/graph-operations.test.ts +10 -0
- package/src/resources/extensions/gsd/tests/gsd-db.test.ts +44 -0
- package/src/resources/extensions/gsd/tests/has-pending-deep-stage.test.ts +33 -1
- package/src/resources/extensions/gsd/tests/journal-integration.test.ts +234 -0
- package/src/resources/extensions/gsd/tests/memory-decay-factor.test.ts +90 -0
- package/src/resources/extensions/gsd/tests/migrate-writer-integration.test.ts +48 -0
- package/src/resources/extensions/gsd/tests/migration-auto-check.test.ts +127 -0
- package/src/resources/extensions/gsd/tests/plan-slice.test.ts +50 -0
- package/src/resources/extensions/gsd/tests/plan-task.test.ts +21 -0
- package/src/resources/extensions/gsd/tests/pr-evidence-equivalence.test.ts +102 -0
- package/src/resources/extensions/gsd/tests/pr-evidence-hardening.test.ts +165 -0
- package/src/resources/extensions/gsd/tests/prompt-path-audit.test.ts +40 -0
- package/src/resources/extensions/gsd/tests/prompt-step-ordering.test.ts +19 -0
- package/src/resources/extensions/gsd/tests/quick-external-gsd.test.ts +40 -0
- package/src/resources/extensions/gsd/tests/right-sized-workflow-prompts.test.ts +192 -0
- package/src/resources/extensions/gsd/tests/safety-harness-false-positives.test.ts +29 -0
- package/src/resources/extensions/gsd/tests/schema-v27-v28-sequence.test.ts +156 -0
- package/src/resources/extensions/gsd/tests/signal-handlers.test.ts +27 -0
- package/src/resources/extensions/gsd/tests/smart-entry-complete.test.ts +38 -0
- package/src/resources/extensions/gsd/tests/stalled-tool-recovery.test.ts +49 -1
- package/src/resources/extensions/gsd/tests/start-auto-detached.test.ts +101 -2
- package/src/resources/extensions/gsd/tests/status-db-open.test.ts +9 -0
- package/src/resources/extensions/gsd/tests/unit-context-composer.test.ts +136 -4
- package/src/resources/extensions/gsd/tests/unit-dispatches.test.ts +30 -0
- package/src/resources/extensions/gsd/tests/unit-runtime.test.ts +37 -0
- package/src/resources/extensions/gsd/tests/uok-plan-v2-wiring.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/workflow-tool-executors.test.ts +3 -0
- package/src/resources/extensions/gsd/tests/working-output-messages.test.ts +93 -0
- package/src/resources/extensions/gsd/tests/worktree-health-dispatch.test.ts +37 -6
- package/src/resources/extensions/gsd/tests/worktree-manager.test.ts +7 -0
- package/src/resources/extensions/gsd/tests/worktree-nested-git-safety.test.ts +9 -2
- package/src/resources/extensions/gsd/tests/worktree-write-gate.test.ts +179 -0
- package/src/resources/extensions/gsd/tools/context-mode-tool-result.ts +25 -0
- package/src/resources/extensions/gsd/tools/exec-search-tool.ts +7 -7
- package/src/resources/extensions/gsd/tools/exec-tool.ts +4 -23
- package/src/resources/extensions/gsd/tools/memory-tools.ts +1 -0
- package/src/resources/extensions/gsd/tools/plan-slice.ts +13 -0
- package/src/resources/extensions/gsd/tools/plan-task.ts +10 -0
- package/src/resources/extensions/gsd/tools/resume-tool.ts +7 -7
- package/src/resources/extensions/gsd/tools/workflow-tool-executors.ts +1 -1
- package/src/resources/extensions/gsd/unit-context-composer.ts +19 -4
- package/src/resources/extensions/gsd/unit-runtime.ts +25 -0
- package/src/resources/extensions/gsd/working-output-messages.ts +120 -0
- package/src/resources/extensions/gsd/worktree-manager.ts +15 -4
- package/packages/contracts/tsconfig.tsbuildinfo +0 -1
- /package/dist/web/standalone/.next/static/{bQDK5_LtkGVS64AirQgQG → 8F5YpnZNBaooIWGF4GBV3}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{bQDK5_LtkGVS64AirQgQG → 8F5YpnZNBaooIWGF4GBV3}/_ssgManifest.js +0 -0
package/README.md
CHANGED
|
@@ -259,6 +259,7 @@ Full documentation is in the [`docs/`](./docs/) directory:
|
|
|
259
259
|
|
|
260
260
|
- **[Architecture](./docs/dev/architecture.md)** — system design and dispatch pipeline
|
|
261
261
|
- **[CI/CD Pipeline](./docs/dev/ci-cd-pipeline.md)** — three-stage promotion pipeline (Dev → Test → Prod)
|
|
262
|
+
- **[E2E Testing](./tests/e2e/README.md)** — real-process CLI/runtime coverage and CI runner expectations
|
|
262
263
|
- **[Pipeline Simplification (ADR-003)](./docs/dev/ADR-003-pipeline-simplification.md)** — merged research into planning, mechanical completion
|
|
263
264
|
- **[VS Code Extension](./vscode-extension/README.md)** — chat participant, sidebar dashboard, RPC integration
|
|
264
265
|
|
|
@@ -361,7 +362,7 @@ The database is authoritative for milestones, slices, tasks, requirements, decis
|
|
|
361
362
|
|
|
362
363
|
2. **Context pre-loading** — The dispatch prompt includes inlined task plans, slice plans, prior task summaries, dependency summaries, roadmap excerpts, and decisions register. The LLM starts with everything it needs instead of spending tool calls reading files.
|
|
363
364
|
|
|
364
|
-
3. **Context Mode** — Context Mode is enabled by default and gives
|
|
365
|
+
3. **Context Mode** — Context Mode is enabled by default and gives eligible auto-mode units guidance for preserving context. Agents are steered toward `gsd_exec` for noisy scans, builds, tests, and diagnostics; capped stdout/stderr and metadata are saved under `.gsd/exec/` while only a short digest enters the conversation. `gsd_exec_search` lets agents reuse prior runs instead of repeating expensive checks, and `gsd_resume` reads a prior compaction snapshot from `.gsd/last-snapshot.md` when one exists. Opt out with `context_mode.enabled: false` to disable Context Mode guidance, snapshot injection, `gsd_exec`, `gsd_exec_search`, and `gsd_resume`; tune sandbox timeout/output caps and environment forwarding with `context_mode.exec_timeout_ms`, `context_mode.exec_stdout_cap_bytes`, `context_mode.exec_digest_chars`, and `context_mode.exec_env_allowlist`.
|
|
365
366
|
|
|
366
367
|
4. **Git isolation** — When `git.isolation` is set to `worktree` or `branch`, each milestone runs on its own `milestone/<MID>` branch (in a worktree or in-place). All slice work commits sequentially — no branch switching, no merge conflicts. When the milestone completes, it's squash-merged to main as one clean commit. The default is `none` (work on the current branch), configurable via preferences. If `worktree` is configured in a repo with no committed `HEAD`, GSD temporarily behaves as `none` until the first commit exists because git worktrees need a committed start point.
|
|
367
368
|
|
|
@@ -659,10 +660,11 @@ auto_report: true
|
|
|
659
660
|
| `unique_milestone_ids` | Uses unique milestone names to avoid clashes when working in teams of people |
|
|
660
661
|
| `git.isolation` | `none` (default), `worktree`, or `branch` — enable worktree or branch isolation for milestone work. `worktree` requires a committed `HEAD`; zero-commit repos temporarily run as `none` |
|
|
661
662
|
| `git.manage_gitignore` | Set `false` to prevent GSD from modifying `.gitignore` |
|
|
662
|
-
| `context_mode.enabled` | Context Mode is default-on; set `false` to disable `gsd_exec`,
|
|
663
|
+
| `context_mode.enabled` | Context Mode is default-on; set `false` to disable prompt guidance, snapshot injection, `gsd_exec`, `gsd_exec_search`, and `gsd_resume` |
|
|
663
664
|
| `context_mode.exec_timeout_ms` | Timeout for sandboxed `gsd_exec` runs (default: 30000) |
|
|
664
665
|
| `context_mode.exec_stdout_cap_bytes` | Persisted stdout cap for `gsd_exec` output (default: 1048576) |
|
|
665
666
|
| `context_mode.exec_digest_chars` | Trailing stdout characters returned to the agent context (default: 300) |
|
|
667
|
+
| `context_mode.exec_env_allowlist` | Environment variables forwarded to sandboxed `gsd_exec` runs in addition to `PATH` and `HOME` |
|
|
666
668
|
| `verification_commands` | Array of shell commands to run after task execution (e.g., `["npm run lint", "npm run test"]`) |
|
|
667
669
|
| `verification_auto_fix` | Auto-retry on verification failures (default: true) |
|
|
668
670
|
| `verification_max_retries` | Max retries for verification failures (default: 2) |
|
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
4a20b588f749081c
|
|
@@ -28,7 +28,7 @@ Then do the thing `STATE.md` says to do next.
|
|
|
28
28
|
## The Hierarchy
|
|
29
29
|
|
|
30
30
|
```
|
|
31
|
-
Milestone → a shippable version (
|
|
31
|
+
Milestone → a shippable version (1-10 slices, sized to the work)
|
|
32
32
|
Slice → one demoable vertical capability (1-7 tasks)
|
|
33
33
|
Task → one context-window-sized unit of work (fits in one session)
|
|
34
34
|
```
|
|
@@ -331,7 +331,7 @@ The **Don't Hand-Roll** and **Common Pitfalls** sections prevent the most expens
|
|
|
331
331
|
|
|
332
332
|
**For a milestone (roadmap):**
|
|
333
333
|
1. Read `M###-CONTEXT.md`, `M###-RESEARCH.md`, and `.gsd/DECISIONS.md` if they exist.
|
|
334
|
-
2. Decompose the vision into
|
|
334
|
+
2. Decompose the vision into 1-10 demoable vertical slices. Prefer one slice for tiny, single-file, or static work unless the request clearly spans independent capabilities.
|
|
335
335
|
3. Order by risk (high-risk first to validate feasibility early).
|
|
336
336
|
4. Write `M###-ROADMAP.md` with checkboxes, risk levels, dependencies, demo sentences.
|
|
337
337
|
5. **Write the boundary map** — for each slice, specify what it produces (functions, types, interfaces, endpoints) and what it consumes from upstream slices. This forces interface thinking before implementation and enables deterministic verification that slices actually connect.
|
|
@@ -8,6 +8,37 @@
|
|
|
8
8
|
* for the `gh` CLI body parameters.
|
|
9
9
|
*/
|
|
10
10
|
import { buildPrEvidence } from "../gsd/pr-evidence.js";
|
|
11
|
+
// ─── Helpers ────────────────────────────────────────────────────────────────
|
|
12
|
+
/**
|
|
13
|
+
* Wrap a string in a CommonMark inline-code span, escaping any embedded
|
|
14
|
+
* backticks by selecting a fence longer than the longest backtick run inside
|
|
15
|
+
* the input. If the input begins or ends with a backtick, pad with a single
|
|
16
|
+
* space inside the fence (CommonMark requirement).
|
|
17
|
+
*
|
|
18
|
+
* Empty input returns an empty string (no fence) — there is nothing to render
|
|
19
|
+
* as code, and emitting an empty pair of backticks would produce literal
|
|
20
|
+
* backticks in GitHub-flavored markdown.
|
|
21
|
+
*/
|
|
22
|
+
export function inlineCode(s) {
|
|
23
|
+
if (s.length === 0)
|
|
24
|
+
return "";
|
|
25
|
+
let longestRun = 0;
|
|
26
|
+
let currentRun = 0;
|
|
27
|
+
for (const ch of s) {
|
|
28
|
+
if (ch === "`") {
|
|
29
|
+
currentRun++;
|
|
30
|
+
if (currentRun > longestRun)
|
|
31
|
+
longestRun = currentRun;
|
|
32
|
+
}
|
|
33
|
+
else {
|
|
34
|
+
currentRun = 0;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
const fence = "`".repeat(longestRun + 1);
|
|
38
|
+
const needsPad = s.startsWith("`") || s.endsWith("`");
|
|
39
|
+
const pad = needsPad ? " " : "";
|
|
40
|
+
return `${fence}${pad}${s}${pad}${fence}`;
|
|
41
|
+
}
|
|
11
42
|
export function formatMilestoneIssueBody(data) {
|
|
12
43
|
const lines = [];
|
|
13
44
|
lines.push(`# ${data.id}: ${data.title}`);
|
|
@@ -78,7 +109,7 @@ export function formatTaskIssueBody(data) {
|
|
|
78
109
|
if (data.files?.length) {
|
|
79
110
|
lines.push("### Files");
|
|
80
111
|
for (const file of data.files) {
|
|
81
|
-
lines.push(`-
|
|
112
|
+
lines.push(`- ${inlineCode(file)}`);
|
|
82
113
|
}
|
|
83
114
|
lines.push("");
|
|
84
115
|
}
|
|
@@ -132,15 +163,14 @@ export function formatSwarmLanePRBody(data) {
|
|
|
132
163
|
const summaries = [
|
|
133
164
|
[
|
|
134
165
|
"### Swarm lane",
|
|
135
|
-
`**Lane:**
|
|
136
|
-
`**Branch:**
|
|
166
|
+
`**Lane:** ${inlineCode(laneLabel)}`,
|
|
167
|
+
`**Branch:** ${inlineCode(data.lane.branch)}`,
|
|
137
168
|
data.lane.owner ? `**Owner:** ${data.lane.owner}` : "",
|
|
138
|
-
data.lane.latestCommit ? `**Latest commit:**
|
|
169
|
+
data.lane.latestCommit ? `**Latest commit:** ${inlineCode(data.lane.latestCommit)}` : "",
|
|
139
170
|
].filter(Boolean).join("\n"),
|
|
140
171
|
`### Impact area\n${data.impactArea}`,
|
|
141
172
|
`### Changed contracts\n${checkedList(data.lane.changedContracts, "No shared contracts changed").join("\n")}`,
|
|
142
173
|
`### Transition risks\n${checkedList(data.transitionRisks, "No transition risks identified").join("\n")}`,
|
|
143
|
-
data.lane.blockers?.length ? `### Blockers\n${data.lane.blockers.map((blocker) => `- ${blocker}`).join("\n")}` : "",
|
|
144
174
|
].filter(Boolean);
|
|
145
175
|
return buildPrEvidence({
|
|
146
176
|
milestoneId: laneLabel,
|
|
@@ -150,6 +180,7 @@ export function formatSwarmLanePRBody(data) {
|
|
|
150
180
|
changeType: "refactor",
|
|
151
181
|
linkedIssue: data.linkedIssue ? `Closes #${data.linkedIssue}` : undefined,
|
|
152
182
|
summaries,
|
|
183
|
+
blockers: data.lane.blockers ?? [],
|
|
153
184
|
testsRun: data.lane.testEvidence,
|
|
154
185
|
rollbackNotes: data.rollbackPlan,
|
|
155
186
|
how: "Generated by GSD GitHub Sync swarm routines from lane evidence.",
|
|
@@ -159,7 +190,7 @@ export function formatSwarmReleaseChecklistBody(data) {
|
|
|
159
190
|
const lines = [];
|
|
160
191
|
lines.push(`# UOK Swarm Release Checklist`);
|
|
161
192
|
lines.push("");
|
|
162
|
-
lines.push(`**Integration branch:**
|
|
193
|
+
lines.push(`**Integration branch:** ${inlineCode(data.integrationBranch)}`);
|
|
163
194
|
lines.push("");
|
|
164
195
|
lines.push("## Lane summary");
|
|
165
196
|
lines.push("");
|
|
@@ -167,9 +198,9 @@ export function formatSwarmReleaseChecklistBody(data) {
|
|
|
167
198
|
lines.push("|------|--------|-------|--------|--------|");
|
|
168
199
|
for (const lane of data.lanes) {
|
|
169
200
|
const owner = lane.owner ?? "";
|
|
170
|
-
const commit = lane.latestCommit ?
|
|
201
|
+
const commit = lane.latestCommit ? inlineCode(lane.latestCommit) : "";
|
|
171
202
|
const status = lane.blockers?.length ? "blocked" : "ready";
|
|
172
|
-
lines.push(`|
|
|
203
|
+
lines.push(`| ${inlineCode(SWARM_LANE_LABELS[lane.id])} | ${inlineCode(lane.branch)} | ${owner} | ${commit} | ${status} |`);
|
|
173
204
|
}
|
|
174
205
|
lines.push("");
|
|
175
206
|
lines.push("## Required evidence");
|
|
@@ -25,6 +25,8 @@ import { normalizeRealPath } from "../paths.js";
|
|
|
25
25
|
import { decideCooldownRecovery, decideDispatchClaim, decideEngineDispatch, decideFinalizeResult, decideInfrastructureError, decideIterationErrorRecovery, decideMemoryPressure, decideModelPolicyBlocked, decideMinRequestInterval, decideWorkflowLoop, formatDispatchExceptionSummary, formatUnhandledDispatchErrorSummary, resolveUnitRequestTimestamp, shouldUseCustomEnginePath, } from "./workflow-kernel.js";
|
|
26
26
|
import { hydrateCustomVerifyRetryCounts, saveCustomVerifyRetryCounts, } from "./custom-verify-retry-store.js";
|
|
27
27
|
import { settleDispatchCompleted, settleDispatchFailed, } from "./workflow-dispatch-ledger.js";
|
|
28
|
+
import { emitOpenUnitEndForUnit } from "../crash-recovery.js";
|
|
29
|
+
import { writeUnitRuntimeRecord } from "../unit-runtime.js";
|
|
28
30
|
import { openDispatchClaim } from "./workflow-dispatch-claim.js";
|
|
29
31
|
import { completeWorkflowIteration } from "./workflow-iteration-completion.js";
|
|
30
32
|
import { createWorkflowJournalReporter } from "./workflow-journal-reporter.js";
|
|
@@ -133,6 +135,24 @@ async function enforceMinRequestInterval(s, prefs) {
|
|
|
133
135
|
await new Promise(r => setTimeout(r, decision.waitMs));
|
|
134
136
|
}
|
|
135
137
|
}
|
|
138
|
+
function closeOutCrashedUnit(s, iterData, err) {
|
|
139
|
+
const summary = formatDispatchExceptionSummary({ error: err });
|
|
140
|
+
try {
|
|
141
|
+
emitOpenUnitEndForUnit(s.basePath, iterData.unitType, iterData.unitId, "cancelled", {
|
|
142
|
+
message: summary,
|
|
143
|
+
category: "unit-exception",
|
|
144
|
+
isTransient: false,
|
|
145
|
+
});
|
|
146
|
+
writeUnitRuntimeRecord(s.basePath, iterData.unitType, iterData.unitId, s.currentUnit?.startedAt ?? Date.now(), {
|
|
147
|
+
phase: "crashed",
|
|
148
|
+
lastProgressAt: Date.now(),
|
|
149
|
+
lastProgressKind: "unit-exception",
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
catch (closeoutErr) {
|
|
153
|
+
logWarning("dispatch", `unit crash closeout failed: ${closeoutErr instanceof Error ? closeoutErr.message : String(closeoutErr)}`);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
136
156
|
/**
|
|
137
157
|
* Main auto-mode execution loop. Iterates: derive → dispatch → guards →
|
|
138
158
|
* runUnit → finalize → repeat. Exits when s.active becomes false or a
|
|
@@ -268,6 +288,19 @@ export async function autoLoop(ctx, pi, s, deps, options) {
|
|
|
268
288
|
// ── Blanket try/catch: one bad iteration must not kill the session
|
|
269
289
|
const prefs = deps.loadEffectiveGSDPreferences()?.preferences;
|
|
270
290
|
const uokFlags = resolveUokFlags(prefs);
|
|
291
|
+
// ── Check sidecar queue before deriveState ──
|
|
292
|
+
// NOTE: Sidecar dequeue MUST run before validateWorkflowSessionLock so a
|
|
293
|
+
// queued item is popped (and the `sidecar-dequeue` journal event emitted)
|
|
294
|
+
// even when the session lock invalidates this iteration. Inverting this
|
|
295
|
+
// order silently drops queued items on lock-loss. Refs #5308.
|
|
296
|
+
const sidecarItem = await dequeueSidecarItem({
|
|
297
|
+
queue: s.sidecarQueue,
|
|
298
|
+
executionGraphEnabled: uokFlags.executionGraph,
|
|
299
|
+
scheduleQueue: scheduleSidecarQueue,
|
|
300
|
+
warnSchedulingFailure: message => logWarning("dispatch", `sidecar queue scheduling failed: ${message}`),
|
|
301
|
+
logDequeue: payload => debugLog("autoLoop", { phase: "sidecar-dequeue", ...payload }),
|
|
302
|
+
emitDequeue: payload => journalReporter.emit("sidecar-dequeue", payload),
|
|
303
|
+
});
|
|
271
304
|
const sessionLockOutcome = validateWorkflowSessionLock({
|
|
272
305
|
active: s.active,
|
|
273
306
|
iteration,
|
|
@@ -287,17 +320,9 @@ export async function autoLoop(ctx, pi, s, deps, options) {
|
|
|
287
320
|
},
|
|
288
321
|
});
|
|
289
322
|
if (sessionLockOutcome.action === "stop" && sessionLockOutcome.reason === "session-lock-lost") {
|
|
323
|
+
finishTurn("stopped", "manual-attention", sessionLockOutcome.reason);
|
|
290
324
|
break;
|
|
291
325
|
}
|
|
292
|
-
// ── Check sidecar queue before deriveState ──
|
|
293
|
-
const sidecarItem = await dequeueSidecarItem({
|
|
294
|
-
queue: s.sidecarQueue,
|
|
295
|
-
executionGraphEnabled: uokFlags.executionGraph,
|
|
296
|
-
scheduleQueue: scheduleSidecarQueue,
|
|
297
|
-
warnSchedulingFailure: message => logWarning("dispatch", `sidecar queue scheduling failed: ${message}`),
|
|
298
|
-
logDequeue: payload => debugLog("autoLoop", { phase: "sidecar-dequeue", ...payload }),
|
|
299
|
-
emitDequeue: payload => journalReporter.emit("sidecar-dequeue", payload),
|
|
300
|
-
});
|
|
301
326
|
const ic = { ctx, pi, s, deps, prefs, iteration, flowId, nextSeq };
|
|
302
327
|
journalReporter.emit("iteration-start", { iteration });
|
|
303
328
|
let iterData;
|
|
@@ -331,6 +356,7 @@ export async function autoLoop(ctx, pi, s, deps, options) {
|
|
|
331
356
|
isComplete: engineState.isComplete,
|
|
332
357
|
});
|
|
333
358
|
if (engineState.isComplete) {
|
|
359
|
+
finishTurn("completed");
|
|
334
360
|
await deps.stopAuto(ctx, pi, "Workflow complete");
|
|
335
361
|
break;
|
|
336
362
|
}
|
|
@@ -386,7 +412,17 @@ export async function autoLoop(ctx, pi, s, deps, options) {
|
|
|
386
412
|
}
|
|
387
413
|
// ── Unit execution (shared with dev path) ──
|
|
388
414
|
await enforceMinRequestInterval(s, prefs);
|
|
389
|
-
|
|
415
|
+
let unitPhaseResult;
|
|
416
|
+
try {
|
|
417
|
+
unitPhaseResult = await runUnitPhaseViaContract(dispatchContract, ic, iterData, loopState, undefined, unitDispatchDeps);
|
|
418
|
+
}
|
|
419
|
+
catch (err) {
|
|
420
|
+
if (err instanceof ModelPolicyDispatchBlockedError) {
|
|
421
|
+
throw err;
|
|
422
|
+
}
|
|
423
|
+
closeOutCrashedUnit(s, iterData, err);
|
|
424
|
+
throw err;
|
|
425
|
+
}
|
|
390
426
|
if (unitPhaseResult.action === "next") {
|
|
391
427
|
const requestTimestamp = resolveUnitRequestTimestamp(unitPhaseResult.data);
|
|
392
428
|
if (requestTimestamp !== undefined)
|
|
@@ -574,6 +610,7 @@ export async function autoLoop(ctx, pi, s, deps, options) {
|
|
|
574
610
|
if (err instanceof ModelPolicyDispatchBlockedError) {
|
|
575
611
|
throw err;
|
|
576
612
|
}
|
|
613
|
+
closeOutCrashedUnit(s, iterData, err);
|
|
577
614
|
dispatchSettled = settleDispatchFailed(dispatchId, formatDispatchExceptionSummary({ error: err }), {
|
|
578
615
|
markFailed: markDispatchFailed,
|
|
579
616
|
logWriteFailure: logDispatchLedgerWriteFailure,
|
|
@@ -734,6 +771,7 @@ export async function autoLoop(ctx, pi, s, deps, options) {
|
|
|
734
771
|
});
|
|
735
772
|
if (cooldownDecision.action === "stop") {
|
|
736
773
|
ctx.ui.notify(cooldownDecision.notifyMessage, "error");
|
|
774
|
+
finishTurn("stopped", "timeout", msg);
|
|
737
775
|
await deps.stopAuto(ctx, pi, cooldownDecision.stopMessage);
|
|
738
776
|
break;
|
|
739
777
|
}
|
|
@@ -13,22 +13,22 @@ import { detectStuck } from "./detect-stuck.js";
|
|
|
13
13
|
import { runUnit } from "./run-unit.js";
|
|
14
14
|
import { debugLog } from "../debug-logger.js";
|
|
15
15
|
import { resolveWorktreeProjectRoot, normalizeWorktreePathForCompare } from "../worktree-root.js";
|
|
16
|
-
import {
|
|
16
|
+
import { classifyProject } from "../detection.js";
|
|
17
17
|
import { MergeConflictError } from "../git-service.js";
|
|
18
18
|
import { setCurrentPhase, clearCurrentPhase } from "../../shared/gsd-phase-state.js";
|
|
19
19
|
import { pauseAutoForProviderError } from "../provider-error-pause.js";
|
|
20
20
|
import { resumeAutoAfterProviderDelay } from "../bootstrap/provider-error-resume.js";
|
|
21
21
|
import { join, basename } from "node:path";
|
|
22
|
-
import { existsSync, cpSync
|
|
22
|
+
import { existsSync, cpSync } from "node:fs";
|
|
23
23
|
import { logWarning, logError, _resetLogs, drainLogs, drainAndSummarize, formatForNotification, hasAnyIssues, } from "../workflow-logger.js";
|
|
24
24
|
import { gsdRoot } from "../paths.js";
|
|
25
25
|
import { atomicWriteSync } from "../atomic-write.js";
|
|
26
|
-
import { verifyExpectedArtifact, diagnoseExpectedArtifact, buildLoopRemediationSteps } from "../auto-recovery.js";
|
|
26
|
+
import { verifyExpectedArtifact, diagnoseExpectedArtifact, buildLoopRemediationSteps, refreshRecoveryDbForArtifact } from "../auto-recovery.js";
|
|
27
27
|
import { writeUnitRuntimeRecord } from "../unit-runtime.js";
|
|
28
28
|
import { withTimeout, FINALIZE_PRE_TIMEOUT_MS, FINALIZE_POST_TIMEOUT_MS } from "./finalize-timeout.js";
|
|
29
29
|
import { getEligibleSlices } from "../slice-parallel-eligibility.js";
|
|
30
30
|
import { startSliceParallel } from "../slice-parallel-orchestrator.js";
|
|
31
|
-
import { isDbAvailable, getMilestoneSlices
|
|
31
|
+
import { isDbAvailable, getMilestoneSlices } from "../gsd-db.js";
|
|
32
32
|
import { ensurePlanV2Graph, isEmptyPlanV2GraphResult, isMissingFinalizedContextResult } from "../uok/plan-v2.js";
|
|
33
33
|
import { resolveUokFlags } from "../uok/flags.js";
|
|
34
34
|
import { UokGateRunner } from "../uok/gate-runner.js";
|
|
@@ -42,13 +42,6 @@ import { getWorkflowTransportSupportError, getRequiredWorkflowToolsForAutoUnit,
|
|
|
42
42
|
function isSamePathLocal(a, b) {
|
|
43
43
|
return normalizeWorktreePathForCompare(a) === normalizeWorktreePathForCompare(b);
|
|
44
44
|
}
|
|
45
|
-
function refreshPlanSliceRecoveryDbIfNeeded(unitType) {
|
|
46
|
-
if (unitType !== "plan-slice")
|
|
47
|
-
return true;
|
|
48
|
-
if (!isDbAvailable())
|
|
49
|
-
return true;
|
|
50
|
-
return refreshOpenDatabaseFromDisk();
|
|
51
|
-
}
|
|
52
45
|
// ─── Session timeout auto-resume state ────────────────────────────────────────
|
|
53
46
|
let consecutiveSessionTimeouts = 0;
|
|
54
47
|
const MAX_SESSION_TIMEOUT_AUTO_RESUMES = 3;
|
|
@@ -498,7 +491,7 @@ export async function runPreDispatch(ic, loopState) {
|
|
|
498
491
|
}
|
|
499
492
|
// #2909: postflight — restore stashed changes after successful merge
|
|
500
493
|
if (preflightTransition.stashPushed) {
|
|
501
|
-
deps.postflightPopStash(s.originalBasePath || s.basePath, s.currentMilestoneId, ctx.ui.notify.bind(ctx.ui));
|
|
494
|
+
deps.postflightPopStash(s.originalBasePath || s.basePath, s.currentMilestoneId, preflightTransition.stashMarker, ctx.ui.notify.bind(ctx.ui));
|
|
502
495
|
}
|
|
503
496
|
// PR creation (auto_pr) is handled inside mergeMilestoneToMain (#2302)
|
|
504
497
|
deps.invalidateAllCaches();
|
|
@@ -574,7 +567,7 @@ export async function runPreDispatch(ic, loopState) {
|
|
|
574
567
|
}
|
|
575
568
|
// #2909: postflight — restore stashed changes after successful merge
|
|
576
569
|
if (preflightAllComplete.stashPushed) {
|
|
577
|
-
deps.postflightPopStash(s.originalBasePath || s.basePath, s.currentMilestoneId, ctx.ui.notify.bind(ctx.ui));
|
|
570
|
+
deps.postflightPopStash(s.originalBasePath || s.basePath, s.currentMilestoneId, preflightAllComplete.stashMarker, ctx.ui.notify.bind(ctx.ui));
|
|
578
571
|
}
|
|
579
572
|
// PR creation (auto_pr) is handled inside mergeMilestoneToMain (#2302)
|
|
580
573
|
}
|
|
@@ -660,7 +653,7 @@ export async function runPreDispatch(ic, loopState) {
|
|
|
660
653
|
}
|
|
661
654
|
// #2909: postflight — restore stashed changes after successful merge
|
|
662
655
|
if (preflightComplete.stashPushed) {
|
|
663
|
-
deps.postflightPopStash(s.originalBasePath || s.basePath, s.currentMilestoneId, ctx.ui.notify.bind(ctx.ui));
|
|
656
|
+
deps.postflightPopStash(s.originalBasePath || s.basePath, s.currentMilestoneId, preflightComplete.stashMarker, ctx.ui.notify.bind(ctx.ui));
|
|
664
657
|
}
|
|
665
658
|
// PR creation (auto_pr) is handled inside mergeMilestoneToMain (#2302)
|
|
666
659
|
}
|
|
@@ -795,11 +788,18 @@ export async function runDispatch(ic, preData, loopState) {
|
|
|
795
788
|
level: 1,
|
|
796
789
|
action: "artifact-found",
|
|
797
790
|
});
|
|
798
|
-
|
|
799
|
-
if (!
|
|
800
|
-
ctx.ui.notify(
|
|
791
|
+
const recoveryDb = refreshRecoveryDbForArtifact(unitType, unitId);
|
|
792
|
+
if (!recoveryDb.ok) {
|
|
793
|
+
ctx.ui.notify(recoveryDb.fatal
|
|
794
|
+
? `${recoveryDb.message} Pausing auto-mode for manual recovery.`
|
|
795
|
+
: `${recoveryDb.message} Keeping stuck state for retry.`, "warning");
|
|
796
|
+
if (recoveryDb.fatal) {
|
|
797
|
+
await deps.pauseAuto(ctx, pi);
|
|
798
|
+
return { action: "break", reason: recoveryDb.reason };
|
|
799
|
+
}
|
|
801
800
|
return { action: "continue" };
|
|
802
801
|
}
|
|
802
|
+
ctx.ui.notify(`Stuck recovery: artifact for ${unitType} ${unitId} found on disk. Invalidating caches.`, "info");
|
|
803
803
|
deps.invalidateAllCaches();
|
|
804
804
|
loopState.recentUnits.length = 0;
|
|
805
805
|
loopState.stuckRecoveryAttempts = 0;
|
|
@@ -818,13 +818,20 @@ export async function runDispatch(ic, preData, loopState) {
|
|
|
818
818
|
level: 2,
|
|
819
819
|
action: "artifact-found",
|
|
820
820
|
});
|
|
821
|
-
|
|
822
|
-
if (
|
|
821
|
+
const recoveryDb = refreshRecoveryDbForArtifact(unitType, unitId);
|
|
822
|
+
if (recoveryDb.ok) {
|
|
823
|
+
ctx.ui.notify(`Stuck recovery: artifact for ${unitType} ${unitId} found on disk after cache invalidation. Continuing.`, "info");
|
|
823
824
|
loopState.recentUnits.length = 0;
|
|
824
825
|
loopState.stuckRecoveryAttempts = 0;
|
|
825
826
|
return { action: "continue" };
|
|
826
827
|
}
|
|
827
|
-
ctx.ui.notify(
|
|
828
|
+
ctx.ui.notify(recoveryDb.fatal
|
|
829
|
+
? `${recoveryDb.message} Pausing auto-mode for manual recovery.`
|
|
830
|
+
: `${recoveryDb.message} Stopping for manual recovery.`, "warning");
|
|
831
|
+
if (recoveryDb.fatal) {
|
|
832
|
+
await deps.pauseAuto(ctx, pi);
|
|
833
|
+
return { action: "break", reason: recoveryDb.reason };
|
|
834
|
+
}
|
|
828
835
|
}
|
|
829
836
|
debugLog("autoLoop", {
|
|
830
837
|
phase: "stuck-detected",
|
|
@@ -1084,8 +1091,9 @@ export async function runUnitPhase(ic, iterData, loopState, sidecarItem) {
|
|
|
1084
1091
|
// Verify the working directory is a valid git checkout with project
|
|
1085
1092
|
// files before dispatching work. A broken worktree causes agents to
|
|
1086
1093
|
// hallucinate summaries since they cannot read or write any files.
|
|
1087
|
-
// Uses
|
|
1088
|
-
//
|
|
1094
|
+
// Uses project classification so project presence is not conflated with
|
|
1095
|
+
// ecosystem marker detection. Static/minimal repos become untyped-existing.
|
|
1096
|
+
let projectClassification = null;
|
|
1089
1097
|
if (s.basePath && unitType === "execute-task") {
|
|
1090
1098
|
const gitMarker = join(s.basePath, ".git");
|
|
1091
1099
|
const hasGit = deps.existsSync(gitMarker);
|
|
@@ -1096,30 +1104,26 @@ export async function runUnitPhase(ic, iterData, loopState, sidecarItem) {
|
|
|
1096
1104
|
await deps.stopAuto(ctx, pi, msg);
|
|
1097
1105
|
return { action: "break", reason: "worktree-invalid" };
|
|
1098
1106
|
}
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
+
projectClassification = classifyProject(s.basePath);
|
|
1108
|
+
if (projectClassification.kind === "invalid-repo") {
|
|
1109
|
+
const msg = `Worktree health check failed: ${s.basePath} classified as invalid-repo (${projectClassification.reason}) — refusing to dispatch ${unitType} ${unitId}`;
|
|
1110
|
+
debugLog("runUnitPhase", { phase: "worktree-health-invalid-repo", basePath: s.basePath, classification: projectClassification });
|
|
1111
|
+
if (projectClassification.reason === "missing .git" && hasGit) {
|
|
1112
|
+
ctx.ui.notify(`Warning: ${s.basePath} project classification could not confirm .git; assuming it has no project content yet — proceeding as greenfield project because worktree health reported .git present`, "warning");
|
|
1113
|
+
}
|
|
1114
|
+
else {
|
|
1115
|
+
ctx.ui.notify(msg, "error");
|
|
1116
|
+
await deps.stopAuto(ctx, pi, msg);
|
|
1117
|
+
return { action: "break", reason: "worktree-invalid" };
|
|
1118
|
+
}
|
|
1107
1119
|
}
|
|
1108
|
-
|
|
1109
|
-
debugLog("runUnitPhase", { phase: "
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
? hasProjectFileInAncestor(s.basePath, deps.existsSync)
|
|
1116
|
-
: false;
|
|
1117
|
-
if (!hasProjectFile && !hasSrcDir && !hasXcodeBundle && !hasProjectFileInParent) {
|
|
1118
|
-
// Greenfield projects won't have project files yet — the first task creates them.
|
|
1119
|
-
// Log a warning but allow execution to proceed. The .git check above is sufficient
|
|
1120
|
-
// to ensure we're in a valid working directory.
|
|
1121
|
-
debugLog("runUnitPhase", { phase: "worktree-health-warn-greenfield", basePath: s.basePath, hasProjectFile, hasSrcDir, hasXcodeBundle });
|
|
1122
|
-
ctx.ui.notify(`Warning: ${s.basePath} has no recognized project files — proceeding as greenfield project`, "warning");
|
|
1120
|
+
else if (projectClassification.kind === "greenfield") {
|
|
1121
|
+
debugLog("runUnitPhase", { phase: "worktree-health-greenfield", basePath: s.basePath, classification: projectClassification });
|
|
1122
|
+
ctx.ui.notify(`Warning: ${s.basePath} has no project content yet — proceeding as greenfield project`, "warning");
|
|
1123
|
+
}
|
|
1124
|
+
else if (projectClassification.kind === "untyped-existing") {
|
|
1125
|
+
debugLog("runUnitPhase", { phase: "worktree-health-untyped-existing", basePath: s.basePath, classification: projectClassification });
|
|
1126
|
+
ctx.ui.notify(`Notice: ${s.basePath} has existing project content but no recognized tooling markers — using generic file-level workflow guidance`, "info");
|
|
1123
1127
|
}
|
|
1124
1128
|
}
|
|
1125
1129
|
// Detect retry and capture previous tier for escalation
|
|
@@ -1182,6 +1186,16 @@ export async function runUnitPhase(ic, iterData, loopState, sidecarItem) {
|
|
|
1182
1186
|
}
|
|
1183
1187
|
// Prompt injection
|
|
1184
1188
|
let finalPrompt = prompt;
|
|
1189
|
+
if (unitType === "execute-task") {
|
|
1190
|
+
projectClassification ??= classifyProject(s.basePath);
|
|
1191
|
+
if (projectClassification.kind === "untyped-existing") {
|
|
1192
|
+
const samples = projectClassification.contentFiles.slice(0, 8).join(", ") || "project files";
|
|
1193
|
+
finalPrompt +=
|
|
1194
|
+
"\n\n**Project classification:** Existing untyped project. No recognized build/tooling markers were detected, " +
|
|
1195
|
+
"so use generic file-level workflow guidance. Task plans and completion summaries must list every concrete " +
|
|
1196
|
+
`project file changed in \`files\` or \`expected_output\`. Detected content sample: ${samples}.`;
|
|
1197
|
+
}
|
|
1198
|
+
}
|
|
1185
1199
|
if (s.pendingVerificationRetry) {
|
|
1186
1200
|
const retryCtx = s.pendingVerificationRetry;
|
|
1187
1201
|
s.pendingVerificationRetry = null;
|
|
@@ -1665,6 +1679,13 @@ export async function runFinalize(ic, iterData, loopState, sidecarItem) {
|
|
|
1665
1679
|
}
|
|
1666
1680
|
// Both pre and post verification completed without timeout — reset counter
|
|
1667
1681
|
loopState.consecutiveFinalizeTimeouts = 0;
|
|
1682
|
+
if (preUnitSnapshot) {
|
|
1683
|
+
writeUnitRuntimeRecord(s.basePath, preUnitSnapshot.type, preUnitSnapshot.id, preUnitSnapshot.startedAt, {
|
|
1684
|
+
phase: "finalized",
|
|
1685
|
+
lastProgressAt: Date.now(),
|
|
1686
|
+
lastProgressKind: "finalize-success",
|
|
1687
|
+
});
|
|
1688
|
+
}
|
|
1668
1689
|
s.currentUnit = null;
|
|
1669
1690
|
clearCurrentPhase();
|
|
1670
1691
|
// Surface accumulated workflow-logger issues for this unit to the user.
|
|
@@ -17,6 +17,7 @@ import { bumpTurnGeneration } from "./turn-epoch.js";
|
|
|
17
17
|
// scoped pendingResolve + pendingAgentEndQueue pattern.
|
|
18
18
|
let _currentResolve = null;
|
|
19
19
|
let _sessionSwitchInFlight = false;
|
|
20
|
+
let _pendingSwitchCancellation = null;
|
|
20
21
|
// ─── Setters (needed for cross-module mutation) ─────────────────────────────
|
|
21
22
|
export function _setCurrentResolve(fn) {
|
|
22
23
|
_currentResolve = fn;
|
|
@@ -27,6 +28,11 @@ export function _setSessionSwitchInFlight(v) {
|
|
|
27
28
|
export function _clearCurrentResolve() {
|
|
28
29
|
_currentResolve = null;
|
|
29
30
|
}
|
|
31
|
+
export function _consumePendingSwitchCancellation() {
|
|
32
|
+
const pending = _pendingSwitchCancellation;
|
|
33
|
+
_pendingSwitchCancellation = null;
|
|
34
|
+
return pending;
|
|
35
|
+
}
|
|
30
36
|
// ─── resolveAgentEnd ─────────────────────────────────────────────────────────
|
|
31
37
|
/**
|
|
32
38
|
* Called from the agent_end event handler in index.ts to resolve the
|
|
@@ -90,8 +96,18 @@ export function resolveAgentEndCancelled(errorContext) {
|
|
|
90
96
|
debugLog("resolveAgentEndCancelled", { status: "resolving-cancelled" });
|
|
91
97
|
const r = _currentResolve;
|
|
92
98
|
_currentResolve = null;
|
|
99
|
+
_pendingSwitchCancellation = null;
|
|
93
100
|
r({ status: "cancelled", ...(errorContext ? { errorContext } : {}) });
|
|
101
|
+
return true;
|
|
102
|
+
}
|
|
103
|
+
if (_sessionSwitchInFlight) {
|
|
104
|
+
bumpTurnGeneration(`cancelled-during-switch:${errorContext?.category ?? "unknown"}`);
|
|
105
|
+
_pendingSwitchCancellation = errorContext ? { errorContext } : {};
|
|
106
|
+
debugLog("resolveAgentEndCancelled", { status: "queued-during-switch" });
|
|
107
|
+
return false;
|
|
94
108
|
}
|
|
109
|
+
debugLog("resolveAgentEndCancelled", { status: "no-pending-resolve" });
|
|
110
|
+
return false;
|
|
95
111
|
}
|
|
96
112
|
// ─── resetPendingResolve (test helper) ───────────────────────────────────────
|
|
97
113
|
/**
|
|
@@ -101,6 +117,7 @@ export function resolveAgentEndCancelled(errorContext) {
|
|
|
101
117
|
export function _resetPendingResolve() {
|
|
102
118
|
_currentResolve = null;
|
|
103
119
|
_sessionSwitchInFlight = false;
|
|
120
|
+
_pendingSwitchCancellation = null;
|
|
104
121
|
}
|
|
105
122
|
export function _hasPendingResolveForTest() {
|
|
106
123
|
return _currentResolve !== null;
|
|
@@ -1,14 +1,11 @@
|
|
|
1
|
-
|
|
2
|
-
* auto/run-unit.ts — Single unit execution: session create → prompt → await agent_end.
|
|
3
|
-
*
|
|
4
|
-
* Imports from: auto/types, auto/resolve
|
|
5
|
-
*/
|
|
1
|
+
// GSD-2 + src/resources/extensions/gsd/auto/run-unit.ts - Runs one GSD auto-mode unit from session creation through agent completion.
|
|
6
2
|
import { NEW_SESSION_TIMEOUT_MS } from "./session.js";
|
|
7
|
-
import { _clearCurrentResolve, _setCurrentResolve, _setSessionSwitchInFlight } from "./resolve.js";
|
|
3
|
+
import { _clearCurrentResolve, _consumePendingSwitchCancellation, _setCurrentResolve, _setSessionSwitchInFlight, } from "./resolve.js";
|
|
8
4
|
import { getCurrentTurnGeneration, runWithTurnGeneration, } from "./turn-epoch.js";
|
|
9
5
|
import { debugLog } from "../debug-logger.js";
|
|
10
6
|
import { logWarning } from "../workflow-logger.js";
|
|
11
7
|
import { resolveAutoSupervisorConfig } from "../preferences.js";
|
|
8
|
+
import { formatAutoUnitWorkingMessage } from "../working-output-messages.js";
|
|
12
9
|
// Tracks the latest session-switch attempt so a late timeout settlement from an
|
|
13
10
|
// older runUnit() call cannot clear the guard for a newer one.
|
|
14
11
|
let sessionSwitchGeneration = 0;
|
|
@@ -74,6 +71,7 @@ export async function runUnit(ctx, pi, s, unitType, unitId, prompt) {
|
|
|
74
71
|
catch (sessionErr) {
|
|
75
72
|
if (sessionTimeoutHandle)
|
|
76
73
|
clearTimeout(sessionTimeoutHandle);
|
|
74
|
+
_consumePendingSwitchCancellation();
|
|
77
75
|
const msg = sessionErr instanceof Error ? sessionErr.message : String(sessionErr);
|
|
78
76
|
debugLog("runUnit", {
|
|
79
77
|
phase: "session-error",
|
|
@@ -86,15 +84,18 @@ export async function runUnit(ctx, pi, s, unitType, unitId, prompt) {
|
|
|
86
84
|
if (sessionTimeoutHandle)
|
|
87
85
|
clearTimeout(sessionTimeoutHandle);
|
|
88
86
|
if (sessionResult.cancelled) {
|
|
87
|
+
_consumePendingSwitchCancellation();
|
|
89
88
|
debugLog("runUnit-session-timeout", { unitType, unitId });
|
|
90
89
|
return { status: "cancelled", errorContext: { message: "Session creation timed out", category: "timeout", isTransient: true } };
|
|
91
90
|
}
|
|
92
91
|
if (!s.active) {
|
|
92
|
+
_consumePendingSwitchCancellation();
|
|
93
93
|
return { status: "cancelled" };
|
|
94
94
|
}
|
|
95
95
|
if (s.currentUnitModel && typeof pi.setModel === "function") {
|
|
96
96
|
const restored = await pi.setModel(s.currentUnitModel, { persist: false });
|
|
97
97
|
if (!restored) {
|
|
98
|
+
_consumePendingSwitchCancellation();
|
|
98
99
|
const message = `Failed to restore configured model ${s.currentUnitModel.provider}/${s.currentUnitModel.id} after session creation`;
|
|
99
100
|
ctx.ui.notify(`${message}. Cancelling unit before dispatch.`, "warning");
|
|
100
101
|
return {
|
|
@@ -114,6 +115,14 @@ export async function runUnit(ctx, pi, s, unitType, unitId, prompt) {
|
|
|
114
115
|
const unitPromise = new Promise((resolve) => {
|
|
115
116
|
_setCurrentResolve(resolve);
|
|
116
117
|
});
|
|
118
|
+
const pendingSwitchCancellation = _consumePendingSwitchCancellation();
|
|
119
|
+
if (pendingSwitchCancellation) {
|
|
120
|
+
_clearCurrentResolve();
|
|
121
|
+
return {
|
|
122
|
+
status: "cancelled",
|
|
123
|
+
...(pendingSwitchCancellation.errorContext ? { errorContext: pendingSwitchCancellation.errorContext } : {}),
|
|
124
|
+
};
|
|
125
|
+
}
|
|
117
126
|
// ── Provider request-readiness pre-check (#4555) ──
|
|
118
127
|
// Verify the provider can accept requests before dispatching. If the token
|
|
119
128
|
// has expired since bootstrap, return cancelled immediately so the unit is
|
|
@@ -151,22 +160,29 @@ export async function runUnit(ctx, pi, s, unitType, unitId, prompt) {
|
|
|
151
160
|
// ── Send the prompt ──
|
|
152
161
|
debugLog("runUnit", { phase: "send-message", unitType, unitId });
|
|
153
162
|
const requestDispatchedAt = Date.now();
|
|
154
|
-
|
|
163
|
+
ctx.ui.setWorkingMessage?.(formatAutoUnitWorkingMessage(unitType, unitId));
|
|
155
164
|
// ── Await agent_end with absolute timeout (H4 fix) ──
|
|
156
165
|
// If supervision fails to resolve unitPromise within 30s, treat as cancelled.
|
|
157
166
|
// Without this, a crashed agent that never emits agent_end hangs the loop (#3161).
|
|
158
|
-
debugLog("runUnit", { phase: "awaiting-agent-end", unitType, unitId });
|
|
159
167
|
const supervisor = resolveAutoSupervisorConfig();
|
|
160
168
|
const UNIT_HARD_TIMEOUT_MS = Math.max(30_000, ((supervisor.hard_timeout_minutes ?? 30) * 60 * 1000) + 30_000);
|
|
161
169
|
let unitTimeoutHandle;
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
+
let result;
|
|
171
|
+
try {
|
|
172
|
+
pi.sendMessage({ customType: "gsd-auto", content: prompt, display: s.verbose }, { triggerTurn: true });
|
|
173
|
+
debugLog("runUnit", { phase: "awaiting-agent-end", unitType, unitId });
|
|
174
|
+
const timeoutResult = new Promise((resolve) => {
|
|
175
|
+
unitTimeoutHandle = setTimeout(() => {
|
|
176
|
+
resolve({ status: "cancelled", errorContext: { message: "Unit hard timeout — supervision may have failed", category: "timeout", isTransient: true } });
|
|
177
|
+
}, UNIT_HARD_TIMEOUT_MS);
|
|
178
|
+
});
|
|
179
|
+
result = await runWithTurnGeneration(capturedTurnGen, () => Promise.race([unitPromise, timeoutResult]));
|
|
180
|
+
}
|
|
181
|
+
finally {
|
|
182
|
+
if (unitTimeoutHandle)
|
|
183
|
+
clearTimeout(unitTimeoutHandle);
|
|
184
|
+
ctx.ui.setWorkingMessage?.(undefined);
|
|
185
|
+
}
|
|
170
186
|
debugLog("runUnit", {
|
|
171
187
|
phase: "agent-end-received",
|
|
172
188
|
unitType,
|