@opengsd/gsd-pi 1.3.0-dev.eed73bea → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +10 -10
- package/dist/cli.js +17 -4
- package/dist/headless-answers.js +1 -1
- package/dist/headless-ui.d.ts +1 -1
- package/dist/headless-ui.js +1 -1
- package/dist/headless.js +1 -1
- package/dist/resources/.managed-resources-content-hash +1 -1
- package/dist/resources/extensions/claude-code-cli/models.js +9 -0
- package/dist/resources/extensions/gsd/artifact-verification.js +427 -0
- package/dist/resources/extensions/gsd/auto/session.js +11 -0
- package/dist/resources/extensions/gsd/auto/verification-retry-policy.js +1 -1
- package/dist/resources/extensions/gsd/auto-artifact-paths.js +28 -1
- package/dist/resources/extensions/gsd/auto-budget.js +5 -1
- package/dist/resources/extensions/gsd/auto-dispatch.js +17 -6
- package/dist/resources/extensions/gsd/auto-post-unit.js +1 -1
- package/dist/resources/extensions/gsd/auto-prompts.js +8 -24
- package/dist/resources/extensions/gsd/auto-recovery.js +9 -517
- package/dist/resources/extensions/gsd/auto-runtime-state.js +4 -5
- package/dist/resources/extensions/gsd/auto-timeout-recovery.js +3 -3
- package/dist/resources/extensions/gsd/auto-verification.js +5 -2
- package/dist/resources/extensions/gsd/auto.js +19 -10
- package/dist/resources/extensions/gsd/bootstrap/core-session-tools.js +39 -0
- package/dist/resources/extensions/gsd/bootstrap/db-tools.js +5 -4
- package/dist/resources/extensions/gsd/bootstrap/register-extension.js +2 -0
- package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +33 -18
- package/dist/resources/extensions/gsd/bootstrap/tool-call-loop-guard.js +48 -36
- package/dist/resources/extensions/gsd/bootstrap/write-gate.js +15 -4
- package/dist/resources/extensions/gsd/closeout-consistency-gate.js +3 -1
- package/dist/resources/extensions/gsd/commands/handlers/auto.js +1 -1
- package/dist/resources/extensions/gsd/commands-prefs-wizard.js +1 -1
- package/dist/resources/extensions/gsd/commands-usage.js +1 -1
- package/dist/resources/extensions/gsd/db/engine.js +4 -1
- package/dist/resources/extensions/gsd/db-memory-fts-schema.js +34 -0
- package/dist/resources/extensions/gsd/db-workspace.js +55 -3
- package/dist/resources/extensions/gsd/delegation-policy.js +1 -1
- package/dist/resources/extensions/gsd/docs/preferences-reference.md +2 -2
- package/dist/resources/extensions/gsd/doctor-engine-checks.js +192 -4
- package/dist/resources/extensions/gsd/doctor-runtime-checks.js +3 -0
- package/dist/resources/extensions/gsd/exec-sandbox.js +8 -2
- package/dist/resources/extensions/gsd/flat-phase-migration.js +45 -0
- package/dist/resources/extensions/gsd/git-service.js +57 -0
- package/dist/resources/extensions/gsd/gitignore.js +4 -1
- package/dist/resources/extensions/gsd/guided-flow-queue.js +20 -13
- package/dist/resources/extensions/gsd/json-persistence.js +20 -0
- package/dist/resources/extensions/gsd/knowledge-backfill.js +18 -11
- package/dist/resources/extensions/gsd/layout-policy.js +3 -1
- package/dist/resources/extensions/gsd/markdown-renderer.js +2 -7
- package/dist/resources/extensions/gsd/memory-backfill.js +28 -21
- package/dist/resources/extensions/gsd/metrics.js +4 -4
- package/dist/resources/extensions/gsd/migrate-external.js +11 -2
- package/dist/resources/extensions/gsd/migration-auto-check.js +22 -0
- package/dist/resources/extensions/gsd/milestone-ids.js +32 -2
- package/dist/resources/extensions/gsd/orphan-stash-audit.js +92 -16
- package/dist/resources/extensions/gsd/prompts/code-review.md +6 -4
- package/dist/resources/extensions/gsd/prompts/plan-milestone.md +2 -2
- package/dist/resources/extensions/gsd/prompts/plan-slice.md +3 -3
- package/dist/resources/extensions/gsd/root-write-leak-guard.js +7 -1
- package/dist/resources/extensions/gsd/safety/destructive-guard.js +8 -1
- package/dist/resources/extensions/gsd/safety/evidence-collector.js +16 -1
- package/dist/resources/extensions/gsd/safety/file-change-validator.js +5 -2
- package/dist/resources/extensions/gsd/skills/gsd-headless/references/commands.md +1 -1
- package/dist/resources/extensions/gsd/state/derive/cache.js +28 -0
- package/dist/resources/extensions/gsd/state/derive/db-open.js +39 -0
- package/dist/resources/extensions/gsd/state/derive/from-db.js +452 -0
- package/dist/resources/extensions/gsd/state/derive/index.js +75 -0
- package/dist/resources/extensions/gsd/state/derive/interrupted-work.js +21 -0
- package/dist/resources/extensions/gsd/state-reconciliation/drift/stale-render.js +27 -33
- package/dist/resources/extensions/gsd/state-reconciliation/index.js +48 -23
- package/dist/resources/extensions/gsd/state-reconciliation/registry.js +32 -28
- package/dist/resources/extensions/gsd/state.js +12 -611
- package/dist/resources/extensions/gsd/tools/complete-milestone.js +4 -2
- package/dist/resources/extensions/gsd/tools/complete-slice.js +3 -34
- package/dist/resources/extensions/gsd/tools/complete-task.js +8 -41
- package/dist/resources/extensions/gsd/tools/plan-slice.js +59 -44
- package/dist/resources/extensions/gsd/tools/plan-task.js +28 -5
- package/dist/resources/extensions/gsd/undo.js +43 -6
- package/dist/resources/extensions/gsd/unit-registry.js +11 -3
- package/dist/resources/extensions/gsd/verification-gate.js +7 -0
- package/dist/resources/extensions/gsd/workflow-manifest.js +126 -13
- package/dist/resources/extensions/gsd/workflow-projections.js +19 -14
- package/dist/resources/extensions/gsd/worktree-manager.js +44 -2
- 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 +4 -4
- package/dist/web/standalone/.next/prerender-manifest.json +3 -3
- package/dist/web/standalone/.next/react-loadable-manifest.json +9 -9
- 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 +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/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/experimental/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/experimental/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/mcp-connections/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/mcp-connections/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/notifications/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/notifications/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 +2 -2
- 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/switch-root/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/switch-root/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 +1 -1
- 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 +10 -10
- package/dist/web/standalone/.next/server/chunks/2842.js +4 -4
- package/dist/web/standalone/.next/server/chunks/8357.js +3 -3
- package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
- package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
- package/dist/web/standalone/.next/server/middleware.js +3 -3
- package/dist/web/standalone/.next/server/pages/404.html +1 -1
- package/dist/web/standalone/.next/server/pages/500.html +1 -1
- package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
- package/dist/web/standalone/.next/static/chunks/{2659.b7b129ee6a769448.js → 2659.58e950899a9bb82f.js} +1 -1
- package/dist/web/standalone/.next/static/chunks/2772.a7c1fcc69a4685ef.js +1 -0
- package/dist/web/standalone/.next/static/chunks/{3616.3c60753b8ffcbd2e.js → 3616.61a2af74bb8833c8.js} +1 -1
- package/dist/web/standalone/.next/static/chunks/{4283.8e446784528ed9dc.js → 4283.d0d9e0a955e441cb.js} +1 -1
- package/dist/web/standalone/.next/static/chunks/{5826.a46ecdd1cfe8dabc.js → 5826.5421d66c72b9f34e.js} +1 -1
- package/dist/web/standalone/.next/static/chunks/{8785.481aa5869991b760.js → 8785.e29b3134cab1d153.js} +1 -1
- package/dist/web/standalone/.next/static/chunks/8937.640dc9c2aaa1dfad.js +10 -0
- package/dist/web/standalone/.next/static/chunks/app/_not-found/page-49f565245e1e4afe.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/{layout-4ae2d68984392bbf.js → layout-b35cbfff38aaf4cf.js} +1 -1
- package/dist/web/standalone/.next/static/chunks/app/page-bc4c723c6a19c6f0.js +1 -0
- package/dist/web/standalone/.next/static/chunks/{main-app-90d1d8d5e5d2dc6b.js → main-app-590a74400e35f685.js} +1 -1
- package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-ec3eaffc9785ba48.js +1 -0
- package/dist/web/standalone/.next/static/chunks/webpack-9c401904f87ded16.js +1 -0
- package/dist/web/standalone/node_modules/@gsd/native/package.json +1 -1
- 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/server.js +1 -1
- package/package.json +6 -6
- package/packages/cloud-mcp-gateway/package.json +2 -2
- package/packages/contracts/package.json +1 -1
- package/packages/daemon/package.json +4 -4
- package/packages/gsd-agent-core/dist/agent-session.d.ts +1 -0
- package/packages/gsd-agent-core/dist/agent-session.d.ts.map +1 -1
- package/packages/gsd-agent-core/dist/agent-session.js +3 -0
- package/packages/gsd-agent-core/dist/agent-session.js.map +1 -1
- package/packages/gsd-agent-core/dist/extension-ui-snapshot.d.ts +41 -0
- package/packages/gsd-agent-core/dist/extension-ui-snapshot.d.ts.map +1 -0
- package/packages/gsd-agent-core/dist/extension-ui-snapshot.js +62 -0
- package/packages/gsd-agent-core/dist/extension-ui-snapshot.js.map +1 -0
- package/packages/gsd-agent-core/dist/index.d.ts +2 -0
- package/packages/gsd-agent-core/dist/index.d.ts.map +1 -1
- package/packages/gsd-agent-core/dist/index.js +2 -0
- package/packages/gsd-agent-core/dist/index.js.map +1 -1
- package/packages/gsd-agent-core/dist/session/agent-session-events.js +1 -1
- package/packages/gsd-agent-core/dist/session/agent-session-events.js.map +1 -1
- package/packages/gsd-agent-core/dist/session/agent-session-host.d.ts +1 -0
- package/packages/gsd-agent-core/dist/session/agent-session-host.d.ts.map +1 -1
- package/packages/gsd-agent-core/dist/session/agent-session-host.js.map +1 -1
- package/packages/gsd-agent-core/dist/session/agent-session-prompt.d.ts +5 -0
- package/packages/gsd-agent-core/dist/session/agent-session-prompt.d.ts.map +1 -1
- package/packages/gsd-agent-core/dist/session/agent-session-prompt.js +60 -3
- package/packages/gsd-agent-core/dist/session/agent-session-prompt.js.map +1 -1
- package/packages/gsd-agent-core/dist/transcript-store.d.ts +58 -0
- package/packages/gsd-agent-core/dist/transcript-store.d.ts.map +1 -0
- package/packages/gsd-agent-core/dist/transcript-store.js +132 -0
- package/packages/gsd-agent-core/dist/transcript-store.js.map +1 -0
- package/packages/gsd-agent-core/package.json +5 -5
- package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.d.ts +2 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.js +25 -11
- package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller-latency.d.ts +4 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller-latency.d.ts.map +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller-latency.js +7 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller-latency.js.map +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.d.ts +3 -24
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.js +26 -841
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-handoff-filter.d.ts +58 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-handoff-filter.d.ts.map +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-handoff-filter.js +312 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-handoff-filter.js.map +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-pinned-zone.d.ts +31 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-pinned-zone.d.ts.map +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-pinned-zone.js +130 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-pinned-zone.js.map +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-segment-walker.d.ts +15 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-segment-walker.d.ts.map +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-segment-walker.js +258 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-segment-walker.js.map +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-tool-rollup.d.ts +13 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-tool-rollup.d.ts.map +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-tool-rollup.js +118 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-tool-rollup.js.map +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-state.d.ts +9 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-state.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-state.js +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-state.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-ui-state.d.ts +54 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-ui-state.d.ts.map +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-ui-state.js +20 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-ui-state.js.map +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.d.ts +4 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.js +9 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/streaming-render-state.d.ts +56 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/streaming-render-state.d.ts.map +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/streaming-render-state.js +44 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/streaming-render-state.js.map +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/tui-transcript-tracker.d.ts +5 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/tui-transcript-tracker.d.ts.map +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/tui-transcript-tracker.js +77 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/tui-transcript-tracker.js.map +1 -0
- package/packages/gsd-agent-modes/dist/modes/rpc/rpc-client.d.ts +2 -0
- package/packages/gsd-agent-modes/dist/modes/rpc/rpc-client.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/rpc/rpc-client.js +23 -5
- package/packages/gsd-agent-modes/dist/modes/rpc/rpc-client.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/rpc/rpc-mode.js +18 -0
- package/packages/gsd-agent-modes/dist/modes/rpc/rpc-mode.js.map +1 -1
- package/packages/gsd-agent-modes/package.json +7 -7
- package/packages/mcp-server/dist/workflow-tools.js +1 -1
- package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
- package/packages/mcp-server/package.json +4 -4
- package/packages/native/package.json +1 -1
- package/packages/pi-agent-core/dist/agent-loop.js +3 -2
- package/packages/pi-agent-core/dist/agent-loop.js.map +1 -1
- package/packages/pi-agent-core/package.json +1 -1
- package/packages/pi-ai/dist/models.generated.d.ts +46 -0
- package/packages/pi-ai/dist/models.generated.d.ts.map +1 -1
- package/packages/pi-ai/dist/models.generated.js +38 -0
- package/packages/pi-ai/dist/models.generated.js.map +1 -1
- package/packages/pi-ai/package.json +1 -1
- package/packages/pi-coding-agent/README.md +3 -2
- package/packages/pi-coding-agent/dist/core/session-manager-context.d.ts +9 -0
- package/packages/pi-coding-agent/dist/core/session-manager-context.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/session-manager-context.js +94 -0
- package/packages/pi-coding-agent/dist/core/session-manager-context.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/session-manager-list.d.ts +8 -0
- package/packages/pi-coding-agent/dist/core/session-manager-list.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/session-manager-list.js +244 -0
- package/packages/pi-coding-agent/dist/core/session-manager-list.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/session-manager-migration.d.ts +12 -0
- package/packages/pi-coding-agent/dist/core/session-manager-migration.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/session-manager-migration.js +84 -0
- package/packages/pi-coding-agent/dist/core/session-manager-migration.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/session-manager-types.d.ts +135 -0
- package/packages/pi-coding-agent/dist/core/session-manager-types.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/session-manager-types.js +2 -0
- package/packages/pi-coding-agent/dist/core/session-manager-types.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/session-manager.d.ts +6 -154
- package/packages/pi-coding-agent/dist/core/session-manager.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/session-manager.js +22 -459
- package/packages/pi-coding-agent/dist/core/session-manager.js.map +1 -1
- package/packages/pi-coding-agent/dist/theme/theme-schema.d.ts +75 -75
- package/packages/pi-coding-agent/dist/theme/theme-schema.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/theme/theme-schema.js +1 -1
- package/packages/pi-coding-agent/dist/theme/theme-schema.js.map +1 -1
- package/packages/pi-coding-agent/dist/theme/theme.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/theme/theme.js +11 -7
- package/packages/pi-coding-agent/dist/theme/theme.js.map +1 -1
- package/packages/pi-coding-agent/package.json +7 -7
- package/packages/pi-tui/package.json +2 -2
- package/packages/rpc-client/package.json +2 -2
- package/pkg/dist/theme/theme-schema.d.ts +75 -75
- package/pkg/dist/theme/theme-schema.d.ts.map +1 -1
- package/pkg/dist/theme/theme-schema.js +1 -1
- package/pkg/dist/theme/theme-schema.js.map +1 -1
- package/pkg/dist/theme/theme.d.ts.map +1 -1
- package/pkg/dist/theme/theme.js +11 -7
- package/pkg/dist/theme/theme.js.map +1 -1
- package/pkg/package.json +1 -1
- package/src/resources/extensions/claude-code-cli/models.ts +9 -0
- package/src/resources/extensions/claude-code-cli/tests/index.test.ts +14 -0
- package/src/resources/extensions/gsd/artifact-verification.ts +464 -0
- package/src/resources/extensions/gsd/auto/loop-deps.ts +1 -0
- package/src/resources/extensions/gsd/auto/session.ts +14 -0
- package/src/resources/extensions/gsd/auto/verification-retry-policy.ts +3 -1
- package/src/resources/extensions/gsd/auto-artifact-paths.ts +47 -1
- package/src/resources/extensions/gsd/auto-budget.ts +12 -1
- package/src/resources/extensions/gsd/auto-dispatch.ts +17 -7
- package/src/resources/extensions/gsd/auto-post-unit.ts +1 -1
- package/src/resources/extensions/gsd/auto-prompts.ts +7 -23
- package/src/resources/extensions/gsd/auto-recovery.ts +13 -518
- package/src/resources/extensions/gsd/auto-runtime-state.ts +4 -5
- package/src/resources/extensions/gsd/auto-timeout-recovery.ts +3 -2
- package/src/resources/extensions/gsd/auto-verification.ts +5 -1
- package/src/resources/extensions/gsd/auto.ts +23 -8
- package/src/resources/extensions/gsd/bootstrap/core-session-tools.ts +44 -0
- package/src/resources/extensions/gsd/bootstrap/db-tools.ts +5 -4
- package/src/resources/extensions/gsd/bootstrap/register-extension.ts +2 -0
- package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +43 -18
- package/src/resources/extensions/gsd/bootstrap/tests/write-gate-basepath.test.ts +49 -1
- package/src/resources/extensions/gsd/bootstrap/tool-call-loop-guard.ts +50 -37
- package/src/resources/extensions/gsd/bootstrap/write-gate.ts +16 -4
- package/src/resources/extensions/gsd/closeout-consistency-gate.ts +2 -1
- package/src/resources/extensions/gsd/commands/handlers/auto.ts +1 -1
- package/src/resources/extensions/gsd/commands-prefs-wizard.ts +1 -1
- package/src/resources/extensions/gsd/commands-usage.ts +1 -1
- package/src/resources/extensions/gsd/db/engine.ts +8 -1
- package/src/resources/extensions/gsd/db-memory-fts-schema.ts +45 -0
- package/src/resources/extensions/gsd/db-workspace.ts +61 -3
- package/src/resources/extensions/gsd/delegation-policy.ts +1 -1
- package/src/resources/extensions/gsd/docs/preferences-reference.md +2 -2
- package/src/resources/extensions/gsd/doctor-engine-checks.ts +233 -5
- package/src/resources/extensions/gsd/doctor-runtime-checks.ts +3 -0
- package/src/resources/extensions/gsd/doctor-types.ts +3 -0
- package/src/resources/extensions/gsd/exec-sandbox.ts +7 -2
- package/src/resources/extensions/gsd/flat-phase-migration.ts +44 -0
- package/src/resources/extensions/gsd/git-service.ts +64 -0
- package/src/resources/extensions/gsd/gitignore.ts +4 -1
- package/src/resources/extensions/gsd/guided-flow-queue.ts +20 -13
- package/src/resources/extensions/gsd/json-persistence.ts +20 -0
- package/src/resources/extensions/gsd/knowledge-backfill.ts +16 -10
- package/src/resources/extensions/gsd/layout-policy.ts +2 -1
- package/src/resources/extensions/gsd/markdown-renderer.ts +2 -10
- package/src/resources/extensions/gsd/memory-backfill.ts +26 -20
- package/src/resources/extensions/gsd/metrics.ts +4 -4
- package/src/resources/extensions/gsd/migrate-external.ts +8 -2
- package/src/resources/extensions/gsd/migration-auto-check.ts +23 -0
- package/src/resources/extensions/gsd/milestone-ids.ts +31 -2
- package/src/resources/extensions/gsd/orphan-stash-audit.ts +108 -20
- package/src/resources/extensions/gsd/prompts/code-review.md +6 -4
- package/src/resources/extensions/gsd/prompts/plan-milestone.md +2 -2
- package/src/resources/extensions/gsd/prompts/plan-slice.md +3 -3
- package/src/resources/extensions/gsd/root-write-leak-guard.ts +13 -1
- package/src/resources/extensions/gsd/safety/destructive-guard.ts +9 -1
- package/src/resources/extensions/gsd/safety/evidence-collector.ts +16 -1
- package/src/resources/extensions/gsd/safety/file-change-validator.ts +8 -2
- package/src/resources/extensions/gsd/skills/gsd-headless/references/commands.md +1 -1
- package/src/resources/extensions/gsd/state/derive/cache.ts +46 -0
- package/src/resources/extensions/gsd/state/derive/db-open.ts +45 -0
- package/src/resources/extensions/gsd/state/derive/from-db.ts +561 -0
- package/src/resources/extensions/gsd/state/derive/index.ts +104 -0
- package/src/resources/extensions/gsd/state/derive/interrupted-work.ts +31 -0
- package/src/resources/extensions/gsd/state-reconciliation/drift/stale-render.ts +36 -30
- package/src/resources/extensions/gsd/state-reconciliation/index.ts +50 -24
- package/src/resources/extensions/gsd/state-reconciliation/registry.ts +43 -28
- package/src/resources/extensions/gsd/state.ts +32 -732
- package/src/resources/extensions/gsd/tests/artifact-retry-cap.test.ts +4 -3
- package/src/resources/extensions/gsd/tests/auto-artifact-paths.test.ts +98 -1
- package/src/resources/extensions/gsd/tests/auto-budget-alerts.test.ts +14 -5
- package/src/resources/extensions/gsd/tests/auto-pause-double-entry-guard.test.ts +36 -0
- package/src/resources/extensions/gsd/tests/auto-paused-ui-cleanup.test.ts +182 -4
- package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +35 -0
- package/src/resources/extensions/gsd/tests/auto-retry-mcp-churn-fixes.test.ts +30 -0
- package/src/resources/extensions/gsd/tests/commands-gsd-core.test.ts +1 -0
- package/src/resources/extensions/gsd/tests/complete-milestone.test.ts +28 -0
- package/src/resources/extensions/gsd/tests/complete-slice-reopen-handoff.test.ts +69 -0
- package/src/resources/extensions/gsd/tests/db-memory-fts-schema.test.ts +58 -3
- package/src/resources/extensions/gsd/tests/decisions-projection-from-memories.test.ts +51 -0
- package/src/resources/extensions/gsd/tests/destructive-guard.test.ts +44 -0
- package/src/resources/extensions/gsd/tests/dispatch-missing-task-plans.test.ts +143 -0
- package/src/resources/extensions/gsd/tests/doctor-scope-db-unavailable.test.ts +239 -2
- package/src/resources/extensions/gsd/tests/exec-sandbox.test.ts +16 -0
- package/src/resources/extensions/gsd/tests/file-change-validator.test.ts +40 -0
- package/src/resources/extensions/gsd/tests/flat-phase-migration.test.ts +37 -2
- package/src/resources/extensions/gsd/tests/gitignore-bg-shell-runtime.test.ts +4 -0
- package/src/resources/extensions/gsd/tests/integration/git-service.test.ts +11 -2
- package/src/resources/extensions/gsd/tests/json-persistence-atomic.test.ts +47 -0
- package/src/resources/extensions/gsd/tests/knowledge-backfill-projection.test.ts +35 -0
- package/src/resources/extensions/gsd/tests/memory-store.test.ts +48 -0
- package/src/resources/extensions/gsd/tests/merge-closeout-consistency-gate.test.ts +31 -1
- package/src/resources/extensions/gsd/tests/metrics-prune-cache-invalidation.test.ts +6 -0
- package/src/resources/extensions/gsd/tests/metrics.test.ts +1 -0
- package/src/resources/extensions/gsd/tests/migrate-external-worktree.test.ts +57 -0
- package/src/resources/extensions/gsd/tests/migration-auto-check.test.ts +70 -0
- package/src/resources/extensions/gsd/tests/orphan-stash-audit.test.ts +91 -7
- package/src/resources/extensions/gsd/tests/parsers-legacy-importers.test.ts +4 -1
- package/src/resources/extensions/gsd/tests/plan-slice-prompt.test.ts +10 -0
- package/src/resources/extensions/gsd/tests/plan-slice.test.ts +103 -4
- package/src/resources/extensions/gsd/tests/plan-task.test.ts +44 -1
- package/src/resources/extensions/gsd/tests/post-mutation-hook.test.ts +4 -2
- package/src/resources/extensions/gsd/tests/progressive-planning.test.ts +50 -14
- package/src/resources/extensions/gsd/tests/prompt-budget-enforcement.test.ts +58 -0
- package/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +8 -6
- package/src/resources/extensions/gsd/tests/register-hooks-loop-guard-auto.test.ts +103 -0
- package/src/resources/extensions/gsd/tests/root-write-leak-guard.test.ts +20 -1
- package/src/resources/extensions/gsd/tests/runtime-invariant-modules.test.ts +15 -3
- package/src/resources/extensions/gsd/tests/stalled-tool-recovery.test.ts +56 -0
- package/src/resources/extensions/gsd/tests/state-reconciliation-drift.test.ts +115 -0
- package/src/resources/extensions/gsd/tests/tool-call-loop-guard.test.ts +140 -0
- package/src/resources/extensions/gsd/tests/tool-param-optionality.test.ts +6 -3
- package/src/resources/extensions/gsd/tests/undo.test.ts +74 -0
- package/src/resources/extensions/gsd/tests/uok-gitops-turn-action.test.ts +38 -0
- package/src/resources/extensions/gsd/tests/verification-retry-policy.test.ts +69 -4
- package/src/resources/extensions/gsd/tests/workflow-manifest.test.ts +96 -15
- package/src/resources/extensions/gsd/tests/workflow-mcp-preflight.test.ts +1 -0
- package/src/resources/extensions/gsd/tests/workflow-mcp.test.ts +8 -4
- package/src/resources/extensions/gsd/tests/workflow-tool-executors.test.ts +6 -5
- package/src/resources/extensions/gsd/tests/worktree-manager.test.ts +39 -0
- package/src/resources/extensions/gsd/tools/complete-milestone.ts +3 -2
- package/src/resources/extensions/gsd/tools/complete-slice.ts +3 -30
- package/src/resources/extensions/gsd/tools/complete-task.ts +7 -39
- package/src/resources/extensions/gsd/tools/plan-slice.ts +60 -47
- package/src/resources/extensions/gsd/tools/plan-task.ts +30 -5
- package/src/resources/extensions/gsd/undo.ts +47 -6
- package/src/resources/extensions/gsd/unit-registry.ts +11 -3
- package/src/resources/extensions/gsd/verification-gate.ts +8 -0
- package/src/resources/extensions/gsd/workflow-manifest.ts +141 -7
- package/src/resources/extensions/gsd/workflow-projections.ts +20 -14
- package/src/resources/extensions/gsd/worktree-manager.ts +41 -1
- package/dist/web/standalone/.next/static/chunks/2772.bfa657f49f955239.js +0 -1
- package/dist/web/standalone/.next/static/chunks/796.3976108148518f7d.js +0 -10
- package/dist/web/standalone/.next/static/chunks/app/_not-found/page-a6fb1847f67f167c.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/page-6644fc6ee8ca1247.js +0 -1
- package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-1115d46ac61b9823.js +0 -1
- package/dist/web/standalone/.next/static/chunks/webpack-7c1d97e39be2da11.js +0 -1
- /package/dist/web/standalone/.next/static/{SzEuqWX37DR9MEpEuQjP1 → zQLcXm0Za8lexoXtgDpMG}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{SzEuqWX37DR9MEpEuQjP1 → zQLcXm0Za8lexoXtgDpMG}/_ssgManifest.js +0 -0
|
@@ -29,21 +29,22 @@ test("#2007 bug 1: MAX_ARTIFACT_VERIFICATION_RETRIES constant is defined", () =>
|
|
|
29
29
|
assert.equal(MAX_ARTIFACT_VERIFICATION_RETRIES, 3);
|
|
30
30
|
});
|
|
31
31
|
|
|
32
|
-
test("#2007 bug 1: retry state
|
|
32
|
+
test("#2007 bug 1: retry state keeps attempt separate from failure context", () => {
|
|
33
33
|
const s = new AutoSession();
|
|
34
34
|
const retryKey = "execute-task:M001/S01/T01";
|
|
35
|
+
const failureContext = "Missing expected artifact";
|
|
35
36
|
|
|
36
37
|
for (let attempt = 1; attempt <= MAX_ARTIFACT_VERIFICATION_RETRIES; attempt++) {
|
|
37
38
|
s.verificationRetryCount.set(retryKey, attempt);
|
|
38
39
|
s.pendingVerificationRetry = {
|
|
39
40
|
unitId: "M001/S01/T01",
|
|
40
|
-
failureContext
|
|
41
|
+
failureContext,
|
|
41
42
|
attempt,
|
|
42
43
|
};
|
|
43
44
|
|
|
44
45
|
assert.equal(s.verificationRetryCount.get(retryKey), attempt);
|
|
45
46
|
assert.equal(s.pendingVerificationRetry.attempt, attempt);
|
|
46
|
-
assert.
|
|
47
|
+
assert.equal(s.pendingVerificationRetry.failureContext, failureContext);
|
|
47
48
|
}
|
|
48
49
|
});
|
|
49
50
|
|
|
@@ -4,7 +4,7 @@ import { mkdtempSync, mkdirSync, realpathSync, rmSync, writeFileSync } from "nod
|
|
|
4
4
|
import { join } from "node:path";
|
|
5
5
|
import { tmpdir } from "node:os";
|
|
6
6
|
|
|
7
|
-
import { resolveExpectedArtifactPath } from "../auto-artifact-paths.ts";
|
|
7
|
+
import { resolveExpectedArtifactPath, resolveSliceResearchLocation, resolveExistingSliceResearchPath } from "../auto-artifact-paths.ts";
|
|
8
8
|
import { clearPathCache, _clearGsdRootCache, isLegacyMilestonesLayout, milestonesDir } from "../paths.ts";
|
|
9
9
|
|
|
10
10
|
test("worktree artifact resolution falls back to project .gsd artifacts", () => {
|
|
@@ -359,3 +359,100 @@ test("canonical worktree + project-root legacy dir produces legacy filename (#bu
|
|
|
359
359
|
rmSync(root, { recursive: true, force: true });
|
|
360
360
|
}
|
|
361
361
|
});
|
|
362
|
+
|
|
363
|
+
// ── resolveSliceResearchLocation / resolveExistingSliceResearchPath ───────────
|
|
364
|
+
//
|
|
365
|
+
// Added in the code-quality consolidation PR as the shared dual-path resolver
|
|
366
|
+
// for slice RESEARCH files (worktree projection first, then canonical path
|
|
367
|
+
// fallback). These tests guard: missing file → null pair; existing legacy-
|
|
368
|
+
// layout file → correct absolute and relative paths.
|
|
369
|
+
|
|
370
|
+
test("resolveSliceResearchLocation returns null pair when no RESEARCH file exists", () => {
|
|
371
|
+
const root = realpathSync(mkdtempSync(join(tmpdir(), "gsd-research-missing-")));
|
|
372
|
+
try {
|
|
373
|
+
const milestoneDir = join(root, ".gsd", "milestones", "M001");
|
|
374
|
+
mkdirSync(join(milestoneDir, "slices", "S01"), { recursive: true });
|
|
375
|
+
// Content-bearing dir so it is not treated as META-only, but no RESEARCH file.
|
|
376
|
+
writeFileSync(join(milestoneDir, "M001-CONTEXT.md"), "# context\n");
|
|
377
|
+
|
|
378
|
+
_clearGsdRootCache();
|
|
379
|
+
clearPathCache();
|
|
380
|
+
|
|
381
|
+
const result = resolveSliceResearchLocation(root, "M001", "S01");
|
|
382
|
+
assert.strictEqual(result.absolutePath, null, "absolutePath must be null when no RESEARCH exists");
|
|
383
|
+
assert.strictEqual(result.relativePath, null, "relativePath must be null when no RESEARCH exists");
|
|
384
|
+
} finally {
|
|
385
|
+
_clearGsdRootCache();
|
|
386
|
+
clearPathCache();
|
|
387
|
+
rmSync(root, { recursive: true, force: true });
|
|
388
|
+
}
|
|
389
|
+
});
|
|
390
|
+
|
|
391
|
+
test("resolveExistingSliceResearchPath returns null when no RESEARCH file exists", () => {
|
|
392
|
+
const root = realpathSync(mkdtempSync(join(tmpdir(), "gsd-research-null-")));
|
|
393
|
+
try {
|
|
394
|
+
const milestoneDir = join(root, ".gsd", "milestones", "M001");
|
|
395
|
+
mkdirSync(join(milestoneDir, "slices", "S01"), { recursive: true });
|
|
396
|
+
writeFileSync(join(milestoneDir, "M001-CONTEXT.md"), "# context\n");
|
|
397
|
+
|
|
398
|
+
_clearGsdRootCache();
|
|
399
|
+
clearPathCache();
|
|
400
|
+
|
|
401
|
+
assert.strictEqual(
|
|
402
|
+
resolveExistingSliceResearchPath(root, "M001", "S01"),
|
|
403
|
+
null,
|
|
404
|
+
"must return null when RESEARCH file is absent",
|
|
405
|
+
);
|
|
406
|
+
} finally {
|
|
407
|
+
_clearGsdRootCache();
|
|
408
|
+
clearPathCache();
|
|
409
|
+
rmSync(root, { recursive: true, force: true });
|
|
410
|
+
}
|
|
411
|
+
});
|
|
412
|
+
|
|
413
|
+
test("resolveSliceResearchLocation finds existing RESEARCH in legacy layout", () => {
|
|
414
|
+
const root = realpathSync(mkdtempSync(join(tmpdir(), "gsd-research-legacy-")));
|
|
415
|
+
try {
|
|
416
|
+
const milestoneDir = join(root, ".gsd", "milestones", "M001");
|
|
417
|
+
const sliceDir = join(milestoneDir, "slices", "S01");
|
|
418
|
+
mkdirSync(sliceDir, { recursive: true });
|
|
419
|
+
writeFileSync(join(milestoneDir, "M001-CONTEXT.md"), "# context\n");
|
|
420
|
+
const researchFile = join(sliceDir, "S01-RESEARCH.md");
|
|
421
|
+
writeFileSync(researchFile, "# slice research\n");
|
|
422
|
+
|
|
423
|
+
_clearGsdRootCache();
|
|
424
|
+
clearPathCache();
|
|
425
|
+
|
|
426
|
+
const result = resolveSliceResearchLocation(root, "M001", "S01");
|
|
427
|
+
assert.ok(result.absolutePath !== null, "absolutePath must be non-null when RESEARCH exists");
|
|
428
|
+
assert.ok(result.relativePath !== null, "relativePath must be non-null when RESEARCH exists");
|
|
429
|
+
assert.equal(result.absolutePath, researchFile, "absolutePath must point to the RESEARCH file");
|
|
430
|
+
} finally {
|
|
431
|
+
_clearGsdRootCache();
|
|
432
|
+
clearPathCache();
|
|
433
|
+
rmSync(root, { recursive: true, force: true });
|
|
434
|
+
}
|
|
435
|
+
});
|
|
436
|
+
|
|
437
|
+
test("resolveExistingSliceResearchPath returns absolute path when RESEARCH exists (legacy layout)", () => {
|
|
438
|
+
const root = realpathSync(mkdtempSync(join(tmpdir(), "gsd-research-existing-")));
|
|
439
|
+
try {
|
|
440
|
+
const milestoneDir = join(root, ".gsd", "milestones", "M001");
|
|
441
|
+
const sliceDir = join(milestoneDir, "slices", "S01");
|
|
442
|
+
mkdirSync(sliceDir, { recursive: true });
|
|
443
|
+
writeFileSync(join(milestoneDir, "M001-CONTEXT.md"), "# context\n");
|
|
444
|
+
const researchFile = join(sliceDir, "S01-RESEARCH.md");
|
|
445
|
+
writeFileSync(researchFile, "# research\n");
|
|
446
|
+
|
|
447
|
+
_clearGsdRootCache();
|
|
448
|
+
clearPathCache();
|
|
449
|
+
|
|
450
|
+
const result = resolveExistingSliceResearchPath(root, "M001", "S01");
|
|
451
|
+
assert.ok(result !== null, "must return non-null when RESEARCH exists");
|
|
452
|
+
assert.equal(result, researchFile, "must return the absolute path to the RESEARCH file");
|
|
453
|
+
} finally {
|
|
454
|
+
_clearGsdRootCache();
|
|
455
|
+
clearPathCache();
|
|
456
|
+
rmSync(root, { recursive: true, force: true });
|
|
457
|
+
}
|
|
458
|
+
});
|
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
getNewBudgetAlertLevel,
|
|
9
9
|
resolveCompactionThresholdPercent,
|
|
10
10
|
shouldRerootStepSessionForContext,
|
|
11
|
+
shouldWarnStepSessionForContext,
|
|
11
12
|
} from "../auto.js";
|
|
12
13
|
import {
|
|
13
14
|
getUnitCostSpikeAction,
|
|
@@ -73,11 +74,19 @@ test("resolveCompactionThresholdPercent defaults to 60 and accepts ratio prefs",
|
|
|
73
74
|
assert.equal(resolveCompactionThresholdPercent(0.4), 60);
|
|
74
75
|
});
|
|
75
76
|
|
|
76
|
-
test("
|
|
77
|
-
assert.equal(
|
|
78
|
-
assert.equal(
|
|
79
|
-
assert.equal(
|
|
80
|
-
assert.equal(
|
|
77
|
+
test("shouldWarnStepSessionForContext uses compaction threshold pref", () => {
|
|
78
|
+
assert.equal(shouldWarnStepSessionForContext(59.9, 0.6), false);
|
|
79
|
+
assert.equal(shouldWarnStepSessionForContext(60, 0.6), true);
|
|
80
|
+
assert.equal(shouldWarnStepSessionForContext(72, 0.6), true);
|
|
81
|
+
assert.equal(shouldWarnStepSessionForContext(undefined, 0.6), false);
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
test("shouldRerootStepSessionForContext only fires at the hard context threshold", () => {
|
|
85
|
+
assert.equal(shouldRerootStepSessionForContext(72), false);
|
|
86
|
+
assert.equal(shouldRerootStepSessionForContext(89.9), false);
|
|
87
|
+
assert.equal(shouldRerootStepSessionForContext(90), true);
|
|
88
|
+
assert.equal(shouldRerootStepSessionForContext(273.8), true);
|
|
89
|
+
assert.equal(shouldRerootStepSessionForContext(undefined), false);
|
|
81
90
|
});
|
|
82
91
|
|
|
83
92
|
test("resolveUnitCostSpikeMultiplier disables the spike pause for burn-max", () => {
|
|
@@ -14,6 +14,7 @@ import { capturePauseAutoUnitIdentity, pauseAuto, isAutoActive } from "../auto.t
|
|
|
14
14
|
import { _resetPendingResolve, _setCurrentResolve } from "../auto/resolve.ts";
|
|
15
15
|
import { autoSession } from "../auto-runtime-state.ts";
|
|
16
16
|
import { _isPauseOriginCancelledResult } from "../auto/phase-helpers.ts";
|
|
17
|
+
import { handleAutoCommand } from "../commands/handlers/auto.ts";
|
|
17
18
|
|
|
18
19
|
test("pauseAuto sets s.active = false synchronously before first await (blocks concurrent re-entry)", async () => {
|
|
19
20
|
const base = mkdtempSync(join(tmpdir(), "gsd-double-pause-guard-"));
|
|
@@ -80,6 +81,41 @@ test("pauseAuto marks paused and cancels the in-flight unit before first await",
|
|
|
80
81
|
}
|
|
81
82
|
});
|
|
82
83
|
|
|
84
|
+
test("/gsd pause aborts the active pi turn before first await", async () => {
|
|
85
|
+
autoSession.reset();
|
|
86
|
+
autoSession.active = true;
|
|
87
|
+
let abortCount = 0;
|
|
88
|
+
const ctx = {
|
|
89
|
+
hasUI: false,
|
|
90
|
+
isIdle: () => false,
|
|
91
|
+
abort: () => {
|
|
92
|
+
abortCount += 1;
|
|
93
|
+
},
|
|
94
|
+
sessionManager: {
|
|
95
|
+
getSessionFile: () => null,
|
|
96
|
+
},
|
|
97
|
+
ui: {
|
|
98
|
+
setStatus() {},
|
|
99
|
+
setWidget() {},
|
|
100
|
+
notify() {},
|
|
101
|
+
},
|
|
102
|
+
} as any;
|
|
103
|
+
|
|
104
|
+
try {
|
|
105
|
+
const pausePromise = handleAutoCommand("pause", ctx, {} as any);
|
|
106
|
+
|
|
107
|
+
assert.equal(
|
|
108
|
+
abortCount,
|
|
109
|
+
1,
|
|
110
|
+
"pauseAuto must abort the active pi turn before reporting auto-mode paused",
|
|
111
|
+
);
|
|
112
|
+
|
|
113
|
+
await pausePromise.catch(() => {});
|
|
114
|
+
} finally {
|
|
115
|
+
autoSession.reset();
|
|
116
|
+
}
|
|
117
|
+
});
|
|
118
|
+
|
|
83
119
|
test("transient-abort errorContext is not classified as pause-origin cancellation", () => {
|
|
84
120
|
// The phases.ts fix passes unitResult.errorContext to pauseAuto for transient aborts.
|
|
85
121
|
// _isPauseOriginCancelledResult must return false when errorContext is present, ensuring
|
|
@@ -3,13 +3,14 @@
|
|
|
3
3
|
import { test } from "node:test";
|
|
4
4
|
import assert from "node:assert/strict";
|
|
5
5
|
import { execFileSync } from "node:child_process";
|
|
6
|
-
import { mkdirSync, mkdtempSync, realpathSync, rmSync, writeFileSync } from "node:fs";
|
|
6
|
+
import { existsSync, mkdirSync, mkdtempSync, realpathSync, rmSync, writeFileSync } from "node:fs";
|
|
7
7
|
import { tmpdir } from "node:os";
|
|
8
8
|
import { join, dirname } from "node:path";
|
|
9
9
|
|
|
10
10
|
import {
|
|
11
11
|
anchorProcessCwdForAutoResume,
|
|
12
12
|
cleanupAfterLoopExit,
|
|
13
|
+
maybeRerootStepSessionForHighContext,
|
|
13
14
|
pauseAuto,
|
|
14
15
|
rerootCommandSession,
|
|
15
16
|
stopAuto,
|
|
@@ -478,8 +479,8 @@ test("cleanupAfterLoopExit preserves step-mode surface and worktree session afte
|
|
|
478
479
|
}
|
|
479
480
|
});
|
|
480
481
|
|
|
481
|
-
test("cleanupAfterLoopExit re-
|
|
482
|
-
const base = mkdtempSync(join(tmpdir(), "gsd-step-
|
|
482
|
+
test("cleanupAfterLoopExit warns but does not re-root step-mode session at soft compaction threshold", async (t) => {
|
|
483
|
+
const base = mkdtempSync(join(tmpdir(), "gsd-step-soft-context-"));
|
|
483
484
|
const worktree = join(base, ".gsd", "worktrees", "M001");
|
|
484
485
|
const previousCwd = process.cwd();
|
|
485
486
|
const newSessionWorkspaces: string[] = [];
|
|
@@ -515,7 +516,59 @@ test("cleanupAfterLoopExit re-roots step-mode session when context exceeds compa
|
|
|
515
516
|
},
|
|
516
517
|
} as any);
|
|
517
518
|
|
|
518
|
-
assert.deepEqual(newSessionWorkspaces, [
|
|
519
|
+
assert.deepEqual(newSessionWorkspaces, [], "soft context pressure must not force a new command session");
|
|
520
|
+
assert.equal(
|
|
521
|
+
notifyMessages.some((msg) => msg.includes("context at 72.0%") && msg.includes("Use /compact")),
|
|
522
|
+
true,
|
|
523
|
+
"soft threshold should warn with a non-disruptive compaction prompt",
|
|
524
|
+
);
|
|
525
|
+
assert.equal(autoSession.basePath, worktree);
|
|
526
|
+
assert.equal(realpathSync(process.cwd()), realpathSync(worktree));
|
|
527
|
+
} finally {
|
|
528
|
+
autoSession.reset();
|
|
529
|
+
process.chdir(previousCwd);
|
|
530
|
+
rmSync(base, { recursive: true, force: true });
|
|
531
|
+
}
|
|
532
|
+
});
|
|
533
|
+
|
|
534
|
+
test("cleanupAfterLoopExit re-roots step-mode session at hard context threshold", async (t) => {
|
|
535
|
+
const base = mkdtempSync(join(tmpdir(), "gsd-step-reroot-"));
|
|
536
|
+
const worktree = join(base, ".gsd", "worktrees", "M001");
|
|
537
|
+
const previousCwd = process.cwd();
|
|
538
|
+
const newSessionWorkspaces: string[] = [];
|
|
539
|
+
const notifyMessages: string[] = [];
|
|
540
|
+
|
|
541
|
+
t.mock.method(WorktreeLifecycle.prototype, "restoreToProjectRoot", function () {});
|
|
542
|
+
|
|
543
|
+
mkdirSync(worktree, { recursive: true });
|
|
544
|
+
process.chdir(worktree);
|
|
545
|
+
autoSession.reset();
|
|
546
|
+
autoSession.active = true;
|
|
547
|
+
autoSession.paused = false;
|
|
548
|
+
autoSession.stepMode = true;
|
|
549
|
+
autoSession.preserveStepSurfaceAfterLoopExit = true;
|
|
550
|
+
autoSession.basePath = worktree;
|
|
551
|
+
autoSession.originalBasePath = base;
|
|
552
|
+
autoSession.cmdCtx = {
|
|
553
|
+
getContextUsage: () => ({ percent: 92, tokens: 920_000, contextWindow: 1_000_000 }),
|
|
554
|
+
newSession: async ({ workspaceRoot }: { workspaceRoot: string }) => {
|
|
555
|
+
newSessionWorkspaces.push(workspaceRoot);
|
|
556
|
+
return { cancelled: false };
|
|
557
|
+
},
|
|
558
|
+
} as any;
|
|
559
|
+
|
|
560
|
+
try {
|
|
561
|
+
await cleanupAfterLoopExit({
|
|
562
|
+
hasUI: true,
|
|
563
|
+
ui: {
|
|
564
|
+
setStatus: () => {},
|
|
565
|
+
setWidget: () => {},
|
|
566
|
+
setHeader: () => {},
|
|
567
|
+
notify: (_msg: string) => notifyMessages.push(_msg),
|
|
568
|
+
},
|
|
569
|
+
} as any);
|
|
570
|
+
|
|
571
|
+
assert.deepEqual(newSessionWorkspaces, [worktree], "critical context pressure should re-root in the active worktree");
|
|
519
572
|
assert.equal(
|
|
520
573
|
notifyMessages.some((msg) => msg.includes("Fresh session ready for /gsd next")),
|
|
521
574
|
true,
|
|
@@ -530,6 +583,131 @@ test("cleanupAfterLoopExit re-roots step-mode session when context exceeds compa
|
|
|
530
583
|
}
|
|
531
584
|
});
|
|
532
585
|
|
|
586
|
+
test("maybeRerootStepSessionForHighContext re-roots at the hard threshold even when the soft pref is set above it", async () => {
|
|
587
|
+
// Regression: the hard 90% re-root must not be gated behind the configurable
|
|
588
|
+
// soft warn threshold, which is allowed up to 0.95. At 92% usage with a 0.95
|
|
589
|
+
// soft pref the soft warn predicate is false, but the session must still
|
|
590
|
+
// re-root because usage crossed the fixed hard boundary.
|
|
591
|
+
const dir = mkdtempSync(join(tmpdir(), "gsd-hard-reroot-high-soft-"));
|
|
592
|
+
const project = join(dir, "project");
|
|
593
|
+
const gsdHomeDir = join(dir, "home");
|
|
594
|
+
const previousCwd = process.cwd();
|
|
595
|
+
const previousGsdHome = process.env.GSD_HOME;
|
|
596
|
+
|
|
597
|
+
mkdirSync(join(project, ".gsd"), { recursive: true });
|
|
598
|
+
mkdirSync(gsdHomeDir, { recursive: true });
|
|
599
|
+
writeFileSync(
|
|
600
|
+
join(project, ".gsd", "PREFERENCES.md"),
|
|
601
|
+
["---", "version: 1", "context_management:", " compaction_threshold_percent: 0.95", "---", ""].join("\n"),
|
|
602
|
+
"utf-8",
|
|
603
|
+
);
|
|
604
|
+
|
|
605
|
+
process.env.GSD_HOME = gsdHomeDir;
|
|
606
|
+
process.chdir(project);
|
|
607
|
+
|
|
608
|
+
const newSessionWorkspaces: string[] = [];
|
|
609
|
+
const notifyMessages: string[] = [];
|
|
610
|
+
const cmdCtx = {
|
|
611
|
+
getContextUsage: () => ({ percent: 92, tokens: 920_000, contextWindow: 1_000_000 }),
|
|
612
|
+
newSession: async ({ workspaceRoot }: { workspaceRoot: string }) => {
|
|
613
|
+
newSessionWorkspaces.push(workspaceRoot);
|
|
614
|
+
return { cancelled: false };
|
|
615
|
+
},
|
|
616
|
+
} as any;
|
|
617
|
+
const ctx = { ui: { notify: (msg: string) => notifyMessages.push(msg) } } as any;
|
|
618
|
+
|
|
619
|
+
try {
|
|
620
|
+
const result = await maybeRerootStepSessionForHighContext(ctx, project, cmdCtx, project);
|
|
621
|
+
|
|
622
|
+
assert.equal(result.rerooted, true, "92% usage must re-root even when the soft pref is 95%");
|
|
623
|
+
assert.deepEqual(newSessionWorkspaces, [project], "hard context pressure must re-root the command session");
|
|
624
|
+
const rerootMessage = notifyMessages.find((msg) => msg.includes("Fresh session ready for /gsd next"));
|
|
625
|
+
assert.ok(rerootMessage, "hard re-root should notify the user");
|
|
626
|
+
// The re-root was triggered by the 90% hard limit, so the notification must
|
|
627
|
+
// cite that limit and not the configured 95% soft compaction threshold.
|
|
628
|
+
assert.match(
|
|
629
|
+
rerootMessage,
|
|
630
|
+
/hard threshold: 90%/,
|
|
631
|
+
"hard re-root notification must cite the 90% hard threshold",
|
|
632
|
+
);
|
|
633
|
+
assert.equal(
|
|
634
|
+
rerootMessage.includes("95%"),
|
|
635
|
+
false,
|
|
636
|
+
"hard re-root notification must not cite the configured soft compaction threshold",
|
|
637
|
+
);
|
|
638
|
+
} finally {
|
|
639
|
+
process.chdir(previousCwd);
|
|
640
|
+
if (previousGsdHome === undefined) delete process.env.GSD_HOME;
|
|
641
|
+
else process.env.GSD_HOME = previousGsdHome;
|
|
642
|
+
rmSync(dir, { recursive: true, force: true });
|
|
643
|
+
}
|
|
644
|
+
});
|
|
645
|
+
|
|
646
|
+
test("maybeRerootStepSessionForHighContext writes a compaction snapshot only at the hard boundary", async () => {
|
|
647
|
+
// Regression: the snapshot is reserved for the hard re-root. Soft-only
|
|
648
|
+
// pressure must warn without writing a compaction snapshot.
|
|
649
|
+
const dir = mkdtempSync(join(tmpdir(), "gsd-soft-no-snapshot-"));
|
|
650
|
+
const project = join(dir, "project");
|
|
651
|
+
const gsdHomeDir = join(dir, "home");
|
|
652
|
+
const previousCwd = process.cwd();
|
|
653
|
+
const previousGsdHome = process.env.GSD_HOME;
|
|
654
|
+
|
|
655
|
+
mkdirSync(join(project, ".gsd"), { recursive: true });
|
|
656
|
+
mkdirSync(gsdHomeDir, { recursive: true });
|
|
657
|
+
writeFileSync(
|
|
658
|
+
join(project, ".gsd", "PREFERENCES.md"),
|
|
659
|
+
["---", "version: 1", "context_management:", " compaction_threshold_percent: 0.6", "---", ""].join("\n"),
|
|
660
|
+
"utf-8",
|
|
661
|
+
);
|
|
662
|
+
|
|
663
|
+
process.env.GSD_HOME = gsdHomeDir;
|
|
664
|
+
process.chdir(project);
|
|
665
|
+
|
|
666
|
+
const newSessionWorkspaces: string[] = [];
|
|
667
|
+
const notifyMessages: string[] = [];
|
|
668
|
+
let contextPercent = 72;
|
|
669
|
+
const cmdCtx = {
|
|
670
|
+
getContextUsage: () => ({ percent: contextPercent, tokens: contextPercent * 10_000, contextWindow: 1_000_000 }),
|
|
671
|
+
newSession: async ({ workspaceRoot }: { workspaceRoot: string }) => {
|
|
672
|
+
newSessionWorkspaces.push(workspaceRoot);
|
|
673
|
+
return { cancelled: false };
|
|
674
|
+
},
|
|
675
|
+
} as any;
|
|
676
|
+
const ctx = { ui: { notify: (msg: string) => notifyMessages.push(msg) } } as any;
|
|
677
|
+
const snapshotPath = join(project, ".gsd", "last-snapshot.md");
|
|
678
|
+
|
|
679
|
+
try {
|
|
680
|
+
const softResult = await maybeRerootStepSessionForHighContext(ctx, project, cmdCtx, project);
|
|
681
|
+
assert.equal(softResult.rerooted, false, "soft pressure must not re-root");
|
|
682
|
+
assert.deepEqual(newSessionWorkspaces, [], "soft pressure must not open a new session");
|
|
683
|
+
assert.equal(
|
|
684
|
+
existsSync(snapshotPath),
|
|
685
|
+
false,
|
|
686
|
+
"soft-only pressure must not write a compaction snapshot",
|
|
687
|
+
);
|
|
688
|
+
assert.equal(
|
|
689
|
+
notifyMessages.some((msg) => msg.includes("context at 72.0%") && msg.includes("Use /compact")),
|
|
690
|
+
true,
|
|
691
|
+
"soft threshold should warn with a non-disruptive compaction prompt",
|
|
692
|
+
);
|
|
693
|
+
|
|
694
|
+
contextPercent = 92;
|
|
695
|
+
const hardResult = await maybeRerootStepSessionForHighContext(ctx, project, cmdCtx, project);
|
|
696
|
+
assert.equal(hardResult.rerooted, true, "hard pressure must re-root");
|
|
697
|
+
assert.deepEqual(newSessionWorkspaces, [project], "hard pressure should re-root once");
|
|
698
|
+
assert.equal(
|
|
699
|
+
existsSync(snapshotPath),
|
|
700
|
+
true,
|
|
701
|
+
"hard boundary must write the compaction snapshot",
|
|
702
|
+
);
|
|
703
|
+
} finally {
|
|
704
|
+
process.chdir(previousCwd);
|
|
705
|
+
if (previousGsdHome === undefined) delete process.env.GSD_HOME;
|
|
706
|
+
else process.env.GSD_HOME = previousGsdHome;
|
|
707
|
+
rmSync(dir, { recursive: true, force: true });
|
|
708
|
+
}
|
|
709
|
+
});
|
|
710
|
+
|
|
533
711
|
test("cleanupAfterLoopExit restores project root through lifecycle and preserves chdir", async (t) => {
|
|
534
712
|
const base = mkdtempSync(join(tmpdir(), "gsd-cleanup-lifecycle-"));
|
|
535
713
|
const worktree = join(base, ".gsd", "worktrees", "M001");
|
|
@@ -1917,6 +1917,41 @@ test("#57: writeReactiveExecuteBlocker reconciles batch task statuses and append
|
|
|
1917
1917
|
}
|
|
1918
1918
|
});
|
|
1919
1919
|
|
|
1920
|
+
test("#1088: writeReactiveExecuteBlocker preserves deferred batch task statuses", () => {
|
|
1921
|
+
const base = makeTmpBase();
|
|
1922
|
+
try {
|
|
1923
|
+
openDatabase(join(base, ".gsd", "gsd.db"));
|
|
1924
|
+
insertMilestone({ id: "M001", title: "Milestone", status: "active" });
|
|
1925
|
+
insertSlice({ id: "S01", milestoneId: "M001", title: "Slice", status: "pending" });
|
|
1926
|
+
insertTask({ id: "T01", milestoneId: "M001", sliceId: "S01", title: "One", status: "deferred" });
|
|
1927
|
+
insertTask({ id: "T02", milestoneId: "M001", sliceId: "S01", title: "Two", status: "deferred" });
|
|
1928
|
+
writeFileSync(
|
|
1929
|
+
join(base, ".gsd", "milestones", "M001", "slices", "S01", "tasks", "T01-SUMMARY.md"),
|
|
1930
|
+
"# T01 Summary\n",
|
|
1931
|
+
"utf-8",
|
|
1932
|
+
);
|
|
1933
|
+
|
|
1934
|
+
const recovery = writeReactiveExecuteBlocker(
|
|
1935
|
+
"M001/S01/reactive+T01,T02",
|
|
1936
|
+
base,
|
|
1937
|
+
"verification retries exhausted",
|
|
1938
|
+
);
|
|
1939
|
+
|
|
1940
|
+
assert.ok(recovery, "recovery should run with DB available");
|
|
1941
|
+
assert.deepEqual(recovery!.completedTaskIds, []);
|
|
1942
|
+
assert.deepEqual(recovery!.skippedTaskIds, []);
|
|
1943
|
+
assert.deepEqual(recovery!.unchangedTaskIds, ["T01", "T02"]);
|
|
1944
|
+
assert.equal(getTask("M001", "S01", "T01")?.status, "deferred");
|
|
1945
|
+
assert.equal(getTask("M001", "S01", "T02")?.status, "deferred");
|
|
1946
|
+
|
|
1947
|
+
const events = readEvents(join(base, ".gsd", "event-log.jsonl"));
|
|
1948
|
+
assert.equal(events.some((e) => e.params.taskId === "T01" || e.params.taskId === "T02"), false);
|
|
1949
|
+
} finally {
|
|
1950
|
+
closeDatabase();
|
|
1951
|
+
cleanup(base);
|
|
1952
|
+
}
|
|
1953
|
+
});
|
|
1954
|
+
|
|
1920
1955
|
test("#4414: verifyExpectedArtifact parallel-research succeeds when all research-ready slices have RESEARCH", () => {
|
|
1921
1956
|
const base = makeTmpBase();
|
|
1922
1957
|
try {
|
|
@@ -15,15 +15,21 @@
|
|
|
15
15
|
|
|
16
16
|
import { describe, it, beforeEach } from "node:test";
|
|
17
17
|
import assert from "node:assert/strict";
|
|
18
|
+
import { mkdtempSync, rmSync, statSync } from "node:fs";
|
|
19
|
+
import { tmpdir } from "node:os";
|
|
20
|
+
import { join } from "node:path";
|
|
18
21
|
|
|
19
22
|
import {
|
|
20
23
|
resetEvidence,
|
|
21
24
|
getEvidence,
|
|
22
25
|
recordToolCall,
|
|
23
26
|
recordToolResult,
|
|
27
|
+
saveEvidenceToDisk,
|
|
24
28
|
type BashEvidence,
|
|
25
29
|
} from "../safety/evidence-collector.js";
|
|
26
30
|
|
|
31
|
+
const waitForMtimeTick = () => new Promise(resolve => setTimeout(resolve, 25));
|
|
32
|
+
|
|
27
33
|
describe("evidence-collector: toolCallId-based matching (A-3)", () => {
|
|
28
34
|
beforeEach(() => {
|
|
29
35
|
resetEvidence();
|
|
@@ -119,4 +125,28 @@ describe("evidence-collector: toolCallId-based matching (A-3)", () => {
|
|
|
119
125
|
assert.equal(entries[1].kind, "bash");
|
|
120
126
|
assert.equal(entries[1].command, "rg TODO");
|
|
121
127
|
});
|
|
128
|
+
|
|
129
|
+
it("skips byte-identical evidence file rewrites", async (t) => {
|
|
130
|
+
const base = mkdtempSync(join(tmpdir(), "gsd-evidence-dedupe-"));
|
|
131
|
+
t.after(() => rmSync(base, { recursive: true, force: true }));
|
|
132
|
+
|
|
133
|
+
recordToolCall("tc-bash-1", "bash", { command: "pnpm test" });
|
|
134
|
+
saveEvidenceToDisk(base, "M001", "S01", "T03");
|
|
135
|
+
|
|
136
|
+
const evidenceFile = join(base, ".gsd", "safety", "evidence-M001-S01-T03.json");
|
|
137
|
+
const firstMtime = statSync(evidenceFile, { bigint: true }).mtimeNs;
|
|
138
|
+
|
|
139
|
+
await waitForMtimeTick();
|
|
140
|
+
saveEvidenceToDisk(base, "M001", "S01", "T03");
|
|
141
|
+
const secondMtime = statSync(evidenceFile, { bigint: true }).mtimeNs;
|
|
142
|
+
|
|
143
|
+
assert.equal(secondMtime, firstMtime, "unchanged evidence must not rewrite the evidence file");
|
|
144
|
+
|
|
145
|
+
await waitForMtimeTick();
|
|
146
|
+
recordToolResult("tc-bash-1", "bash", "Command exited with code 0\nok\n", false);
|
|
147
|
+
saveEvidenceToDisk(base, "M001", "S01", "T03");
|
|
148
|
+
const thirdMtime = statSync(evidenceFile, { bigint: true }).mtimeNs;
|
|
149
|
+
|
|
150
|
+
assert.ok(thirdMtime > secondMtime, "changed evidence must still be persisted");
|
|
151
|
+
});
|
|
122
152
|
});
|
|
@@ -460,6 +460,7 @@ describe("Batch 3 prompt templates resolve", () => {
|
|
|
460
460
|
const out = loadPrompt("code-review", { scope: "s", depth: "deep", fixMode: "off", reviewId: "001" });
|
|
461
461
|
assert.match(out, /deep/);
|
|
462
462
|
assert.match(out, /001/);
|
|
463
|
+
assert.match(out, /diff-first/i, "code-review prompt should require diff-first context gathering");
|
|
463
464
|
});
|
|
464
465
|
test("review.md loads with target + reviewers", () => {
|
|
465
466
|
const out = loadPrompt("review", { target: "t", reviewers: "claude, codex" });
|
|
@@ -312,6 +312,34 @@ console.log('\n=== complete-milestone: incomplete slices block closeout ===');
|
|
|
312
312
|
cleanup(dbPath);
|
|
313
313
|
}
|
|
314
314
|
|
|
315
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
316
|
+
// complete-milestone: deferred slices are inactive for closeout
|
|
317
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
318
|
+
|
|
319
|
+
console.log('\n=== complete-milestone: deferred slices do not block closeout ===');
|
|
320
|
+
{
|
|
321
|
+
const dbPath = tempDbPath();
|
|
322
|
+
openDatabase(dbPath);
|
|
323
|
+
const { basePath } = createTempProject();
|
|
324
|
+
seedCompletedMilestone({ basePath, validationVerdict: 'pass' });
|
|
325
|
+
insertSlice({ id: 'S02', milestoneId: 'M001', title: 'Deferred Slice', status: 'deferred' });
|
|
326
|
+
insertTask({
|
|
327
|
+
id: 'T02',
|
|
328
|
+
sliceId: 'S02',
|
|
329
|
+
milestoneId: 'M001',
|
|
330
|
+
status: 'pending',
|
|
331
|
+
title: 'Deferred Slice Task',
|
|
332
|
+
});
|
|
333
|
+
|
|
334
|
+
const result = await handleCompleteMilestone(makeValidParams(), basePath);
|
|
335
|
+
|
|
336
|
+
assertTrue(!('error' in result), 'deferred slice should not block milestone completion');
|
|
337
|
+
assertEq(getMilestone('M001')!.status, 'complete', 'milestone should complete with deferred inactive slice');
|
|
338
|
+
|
|
339
|
+
cleanupDir(basePath);
|
|
340
|
+
cleanup(dbPath);
|
|
341
|
+
}
|
|
342
|
+
|
|
315
343
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
316
344
|
// complete-milestone: deep task check (slice closed, task not)
|
|
317
345
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
@@ -7,6 +7,10 @@ import { join } from "node:path";
|
|
|
7
7
|
|
|
8
8
|
import { postUnitPreVerification } from "../auto-post-unit.ts";
|
|
9
9
|
import { AutoSession } from "../auto/session.ts";
|
|
10
|
+
import {
|
|
11
|
+
decideVerificationRetry,
|
|
12
|
+
hashVerificationFailureContext,
|
|
13
|
+
} from "../auto/verification-retry-policy.ts";
|
|
10
14
|
import { cleanup, makeTempRepo } from "./test-utils.ts";
|
|
11
15
|
|
|
12
16
|
function makePostUnitContext(base: string, s: AutoSession, notifications: string[]) {
|
|
@@ -227,3 +231,68 @@ test("complete-slice with gsd_replan_slice but no REPLAN artifact retries", asyn
|
|
|
227
231
|
cleanup(base);
|
|
228
232
|
}
|
|
229
233
|
});
|
|
234
|
+
|
|
235
|
+
test("artifact retry context stays stable across attempts while notifications show attempt count", async () => {
|
|
236
|
+
const base = makeTempRepo("gsd-artifact-retry-stable-context-");
|
|
237
|
+
try {
|
|
238
|
+
mkdirSync(join(base, ".gsd", "milestones", "M001", "slices", "S01"), { recursive: true });
|
|
239
|
+
|
|
240
|
+
const s = new AutoSession();
|
|
241
|
+
s.active = true;
|
|
242
|
+
s.basePath = base;
|
|
243
|
+
s.currentUnit = { type: "complete-slice", id: "M001/S01", startedAt: Date.now() };
|
|
244
|
+
|
|
245
|
+
const notifications: string[] = [];
|
|
246
|
+
const pctx = makePostUnitContext(base, s, notifications);
|
|
247
|
+
const opts = {
|
|
248
|
+
skipSettleDelay: true,
|
|
249
|
+
skipWorktreeSync: true,
|
|
250
|
+
agentEndMessages: [
|
|
251
|
+
{
|
|
252
|
+
role: "toolResult",
|
|
253
|
+
toolName: "gsd_replan_slice",
|
|
254
|
+
isError: false,
|
|
255
|
+
content: "Slice replanned with reopened task T02.",
|
|
256
|
+
},
|
|
257
|
+
],
|
|
258
|
+
};
|
|
259
|
+
|
|
260
|
+
assert.equal(await postUnitPreVerification(pctx, opts), "retry");
|
|
261
|
+
const firstRetry = s.pendingVerificationRetry;
|
|
262
|
+
assert.ok(firstRetry);
|
|
263
|
+
assert.equal(firstRetry.attempt, 1);
|
|
264
|
+
assert.doesNotMatch(firstRetry.failureContext, /\(attempt \d\/3\)\.$/);
|
|
265
|
+
const firstFailureHash = hashVerificationFailureContext(firstRetry.failureContext);
|
|
266
|
+
|
|
267
|
+
assert.equal(await postUnitPreVerification(pctx, opts), "retry");
|
|
268
|
+
const secondRetry = s.pendingVerificationRetry;
|
|
269
|
+
assert.ok(secondRetry);
|
|
270
|
+
assert.equal(secondRetry.attempt, 2);
|
|
271
|
+
assert.equal(secondRetry.failureContext, firstRetry.failureContext);
|
|
272
|
+
assert.equal(hashVerificationFailureContext(secondRetry.failureContext), firstFailureHash);
|
|
273
|
+
assert.deepEqual(
|
|
274
|
+
decideVerificationRetry({
|
|
275
|
+
unitType: s.currentUnit.type,
|
|
276
|
+
retryInfo: secondRetry,
|
|
277
|
+
previousFailureHash: firstFailureHash,
|
|
278
|
+
random: () => 0.5,
|
|
279
|
+
}),
|
|
280
|
+
{
|
|
281
|
+
action: "pause",
|
|
282
|
+
reason: "duplicate-failure-context",
|
|
283
|
+
key: "complete-slice:M001/S01",
|
|
284
|
+
failureHash: firstFailureHash,
|
|
285
|
+
},
|
|
286
|
+
);
|
|
287
|
+
assert.ok(
|
|
288
|
+
notifications.some((message) => message.includes("Retrying (attempt 1/3).")),
|
|
289
|
+
`expected first attempt notification, got: ${notifications.join("\n")}`,
|
|
290
|
+
);
|
|
291
|
+
assert.ok(
|
|
292
|
+
notifications.some((message) => message.includes("Retrying (attempt 2/3).")),
|
|
293
|
+
`expected second attempt notification, got: ${notifications.join("\n")}`,
|
|
294
|
+
);
|
|
295
|
+
} finally {
|
|
296
|
+
cleanup(base);
|
|
297
|
+
}
|
|
298
|
+
});
|