gsd-pi 2.80.0-dev.2848d9009 → 2.80.0-dev.3065f7bfa
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -2
- package/dist/resources/.managed-resources-content-hash +1 -1
- package/dist/resources/extensions/gsd/auto/loop.js +32 -1
- package/dist/resources/extensions/gsd/auto/phases.js +178 -108
- package/dist/resources/extensions/gsd/auto/resolve.js +17 -0
- package/dist/resources/extensions/gsd/auto/run-unit.js +20 -30
- package/dist/resources/extensions/gsd/auto/session.js +8 -0
- package/dist/resources/extensions/gsd/auto-direct-dispatch.js +5 -32
- package/dist/resources/extensions/gsd/auto-dispatch.js +16 -0
- package/dist/resources/extensions/gsd/auto-post-unit.js +17 -4
- package/dist/resources/extensions/gsd/auto-prompts.js +103 -16
- package/dist/resources/extensions/gsd/auto-recovery.js +43 -1
- package/dist/resources/extensions/gsd/auto-start.js +197 -6
- package/dist/resources/extensions/gsd/auto-supervisor.js +8 -1
- package/dist/resources/extensions/gsd/auto-timeout-recovery.js +2 -2
- package/dist/resources/extensions/gsd/auto-worktree.js +111 -1
- package/dist/resources/extensions/gsd/auto.js +86 -26
- package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +42 -2
- package/dist/resources/extensions/gsd/bootstrap/db-tools.js +49 -36
- package/dist/resources/extensions/gsd/bootstrap/dynamic-tools.js +15 -5
- package/dist/resources/extensions/gsd/bootstrap/exec-tools.js +33 -20
- package/dist/resources/extensions/gsd/bootstrap/journal-tools.js +7 -1
- package/dist/resources/extensions/gsd/bootstrap/memory-tools.js +9 -3
- package/dist/resources/extensions/gsd/bootstrap/query-tools.js +8 -2
- package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +259 -28
- package/dist/resources/extensions/gsd/bootstrap/system-context.js +82 -23
- package/dist/resources/extensions/gsd/clean-root-preflight.js +24 -6
- package/dist/resources/extensions/gsd/commands-handlers.js +23 -9
- package/dist/resources/extensions/gsd/context-budget.js +37 -2
- package/dist/resources/extensions/gsd/crash-recovery.js +56 -10
- package/dist/resources/extensions/gsd/db/unit-dispatches.js +39 -0
- package/dist/resources/extensions/gsd/db-base-schema.js +4 -2
- package/dist/resources/extensions/gsd/db-migration-steps.js +6 -0
- package/dist/resources/extensions/gsd/ecosystem/gsd-extension-api.js +2 -0
- package/dist/resources/extensions/gsd/git-service.js +36 -4
- package/dist/resources/extensions/gsd/gsd-db.js +46 -13
- package/dist/resources/extensions/gsd/guided-flow.js +99 -38
- package/dist/resources/extensions/gsd/memory-store.js +69 -12
- package/dist/resources/extensions/gsd/migrate/command.js +40 -1
- package/dist/resources/extensions/gsd/migration-auto-check.js +87 -0
- package/dist/resources/extensions/gsd/native-git-bridge.js +32 -8
- package/dist/resources/extensions/gsd/orphan-stash-audit.js +101 -0
- package/dist/resources/extensions/gsd/parallel-orchestrator.js +13 -3
- package/dist/resources/extensions/gsd/planning-path-scope.js +26 -0
- package/dist/resources/extensions/gsd/pre-execution-checks.js +22 -0
- package/dist/resources/extensions/gsd/prompt-loader.js +28 -2
- package/dist/resources/extensions/gsd/prompts/complete-milestone.md +16 -13
- package/dist/resources/extensions/gsd/prompts/complete-slice.md +1 -1
- package/dist/resources/extensions/gsd/prompts/execute-task.md +4 -2
- package/dist/resources/extensions/gsd/prompts/parallel-research-slices.md +1 -1
- package/dist/resources/extensions/gsd/prompts/plan-slice.md +1 -1
- package/dist/resources/extensions/gsd/prompts/quick-task.md +1 -5
- package/dist/resources/extensions/gsd/prompts/replan-slice.md +2 -2
- package/dist/resources/extensions/gsd/prompts/validate-milestone.md +2 -2
- package/dist/resources/extensions/gsd/quick.js +34 -2
- package/dist/resources/extensions/gsd/tools/context-mode-tool-result.js +15 -0
- package/dist/resources/extensions/gsd/tools/exec-search-tool.js +5 -0
- package/dist/resources/extensions/gsd/tools/exec-tool.js +3 -15
- package/dist/resources/extensions/gsd/tools/memory-tools.js +1 -0
- package/dist/resources/extensions/gsd/tools/plan-slice.js +9 -0
- package/dist/resources/extensions/gsd/tools/plan-task.js +9 -0
- package/dist/resources/extensions/gsd/tools/resume-tool.js +5 -0
- package/dist/resources/extensions/gsd/tools/workflow-tool-executors.js +1 -1
- package/dist/resources/extensions/gsd/unit-context-composer.js +12 -3
- package/dist/resources/extensions/gsd/unit-runtime.js +22 -0
- package/dist/resources/extensions/gsd/workflow-protocol.js +131 -0
- package/dist/resources/extensions/gsd/worktree-resolver.js +68 -21
- 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 +15 -15
- package/dist/web/standalone/.next/build-manifest.json +2 -2
- package/dist/web/standalone/.next/prerender-manifest.json +3 -3
- package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.html +1 -1
- package/dist/web/standalone/.next/server/app/index.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app-paths-manifest.json +15 -15
- package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
- package/dist/web/standalone/.next/server/pages/404.html +1 -1
- package/dist/web/standalone/.next/server/pages/500.html +1 -1
- package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
- package/package.json +3 -3
- package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
- package/packages/mcp-server/dist/workflow-tools.js +22 -17
- package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
- package/packages/mcp-server/src/workflow-tools.test.ts +75 -2
- package/packages/mcp-server/src/workflow-tools.ts +30 -16
- package/packages/mcp-server/tsconfig.tsbuildinfo +1 -1
- package/packages/native/tsconfig.tsbuildinfo +1 -1
- package/packages/pi-agent-core/dist/agent-loop.d.ts.map +1 -1
- package/packages/pi-agent-core/dist/agent-loop.js +4 -1
- package/packages/pi-agent-core/dist/agent-loop.js.map +1 -1
- package/packages/pi-agent-core/dist/agent.d.ts +5 -0
- 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/index.d.ts +1 -0
- package/packages/pi-agent-core/dist/index.d.ts.map +1 -1
- package/packages/pi-agent-core/dist/index.js +2 -0
- package/packages/pi-agent-core/dist/index.js.map +1 -1
- package/packages/pi-agent-core/dist/token-audit.d.ts +47 -0
- package/packages/pi-agent-core/dist/token-audit.d.ts.map +1 -0
- package/packages/pi-agent-core/dist/token-audit.js +221 -0
- package/packages/pi-agent-core/dist/token-audit.js.map +1 -0
- package/packages/pi-agent-core/dist/types.d.ts +9 -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-loop.test.ts +128 -0
- package/packages/pi-agent-core/src/agent-loop.ts +4 -1
- package/packages/pi-agent-core/src/agent.ts +8 -0
- package/packages/pi-agent-core/src/index.ts +2 -0
- package/packages/pi-agent-core/src/token-audit.test.ts +189 -0
- package/packages/pi-agent-core/src/token-audit.ts +287 -0
- package/packages/pi-agent-core/src/types.ts +14 -0
- package/packages/pi-agent-core/tsconfig.tsbuildinfo +1 -1
- package/packages/pi-coding-agent/dist/core/agent-session-abort-order.test.js +32 -0
- package/packages/pi-coding-agent/dist/core/agent-session-abort-order.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/agent-session-tool-refresh.test.js +18 -0
- package/packages/pi-coding-agent/dist/core/agent-session-tool-refresh.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/agent-session.d.ts +12 -0
- package/packages/pi-coding-agent/dist/core/agent-session.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/agent-session.js +44 -7
- package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/chat-controller-ordering.test.js +3 -1
- package/packages/pi-coding-agent/dist/core/chat-controller-ordering.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/compaction/compaction.d.ts +11 -0
- package/packages/pi-coding-agent/dist/core/compaction/compaction.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/compaction/compaction.js +9 -0
- package/packages/pi-coding-agent/dist/core/compaction/compaction.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/compaction-threshold.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/compaction-threshold.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/compaction-threshold.test.js +103 -0
- package/packages/pi-coding-agent/dist/core/compaction-threshold.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/db-snapshot.d.ts +15 -0
- package/packages/pi-coding-agent/dist/core/db-snapshot.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/db-snapshot.js +66 -0
- package/packages/pi-coding-agent/dist/core/db-snapshot.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/db-snapshot.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/db-snapshot.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/db-snapshot.test.js +24 -0
- package/packages/pi-coding-agent/dist/core/db-snapshot.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/extensions/loader.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/loader.js +8 -0
- package/packages/pi-coding-agent/dist/core/extensions/loader.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/runner.d.ts +3 -0
- package/packages/pi-coding-agent/dist/core/extensions/runner.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/runner.js +6 -6
- package/packages/pi-coding-agent/dist/core/extensions/runner.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/runner.test.js +5 -3
- package/packages/pi-coding-agent/dist/core/extensions/runner.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/types.d.ts +39 -1
- package/packages/pi-coding-agent/dist/core/extensions/types.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/types.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/hooks-runner.test.js +2 -0
- package/packages/pi-coding-agent/dist/core/hooks-runner.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/sdk-tool-filter.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/sdk-tool-filter.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/sdk-tool-filter.test.js +46 -0
- package/packages/pi-coding-agent/dist/core/sdk-tool-filter.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/sdk.d.ts +10 -2
- package/packages/pi-coding-agent/dist/core/sdk.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/sdk.js +74 -2
- package/packages/pi-coding-agent/dist/core/sdk.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/settings-manager.d.ts +20 -0
- package/packages/pi-coding-agent/dist/core/settings-manager.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/settings-manager.js +25 -0
- package/packages/pi-coding-agent/dist/core/settings-manager.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/skill-tool.test.js +22 -0
- package/packages/pi-coding-agent/dist/core/skill-tool.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/system-prompt.d.ts +6 -7
- package/packages/pi-coding-agent/dist/core/system-prompt.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/system-prompt.js +2 -3
- package/packages/pi-coding-agent/dist/core/system-prompt.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js +3 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js +13 -5
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.test.js +53 -0
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js +3 -0
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/packages/pi-coding-agent/dist/resources/extensions/memory/storage-safety-guard.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/resources/extensions/memory/storage-safety-guard.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/resources/extensions/memory/storage-safety-guard.test.js +10 -0
- package/packages/pi-coding-agent/dist/resources/extensions/memory/storage-safety-guard.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/resources/extensions/memory/storage.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/resources/extensions/memory/storage.js +3 -2
- package/packages/pi-coding-agent/dist/resources/extensions/memory/storage.js.map +1 -1
- package/packages/pi-coding-agent/src/core/agent-session-abort-order.test.ts +36 -0
- package/packages/pi-coding-agent/src/core/agent-session-tool-refresh.test.ts +25 -0
- package/packages/pi-coding-agent/src/core/agent-session.ts +48 -7
- package/packages/pi-coding-agent/src/core/chat-controller-ordering.test.ts +3 -1
- package/packages/pi-coding-agent/src/core/compaction/compaction.ts +18 -0
- package/packages/pi-coding-agent/src/core/compaction-threshold.test.ts +121 -0
- package/packages/pi-coding-agent/src/core/db-snapshot.test.ts +32 -0
- package/packages/pi-coding-agent/src/core/db-snapshot.ts +66 -0
- package/packages/pi-coding-agent/src/core/extensions/loader.ts +10 -0
- package/packages/pi-coding-agent/src/core/extensions/runner.test.ts +5 -3
- package/packages/pi-coding-agent/src/core/extensions/runner.ts +8 -5
- package/packages/pi-coding-agent/src/core/extensions/types.ts +42 -1
- package/packages/pi-coding-agent/src/core/hooks-runner.test.ts +2 -0
- package/packages/pi-coding-agent/src/core/sdk-tool-filter.test.ts +60 -0
- package/packages/pi-coding-agent/src/core/sdk.ts +85 -3
- package/packages/pi-coding-agent/src/core/settings-manager.ts +39 -1
- package/packages/pi-coding-agent/src/core/skill-tool.test.ts +28 -0
- package/packages/pi-coding-agent/src/core/system-prompt.ts +8 -10
- package/packages/pi-coding-agent/src/modes/interactive/components/tool-execution.ts +4 -0
- package/packages/pi-coding-agent/src/modes/interactive/controllers/chat-controller.test.ts +56 -0
- package/packages/pi-coding-agent/src/modes/interactive/controllers/chat-controller.ts +22 -7
- package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +3 -0
- package/packages/pi-coding-agent/src/resources/extensions/memory/storage-safety-guard.test.ts +14 -0
- package/packages/pi-coding-agent/src/resources/extensions/memory/storage.ts +3 -2
- package/packages/pi-coding-agent/tsconfig.tsbuildinfo +1 -1
- package/packages/pi-tui/dist/tui.d.ts.map +1 -1
- package/packages/pi-tui/dist/tui.js +18 -8
- package/packages/pi-tui/dist/tui.js.map +1 -1
- package/packages/pi-tui/src/tui.ts +20 -8
- package/packages/pi-tui/tsconfig.tsbuildinfo +1 -1
- package/src/resources/extensions/gsd/auto/loop-deps.ts +2 -2
- package/src/resources/extensions/gsd/auto/loop.ts +50 -8
- package/src/resources/extensions/gsd/auto/phases.ts +251 -172
- package/src/resources/extensions/gsd/auto/resolve.ts +23 -1
- package/src/resources/extensions/gsd/auto/run-unit.ts +25 -30
- package/src/resources/extensions/gsd/auto/session.ts +8 -0
- package/src/resources/extensions/gsd/auto-direct-dispatch.ts +8 -34
- package/src/resources/extensions/gsd/auto-dispatch.ts +16 -0
- package/src/resources/extensions/gsd/auto-post-unit.ts +18 -4
- package/src/resources/extensions/gsd/auto-prompts.ts +112 -15
- package/src/resources/extensions/gsd/auto-recovery.ts +54 -0
- package/src/resources/extensions/gsd/auto-start.ts +230 -9
- package/src/resources/extensions/gsd/auto-supervisor.ts +7 -0
- package/src/resources/extensions/gsd/auto-timeout-recovery.ts +2 -2
- package/src/resources/extensions/gsd/auto-worktree.ts +123 -0
- package/src/resources/extensions/gsd/auto.ts +98 -21
- package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +49 -1
- package/src/resources/extensions/gsd/bootstrap/db-tools.ts +50 -36
- package/src/resources/extensions/gsd/bootstrap/dynamic-tools.ts +16 -5
- package/src/resources/extensions/gsd/bootstrap/exec-tools.ts +34 -19
- package/src/resources/extensions/gsd/bootstrap/journal-tools.ts +8 -1
- package/src/resources/extensions/gsd/bootstrap/memory-tools.ts +10 -3
- package/src/resources/extensions/gsd/bootstrap/query-tools.ts +9 -2
- package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +305 -28
- package/src/resources/extensions/gsd/bootstrap/system-context.ts +90 -22
- package/src/resources/extensions/gsd/clean-root-preflight.ts +32 -7
- package/src/resources/extensions/gsd/commands-handlers.ts +34 -15
- package/src/resources/extensions/gsd/context-budget.ts +44 -2
- package/src/resources/extensions/gsd/crash-recovery.ts +67 -10
- package/src/resources/extensions/gsd/db/unit-dispatches.ts +41 -0
- package/src/resources/extensions/gsd/db-base-schema.ts +4 -2
- package/src/resources/extensions/gsd/db-migration-steps.ts +8 -0
- package/src/resources/extensions/gsd/ecosystem/gsd-extension-api.ts +3 -0
- package/src/resources/extensions/gsd/git-service.ts +46 -8
- package/src/resources/extensions/gsd/gsd-db.ts +50 -13
- package/src/resources/extensions/gsd/guided-flow.ts +123 -45
- package/src/resources/extensions/gsd/memory-store.ts +77 -12
- package/src/resources/extensions/gsd/migrate/command.ts +47 -1
- package/src/resources/extensions/gsd/migration-auto-check.ts +129 -0
- package/src/resources/extensions/gsd/native-git-bridge.ts +39 -6
- package/src/resources/extensions/gsd/orphan-stash-audit.ts +117 -0
- package/src/resources/extensions/gsd/parallel-orchestrator.ts +13 -3
- package/src/resources/extensions/gsd/planning-path-scope.ts +35 -0
- package/src/resources/extensions/gsd/pre-execution-checks.ts +23 -0
- package/src/resources/extensions/gsd/preferences-types.ts +1 -1
- package/src/resources/extensions/gsd/prompt-loader.ts +27 -2
- package/src/resources/extensions/gsd/prompts/complete-milestone.md +16 -13
- package/src/resources/extensions/gsd/prompts/complete-slice.md +1 -1
- package/src/resources/extensions/gsd/prompts/execute-task.md +4 -2
- package/src/resources/extensions/gsd/prompts/parallel-research-slices.md +1 -1
- package/src/resources/extensions/gsd/prompts/plan-slice.md +1 -1
- package/src/resources/extensions/gsd/prompts/quick-task.md +1 -5
- package/src/resources/extensions/gsd/prompts/replan-slice.md +2 -2
- package/src/resources/extensions/gsd/prompts/validate-milestone.md +2 -2
- package/src/resources/extensions/gsd/quick.ts +37 -2
- package/src/resources/extensions/gsd/tests/artifact-retry-cap.test.ts +2 -2
- package/src/resources/extensions/gsd/tests/auto-loop.test.ts +417 -10
- package/src/resources/extensions/gsd/tests/auto-phases-lifecycle.test.ts +56 -13
- package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +14 -1
- package/src/resources/extensions/gsd/tests/auto-wrapup-inflight-guard.test.ts +168 -6
- package/src/resources/extensions/gsd/tests/clean-root-preflight.test.ts +15 -6
- package/src/resources/extensions/gsd/tests/compaction-snapshot.test.ts +14 -1
- package/src/resources/extensions/gsd/tests/complete-milestone-excerpt.test.ts +31 -0
- package/src/resources/extensions/gsd/tests/complete-slice-composer.test.ts +3 -2
- package/src/resources/extensions/gsd/tests/context-budget.test.ts +10 -1
- package/src/resources/extensions/gsd/tests/context-store.test.ts +7 -1
- package/src/resources/extensions/gsd/tests/crash-handler-secondary.test.ts +55 -0
- package/src/resources/extensions/gsd/tests/crash-recovery-via-db.test.ts +22 -0
- package/src/resources/extensions/gsd/tests/custom-engine-loop-integration.test.ts +5 -1
- package/src/resources/extensions/gsd/tests/dispatch-rule-coverage.test.ts +313 -0
- package/src/resources/extensions/gsd/tests/exec-history.test.ts +15 -0
- package/src/resources/extensions/gsd/tests/exec-sandbox.test.ts +65 -0
- package/src/resources/extensions/gsd/tests/execute-task-rendering.test.ts +5 -2
- package/src/resources/extensions/gsd/tests/fast-forward-reused-milestone-branch.test.ts +219 -0
- package/src/resources/extensions/gsd/tests/finalize-survivor-branch.test.ts +132 -0
- package/src/resources/extensions/gsd/tests/integration/git-service.test.ts +54 -0
- package/src/resources/extensions/gsd/tests/isolation-none-branch-guard.test.ts +6 -3
- package/src/resources/extensions/gsd/tests/journal-integration.test.ts +239 -1
- package/src/resources/extensions/gsd/tests/journal-query-tool.test.ts +32 -0
- package/src/resources/extensions/gsd/tests/knowledge.test.ts +47 -0
- package/src/resources/extensions/gsd/tests/memory-decay-factor.test.ts +90 -0
- package/src/resources/extensions/gsd/tests/merge-conflict-stops-loop.test.ts +1 -0
- package/src/resources/extensions/gsd/tests/migrate-writer-integration.test.ts +48 -0
- package/src/resources/extensions/gsd/tests/migration-auto-check.test.ts +127 -0
- package/src/resources/extensions/gsd/tests/milestone-merge-stash-restore.test.ts +242 -0
- package/src/resources/extensions/gsd/tests/native-git-bridge-exec-fallback.test.ts +34 -2
- package/src/resources/extensions/gsd/tests/originalbase-path-comparison.test.ts +3 -0
- package/src/resources/extensions/gsd/tests/orphan-merge-bootstrap.test.ts +133 -0
- package/src/resources/extensions/gsd/tests/orphan-stash-audit.test.ts +201 -0
- package/src/resources/extensions/gsd/tests/parallel-orchestrator-fast-forward.test.ts +113 -0
- package/src/resources/extensions/gsd/tests/plan-slice.test.ts +50 -0
- package/src/resources/extensions/gsd/tests/plan-task.test.ts +21 -0
- package/src/resources/extensions/gsd/tests/pre-execution-checks.test.ts +45 -5
- package/src/resources/extensions/gsd/tests/prompt-duplication-cuts.test.ts +230 -0
- package/src/resources/extensions/gsd/tests/prompt-path-audit.test.ts +40 -0
- package/src/resources/extensions/gsd/tests/prompt-step-ordering.test.ts +19 -0
- package/src/resources/extensions/gsd/tests/query-tools-db-open.test.ts +3 -3
- package/src/resources/extensions/gsd/tests/quick-external-gsd.test.ts +40 -0
- package/src/resources/extensions/gsd/tests/restore-tools-after-discuss.test.ts +38 -17
- package/src/resources/extensions/gsd/tests/schema-v27-v28-sequence.test.ts +156 -0
- package/src/resources/extensions/gsd/tests/select-resumable-milestone.test.ts +96 -0
- package/src/resources/extensions/gsd/tests/session-switch-abort-misclassification.test.ts +106 -0
- package/src/resources/extensions/gsd/tests/signal-handlers.test.ts +27 -0
- package/src/resources/extensions/gsd/tests/smart-entry-complete.test.ts +20 -0
- package/src/resources/extensions/gsd/tests/stalled-tool-recovery.test.ts +49 -1
- package/src/resources/extensions/gsd/tests/start-auto-detached.test.ts +55 -0
- package/src/resources/extensions/gsd/tests/state-corruption-2945.test.ts +1 -0
- package/src/resources/extensions/gsd/tests/status-db-open.test.ts +9 -0
- package/src/resources/extensions/gsd/tests/system-context-memory.test.ts +112 -0
- package/src/resources/extensions/gsd/tests/system-context-message-routing.test.ts +7 -9
- package/src/resources/extensions/gsd/tests/token-tool-gating.test.ts +291 -0
- package/src/resources/extensions/gsd/tests/unit-context-composer.test.ts +136 -4
- package/src/resources/extensions/gsd/tests/unit-dispatches.test.ts +30 -0
- package/src/resources/extensions/gsd/tests/unit-runtime.test.ts +37 -0
- package/src/resources/extensions/gsd/tests/unstructured-continue-context-injection.test.ts +5 -4
- package/src/resources/extensions/gsd/tests/workflow-protocol-excerpt.test.ts +99 -0
- package/src/resources/extensions/gsd/tests/workflow-tool-executors.test.ts +3 -0
- package/src/resources/extensions/gsd/tests/worktree-journal-events.test.ts +1 -0
- package/src/resources/extensions/gsd/tests/worktree-path-injection.test.ts +22 -19
- package/src/resources/extensions/gsd/tests/worktree-project-root-degrade.test.ts +66 -0
- package/src/resources/extensions/gsd/tests/worktree-resolver.test.ts +167 -4
- package/src/resources/extensions/gsd/tools/context-mode-tool-result.ts +25 -0
- package/src/resources/extensions/gsd/tools/exec-search-tool.ts +7 -7
- package/src/resources/extensions/gsd/tools/exec-tool.ts +4 -23
- package/src/resources/extensions/gsd/tools/memory-tools.ts +1 -0
- package/src/resources/extensions/gsd/tools/plan-slice.ts +13 -0
- package/src/resources/extensions/gsd/tools/plan-task.ts +10 -0
- package/src/resources/extensions/gsd/tools/resume-tool.ts +7 -7
- package/src/resources/extensions/gsd/tools/workflow-tool-executors.ts +1 -1
- package/src/resources/extensions/gsd/unit-context-composer.ts +19 -4
- package/src/resources/extensions/gsd/unit-runtime.ts +25 -0
- package/src/resources/extensions/gsd/workflow-protocol.ts +160 -0
- package/src/resources/extensions/gsd/worktree-resolver.ts +85 -19
- package/src/resources/extensions/gsd/tests/phases-merge-error-stops-auto.test.ts +0 -97
- /package/dist/web/standalone/.next/static/{vaQ47E8aNlbbNEDoeME6G → O2WvnXROue6l7nAp_4dhC}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{vaQ47E8aNlbbNEDoeME6G → O2WvnXROue6l7nAp_4dhC}/_ssgManifest.js +0 -0
|
@@ -3,8 +3,14 @@
|
|
|
3
3
|
|
|
4
4
|
import { describe, test } from "node:test";
|
|
5
5
|
import assert from "node:assert/strict";
|
|
6
|
-
import { readFileSync } from "node:fs";
|
|
6
|
+
import { mkdtempSync, mkdirSync, readFileSync, realpathSync, rmSync } from "node:fs";
|
|
7
7
|
import { join } from "node:path";
|
|
8
|
+
import { tmpdir } from "node:os";
|
|
9
|
+
|
|
10
|
+
import { autoSession } from "../auto-runtime-state.ts";
|
|
11
|
+
import { dispatchHookUnit } from "../auto.ts";
|
|
12
|
+
import { registerHooks } from "../bootstrap/register-hooks.ts";
|
|
13
|
+
import { clearDiscussionFlowState, getPendingGate } from "../bootstrap/write-gate.ts";
|
|
8
14
|
|
|
9
15
|
const autoTimersPath = join(import.meta.dirname, "..", "auto-timers.ts");
|
|
10
16
|
const autoTimersSrc = readFileSync(autoTimersPath, "utf-8");
|
|
@@ -18,6 +24,37 @@ const runUnitSrc = readFileSync(runUnitPath, "utf-8");
|
|
|
18
24
|
const registerHooksPath = join(import.meta.dirname, "..", "bootstrap", "register-hooks.ts");
|
|
19
25
|
const registerHooksSrc = readFileSync(registerHooksPath, "utf-8");
|
|
20
26
|
|
|
27
|
+
function makeHookHarness() {
|
|
28
|
+
const handlers = new Map<string, Array<(event: any, ctx: any) => Promise<any>>>();
|
|
29
|
+
const pi = {
|
|
30
|
+
on(name: string, handler: (event: any, ctx: any) => Promise<any>) {
|
|
31
|
+
const current = handlers.get(name) ?? [];
|
|
32
|
+
current.push(handler);
|
|
33
|
+
handlers.set(name, current);
|
|
34
|
+
},
|
|
35
|
+
};
|
|
36
|
+
const ctx = {
|
|
37
|
+
ui: {
|
|
38
|
+
notify: () => {},
|
|
39
|
+
setStatus: () => {},
|
|
40
|
+
setWidget: () => {},
|
|
41
|
+
},
|
|
42
|
+
modelRegistry: {
|
|
43
|
+
setDisabledModelProviders: () => {},
|
|
44
|
+
},
|
|
45
|
+
setCompactionThresholdOverride: () => {},
|
|
46
|
+
};
|
|
47
|
+
async function emit(name: string, event: any): Promise<any> {
|
|
48
|
+
for (const handler of handlers.get(name) ?? []) {
|
|
49
|
+
const result = await handler(event, ctx);
|
|
50
|
+
if (result?.block) return result;
|
|
51
|
+
}
|
|
52
|
+
return undefined;
|
|
53
|
+
}
|
|
54
|
+
registerHooks(pi as any, []);
|
|
55
|
+
return { emit };
|
|
56
|
+
}
|
|
57
|
+
|
|
21
58
|
describe("#3512: gsd-auto-wrapup must not interrupt in-flight tool calls", () => {
|
|
22
59
|
test("soft timeout wrapup gates triggerTurn on getInFlightToolCount() === 0", () => {
|
|
23
60
|
// The soft timeout sendMessage must NOT use a hardcoded `triggerTurn: true`.
|
|
@@ -73,10 +110,65 @@ describe("#3512: gsd-auto-wrapup must not interrupt in-flight tool calls", () =>
|
|
|
73
110
|
});
|
|
74
111
|
});
|
|
75
112
|
|
|
113
|
+
describe("hook dispatch session workspace root", () => {
|
|
114
|
+
test("dispatchHookUnit passes basePath explicitly to newSession", async (t) => {
|
|
115
|
+
const originalCwd = process.cwd();
|
|
116
|
+
const basePath = mkdtempSync(join(tmpdir(), "gsd-hook-cwd-"));
|
|
117
|
+
mkdirSync(join(basePath, ".gsd"), { recursive: true });
|
|
118
|
+
autoSession.reset();
|
|
119
|
+
t.after(() => {
|
|
120
|
+
try {
|
|
121
|
+
process.chdir(originalCwd);
|
|
122
|
+
} catch {
|
|
123
|
+
// best effort cleanup after cwd-sensitive dispatch tests
|
|
124
|
+
}
|
|
125
|
+
autoSession.reset();
|
|
126
|
+
rmSync(basePath, { recursive: true, force: true });
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
let newSessionOptions: unknown;
|
|
130
|
+
const ctx = {
|
|
131
|
+
ui: {
|
|
132
|
+
notify: () => {},
|
|
133
|
+
setStatus: () => {},
|
|
134
|
+
setWidget: () => {},
|
|
135
|
+
},
|
|
136
|
+
modelRegistry: {
|
|
137
|
+
getAvailable: () => [],
|
|
138
|
+
},
|
|
139
|
+
sessionManager: {
|
|
140
|
+
getSessionFile: () => join(basePath, "session.jsonl"),
|
|
141
|
+
},
|
|
142
|
+
newSession: async (options?: unknown) => {
|
|
143
|
+
newSessionOptions = options;
|
|
144
|
+
return { cancelled: false };
|
|
145
|
+
},
|
|
146
|
+
};
|
|
147
|
+
const pi = {
|
|
148
|
+
sendMessage: () => {},
|
|
149
|
+
setModel: async () => true,
|
|
150
|
+
};
|
|
151
|
+
|
|
152
|
+
const dispatched = await dispatchHookUnit(
|
|
153
|
+
ctx as any,
|
|
154
|
+
pi as any,
|
|
155
|
+
"review",
|
|
156
|
+
"execute-task",
|
|
157
|
+
"M001/S01/T01",
|
|
158
|
+
"review the completed unit",
|
|
159
|
+
undefined,
|
|
160
|
+
basePath,
|
|
161
|
+
);
|
|
162
|
+
|
|
163
|
+
assert.equal(dispatched, true);
|
|
164
|
+
assert.deepEqual(newSessionOptions, { workspaceRoot: basePath });
|
|
165
|
+
});
|
|
166
|
+
});
|
|
167
|
+
|
|
76
168
|
describe("#4276: pending/skipped tools stay visible to auto-mode hooks", () => {
|
|
77
169
|
test("tool_call handler marks GSD tools in-flight before execution_start", () => {
|
|
78
170
|
const startMarker = 'pi.on("tool_call", async (event, ctx) => {';
|
|
79
|
-
const endMarker = 'pi.on("tool_result", async (event) => {';
|
|
171
|
+
const endMarker = 'pi.on("tool_result", async (event, ctx) => {';
|
|
80
172
|
const toolCallSection = registerHooksSrc.slice(
|
|
81
173
|
registerHooksSrc.indexOf(startMarker),
|
|
82
174
|
registerHooksSrc.indexOf(endMarker),
|
|
@@ -90,7 +182,7 @@ describe("#4276: pending/skipped tools stay visible to auto-mode hooks", () => {
|
|
|
90
182
|
});
|
|
91
183
|
|
|
92
184
|
test("tool_result handler clears pending tools and records queued-skip errors", () => {
|
|
93
|
-
const startMarker = 'pi.on("tool_result", async (event) => {';
|
|
185
|
+
const startMarker = 'pi.on("tool_result", async (event, ctx) => {';
|
|
94
186
|
const endMarker = 'pi.on("tool_execution_start", async (event) => {';
|
|
95
187
|
const toolResultSection = registerHooksSrc.slice(
|
|
96
188
|
registerHooksSrc.indexOf(startMarker),
|
|
@@ -193,7 +285,7 @@ describe("#4365: tool_execution_start hook must pass toolName to markToolStart",
|
|
|
193
285
|
});
|
|
194
286
|
|
|
195
287
|
describe("deep setup approval questions pause immediately", () => {
|
|
196
|
-
test("register-hooks
|
|
288
|
+
test("register-hooks defers the pending gate during message_update without aborting the stream", () => {
|
|
197
289
|
const startMarker = 'pi.on("message_update"';
|
|
198
290
|
const endMarker = 'pi.on("session_shutdown"';
|
|
199
291
|
const messageUpdateSection = registerHooksSrc.slice(
|
|
@@ -210,8 +302,8 @@ describe("deep setup approval questions pause immediately", () => {
|
|
|
210
302
|
"message_update must detect approval/question boundaries",
|
|
211
303
|
);
|
|
212
304
|
assert.ok(
|
|
213
|
-
messageUpdateSection.includes("approvalGateIdForUnit") && messageUpdateSection.includes("
|
|
214
|
-
"plain-text approval questions must
|
|
305
|
+
messageUpdateSection.includes("approvalGateIdForUnit") && messageUpdateSection.includes("deferApprovalGate"),
|
|
306
|
+
"plain-text approval questions must defer the durable write gate until same-turn draft persistence can finish",
|
|
215
307
|
);
|
|
216
308
|
assert.ok(
|
|
217
309
|
messageUpdateSection.includes("getDiscussionMilestoneIdFor") && messageUpdateSection.includes('"discuss-milestone"'),
|
|
@@ -222,4 +314,74 @@ describe("deep setup approval questions pause immediately", () => {
|
|
|
222
314
|
"message_update must NOT abort the stream — aborting eats the model's question text on external CLI providers; the pending gate set above blocks subsequent tool calls instead",
|
|
223
315
|
);
|
|
224
316
|
});
|
|
317
|
+
|
|
318
|
+
test("plain-text approval boundary defers durable gate until same-turn CONTEXT-DRAFT can save", async () => {
|
|
319
|
+
const base = realpathSync(mkdtempSync(join(tmpdir(), "gsd-deferred-approval-")));
|
|
320
|
+
const previousCwd = process.cwd();
|
|
321
|
+
try {
|
|
322
|
+
mkdirSync(join(base, ".gsd", "milestones", "M003"), { recursive: true });
|
|
323
|
+
process.chdir(base);
|
|
324
|
+
clearDiscussionFlowState(base);
|
|
325
|
+
autoSession.reset();
|
|
326
|
+
autoSession.basePath = base;
|
|
327
|
+
autoSession.currentUnit = {
|
|
328
|
+
type: "discuss-milestone",
|
|
329
|
+
id: "M003",
|
|
330
|
+
startedAt: Date.now(),
|
|
331
|
+
};
|
|
332
|
+
|
|
333
|
+
const { emit } = makeHookHarness();
|
|
334
|
+
await emit("message_update", {
|
|
335
|
+
message: {
|
|
336
|
+
role: "assistant",
|
|
337
|
+
content: [{ type: "text", text: "Did I capture that correctly? If not, tell me what I missed." }],
|
|
338
|
+
},
|
|
339
|
+
});
|
|
340
|
+
|
|
341
|
+
assert.equal(
|
|
342
|
+
getPendingGate(base),
|
|
343
|
+
null,
|
|
344
|
+
"approval text should not install the durable pending gate until the assistant turn ends",
|
|
345
|
+
);
|
|
346
|
+
|
|
347
|
+
const draftResult = await emit("tool_call", {
|
|
348
|
+
toolCallId: "draft-save",
|
|
349
|
+
toolName: "gsd_summary_save",
|
|
350
|
+
input: {
|
|
351
|
+
milestone_id: "M003",
|
|
352
|
+
artifact_type: "CONTEXT-DRAFT",
|
|
353
|
+
content: "# M003 Draft\n",
|
|
354
|
+
},
|
|
355
|
+
});
|
|
356
|
+
assert.equal(
|
|
357
|
+
draftResult?.block,
|
|
358
|
+
undefined,
|
|
359
|
+
"same-turn CONTEXT-DRAFT persistence should remain allowed after the approval text streams",
|
|
360
|
+
);
|
|
361
|
+
|
|
362
|
+
const finalContextResult = await emit("tool_call", {
|
|
363
|
+
toolCallId: "final-context",
|
|
364
|
+
toolName: "gsd_summary_save",
|
|
365
|
+
input: {
|
|
366
|
+
milestone_id: "M003",
|
|
367
|
+
artifact_type: "CONTEXT",
|
|
368
|
+
content: "# M003 Context\n",
|
|
369
|
+
},
|
|
370
|
+
});
|
|
371
|
+
assert.equal(finalContextResult?.block, true, "final CONTEXT must still wait for approval");
|
|
372
|
+
assert.match(finalContextResult.reason, /Approval question "depth_verification_M003_confirm"/);
|
|
373
|
+
|
|
374
|
+
await emit("agent_end", { messages: [] });
|
|
375
|
+
assert.equal(
|
|
376
|
+
getPendingGate(base),
|
|
377
|
+
"depth_verification_M003_confirm",
|
|
378
|
+
"agent_end should activate the durable pending gate for the next turn",
|
|
379
|
+
);
|
|
380
|
+
} finally {
|
|
381
|
+
process.chdir(previousCwd);
|
|
382
|
+
autoSession.reset();
|
|
383
|
+
clearDiscussionFlowState(base);
|
|
384
|
+
rmSync(base, { recursive: true, force: true });
|
|
385
|
+
}
|
|
386
|
+
});
|
|
225
387
|
});
|
|
@@ -131,9 +131,11 @@ test("postflightPopStash — restores stashed changes and emits info notificatio
|
|
|
131
131
|
run('git commit -m "simulate merge"', repo);
|
|
132
132
|
|
|
133
133
|
const postNotifications: Array<{ msg: string; level: string }> = [];
|
|
134
|
-
postflightPopStash(repo, "M004", preflight.stashMarker, (msg, level) => {
|
|
134
|
+
const postflight = postflightPopStash(repo, "M004", preflight.stashMarker, (msg, level) => {
|
|
135
135
|
postNotifications.push({ msg, level });
|
|
136
136
|
});
|
|
137
|
+
assert.equal(postflight.restored, true, "postflight must report successful restore");
|
|
138
|
+
assert.equal(postflight.needsManualRecovery, false, "successful restore must not need manual recovery");
|
|
137
139
|
|
|
138
140
|
// The stashed README.md change must be restored
|
|
139
141
|
const content = readFileSync(join(repo, "README.md"), "utf-8");
|
|
@@ -171,7 +173,8 @@ test("preflight + merge + postflight round-trip preserves uncommitted changes",
|
|
|
171
173
|
run('git commit -m "feat: add feature"', repo);
|
|
172
174
|
|
|
173
175
|
// Postflight: pop stash
|
|
174
|
-
postflightPopStash(repo, "M005", preflight.stashMarker, () => {});
|
|
176
|
+
const postflight = postflightPopStash(repo, "M005", preflight.stashMarker, () => {});
|
|
177
|
+
assert.equal(postflight.needsManualRecovery, false, "clean restore must not stop auto-mode");
|
|
175
178
|
|
|
176
179
|
// README.md must still have our local content
|
|
177
180
|
const restored = readFileSync(join(repo, "README.md"), "utf-8");
|
|
@@ -197,9 +200,12 @@ test("postflightPopStash conflict warning names the exact stash ref", () => {
|
|
|
197
200
|
run('git commit -m "simulate conflicting merge"', repo);
|
|
198
201
|
|
|
199
202
|
const notifications: Array<{ msg: string; level: string }> = [];
|
|
200
|
-
postflightPopStash(repo, "M005C", preflight.stashMarker, (msg, level) => {
|
|
203
|
+
const postflight = postflightPopStash(repo, "M005C", preflight.stashMarker, (msg, level) => {
|
|
201
204
|
notifications.push({ msg, level });
|
|
202
205
|
});
|
|
206
|
+
assert.equal(postflight.restored, false, "conflicted restore must report restored=false");
|
|
207
|
+
assert.equal(postflight.needsManualRecovery, true, "conflicted restore must require manual recovery");
|
|
208
|
+
assert.match(postflight.message, /failed after merge of milestone M005C/);
|
|
203
209
|
|
|
204
210
|
const warning = notifications.find((n) => n.level === "warning")?.msg ?? "";
|
|
205
211
|
assert.match(warning, /git stash pop stash@\{\d+\}/);
|
|
@@ -219,7 +225,8 @@ test("postflightPopStash restores the matching GSD stash, not stash@{0}", () =>
|
|
|
219
225
|
writeFileSync(join(repo, "other.txt"), "other stash\n");
|
|
220
226
|
run('git stash push --include-untracked -m "unrelated newer stash"', repo);
|
|
221
227
|
|
|
222
|
-
postflightPopStash(repo, "M006", preflight.stashMarker, () => {});
|
|
228
|
+
const postflight = postflightPopStash(repo, "M006", preflight.stashMarker, () => {});
|
|
229
|
+
assert.equal(postflight.needsManualRecovery, false, "targeted restore must not need manual recovery");
|
|
223
230
|
|
|
224
231
|
const content = readFileSync(join(repo, "README.md"), "utf-8");
|
|
225
232
|
assert.equal(content.replace(/\r\n/g, "\n"), "# target stash\n");
|
|
@@ -242,7 +249,8 @@ test("postflightPopStash restores the exact preflight marker when another same-m
|
|
|
242
249
|
writeFileSync(join(repo, "same-milestone.txt"), "newer same milestone stash\n");
|
|
243
250
|
run('git stash push --include-untracked -m "gsd-preflight-stash [gsd-preflight-stash:M007:other]"', repo);
|
|
244
251
|
|
|
245
|
-
postflightPopStash(repo, "M007", preflight.stashMarker, () => {});
|
|
252
|
+
const postflight = postflightPopStash(repo, "M007", preflight.stashMarker, () => {});
|
|
253
|
+
assert.equal(postflight.needsManualRecovery, false, "exact marker restore must not need manual recovery");
|
|
246
254
|
|
|
247
255
|
const content = readFileSync(join(repo, "README.md"), "utf-8");
|
|
248
256
|
assert.equal(content.replace(/\r\n/g, "\n"), "# target stash\n");
|
|
@@ -260,7 +268,8 @@ test("postflightPopStash falls back to milestone marker prefix when exact marker
|
|
|
260
268
|
writeFileSync(join(repo, "README.md"), "# fallback stash\n");
|
|
261
269
|
run('git stash push --include-untracked -m "gsd-preflight-stash [gsd-preflight-stash:M008:fallback]"', repo);
|
|
262
270
|
|
|
263
|
-
postflightPopStash(repo, "M008", undefined, () => {});
|
|
271
|
+
const postflight = postflightPopStash(repo, "M008", undefined, () => {});
|
|
272
|
+
assert.equal(postflight.needsManualRecovery, false, "fallback marker restore must not need manual recovery");
|
|
264
273
|
|
|
265
274
|
const content = readFileSync(join(repo, "README.md"), "utf-8");
|
|
266
275
|
assert.equal(content.replace(/\r\n/g, "\n"), "# fallback stash\n");
|
|
@@ -29,7 +29,8 @@ test('buildSnapshot: renders memories, exec history, and active context', () =>
|
|
|
29
29
|
memories: [
|
|
30
30
|
{ id: 'MEM001', category: 'gotcha', content: 'FTS5 needs Porter tokenizer', confidence: 0.9,
|
|
31
31
|
source_unit_type: null, source_unit_id: null, created_at: '', updated_at: '',
|
|
32
|
-
superseded_by: null, hit_count: 0, scope: 'project', seq: 1, tags: [], structured_fields: null
|
|
32
|
+
superseded_by: null, hit_count: 0, scope: 'project', seq: 1, tags: [], structured_fields: null,
|
|
33
|
+
last_hit_at: null },
|
|
33
34
|
],
|
|
34
35
|
execHistory: [
|
|
35
36
|
{
|
|
@@ -65,6 +66,7 @@ test('buildSnapshot: enforces the byte cap with a truncation marker', () => {
|
|
|
65
66
|
seq: i,
|
|
66
67
|
tags: [] as string[],
|
|
67
68
|
structured_fields: null,
|
|
69
|
+
last_hit_at: null,
|
|
68
70
|
}));
|
|
69
71
|
const snap = buildSnapshot(
|
|
70
72
|
{ generatedAt: new Date(), memories: longMemories, execHistory: [] },
|
|
@@ -121,3 +123,14 @@ test('executeResume: reports friendly empty state when no snapshot exists', () =
|
|
|
121
123
|
cleanup(base);
|
|
122
124
|
}
|
|
123
125
|
});
|
|
126
|
+
|
|
127
|
+
test('executeResume: returns disabled error when context_mode.enabled=false', () => {
|
|
128
|
+
const base = freshBase();
|
|
129
|
+
try {
|
|
130
|
+
const result = executeResume({}, { baseDir: base, preferences: { context_mode: { enabled: false } } });
|
|
131
|
+
assert.equal(result.isError, true);
|
|
132
|
+
assert.equal((result.details as { error?: string }).error, 'context_mode_disabled');
|
|
133
|
+
} finally {
|
|
134
|
+
cleanup(base);
|
|
135
|
+
}
|
|
136
|
+
});
|
|
@@ -261,3 +261,34 @@ test("#4780 closer prompt: uses excerpts + lists on-demand slice SUMMARY paths",
|
|
|
261
261
|
`closer prompt length ${prompt.length} should be < raw summary size ${rawSize} + 20KB headroom`,
|
|
262
262
|
);
|
|
263
263
|
});
|
|
264
|
+
|
|
265
|
+
test("complete-milestone prompt caps repeated inlined context around 20k chars", async (t) => {
|
|
266
|
+
const base = createBase();
|
|
267
|
+
t.after(() => cleanup(base));
|
|
268
|
+
invalidateAllCaches();
|
|
269
|
+
|
|
270
|
+
writeRoadmap(base, makeRoadmap());
|
|
271
|
+
writeSummary(base, "S01", makeFatSummary("S01"));
|
|
272
|
+
writeSummary(base, "S02", makeFatSummary("S02"));
|
|
273
|
+
writeFileSync(
|
|
274
|
+
join(base, ".gsd", "milestones", "M001", "M001-CONTEXT.md"),
|
|
275
|
+
"# M001 Context\n\n" + "Large milestone context body. ".repeat(1200),
|
|
276
|
+
);
|
|
277
|
+
writeFileSync(
|
|
278
|
+
join(base, ".gsd", "KNOWLEDGE.md"),
|
|
279
|
+
"# Project Knowledge\n\n## Patterns\n\n### Test Milestone shared\n" + "Large scoped knowledge body. ".repeat(1200),
|
|
280
|
+
);
|
|
281
|
+
|
|
282
|
+
const prompt = await buildCompleteMilestonePrompt("M001", "Test Milestone", base);
|
|
283
|
+
const contextStart = prompt.indexOf("## Inlined Context (preloaded");
|
|
284
|
+
const contextEnd = prompt.indexOf("## Steps", contextStart);
|
|
285
|
+
assert.ok(contextStart >= 0, "prompt should include inlined context");
|
|
286
|
+
assert.ok(contextEnd > contextStart, "prompt should include steps after inlined context");
|
|
287
|
+
|
|
288
|
+
const inlinedContext = prompt.slice(contextStart, contextEnd);
|
|
289
|
+
assert.ok(
|
|
290
|
+
inlinedContext.length <= 21_000,
|
|
291
|
+
`inlined context ${inlinedContext.length} chars should stay near the 20k cap`,
|
|
292
|
+
);
|
|
293
|
+
assert.match(inlinedContext, /\[\.\.\.truncated \d+ sections\]/);
|
|
294
|
+
});
|
|
@@ -113,8 +113,9 @@ test("#4782 phase 3: buildCompleteSlicePrompt composes roadmap → plan → task
|
|
|
113
113
|
"task summaries precede slice-summary template",
|
|
114
114
|
);
|
|
115
115
|
|
|
116
|
-
// Task
|
|
117
|
-
assert.match(prompt,
|
|
116
|
+
// Task summary excerpt is inlined; full narrative remains on-demand.
|
|
117
|
+
assert.match(prompt, /### Task Summary: T01 \(excerpt\)/);
|
|
118
|
+
assert.doesNotMatch(prompt, /Task one did the thing/);
|
|
118
119
|
});
|
|
119
120
|
|
|
120
121
|
test("#4782 phase 3: buildCompleteSlicePrompt handles missing task summaries gracefully", async (t) => {
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* No I/O, no extension context, no global state.
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import { describe, it } from "node:test";
|
|
7
|
+
import { describe, it, beforeEach } from "node:test";
|
|
8
8
|
import assert from "node:assert/strict";
|
|
9
9
|
|
|
10
10
|
import {
|
|
@@ -16,8 +16,17 @@ import {
|
|
|
16
16
|
computeBudgets,
|
|
17
17
|
truncateAtSectionBoundary,
|
|
18
18
|
resolveExecutorContextWindow,
|
|
19
|
+
_resetEmpiricalCacheForTest,
|
|
19
20
|
} from "../context-budget.js";
|
|
20
21
|
|
|
22
|
+
// Reset the per-provider empirical chars-per-token cache before each test.
|
|
23
|
+
// The hardcoded char-ratio assertions below assume the static fallback path
|
|
24
|
+
// (3.5 / 4.0 chars/token) is used. Without this guard, a prior test that
|
|
25
|
+
// warms tiktoken would populate the cache and silently break these tests.
|
|
26
|
+
beforeEach(() => {
|
|
27
|
+
_resetEmpiricalCacheForTest();
|
|
28
|
+
});
|
|
29
|
+
|
|
21
30
|
import type { TokenProvider } from "../token-counter.js";
|
|
22
31
|
|
|
23
32
|
// ─── Test helpers ─────────────────────────────────────────────────────────────
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
// GSD-2 + context-store.test.ts — Regression coverage for DB-backed context query helpers.
|
|
2
|
+
|
|
1
3
|
import { describe, test, afterEach } from "node:test";
|
|
2
4
|
import assert from "node:assert/strict";
|
|
3
5
|
import {
|
|
@@ -362,7 +364,11 @@ describe("context-store: sub-5ms query timing", () => {
|
|
|
362
364
|
|
|
363
365
|
assert.strictEqual(decisions.length, 50, `got ${decisions.length} decisions (expected 50)`);
|
|
364
366
|
assert.strictEqual(requirements.length, 50, `got ${requirements.length} requirements (expected 50)`);
|
|
365
|
-
|
|
367
|
+
const maxLatencyMs = process.env.NODE_V8_COVERAGE ? 15 : 5;
|
|
368
|
+
assert.ok(
|
|
369
|
+
elapsed < maxLatencyMs,
|
|
370
|
+
`query latency ${elapsed.toFixed(2)}ms should be < ${maxLatencyMs}ms`,
|
|
371
|
+
);
|
|
366
372
|
});
|
|
367
373
|
});
|
|
368
374
|
|
|
@@ -232,4 +232,59 @@ describe('emitCrashRecoveredUnitEnd (#3348)', () => {
|
|
|
232
232
|
rmSync(base, { recursive: true, force: true });
|
|
233
233
|
}
|
|
234
234
|
});
|
|
235
|
+
|
|
236
|
+
test('emitOpenUnitEndForUnit closes the latest open start with error context', async () => {
|
|
237
|
+
const base = makeTmpBase();
|
|
238
|
+
try {
|
|
239
|
+
const { emitJournalEvent, queryJournal } = await import('../journal.ts');
|
|
240
|
+
const { emitOpenUnitEndForUnit } = await import('../crash-recovery.ts');
|
|
241
|
+
|
|
242
|
+
const firstFlowId = randomUUID();
|
|
243
|
+
const secondFlowId = randomUUID();
|
|
244
|
+
emitJournalEvent(base, {
|
|
245
|
+
ts: new Date().toISOString(),
|
|
246
|
+
flowId: firstFlowId,
|
|
247
|
+
seq: 1,
|
|
248
|
+
eventType: 'unit-start',
|
|
249
|
+
data: { unitType: 'execute-task', unitId: 'M008/S04/T02' },
|
|
250
|
+
});
|
|
251
|
+
emitJournalEvent(base, {
|
|
252
|
+
ts: new Date().toISOString(),
|
|
253
|
+
flowId: firstFlowId,
|
|
254
|
+
seq: 2,
|
|
255
|
+
eventType: 'unit-end',
|
|
256
|
+
data: { unitType: 'execute-task', unitId: 'M008/S04/T02', status: 'completed' },
|
|
257
|
+
causedBy: { flowId: firstFlowId, seq: 1 },
|
|
258
|
+
});
|
|
259
|
+
emitJournalEvent(base, {
|
|
260
|
+
ts: new Date().toISOString(),
|
|
261
|
+
flowId: secondFlowId,
|
|
262
|
+
seq: 3,
|
|
263
|
+
eventType: 'unit-start',
|
|
264
|
+
data: { unitType: 'execute-task', unitId: 'M008/S04/T02' },
|
|
265
|
+
});
|
|
266
|
+
|
|
267
|
+
const emitted = emitOpenUnitEndForUnit(
|
|
268
|
+
base,
|
|
269
|
+
'execute-task',
|
|
270
|
+
'M008/S04/T02',
|
|
271
|
+
'cancelled',
|
|
272
|
+
{ message: 'runUnitPhase exploded', category: 'unit-exception', isTransient: false },
|
|
273
|
+
);
|
|
274
|
+
|
|
275
|
+
assert.equal(emitted, true, 'open unit should be closed');
|
|
276
|
+
const ends = queryJournal(base).filter((e) => e.eventType === 'unit-end');
|
|
277
|
+
assert.equal(ends.length, 2, 'should preserve existing end and add one new end');
|
|
278
|
+
const newEnd = ends.find((e) => e.causedBy?.flowId === secondFlowId);
|
|
279
|
+
assert.ok(newEnd, 'new end should close the latest open start');
|
|
280
|
+
assert.equal(newEnd!.data?.status, 'cancelled');
|
|
281
|
+
assert.deepEqual(newEnd!.data?.errorContext, {
|
|
282
|
+
message: 'runUnitPhase exploded',
|
|
283
|
+
category: 'unit-exception',
|
|
284
|
+
isTransient: false,
|
|
285
|
+
});
|
|
286
|
+
} finally {
|
|
287
|
+
rmSync(base, { recursive: true, force: true });
|
|
288
|
+
}
|
|
289
|
+
});
|
|
235
290
|
});
|
|
@@ -30,6 +30,7 @@ import {
|
|
|
30
30
|
isLockProcessAlive,
|
|
31
31
|
} from "../crash-recovery.ts";
|
|
32
32
|
import { normalizeRealPath } from "../paths.ts";
|
|
33
|
+
import { writeUnitRuntimeRecord } from "../unit-runtime.ts";
|
|
33
34
|
|
|
34
35
|
function makeBase(): string {
|
|
35
36
|
const base = mkdtempSync(join(tmpdir(), "gsd-crash-recovery-"));
|
|
@@ -102,6 +103,27 @@ test("readCrashLock synthesizes LockData from a stale dead worker (no dispatches
|
|
|
102
103
|
assert.ok(lock!.startedAt, "startedAt populated from workers.started_at");
|
|
103
104
|
});
|
|
104
105
|
|
|
106
|
+
test("readCrashLock falls back to latest in-flight runtime record when dispatch claim is missing", (t) => {
|
|
107
|
+
const base = makeBase();
|
|
108
|
+
t.after(() => cleanup(base));
|
|
109
|
+
openDatabase(join(base, ".gsd", "gsd.db"));
|
|
110
|
+
const projectRoot = normalizeRealPath(base);
|
|
111
|
+
const workerId = registerAutoWorker({ projectRootRealpath: projectRoot });
|
|
112
|
+
writeUnitRuntimeRecord(base, "execute-task", "M008/S04/T02", 1778069087937, {
|
|
113
|
+
phase: "dispatched",
|
|
114
|
+
lastProgressAt: 1778069087937,
|
|
115
|
+
lastProgressKind: "dispatch",
|
|
116
|
+
});
|
|
117
|
+
setWorkerPid(workerId, 99999);
|
|
118
|
+
expireWorker(workerId);
|
|
119
|
+
|
|
120
|
+
const lock = readCrashLock(base);
|
|
121
|
+
assert.ok(lock, "stale worker surfaced as a crash lock");
|
|
122
|
+
assert.equal(lock!.unitType, "execute-task");
|
|
123
|
+
assert.equal(lock!.unitId, "M008/S04/T02");
|
|
124
|
+
assert.equal(lock!.unitStartedAt, new Date(1778069087937).toISOString());
|
|
125
|
+
});
|
|
126
|
+
|
|
105
127
|
test("readCrashLock includes the most recent dispatch as unitType/unitId", (t) => {
|
|
106
128
|
const base = makeBase();
|
|
107
129
|
t.after(() => cleanup(base));
|
|
@@ -192,7 +192,11 @@ function makeMockDeps(overrides?: Partial<LoopDeps>): LoopDeps & { callLog: stri
|
|
|
192
192
|
resolveMilestoneFile: () => null,
|
|
193
193
|
reconcileMergeState: () => "clean",
|
|
194
194
|
preflightCleanRoot: () => ({ stashPushed: false, summary: "" }),
|
|
195
|
-
postflightPopStash: () => {
|
|
195
|
+
postflightPopStash: () => ({
|
|
196
|
+
restored: true,
|
|
197
|
+
needsManualRecovery: false,
|
|
198
|
+
message: "restored",
|
|
199
|
+
}),
|
|
196
200
|
getLedger: () => null,
|
|
197
201
|
getProjectTotals: () => ({ cost: 0 }),
|
|
198
202
|
formatCost: (c: number) => `$${c.toFixed(2)}`,
|