gsd-pi 2.42.0-dev.97e9e30 → 2.43.0-next.1
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/extensions/gsd/auto-post-unit.js +81 -6
- package/dist/resources/extensions/gsd/auto-recovery.js +58 -126
- package/dist/resources/extensions/gsd/auto-timeout-recovery.js +4 -7
- package/dist/resources/extensions/gsd/auto-worktree.js +22 -12
- package/dist/resources/extensions/gsd/auto.js +1 -1
- package/dist/resources/extensions/gsd/bootstrap/db-tools.js +168 -0
- package/dist/resources/extensions/gsd/bootstrap/dynamic-tools.js +28 -3
- package/dist/resources/extensions/gsd/commands/catalog.js +3 -1
- package/dist/resources/extensions/gsd/commands/handlers/ops.js +15 -1
- package/dist/resources/extensions/gsd/commands-handlers.js +1 -1
- package/dist/resources/extensions/gsd/commands-maintenance.js +60 -2
- package/dist/resources/extensions/gsd/doctor-types.js +0 -15
- package/dist/resources/extensions/gsd/doctor.js +1 -274
- package/dist/resources/extensions/gsd/git-constants.js +1 -0
- package/dist/resources/extensions/gsd/git-service.js +68 -2
- package/dist/resources/extensions/gsd/gsd-db.js +467 -2
- package/dist/resources/extensions/gsd/markdown-renderer.js +562 -0
- package/dist/resources/extensions/gsd/md-importer.js +154 -4
- package/dist/resources/extensions/gsd/native-git-bridge.js +1 -0
- package/dist/resources/extensions/gsd/prompts/complete-slice.md +22 -9
- package/dist/resources/extensions/gsd/prompts/execute-task.md +15 -5
- package/dist/resources/extensions/gsd/prompts/forensics.md +10 -5
- package/dist/resources/extensions/gsd/prompts/guided-complete-slice.md +1 -1
- package/dist/resources/extensions/gsd/prompts/guided-execute-task.md +1 -1
- package/dist/resources/extensions/gsd/prompts/reactive-execute.md +3 -3
- package/dist/resources/extensions/gsd/state.js +451 -11
- package/dist/resources/extensions/gsd/tools/complete-slice.js +244 -0
- package/dist/resources/extensions/gsd/tools/complete-task.js +204 -0
- package/dist/resources/extensions/gsd/undo.js +197 -3
- package/dist/web/standalone/.next/BUILD_ID +1 -1
- package/dist/web/standalone/.next/app-path-routes-manifest.json +14 -14
- 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/required-server-files.json +3 -3
- package/dist/web/standalone/.next/server/app/_global-error/page.js +3 -3
- package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.html +2 -2
- 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/page.js +2 -2
- package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.rsc +3 -3
- package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +3 -3
- 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 +3 -3
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/api/boot/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/boot/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/browse-directories/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/browse-directories/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/captures/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/captures/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/cleanup/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/cleanup/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/dev-mode/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/dev-mode/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/doctor/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/doctor/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/export-data/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/export-data/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/files/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/files/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/forensics/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/forensics/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/git/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/history/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/history/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/hooks/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/hooks/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/inspect/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/inspect/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/knowledge/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/knowledge/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/live-state/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/live-state/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/onboarding/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/onboarding/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/preferences/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/preferences/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/projects/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/projects/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/recovery/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/recovery/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/remote-questions/route.js +5 -5
- package/dist/web/standalone/.next/server/app/api/remote-questions/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/browser/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/browser/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/command/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/command/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/events/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/session/events/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/manage/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/manage/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/settings-data/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/settings-data/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/shutdown/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/shutdown/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/skill-health/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/skill-health/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/steer/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/steer/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/input/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/input/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/resize/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/terminal/resize/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/terminal/sessions/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js +4 -4
- package/dist/web/standalone/.next/server/app/api/terminal/stream/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/upload/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/upload/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/undo/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/undo/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/update/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/visualizer/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/visualizer/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/index.html +1 -1
- package/dist/web/standalone/.next/server/app/index.rsc +4 -4
- package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
- package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +4 -4
- 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 +3 -3
- package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/page.js +2 -2
- package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app-paths-manifest.json +14 -14
- package/dist/web/standalone/.next/server/chunks/229.js +2 -2
- package/dist/web/standalone/.next/server/chunks/471.js +3 -3
- package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
- package/dist/web/standalone/.next/server/middleware.js +2 -2
- package/dist/web/standalone/.next/server/next-font-manifest.js +1 -1
- package/dist/web/standalone/.next/server/next-font-manifest.json +1 -1
- package/dist/web/standalone/.next/server/pages/404.html +1 -1
- package/dist/web/standalone/.next/server/pages/500.html +2 -2
- package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
- package/dist/web/standalone/.next/static/chunks/app/_not-found/page-e07acdb7dd069836.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/layout-745c6ed5fea5fb06.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/page-801b53eff6e83579.js +1 -0
- package/dist/web/standalone/.next/static/chunks/{main-app-fdab67f7802d7832.js → main-app-2f2ee7b85712c2bd.js} +1 -1
- package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-e6255954dccfcf0a.js +1 -0
- package/dist/web/standalone/node_modules/node-pty/build/Makefile +2 -2
- package/dist/web/standalone/node_modules/node-pty/build/Release/pty.node +0 -0
- package/dist/web/standalone/node_modules/node-pty/build/pty.target.mk +14 -14
- package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api.target.mk +14 -14
- package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_except.target.mk +14 -14
- package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_maybe.target.mk +14 -14
- package/dist/web/standalone/server.js +1 -1
- package/dist/web-mode.d.ts +2 -0
- package/dist/web-mode.js +30 -1
- package/package.json +1 -1
- package/packages/pi-agent-core/dist/agent.d.ts.map +1 -1
- package/packages/pi-agent-core/dist/agent.js +2 -0
- package/packages/pi-agent-core/dist/agent.js.map +1 -1
- package/packages/pi-agent-core/dist/types.d.ts +6 -0
- package/packages/pi-agent-core/dist/types.d.ts.map +1 -1
- package/packages/pi-agent-core/dist/types.js.map +1 -1
- package/packages/pi-agent-core/src/agent.test.ts +53 -0
- package/packages/pi-agent-core/src/agent.ts +3 -0
- package/packages/pi-agent-core/src/types.ts +6 -0
- package/packages/pi-agent-core/tsconfig.json +1 -1
- package/packages/pi-ai/dist/models.d.ts +5 -3
- package/packages/pi-ai/dist/models.d.ts.map +1 -1
- package/packages/pi-ai/dist/models.generated.d.ts +801 -1468
- package/packages/pi-ai/dist/models.generated.d.ts.map +1 -1
- package/packages/pi-ai/dist/models.generated.js +1135 -1588
- package/packages/pi-ai/dist/models.generated.js.map +1 -1
- package/packages/pi-ai/dist/models.js.map +1 -1
- package/packages/pi-ai/dist/utils/oauth/github-copilot.d.ts.map +1 -1
- package/packages/pi-ai/dist/utils/oauth/github-copilot.js +60 -2
- package/packages/pi-ai/dist/utils/oauth/github-copilot.js.map +1 -1
- package/packages/pi-ai/scripts/generate-models.ts +1543 -0
- package/packages/pi-ai/src/models.generated.ts +1140 -1593
- package/packages/pi-ai/src/models.ts +7 -4
- package/packages/pi-ai/src/utils/oauth/github-copilot.ts +74 -2
- package/packages/pi-coding-agent/dist/core/auth-storage.d.ts +7 -0
- package/packages/pi-coding-agent/dist/core/auth-storage.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/auth-storage.js +23 -0
- package/packages/pi-coding-agent/dist/core/auth-storage.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 +2 -0
- package/packages/pi-coding-agent/dist/core/model-registry.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/footer.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/footer.js +9 -6
- package/packages/pi-coding-agent/dist/modes/interactive/components/footer.js.map +1 -1
- package/packages/pi-coding-agent/src/core/auth-storage.ts +25 -0
- package/packages/pi-coding-agent/src/core/model-registry.ts +3 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/footer.ts +10 -6
- package/pkg/package.json +1 -1
- package/src/resources/extensions/gsd/auto-post-unit.ts +93 -5
- package/src/resources/extensions/gsd/auto-recovery.ts +53 -134
- package/src/resources/extensions/gsd/auto-timeout-recovery.ts +6 -7
- package/src/resources/extensions/gsd/auto-worktree.ts +21 -11
- package/src/resources/extensions/gsd/auto.ts +0 -2
- package/src/resources/extensions/gsd/bootstrap/db-tools.ts +194 -0
- package/src/resources/extensions/gsd/bootstrap/dynamic-tools.ts +31 -3
- package/src/resources/extensions/gsd/commands/catalog.ts +3 -1
- package/src/resources/extensions/gsd/commands/handlers/ops.ts +15 -1
- package/src/resources/extensions/gsd/commands-handlers.ts +1 -1
- package/src/resources/extensions/gsd/commands-maintenance.ts +69 -2
- package/src/resources/extensions/gsd/doctor-types.ts +0 -23
- package/src/resources/extensions/gsd/doctor.ts +1 -288
- package/src/resources/extensions/gsd/git-constants.ts +1 -0
- package/src/resources/extensions/gsd/git-service.ts +71 -2
- package/src/resources/extensions/gsd/gsd-db.ts +638 -1
- package/src/resources/extensions/gsd/markdown-renderer.ts +721 -0
- package/src/resources/extensions/gsd/md-importer.ts +182 -2
- package/src/resources/extensions/gsd/native-git-bridge.ts +1 -0
- package/src/resources/extensions/gsd/prompts/complete-slice.md +22 -9
- package/src/resources/extensions/gsd/prompts/execute-task.md +15 -5
- package/src/resources/extensions/gsd/prompts/forensics.md +10 -5
- package/src/resources/extensions/gsd/prompts/guided-complete-slice.md +1 -1
- package/src/resources/extensions/gsd/prompts/guided-execute-task.md +1 -1
- package/src/resources/extensions/gsd/prompts/reactive-execute.md +3 -3
- package/src/resources/extensions/gsd/state.ts +510 -11
- package/src/resources/extensions/gsd/tests/atomic-task-closeout.test.ts +8 -120
- package/src/resources/extensions/gsd/tests/auto-preflight.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +3 -4
- package/src/resources/extensions/gsd/tests/complete-slice.test.ts +410 -0
- package/src/resources/extensions/gsd/tests/complete-task.test.ts +439 -0
- package/src/resources/extensions/gsd/tests/derive-state-crossval.test.ts +527 -0
- package/src/resources/extensions/gsd/tests/derive-state-db.test.ts +583 -2
- package/src/resources/extensions/gsd/tests/doctor-completion-deferral.test.ts +22 -80
- package/src/resources/extensions/gsd/tests/doctor-enhancements.test.ts +5 -7
- package/src/resources/extensions/gsd/tests/doctor-fixlevel.test.ts +38 -130
- package/src/resources/extensions/gsd/tests/doctor-roadmap-summary-atomicity.test.ts +38 -76
- package/src/resources/extensions/gsd/tests/doctor.test.ts +9 -19
- package/src/resources/extensions/gsd/tests/forensics-issue-routing.test.ts +43 -0
- package/src/resources/extensions/gsd/tests/git-locale.test.ts +133 -0
- package/src/resources/extensions/gsd/tests/git-service.test.ts +49 -0
- package/src/resources/extensions/gsd/tests/gsd-db.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/gsd-recover.test.ts +356 -0
- package/src/resources/extensions/gsd/tests/idle-recovery.test.ts +4 -172
- package/src/resources/extensions/gsd/tests/integration-proof.test.ts +643 -0
- package/src/resources/extensions/gsd/tests/markdown-renderer.test.ts +1071 -0
- package/src/resources/extensions/gsd/tests/md-importer.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/memory-store.test.ts +2 -2
- package/src/resources/extensions/gsd/tests/migrate-hierarchy.test.ts +439 -0
- package/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +79 -0
- package/src/resources/extensions/gsd/tests/rogue-file-detection.test.ts +185 -0
- package/src/resources/extensions/gsd/tests/shared-wal.test.ts +216 -0
- package/src/resources/extensions/gsd/tests/tool-naming.test.ts +4 -2
- package/src/resources/extensions/gsd/tests/undo.test.ts +321 -1
- package/src/resources/extensions/gsd/tests/validate-milestone.test.ts +1 -1
- package/src/resources/extensions/gsd/tools/complete-slice.ts +300 -0
- package/src/resources/extensions/gsd/tools/complete-task.ts +245 -0
- package/src/resources/extensions/gsd/types.ts +50 -0
- package/src/resources/extensions/gsd/undo.ts +247 -3
- package/dist/resources/extensions/gsd/roadmap-mutations.js +0 -110
- package/dist/web/standalone/.next/static/chunks/app/_not-found/page-f2a7482d42a5614b.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/layout-a16c7a7ecdf0c2cf.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/page-b9367c5ae13b99c6.js +0 -1
- package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-459824ffb8c323dd.js +0 -1
- package/src/resources/extensions/gsd/roadmap-mutations.ts +0 -134
- package/src/resources/extensions/gsd/tests/doctor-task-done-missing-summary-slice-loop.test.ts +0 -174
- /package/dist/web/standalone/.next/static/{PXrI5DoWsm7rwAVnEU2rD → 35A5zXBIDa1N0K7NO5i0b}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{PXrI5DoWsm7rwAVnEU2rD → 35A5zXBIDa1N0K7NO5i0b}/_ssgManifest.js +0 -0
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
import { deriveState } from "./state.js";
|
|
14
14
|
import { loadFile, parseSummary, resolveAllOverrides } from "./files.js";
|
|
15
15
|
import { loadPrompt } from "./prompt-loader.js";
|
|
16
|
-
import { resolveSliceFile, resolveTaskFile, resolveMilestoneFile, resolveTasksDir, buildTaskFileName, gsdRoot, } from "./paths.js";
|
|
16
|
+
import { resolveSliceFile, resolveSlicePath, resolveTaskFile, resolveMilestoneFile, resolveTasksDir, buildTaskFileName, gsdRoot, } from "./paths.js";
|
|
17
17
|
import { invalidateAllCaches } from "./cache.js";
|
|
18
18
|
import { closeoutUnit } from "./auto-unit-closeout.js";
|
|
19
19
|
import { autoCommitCurrentBranch, } from "./worktree.js";
|
|
@@ -22,16 +22,56 @@ import { writeUnitRuntimeRecord, clearUnitRuntimeRecord } from "./unit-runtime.j
|
|
|
22
22
|
import { runGSDDoctor, rebuildState, summarizeDoctorIssues } from "./doctor.js";
|
|
23
23
|
import { recordHealthSnapshot, checkHealEscalation } from "./doctor-proactive.js";
|
|
24
24
|
import { syncStateToProjectRoot } from "./auto-worktree-sync.js";
|
|
25
|
-
import { isDbAvailable } from "./gsd-db.js";
|
|
25
|
+
import { isDbAvailable, getTask, getSlice, updateTaskStatus } from "./gsd-db.js";
|
|
26
|
+
import { renderPlanCheckboxes } from "./markdown-renderer.js";
|
|
26
27
|
import { consumeSignal } from "./session-status-io.js";
|
|
27
28
|
import { checkPostUnitHooks, isRetryPending, consumeRetryTrigger, persistHookState, resolveHookArtifactPath, } from "./post-unit-hooks.js";
|
|
28
29
|
import { hasPendingCaptures, loadPendingCaptures } from "./captures.js";
|
|
29
30
|
import { debugLog } from "./debug-logger.js";
|
|
30
|
-
import { existsSync, unlinkSync } from "node:fs";
|
|
31
|
+
import { existsSync, unlinkSync, readFileSync, writeFileSync } from "node:fs";
|
|
31
32
|
import { join } from "node:path";
|
|
32
|
-
import { uncheckTaskInPlan } from "./undo.js";
|
|
33
33
|
import { atomicWriteSync } from "./atomic-write.js";
|
|
34
34
|
import { _resetHasChangesCache } from "./native-git-bridge.js";
|
|
35
|
+
/**
|
|
36
|
+
* Detect summary files written directly to disk without the LLM calling
|
|
37
|
+
* the completion tool. A "rogue" file is one that exists on disk but has
|
|
38
|
+
* no corresponding DB row with status "complete".
|
|
39
|
+
*
|
|
40
|
+
* This is a safety-net diagnostic (D003). The existing migrateFromMarkdown()
|
|
41
|
+
* in postUnitPostVerification() eventually ingests rogue files, but explicit
|
|
42
|
+
* detection provides immediate diagnostics so operators know the prompt failed.
|
|
43
|
+
*/
|
|
44
|
+
export function detectRogueFileWrites(unitType, unitId, basePath) {
|
|
45
|
+
if (!isDbAvailable())
|
|
46
|
+
return [];
|
|
47
|
+
const parts = unitId.split("/");
|
|
48
|
+
const rogues = [];
|
|
49
|
+
if (unitType === "execute-task") {
|
|
50
|
+
const [mid, sid, tid] = parts;
|
|
51
|
+
if (!mid || !sid || !tid)
|
|
52
|
+
return [];
|
|
53
|
+
const summaryPath = resolveTaskFile(basePath, mid, sid, tid, "SUMMARY");
|
|
54
|
+
if (!summaryPath || !existsSync(summaryPath))
|
|
55
|
+
return [];
|
|
56
|
+
const dbRow = getTask(mid, sid, tid);
|
|
57
|
+
if (!dbRow || dbRow.status !== "complete") {
|
|
58
|
+
rogues.push({ path: summaryPath, unitType, unitId });
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
else if (unitType === "complete-slice") {
|
|
62
|
+
const [mid, sid] = parts;
|
|
63
|
+
if (!mid || !sid)
|
|
64
|
+
return [];
|
|
65
|
+
const summaryPath = resolveSliceFile(basePath, mid, sid, "SUMMARY");
|
|
66
|
+
if (!summaryPath || !existsSync(summaryPath))
|
|
67
|
+
return [];
|
|
68
|
+
const dbRow = getSlice(mid, sid);
|
|
69
|
+
if (!dbRow || dbRow.status !== "complete") {
|
|
70
|
+
rogues.push({ path: summaryPath, unitType, unitId });
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
return rogues;
|
|
74
|
+
}
|
|
35
75
|
/** Throttle STATE.md rebuilds — at most once per 30 seconds */
|
|
36
76
|
const STATE_REBUILD_MIN_INTERVAL_MS = 30_000;
|
|
37
77
|
/**
|
|
@@ -283,6 +323,17 @@ export async function postUnitPreVerification(pctx, opts) {
|
|
|
283
323
|
process.stderr.write(`gsd-triage: resolution execution failed: ${err.message}\n`);
|
|
284
324
|
}
|
|
285
325
|
}
|
|
326
|
+
// Rogue file detection — safety net for LLM bypassing completion tools (D003)
|
|
327
|
+
try {
|
|
328
|
+
const rogueFiles = detectRogueFileWrites(s.currentUnit.type, s.currentUnit.id, s.basePath);
|
|
329
|
+
for (const rogue of rogueFiles) {
|
|
330
|
+
process.stderr.write(`gsd-rogue: detected rogue file write: ${rogue.path} (unit: ${rogue.unitId})\n`);
|
|
331
|
+
ctx.ui.notify(`Rogue file write detected: ${rogue.path}`, "warning");
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
catch (e) {
|
|
335
|
+
debugLog("postUnit", { phase: "rogue-detection", error: String(e) });
|
|
336
|
+
}
|
|
286
337
|
// Artifact verification
|
|
287
338
|
let triggerArtifactVerified = false;
|
|
288
339
|
if (!s.currentUnit.type.startsWith("hook/")) {
|
|
@@ -389,9 +440,33 @@ export async function postUnitPostVerification(pctx) {
|
|
|
389
440
|
try {
|
|
390
441
|
const parts = trigger.unitId.split("/");
|
|
391
442
|
const [mid, sid, tid] = parts;
|
|
392
|
-
// 1.
|
|
443
|
+
// 1. Reset task status in DB and re-render plan checkboxes
|
|
393
444
|
if (mid && sid && tid) {
|
|
394
|
-
|
|
445
|
+
try {
|
|
446
|
+
updateTaskStatus(mid, sid, tid, "pending");
|
|
447
|
+
await renderPlanCheckboxes(s.basePath, mid, sid);
|
|
448
|
+
}
|
|
449
|
+
catch {
|
|
450
|
+
// DB may be unavailable — fall back to direct file-based uncheck
|
|
451
|
+
try {
|
|
452
|
+
const slicePath = resolveSlicePath(s.basePath, mid, sid);
|
|
453
|
+
if (slicePath) {
|
|
454
|
+
const { readdirSync } = await import("node:fs");
|
|
455
|
+
const planCandidates = readdirSync(slicePath)
|
|
456
|
+
.filter((f) => f.includes("PLAN") && (f.startsWith(sid) || f.startsWith(`${sid}-`)));
|
|
457
|
+
if (planCandidates.length > 0) {
|
|
458
|
+
const planFile = join(slicePath, planCandidates[0]);
|
|
459
|
+
let content = readFileSync(planFile, "utf-8");
|
|
460
|
+
const regex = new RegExp(`^(\\s*-\\s*)\\[x\\](\\s*\\**${tid}\\**[:\\s])`, "mi");
|
|
461
|
+
if (regex.test(content)) {
|
|
462
|
+
content = content.replace(regex, "$1[ ]$2");
|
|
463
|
+
writeFileSync(planFile, content, "utf-8");
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
catch { /* non-fatal: file-based fallback failure */ }
|
|
469
|
+
}
|
|
395
470
|
}
|
|
396
471
|
// 2. Delete SUMMARY.md for the task
|
|
397
472
|
if (mid && sid && tid) {
|
|
@@ -6,13 +6,12 @@
|
|
|
6
6
|
* Pure functions that receive all needed state as parameters — no module-level
|
|
7
7
|
* globals or AutoContext dependency.
|
|
8
8
|
*/
|
|
9
|
-
import { parseUnitId } from "./unit-id.js";
|
|
10
9
|
import { clearUnitRuntimeRecord } from "./unit-runtime.js";
|
|
11
10
|
import { clearParseCache, parseRoadmap, parsePlan } from "./files.js";
|
|
11
|
+
import { isDbAvailable, getTask, getSlice } from "./gsd-db.js";
|
|
12
12
|
import { isValidationTerminal } from "./state.js";
|
|
13
13
|
import { nativeConflictFiles, nativeCommit, nativeCheckoutTheirs, nativeAddPaths, nativeMergeAbort, nativeResetHard, } from "./native-git-bridge.js";
|
|
14
|
-
import { resolveMilestonePath, resolveSlicePath, resolveSliceFile, resolveTasksDir, resolveTaskFiles, relMilestoneFile, relSliceFile,
|
|
15
|
-
import { markSliceDoneInRoadmap } from "./roadmap-mutations.js";
|
|
14
|
+
import { resolveMilestonePath, resolveSlicePath, resolveSliceFile, resolveTasksDir, resolveTaskFiles, relMilestoneFile, relSliceFile, buildMilestoneFileName, buildSliceFileName, buildTaskFileName, resolveMilestoneFile, clearPathCache, resolveGsdRootFile, } from "./paths.js";
|
|
16
15
|
import { existsSync, mkdirSync, readFileSync, writeFileSync, unlinkSync, } from "node:fs";
|
|
17
16
|
import { execFileSync } from "node:child_process";
|
|
18
17
|
import { dirname, join } from "node:path";
|
|
@@ -269,26 +268,37 @@ export function verifyExpectedArtifact(unitType, unitId, base) {
|
|
|
269
268
|
if (!hasCheckboxTask && !hasHeadingTask)
|
|
270
269
|
return false;
|
|
271
270
|
}
|
|
272
|
-
// execute-task
|
|
273
|
-
//
|
|
274
|
-
// file existence (checked above via resolveExpectedArtifactPath) is sufficient.
|
|
271
|
+
// execute-task: DB status is authoritative. Fall back to heading-style plan
|
|
272
|
+
// detection when the DB is unavailable (unmigrated projects).
|
|
275
273
|
if (unitType === "execute-task") {
|
|
276
274
|
const parts = unitId.split("/");
|
|
277
275
|
const mid = parts[0];
|
|
278
276
|
const sid = parts[1];
|
|
279
277
|
const tid = parts[2];
|
|
280
278
|
if (mid && sid && tid) {
|
|
281
|
-
const
|
|
282
|
-
if (
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
const cbRe = new RegExp(`^- \\[[xX]\\] \\*\\*${escapedTid}:`, "m");
|
|
286
|
-
const hdRe = new RegExp(`^#{2,4}\\s+${escapedTid}\\s*(?:--|—|:)`, "m");
|
|
287
|
-
// Heading-style entries count as verified (no checkbox to toggle);
|
|
288
|
-
// checkbox-style entries require [x].
|
|
289
|
-
if (!cbRe.test(planContent) && !hdRe.test(planContent))
|
|
279
|
+
const dbTask = getTask(mid, sid, tid);
|
|
280
|
+
if (dbTask) {
|
|
281
|
+
// DB available — trust it
|
|
282
|
+
if (dbTask.status !== "complete" && dbTask.status !== "done")
|
|
290
283
|
return false;
|
|
291
284
|
}
|
|
285
|
+
else if (!isDbAvailable()) {
|
|
286
|
+
// DB unavailable — fall back to plan heading check (format detection,
|
|
287
|
+
// not reconciliation). Heading-style entries (### T01 --) count as
|
|
288
|
+
// verified because the summary file existence (checked above) is the
|
|
289
|
+
// real signal.
|
|
290
|
+
const planAbs = resolveSliceFile(base, mid, sid, "PLAN");
|
|
291
|
+
if (planAbs && existsSync(planAbs)) {
|
|
292
|
+
const planContent = readFileSync(planAbs, "utf-8");
|
|
293
|
+
const escapedTid = tid.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
294
|
+
const hdRe = new RegExp(`^#{2,4}\\s+${escapedTid}\\s*(?:--|—|:)`, "m");
|
|
295
|
+
const cbRe = new RegExp(`^- \\[[xX]\\] \\*\\*${escapedTid}:`, "m");
|
|
296
|
+
if (!hdRe.test(planContent) && !cbRe.test(planContent))
|
|
297
|
+
return false;
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
// else: DB available but task not found — summary file exists (checked above),
|
|
301
|
+
// so treat as verified (task may not be imported yet)
|
|
292
302
|
}
|
|
293
303
|
}
|
|
294
304
|
// plan-slice must also produce individual task plan files for every task listed
|
|
@@ -317,11 +327,8 @@ export function verifyExpectedArtifact(unitType, unitId, base) {
|
|
|
317
327
|
}
|
|
318
328
|
}
|
|
319
329
|
}
|
|
320
|
-
// complete-slice
|
|
321
|
-
//
|
|
322
|
-
// the roadmap causes an infinite skip loop: the idempotency key says "done" but the
|
|
323
|
-
// state machine keeps returning the same complete-slice unit (roadmap still shows
|
|
324
|
-
// the slice incomplete), so dispatchNextUnit recurses forever.
|
|
330
|
+
// complete-slice: DB status is authoritative for whether the slice is done.
|
|
331
|
+
// Fall back to file-based check (roadmap [x]) when DB is unavailable.
|
|
325
332
|
if (unitType === "complete-slice") {
|
|
326
333
|
const parts = unitId.split("/");
|
|
327
334
|
const mid = parts[0];
|
|
@@ -333,24 +340,30 @@ export function verifyExpectedArtifact(unitType, unitId, base) {
|
|
|
333
340
|
if (!existsSync(uatPath))
|
|
334
341
|
return false;
|
|
335
342
|
}
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
try {
|
|
341
|
-
const roadmapContent = readFileSync(roadmapFile, "utf-8");
|
|
342
|
-
const roadmap = parseRoadmap(roadmapContent);
|
|
343
|
-
const slice = roadmap.slices.find((s) => s.id === sid);
|
|
344
|
-
if (slice && !slice.done)
|
|
345
|
-
return false;
|
|
346
|
-
}
|
|
347
|
-
catch {
|
|
348
|
-
// Corrupt/unparseable roadmap — fail verification so the unit
|
|
349
|
-
// re-runs and has a chance to fix the roadmap. Silently passing
|
|
350
|
-
// here could advance past an incomplete slice.
|
|
343
|
+
const dbSlice = getSlice(mid, sid);
|
|
344
|
+
if (dbSlice) {
|
|
345
|
+
// DB available — trust it
|
|
346
|
+
if (dbSlice.status !== "complete")
|
|
351
347
|
return false;
|
|
348
|
+
}
|
|
349
|
+
else if (!isDbAvailable()) {
|
|
350
|
+
// DB unavailable — fall back to roadmap checkbox check
|
|
351
|
+
const roadmapFile = resolveMilestoneFile(base, mid, "ROADMAP");
|
|
352
|
+
if (roadmapFile && existsSync(roadmapFile)) {
|
|
353
|
+
try {
|
|
354
|
+
const roadmapContent = readFileSync(roadmapFile, "utf-8");
|
|
355
|
+
const roadmap = parseRoadmap(roadmapContent);
|
|
356
|
+
const slice = roadmap.slices.find((s) => s.id === sid);
|
|
357
|
+
if (slice && !slice.done)
|
|
358
|
+
return false;
|
|
359
|
+
}
|
|
360
|
+
catch {
|
|
361
|
+
return false;
|
|
362
|
+
}
|
|
352
363
|
}
|
|
353
364
|
}
|
|
365
|
+
// else: DB available but slice not found — summary + UAT exist,
|
|
366
|
+
// treat as verified (slice may not be imported yet)
|
|
354
367
|
}
|
|
355
368
|
}
|
|
356
369
|
// complete-milestone must have produced implementation artifacts (#1703).
|
|
@@ -423,52 +436,6 @@ export function diagnoseExpectedArtifact(unitType, unitId, base) {
|
|
|
423
436
|
return null;
|
|
424
437
|
}
|
|
425
438
|
}
|
|
426
|
-
// ─── Skip / Blocker Artifact Generation ───────────────────────────────────────
|
|
427
|
-
/**
|
|
428
|
-
* Write skip artifacts for a stuck execute-task: a blocker task summary and
|
|
429
|
-
* the [x] checkbox in the slice plan. Returns true if artifacts were written.
|
|
430
|
-
*/
|
|
431
|
-
export function skipExecuteTask(base, mid, sid, tid, status, reason, maxAttempts) {
|
|
432
|
-
// Write a blocker task summary if missing.
|
|
433
|
-
if (!status.summaryExists) {
|
|
434
|
-
const tasksDir = resolveTasksDir(base, mid, sid);
|
|
435
|
-
const sDir = resolveSlicePath(base, mid, sid);
|
|
436
|
-
const targetDir = tasksDir ?? (sDir ? join(sDir, "tasks") : null);
|
|
437
|
-
if (!targetDir)
|
|
438
|
-
return false;
|
|
439
|
-
if (!existsSync(targetDir))
|
|
440
|
-
mkdirSync(targetDir, { recursive: true });
|
|
441
|
-
const summaryPath = join(targetDir, buildTaskFileName(tid, "SUMMARY"));
|
|
442
|
-
const content = [
|
|
443
|
-
`# BLOCKER — task skipped by auto-mode recovery`,
|
|
444
|
-
``,
|
|
445
|
-
`Task \`${tid}\` in slice \`${sid}\` (milestone \`${mid}\`) failed to complete after ${reason} recovery exhausted ${maxAttempts} attempts.`,
|
|
446
|
-
``,
|
|
447
|
-
`This placeholder was written by auto-mode so the pipeline can advance.`,
|
|
448
|
-
`Review this task manually and replace this file with a real summary.`,
|
|
449
|
-
].join("\n");
|
|
450
|
-
writeFileSync(summaryPath, content, "utf-8");
|
|
451
|
-
}
|
|
452
|
-
// Mark [x] in the slice plan if not already checked.
|
|
453
|
-
if (!status.taskChecked) {
|
|
454
|
-
const planAbs = resolveSliceFile(base, mid, sid, "PLAN");
|
|
455
|
-
if (planAbs && existsSync(planAbs)) {
|
|
456
|
-
const planContent = readFileSync(planAbs, "utf-8");
|
|
457
|
-
const escapedTid = tid.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
458
|
-
const re = new RegExp(`^(- \\[) \\] (\\*\\*${escapedTid}:)`, "m");
|
|
459
|
-
if (re.test(planContent)) {
|
|
460
|
-
writeFileSync(planAbs, planContent.replace(re, "$1x] $2"), "utf-8");
|
|
461
|
-
}
|
|
462
|
-
else {
|
|
463
|
-
// Regex didn't match — checkbox format differs from expected pattern.
|
|
464
|
-
// Return false so callers know the plan was NOT updated and can
|
|
465
|
-
// fall through to other recovery strategies instead of assuming success.
|
|
466
|
-
return false;
|
|
467
|
-
}
|
|
468
|
-
}
|
|
469
|
-
}
|
|
470
|
-
return true;
|
|
471
|
-
}
|
|
472
439
|
// ─── Merge State Reconciliation ───────────────────────────────────────────────
|
|
473
440
|
/**
|
|
474
441
|
* Detect leftover merge state from a prior session and reconcile it.
|
|
@@ -590,39 +557,8 @@ export async function selfHealRuntimeRecords(base, ctx) {
|
|
|
590
557
|
const now = Date.now();
|
|
591
558
|
for (const record of records) {
|
|
592
559
|
const { unitType, unitId } = record;
|
|
593
|
-
// Case 0
|
|
594
|
-
//
|
|
595
|
-
// flipping the roadmap checkbox, the verification fails and the dispatch
|
|
596
|
-
// loop relaunches the same unit forever. Auto-fix the checkbox.
|
|
597
|
-
if (unitType === "complete-slice") {
|
|
598
|
-
const { milestone: mid, slice: sid } = parseUnitId(unitId);
|
|
599
|
-
if (mid && sid) {
|
|
600
|
-
const dir = resolveSlicePath(base, mid, sid);
|
|
601
|
-
if (dir) {
|
|
602
|
-
const summaryPath = join(dir, buildSliceFileName(sid, "SUMMARY"));
|
|
603
|
-
const uatPath = join(dir, buildSliceFileName(sid, "UAT"));
|
|
604
|
-
if (existsSync(summaryPath) && existsSync(uatPath)) {
|
|
605
|
-
const roadmapFile = resolveMilestoneFile(base, mid, "ROADMAP");
|
|
606
|
-
if (roadmapFile && existsSync(roadmapFile)) {
|
|
607
|
-
try {
|
|
608
|
-
const roadmapContent = readFileSync(roadmapFile, "utf-8");
|
|
609
|
-
const roadmap = parseRoadmap(roadmapContent);
|
|
610
|
-
const slice = (roadmap.slices ?? []).find(s => s.id === sid);
|
|
611
|
-
if (slice && !slice.done) {
|
|
612
|
-
// Auto-fix: flip the checkbox using shared utility
|
|
613
|
-
if (markSliceDoneInRoadmap(base, mid, sid)) {
|
|
614
|
-
ctx.ui.notify(`Self-heal: marked ${sid} done in roadmap (SUMMARY + UAT exist but checkbox was stale).`, "info");
|
|
615
|
-
}
|
|
616
|
-
}
|
|
617
|
-
}
|
|
618
|
-
catch {
|
|
619
|
-
// Roadmap parse failure — don't block self-heal
|
|
620
|
-
}
|
|
621
|
-
}
|
|
622
|
-
}
|
|
623
|
-
}
|
|
624
|
-
}
|
|
625
|
-
}
|
|
560
|
+
// Case 0 removed — roadmap checkbox auto-fix is no longer needed.
|
|
561
|
+
// With DB-as-truth, stale checkboxes are fixed by repairStaleRenders().
|
|
626
562
|
// Clear stale dispatched records (dispatched > 1h ago, process crashed)
|
|
627
563
|
const age = now - (record.startedAt ?? 0);
|
|
628
564
|
if (record.phase === "dispatched" && age > STALE_THRESHOLD_MS) {
|
|
@@ -654,13 +590,10 @@ export function buildLoopRemediationSteps(unitType, unitId, base) {
|
|
|
654
590
|
case "execute-task": {
|
|
655
591
|
if (!mid || !sid || !tid)
|
|
656
592
|
break;
|
|
657
|
-
const planRel = relSliceFile(base, mid, sid, "PLAN");
|
|
658
|
-
const summaryRel = relTaskFile(base, mid, sid, tid, "SUMMARY");
|
|
659
593
|
return [
|
|
660
|
-
` 1.
|
|
661
|
-
` 2.
|
|
662
|
-
` 3.
|
|
663
|
-
` 4. Resume auto-mode — it will pick up from the next task`,
|
|
594
|
+
` 1. Run \`gsd undo-task ${tid}\` to reset the task state`,
|
|
595
|
+
` 2. Resume auto-mode — it will re-execute the task`,
|
|
596
|
+
` 3. If the task keeps failing, run \`gsd recover\` to rebuild DB state from disk`,
|
|
664
597
|
].join("\n");
|
|
665
598
|
}
|
|
666
599
|
case "plan-slice":
|
|
@@ -672,7 +605,7 @@ export function buildLoopRemediationSteps(unitType, unitId, base) {
|
|
|
672
605
|
: relSliceFile(base, mid, sid, "RESEARCH");
|
|
673
606
|
return [
|
|
674
607
|
` 1. Write ${artifactRel} manually (or with the LLM in interactive mode)`,
|
|
675
|
-
` 2. Run \`gsd
|
|
608
|
+
` 2. Run \`gsd recover\` to rebuild DB state from disk`,
|
|
676
609
|
` 3. Resume auto-mode`,
|
|
677
610
|
].join("\n");
|
|
678
611
|
}
|
|
@@ -680,10 +613,9 @@ export function buildLoopRemediationSteps(unitType, unitId, base) {
|
|
|
680
613
|
if (!mid || !sid)
|
|
681
614
|
break;
|
|
682
615
|
return [
|
|
683
|
-
` 1.
|
|
684
|
-
` 2.
|
|
685
|
-
` 3.
|
|
686
|
-
` 4. Resume auto-mode`,
|
|
616
|
+
` 1. Run \`gsd reset-slice ${sid}\` to reset the slice and all its tasks`,
|
|
617
|
+
` 2. Resume auto-mode — it will re-execute incomplete tasks and re-complete the slice`,
|
|
618
|
+
` 3. If the slice keeps failing, run \`gsd recover\` to rebuild DB state from disk`,
|
|
687
619
|
].join("\n");
|
|
688
620
|
}
|
|
689
621
|
case "validate-milestone": {
|
|
@@ -692,7 +624,7 @@ export function buildLoopRemediationSteps(unitType, unitId, base) {
|
|
|
692
624
|
const artifactRel = relMilestoneFile(base, mid, "VALIDATION");
|
|
693
625
|
return [
|
|
694
626
|
` 1. Write ${artifactRel} with verdict: pass`,
|
|
695
|
-
` 2. Run \`gsd
|
|
627
|
+
` 2. Run \`gsd recover\` to rebuild DB state from disk`,
|
|
696
628
|
` 3. Resume auto-mode`,
|
|
697
629
|
].join("\n");
|
|
698
630
|
}
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* and blocker placeholder generation.
|
|
5
5
|
*/
|
|
6
6
|
import { readUnitRuntimeRecord, writeUnitRuntimeRecord, formatExecuteTaskRecoveryStatus, inspectExecuteTaskDurability, } from "./unit-runtime.js";
|
|
7
|
-
import { resolveExpectedArtifactPath, diagnoseExpectedArtifact,
|
|
7
|
+
import { resolveExpectedArtifactPath, diagnoseExpectedArtifact, writeBlockerPlaceholder, } from "./auto-recovery.js";
|
|
8
8
|
import { existsSync } from "node:fs";
|
|
9
9
|
import { resolveAgentEnd } from "./auto-loop.js";
|
|
10
10
|
export async function recoverTimedOutUnit(ctx, pi, unitType, unitId, reason, rctx) {
|
|
@@ -78,13 +78,10 @@ export async function recoverTimedOutUnit(ctx, pi, unitType, unitId, reason, rct
|
|
|
78
78
|
ctx.ui.notify(`${reason === "idle" ? "Idle" : "Timeout"} recovery: steering ${unitType} ${unitId} to finish durable output (attempt ${attemptNumber}, session ${recoveryAttempts + 1}/${maxRecoveryAttempts}).`, "warning");
|
|
79
79
|
return "recovered";
|
|
80
80
|
}
|
|
81
|
-
// Retries exhausted — write
|
|
81
|
+
// Retries exhausted — write a blocker placeholder and advance.
|
|
82
82
|
const diagnostic = formatExecuteTaskRecoveryStatus(status);
|
|
83
|
-
const
|
|
84
|
-
|
|
85
|
-
? skipExecuteTask(basePath, mid, sid, tid, status, reason, maxRecoveryAttempts)
|
|
86
|
-
: false;
|
|
87
|
-
if (skipped) {
|
|
83
|
+
const placeholder = writeBlockerPlaceholder(unitType, unitId, basePath, `${reason} recovery exhausted ${maxRecoveryAttempts} attempts. Status: ${diagnostic}`);
|
|
84
|
+
if (placeholder) {
|
|
88
85
|
writeUnitRuntimeRecord(basePath, unitType, unitId, currentUnitStartedAt, {
|
|
89
86
|
phase: "skipped",
|
|
90
87
|
recovery: status,
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
import { existsSync, cpSync, readFileSync, readdirSync, mkdirSync, realpathSync, rmSync, unlinkSync, lstatSync as lstatSyncFn, } from "node:fs";
|
|
9
9
|
import { isAbsolute, join } from "node:path";
|
|
10
10
|
import { GSDError, GSD_IO_ERROR, GSD_GIT_ERROR } from "./errors.js";
|
|
11
|
-
import {
|
|
11
|
+
import { reconcileWorktreeDb, isDbAvailable, } from "./gsd-db.js";
|
|
12
12
|
import { atomicWriteSync } from "./atomic-write.js";
|
|
13
13
|
import { execFileSync } from "node:child_process";
|
|
14
14
|
import { safeCopy, safeCopyRecursive } from "./safe-fs.js";
|
|
@@ -251,6 +251,22 @@ export function syncWorktreeStateBack(mainBasePath, worktreePath, milestoneId) {
|
|
|
251
251
|
}
|
|
252
252
|
if (!existsSync(wtGsd) || !existsSync(mainGsd))
|
|
253
253
|
return { synced };
|
|
254
|
+
// ── 0. Pre-upgrade worktree DB reconciliation ────────────────────────
|
|
255
|
+
// If the worktree has its own gsd.db (copied before the WAL transition),
|
|
256
|
+
// reconcile its hierarchy data into the project root DB before syncing
|
|
257
|
+
// files. This handles in-flight worktrees that were created before the
|
|
258
|
+
// upgrade to shared WAL mode.
|
|
259
|
+
const wtLocalDb = join(wtGsd, "gsd.db");
|
|
260
|
+
const mainDb = join(mainGsd, "gsd.db");
|
|
261
|
+
if (existsSync(wtLocalDb) && existsSync(mainDb)) {
|
|
262
|
+
try {
|
|
263
|
+
reconcileWorktreeDb(mainDb, wtLocalDb);
|
|
264
|
+
synced.push("gsd.db (pre-upgrade reconcile)");
|
|
265
|
+
}
|
|
266
|
+
catch {
|
|
267
|
+
// Non-fatal — file sync below is the fallback
|
|
268
|
+
}
|
|
269
|
+
}
|
|
254
270
|
// ── 1. Sync root-level .gsd/ files back ──────────────────────────────
|
|
255
271
|
// The worktree is authoritative — complete-milestone updates REQUIREMENTS,
|
|
256
272
|
// PROJECT, etc. These must overwrite main's copies so they survive teardown.
|
|
@@ -641,17 +657,11 @@ function copyPlanningArtifacts(srcBase, wtPath) {
|
|
|
641
657
|
]) {
|
|
642
658
|
safeCopy(join(srcGsd, file), join(dstGsd, file), { force: true });
|
|
643
659
|
}
|
|
644
|
-
//
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
copyWorktreeDb(srcDb, destDb);
|
|
650
|
-
}
|
|
651
|
-
catch {
|
|
652
|
-
/* non-fatal */
|
|
653
|
-
}
|
|
654
|
-
}
|
|
660
|
+
// Shared WAL (R012): worktrees use the project root's DB directly.
|
|
661
|
+
// No longer copy gsd.db into the worktree — the DB path resolver in
|
|
662
|
+
// ensureDbOpen() detects the worktree location and opens the root DB.
|
|
663
|
+
// Compat note: reconcileWorktreeDb() in mergeMilestoneToMain handles
|
|
664
|
+
// worktrees that already have a local gsd.db from before this change.
|
|
655
665
|
}
|
|
656
666
|
/**
|
|
657
667
|
* Teardown an auto-worktree: chdir back to original base, then remove
|
|
@@ -1063,4 +1063,4 @@ export async function dispatchHookUnit(ctx, pi, hookName, triggerUnitType, trigg
|
|
|
1063
1063
|
// Direct phase dispatch → auto-direct-dispatch.ts
|
|
1064
1064
|
export { dispatchDirectPhase } from "./auto-direct-dispatch.js";
|
|
1065
1065
|
// Re-export recovery functions for external consumers
|
|
1066
|
-
export { resolveExpectedArtifactPath, verifyExpectedArtifact, writeBlockerPlaceholder,
|
|
1066
|
+
export { resolveExpectedArtifactPath, verifyExpectedArtifact, writeBlockerPlaceholder, buildLoopRemediationSteps, } from "./auto-recovery.js";
|