@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
|
@@ -16,6 +16,7 @@ import { execSync } from "node:child_process";
|
|
|
16
16
|
|
|
17
17
|
import { captureIntegrationBranch, getCurrentBranch } from "../../worktree.ts";
|
|
18
18
|
import { readIntegrationBranch, QUICK_BRANCH_RE } from "../../git-service.ts";
|
|
19
|
+
import { disableDebug, enableDebug, getDebugCounters } from "../../debug-logger.ts";
|
|
19
20
|
|
|
20
21
|
function run(command: string, cwd: string): string {
|
|
21
22
|
return execSync(command, { cwd, stdio: ["ignore", "pipe", "pipe"], encoding: "utf-8" }).trim();
|
|
@@ -205,16 +206,25 @@ test('cleanupQuickBranch: recovers from disk state (cross-session)', async () =>
|
|
|
205
206
|
test('cleanupQuickBranch: no-op without pending state', async () => {
|
|
206
207
|
const repo = createTestRepo();
|
|
207
208
|
const origCwd = process.cwd();
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
const result = cleanupQuickBranch();
|
|
212
|
-
|
|
213
|
-
assert.ok(!result, "returns false when no pending state");
|
|
214
|
-
assert.deepStrictEqual(getCurrentBranch(repo), "main", "stays on main");
|
|
209
|
+
try {
|
|
210
|
+
process.chdir(repo);
|
|
211
|
+
enableDebug(repo);
|
|
215
212
|
|
|
216
|
-
|
|
217
|
-
|
|
213
|
+
const { cleanupQuickBranch } = await import("../../quick.ts");
|
|
214
|
+
const result = cleanupQuickBranch();
|
|
215
|
+
const firstGitInvocations = getDebugCounters().gitInvocations;
|
|
216
|
+
const secondResult = cleanupQuickBranch();
|
|
217
|
+
|
|
218
|
+
assert.ok(!result, "returns false when no pending state");
|
|
219
|
+
assert.ok(!secondResult, "still returns false when no pending state");
|
|
220
|
+
assert.deepStrictEqual(getDebugCounters().gitInvocations, firstGitInvocations,
|
|
221
|
+
"cached no-state cleanup does not re-run git branch inference");
|
|
222
|
+
assert.deepStrictEqual(getCurrentBranch(repo), "main", "stays on main");
|
|
223
|
+
} finally {
|
|
224
|
+
disableDebug();
|
|
225
|
+
process.chdir(origCwd);
|
|
226
|
+
rmSync(repo, { recursive: true, force: true });
|
|
227
|
+
}
|
|
218
228
|
});
|
|
219
229
|
|
|
220
230
|
test('cleanupQuickBranch: infers return state from current gsd/quick branch', async () => {
|
|
@@ -240,6 +250,43 @@ test('cleanupQuickBranch: infers return state from current gsd/quick branch', as
|
|
|
240
250
|
}
|
|
241
251
|
});
|
|
242
252
|
|
|
253
|
+
// ═══════════════════════════════════════════════════════════════════════
|
|
254
|
+
// cleanupQuickBranch: stale miss invalidated after mid-session branch switch
|
|
255
|
+
// ═══════════════════════════════════════════════════════════════════════
|
|
256
|
+
test('cleanupQuickBranch: clears stale miss when branch switches to gsd/quick mid-session', async () => {
|
|
257
|
+
const repo = createTestRepo();
|
|
258
|
+
const origCwd = process.cwd();
|
|
259
|
+
try {
|
|
260
|
+
// Create a quick branch with real product work (so inference finds a diff)
|
|
261
|
+
run("git checkout -b gsd/quick/3-stale-miss", repo);
|
|
262
|
+
writeFileSync(join(repo, "stale.txt"), "stale miss test\n");
|
|
263
|
+
run("git add stale.txt", repo);
|
|
264
|
+
run('git commit -m "test: stale miss"', repo);
|
|
265
|
+
// Return to main so the first cleanupQuickBranch call records a miss
|
|
266
|
+
run("git checkout main", repo);
|
|
267
|
+
|
|
268
|
+
process.chdir(repo);
|
|
269
|
+
const { cleanupQuickBranch } = await import("../../quick.ts");
|
|
270
|
+
|
|
271
|
+
// First call: on main with no disk state → miss recorded (keyed to "main")
|
|
272
|
+
const result1 = cleanupQuickBranch();
|
|
273
|
+
assert.ok(!result1, "first call (on main) returns false — miss recorded");
|
|
274
|
+
|
|
275
|
+
// Simulate mid-session external branch switch to the stranded quick branch
|
|
276
|
+
run("git checkout gsd/quick/3-stale-miss", repo);
|
|
277
|
+
|
|
278
|
+
// Second call: branch changed from the recorded miss, so cache is invalidated
|
|
279
|
+
// and inferQuickReturnFromBranch runs — cleanup must succeed
|
|
280
|
+
const result2 = cleanupQuickBranch();
|
|
281
|
+
assert.ok(result2, "second call returns true after mid-session switch to quick branch");
|
|
282
|
+
assert.deepStrictEqual(getCurrentBranch(repo), "main",
|
|
283
|
+
"cleanup merged back to main after stale-miss invalidation");
|
|
284
|
+
} finally {
|
|
285
|
+
process.chdir(origCwd);
|
|
286
|
+
rmSync(repo, { recursive: true, force: true });
|
|
287
|
+
}
|
|
288
|
+
});
|
|
289
|
+
|
|
243
290
|
// ═══════════════════════════════════════════════════════════════════════
|
|
244
291
|
// End-to-end: quick branch does NOT contaminate integration branch
|
|
245
292
|
// ═══════════════════════════════════════════════════════════════════════
|
|
@@ -19,6 +19,7 @@ import { tmpdir } from "node:os";
|
|
|
19
19
|
|
|
20
20
|
import {
|
|
21
21
|
saveJsonFile,
|
|
22
|
+
saveJsonFileCompact,
|
|
22
23
|
loadJsonFile,
|
|
23
24
|
writeJsonFileAtomic,
|
|
24
25
|
} from "../json-persistence.ts";
|
|
@@ -56,6 +57,37 @@ test("saveJsonFile creates file with valid JSON content", () => {
|
|
|
56
57
|
}
|
|
57
58
|
});
|
|
58
59
|
|
|
60
|
+
test("saveJsonFile keeps pretty-printed output for human-readable state", () => {
|
|
61
|
+
const dir = makeTempDir();
|
|
62
|
+
const filePath = join(dir, "pretty.json");
|
|
63
|
+
|
|
64
|
+
try {
|
|
65
|
+
const data = { foo: "bar", nested: { count: 42 } };
|
|
66
|
+
saveJsonFile(filePath, data);
|
|
67
|
+
|
|
68
|
+
const content = readFileSync(filePath, "utf-8");
|
|
69
|
+
assert.equal(content, JSON.stringify(data, null, 2) + "\n");
|
|
70
|
+
} finally {
|
|
71
|
+
cleanup(dir);
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
test("saveJsonFileCompact writes valid compact JSON content", () => {
|
|
76
|
+
const dir = makeTempDir();
|
|
77
|
+
const filePath = join(dir, "compact.json");
|
|
78
|
+
|
|
79
|
+
try {
|
|
80
|
+
const data = { foo: "bar", nested: { count: 42 } };
|
|
81
|
+
saveJsonFileCompact(filePath, data);
|
|
82
|
+
|
|
83
|
+
const content = readFileSync(filePath, "utf-8");
|
|
84
|
+
assert.equal(content, JSON.stringify(data) + "\n");
|
|
85
|
+
assert.deepEqual(JSON.parse(content), data);
|
|
86
|
+
} finally {
|
|
87
|
+
cleanup(dir);
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
|
|
59
91
|
test("saveJsonFile does not leave .tmp files on success", () => {
|
|
60
92
|
const dir = makeTempDir();
|
|
61
93
|
const filePath = join(dir, "clean.json");
|
|
@@ -72,6 +104,21 @@ test("saveJsonFile does not leave .tmp files on success", () => {
|
|
|
72
104
|
}
|
|
73
105
|
});
|
|
74
106
|
|
|
107
|
+
test("saveJsonFileCompact does not leave .tmp files on success", () => {
|
|
108
|
+
const dir = makeTempDir();
|
|
109
|
+
const filePath = join(dir, "compact-clean.json");
|
|
110
|
+
|
|
111
|
+
try {
|
|
112
|
+
saveJsonFileCompact(filePath, { test: true });
|
|
113
|
+
|
|
114
|
+
const files = readdirSync(dir);
|
|
115
|
+
const tmpFiles = files.filter(f => f.includes(".tmp"));
|
|
116
|
+
assert.equal(tmpFiles.length, 0, `Unexpected .tmp files: ${tmpFiles.join(", ")}`);
|
|
117
|
+
} finally {
|
|
118
|
+
cleanup(dir);
|
|
119
|
+
}
|
|
120
|
+
});
|
|
121
|
+
|
|
75
122
|
test("saveJsonFile creates parent directories", () => {
|
|
76
123
|
const dir = makeTempDir();
|
|
77
124
|
const filePath = join(dir, "deep", "nested", "data.json");
|
|
@@ -161,6 +161,41 @@ test("backfill is idempotent — second run on the same file is a no-op", () =>
|
|
|
161
161
|
}
|
|
162
162
|
});
|
|
163
163
|
|
|
164
|
+
test("backfill skips a knowledge row whose memory insert throws and continues later rows", () => {
|
|
165
|
+
const base = makeTmpBase();
|
|
166
|
+
try {
|
|
167
|
+
writeKnowledgeMd(base, FIXTURE);
|
|
168
|
+
|
|
169
|
+
const adapter = _getAdapter();
|
|
170
|
+
assert.ok(adapter);
|
|
171
|
+
adapter.exec(`
|
|
172
|
+
CREATE TRIGGER fail_p002_memory_insert
|
|
173
|
+
BEFORE INSERT ON memories
|
|
174
|
+
WHEN json_extract(NEW.structured_fields, '$.sourceKnowledgeId') = 'P002'
|
|
175
|
+
BEGIN
|
|
176
|
+
SELECT RAISE(ABORT, 'poison knowledge P002');
|
|
177
|
+
END
|
|
178
|
+
`);
|
|
179
|
+
|
|
180
|
+
const written = backfillKnowledgeToMemories(base);
|
|
181
|
+
assert.equal(written, 2, "one poisoned row should not abort the batch");
|
|
182
|
+
|
|
183
|
+
const rows = adapter
|
|
184
|
+
.prepare(
|
|
185
|
+
"SELECT structured_fields FROM memories WHERE structured_fields LIKE '%\"sourceKnowledgeId\":\"%' ORDER BY seq",
|
|
186
|
+
)
|
|
187
|
+
.all() as Array<{ structured_fields: string }>;
|
|
188
|
+
|
|
189
|
+
assert.deepEqual(
|
|
190
|
+
rows.map((row) => JSON.parse(row.structured_fields).sourceKnowledgeId),
|
|
191
|
+
["P001", "L001"],
|
|
192
|
+
"rows after the poisoned knowledge entry should still be migrated",
|
|
193
|
+
);
|
|
194
|
+
} finally {
|
|
195
|
+
cleanup(base);
|
|
196
|
+
}
|
|
197
|
+
});
|
|
198
|
+
|
|
164
199
|
test("backfill returns 0 when KNOWLEDGE.md is absent", () => {
|
|
165
200
|
const base = makeTmpBase();
|
|
166
201
|
try {
|
|
@@ -136,8 +136,10 @@ test("#896 startup maintenance skips repeated sentinel work in one session", asy
|
|
|
136
136
|
closeDatabase();
|
|
137
137
|
assert.equal(isDbAvailable(), false);
|
|
138
138
|
|
|
139
|
+
let sessionId = "session-one";
|
|
139
140
|
const ctx = {
|
|
140
141
|
projectRoot: base,
|
|
142
|
+
sessionManager: { getSessionId: () => sessionId },
|
|
141
143
|
ui: { notify: () => undefined },
|
|
142
144
|
} as unknown as ExtensionContext;
|
|
143
145
|
|
|
@@ -190,6 +192,18 @@ test("#896 startup maintenance skips repeated sentinel work in one session", asy
|
|
|
190
192
|
.prepare("SELECT COUNT(*) AS count FROM memories WHERE structured_fields LIKE '%\"sourceKnowledgeId\":\"P002\"%'")
|
|
191
193
|
.get() as { count: number };
|
|
192
194
|
assert.equal(secondPass.count, 0, "second startup in same session should not re-run KNOWLEDGE.md sentinel backfill");
|
|
195
|
+
|
|
196
|
+
sessionId = "session-two";
|
|
197
|
+
await buildBeforeAgentStartResult(
|
|
198
|
+
{ prompt: "Inspect project knowledge in a new session", systemPrompt: "base system prompt" },
|
|
199
|
+
ctx,
|
|
200
|
+
);
|
|
201
|
+
await _flushDeferredContextMaintenanceForTest(base);
|
|
202
|
+
|
|
203
|
+
const nextSessionPass = adapter
|
|
204
|
+
.prepare("SELECT COUNT(*) AS count FROM memories WHERE structured_fields LIKE '%\"sourceKnowledgeId\":\"P002\"%'")
|
|
205
|
+
.get() as { count: number };
|
|
206
|
+
assert.equal(nextSessionPass.count, 1, "startup maintenance should run once for a later session");
|
|
193
207
|
});
|
|
194
208
|
|
|
195
209
|
test("#896 later turns reopen the project DB after startup maintenance is complete", async (t) => {
|
|
@@ -16,6 +16,7 @@ import {
|
|
|
16
16
|
openDatabase,
|
|
17
17
|
closeDatabase,
|
|
18
18
|
insertDecision,
|
|
19
|
+
_getAdapter,
|
|
19
20
|
} from "../gsd-db.ts";
|
|
20
21
|
import { createMemory } from "../memory-store.ts";
|
|
21
22
|
import {
|
|
@@ -271,6 +272,83 @@ test("scanConsolidationGaps combines decisions and KNOWLEDGE.md gaps in summary"
|
|
|
271
272
|
}
|
|
272
273
|
});
|
|
273
274
|
|
|
275
|
+
test("scanConsolidationGaps collects memory source markers with one memories scan", () => {
|
|
276
|
+
const base = makeTmpBase();
|
|
277
|
+
try {
|
|
278
|
+
insertDecision({
|
|
279
|
+
id: "D001",
|
|
280
|
+
when_context: "2026-01-01",
|
|
281
|
+
scope: "M001",
|
|
282
|
+
decision: "Unmigrated decision",
|
|
283
|
+
choice: "A",
|
|
284
|
+
rationale: "x",
|
|
285
|
+
revisable: "yes",
|
|
286
|
+
made_by: "agent",
|
|
287
|
+
superseded_by: null,
|
|
288
|
+
});
|
|
289
|
+
insertDecision({
|
|
290
|
+
id: "D002",
|
|
291
|
+
when_context: "2026-01-02",
|
|
292
|
+
scope: "M001",
|
|
293
|
+
decision: "Migrated decision",
|
|
294
|
+
choice: "B",
|
|
295
|
+
rationale: "y",
|
|
296
|
+
revisable: "yes",
|
|
297
|
+
made_by: "agent",
|
|
298
|
+
superseded_by: null,
|
|
299
|
+
});
|
|
300
|
+
createMemory({
|
|
301
|
+
category: "architecture",
|
|
302
|
+
content: "Migrated decision Chose: B. Rationale: y.",
|
|
303
|
+
scope: "M001",
|
|
304
|
+
structuredFields: { sourceDecisionId: "D002" },
|
|
305
|
+
});
|
|
306
|
+
createMemory({
|
|
307
|
+
category: "pattern",
|
|
308
|
+
content: "Migrated knowledge pattern",
|
|
309
|
+
scope: "project",
|
|
310
|
+
structuredFields: { sourceKnowledgeId: "P001" },
|
|
311
|
+
});
|
|
312
|
+
writeKnowledgeMd(
|
|
313
|
+
base,
|
|
314
|
+
`## Patterns
|
|
315
|
+
|
|
316
|
+
| # | Pattern | Where | Notes |
|
|
317
|
+
|---|---------|-------|-------|
|
|
318
|
+
| P001 | Migrated knowledge pattern | scanner | covered |
|
|
319
|
+
| P002 | Unmigrated knowledge pattern | scanner | gap |
|
|
320
|
+
`,
|
|
321
|
+
);
|
|
322
|
+
|
|
323
|
+
const adapter = _getAdapter();
|
|
324
|
+
assert.ok(adapter);
|
|
325
|
+
const originalPrepare = adapter.prepare.bind(adapter);
|
|
326
|
+
const memorySql: string[] = [];
|
|
327
|
+
adapter.prepare = (sql: string) => {
|
|
328
|
+
if (sql.includes("FROM memories")) memorySql.push(sql);
|
|
329
|
+
return originalPrepare(sql);
|
|
330
|
+
};
|
|
331
|
+
|
|
332
|
+
const report = scanConsolidationGaps(base);
|
|
333
|
+
assert.equal(report.decisions.migrated, 1);
|
|
334
|
+
assert.equal(report.decisions.unmigrated, 1);
|
|
335
|
+
assert.equal(report.knowledge.migrated, 1);
|
|
336
|
+
assert.equal(report.knowledge.unmigrated, 1);
|
|
337
|
+
assert.equal(
|
|
338
|
+
memorySql.filter((sql) => sql.includes("SELECT structured_fields FROM memories")).length,
|
|
339
|
+
1,
|
|
340
|
+
"source marker detection should read memories once",
|
|
341
|
+
);
|
|
342
|
+
assert.equal(
|
|
343
|
+
memorySql.some((sql) => sql.includes("LIKE :pattern")),
|
|
344
|
+
false,
|
|
345
|
+
"scanner must not reintroduce per-row LIKE marker probes",
|
|
346
|
+
);
|
|
347
|
+
} finally {
|
|
348
|
+
cleanup(base);
|
|
349
|
+
}
|
|
350
|
+
});
|
|
351
|
+
|
|
274
352
|
// ─── reportConsolidationGaps ───────────────────────────────────────────────
|
|
275
353
|
|
|
276
354
|
test("reportConsolidationGaps emits a notification + warning when gaps exist", () => {
|
|
@@ -5,6 +5,9 @@ import {
|
|
|
5
5
|
SCHEMA_VERSION,
|
|
6
6
|
_getAdapter,
|
|
7
7
|
} from '../gsd-db.ts';
|
|
8
|
+
import * as fs from 'node:fs';
|
|
9
|
+
import * as path from 'node:path';
|
|
10
|
+
import * as os from 'node:os';
|
|
8
11
|
import {
|
|
9
12
|
_resetLogs,
|
|
10
13
|
peekLogs,
|
|
@@ -22,6 +25,7 @@ import {
|
|
|
22
25
|
markUnitProcessed,
|
|
23
26
|
decayStaleMemories,
|
|
24
27
|
enforceMemoryCap,
|
|
28
|
+
queryMemoriesRanked,
|
|
25
29
|
applyMemoryActions,
|
|
26
30
|
formatMemoriesForPrompt,
|
|
27
31
|
} from '../memory-store.ts';
|
|
@@ -29,6 +33,16 @@ import type { MemoryAction } from '../memory-store.ts';
|
|
|
29
33
|
import { describe, test, beforeEach, afterEach } from 'node:test';
|
|
30
34
|
import assert from 'node:assert/strict';
|
|
31
35
|
|
|
36
|
+
function tempDbPath(): string {
|
|
37
|
+
const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'gsd-memory-store-test-'));
|
|
38
|
+
return path.join(dir, 'test.db');
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function cleanupDbPath(dbPath: string): void {
|
|
42
|
+
closeDatabase();
|
|
43
|
+
fs.rmSync(path.dirname(dbPath), { recursive: true, force: true });
|
|
44
|
+
}
|
|
45
|
+
|
|
32
46
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
33
47
|
// memory-store: fallback when DB not open
|
|
34
48
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
@@ -366,6 +380,40 @@ test('memory-store: schema includes memories table', () => {
|
|
|
366
380
|
closeDatabase();
|
|
367
381
|
});
|
|
368
382
|
|
|
383
|
+
test('memory-store: reopening rebuilds FTS index for pre-FTS memories', () => {
|
|
384
|
+
const dbPath = tempDbPath();
|
|
385
|
+
try {
|
|
386
|
+
openDatabase(dbPath);
|
|
387
|
+
const id = createMemory({ category: 'gotcha', content: 'pre FTS auth memory must become searchable' });
|
|
388
|
+
assert.equal(id, 'MEM001');
|
|
389
|
+
|
|
390
|
+
const adapter = _getAdapter()!;
|
|
391
|
+
const fts = adapter.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name='memories_fts'").get();
|
|
392
|
+
if (!fts) return;
|
|
393
|
+
|
|
394
|
+
adapter.exec('DROP TRIGGER IF EXISTS memories_ai');
|
|
395
|
+
adapter.exec('DROP TRIGGER IF EXISTS memories_ad');
|
|
396
|
+
adapter.exec('DROP TRIGGER IF EXISTS memories_au');
|
|
397
|
+
adapter.exec('DROP TABLE IF EXISTS memories_fts');
|
|
398
|
+
adapter.prepare(
|
|
399
|
+
"DELETE FROM runtime_kv WHERE scope = 'global' AND scope_id = '' AND key = 'memories_fts_rebuilt_at'",
|
|
400
|
+
).run();
|
|
401
|
+
closeDatabase();
|
|
402
|
+
|
|
403
|
+
openDatabase(dbPath);
|
|
404
|
+
const reopened = _getAdapter()!;
|
|
405
|
+
const marker = reopened.prepare(
|
|
406
|
+
"SELECT value_json FROM runtime_kv WHERE scope = 'global' AND scope_id = '' AND key = 'memories_fts_rebuilt_at'",
|
|
407
|
+
).get();
|
|
408
|
+
assert.ok(marker, 'FTS rebuild marker should be set after reopening');
|
|
409
|
+
|
|
410
|
+
const hits = queryMemoriesRanked({ query: 'auth', k: 5 }).map((hit) => hit.memory.id);
|
|
411
|
+
assert.deepEqual(hits, ['MEM001']);
|
|
412
|
+
} finally {
|
|
413
|
+
cleanupDbPath(dbPath);
|
|
414
|
+
}
|
|
415
|
+
});
|
|
416
|
+
|
|
369
417
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
370
418
|
// regression #4967 — createMemory must not silently swallow SQL errors
|
|
371
419
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
@@ -9,7 +9,15 @@ import { tmpdir } from "node:os";
|
|
|
9
9
|
import { execFileSync } from "node:child_process";
|
|
10
10
|
|
|
11
11
|
import { mergeMilestoneToMain } from "../auto-worktree.ts";
|
|
12
|
-
import {
|
|
12
|
+
import { checkCloseoutConsistencyGate } from "../closeout-consistency-gate.ts";
|
|
13
|
+
import {
|
|
14
|
+
closeDatabase,
|
|
15
|
+
insertAssessment,
|
|
16
|
+
insertMilestone,
|
|
17
|
+
insertSlice,
|
|
18
|
+
insertTask,
|
|
19
|
+
openDatabase,
|
|
20
|
+
} from "../gsd-db.ts";
|
|
13
21
|
|
|
14
22
|
function git(args: string[], cwd: string): string {
|
|
15
23
|
return execFileSync("git", args, {
|
|
@@ -61,3 +69,25 @@ test("mergeMilestoneToMain blocks when project DB closeout is still open", () =>
|
|
|
61
69
|
if (existsSync(repo)) rmSync(repo, { recursive: true, force: true });
|
|
62
70
|
}
|
|
63
71
|
});
|
|
72
|
+
|
|
73
|
+
test("closeout consistency treats deferred slices as inactive", () => {
|
|
74
|
+
try {
|
|
75
|
+
assert.equal(openDatabase(":memory:"), true);
|
|
76
|
+
insertMilestone({ id: "M001", title: "Milestone One", status: "complete" });
|
|
77
|
+
insertSlice({ milestoneId: "M001", id: "S01", title: "Done", status: "complete" });
|
|
78
|
+
insertTask({ milestoneId: "M001", sliceId: "S01", id: "T01", title: "Done", status: "complete" });
|
|
79
|
+
insertSlice({ milestoneId: "M001", id: "S02", title: "Deferred", status: "deferred" });
|
|
80
|
+
insertTask({ milestoneId: "M001", sliceId: "S02", id: "T02", title: "Deferred", status: "pending" });
|
|
81
|
+
insertAssessment({
|
|
82
|
+
path: "milestones/M001/M001-VALIDATION.md",
|
|
83
|
+
milestoneId: "M001",
|
|
84
|
+
status: "pass",
|
|
85
|
+
scope: "milestone-validation",
|
|
86
|
+
fullContent: "verdict: pass",
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
assert.deepEqual(checkCloseoutConsistencyGate("M001"), { ok: true });
|
|
90
|
+
} finally {
|
|
91
|
+
closeDatabase();
|
|
92
|
+
}
|
|
93
|
+
});
|
|
@@ -112,6 +112,12 @@ describe("pruneMetricsLedger: invalidates scoped ledger cache", () => {
|
|
|
112
112
|
// 3. Prune to keepCount=2 — should evict 3 old units from disk AND clear scopedLedgers.
|
|
113
113
|
const removed = pruneMetricsLedger(tmpDir, 2);
|
|
114
114
|
assert.equal(removed, 3, "pruneMetricsLedger should report 3 removed units");
|
|
115
|
+
const prunedRaw = readFileSync(metricsPath(tmpDir), "utf-8");
|
|
116
|
+
assert.equal(
|
|
117
|
+
prunedRaw,
|
|
118
|
+
JSON.stringify(JSON.parse(prunedRaw)) + "\n",
|
|
119
|
+
"pruneMetricsLedger should persist compact metrics.json",
|
|
120
|
+
);
|
|
115
121
|
|
|
116
122
|
// 4. Snapshot a new unit via scope. This exercises the lazy-reload path
|
|
117
123
|
// (scopedLedgers was cleared by prune) and writes the result to disk.
|
|
@@ -259,6 +259,7 @@ test("initMetrics creates ledger, snapshotUnitMetrics persists across resets", (
|
|
|
259
259
|
// Verify file content
|
|
260
260
|
const raw = readFileSync(join(tmpBase, ".gsd", "metrics.json"), "utf-8");
|
|
261
261
|
const parsed: MetricsLedger = JSON.parse(raw);
|
|
262
|
+
assert.equal(raw, JSON.stringify(parsed) + "\n", "metrics.json should be serialized compactly");
|
|
262
263
|
assert.equal(parsed.version, 1);
|
|
263
264
|
assert.equal(parsed.units.length, 1);
|
|
264
265
|
|
|
@@ -7,7 +7,10 @@ import {
|
|
|
7
7
|
existsSync,
|
|
8
8
|
mkdirSync,
|
|
9
9
|
realpathSync,
|
|
10
|
+
readFileSync,
|
|
10
11
|
} from "node:fs";
|
|
12
|
+
import fs from "node:fs";
|
|
13
|
+
import { syncBuiltinESMExports } from "node:module";
|
|
11
14
|
import { join } from "node:path";
|
|
12
15
|
import { tmpdir } from "node:os";
|
|
13
16
|
import { execSync } from "node:child_process";
|
|
@@ -116,6 +119,60 @@ describe("migrate-external worktree guard (#2970)", () => {
|
|
|
116
119
|
});
|
|
117
120
|
});
|
|
118
121
|
|
|
122
|
+
describe("migrateToExternalState copy failure rollback (#1047)", () => {
|
|
123
|
+
test("restores .gsd when a source entry fails to copy", () => {
|
|
124
|
+
const base = realpathSync(mkdtempSync(join(tmpdir(), "gsd-migrate-copy-fail-")));
|
|
125
|
+
const stateDir = realpathSync(mkdtempSync(join(tmpdir(), "gsd-state-copy-fail-")));
|
|
126
|
+
const previousStateDir = process.env.GSD_STATE_DIR;
|
|
127
|
+
const previousProjectId = process.env.GSD_PROJECT_ID;
|
|
128
|
+
const originalCpSync = fs.cpSync;
|
|
129
|
+
process.env.GSD_STATE_DIR = stateDir;
|
|
130
|
+
process.env.GSD_PROJECT_ID = "copy-fail";
|
|
131
|
+
|
|
132
|
+
try {
|
|
133
|
+
run("git init -b main", base);
|
|
134
|
+
mkdirSync(join(base, ".gsd"), { recursive: true });
|
|
135
|
+
writeFileSync(join(base, ".gsd", "PREFERENCES.md"), "# prefs\n", "utf-8");
|
|
136
|
+
writeFileSync(join(base, ".gsd", "gsd.db"), "state", "utf-8");
|
|
137
|
+
const failingSource = join(base, ".gsd.migrating", "gsd.db");
|
|
138
|
+
fs.cpSync = ((...args: Parameters<typeof fs.cpSync>) => {
|
|
139
|
+
const src = args[0];
|
|
140
|
+
if (String(src) === failingSource) {
|
|
141
|
+
const error = new Error("simulated copy failure") as NodeJS.ErrnoException;
|
|
142
|
+
error.code = "EACCES";
|
|
143
|
+
throw error;
|
|
144
|
+
}
|
|
145
|
+
return originalCpSync(...args);
|
|
146
|
+
}) as typeof fs.cpSync;
|
|
147
|
+
syncBuiltinESMExports();
|
|
148
|
+
|
|
149
|
+
const result = migrateToExternalState(base);
|
|
150
|
+
|
|
151
|
+
assert.equal(result.migrated, false, "copy failure must fail the migration");
|
|
152
|
+
assert.match(result.error ?? "", /Migration copy failed/);
|
|
153
|
+
assert.ok(existsSync(join(base, ".gsd", "gsd.db")), "source .gsd must be restored");
|
|
154
|
+
assert.equal(readFileSync(join(base, ".gsd", "PREFERENCES.md"), "utf-8"), "# prefs\n");
|
|
155
|
+
assert.ok(!existsSync(join(base, ".gsd.migrating")), "backup staging dir must not remain after restore");
|
|
156
|
+
assert.ok(!existsSync(join(stateDir, "projects", "copy-fail", "gsd.db")), "failed file must not be reported as migrated");
|
|
157
|
+
} finally {
|
|
158
|
+
fs.cpSync = originalCpSync;
|
|
159
|
+
syncBuiltinESMExports();
|
|
160
|
+
if (previousStateDir === undefined) {
|
|
161
|
+
delete process.env.GSD_STATE_DIR;
|
|
162
|
+
} else {
|
|
163
|
+
process.env.GSD_STATE_DIR = previousStateDir;
|
|
164
|
+
}
|
|
165
|
+
if (previousProjectId === undefined) {
|
|
166
|
+
delete process.env.GSD_PROJECT_ID;
|
|
167
|
+
} else {
|
|
168
|
+
process.env.GSD_PROJECT_ID = previousProjectId;
|
|
169
|
+
}
|
|
170
|
+
rmSync(base, { recursive: true, force: true });
|
|
171
|
+
rmSync(stateDir, { recursive: true, force: true });
|
|
172
|
+
}
|
|
173
|
+
});
|
|
174
|
+
});
|
|
175
|
+
|
|
119
176
|
// Regression tests for #5571 — recoverFailedMigration handles orphaned .gsd.migrating
|
|
120
177
|
describe("recoverFailedMigration (#5571)", () => {
|
|
121
178
|
test("returns false when .gsd.migrating does not exist", () => {
|
|
@@ -429,3 +429,73 @@ test("rebuildMarkdownProjectionsFromDb realigns markdown when DB holds extra row
|
|
|
429
429
|
cleanup(base);
|
|
430
430
|
}
|
|
431
431
|
});
|
|
432
|
+
|
|
433
|
+
test("rebuildMarkdownProjectionsFromDb realigns markdown for numeric milestone IDs", async () => {
|
|
434
|
+
const base = makeBase();
|
|
435
|
+
try {
|
|
436
|
+
await writeGSDDirectory({ projectContent: "# P\n", decisionsContent: "", requirements: [], milestones: [] }, base);
|
|
437
|
+
assert.equal(await ensureDbOpen(base), true);
|
|
438
|
+
insertMilestone({ id: "15", title: "Numeric milestone", status: "active" });
|
|
439
|
+
insertSlice({
|
|
440
|
+
id: "S01",
|
|
441
|
+
milestoneId: "15",
|
|
442
|
+
title: "Numeric slice",
|
|
443
|
+
status: "pending",
|
|
444
|
+
risk: "medium",
|
|
445
|
+
depends: [],
|
|
446
|
+
demo: "d",
|
|
447
|
+
sequence: 1,
|
|
448
|
+
});
|
|
449
|
+
insertTask({
|
|
450
|
+
id: "T01",
|
|
451
|
+
sliceId: "S01",
|
|
452
|
+
milestoneId: "15",
|
|
453
|
+
title: "Numeric task",
|
|
454
|
+
status: "pending",
|
|
455
|
+
});
|
|
456
|
+
|
|
457
|
+
const before = await checkMarkdownHierarchyAgainstDb(base);
|
|
458
|
+
assert.equal(before.recoveryCommand, "/gsd rebuild markdown");
|
|
459
|
+
|
|
460
|
+
const { rebuildMarkdownProjectionsFromDb } = await import("../commands-maintenance.ts");
|
|
461
|
+
const rebuild = await rebuildMarkdownProjectionsFromDb(base);
|
|
462
|
+
assert.ok(rebuild.rendered > 0, "expected markdown projections to render");
|
|
463
|
+
|
|
464
|
+
const after = await checkMarkdownHierarchyAgainstDb(base);
|
|
465
|
+
assert.equal(after.action, "none");
|
|
466
|
+
assert.equal(after.reason, "in-sync");
|
|
467
|
+
assert.deepEqual(after.markdown, { milestones: 1, slices: 1, tasks: 1 });
|
|
468
|
+
assert.deepEqual(after.beforeDb, { milestones: 1, slices: 1, tasks: 1 });
|
|
469
|
+
} finally {
|
|
470
|
+
cleanup(base);
|
|
471
|
+
}
|
|
472
|
+
});
|
|
473
|
+
|
|
474
|
+
test("rebuildMarkdownProjectionsFromDb realigns markdown for planned zero-slice milestones", async () => {
|
|
475
|
+
const base = makeBase();
|
|
476
|
+
try {
|
|
477
|
+
await writeGSDDirectory({ projectContent: "# P\n", decisionsContent: "", requirements: [], milestones: [] }, base);
|
|
478
|
+
assert.equal(await ensureDbOpen(base), true);
|
|
479
|
+
insertMilestone({
|
|
480
|
+
id: "M016",
|
|
481
|
+
title: "Queued milestone",
|
|
482
|
+
status: "queued",
|
|
483
|
+
planning: { vision: "Defined but not sliced yet" },
|
|
484
|
+
});
|
|
485
|
+
|
|
486
|
+
const before = await checkMarkdownHierarchyAgainstDb(base);
|
|
487
|
+
assert.equal(before.recoveryCommand, "/gsd rebuild markdown");
|
|
488
|
+
|
|
489
|
+
const { rebuildMarkdownProjectionsFromDb } = await import("../commands-maintenance.ts");
|
|
490
|
+
const rebuild = await rebuildMarkdownProjectionsFromDb(base);
|
|
491
|
+
assert.ok(rebuild.rendered > 0, "expected markdown projections to render");
|
|
492
|
+
|
|
493
|
+
const after = await checkMarkdownHierarchyAgainstDb(base);
|
|
494
|
+
assert.equal(after.action, "none");
|
|
495
|
+
assert.equal(after.reason, "in-sync");
|
|
496
|
+
assert.deepEqual(after.markdown, { milestones: 1, slices: 0, tasks: 0 });
|
|
497
|
+
assert.deepEqual(after.beforeDb, { milestones: 1, slices: 0, tasks: 0 });
|
|
498
|
+
} finally {
|
|
499
|
+
cleanup(base);
|
|
500
|
+
}
|
|
501
|
+
});
|