@opengsd/gsd-pi 1.3.0-dev.65546769 → 1.3.0-dev.738160b9
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 +1 -1
- 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/claude-code-cli/stream-adapter.js +11 -2
- package/dist/resources/extensions/google-cli/stream-adapter.js +82 -15
- package/dist/resources/extensions/gsd/artifact-verification.js +427 -0
- package/dist/resources/extensions/gsd/auto/orchestrator.js +12 -3
- 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 +34 -20
- package/dist/resources/extensions/gsd/auto-post-unit.js +1 -1
- package/dist/resources/extensions/gsd/auto-prompts.js +29 -14
- package/dist/resources/extensions/gsd/auto-recovery.js +9 -510
- 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/agent-end-recovery.js +103 -13
- package/dist/resources/extensions/gsd/bootstrap/core-session-tools.js +39 -0
- package/dist/resources/extensions/gsd/bootstrap/db-tools.js +11 -5
- package/dist/resources/extensions/gsd/bootstrap/exec-tools.js +2 -0
- package/dist/resources/extensions/gsd/bootstrap/register-extension.js +2 -0
- package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +41 -21
- package/dist/resources/extensions/gsd/bootstrap/system-context.js +46 -19
- package/dist/resources/extensions/gsd/bootstrap/tool-call-loop-guard.js +96 -10
- package/dist/resources/extensions/gsd/bootstrap/write-gate.js +1 -1
- 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-context.js +19 -1
- package/dist/resources/extensions/gsd/commands-prefs-wizard.js +17 -11
- package/dist/resources/extensions/gsd/commands-usage.js +1 -1
- package/dist/resources/extensions/gsd/commands-worktree.js +12 -10
- package/dist/resources/extensions/gsd/dashboard-overlay.js +32 -3
- package/dist/resources/extensions/gsd/db/engine.js +4 -1
- package/dist/resources/extensions/gsd/db/queries.js +60 -0
- 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-providers.js +92 -8
- package/dist/resources/extensions/gsd/doctor-runtime-checks.js +3 -0
- package/dist/resources/extensions/gsd/exec-sandbox.js +53 -11
- package/dist/resources/extensions/gsd/flat-phase-migration.js +45 -0
- package/dist/resources/extensions/gsd/forensics.js +2 -32
- package/dist/resources/extensions/gsd/git-service.js +61 -4
- package/dist/resources/extensions/gsd/gitignore.js +4 -1
- package/dist/resources/extensions/gsd/guided-flow-queue.js +66 -5
- package/dist/resources/extensions/gsd/health-widget.js +55 -29
- 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 +8 -9
- package/dist/resources/extensions/gsd/memory-backfill.js +28 -21
- package/dist/resources/extensions/gsd/memory-consolidation-scanner.js +44 -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/milestone-implementation-evidence.js +26 -20
- 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/quick.js +45 -2
- 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/session-forensics.js +11 -1
- 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 +45 -2
- 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 +2 -2
- package/dist/resources/extensions/gsd/tools/complete-task.js +43 -14
- package/dist/resources/extensions/gsd/tools/exec-tool.js +7 -2
- 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-context-composer.js +23 -7
- package/dist/resources/extensions/gsd/unit-registry.js +36 -6
- package/dist/resources/extensions/gsd/unmerged-milestone-guard.js +33 -3
- package/dist/resources/extensions/gsd/validation-block-guard.js +9 -4
- 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/workspace-git-preflight.js +30 -1
- 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 +3 -3
- 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/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_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 +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/api/visualizer/route.js +1 -1
- package/dist/web/standalone/.next/server/app/index.html +1 -1
- package/dist/web/standalone/.next/server/app/index.rsc +2 -2
- 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 +2 -2
- 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/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/8357.js +1 -1
- package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
- package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
- package/dist/web/standalone/.next/server/pages/404.html +1 -1
- package/dist/web/standalone/.next/server/pages/500.html +1 -1
- package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
- package/dist/web/standalone/.next/static/chunks/{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/{page-6644fc6ee8ca1247.js → page-72a856634ad14c10.js} +1 -1
- package/dist/web/standalone/.next/static/chunks/webpack-9c401904f87ded16.js +1 -0
- package/dist/web/standalone/node_modules/node-pty/build/Makefile +1 -1
- package/package.json +1 -1
- package/packages/cloud-mcp-gateway/package.json +2 -2
- package/packages/contracts/dist/workflow.d.ts +1 -0
- package/packages/contracts/dist/workflow.d.ts.map +1 -1
- package/packages/contracts/dist/workflow.js +2 -0
- package/packages/contracts/dist/workflow.js.map +1 -1
- 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 -829
- 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/README.md +1 -1
- package/packages/mcp-server/dist/server.d.ts +1 -1
- package/packages/mcp-server/dist/server.d.ts.map +1 -1
- package/packages/mcp-server/dist/server.js +3 -3
- package/packages/mcp-server/dist/server.js.map +1 -1
- package/packages/mcp-server/dist/workflow-tools.d.ts +13 -1
- package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
- package/packages/mcp-server/dist/workflow-tools.js +35 -21
- 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/stream-adapter.ts +20 -2
- package/src/resources/extensions/claude-code-cli/tests/index.test.ts +14 -0
- package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +80 -0
- package/src/resources/extensions/google-cli/stream-adapter.ts +106 -19
- 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/orchestrator.ts +25 -11
- 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 +35 -24
- package/src/resources/extensions/gsd/auto-post-unit.ts +1 -1
- package/src/resources/extensions/gsd/auto-prompts.ts +41 -15
- package/src/resources/extensions/gsd/auto-recovery.ts +13 -511
- 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/agent-end-recovery.ts +125 -12
- package/src/resources/extensions/gsd/bootstrap/core-session-tools.ts +44 -0
- package/src/resources/extensions/gsd/bootstrap/db-tools.ts +11 -5
- package/src/resources/extensions/gsd/bootstrap/exec-tools.ts +2 -0
- package/src/resources/extensions/gsd/bootstrap/register-extension.ts +2 -0
- package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +52 -21
- package/src/resources/extensions/gsd/bootstrap/system-context.ts +52 -18
- package/src/resources/extensions/gsd/bootstrap/tool-call-loop-guard.ts +104 -10
- package/src/resources/extensions/gsd/bootstrap/write-gate.ts +1 -1
- 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-context.ts +18 -1
- package/src/resources/extensions/gsd/commands-prefs-wizard.ts +15 -10
- package/src/resources/extensions/gsd/commands-usage.ts +1 -1
- package/src/resources/extensions/gsd/commands-worktree.ts +12 -10
- package/src/resources/extensions/gsd/dashboard-overlay.ts +32 -3
- package/src/resources/extensions/gsd/db/engine.ts +8 -1
- package/src/resources/extensions/gsd/db/queries.ts +79 -0
- 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-providers.ts +103 -9
- 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 +56 -11
- package/src/resources/extensions/gsd/flat-phase-migration.ts +44 -0
- package/src/resources/extensions/gsd/forensics.ts +2 -33
- package/src/resources/extensions/gsd/git-service.ts +69 -5
- package/src/resources/extensions/gsd/gitignore.ts +4 -1
- package/src/resources/extensions/gsd/guided-flow-queue.ts +89 -4
- package/src/resources/extensions/gsd/health-widget.ts +69 -32
- 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 +8 -11
- package/src/resources/extensions/gsd/memory-backfill.ts +26 -20
- package/src/resources/extensions/gsd/memory-consolidation-scanner.ts +51 -19
- 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/milestone-implementation-evidence.ts +35 -21
- 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/quick.ts +43 -2
- 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/session-forensics.ts +11 -1
- 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 +81 -7
- 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 +146 -1
- package/src/resources/extensions/gsd/tests/auto-retry-mcp-churn-fixes.test.ts +30 -0
- package/src/resources/extensions/gsd/tests/commands-context.test.ts +26 -0
- package/src/resources/extensions/gsd/tests/commands-gsd-core.test.ts +1 -0
- package/src/resources/extensions/gsd/tests/commands-worktree-clean.test.ts +80 -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/complete-slice.test.ts +11 -0
- package/src/resources/extensions/gsd/tests/complete-task-rollback-evidence.test.ts +48 -8
- package/src/resources/extensions/gsd/tests/complete-task.test.ts +75 -0
- package/src/resources/extensions/gsd/tests/dashboard-overlay.test.ts +55 -2
- 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/dispatch-rule-coverage.test.ts +26 -1
- package/src/resources/extensions/gsd/tests/doctor-forensics-db-open-regression.test.ts +70 -2
- package/src/resources/extensions/gsd/tests/doctor-providers.test.ts +107 -0
- package/src/resources/extensions/gsd/tests/doctor-scope-db-unavailable.test.ts +239 -2
- package/src/resources/extensions/gsd/tests/exec-graceful-kill.test.ts +38 -0
- package/src/resources/extensions/gsd/tests/exec-sandbox.test.ts +16 -0
- package/src/resources/extensions/gsd/tests/exec-tool.test.ts +45 -1
- 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/forensics-error-filter.test.ts +88 -0
- package/src/resources/extensions/gsd/tests/gitignore-bg-shell-runtime.test.ts +4 -0
- package/src/resources/extensions/gsd/tests/guided-discuss-milestone-prompt-rendering.test.ts +42 -0
- package/src/resources/extensions/gsd/tests/health-widget.test.ts +268 -3
- package/src/resources/extensions/gsd/tests/integration/git-service.test.ts +130 -3
- package/src/resources/extensions/gsd/tests/integration/queue-active-milestone-context-budget.test.ts +93 -0
- package/src/resources/extensions/gsd/tests/integration/quick-branch-lifecycle.test.ts +56 -9
- 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/knowledge-cold-start.test.ts +14 -0
- package/src/resources/extensions/gsd/tests/memory-consolidation-scanner.test.ts +78 -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/orchestrator-logs.test.ts +43 -1
- package/src/resources/extensions/gsd/tests/orphan-stash-audit.test.ts +91 -7
- package/src/resources/extensions/gsd/tests/parallel-research-dispatch.test.ts +26 -0
- package/src/resources/extensions/gsd/tests/parsers-legacy-importers.test.ts +4 -1
- package/src/resources/extensions/gsd/tests/pipeline-variant-dispatch.test.ts +1 -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/prefs-wizard-coverage.test.ts +54 -1
- 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/provider-errors.test.ts +195 -1
- package/src/resources/extensions/gsd/tests/read-uat-gate-verdict.test.ts +185 -0
- package/src/resources/extensions/gsd/tests/register-hooks-depth-verification.test.ts +87 -0
- 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 +191 -0
- package/src/resources/extensions/gsd/tests/tool-call-loop-guard.test.ts +208 -0
- package/src/resources/extensions/gsd/tests/tool-param-optionality.test.ts +32 -3
- package/src/resources/extensions/gsd/tests/undo.test.ts +74 -0
- package/src/resources/extensions/gsd/tests/unit-context-composer.test.ts +193 -14
- package/src/resources/extensions/gsd/tests/unmerged-milestone-guard.test.ts +25 -0
- package/src/resources/extensions/gsd/tests/uok-gitops-turn-action.test.ts +38 -0
- package/src/resources/extensions/gsd/tests/validation-block-guard.test.ts +79 -0
- package/src/resources/extensions/gsd/tests/verification-retry-policy.test.ts +69 -4
- package/src/resources/extensions/gsd/tests/verify-artifact-tightened.test.ts +66 -0
- 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/workspace-git-preflight.test.ts +151 -2
- 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 +2 -2
- package/src/resources/extensions/gsd/tools/complete-task.ts +53 -15
- package/src/resources/extensions/gsd/tools/exec-tool.ts +7 -3
- 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-context-composer.ts +33 -7
- package/src/resources/extensions/gsd/unit-registry.ts +36 -6
- package/src/resources/extensions/gsd/unmerged-milestone-guard.ts +41 -5
- package/src/resources/extensions/gsd/validation-block-guard.ts +13 -7
- 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/workspace-git-preflight.ts +31 -0
- 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.e0bdc932325d7e03.js +0 -10
- package/dist/web/standalone/.next/static/chunks/webpack-f46ea08200a0227e.js +0 -1
- /package/dist/web/standalone/.next/static/{BTKtGFF1Y-hvVJEGhBRo9 → 2A_WqqCS-EoYZxN9_v3d2}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{BTKtGFF1Y-hvVJEGhBRo9 → 2A_WqqCS-EoYZxN9_v3d2}/_ssgManifest.js +0 -0
|
@@ -970,6 +970,93 @@ test("register-hooks agent_end does not re-arm deferred gate after workflow MCP
|
|
|
970
970
|
});
|
|
971
971
|
});
|
|
972
972
|
|
|
973
|
+
test("register-hooks message_update uses in-memory write-gate snapshot instead of disk reconcile", async (t) => {
|
|
974
|
+
const dir = makeTempDir("message-update-memory-snapshot");
|
|
975
|
+
const originalCwd = process.cwd();
|
|
976
|
+
const originalEnv = process.env.GSD_PERSIST_WRITE_GATE_STATE;
|
|
977
|
+
process.chdir(dir);
|
|
978
|
+
process.env.GSD_PERSIST_WRITE_GATE_STATE = "1";
|
|
979
|
+
resetWriteGateState(dir);
|
|
980
|
+
clearPendingAutoStart(dir);
|
|
981
|
+
|
|
982
|
+
const gateId = "depth_verification_M012_confirm";
|
|
983
|
+
const statePath = join(dir, ".gsd", "runtime", "write-gate-state.json");
|
|
984
|
+
|
|
985
|
+
t.after(() => {
|
|
986
|
+
try {
|
|
987
|
+
resetWriteGateState(dir);
|
|
988
|
+
clearPendingAutoStart(dir);
|
|
989
|
+
} finally {
|
|
990
|
+
if (originalEnv === undefined) {
|
|
991
|
+
delete process.env.GSD_PERSIST_WRITE_GATE_STATE;
|
|
992
|
+
} else {
|
|
993
|
+
process.env.GSD_PERSIST_WRITE_GATE_STATE = originalEnv;
|
|
994
|
+
}
|
|
995
|
+
process.chdir(originalCwd);
|
|
996
|
+
rmSync(dir, { recursive: true, force: true });
|
|
997
|
+
}
|
|
998
|
+
});
|
|
999
|
+
|
|
1000
|
+
const handlers = new Map<string, Array<(event: any, ctx?: any) => Promise<any> | any>>();
|
|
1001
|
+
const pi = {
|
|
1002
|
+
on(event: string, handler: (event: any, ctx?: any) => Promise<any> | any) {
|
|
1003
|
+
const existing = handlers.get(event) ?? [];
|
|
1004
|
+
existing.push(handler);
|
|
1005
|
+
handlers.set(event, existing);
|
|
1006
|
+
},
|
|
1007
|
+
} as any;
|
|
1008
|
+
|
|
1009
|
+
const notices: Array<{ text: string; level: string }> = [];
|
|
1010
|
+
const ctx = {
|
|
1011
|
+
cwd: dir,
|
|
1012
|
+
ui: { notify: (text: string, level: string) => notices.push({ text, level }) },
|
|
1013
|
+
} as any;
|
|
1014
|
+
|
|
1015
|
+
registerHooks(pi, []);
|
|
1016
|
+
setPendingAutoStart(dir, {
|
|
1017
|
+
basePath: dir,
|
|
1018
|
+
milestoneId: "M012",
|
|
1019
|
+
ctx,
|
|
1020
|
+
pi: { sendMessage: () => undefined } as any,
|
|
1021
|
+
});
|
|
1022
|
+
|
|
1023
|
+
mkdirSync(join(dir, ".gsd", "runtime"), { recursive: true });
|
|
1024
|
+
writeFileSync(statePath, JSON.stringify({
|
|
1025
|
+
verifiedDepthMilestones: ["M012"],
|
|
1026
|
+
verifiedApprovalGates: [gateId],
|
|
1027
|
+
activeQueuePhase: false,
|
|
1028
|
+
pendingGateId: null,
|
|
1029
|
+
}, null, 2), "utf-8");
|
|
1030
|
+
|
|
1031
|
+
const approvalMessage = {
|
|
1032
|
+
role: "assistant",
|
|
1033
|
+
content: [
|
|
1034
|
+
{ type: "text", text: "Here is the milestone plan.\n\nDid I capture the project correctly?" },
|
|
1035
|
+
],
|
|
1036
|
+
};
|
|
1037
|
+
|
|
1038
|
+
for (const handler of handlers.get("message_update") ?? []) {
|
|
1039
|
+
await handler({ message: approvalMessage }, ctx);
|
|
1040
|
+
}
|
|
1041
|
+
|
|
1042
|
+
assert.equal(
|
|
1043
|
+
notices.some((n) => /discuss-milestone M012 is waiting for your approval - pausing/.test(n.text)),
|
|
1044
|
+
true,
|
|
1045
|
+
"streaming hook must not suppress the pause from a disk-only verification",
|
|
1046
|
+
);
|
|
1047
|
+
assert.equal(
|
|
1048
|
+
shouldBlockContextArtifactSave("CONTEXT", "M012", null, dir).block,
|
|
1049
|
+
true,
|
|
1050
|
+
"streaming hook must not reconcile disk-only verification into the in-memory snapshot",
|
|
1051
|
+
);
|
|
1052
|
+
|
|
1053
|
+
for (const handler of handlers.get("agent_end") ?? []) {
|
|
1054
|
+
await handler({ messages: [] }, ctx);
|
|
1055
|
+
}
|
|
1056
|
+
|
|
1057
|
+
assert.equal(getPendingGate(dir), null, "agent_end still reconciles disk and suppresses durable re-arm");
|
|
1058
|
+
});
|
|
1059
|
+
|
|
973
1060
|
// ── External-engine post-hoc gate replay (write-gate two-process sync) ──────
|
|
974
1061
|
// On claude-code-cli, pi ingests the SDK turn's tool blocks after the workflow
|
|
975
1062
|
// MCP child already executed them. The depth gate can therefore arrive at
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import test from "node:test";
|
|
2
|
+
import assert from "node:assert/strict";
|
|
3
|
+
|
|
4
|
+
import { autoSession } from "../auto-runtime-state.ts";
|
|
5
|
+
import { registerHooks } from "../bootstrap/register-hooks.ts";
|
|
6
|
+
import { resetToolCallLoopGuard } from "../bootstrap/tool-call-loop-guard.ts";
|
|
7
|
+
|
|
8
|
+
type Handler = (event: any, ctx?: any) => Promise<any> | any;
|
|
9
|
+
|
|
10
|
+
function makeHookHarness(): {
|
|
11
|
+
emitToolCall: (toolName: string, input: Record<string, unknown>) => Promise<any>;
|
|
12
|
+
} {
|
|
13
|
+
const handlers = new Map<string, Handler[]>();
|
|
14
|
+
const pi = {
|
|
15
|
+
on(event: string, handler: Handler) {
|
|
16
|
+
const existing = handlers.get(event) ?? [];
|
|
17
|
+
existing.push(handler);
|
|
18
|
+
handlers.set(event, existing);
|
|
19
|
+
},
|
|
20
|
+
};
|
|
21
|
+
const ctx = {
|
|
22
|
+
cwd: process.cwd(),
|
|
23
|
+
ui: { notify: () => undefined },
|
|
24
|
+
};
|
|
25
|
+
let callId = 0;
|
|
26
|
+
|
|
27
|
+
registerHooks(pi as any, []);
|
|
28
|
+
|
|
29
|
+
return {
|
|
30
|
+
async emitToolCall(toolName: string, input: Record<string, unknown>): Promise<any> {
|
|
31
|
+
callId += 1;
|
|
32
|
+
const loopGuardHandler = handlers.get("tool_call")?.[0];
|
|
33
|
+
assert.ok(loopGuardHandler, "loop-guard tool_call handler should be registered");
|
|
34
|
+
return loopGuardHandler({ toolCallId: `loop-${callId}`, toolName, input }, ctx);
|
|
35
|
+
},
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
test("register-hooks keeps loop-guard block reason interactive outside auto-mode", async (t) => {
|
|
40
|
+
autoSession.reset();
|
|
41
|
+
resetToolCallLoopGuard();
|
|
42
|
+
t.after(() => {
|
|
43
|
+
autoSession.reset();
|
|
44
|
+
resetToolCallLoopGuard();
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
const { emitToolCall } = makeHookHarness();
|
|
48
|
+
|
|
49
|
+
for (let i = 0; i < 4; i += 1) {
|
|
50
|
+
await emitToolCall("web_search", { query: "same query" });
|
|
51
|
+
}
|
|
52
|
+
const block = await emitToolCall("web_search", { query: "same query" });
|
|
53
|
+
|
|
54
|
+
assert.equal(block?.block, true);
|
|
55
|
+
assert.match(block.reason, /respond to the user in text/);
|
|
56
|
+
assert.doesNotMatch(block.reason, /auto-mode recovery\/replan path/);
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
test("register-hooks rewrites loop-guard block reason for auto-mode identical-args blocks", async (t) => {
|
|
60
|
+
autoSession.reset();
|
|
61
|
+
resetToolCallLoopGuard();
|
|
62
|
+
autoSession.active = true;
|
|
63
|
+
t.after(() => {
|
|
64
|
+
autoSession.reset();
|
|
65
|
+
resetToolCallLoopGuard();
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
const { emitToolCall } = makeHookHarness();
|
|
69
|
+
|
|
70
|
+
for (let i = 0; i < 4; i += 1) {
|
|
71
|
+
await emitToolCall("web_search", { query: "same query" });
|
|
72
|
+
}
|
|
73
|
+
const block = await emitToolCall("web_search", { query: "same query" });
|
|
74
|
+
|
|
75
|
+
assert.equal(block?.block, true);
|
|
76
|
+
assert.match(block.reason, /Tool loop detected \(identical args\): web_search/);
|
|
77
|
+
assert.match(block.reason, /Do not re-issue this blocked tool/);
|
|
78
|
+
assert.match(block.reason, /auto-mode recovery\/replan path/);
|
|
79
|
+
assert.doesNotMatch(block.reason, /respond to the user in text/);
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
test("register-hooks rewrites loop-guard block reason for auto-mode per-tool blocks", async (t) => {
|
|
83
|
+
autoSession.reset();
|
|
84
|
+
resetToolCallLoopGuard();
|
|
85
|
+
autoSession.active = true;
|
|
86
|
+
t.after(() => {
|
|
87
|
+
autoSession.reset();
|
|
88
|
+
resetToolCallLoopGuard();
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
const { emitToolCall } = makeHookHarness();
|
|
92
|
+
|
|
93
|
+
for (let i = 0; i < 6; i += 1) {
|
|
94
|
+
await emitToolCall("gsd_complete_milestone", { milestone: `M${i}` });
|
|
95
|
+
}
|
|
96
|
+
const block = await emitToolCall("gsd_complete_milestone", { milestone: "M7" });
|
|
97
|
+
|
|
98
|
+
assert.equal(block?.block, true);
|
|
99
|
+
assert.match(block.reason, /Tool loop detected \(repeated tool\): gsd_complete_milestone/);
|
|
100
|
+
assert.match(block.reason, /Do not re-issue this blocked tool/);
|
|
101
|
+
assert.match(block.reason, /auto-mode recovery\/replan path/);
|
|
102
|
+
assert.doesNotMatch(block.reason, /respond to the user in text/);
|
|
103
|
+
});
|
|
@@ -7,7 +7,26 @@ import { closeSync, ftruncateSync, openSync, statSync, writeFileSync } from "nod
|
|
|
7
7
|
import { join } from "node:path";
|
|
8
8
|
|
|
9
9
|
import { captureRootDirtySnapshot } from "../root-write-leak-guard.ts";
|
|
10
|
-
import { cleanup, git, makeTempRepo } from "./test-utils.ts";
|
|
10
|
+
import { cleanup, createFile, git, makeTempRepo } from "./test-utils.ts";
|
|
11
|
+
|
|
12
|
+
test("captureRootDirtySnapshot ignores unignored GSD root runtime directories", () => {
|
|
13
|
+
const base = makeTempRepo("gsd-root-dirty-runtime-");
|
|
14
|
+
try {
|
|
15
|
+
createFile(base, ".gsd/STATE.md", "state\n");
|
|
16
|
+
createFile(base, ".gsd-backups/snap-001", "backup\n");
|
|
17
|
+
createFile(base, ".gsd-worktrees/M001/file.txt", "worktree\n");
|
|
18
|
+
createFile(base, "src/foo.ts", "export {};\n");
|
|
19
|
+
|
|
20
|
+
const snapshot = captureRootDirtySnapshot(base);
|
|
21
|
+
|
|
22
|
+
assert.equal(snapshot.has(".gsd/STATE.md"), false);
|
|
23
|
+
assert.equal(snapshot.has(".gsd-backups/snap-001"), false);
|
|
24
|
+
assert.equal(snapshot.has(".gsd-worktrees/M001/file.txt"), false);
|
|
25
|
+
assert.equal(snapshot.has("src/foo.ts"), true);
|
|
26
|
+
} finally {
|
|
27
|
+
cleanup(base);
|
|
28
|
+
}
|
|
29
|
+
});
|
|
11
30
|
|
|
12
31
|
test("captureRootDirtySnapshot does not read dirty files larger than Node's Buffer limit", () => {
|
|
13
32
|
const base = makeTempRepo("gsd-root-dirty-large-");
|
|
@@ -177,10 +177,22 @@ test("auto Unit tool scope allows status/read helpers named by closeout prompts"
|
|
|
177
177
|
}
|
|
178
178
|
});
|
|
179
179
|
|
|
180
|
-
test("auto Unit tool scope
|
|
181
|
-
for (const
|
|
180
|
+
test("auto Unit tool scope allows reactive-execute status and diagnostic tools", () => {
|
|
181
|
+
for (const toolName of ["gsd_milestone_status", "gsd_exec"]) {
|
|
182
|
+
const result = shouldBlockAutoUnitToolCall("reactive-execute", toolName);
|
|
183
|
+
assert.equal(result.block, false, `reactive-execute should be able to call ${toolName}`);
|
|
184
|
+
}
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
test("auto Unit tool scope allows incremental task planning during plan-slice", () => {
|
|
188
|
+
const result = shouldBlockAutoUnitToolCall("plan-slice", "gsd_plan_task");
|
|
189
|
+
assert.equal(result.block, false, "plan-slice should be able to call gsd_plan_task incrementally");
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
test("auto Unit tool scope still blocks per-task planner outside plan-slice", () => {
|
|
193
|
+
for (const unitType of ["refine-slice", "replan-slice"]) {
|
|
182
194
|
const result = shouldBlockAutoUnitToolCall(unitType, "gsd_plan_task");
|
|
183
|
-
assert.equal(result.block, true, `${unitType} should not call
|
|
195
|
+
assert.equal(result.block, true, `${unitType} should not call gsd_plan_task`);
|
|
184
196
|
}
|
|
185
197
|
});
|
|
186
198
|
|
|
@@ -48,6 +48,16 @@ function makeRecordingPi() {
|
|
|
48
48
|
} as any;
|
|
49
49
|
}
|
|
50
50
|
|
|
51
|
+
function makeRecordingCtx() {
|
|
52
|
+
const notifications: Array<{ message: string; level: string }> = [];
|
|
53
|
+
return {
|
|
54
|
+
notifications,
|
|
55
|
+
ui: {
|
|
56
|
+
notify: (message: string, level: string) => { notifications.push({ message, level }); },
|
|
57
|
+
},
|
|
58
|
+
} as any;
|
|
59
|
+
}
|
|
60
|
+
|
|
51
61
|
// ═══ #1855: empty RecoveryContext (basePath undefined) crashes ════════════════
|
|
52
62
|
|
|
53
63
|
{
|
|
@@ -111,6 +121,52 @@ function makeRecordingPi() {
|
|
|
111
121
|
}
|
|
112
122
|
}
|
|
113
123
|
|
|
124
|
+
// ═══ plan-slice timeout recovery verifies stale PLAN before advancing ═══════
|
|
125
|
+
|
|
126
|
+
{
|
|
127
|
+
console.log("\n=== plan-slice timeout recovery rejects stale placeholder PLAN ===");
|
|
128
|
+
const base = mkdtempSync(join(tmpdir(), "gsd-timeout-stale-plan-"));
|
|
129
|
+
const sliceDir = join(base, ".gsd", "milestones", "M001", "slices", "S01");
|
|
130
|
+
mkdirSync(sliceDir, { recursive: true });
|
|
131
|
+
|
|
132
|
+
try {
|
|
133
|
+
openDatabase(join(base, ".gsd", "gsd.db"));
|
|
134
|
+
insertMilestone({ id: "M001", title: "Milestone", status: "active" });
|
|
135
|
+
insertSlice({ id: "S01", milestoneId: "M001", title: "Slice", status: "pending" });
|
|
136
|
+
writeFileSync(
|
|
137
|
+
join(sliceDir, "S01-PLAN.md"),
|
|
138
|
+
"# S01: Slice\n\n## Tasks\n\nPlanning was interrupted before task rows were persisted.\n",
|
|
139
|
+
"utf-8",
|
|
140
|
+
);
|
|
141
|
+
|
|
142
|
+
const ctx = makeRecordingCtx();
|
|
143
|
+
const pi = makeRecordingPi();
|
|
144
|
+
const result = await recoverTimedOutUnit(ctx, pi, "plan-slice", "M001/S01", "idle", {
|
|
145
|
+
basePath: base,
|
|
146
|
+
verbose: false,
|
|
147
|
+
currentUnitStartedAt: Date.now(),
|
|
148
|
+
unitRecoveryCount: new Map(),
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
assert.equal(result, "recovered", "invalid existing plan should enter steering recovery");
|
|
152
|
+
assert.equal(pi.messages.length, 1, "invalid existing plan should trigger steering instead of advancing");
|
|
153
|
+
assert.ok(
|
|
154
|
+
ctx.notifications.some((entry: { message: string }) => entry.message.includes("steering plan-slice M001/S01")),
|
|
155
|
+
"recovery notification should describe steering, not artifact advance",
|
|
156
|
+
);
|
|
157
|
+
assert.ok(
|
|
158
|
+
!ctx.notifications.some((entry: { message: string }) => entry.message.includes("artifact already exists on disk. Advancing.")),
|
|
159
|
+
"stale placeholder plan should not use the advance-on-existence path",
|
|
160
|
+
);
|
|
161
|
+
const runtime = JSON.parse(readFileSync(join(base, ".gsd", "runtime", "units", "plan-slice-M001-S01.json"), "utf-8"));
|
|
162
|
+
assert.equal(runtime.phase, "recovered", "stale placeholder plan must not be finalized");
|
|
163
|
+
assert.equal(runtime.recoveryAttempts, 1, "steering recovery attempt should be recorded");
|
|
164
|
+
} finally {
|
|
165
|
+
closeDatabase();
|
|
166
|
+
rmSync(base, { recursive: true, force: true });
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
114
170
|
// ═══ #1855: valid RecoveryContext does not crash ═════════════════════════════
|
|
115
171
|
|
|
116
172
|
{
|
|
@@ -42,6 +42,8 @@ import {
|
|
|
42
42
|
type ReconciliationDeps,
|
|
43
43
|
} from "../state-reconciliation.ts";
|
|
44
44
|
import { classifyFailure } from "../recovery-classification.ts";
|
|
45
|
+
import { handlerPhaseIndex, RECONCILIATION_REPAIR_PHASES } from "../state-reconciliation/registry.ts";
|
|
46
|
+
import { staleRenderHandler } from "../state-reconciliation/drift/stale-render.ts";
|
|
45
47
|
import type { GSDState } from "../types.ts";
|
|
46
48
|
|
|
47
49
|
function makeState(overrides: Partial<GSDState> = {}): GSDState {
|
|
@@ -159,6 +161,29 @@ test("ADR-017 (#5700): repair failure throws ReconciliationFailedError with shap
|
|
|
159
161
|
);
|
|
160
162
|
});
|
|
161
163
|
|
|
164
|
+
test("ADR-017 (#5700): custom registry handlers outside built-in phases are repaired", async () => {
|
|
165
|
+
const drift = { kind: "custom-drift", id: "D001" } as unknown as DriftRecord;
|
|
166
|
+
let repaired = false;
|
|
167
|
+
const handler = {
|
|
168
|
+
kind: "custom-drift",
|
|
169
|
+
detect: () => (repaired ? [] : [drift]),
|
|
170
|
+
repair: () => {
|
|
171
|
+
repaired = true;
|
|
172
|
+
},
|
|
173
|
+
} as unknown as DriftHandler;
|
|
174
|
+
|
|
175
|
+
const result = await reconcileBeforeDispatch("/project", {
|
|
176
|
+
invalidateStateCache: () => {},
|
|
177
|
+
deriveState: async () => makeState(),
|
|
178
|
+
registry: [handler],
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
assert.equal(result.ok, true);
|
|
182
|
+
assert.equal(repaired, true);
|
|
183
|
+
assert.equal(result.repaired.length, 1);
|
|
184
|
+
assert.equal(result.repaired[0]?.kind, "custom-drift");
|
|
185
|
+
});
|
|
186
|
+
|
|
162
187
|
test("ADR-017 (#5700): a detector failure degrades to a blocker without aborting other handlers", async () => {
|
|
163
188
|
// A single detector throwing (e.g. a transient file read error) must NOT
|
|
164
189
|
// abort the whole cycle and hide every later handler's drift. It is collected
|
|
@@ -696,6 +721,126 @@ test("ADR-017 (#5702): stale-render drift detected and repaired end-to-end", asy
|
|
|
696
721
|
assert.match(repairedContent, /\[x\][^\n]*\*\*T02\*\*/, "T02 checkbox should be checked after repair");
|
|
697
722
|
});
|
|
698
723
|
|
|
724
|
+
test("#1003: stale-render plan repair reopens DB before rendering", async (t) => {
|
|
725
|
+
const base = mkdtempSync(join(tmpdir(), "gsd-stale-render-reopen-"));
|
|
726
|
+
const sliceDir = join(base, ".gsd", "phases", "01-test");
|
|
727
|
+
mkdirSync(sliceDir, { recursive: true });
|
|
728
|
+
t.after(() => {
|
|
729
|
+
try { closeDatabase(); } catch { /* noop */ }
|
|
730
|
+
rmTreeQuiet(base);
|
|
731
|
+
});
|
|
732
|
+
|
|
733
|
+
openDatabase(join(base, ".gsd", "gsd.db"));
|
|
734
|
+
clearRendererCaches();
|
|
735
|
+
insertMilestone({ id: "M001", title: "Test", status: "active" });
|
|
736
|
+
insertSlice({ id: "S01", milestoneId: "M001", title: "Slice", status: "pending" });
|
|
737
|
+
insertTask({ id: "T01", sliceId: "S01", milestoneId: "M001", title: "First task", status: "done" });
|
|
738
|
+
|
|
739
|
+
const planPath = join(sliceDir, "01-01-PLAN.md");
|
|
740
|
+
writeFileSync(planPath, makeStalePlanContent("S01", [
|
|
741
|
+
{ id: "T01", title: "First task", done: false },
|
|
742
|
+
]));
|
|
743
|
+
closeDatabase();
|
|
744
|
+
|
|
745
|
+
await staleRenderHandler.repair(
|
|
746
|
+
{
|
|
747
|
+
kind: "stale-render",
|
|
748
|
+
renderPath: planPath,
|
|
749
|
+
reason: "T01 is done in DB but unchecked in plan",
|
|
750
|
+
},
|
|
751
|
+
{ basePath: base, state: makeState() },
|
|
752
|
+
);
|
|
753
|
+
|
|
754
|
+
const repairedContent = readFileSync(planPath, "utf-8");
|
|
755
|
+
assert.match(repairedContent, /\[x\][^\n]*\*\*T01\*\*/, "T01 checkbox should be checked after DB reopen repair");
|
|
756
|
+
assert.equal(getSliceTasks("M001", "S01").length, 1, "DB should be reopened on the original project database");
|
|
757
|
+
});
|
|
758
|
+
|
|
759
|
+
test("#1003: stale-render plan repair switches back from an open wrong DB", async (t) => {
|
|
760
|
+
const base = mkdtempSync(join(tmpdir(), "gsd-stale-render-wrong-db-"));
|
|
761
|
+
const wrongBase = mkdtempSync(join(tmpdir(), "gsd-stale-render-other-db-"));
|
|
762
|
+
const sliceDir = join(base, ".gsd", "phases", "01-test");
|
|
763
|
+
mkdirSync(sliceDir, { recursive: true });
|
|
764
|
+
mkdirSync(join(wrongBase, ".gsd"), { recursive: true });
|
|
765
|
+
t.after(() => {
|
|
766
|
+
try { closeDatabase(); } catch { /* noop */ }
|
|
767
|
+
rmTreeQuiet(base);
|
|
768
|
+
rmTreeQuiet(wrongBase);
|
|
769
|
+
});
|
|
770
|
+
|
|
771
|
+
openDatabase(join(base, ".gsd", "gsd.db"));
|
|
772
|
+
clearRendererCaches();
|
|
773
|
+
insertMilestone({ id: "M001", title: "Test", status: "active" });
|
|
774
|
+
insertSlice({ id: "S01", milestoneId: "M001", title: "Slice", status: "pending" });
|
|
775
|
+
insertTask({ id: "T01", sliceId: "S01", milestoneId: "M001", title: "First task", status: "done" });
|
|
776
|
+
|
|
777
|
+
const planPath = join(sliceDir, "01-01-PLAN.md");
|
|
778
|
+
writeFileSync(planPath, makeStalePlanContent("S01", [
|
|
779
|
+
{ id: "T01", title: "First task", done: false },
|
|
780
|
+
]));
|
|
781
|
+
closeDatabase();
|
|
782
|
+
|
|
783
|
+
openDatabase(join(wrongBase, ".gsd", "gsd.db"));
|
|
784
|
+
|
|
785
|
+
await staleRenderHandler.repair(
|
|
786
|
+
{
|
|
787
|
+
kind: "stale-render",
|
|
788
|
+
renderPath: planPath,
|
|
789
|
+
reason: "T01 is done in DB but unchecked in plan",
|
|
790
|
+
},
|
|
791
|
+
{ basePath: base, state: makeState() },
|
|
792
|
+
);
|
|
793
|
+
|
|
794
|
+
const repairedContent = readFileSync(planPath, "utf-8");
|
|
795
|
+
assert.match(repairedContent, /\[x\][^\n]*\*\*T01\*\*/, "T01 checkbox should be checked after switching back to the project DB");
|
|
796
|
+
assert.equal(getSliceTasks("M001", "S01").length, 1, "repair should leave the project DB active");
|
|
797
|
+
});
|
|
798
|
+
|
|
799
|
+
test("#1034: validation-blocked milestone summary drift returns blocker instead of exhausting repair passes", async () => {
|
|
800
|
+
const drift: Extract<DriftRecord, { kind: "stale-render" }> = {
|
|
801
|
+
kind: "stale-render",
|
|
802
|
+
renderPath: "/repo/.gsd/milestones/M001/M001-SUMMARY.md",
|
|
803
|
+
reason: "M001 is complete with summary in DB but SUMMARY.md missing on disk",
|
|
804
|
+
};
|
|
805
|
+
let repairCalled = false;
|
|
806
|
+
const handler: DriftHandler<Extract<DriftRecord, { kind: "stale-render" }>> = {
|
|
807
|
+
kind: "stale-render",
|
|
808
|
+
detect: () => [drift],
|
|
809
|
+
blocker: staleRenderHandler.blocker!,
|
|
810
|
+
repair: () => {
|
|
811
|
+
repairCalled = true;
|
|
812
|
+
},
|
|
813
|
+
};
|
|
814
|
+
|
|
815
|
+
const validationBlocker = [
|
|
816
|
+
"Milestone M001 is blocked because milestone validation returned needs-attention.",
|
|
817
|
+
"Fix options:",
|
|
818
|
+
"1. Review the validation details: `/gsd status`",
|
|
819
|
+
].join("\n");
|
|
820
|
+
|
|
821
|
+
const result = await reconcileBeforeDispatch("/repo", {
|
|
822
|
+
invalidateStateCache: () => {},
|
|
823
|
+
deriveState: async () =>
|
|
824
|
+
makeState({
|
|
825
|
+
phase: "blocked",
|
|
826
|
+
blockers: [validationBlocker],
|
|
827
|
+
nextAction: "Resolve M001 validation attention before proceeding.",
|
|
828
|
+
}),
|
|
829
|
+
registry: [handler],
|
|
830
|
+
});
|
|
831
|
+
|
|
832
|
+
assert.equal(result.ok, true);
|
|
833
|
+
assert.equal(repairCalled, false, "validation-blocked milestone summary drift should not attempt repair");
|
|
834
|
+
assert.ok(
|
|
835
|
+
result.blockers.some((blocker) => blocker.includes("milestone validation returned needs-attention")),
|
|
836
|
+
"validation blocker should be returned to the caller",
|
|
837
|
+
);
|
|
838
|
+
assert.ok(
|
|
839
|
+
result.blockers.some((blocker) => blocker.includes("Stale milestone summary render")),
|
|
840
|
+
"stale-render blocker should explain why repair did not run",
|
|
841
|
+
);
|
|
842
|
+
});
|
|
843
|
+
|
|
699
844
|
test("ADR-017 (#5702): stale-render detector reason strings match repair contract", (t) => {
|
|
700
845
|
t.skip("TODO(flat-phase): stale-render detection temporarily disabled during layout transition"); return;
|
|
701
846
|
const base = mkdtempSync(join(tmpdir(), "gsd-adr017-render-reasons-"));
|
|
@@ -1811,3 +1956,49 @@ test("ADR-017 (#5700): cascading drift triggers second pass within cap", async (
|
|
|
1811
1956
|
assert.equal(result.repaired.length, 2, "both passes' repairs collected");
|
|
1812
1957
|
assert.equal(repaired.length, 2);
|
|
1813
1958
|
});
|
|
1959
|
+
|
|
1960
|
+
test("deriveState is pure: stale sketch healed only via reconcileBeforeDispatch", async (t) => {
|
|
1961
|
+
const base = makeFixtureBase();
|
|
1962
|
+
t.after(() => cleanup(base));
|
|
1963
|
+
|
|
1964
|
+
openDatabase(join(base, ".gsd", "gsd.db"));
|
|
1965
|
+
insertMilestone({ id: "M001", title: "Test", status: "active" });
|
|
1966
|
+
insertSlice({
|
|
1967
|
+
id: "S02",
|
|
1968
|
+
milestoneId: "M001",
|
|
1969
|
+
title: "Feature",
|
|
1970
|
+
status: "pending",
|
|
1971
|
+
risk: "medium",
|
|
1972
|
+
depends: [],
|
|
1973
|
+
demo: "S02 demo.",
|
|
1974
|
+
sequence: 1,
|
|
1975
|
+
isSketch: true,
|
|
1976
|
+
sketchScope: "limited",
|
|
1977
|
+
});
|
|
1978
|
+
writeFileSync(
|
|
1979
|
+
join(base, ".gsd", "phases", "01-test", "01-02-PLAN.md"),
|
|
1980
|
+
"# S02 Plan\n",
|
|
1981
|
+
);
|
|
1982
|
+
|
|
1983
|
+
const { deriveState } = await import("../state.ts");
|
|
1984
|
+
invalidateStateCache();
|
|
1985
|
+
|
|
1986
|
+
const beforeReconcile = await deriveState(base);
|
|
1987
|
+
assert.equal(beforeReconcile.phase, "refining", "derive alone must not heal stale sketch flag");
|
|
1988
|
+
assert.equal(getSlice("M001", "S02")?.is_sketch, 1, "DB flag unchanged before reconcile");
|
|
1989
|
+
|
|
1990
|
+
const result = await reconcileBeforeDispatch(base);
|
|
1991
|
+
assert.equal(result.ok, true);
|
|
1992
|
+
assert.equal(getSlice("M001", "S02")?.is_sketch, 0, "reconcile clears sketch flag");
|
|
1993
|
+
|
|
1994
|
+
invalidateStateCache();
|
|
1995
|
+
const afterReconcile = await deriveState(base);
|
|
1996
|
+
assert.notEqual(afterReconcile.phase, "refining", "derive after reconcile advances past sketch gate");
|
|
1997
|
+
});
|
|
1998
|
+
|
|
1999
|
+
test("reconciliation repair phases: external edits precede re-project handlers", () => {
|
|
2000
|
+
assert.equal(RECONCILIATION_REPAIR_PHASES.length, 3);
|
|
2001
|
+
assert.ok(handlerPhaseIndex("external-markdown-edit") < handlerPhaseIndex("stale-render"));
|
|
2002
|
+
assert.ok(handlerPhaseIndex("external-planning-edit") < handlerPhaseIndex("roadmap-divergence"));
|
|
2003
|
+
assert.ok(handlerPhaseIndex("stale-sketch-flag") < handlerPhaseIndex("stale-render"));
|
|
2004
|
+
});
|