gsd-pi 2.81.0 → 2.82.0-dev.c22380fc3
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 +60 -30
- package/dist/resources/.managed-resources-content-hash +1 -1
- package/dist/resources/extensions/browser-tools/tools/screenshot.js +1 -0
- package/dist/resources/extensions/browser-tools/tools/zoom.js +1 -0
- package/dist/resources/extensions/gsd/auto/loop.js +111 -8
- package/dist/resources/extensions/gsd/auto/orchestrator.js +113 -6
- package/dist/resources/extensions/gsd/auto/phases.js +199 -97
- package/dist/resources/extensions/gsd/auto/run-unit.js +66 -3
- package/dist/resources/extensions/gsd/auto/session.js +9 -0
- package/dist/resources/extensions/gsd/auto/verification-retry-policy.js +43 -0
- package/dist/resources/extensions/gsd/auto-dashboard.js +182 -178
- package/dist/resources/extensions/gsd/auto-dispatch.js +14 -11
- package/dist/resources/extensions/gsd/auto-post-unit.js +7 -1
- package/dist/resources/extensions/gsd/auto-prompts.js +11 -3
- package/dist/resources/extensions/gsd/auto-recovery.js +6 -181
- package/dist/resources/extensions/gsd/auto-runtime-state.js +5 -0
- package/dist/resources/extensions/gsd/auto-start.js +20 -23
- package/dist/resources/extensions/gsd/auto-unit-closeout.js +33 -5
- package/dist/resources/extensions/gsd/auto-verification.js +12 -6
- package/dist/resources/extensions/gsd/auto-worktree.js +8 -0
- package/dist/resources/extensions/gsd/auto.js +371 -106
- package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +13 -6
- package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +13 -2
- package/dist/resources/extensions/gsd/bootstrap/register-shortcuts.js +4 -8
- package/dist/resources/extensions/gsd/bootstrap/system-context.js +55 -12
- package/dist/resources/extensions/gsd/commands/handlers/core.js +1 -1
- package/dist/resources/extensions/gsd/commands/handlers/notifications-handler.js +4 -10
- package/dist/resources/extensions/gsd/commands/handlers/parallel.js +9 -0
- package/dist/resources/extensions/gsd/commands-handlers.js +15 -2
- package/dist/resources/extensions/gsd/context-store.js +112 -0
- package/dist/resources/extensions/gsd/db-writer.js +150 -84
- package/dist/resources/extensions/gsd/docs/preferences-reference.md +1 -1
- package/dist/resources/extensions/gsd/doctor-git-checks.js +41 -6
- package/dist/resources/extensions/gsd/git-service.js +2 -1
- package/dist/resources/extensions/gsd/gsd-db.js +7 -23
- package/dist/resources/extensions/gsd/health-widget-core.js +1 -1
- package/dist/resources/extensions/gsd/health-widget.js +4 -10
- package/dist/resources/extensions/gsd/knowledge-backfill.js +144 -0
- package/dist/resources/extensions/gsd/knowledge-capture.js +136 -0
- package/dist/resources/extensions/gsd/knowledge-parser.js +154 -0
- package/dist/resources/extensions/gsd/knowledge-projection.js +210 -0
- package/dist/resources/extensions/gsd/markdown-renderer.js +6 -96
- package/dist/resources/extensions/gsd/md-importer.js +1 -1
- package/dist/resources/extensions/gsd/memory-backfill.js +73 -17
- package/dist/resources/extensions/gsd/memory-consolidation-scanner.js +222 -0
- package/dist/resources/extensions/gsd/migrate/command.js +5 -0
- package/dist/resources/extensions/gsd/migrate/preview.js +9 -0
- package/dist/resources/extensions/gsd/migrate/transformer.js +51 -4
- package/dist/resources/extensions/gsd/migrate/writer.js +11 -1
- package/dist/resources/extensions/gsd/native-git-bridge.js +14 -14
- package/dist/resources/extensions/gsd/notification-overlay.js +35 -40
- package/dist/resources/extensions/gsd/parallel-merge.js +53 -30
- package/dist/resources/extensions/gsd/parallel-monitor-overlay.js +25 -33
- package/dist/resources/extensions/gsd/prompts/complete-slice.md +14 -12
- package/dist/resources/extensions/gsd/prompts/discuss-headless.md +20 -2
- package/dist/resources/extensions/gsd/prompts/discuss.md +20 -2
- package/dist/resources/extensions/gsd/prompts/system.md +2 -2
- package/dist/resources/extensions/gsd/provider-switch-observer.js +146 -0
- package/dist/resources/extensions/gsd/recovery-classification.js +15 -1
- package/dist/resources/extensions/gsd/session-lock.js +40 -0
- package/dist/resources/extensions/gsd/state-reconciliation/drift/completion.js +131 -0
- package/dist/resources/extensions/gsd/state-reconciliation/drift/merge-state.js +247 -0
- package/dist/resources/extensions/gsd/state-reconciliation/drift/project-md.js +50 -0
- package/dist/resources/extensions/gsd/state-reconciliation/drift/roadmap.js +87 -0
- package/dist/resources/extensions/gsd/state-reconciliation/drift/sketch-flag.js +50 -0
- package/dist/resources/extensions/gsd/state-reconciliation/drift/stale-render.js +124 -0
- package/dist/resources/extensions/gsd/state-reconciliation/drift/stale-worker.js +32 -0
- package/dist/resources/extensions/gsd/state-reconciliation/errors.js +41 -0
- package/dist/resources/extensions/gsd/state-reconciliation/index.js +99 -0
- package/dist/resources/extensions/gsd/state-reconciliation/registry.js +24 -0
- package/dist/resources/extensions/gsd/state-reconciliation/spawn-gate.js +43 -0
- package/dist/resources/extensions/gsd/state-reconciliation/types.js +3 -0
- package/dist/resources/extensions/gsd/state-reconciliation.js +5 -26
- package/dist/resources/extensions/gsd/templates/knowledge.md +2 -2
- package/dist/resources/extensions/gsd/tools/workflow-tool-executors.js +119 -0
- package/dist/resources/extensions/gsd/tui/render-kit.js +74 -0
- package/dist/resources/extensions/gsd/watch/header-renderer.js +92 -69
- package/dist/resources/extensions/gsd/watch/splash-palette.js +10 -0
- package/dist/resources/extensions/gsd/workflow-mcp.js +2 -2
- package/dist/resources/extensions/gsd/worktree-lifecycle.js +743 -318
- package/dist/resources/extensions/gsd/worktree-telemetry.js +3 -1
- 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 +12 -12
- package/dist/web/standalone/.next/build-manifest.json +3 -3
- package/dist/web/standalone/.next/prerender-manifest.json +3 -3
- package/dist/web/standalone/.next/required-server-files.json +3 -3
- package/dist/web/standalone/.next/server/app/_global-error/page.js +3 -3
- package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found/page.js +2 -2
- package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.rsc +3 -3
- package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +3 -3
- package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +3 -3
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/api/boot/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/boot/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/browse-directories/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/browse-directories/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/captures/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/captures/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/cleanup/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/cleanup/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/dev-mode/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/dev-mode/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/doctor/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/doctor/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/experimental/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/experimental/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/export-data/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/export-data/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/files/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/files/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/forensics/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/forensics/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/git/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/history/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/history/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/hooks/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/hooks/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/inspect/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/inspect/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/knowledge/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/knowledge/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/live-state/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/live-state/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/notifications/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/notifications/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/onboarding/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/onboarding/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/preferences/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/preferences/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/projects/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/projects/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/recovery/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/recovery/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/remote-questions/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/remote-questions/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/browser/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/browser/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/command/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/command/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/events/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/session/events/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/manage/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/manage/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/settings-data/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/settings-data/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/shutdown/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/shutdown/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/skill-health/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/skill-health/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/steer/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/steer/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/switch-root/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/switch-root/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/input/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/input/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/resize/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/terminal/resize/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/sessions/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/terminal/stream/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/upload/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/upload/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/undo/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/undo/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/update/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/visualizer/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/visualizer/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/index.html +1 -1
- package/dist/web/standalone/.next/server/app/index.rsc +4 -4
- package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
- package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +4 -4
- package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +3 -3
- package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/page.js +2 -2
- package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app-paths-manifest.json +12 -12
- package/dist/web/standalone/.next/server/chunks/63.js +3 -3
- package/dist/web/standalone/.next/server/chunks/6897.js +1 -1
- package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
- package/dist/web/standalone/.next/server/middleware.js +2 -2
- package/dist/web/standalone/.next/server/next-font-manifest.js +1 -1
- package/dist/web/standalone/.next/server/next-font-manifest.json +1 -1
- package/dist/web/standalone/.next/server/pages/404.html +1 -1
- package/dist/web/standalone/.next/server/pages/500.html +1 -1
- package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
- package/dist/web/standalone/.next/static/chunks/app/_not-found/{page-2f24283c162b6ab3.js → page-f2a7482d42a5614b.js} +1 -1
- package/dist/web/standalone/.next/static/chunks/app/{layout-9ecfd95f343793f0.js → layout-a16c7a7ecdf0c2cf.js} +1 -1
- package/dist/web/standalone/.next/static/chunks/app/page-752f1e2ebdaa3e45.js +1 -0
- package/dist/web/standalone/.next/static/chunks/main-app-fdab67f7802d7832.js +1 -0
- package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-459824ffb8c323dd.js +1 -0
- package/dist/web/standalone/node_modules/node-pty/build/Makefile +2 -2
- package/dist/web/standalone/node_modules/node-pty/build/Release/pty.node +0 -0
- package/dist/web/standalone/node_modules/node-pty/build/pty.target.mk +14 -14
- package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api.target.mk +14 -14
- package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_except.target.mk +14 -14
- package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_maybe.target.mk +14 -14
- package/dist/web/standalone/server.js +1 -1
- package/dist/welcome-screen.d.ts +0 -7
- package/dist/welcome-screen.js +60 -69
- package/package.json +3 -2
- package/packages/contracts/dist/rpc.test.js +7 -0
- package/packages/contracts/dist/rpc.test.js.map +1 -1
- package/packages/contracts/dist/workflow.d.ts +21 -0
- package/packages/contracts/dist/workflow.d.ts.map +1 -1
- package/packages/contracts/dist/workflow.js +24 -0
- package/packages/contracts/dist/workflow.js.map +1 -1
- package/packages/contracts/src/rpc.test.ts +8 -0
- package/packages/contracts/src/workflow.ts +24 -0
- package/packages/daemon/package.json +2 -2
- package/packages/mcp-server/README.md +14 -3
- package/packages/mcp-server/dist/workflow-tools.d.ts +0 -3
- package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
- package/packages/mcp-server/dist/workflow-tools.js +80 -0
- package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
- package/packages/mcp-server/package.json +2 -2
- package/packages/mcp-server/src/workflow-tools-parity.test.ts +244 -0
- package/packages/mcp-server/src/workflow-tools.test.ts +22 -0
- package/packages/mcp-server/src/workflow-tools.ts +168 -0
- package/packages/mcp-server/tsconfig.tsbuildinfo +1 -1
- package/packages/native/package.json +1 -1
- package/packages/pi-agent-core/package.json +1 -1
- package/packages/pi-agent-core/tsconfig.tsbuildinfo +1 -1
- package/packages/pi-ai/dist/index.d.ts +2 -2
- package/packages/pi-ai/dist/index.d.ts.map +1 -1
- package/packages/pi-ai/dist/index.js +1 -1
- package/packages/pi-ai/dist/index.js.map +1 -1
- package/packages/pi-ai/dist/providers/transform-messages.d.ts +11 -0
- package/packages/pi-ai/dist/providers/transform-messages.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/transform-messages.js +20 -0
- package/packages/pi-ai/dist/providers/transform-messages.js.map +1 -1
- package/packages/pi-ai/package.json +1 -1
- package/packages/pi-ai/src/index.ts +7 -2
- package/packages/pi-ai/src/providers/transform-messages.ts +24 -0
- package/packages/pi-ai/tsconfig.tsbuildinfo +1 -1
- package/packages/pi-coding-agent/dist/core/system-prompt.js +4 -4
- package/packages/pi-coding-agent/dist/core/system-prompt.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/assistant-message-design.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/assistant-message-design.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/assistant-message-design.test.js +47 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/assistant-message-design.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-execution.test.js +76 -9
- package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-execution.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/user-message-design.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/user-message-design.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/user-message-design.test.js +40 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/user-message-design.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/adaptive-layout.d.ts +0 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/adaptive-layout.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/adaptive-layout.js +30 -29
- package/packages/pi-coding-agent/dist/modes/interactive/components/adaptive-layout.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/adaptive-layout.test.js +10 -3
- package/packages/pi-coding-agent/dist/modes/interactive/components/adaptive-layout.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.js +13 -13
- package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/bash-execution.d.ts +1 -3
- package/packages/pi-coding-agent/dist/modes/interactive/components/bash-execution.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/bash-execution.js +58 -3
- package/packages/pi-coding-agent/dist/modes/interactive/components/bash-execution.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/diff.d.ts +2 -2
- package/packages/pi-coding-agent/dist/modes/interactive/components/diff.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/diff.js +12 -6
- package/packages/pi-coding-agent/dist/modes/interactive/components/diff.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/footer.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/footer.js +14 -41
- package/packages/pi-coding-agent/dist/modes/interactive/components/footer.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts +0 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js +86 -82
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/transcript-design.d.ts +35 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/transcript-design.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/transcript-design.js +152 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/transcript-design.js.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/tui-style-kit.d.ts +16 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/tui-style-kit.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/tui-style-kit.js +73 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/tui-style-kit.js.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/user-message.d.ts +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/user-message.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/user-message.js +12 -8
- package/packages/pi-coding-agent/dist/modes/interactive/components/user-message.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/theme/theme-highlight.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/modes/interactive/theme/theme-highlight.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/theme/theme-highlight.test.js +17 -0
- package/packages/pi-coding-agent/dist/modes/interactive/theme/theme-highlight.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/theme/theme.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/theme/theme.js +105 -1
- package/packages/pi-coding-agent/dist/modes/interactive/theme/theme.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/theme/themes.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/theme/themes.js +27 -26
- package/packages/pi-coding-agent/dist/modes/interactive/theme/themes.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/tui-mode.test.js +9 -6
- package/packages/pi-coding-agent/dist/modes/interactive/tui-mode.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/tests/system-prompt-file-safety.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/tests/system-prompt-file-safety.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/tests/system-prompt-file-safety.test.js +17 -0
- package/packages/pi-coding-agent/dist/tests/system-prompt-file-safety.test.js.map +1 -0
- package/packages/pi-coding-agent/package.json +1 -1
- package/packages/pi-coding-agent/src/core/system-prompt.ts +4 -4
- package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/assistant-message-design.test.ts +56 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/tool-execution.test.ts +113 -9
- package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/user-message-design.test.ts +48 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/adaptive-layout.test.ts +10 -3
- package/packages/pi-coding-agent/src/modes/interactive/components/adaptive-layout.ts +43 -42
- package/packages/pi-coding-agent/src/modes/interactive/components/assistant-message.ts +14 -14
- package/packages/pi-coding-agent/src/modes/interactive/components/bash-execution.ts +64 -3
- package/packages/pi-coding-agent/src/modes/interactive/components/diff.ts +13 -7
- package/packages/pi-coding-agent/src/modes/interactive/components/footer.ts +15 -42
- package/packages/pi-coding-agent/src/modes/interactive/components/tool-execution.ts +84 -104
- package/packages/pi-coding-agent/src/modes/interactive/components/transcript-design.ts +196 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/tui-style-kit.ts +94 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/user-message.ts +14 -9
- package/packages/pi-coding-agent/src/modes/interactive/theme/theme-highlight.test.ts +23 -0
- package/packages/pi-coding-agent/src/modes/interactive/theme/theme.ts +106 -1
- package/packages/pi-coding-agent/src/modes/interactive/theme/themes.ts +27 -26
- package/packages/pi-coding-agent/src/modes/interactive/tui-mode.test.ts +9 -6
- package/packages/pi-coding-agent/src/tests/system-prompt-file-safety.test.ts +22 -0
- package/packages/pi-coding-agent/tsconfig.tsbuildinfo +1 -1
- package/packages/pi-tui/dist/__tests__/overlay-layout.test.js +14 -1
- package/packages/pi-tui/dist/__tests__/overlay-layout.test.js.map +1 -1
- package/packages/pi-tui/dist/overlay-layout.d.ts.map +1 -1
- package/packages/pi-tui/dist/overlay-layout.js +9 -6
- package/packages/pi-tui/dist/overlay-layout.js.map +1 -1
- package/packages/pi-tui/dist/tui.d.ts.map +1 -1
- package/packages/pi-tui/dist/tui.js +5 -0
- package/packages/pi-tui/dist/tui.js.map +1 -1
- package/packages/pi-tui/package.json +1 -1
- package/packages/pi-tui/src/__tests__/overlay-layout.test.ts +20 -1
- package/packages/pi-tui/src/overlay-layout.ts +10 -7
- package/packages/pi-tui/src/tui.ts +6 -0
- package/packages/pi-tui/tsconfig.tsbuildinfo +1 -1
- package/packages/rpc-client/package.json +1 -1
- package/packages/rpc-client/tsconfig.tsbuildinfo +1 -1
- package/pkg/dist/modes/interactive/theme/theme-highlight.test.d.ts +2 -0
- package/pkg/dist/modes/interactive/theme/theme-highlight.test.d.ts.map +1 -0
- package/pkg/dist/modes/interactive/theme/theme-highlight.test.js +17 -0
- package/pkg/dist/modes/interactive/theme/theme-highlight.test.js.map +1 -0
- package/pkg/dist/modes/interactive/theme/theme.d.ts.map +1 -1
- package/pkg/dist/modes/interactive/theme/theme.js +105 -1
- package/pkg/dist/modes/interactive/theme/theme.js.map +1 -1
- package/pkg/dist/modes/interactive/theme/themes.d.ts.map +1 -1
- package/pkg/dist/modes/interactive/theme/themes.js +27 -26
- package/pkg/dist/modes/interactive/theme/themes.js.map +1 -1
- package/pkg/package.json +1 -1
- package/src/resources/extensions/browser-tools/tools/screenshot.ts +1 -0
- package/src/resources/extensions/browser-tools/tools/zoom.ts +1 -0
- package/src/resources/extensions/gsd/auto/contracts.ts +46 -11
- package/src/resources/extensions/gsd/auto/loop-deps.ts +9 -5
- package/src/resources/extensions/gsd/auto/loop.ts +113 -9
- package/src/resources/extensions/gsd/auto/orchestrator.ts +118 -6
- package/src/resources/extensions/gsd/auto/phases.ts +158 -19
- package/src/resources/extensions/gsd/auto/run-unit.ts +69 -4
- package/src/resources/extensions/gsd/auto/session.ts +10 -0
- package/src/resources/extensions/gsd/auto/verification-retry-policy.ts +82 -0
- package/src/resources/extensions/gsd/auto-dashboard.ts +230 -183
- package/src/resources/extensions/gsd/auto-dispatch.ts +15 -1
- package/src/resources/extensions/gsd/auto-post-unit.ts +7 -1
- package/src/resources/extensions/gsd/auto-prompts.ts +11 -3
- package/src/resources/extensions/gsd/auto-recovery.ts +7 -209
- package/src/resources/extensions/gsd/auto-runtime-state.ts +5 -0
- package/src/resources/extensions/gsd/auto-start.ts +22 -22
- package/src/resources/extensions/gsd/auto-unit-closeout.ts +51 -0
- package/src/resources/extensions/gsd/auto-verification.ts +12 -6
- package/src/resources/extensions/gsd/auto-worktree.ts +8 -0
- package/src/resources/extensions/gsd/auto.ts +411 -106
- package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +21 -6
- package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +12 -2
- package/src/resources/extensions/gsd/bootstrap/register-shortcuts.ts +5 -8
- package/src/resources/extensions/gsd/bootstrap/system-context.ts +58 -15
- package/src/resources/extensions/gsd/commands/handlers/core.ts +1 -1
- package/src/resources/extensions/gsd/commands/handlers/notifications-handler.ts +4 -10
- package/src/resources/extensions/gsd/commands/handlers/parallel.ts +12 -0
- package/src/resources/extensions/gsd/commands-handlers.ts +19 -2
- package/src/resources/extensions/gsd/context-store.ts +120 -1
- package/src/resources/extensions/gsd/db-writer.ts +167 -84
- package/src/resources/extensions/gsd/docs/preferences-reference.md +1 -1
- package/src/resources/extensions/gsd/doctor-git-checks.ts +44 -6
- package/src/resources/extensions/gsd/doctor-types.ts +2 -0
- package/src/resources/extensions/gsd/git-service.ts +2 -0
- package/src/resources/extensions/gsd/gsd-db.ts +7 -23
- package/src/resources/extensions/gsd/health-widget-core.ts +1 -1
- package/src/resources/extensions/gsd/health-widget.ts +6 -10
- package/src/resources/extensions/gsd/journal.ts +2 -0
- package/src/resources/extensions/gsd/knowledge-backfill.ts +164 -0
- package/src/resources/extensions/gsd/knowledge-capture.ts +160 -0
- package/src/resources/extensions/gsd/knowledge-parser.ts +174 -0
- package/src/resources/extensions/gsd/knowledge-projection.ts +241 -0
- package/src/resources/extensions/gsd/markdown-renderer.ts +10 -96
- package/src/resources/extensions/gsd/md-importer.ts +1 -1
- package/src/resources/extensions/gsd/memory-backfill.ts +89 -17
- package/src/resources/extensions/gsd/memory-consolidation-scanner.ts +277 -0
- package/src/resources/extensions/gsd/migrate/command.ts +5 -0
- package/src/resources/extensions/gsd/migrate/preview.ts +10 -0
- package/src/resources/extensions/gsd/migrate/transformer.ts +58 -4
- package/src/resources/extensions/gsd/migrate/writer.ts +14 -1
- package/src/resources/extensions/gsd/native-git-bridge.ts +14 -13
- package/src/resources/extensions/gsd/notification-overlay.ts +50 -46
- package/src/resources/extensions/gsd/parallel-merge.ts +61 -34
- package/src/resources/extensions/gsd/parallel-monitor-overlay.ts +33 -35
- package/src/resources/extensions/gsd/prompts/complete-slice.md +14 -12
- package/src/resources/extensions/gsd/prompts/discuss-headless.md +20 -2
- package/src/resources/extensions/gsd/prompts/discuss.md +20 -2
- package/src/resources/extensions/gsd/prompts/system.md +2 -2
- package/src/resources/extensions/gsd/provider-switch-observer.ts +185 -0
- package/src/resources/extensions/gsd/recovery-classification.ts +18 -1
- package/src/resources/extensions/gsd/session-lock.ts +41 -0
- package/src/resources/extensions/gsd/state-reconciliation/drift/completion.ts +172 -0
- package/src/resources/extensions/gsd/state-reconciliation/drift/merge-state.ts +337 -0
- package/src/resources/extensions/gsd/state-reconciliation/drift/project-md.ts +69 -0
- package/src/resources/extensions/gsd/state-reconciliation/drift/roadmap.ts +109 -0
- package/src/resources/extensions/gsd/state-reconciliation/drift/sketch-flag.ts +68 -0
- package/src/resources/extensions/gsd/state-reconciliation/drift/stale-render.ts +185 -0
- package/src/resources/extensions/gsd/state-reconciliation/drift/stale-worker.ts +46 -0
- package/src/resources/extensions/gsd/state-reconciliation/errors.ts +67 -0
- package/src/resources/extensions/gsd/state-reconciliation/index.ts +142 -0
- package/src/resources/extensions/gsd/state-reconciliation/registry.ts +27 -0
- package/src/resources/extensions/gsd/state-reconciliation/spawn-gate.ts +60 -0
- package/src/resources/extensions/gsd/state-reconciliation/types.ts +83 -0
- package/src/resources/extensions/gsd/state-reconciliation.ts +21 -53
- package/src/resources/extensions/gsd/templates/knowledge.md +2 -2
- package/src/resources/extensions/gsd/tests/artifact-retry-cap.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/auto-dashboard.test.ts +99 -0
- package/src/resources/extensions/gsd/tests/auto-loop.test.ts +729 -176
- package/src/resources/extensions/gsd/tests/auto-orchestrator.test.ts +408 -4
- package/src/resources/extensions/gsd/tests/auto-paused-ui-cleanup.test.ts +292 -4
- package/src/resources/extensions/gsd/tests/auto-runtime-state.test.ts +20 -5
- package/src/resources/extensions/gsd/tests/auto-start-orphan-bootstrap.test.ts +18 -0
- package/src/resources/extensions/gsd/tests/auto-unit-closeout.test.ts +68 -0
- package/src/resources/extensions/gsd/tests/browser-tools-compatibility-declarations.test.ts +62 -0
- package/src/resources/extensions/gsd/tests/context-store-decisions-from-memories.test.ts +312 -0
- package/src/resources/extensions/gsd/tests/custom-engine-loop-integration.test.ts +28 -1
- package/src/resources/extensions/gsd/tests/db-writer.test.ts +13 -8
- package/src/resources/extensions/gsd/tests/decisions-projection-from-memories.test.ts +453 -0
- package/src/resources/extensions/gsd/tests/decisions-stop-table-writes.test.ts +348 -0
- package/src/resources/extensions/gsd/tests/deep-project-auto-loop.test.ts +20 -2
- package/src/resources/extensions/gsd/tests/dispatch-complete-milestone-guard.test.ts +44 -0
- package/src/resources/extensions/gsd/tests/freeform-decisions.test.ts +8 -4
- package/src/resources/extensions/gsd/tests/gsd-tools.test.ts +11 -7
- package/src/resources/extensions/gsd/tests/header-renderer.test.ts +40 -0
- package/src/resources/extensions/gsd/tests/headless-milestone-parity.test.ts +10 -0
- package/src/resources/extensions/gsd/tests/health-widget.test.ts +14 -4
- package/src/resources/extensions/gsd/tests/integration/doctor-git.test.ts +44 -0
- package/src/resources/extensions/gsd/tests/integration/git-service.test.ts +26 -0
- package/src/resources/extensions/gsd/tests/integration/integration-lifecycle.test.ts +13 -5
- package/src/resources/extensions/gsd/tests/integration/integration-proof.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/integration/migrate-command.test.ts +48 -3
- package/src/resources/extensions/gsd/tests/integration/parallel-merge.test.ts +116 -24
- package/src/resources/extensions/gsd/tests/journal-integration.test.ts +0 -1
- package/src/resources/extensions/gsd/tests/knowledge-backfill-projection.test.ts +323 -0
- package/src/resources/extensions/gsd/tests/knowledge-capture.test.ts +242 -0
- package/src/resources/extensions/gsd/tests/knowledge.test.ts +47 -2
- package/src/resources/extensions/gsd/tests/load-knowledge-block-rules-only.test.ts +209 -0
- package/src/resources/extensions/gsd/tests/markdown-renderer.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/memory-consolidation-scanner.test.ts +316 -0
- package/src/resources/extensions/gsd/tests/merge-conflict-stops-loop.test.ts +46 -11
- package/src/resources/extensions/gsd/tests/migrate-transformer.test.ts +5 -1
- package/src/resources/extensions/gsd/tests/migrate-writer-integration.test.ts +6 -1
- package/src/resources/extensions/gsd/tests/notification-overlay.test.ts +78 -41
- package/src/resources/extensions/gsd/tests/notifications-handler.test.ts +44 -0
- package/src/resources/extensions/gsd/tests/originalbase-path-comparison.test.ts +12 -217
- package/src/resources/extensions/gsd/tests/parallel-monitor-overlay.test.ts +38 -6
- package/src/resources/extensions/gsd/tests/plan-milestone-sketch-render.test.ts +157 -0
- package/src/resources/extensions/gsd/tests/post-exec-retry-bypass.test.ts +2 -2
- package/src/resources/extensions/gsd/tests/progressive-planning.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +32 -1
- package/src/resources/extensions/gsd/tests/provider-switch-observer.test.ts +252 -0
- package/src/resources/extensions/gsd/tests/resume-dispatch-worktree.test.ts +7 -3
- package/src/resources/extensions/gsd/tests/runtime-invariant-modules.test.ts +6 -3
- package/src/resources/extensions/gsd/tests/session-start-footer.test.ts +16 -4
- package/src/resources/extensions/gsd/tests/session-switch-abort-misclassification.test.ts +24 -0
- package/src/resources/extensions/gsd/tests/state-corruption-2945.test.ts +71 -58
- package/src/resources/extensions/gsd/tests/state-reconciliation-drift.test.ts +952 -0
- package/src/resources/extensions/gsd/tests/token-tool-gating.test.ts +4 -0
- package/src/resources/extensions/gsd/tests/tui-header-lifecycle.test.ts +121 -1
- package/src/resources/extensions/gsd/tests/tui-render-kit.test.ts +66 -0
- package/src/resources/extensions/gsd/tests/verification-retry-policy.test.ts +83 -0
- package/src/resources/extensions/gsd/tests/workflow-mcp.test.ts +6 -0
- package/src/resources/extensions/gsd/tests/worktree-journal-events.test.ts +158 -58
- package/src/resources/extensions/gsd/tests/worktree-lifecycle.test.ts +597 -118
- package/src/resources/extensions/gsd/tests/worktree-telemetry.test.ts +59 -2
- package/src/resources/extensions/gsd/tests/write-gate-planning-unit.test.ts +18 -0
- package/src/resources/extensions/gsd/tools/workflow-tool-executors.ts +135 -0
- package/src/resources/extensions/gsd/tui/render-kit.ts +109 -0
- package/src/resources/extensions/gsd/watch/header-renderer.ts +121 -79
- package/src/resources/extensions/gsd/watch/splash-palette.ts +11 -0
- package/src/resources/extensions/gsd/workflow-logger.ts +4 -0
- package/src/resources/extensions/gsd/workflow-mcp.ts +2 -2
- package/src/resources/extensions/gsd/worktree-lifecycle.ts +1171 -526
- package/src/resources/extensions/gsd/worktree-telemetry.ts +7 -2
- package/dist/web/standalone/.next/static/chunks/app/page-200592a7f3baf579.js +0 -1
- package/dist/web/standalone/.next/static/chunks/main-app-d3d4c336195465f9.js +0 -1
- package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-ab5a8926e07ec673.js +0 -1
- package/src/resources/extensions/gsd/tests/worktree-resolver.test.ts +0 -1544
- /package/dist/web/standalone/.next/static/{drLMkgfHQ8lzS229_HWYR → Wop3A7KRGyR06H3rla_1-}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{drLMkgfHQ8lzS229_HWYR → Wop3A7KRGyR06H3rla_1-}/_ssgManifest.js +0 -0
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
// ADR-011 #5750: ROADMAP.md renders sketch slices with a `[sketch]` badge.
|
|
2
|
+
//
|
|
3
|
+
// Locks in the visual distinction so an auditor scanning the rendered roadmap
|
|
4
|
+
// can tell which slices are sketches awaiting refine-slice expansion vs which
|
|
5
|
+
// already carry a full plan. Sits alongside `plan-milestone.test.ts` which
|
|
6
|
+
// covers the full-plan render path.
|
|
7
|
+
|
|
8
|
+
import test from "node:test";
|
|
9
|
+
import assert from "node:assert/strict";
|
|
10
|
+
import { mkdtempSync, mkdirSync, rmSync, readFileSync } from "node:fs";
|
|
11
|
+
import { join } from "node:path";
|
|
12
|
+
import { tmpdir } from "node:os";
|
|
13
|
+
|
|
14
|
+
import { openDatabase, closeDatabase } from "../gsd-db.ts";
|
|
15
|
+
import { handlePlanMilestone, type PlanMilestoneParams } from "../tools/plan-milestone.ts";
|
|
16
|
+
|
|
17
|
+
function makeTmpBase(): string {
|
|
18
|
+
const base = mkdtempSync(join(tmpdir(), "gsd-plan-sketch-render-"));
|
|
19
|
+
mkdirSync(join(base, ".gsd", "milestones", "M001"), { recursive: true });
|
|
20
|
+
openDatabase(join(base, ".gsd", "gsd.db"));
|
|
21
|
+
return base;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function cleanup(base: string): void {
|
|
25
|
+
try {
|
|
26
|
+
closeDatabase();
|
|
27
|
+
} catch {
|
|
28
|
+
/* noop */
|
|
29
|
+
}
|
|
30
|
+
try {
|
|
31
|
+
rmSync(base, { recursive: true, force: true });
|
|
32
|
+
} catch {
|
|
33
|
+
/* noop */
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function planMilestoneWithSketches(): PlanMilestoneParams {
|
|
38
|
+
return {
|
|
39
|
+
milestoneId: "M001",
|
|
40
|
+
title: "Progressive Planning Demo",
|
|
41
|
+
vision: "Demonstrate sketch slices in ROADMAP rendering.",
|
|
42
|
+
successCriteria: ["S01 full, S02 sketch", "ROADMAP distinguishes them"],
|
|
43
|
+
keyRisks: [{ risk: "Visual collision", whyItMatters: "Auditors need to spot sketches." }],
|
|
44
|
+
proofStrategy: [{ riskOrUnknown: "Render correctness", retireIn: "S01", whatWillBeProven: "Roadmap shows the badge." }],
|
|
45
|
+
verificationContract: "Contract verification text",
|
|
46
|
+
verificationIntegration: "Integration verification text",
|
|
47
|
+
verificationOperational: "Operational verification text",
|
|
48
|
+
verificationUat: "UAT verification text",
|
|
49
|
+
definitionOfDone: ["Renderer emits badge", "Test asserts it"],
|
|
50
|
+
requirementCoverage: "Covers ADR-011 #5750.",
|
|
51
|
+
boundaryMapMarkdown: "| From | To | Produces | Consumes |\n|------|----|----------|----------|\n| S01 | S02 | scaffold | nothing |",
|
|
52
|
+
slices: [
|
|
53
|
+
{
|
|
54
|
+
sliceId: "S01",
|
|
55
|
+
title: "Fully planned scaffold",
|
|
56
|
+
risk: "medium" as const,
|
|
57
|
+
depends: [],
|
|
58
|
+
demo: "Scaffold is in place.",
|
|
59
|
+
goal: "Lay down the structural foundation.",
|
|
60
|
+
successCriteria: "Scaffold tests pass.",
|
|
61
|
+
proofLevel: "integration" as const,
|
|
62
|
+
integrationClosure: "Downstream slices depend on this scaffold.",
|
|
63
|
+
observabilityImpact: "No new telemetry.",
|
|
64
|
+
// No isSketch flag — defaults to full plan.
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
sliceId: "S02",
|
|
68
|
+
title: "Refinement candidate",
|
|
69
|
+
risk: "low" as const,
|
|
70
|
+
depends: ["S01"],
|
|
71
|
+
demo: "Sketched until S01 ships.",
|
|
72
|
+
goal: "Refine into a full plan after S01 lands.",
|
|
73
|
+
successCriteria: "",
|
|
74
|
+
proofLevel: "",
|
|
75
|
+
integrationClosure: "",
|
|
76
|
+
observabilityImpact: "",
|
|
77
|
+
isSketch: true,
|
|
78
|
+
sketchScope: "Pick up the scaffold from S01 and add the demo behavior. Stay inside the existing module boundaries.",
|
|
79
|
+
},
|
|
80
|
+
],
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
test("ROADMAP renders sketch slices with [sketch] badge and full slices without", async () => {
|
|
85
|
+
const base = makeTmpBase();
|
|
86
|
+
try {
|
|
87
|
+
const params = planMilestoneWithSketches();
|
|
88
|
+
const result = await handlePlanMilestone(params, base);
|
|
89
|
+
if ("error" in result) {
|
|
90
|
+
assert.fail(`handlePlanMilestone failed: ${result.error}`);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
const roadmapPath = join(base, ".gsd", "milestones", "M001", "M001-ROADMAP.md");
|
|
94
|
+
const roadmap = readFileSync(roadmapPath, "utf-8");
|
|
95
|
+
|
|
96
|
+
// S01 is a full slice — no sketch badge.
|
|
97
|
+
const s01Line = roadmap.split("\n").find((line) => line.includes("**S01:"));
|
|
98
|
+
assert.ok(s01Line, "S01 slice line must exist in roadmap");
|
|
99
|
+
assert.equal(
|
|
100
|
+
s01Line.includes("`[sketch]`"),
|
|
101
|
+
false,
|
|
102
|
+
"fully-planned S01 must NOT carry the sketch badge",
|
|
103
|
+
);
|
|
104
|
+
assert.match(s01Line, /`risk:medium`/);
|
|
105
|
+
|
|
106
|
+
// S02 is a sketch — badge required, positioned before risk.
|
|
107
|
+
const s02Line = roadmap.split("\n").find((line) => line.includes("**S02:"));
|
|
108
|
+
assert.ok(s02Line, "S02 slice line must exist in roadmap");
|
|
109
|
+
assert.ok(
|
|
110
|
+
s02Line.includes("`[sketch]`"),
|
|
111
|
+
`sketch slice S02 must carry the sketch badge, got: ${s02Line}`,
|
|
112
|
+
);
|
|
113
|
+
// Badge sits before risk so it stays visible if the line truncates.
|
|
114
|
+
const sketchIdx = s02Line.indexOf("`[sketch]`");
|
|
115
|
+
const riskIdx = s02Line.indexOf("`risk:");
|
|
116
|
+
assert.ok(
|
|
117
|
+
sketchIdx >= 0 && riskIdx >= 0 && sketchIdx < riskIdx,
|
|
118
|
+
"sketch badge must appear before the risk tag",
|
|
119
|
+
);
|
|
120
|
+
} finally {
|
|
121
|
+
cleanup(base);
|
|
122
|
+
}
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
test("ROADMAP omits sketch badge when no slices are sketches", async () => {
|
|
126
|
+
const base = makeTmpBase();
|
|
127
|
+
try {
|
|
128
|
+
const params = planMilestoneWithSketches();
|
|
129
|
+
// Strip the sketch designation from S02 so both slices are fully planned.
|
|
130
|
+
params.slices[1] = {
|
|
131
|
+
...params.slices[1],
|
|
132
|
+
isSketch: false,
|
|
133
|
+
successCriteria: "Demo behavior works.",
|
|
134
|
+
proofLevel: "unit" as const,
|
|
135
|
+
integrationClosure: "S02 closes the demo behavior.",
|
|
136
|
+
observabilityImpact: "No new telemetry.",
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
const result = await handlePlanMilestone(params, base);
|
|
140
|
+
if ("error" in result) {
|
|
141
|
+
assert.fail(`handlePlanMilestone failed: ${result.error}`);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
const roadmap = readFileSync(
|
|
145
|
+
join(base, ".gsd", "milestones", "M001", "M001-ROADMAP.md"),
|
|
146
|
+
"utf-8",
|
|
147
|
+
);
|
|
148
|
+
|
|
149
|
+
assert.equal(
|
|
150
|
+
roadmap.includes("`[sketch]`"),
|
|
151
|
+
false,
|
|
152
|
+
"roadmap must not carry the sketch badge when no slice is a sketch",
|
|
153
|
+
);
|
|
154
|
+
} finally {
|
|
155
|
+
cleanup(base);
|
|
156
|
+
}
|
|
157
|
+
});
|
|
@@ -250,14 +250,14 @@ describe("Post-execution blocking failure retry bypass", () => {
|
|
|
250
250
|
const s = makeMockSession(tempDir, { type: "execute-task", id: "M001/S01/T01" });
|
|
251
251
|
|
|
252
252
|
// Pre-set some retry state
|
|
253
|
-
s.verificationRetryCount.set("M001/S01/T01", 2);
|
|
253
|
+
s.verificationRetryCount.set("execute-task:M001/S01/T01", 2);
|
|
254
254
|
|
|
255
255
|
const vctx: VerificationContext = { s, ctx, pi };
|
|
256
256
|
const result = await runPostUnitVerification(vctx, pauseAutoMock);
|
|
257
257
|
|
|
258
258
|
// On success, retry count should be cleared
|
|
259
259
|
assert.equal(result, "continue");
|
|
260
|
-
assert.equal(s.verificationRetryCount.has("M001/S01/T01"), false);
|
|
260
|
+
assert.equal(s.verificationRetryCount.has("execute-task:M001/S01/T01"), false);
|
|
261
261
|
});
|
|
262
262
|
|
|
263
263
|
test("post-exec failure notification mentions cross-task consistency", async () => {
|
|
@@ -14,9 +14,9 @@ import {
|
|
|
14
14
|
insertMilestone,
|
|
15
15
|
insertSlice,
|
|
16
16
|
setSliceSketchFlag,
|
|
17
|
-
autoHealSketchFlags,
|
|
18
17
|
getSlice,
|
|
19
18
|
} from "../gsd-db.ts";
|
|
19
|
+
import { autoHealSketchFlags } from "../state-reconciliation/drift/sketch-flag.ts";
|
|
20
20
|
import { deriveStateFromDb } from "../state.ts";
|
|
21
21
|
import { resolveDispatch } from "../auto-dispatch.ts";
|
|
22
22
|
import type { DispatchContext } from "../auto-dispatch.ts";
|
|
@@ -55,6 +55,14 @@ test("system prompt hard rules forbid fabricating user responses", () => {
|
|
|
55
55
|
assert.match(prompt, /ask_user_questions.*only valid structured user input/i);
|
|
56
56
|
});
|
|
57
57
|
|
|
58
|
+
test("system prompt requires reading before edit or overwrite", () => {
|
|
59
|
+
const prompt = readPrompt("system");
|
|
60
|
+
assert.match(prompt, /Read before edit or overwrite/i);
|
|
61
|
+
assert.match(prompt, /Before any write that creates or replaces a file/i);
|
|
62
|
+
assert.match(prompt, /confirm whether the path exists; if it does, `read` it first/i);
|
|
63
|
+
assert.match(prompt, /For truly new files, confirm the path does not already exist/i);
|
|
64
|
+
});
|
|
65
|
+
|
|
58
66
|
test("discuss prompt allows implementation questions when they materially matter", () => {
|
|
59
67
|
const prompt = readPrompt("discuss");
|
|
60
68
|
assert.match(prompt, /Lead with experience, but ask implementation when it materially matters/i);
|
|
@@ -64,6 +72,16 @@ test("discuss prompt allows implementation questions when they materially matter
|
|
|
64
72
|
assert.doesNotMatch(prompt, /Questions must be about the experience, not the implementation/i);
|
|
65
73
|
});
|
|
66
74
|
|
|
75
|
+
test("discuss prompt ends milestone planning with next-step handoff", () => {
|
|
76
|
+
const prompt = readPrompt("discuss");
|
|
77
|
+
assert.match(prompt, /Next steps:/);
|
|
78
|
+
assert.match(prompt, /\/gsd auto/);
|
|
79
|
+
assert.match(prompt, /\/gsd status/);
|
|
80
|
+
assert.match(prompt, /\/gsd visualize/);
|
|
81
|
+
assert.match(prompt, /\/gsd notifications/);
|
|
82
|
+
assert.doesNotMatch(prompt, /nothing else\. Auto-mode will start automatically/);
|
|
83
|
+
});
|
|
84
|
+
|
|
67
85
|
test("guided discussion prompts avoid wrap-up prompts after every round", () => {
|
|
68
86
|
const milestonePrompt = readPrompt("guided-discuss-milestone");
|
|
69
87
|
const slicePrompt = readPrompt("guided-discuss-slice");
|
|
@@ -217,6 +235,17 @@ test("complete-slice prompt does not instruct LLM to toggle checkboxes manually"
|
|
|
217
235
|
assert.doesNotMatch(prompt, /change \[ \] to \[x\]/);
|
|
218
236
|
});
|
|
219
237
|
|
|
238
|
+
test("complete-slice prompt keeps source fixes in execution units", () => {
|
|
239
|
+
const prompt = readPrompt("complete-slice");
|
|
240
|
+
assert.match(prompt, /Do not use direct `bash` for verification commands/i);
|
|
241
|
+
assert.match(prompt, /do \*\*not\*\* edit source files in this unit/i);
|
|
242
|
+
assert.match(prompt, /do \*\*not\*\* call `gsd_slice_complete`/i);
|
|
243
|
+
assert.match(prompt, /gsd_task_reopen/);
|
|
244
|
+
assert.match(prompt, /gsd_replan_slice/);
|
|
245
|
+
assert.match(prompt, /needs execution follow-up/i);
|
|
246
|
+
assert.doesNotMatch(prompt, /Fix failures before marking done/i);
|
|
247
|
+
});
|
|
248
|
+
|
|
220
249
|
test("complete-slice prompt instructs writing summary and UAT files before tool call", () => {
|
|
221
250
|
const prompt = readPrompt("complete-slice");
|
|
222
251
|
assert.match(prompt, /\{\{sliceSummaryPath\}\}/);
|
|
@@ -363,7 +392,9 @@ test("execute-task prompt uses camelCase parameter names matching TypeBox schema
|
|
|
363
392
|
test("complete-slice prompt uses camelCase parameter names matching TypeBox schema", () => {
|
|
364
393
|
const prompt = readPrompt("complete-slice");
|
|
365
394
|
// The gsd_complete_slice tool schema uses camelCase: milestoneId, sliceId
|
|
366
|
-
const toolCallLine = prompt.split("\n").find((l) =>
|
|
395
|
+
const toolCallLine = prompt.split("\n").find((l) =>
|
|
396
|
+
(/gsd_complete_slice/.test(l) || /gsd_slice_complete/.test(l)) && /milestoneId/.test(l) && /sliceId/.test(l)
|
|
397
|
+
);
|
|
367
398
|
assert.ok(toolCallLine, "prompt must contain a gsd_complete_slice or gsd_slice_complete tool call line");
|
|
368
399
|
assert.doesNotMatch(toolCallLine!, /milestone_id/, "must use milestoneId, not milestone_id");
|
|
369
400
|
assert.doesNotMatch(toolCallLine!, /slice_id/, "must use sliceId, not slice_id");
|
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
// GSD-2 — ADR-005 Phase 3b: ProviderSwitchObserver Tests
|
|
2
|
+
import test from "node:test";
|
|
3
|
+
import assert from "node:assert/strict";
|
|
4
|
+
import { mkdtempSync, readFileSync, rmSync, existsSync } from "node:fs";
|
|
5
|
+
import { join } from "node:path";
|
|
6
|
+
import { tmpdir } from "node:os";
|
|
7
|
+
|
|
8
|
+
import { setProviderSwitchObserver, type ProviderSwitchReport } from "@gsd/pi-ai";
|
|
9
|
+
|
|
10
|
+
import { autoSession } from "../auto-runtime-state.ts";
|
|
11
|
+
import {
|
|
12
|
+
initNotificationStore,
|
|
13
|
+
readNotifications,
|
|
14
|
+
_resetNotificationStore,
|
|
15
|
+
} from "../notification-store.ts";
|
|
16
|
+
import {
|
|
17
|
+
_resetProviderSwitchStats,
|
|
18
|
+
getProviderSwitchStats,
|
|
19
|
+
installProviderSwitchObserver,
|
|
20
|
+
uninstallProviderSwitchObserver,
|
|
21
|
+
} from "../provider-switch-observer.ts";
|
|
22
|
+
|
|
23
|
+
function makeReport(overrides: Partial<ProviderSwitchReport> = {}): ProviderSwitchReport {
|
|
24
|
+
return {
|
|
25
|
+
fromApi: "anthropic-messages",
|
|
26
|
+
toApi: "openai-responses",
|
|
27
|
+
thinkingBlocksDropped: 0,
|
|
28
|
+
thinkingBlocksDowngraded: 0,
|
|
29
|
+
toolCallIdsRemapped: 0,
|
|
30
|
+
syntheticToolResultsInserted: 0,
|
|
31
|
+
thoughtSignaturesDropped: 0,
|
|
32
|
+
...overrides,
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function withTempBasePath(): { basePath: string; cleanup: () => void } {
|
|
37
|
+
const basePath = mkdtempSync(join(tmpdir(), "gsd-provider-switch-"));
|
|
38
|
+
return {
|
|
39
|
+
basePath,
|
|
40
|
+
cleanup: () => rmSync(basePath, { recursive: true, force: true }),
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
test.beforeEach(() => {
|
|
45
|
+
_resetProviderSwitchStats();
|
|
46
|
+
_resetNotificationStore();
|
|
47
|
+
autoSession.currentTraceId = null;
|
|
48
|
+
autoSession.basePath = "";
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
test.afterEach(() => {
|
|
52
|
+
uninstallProviderSwitchObserver();
|
|
53
|
+
_resetNotificationStore();
|
|
54
|
+
autoSession.currentTraceId = null;
|
|
55
|
+
autoSession.basePath = "";
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
test("installProviderSwitchObserver wires the pi-ai observer hook", () => {
|
|
59
|
+
installProviderSwitchObserver();
|
|
60
|
+
// Indirect: a second install is a no-op. We verify by checking the counter
|
|
61
|
+
// increments exactly once when we fire a single report directly into pi-ai's
|
|
62
|
+
// observer slot.
|
|
63
|
+
installProviderSwitchObserver();
|
|
64
|
+
|
|
65
|
+
// Drive the pi-ai observer directly. The install above pointed it at our
|
|
66
|
+
// handler; firing here exercises the same code path as a real transform.
|
|
67
|
+
// We can't reach the installed handler reference from here, so we re-install
|
|
68
|
+
// a sentinel and confirm setProviderSwitchObserver accepts undefined.
|
|
69
|
+
setProviderSwitchObserver(undefined);
|
|
70
|
+
assert.ok(true); // install/uninstall did not throw
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
test("non-empty report increments the in-memory counter", () => {
|
|
74
|
+
installProviderSwitchObserver();
|
|
75
|
+
|
|
76
|
+
// Reach into the installed handler via setProviderSwitchObserver re-binding.
|
|
77
|
+
// We snapshot the handler by re-installing, capturing nothing — instead we
|
|
78
|
+
// use the public API: drive a report through the observer hook directly by
|
|
79
|
+
// calling setProviderSwitchObserver with a wrapper that proxies into the
|
|
80
|
+
// installed handler. This is awkward without a separate seam, so we test
|
|
81
|
+
// the recordReport path end-to-end by firing through pi-ai's transform helper
|
|
82
|
+
// pattern in a sibling test below. Here we exercise install idempotency only.
|
|
83
|
+
|
|
84
|
+
// Fire by setting our own observer that forwards to the module API isn't
|
|
85
|
+
// possible without exporting handleReport. Instead, verify install state
|
|
86
|
+
// doesn't crash; the real fire path is covered by the integration test
|
|
87
|
+
// below that exercises transformMessagesWithReport.
|
|
88
|
+
assert.deepEqual(getProviderSwitchStats().totalSwitches, 0);
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
test("end-to-end: transformMessagesWithReport fires the observer and updates stats + notifications", async () => {
|
|
92
|
+
const { transformMessagesWithReport } = await import("@gsd/pi-ai");
|
|
93
|
+
|
|
94
|
+
const { basePath, cleanup } = withTempBasePath();
|
|
95
|
+
try {
|
|
96
|
+
initNotificationStore(basePath);
|
|
97
|
+
installProviderSwitchObserver();
|
|
98
|
+
|
|
99
|
+
// Construct a cross-API transform that will drop a redacted thinking block.
|
|
100
|
+
const targetModel = {
|
|
101
|
+
id: "gpt-5",
|
|
102
|
+
name: "GPT-5",
|
|
103
|
+
api: "openai-responses",
|
|
104
|
+
provider: "openai",
|
|
105
|
+
baseUrl: "",
|
|
106
|
+
reasoning: false,
|
|
107
|
+
input: ["text"],
|
|
108
|
+
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
|
|
109
|
+
contextWindow: 128000,
|
|
110
|
+
maxTokens: 8192,
|
|
111
|
+
} as Parameters<typeof transformMessagesWithReport>[1];
|
|
112
|
+
|
|
113
|
+
const messages = [
|
|
114
|
+
{
|
|
115
|
+
role: "assistant" as const,
|
|
116
|
+
content: [
|
|
117
|
+
{ type: "thinking" as const, thinking: "", redacted: true },
|
|
118
|
+
{ type: "text" as const, text: "hi" },
|
|
119
|
+
],
|
|
120
|
+
api: "anthropic-messages",
|
|
121
|
+
provider: "anthropic",
|
|
122
|
+
model: "claude-sonnet-4-6",
|
|
123
|
+
usage: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, totalTokens: 0, cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 } },
|
|
124
|
+
stopReason: "stop" as const,
|
|
125
|
+
timestamp: Date.now(),
|
|
126
|
+
},
|
|
127
|
+
];
|
|
128
|
+
|
|
129
|
+
transformMessagesWithReport(messages as Parameters<typeof transformMessagesWithReport>[0], targetModel, undefined, "anthropic-messages");
|
|
130
|
+
|
|
131
|
+
const stats = getProviderSwitchStats();
|
|
132
|
+
assert.equal(stats.totalSwitches, 1, "non-empty report should bump the counter");
|
|
133
|
+
assert.ok(stats.totals.thinkingBlocksDropped >= 1, "thinking block drop should be tallied");
|
|
134
|
+
assert.ok(stats.lastReport, "last report should be retained");
|
|
135
|
+
assert.equal(stats.lastReport?.fromApi, "anthropic-messages");
|
|
136
|
+
assert.equal(stats.lastReport?.toApi, "openai-responses");
|
|
137
|
+
|
|
138
|
+
// Notification persistence — the observer is interactive (no traceId), so
|
|
139
|
+
// the byTrace key falls back to "interactive".
|
|
140
|
+
assert.ok("interactive" in stats.byTrace, "interactive trace bucket should exist");
|
|
141
|
+
assert.equal(stats.byTrace.interactive?.switches, 1);
|
|
142
|
+
|
|
143
|
+
const notifications = readNotifications(basePath);
|
|
144
|
+
const switchNotifs = notifications.filter((n) => n.message.includes("Provider switch"));
|
|
145
|
+
assert.ok(switchNotifs.length >= 1, "a provider-switch notification should be persisted");
|
|
146
|
+
assert.equal(switchNotifs[0]?.severity, "warning");
|
|
147
|
+
} finally {
|
|
148
|
+
cleanup();
|
|
149
|
+
}
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
test("end-to-end: audit event is emitted when an auto trace is active", async () => {
|
|
153
|
+
const { transformMessagesWithReport } = await import("@gsd/pi-ai");
|
|
154
|
+
|
|
155
|
+
const { basePath, cleanup } = withTempBasePath();
|
|
156
|
+
try {
|
|
157
|
+
initNotificationStore(basePath);
|
|
158
|
+
installProviderSwitchObserver();
|
|
159
|
+
autoSession.basePath = basePath;
|
|
160
|
+
autoSession.currentTraceId = "trace-provider-switch-1";
|
|
161
|
+
|
|
162
|
+
const targetModel = {
|
|
163
|
+
id: "gpt-5",
|
|
164
|
+
name: "GPT-5",
|
|
165
|
+
api: "openai-responses",
|
|
166
|
+
provider: "openai",
|
|
167
|
+
baseUrl: "",
|
|
168
|
+
reasoning: false,
|
|
169
|
+
input: ["text"],
|
|
170
|
+
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
|
|
171
|
+
contextWindow: 128000,
|
|
172
|
+
maxTokens: 8192,
|
|
173
|
+
} as Parameters<typeof transformMessagesWithReport>[1];
|
|
174
|
+
|
|
175
|
+
const messages = [
|
|
176
|
+
{
|
|
177
|
+
role: "assistant" as const,
|
|
178
|
+
content: [
|
|
179
|
+
{ type: "thinking" as const, thinking: "", redacted: true },
|
|
180
|
+
{ type: "text" as const, text: "hi" },
|
|
181
|
+
],
|
|
182
|
+
api: "anthropic-messages",
|
|
183
|
+
provider: "anthropic",
|
|
184
|
+
model: "claude-sonnet-4-6",
|
|
185
|
+
usage: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, totalTokens: 0, cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 } },
|
|
186
|
+
stopReason: "stop" as const,
|
|
187
|
+
timestamp: Date.now(),
|
|
188
|
+
},
|
|
189
|
+
];
|
|
190
|
+
|
|
191
|
+
transformMessagesWithReport(messages as Parameters<typeof transformMessagesWithReport>[0], targetModel, undefined, "anthropic-messages");
|
|
192
|
+
|
|
193
|
+
const auditLogPath = join(basePath, ".gsd", "audit", "events.jsonl");
|
|
194
|
+
assert.ok(existsSync(auditLogPath), "audit events file should be created");
|
|
195
|
+
const auditLines = readFileSync(auditLogPath, "utf-8")
|
|
196
|
+
.trim()
|
|
197
|
+
.split("\n")
|
|
198
|
+
.map((line) => JSON.parse(line) as { category: string; type: string; traceId: string; payload: Record<string, unknown> });
|
|
199
|
+
const switchEvent = auditLines.find((e) => e.category === "model-policy" && e.type === "provider-switch");
|
|
200
|
+
assert.ok(switchEvent, "a model-policy/provider-switch audit event should be present");
|
|
201
|
+
assert.equal(switchEvent?.traceId, "trace-provider-switch-1");
|
|
202
|
+
assert.equal(switchEvent?.payload.fromApi, "anthropic-messages");
|
|
203
|
+
assert.equal(switchEvent?.payload.toApi, "openai-responses");
|
|
204
|
+
|
|
205
|
+
const stats = getProviderSwitchStats();
|
|
206
|
+
assert.ok("trace-provider-switch-1" in stats.byTrace, "trace-keyed bucket should be populated");
|
|
207
|
+
assert.equal(stats.byTrace["trace-provider-switch-1"]?.switches, 1);
|
|
208
|
+
} finally {
|
|
209
|
+
cleanup();
|
|
210
|
+
}
|
|
211
|
+
});
|
|
212
|
+
|
|
213
|
+
test("empty report does not bump counter or emit a notification", async () => {
|
|
214
|
+
const { transformMessagesWithReport } = await import("@gsd/pi-ai");
|
|
215
|
+
|
|
216
|
+
const { basePath, cleanup } = withTempBasePath();
|
|
217
|
+
try {
|
|
218
|
+
initNotificationStore(basePath);
|
|
219
|
+
installProviderSwitchObserver();
|
|
220
|
+
|
|
221
|
+
// Same-API transform → no transformations → empty report.
|
|
222
|
+
const sameApiModel = {
|
|
223
|
+
id: "claude-sonnet-4-6",
|
|
224
|
+
name: "Claude Sonnet 4.6",
|
|
225
|
+
api: "anthropic-messages",
|
|
226
|
+
provider: "anthropic",
|
|
227
|
+
baseUrl: "",
|
|
228
|
+
reasoning: false,
|
|
229
|
+
input: ["text"],
|
|
230
|
+
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
|
|
231
|
+
contextWindow: 200000,
|
|
232
|
+
maxTokens: 8192,
|
|
233
|
+
} as Parameters<typeof transformMessagesWithReport>[1];
|
|
234
|
+
|
|
235
|
+
transformMessagesWithReport(
|
|
236
|
+
[
|
|
237
|
+
{
|
|
238
|
+
role: "user" as const,
|
|
239
|
+
content: "plain text — no transforms triggered",
|
|
240
|
+
},
|
|
241
|
+
] as Parameters<typeof transformMessagesWithReport>[0],
|
|
242
|
+
sameApiModel,
|
|
243
|
+
undefined,
|
|
244
|
+
"anthropic-messages",
|
|
245
|
+
);
|
|
246
|
+
|
|
247
|
+
assert.equal(getProviderSwitchStats().totalSwitches, 0);
|
|
248
|
+
assert.equal(readNotifications(basePath).length, 0);
|
|
249
|
+
} finally {
|
|
250
|
+
cleanup();
|
|
251
|
+
}
|
|
252
|
+
});
|
|
@@ -10,7 +10,11 @@ import { join } from "node:path";
|
|
|
10
10
|
import { tmpdir } from "node:os";
|
|
11
11
|
import { randomUUID } from "node:crypto";
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
// ADR-016 phase 2 / B3 (#5621): the legacy `resolvePausedResumeBasePath`
|
|
14
|
+
// helper was retired and folded into `WorktreeLifecycle.resumeFromPausedSession`.
|
|
15
|
+
// The pure path-resolution function lives in `worktree-lifecycle.ts` for tests
|
|
16
|
+
// that exercise the path-resolution invariant without constructing a session.
|
|
17
|
+
import { resolvePausedResumeBasePath } from "../worktree-lifecycle.ts";
|
|
14
18
|
|
|
15
19
|
function makeTmpBase(): string {
|
|
16
20
|
const base = join(tmpdir(), `gsd-resume-wt-${randomUUID()}`);
|
|
@@ -59,7 +63,7 @@ test("resume base path uses paused-session worktreePath when the worktree exists
|
|
|
59
63
|
try {
|
|
60
64
|
setupWorktreeOnDisk(wt);
|
|
61
65
|
assert.equal(
|
|
62
|
-
|
|
66
|
+
resolvePausedResumeBasePath(base, wt),
|
|
63
67
|
wt,
|
|
64
68
|
);
|
|
65
69
|
} finally {
|
|
@@ -72,7 +76,7 @@ test("resume base path falls back to project root when paused worktree is missin
|
|
|
72
76
|
const wt = makeWorktreePath(base, "M001-test");
|
|
73
77
|
try {
|
|
74
78
|
assert.equal(
|
|
75
|
-
|
|
79
|
+
resolvePausedResumeBasePath(base, wt),
|
|
76
80
|
base,
|
|
77
81
|
);
|
|
78
82
|
} finally {
|
|
@@ -42,16 +42,19 @@ test("State Reconciliation invalidates cache and returns reconciled state", asyn
|
|
|
42
42
|
assert.equal(result.ok && result.stateSnapshot, state);
|
|
43
43
|
});
|
|
44
44
|
|
|
45
|
-
test("State Reconciliation
|
|
45
|
+
test("State Reconciliation surfaces terminal blockers in result (ADR-017)", async () => {
|
|
46
|
+
// Under ADR-017, blockers are terminal but do not throw — they ride along
|
|
47
|
+
// in the result so the orchestrator adapter can map them to ok=false.
|
|
46
48
|
const result = await reconcileBeforeDispatch("/project", {
|
|
47
49
|
invalidateStateCache() {},
|
|
48
50
|
async deriveState() {
|
|
49
51
|
return makeState({ phase: "blocked", blockers: ["slice lock missing"] });
|
|
50
52
|
},
|
|
53
|
+
registry: [],
|
|
51
54
|
});
|
|
52
55
|
|
|
53
|
-
assert.equal(result.ok,
|
|
54
|
-
assert.
|
|
56
|
+
assert.equal(result.ok, true);
|
|
57
|
+
assert.deepEqual(result.blockers, ["slice lock missing"]);
|
|
55
58
|
});
|
|
56
59
|
|
|
57
60
|
test("Tool Contract compiles known Unit prompt and tool policy", () => {
|
|
@@ -1,9 +1,11 @@
|
|
|
1
|
+
// Project/App: GSD-2
|
|
2
|
+
// File Purpose: Verifies GSD session hook widget and footer lifecycle behavior.
|
|
3
|
+
|
|
1
4
|
/**
|
|
2
|
-
* session-start-footer.test.ts
|
|
3
|
-
*
|
|
4
5
|
* Verifies that register-hooks.ts suppresses the gsd-health widget (not the
|
|
5
|
-
* built-in footer) when isAutoActive() is true,
|
|
6
|
-
*
|
|
6
|
+
* built-in footer) when isAutoActive() is true, clears stale completion widgets
|
|
7
|
+
* on inactive session switches, and that setFooter is never called by the
|
|
8
|
+
* extension in either session_start or session_switch.
|
|
7
9
|
*
|
|
8
10
|
* Testing strategy:
|
|
9
11
|
* 1. Source-code regression guards: structural checks on register-hooks.ts.
|
|
@@ -139,6 +141,16 @@ test("session_switch toggles gsd-health from runtime auto state without touching
|
|
|
139
141
|
widgetCalls.length = 0;
|
|
140
142
|
autoSession.active = false;
|
|
141
143
|
await sessionSwitch!({ reason: "resume" }, ctx);
|
|
144
|
+
assert.deepEqual(
|
|
145
|
+
widgetCalls
|
|
146
|
+
.filter((call) => call.key === "gsd-progress" || call.key === "gsd-outcome")
|
|
147
|
+
.map((call) => [call.key, call.value]),
|
|
148
|
+
[
|
|
149
|
+
["gsd-progress", undefined],
|
|
150
|
+
["gsd-outcome", undefined],
|
|
151
|
+
],
|
|
152
|
+
"session_switch should clear stale GSD completion widgets when auto is inactive",
|
|
153
|
+
);
|
|
142
154
|
const healthWidgetValues = widgetCalls
|
|
143
155
|
.filter((call) => call.key === "gsd-health")
|
|
144
156
|
.map((call) => call.value);
|
|
@@ -188,6 +188,30 @@ test("empty-content aborted during session-switch is silently ignored", () => {
|
|
|
188
188
|
assert.equal(cancelledWith, null);
|
|
189
189
|
});
|
|
190
190
|
|
|
191
|
+
test("completed assistant content with aborted stopReason during session-switch is ignored", () => {
|
|
192
|
+
// newSession() can abort the just-finished provider stream while the last
|
|
193
|
+
// assistant message still carries the completed unit summary. That is a
|
|
194
|
+
// session-transition artifact, not a cancellation for the next unit.
|
|
195
|
+
let cancelledWith: unknown = null;
|
|
196
|
+
const resolveCancelled = (ctx: ErrorContext) => {
|
|
197
|
+
cancelledWith = ctx;
|
|
198
|
+
return true;
|
|
199
|
+
};
|
|
200
|
+
|
|
201
|
+
_handleSessionSwitchAgentEnd(
|
|
202
|
+
{
|
|
203
|
+
stopReason: "aborted",
|
|
204
|
+
content: [{
|
|
205
|
+
type: "text",
|
|
206
|
+
text: "Implemented T01 and verified the slice task is complete.",
|
|
207
|
+
}],
|
|
208
|
+
},
|
|
209
|
+
resolveCancelled,
|
|
210
|
+
);
|
|
211
|
+
|
|
212
|
+
assert.equal(cancelledWith, null);
|
|
213
|
+
});
|
|
214
|
+
|
|
191
215
|
test("non-abort errors during session-switch are not propagated through this helper", () => {
|
|
192
216
|
// Real provider errors (rate-limit, network, unsupported-model) are handled
|
|
193
217
|
// by the post-switch retry pipeline — not by the in-flight switch handler.
|