gsd-pi 2.80.0-dev.c5f2443b3 → 2.80.0-dev.f2447468f
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/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 +16 -9
- package/dist/resources/extensions/gsd/auto/phases.js +37 -30
- package/dist/resources/extensions/gsd/auto/run-unit.js +19 -15
- 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 +111 -1
- package/dist/resources/extensions/gsd/auto-recovery.js +154 -8
- package/dist/resources/extensions/gsd/auto-start.js +2 -3
- package/dist/resources/extensions/gsd/auto.js +9 -1
- package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +15 -1
- package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +11 -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/custom-workflow-engine.js +22 -2
- package/dist/resources/extensions/gsd/db-base-schema.js +14 -0
- package/dist/resources/extensions/gsd/db-migration-steps.js +16 -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 +102 -2
- package/dist/resources/extensions/gsd/guided-flow.js +46 -9
- 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/prompts/complete-milestone.md +7 -8
- 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/safety/evidence-collector.js +10 -2
- 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/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 +10 -10
- 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 +10 -10
- 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 +10 -6
- package/packages/contracts/package.json +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/chat-controller-ordering.test.js +74 -0
- package/packages/pi-coding-agent/dist/core/chat-controller-ordering.test.js.map +1 -1
- 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 +2 -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 +14 -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 +97 -0
- package/packages/pi-coding-agent/dist/core/extensions/runner.test.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 +4 -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 +8 -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 +16 -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 +106 -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 +60 -1
- 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 +40 -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 +23 -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/chat-controller-ordering.test.ts +87 -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 +108 -0
- package/packages/pi-coding-agent/src/core/extensions/runner.ts +16 -1
- package/packages/pi-coding-agent/src/core/model-registry.ts +4 -0
- package/packages/pi-coding-agent/src/core/settings-manager.ts +12 -0
- 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 +118 -17
- package/packages/pi-coding-agent/src/modes/interactive/controllers/chat-controller.test.ts +43 -1
- package/packages/pi-coding-agent/src/modes/interactive/controllers/chat-controller.ts +75 -1
- 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 +25 -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 +3 -8
- 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 +3 -8
- 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 +17 -10
- package/src/resources/extensions/gsd/auto/phases.ts +42 -28
- package/src/resources/extensions/gsd/auto/run-unit.ts +24 -14
- 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 +116 -1
- package/src/resources/extensions/gsd/auto-recovery.ts +153 -7
- package/src/resources/extensions/gsd/auto-start.ts +7 -6
- package/src/resources/extensions/gsd/auto.ts +12 -1
- package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +16 -1
- package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +17 -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/custom-workflow-engine.ts +24 -1
- package/src/resources/extensions/gsd/db-base-schema.ts +15 -0
- package/src/resources/extensions/gsd/db-migration-steps.ts +17 -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 +119 -1
- package/src/resources/extensions/gsd/guided-flow.ts +46 -9
- 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/prompts/complete-milestone.md +7 -8
- 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/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 +84 -5
- package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +170 -1
- 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/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/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/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/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/smart-entry-complete.test.ts +38 -0
- package/src/resources/extensions/gsd/tests/start-auto-detached.test.ts +46 -2
- package/src/resources/extensions/gsd/tests/uok-plan-v2-wiring.test.ts +1 -1
- 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/plan-slice.ts +13 -0
- package/src/resources/extensions/gsd/tools/plan-task.ts +10 -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 → _67VlKGhH0VvTM6yfRGKl}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{bQDK5_LtkGVS64AirQgQG → _67VlKGhH0VvTM6yfRGKl}/_ssgManifest.js +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
f9db90ffe20c559d
|
|
@@ -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");
|
|
@@ -268,6 +268,19 @@ export async function autoLoop(ctx, pi, s, deps, options) {
|
|
|
268
268
|
// ── Blanket try/catch: one bad iteration must not kill the session
|
|
269
269
|
const prefs = deps.loadEffectiveGSDPreferences()?.preferences;
|
|
270
270
|
const uokFlags = resolveUokFlags(prefs);
|
|
271
|
+
// ── Check sidecar queue before deriveState ──
|
|
272
|
+
// NOTE: Sidecar dequeue MUST run before validateWorkflowSessionLock so a
|
|
273
|
+
// queued item is popped (and the `sidecar-dequeue` journal event emitted)
|
|
274
|
+
// even when the session lock invalidates this iteration. Inverting this
|
|
275
|
+
// order silently drops queued items on lock-loss. Refs #5308.
|
|
276
|
+
const sidecarItem = await dequeueSidecarItem({
|
|
277
|
+
queue: s.sidecarQueue,
|
|
278
|
+
executionGraphEnabled: uokFlags.executionGraph,
|
|
279
|
+
scheduleQueue: scheduleSidecarQueue,
|
|
280
|
+
warnSchedulingFailure: message => logWarning("dispatch", `sidecar queue scheduling failed: ${message}`),
|
|
281
|
+
logDequeue: payload => debugLog("autoLoop", { phase: "sidecar-dequeue", ...payload }),
|
|
282
|
+
emitDequeue: payload => journalReporter.emit("sidecar-dequeue", payload),
|
|
283
|
+
});
|
|
271
284
|
const sessionLockOutcome = validateWorkflowSessionLock({
|
|
272
285
|
active: s.active,
|
|
273
286
|
iteration,
|
|
@@ -287,17 +300,9 @@ export async function autoLoop(ctx, pi, s, deps, options) {
|
|
|
287
300
|
},
|
|
288
301
|
});
|
|
289
302
|
if (sessionLockOutcome.action === "stop" && sessionLockOutcome.reason === "session-lock-lost") {
|
|
303
|
+
finishTurn("stopped", "manual-attention", sessionLockOutcome.reason);
|
|
290
304
|
break;
|
|
291
305
|
}
|
|
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
306
|
const ic = { ctx, pi, s, deps, prefs, iteration, flowId, nextSeq };
|
|
302
307
|
journalReporter.emit("iteration-start", { iteration });
|
|
303
308
|
let iterData;
|
|
@@ -331,6 +336,7 @@ export async function autoLoop(ctx, pi, s, deps, options) {
|
|
|
331
336
|
isComplete: engineState.isComplete,
|
|
332
337
|
});
|
|
333
338
|
if (engineState.isComplete) {
|
|
339
|
+
finishTurn("completed");
|
|
334
340
|
await deps.stopAuto(ctx, pi, "Workflow complete");
|
|
335
341
|
break;
|
|
336
342
|
}
|
|
@@ -734,6 +740,7 @@ export async function autoLoop(ctx, pi, s, deps, options) {
|
|
|
734
740
|
});
|
|
735
741
|
if (cooldownDecision.action === "stop") {
|
|
736
742
|
ctx.ui.notify(cooldownDecision.notifyMessage, "error");
|
|
743
|
+
finishTurn("stopped", "timeout", msg);
|
|
737
744
|
await deps.stopAuto(ctx, pi, cooldownDecision.stopMessage);
|
|
738
745
|
break;
|
|
739
746
|
}
|
|
@@ -13,13 +13,13 @@ 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";
|
|
@@ -498,7 +498,7 @@ export async function runPreDispatch(ic, loopState) {
|
|
|
498
498
|
}
|
|
499
499
|
// #2909: postflight — restore stashed changes after successful merge
|
|
500
500
|
if (preflightTransition.stashPushed) {
|
|
501
|
-
deps.postflightPopStash(s.originalBasePath || s.basePath, s.currentMilestoneId, ctx.ui.notify.bind(ctx.ui));
|
|
501
|
+
deps.postflightPopStash(s.originalBasePath || s.basePath, s.currentMilestoneId, preflightTransition.stashMarker, ctx.ui.notify.bind(ctx.ui));
|
|
502
502
|
}
|
|
503
503
|
// PR creation (auto_pr) is handled inside mergeMilestoneToMain (#2302)
|
|
504
504
|
deps.invalidateAllCaches();
|
|
@@ -574,7 +574,7 @@ export async function runPreDispatch(ic, loopState) {
|
|
|
574
574
|
}
|
|
575
575
|
// #2909: postflight — restore stashed changes after successful merge
|
|
576
576
|
if (preflightAllComplete.stashPushed) {
|
|
577
|
-
deps.postflightPopStash(s.originalBasePath || s.basePath, s.currentMilestoneId, ctx.ui.notify.bind(ctx.ui));
|
|
577
|
+
deps.postflightPopStash(s.originalBasePath || s.basePath, s.currentMilestoneId, preflightAllComplete.stashMarker, ctx.ui.notify.bind(ctx.ui));
|
|
578
578
|
}
|
|
579
579
|
// PR creation (auto_pr) is handled inside mergeMilestoneToMain (#2302)
|
|
580
580
|
}
|
|
@@ -660,7 +660,7 @@ export async function runPreDispatch(ic, loopState) {
|
|
|
660
660
|
}
|
|
661
661
|
// #2909: postflight — restore stashed changes after successful merge
|
|
662
662
|
if (preflightComplete.stashPushed) {
|
|
663
|
-
deps.postflightPopStash(s.originalBasePath || s.basePath, s.currentMilestoneId, ctx.ui.notify.bind(ctx.ui));
|
|
663
|
+
deps.postflightPopStash(s.originalBasePath || s.basePath, s.currentMilestoneId, preflightComplete.stashMarker, ctx.ui.notify.bind(ctx.ui));
|
|
664
664
|
}
|
|
665
665
|
// PR creation (auto_pr) is handled inside mergeMilestoneToMain (#2302)
|
|
666
666
|
}
|
|
@@ -1084,8 +1084,9 @@ export async function runUnitPhase(ic, iterData, loopState, sidecarItem) {
|
|
|
1084
1084
|
// Verify the working directory is a valid git checkout with project
|
|
1085
1085
|
// files before dispatching work. A broken worktree causes agents to
|
|
1086
1086
|
// hallucinate summaries since they cannot read or write any files.
|
|
1087
|
-
// Uses
|
|
1088
|
-
//
|
|
1087
|
+
// Uses project classification so project presence is not conflated with
|
|
1088
|
+
// ecosystem marker detection. Static/minimal repos become untyped-existing.
|
|
1089
|
+
let projectClassification = null;
|
|
1089
1090
|
if (s.basePath && unitType === "execute-task") {
|
|
1090
1091
|
const gitMarker = join(s.basePath, ".git");
|
|
1091
1092
|
const hasGit = deps.existsSync(gitMarker);
|
|
@@ -1096,30 +1097,26 @@ export async function runUnitPhase(ic, iterData, loopState, sidecarItem) {
|
|
|
1096
1097
|
await deps.stopAuto(ctx, pi, msg);
|
|
1097
1098
|
return { action: "break", reason: "worktree-invalid" };
|
|
1098
1099
|
}
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1100
|
+
projectClassification = classifyProject(s.basePath);
|
|
1101
|
+
if (projectClassification.kind === "invalid-repo") {
|
|
1102
|
+
const msg = `Worktree health check failed: ${s.basePath} classified as invalid-repo (${projectClassification.reason}) — refusing to dispatch ${unitType} ${unitId}`;
|
|
1103
|
+
debugLog("runUnitPhase", { phase: "worktree-health-invalid-repo", basePath: s.basePath, classification: projectClassification });
|
|
1104
|
+
if (projectClassification.reason === "missing .git" && hasGit) {
|
|
1105
|
+
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");
|
|
1106
|
+
}
|
|
1107
|
+
else {
|
|
1108
|
+
ctx.ui.notify(msg, "error");
|
|
1109
|
+
await deps.stopAuto(ctx, pi, msg);
|
|
1110
|
+
return { action: "break", reason: "worktree-invalid" };
|
|
1111
|
+
}
|
|
1107
1112
|
}
|
|
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");
|
|
1113
|
+
else if (projectClassification.kind === "greenfield") {
|
|
1114
|
+
debugLog("runUnitPhase", { phase: "worktree-health-greenfield", basePath: s.basePath, classification: projectClassification });
|
|
1115
|
+
ctx.ui.notify(`Warning: ${s.basePath} has no project content yet — proceeding as greenfield project`, "warning");
|
|
1116
|
+
}
|
|
1117
|
+
else if (projectClassification.kind === "untyped-existing") {
|
|
1118
|
+
debugLog("runUnitPhase", { phase: "worktree-health-untyped-existing", basePath: s.basePath, classification: projectClassification });
|
|
1119
|
+
ctx.ui.notify(`Notice: ${s.basePath} has existing project content but no recognized tooling markers — using generic file-level workflow guidance`, "info");
|
|
1123
1120
|
}
|
|
1124
1121
|
}
|
|
1125
1122
|
// Detect retry and capture previous tier for escalation
|
|
@@ -1182,6 +1179,16 @@ export async function runUnitPhase(ic, iterData, loopState, sidecarItem) {
|
|
|
1182
1179
|
}
|
|
1183
1180
|
// Prompt injection
|
|
1184
1181
|
let finalPrompt = prompt;
|
|
1182
|
+
if (unitType === "execute-task") {
|
|
1183
|
+
projectClassification ??= classifyProject(s.basePath);
|
|
1184
|
+
if (projectClassification.kind === "untyped-existing") {
|
|
1185
|
+
const samples = projectClassification.contentFiles.slice(0, 8).join(", ") || "project files";
|
|
1186
|
+
finalPrompt +=
|
|
1187
|
+
"\n\n**Project classification:** Existing untyped project. No recognized build/tooling markers were detected, " +
|
|
1188
|
+
"so use generic file-level workflow guidance. Task plans and completion summaries must list every concrete " +
|
|
1189
|
+
`project file changed in \`files\` or \`expected_output\`. Detected content sample: ${samples}.`;
|
|
1190
|
+
}
|
|
1191
|
+
}
|
|
1185
1192
|
if (s.pendingVerificationRetry) {
|
|
1186
1193
|
const retryCtx = s.pendingVerificationRetry;
|
|
1187
1194
|
s.pendingVerificationRetry = 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
3
|
import { _clearCurrentResolve, _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;
|
|
@@ -151,22 +148,29 @@ export async function runUnit(ctx, pi, s, unitType, unitId, prompt) {
|
|
|
151
148
|
// ── Send the prompt ──
|
|
152
149
|
debugLog("runUnit", { phase: "send-message", unitType, unitId });
|
|
153
150
|
const requestDispatchedAt = Date.now();
|
|
154
|
-
|
|
151
|
+
ctx.ui.setWorkingMessage?.(formatAutoUnitWorkingMessage(unitType, unitId));
|
|
155
152
|
// ── Await agent_end with absolute timeout (H4 fix) ──
|
|
156
153
|
// If supervision fails to resolve unitPromise within 30s, treat as cancelled.
|
|
157
154
|
// Without this, a crashed agent that never emits agent_end hangs the loop (#3161).
|
|
158
|
-
debugLog("runUnit", { phase: "awaiting-agent-end", unitType, unitId });
|
|
159
155
|
const supervisor = resolveAutoSupervisorConfig();
|
|
160
156
|
const UNIT_HARD_TIMEOUT_MS = Math.max(30_000, ((supervisor.hard_timeout_minutes ?? 30) * 60 * 1000) + 30_000);
|
|
161
157
|
let unitTimeoutHandle;
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
158
|
+
let result;
|
|
159
|
+
try {
|
|
160
|
+
pi.sendMessage({ customType: "gsd-auto", content: prompt, display: s.verbose }, { triggerTurn: true });
|
|
161
|
+
debugLog("runUnit", { phase: "awaiting-agent-end", unitType, unitId });
|
|
162
|
+
const timeoutResult = new Promise((resolve) => {
|
|
163
|
+
unitTimeoutHandle = setTimeout(() => {
|
|
164
|
+
resolve({ status: "cancelled", errorContext: { message: "Unit hard timeout — supervision may have failed", category: "timeout", isTransient: true } });
|
|
165
|
+
}, UNIT_HARD_TIMEOUT_MS);
|
|
166
|
+
});
|
|
167
|
+
result = await runWithTurnGeneration(capturedTurnGen, () => Promise.race([unitPromise, timeoutResult]));
|
|
168
|
+
}
|
|
169
|
+
finally {
|
|
170
|
+
if (unitTimeoutHandle)
|
|
171
|
+
clearTimeout(unitTimeoutHandle);
|
|
172
|
+
ctx.ui.setWorkingMessage?.(undefined);
|
|
173
|
+
}
|
|
170
174
|
debugLog("runUnit", {
|
|
171
175
|
phase: "agent-end-received",
|
|
172
176
|
unitType,
|
|
@@ -1,10 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
* Auto-mode Dashboard — progress widget rendering, elapsed time formatting,
|
|
3
|
-
* unit description helpers, and slice progress caching.
|
|
4
|
-
*
|
|
5
|
-
* Pure functions that accept specific parameters — no module-level globals
|
|
6
|
-
* or AutoContext dependency. State accessors are passed as callbacks.
|
|
7
|
-
*/
|
|
1
|
+
// GSD-2 + src/resources/extensions/gsd/auto-dashboard.ts - Auto-mode progress widget rendering and dashboard helpers.
|
|
8
2
|
import { getCurrentBranch } from "./worktree.js";
|
|
9
3
|
import { getActiveHook } from "./post-unit-hooks.js";
|
|
10
4
|
import { getLedger, getProjectTotals } from "./metrics.js";
|
|
@@ -25,6 +19,7 @@ import { formatRtkSavingsLabel, getRtkSessionSavings, } from "../shared/rtk-sess
|
|
|
25
19
|
import { logWarning } from "./workflow-logger.js";
|
|
26
20
|
import { formattedShortcutPair } from "./shortcut-defs.js";
|
|
27
21
|
import { homedir } from "node:os";
|
|
22
|
+
import { readUnitRuntimeRecord } from "./unit-runtime.js";
|
|
28
23
|
// ─── UAT Slice Extraction ─────────────────────────────────────────────────────
|
|
29
24
|
/**
|
|
30
25
|
* Extract the target slice ID from a run-uat unit ID (e.g. "M001/S01" → "S01").
|
|
@@ -165,6 +160,30 @@ export function formatWidgetTokens(count) {
|
|
|
165
160
|
return `${(count / 1000000).toFixed(1)}M`;
|
|
166
161
|
return `${Math.round(count / 1000000)}M`;
|
|
167
162
|
}
|
|
163
|
+
export function formatRuntimeHealthSignal(record, now = Date.now()) {
|
|
164
|
+
if (!record)
|
|
165
|
+
return null;
|
|
166
|
+
const idleMs = Math.max(0, now - record.lastProgressAt);
|
|
167
|
+
const idleMinutes = Math.floor(idleMs / 60_000);
|
|
168
|
+
if ((record.recoveryAttempts ?? 0) > 0 || record.phase === "recovered" || record.lastProgressKind.includes("recovery")) {
|
|
169
|
+
return {
|
|
170
|
+
level: "yellow",
|
|
171
|
+
summary: "Recovering",
|
|
172
|
+
detail: `retry ${record.recoveryAttempts ?? 1} after ${record.lastRecoveryReason ?? "idle"} stall`,
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
if (record.progressCount === 0 && idleMs >= 60_000) {
|
|
176
|
+
return {
|
|
177
|
+
level: "yellow",
|
|
178
|
+
summary: "Waiting on provider",
|
|
179
|
+
detail: `no output for ${idleMinutes}m`,
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
return null;
|
|
183
|
+
}
|
|
184
|
+
export function shouldRenderRoadmapProgress(progress) {
|
|
185
|
+
return !!progress && progress.total > 0;
|
|
186
|
+
}
|
|
168
187
|
// ─── ETA Estimation ──────────────────────────────────────────────────────────
|
|
169
188
|
/**
|
|
170
189
|
* Estimate remaining time based on average unit duration from the metrics ledger.
|
|
@@ -499,6 +518,7 @@ export function updateProgressWidget(ctx, unitType, unitId, state, accessors, ti
|
|
|
499
518
|
let cachedLines;
|
|
500
519
|
let cachedWidth;
|
|
501
520
|
let cachedRtkLabel;
|
|
521
|
+
let cachedRuntimeRecord = null;
|
|
502
522
|
const refreshRtkLabel = () => {
|
|
503
523
|
try {
|
|
504
524
|
const sessionId = ctx.sessionManager.getSessionId();
|
|
@@ -510,7 +530,16 @@ export function updateProgressWidget(ctx, unitType, unitId, state, accessors, ti
|
|
|
510
530
|
cachedRtkLabel = null;
|
|
511
531
|
}
|
|
512
532
|
};
|
|
533
|
+
const refreshRuntimeRecord = () => {
|
|
534
|
+
try {
|
|
535
|
+
cachedRuntimeRecord = readUnitRuntimeRecord(accessors.getBasePath(), unitType, unitId);
|
|
536
|
+
}
|
|
537
|
+
catch {
|
|
538
|
+
cachedRuntimeRecord = null;
|
|
539
|
+
}
|
|
540
|
+
};
|
|
513
541
|
refreshRtkLabel();
|
|
542
|
+
refreshRuntimeRecord();
|
|
514
543
|
const pulseTimer = setInterval(() => {
|
|
515
544
|
pulseBright = !pulseBright;
|
|
516
545
|
cachedLines = undefined;
|
|
@@ -526,6 +555,7 @@ export function updateProgressWidget(ctx, unitType, unitId, state, accessors, ti
|
|
|
526
555
|
updateSliceProgressCache(accessors.getBasePath(), mid.id, slice?.id);
|
|
527
556
|
}
|
|
528
557
|
refreshRtkLabel();
|
|
558
|
+
refreshRuntimeRecord();
|
|
529
559
|
cachedLines = undefined;
|
|
530
560
|
}
|
|
531
561
|
catch (err) { /* non-fatal */
|
|
@@ -555,13 +585,16 @@ export function updateProgressWidget(ctx, unitType, unitId, state, accessors, ti
|
|
|
555
585
|
const modeTag = accessors.isStepMode() ? "NEXT" : "AUTO";
|
|
556
586
|
// Health indicator in header
|
|
557
587
|
const score = computeProgressScore();
|
|
558
|
-
const
|
|
559
|
-
|
|
588
|
+
const runtimeSignal = formatRuntimeHealthSignal(cachedRuntimeRecord);
|
|
589
|
+
const healthLevel = runtimeSignal?.level ?? score.level;
|
|
590
|
+
const healthSummary = runtimeSignal?.summary ?? score.summary;
|
|
591
|
+
const healthColor = healthLevel === "green" ? "success"
|
|
592
|
+
: healthLevel === "yellow" ? "warning"
|
|
560
593
|
: "error";
|
|
561
|
-
const healthIcon =
|
|
562
|
-
:
|
|
594
|
+
const healthIcon = healthLevel === "green" ? GLYPH.statusActive
|
|
595
|
+
: healthLevel === "yellow" ? "!"
|
|
563
596
|
: "x";
|
|
564
|
-
const healthStr = ` ${theme.fg(healthColor, healthIcon)} ${theme.fg(healthColor,
|
|
597
|
+
const healthStr = ` ${theme.fg(healthColor, healthIcon)} ${theme.fg(healthColor, healthSummary)}`;
|
|
565
598
|
const headerLeft = `${pad}${dot} ${theme.fg("accent", theme.bold("GSD"))} ${theme.fg("success", modeTag)}${healthStr}`;
|
|
566
599
|
// ETA in header right, after elapsed
|
|
567
600
|
const eta = estimateTimeRemaining();
|
|
@@ -573,7 +606,10 @@ export function updateProgressWidget(ctx, unitType, unitId, state, accessors, ti
|
|
|
573
606
|
: "";
|
|
574
607
|
lines.push(rightAlign(headerLeft, headerRight, width));
|
|
575
608
|
// Show health signal details when degraded (yellow/red)
|
|
576
|
-
if (
|
|
609
|
+
if (runtimeSignal?.detail && widgetMode !== "min") {
|
|
610
|
+
lines.push(`${pad} ${theme.fg("dim", runtimeSignal.detail)}`);
|
|
611
|
+
}
|
|
612
|
+
else if (score.level !== "green" && score.signals.length > 0 && widgetMode !== "min") {
|
|
577
613
|
// Show up to 3 most relevant signals in compact form
|
|
578
614
|
const topSignals = score.signals
|
|
579
615
|
.filter(s => s.kind === "negative")
|
|
@@ -645,7 +681,7 @@ export function updateProgressWidget(ctx, unitType, unitId, state, accessors, ti
|
|
|
645
681
|
lines.push(rightAlign(actionLeft, theme.fg("dim", phaseLabel), width));
|
|
646
682
|
// Progress bar
|
|
647
683
|
const roadmapSlices = mid ? getRoadmapSlicesSync() : null;
|
|
648
|
-
if (roadmapSlices) {
|
|
684
|
+
if (shouldRenderRoadmapProgress(roadmapSlices)) {
|
|
649
685
|
const { done, total, activeSliceTasks } = roadmapSlices;
|
|
650
686
|
const barWidth = Math.max(6, Math.min(18, Math.floor(width * 0.25)));
|
|
651
687
|
const pct = total > 0 ? done / total : 0;
|
|
@@ -706,7 +742,7 @@ export function updateProgressWidget(ctx, unitType, unitId, state, accessors, ti
|
|
|
706
742
|
? Math.floor(width * (width >= 100 ? 0.45 : 0.50))
|
|
707
743
|
: width;
|
|
708
744
|
const leftLines = [];
|
|
709
|
-
if (roadmapSlices) {
|
|
745
|
+
if (shouldRenderRoadmapProgress(roadmapSlices)) {
|
|
710
746
|
const { done, total, activeSliceTasks } = roadmapSlices;
|
|
711
747
|
const barWidth = Math.max(6, Math.min(18, Math.floor(leftColWidth * 0.4)));
|
|
712
748
|
const pct = total > 0 ? done / total : 0;
|
|
@@ -93,6 +93,16 @@ export function hasPendingDeepStage(prefs, basePath) {
|
|
|
93
93
|
const gate = getDeepStageGate(prefs, basePath);
|
|
94
94
|
return gate.status === "pending" || gate.status === "blocked";
|
|
95
95
|
}
|
|
96
|
+
export function shouldRunDeepProjectSetup(state, prefs, basePath, options = {}) {
|
|
97
|
+
if (options.hasSurvivorBranch === true)
|
|
98
|
+
return false;
|
|
99
|
+
if (state.phase !== "pre-planning" &&
|
|
100
|
+
state.phase !== "needs-discussion" &&
|
|
101
|
+
state.phase !== "planning") {
|
|
102
|
+
return false;
|
|
103
|
+
}
|
|
104
|
+
return hasPendingDeepStage(prefs, basePath);
|
|
105
|
+
}
|
|
96
106
|
function missingSliceStop(mid, phase) {
|
|
97
107
|
return {
|
|
98
108
|
action: "stop",
|
|
@@ -25,7 +25,7 @@ import { verifyExpectedArtifact, resolveExpectedArtifactPath, writeBlockerPlaceh
|
|
|
25
25
|
import { regenerateIfMissing } from "./workflow-projections.js";
|
|
26
26
|
import { syncStateToProjectRoot } from "./auto-worktree.js";
|
|
27
27
|
import { normalizeWorktreePathForCompare } from "./worktree-root.js";
|
|
28
|
-
import { isDbAvailable, getTask, getSlice, getMilestone, updateTaskStatus, _getAdapter } from "./gsd-db.js";
|
|
28
|
+
import { isDbAvailable, getTask, getSlice, getMilestone, updateTaskStatus, _getAdapter, getVerificationEvidence } from "./gsd-db.js";
|
|
29
29
|
import { renderPlanCheckboxes } from "./markdown-renderer.js";
|
|
30
30
|
import { consumeSignal } from "./session-status-io.js";
|
|
31
31
|
import { checkPostUnitHooks, isRetryPending, consumeRetryTrigger, persistHookState, resolveHookArtifactPath, } from "./post-unit-hooks.js";
|
|
@@ -719,21 +719,21 @@ export async function postUnitPreVerification(pctx, opts) {
|
|
|
719
719
|
}
|
|
720
720
|
}
|
|
721
721
|
// Evidence cross-reference (execute-task only)
|
|
722
|
-
//
|
|
723
|
-
//
|
|
724
|
-
//
|
|
725
|
-
// we can still detect units that claimed success but ran no commands.
|
|
722
|
+
// Only compare against concrete command evidence persisted by the task
|
|
723
|
+
// completion tool. A prose Verify field can be satisfied later by the
|
|
724
|
+
// host verification gate, so it is not enough to accuse the unit.
|
|
726
725
|
if (safetyConfig.evidence_cross_reference && s.currentUnit.type === "execute-task") {
|
|
727
726
|
try {
|
|
728
727
|
const actual = getEvidence();
|
|
729
728
|
const bashCalls = actual.filter(e => e.kind === "bash");
|
|
730
|
-
// If the task is marked complete but zero bash commands were run,
|
|
731
|
-
// it's suspicious — the LLM may have fabricated results.
|
|
732
729
|
if (sMid && sSid && sTid && isDbAvailable()) {
|
|
733
730
|
const taskRow = getTask(sMid, sSid, sTid);
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
731
|
+
const claimedCommands = getVerificationEvidence(sMid, sSid, sTid)
|
|
732
|
+
.map((row) => row.command)
|
|
733
|
+
.filter((command) => typeof command === "string" && command.trim().length > 0);
|
|
734
|
+
if (taskRow?.status === "complete" && claimedCommands.length > 0 && bashCalls.length === 0) {
|
|
735
|
+
logWarning("safety", "task claimed verification command evidence but no execution tool calls were recorded");
|
|
736
|
+
ctx.ui.notify(`Safety: task ${sTid} claimed command evidence but no execution tool calls were recorded`, "warning");
|
|
737
737
|
}
|
|
738
738
|
}
|
|
739
739
|
}
|