gsd-pi 2.50.0 → 2.51.0-dev.ae8f7cb
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 +2 -0
- package/dist/cli.js +26 -0
- package/dist/loader.js +4 -0
- package/dist/resource-loader.d.ts +4 -1
- package/dist/resource-loader.js +138 -3
- package/dist/resources/extensions/async-jobs/async-bash-tool.js +3 -1
- package/dist/resources/extensions/bg-shell/interaction.js +3 -1
- package/dist/resources/extensions/bg-shell/process-manager.js +4 -1
- package/dist/resources/extensions/claude-code-cli/partial-builder.js +5 -0
- package/dist/resources/extensions/gsd/auto/phases.js +16 -1
- package/dist/resources/extensions/gsd/auto/session.js +5 -0
- package/dist/resources/extensions/gsd/auto-dashboard.js +22 -3
- package/dist/resources/extensions/gsd/auto-dispatch.js +81 -54
- package/dist/resources/extensions/gsd/auto-observability.js +54 -0
- package/dist/resources/extensions/gsd/auto-post-unit.js +37 -76
- package/dist/resources/extensions/gsd/auto-prompts.js +57 -0
- package/dist/resources/extensions/gsd/auto-recovery.js +21 -25
- package/dist/resources/extensions/gsd/auto-utils.js +20 -0
- package/dist/resources/extensions/gsd/auto.js +15 -5
- package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +16 -0
- package/dist/resources/extensions/gsd/crash-recovery.js +6 -2
- package/dist/resources/extensions/gsd/custom-execution-policy.js +3 -2
- package/dist/resources/extensions/gsd/custom-verification.js +3 -1
- package/dist/resources/extensions/gsd/custom-workflow-engine.js +3 -2
- package/dist/resources/extensions/gsd/dashboard-overlay.js +4 -0
- package/dist/resources/extensions/gsd/detection.js +589 -3
- package/dist/resources/extensions/gsd/dispatch-guard.js +2 -1
- package/dist/resources/extensions/gsd/docs/preferences-reference.md +15 -0
- package/dist/resources/extensions/gsd/files.js +5 -1
- package/dist/resources/extensions/gsd/guided-flow.js +10 -0
- package/dist/resources/extensions/gsd/init-wizard.js +9 -1
- package/dist/resources/extensions/gsd/model-router.js +25 -0
- package/dist/resources/extensions/gsd/notifications.js +23 -0
- package/dist/resources/extensions/gsd/observability-validator.js +422 -0
- package/dist/resources/extensions/gsd/preferences-skills.js +11 -5
- package/dist/resources/extensions/gsd/preferences-types.js +1 -0
- package/dist/resources/extensions/gsd/preferences-validation.js +25 -0
- package/dist/resources/extensions/gsd/preferences.js +3 -0
- package/dist/resources/extensions/gsd/prompts/forensics.md +11 -7
- package/dist/resources/extensions/gsd/prompts/validate-milestone.md +6 -1
- package/dist/resources/extensions/gsd/provider-error-pause.js +8 -0
- package/dist/resources/extensions/gsd/roadmap-mutations.js +110 -0
- package/dist/resources/extensions/gsd/rtk-status.js +43 -0
- package/dist/resources/extensions/gsd/rule-registry.js +10 -11
- package/dist/resources/extensions/gsd/session-forensics.js +7 -3
- package/dist/resources/extensions/gsd/skill-catalog.js +1026 -0
- package/dist/resources/extensions/gsd/skill-discovery.js +3 -2
- package/dist/resources/extensions/gsd/skill-health.js +2 -2
- package/dist/resources/extensions/gsd/skill-telemetry.js +15 -5
- package/dist/resources/extensions/gsd/state.js +17 -5
- package/dist/resources/extensions/gsd/templates/milestone-validation.md +12 -0
- package/dist/resources/extensions/gsd/templates/preferences.md +2 -0
- package/dist/resources/extensions/gsd/tests/dist-redirect.mjs +28 -9
- package/dist/resources/extensions/gsd/undo.js +8 -7
- package/dist/resources/extensions/gsd/unit-runtime.js +2 -1
- package/dist/resources/extensions/gsd/verification-gate.js +3 -1
- package/dist/resources/extensions/shared/rtk-session-stats.js +189 -0
- package/dist/resources/extensions/shared/rtk.js +100 -0
- package/dist/rtk.d.ts +52 -0
- package/dist/rtk.js +332 -0
- package/dist/web/standalone/.next/BUILD_ID +1 -1
- package/dist/web/standalone/.next/app-path-routes-manifest.json +12 -11
- package/dist/web/standalone/.next/build-manifest.json +4 -4
- package/dist/web/standalone/.next/prerender-manifest.json +3 -3
- package/dist/web/standalone/.next/react-loadable-manifest.json +2 -2
- package/dist/web/standalone/.next/required-server-files.json +3 -3
- package/dist/web/standalone/.next/routes-manifest.json +6 -0
- package/dist/web/standalone/.next/server/app/_global-error/page.js +3 -3
- package/dist/web/standalone/.next/server/app/_global-error/page.js.nft.json +1 -1
- 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 +2 -2
- 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.js.nft.json +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 +4 -4
- package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +4 -4
- 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 +4 -4
- 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 +2 -2
- package/dist/web/standalone/.next/server/app/api/boot/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/boot/route.js.nft.json +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.js.nft.json +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.js.nft.json +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.js.nft.json +1 -1
- 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.js.nft.json +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.js.nft.json +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.js.nft.json +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.js.nft.json +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.js.nft.json +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 +3 -0
- package/dist/web/standalone/.next/server/app/api/experimental/route.js.nft.json +1 -0
- package/dist/web/standalone/.next/server/app/api/experimental/route_client-reference-manifest.js +1 -0
- 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.js.nft.json +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.js.nft.json +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.js.nft.json +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.js.nft.json +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.js.nft.json +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.js.nft.json +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.js.nft.json +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.js.nft.json +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.js.nft.json +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/onboarding/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/onboarding/route.js.nft.json +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.js.nft.json +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.js.nft.json +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.js.nft.json +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 -26
- package/dist/web/standalone/.next/server/app/api/remote-questions/route.js.nft.json +1 -1
- 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.js.nft.json +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.js.nft.json +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.js.nft.json +1 -1
- 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.js.nft.json +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.js.nft.json +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.js.nft.json +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.js.nft.json +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.js.nft.json +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.js.nft.json +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 +2 -2
- package/dist/web/standalone/.next/server/app/api/terminal/input/route.js.nft.json +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.js.nft.json +1 -1
- 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 +2 -2
- package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/sessions/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js +4 -4
- package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js.nft.json +1 -1
- 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.js.nft.json +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.js.nft.json +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.js.nft.json +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.js.nft.json +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 +5 -5
- 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 +5 -5
- 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 +4 -4
- package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +2 -2
- package/dist/web/standalone/.next/server/app/page.js +2 -2
- package/dist/web/standalone/.next/server/app/page.js.nft.json +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 +12 -11
- package/dist/web/standalone/.next/server/chunks/2229.js +12 -0
- package/dist/web/standalone/.next/server/chunks/2331.js +25 -0
- package/dist/web/standalone/.next/server/chunks/{741.js → 4741.js} +1 -1
- package/dist/web/standalone/.next/server/chunks/5822.js +2 -0
- package/dist/web/standalone/.next/server/chunks/7471.js +13 -0
- package/dist/web/standalone/.next/server/functions-config-manifest.json +1 -0
- package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
- package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
- package/dist/web/standalone/.next/server/middleware.js +3 -3
- package/dist/web/standalone/.next/server/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 +2 -2
- package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
- package/dist/web/standalone/.next/server/webpack-runtime.js +1 -1
- package/dist/web/standalone/.next/static/5_KeZz1X0tXJK-d_4OhjB/_buildManifest.js +1 -0
- package/dist/web/standalone/.next/static/chunks/{485.243af25f0cdf50d6.js → 2008.817d0885545aaea9.js} +6 -6
- package/dist/web/standalone/.next/static/chunks/4024.9ad5def014d90ce4.js +9 -0
- package/dist/web/standalone/.next/static/chunks/app/_global-error/page-c4cc189e7b117ea2.js +1 -0
- 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/api/boot/route-c4cc189e7b117ea2.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/bridge-terminal/input/route-c4cc189e7b117ea2.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/bridge-terminal/resize/route-c4cc189e7b117ea2.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/bridge-terminal/stream/route-c4cc189e7b117ea2.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/browse-directories/route-c4cc189e7b117ea2.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/captures/route-c4cc189e7b117ea2.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/cleanup/route-c4cc189e7b117ea2.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/dev-mode/route-c4cc189e7b117ea2.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/doctor/route-c4cc189e7b117ea2.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/experimental/route-c4cc189e7b117ea2.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/export-data/route-c4cc189e7b117ea2.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/files/route-c4cc189e7b117ea2.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/forensics/route-c4cc189e7b117ea2.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/git/route-c4cc189e7b117ea2.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/history/route-c4cc189e7b117ea2.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/hooks/route-c4cc189e7b117ea2.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/inspect/route-c4cc189e7b117ea2.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/knowledge/route-c4cc189e7b117ea2.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/live-state/route-c4cc189e7b117ea2.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/onboarding/route-c4cc189e7b117ea2.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/preferences/route-c4cc189e7b117ea2.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/projects/route-c4cc189e7b117ea2.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/recovery/route-c4cc189e7b117ea2.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/remote-questions/route-c4cc189e7b117ea2.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/session/browser/route-c4cc189e7b117ea2.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/session/command/route-c4cc189e7b117ea2.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/session/events/route-c4cc189e7b117ea2.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/session/manage/route-c4cc189e7b117ea2.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/settings-data/route-c4cc189e7b117ea2.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/shutdown/route-c4cc189e7b117ea2.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/skill-health/route-c4cc189e7b117ea2.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/steer/route-c4cc189e7b117ea2.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/switch-root/route-c4cc189e7b117ea2.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/terminal/input/route-c4cc189e7b117ea2.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/terminal/resize/route-c4cc189e7b117ea2.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/terminal/sessions/route-c4cc189e7b117ea2.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/terminal/stream/route-c4cc189e7b117ea2.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/terminal/upload/route-c4cc189e7b117ea2.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/undo/route-c4cc189e7b117ea2.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/update/route-c4cc189e7b117ea2.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/visualizer/route-c4cc189e7b117ea2.js +1 -0
- 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-b950e4e384cc62b3.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/app-error-c4cc189e7b117ea2.js +1 -0
- package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/forbidden-c4cc189e7b117ea2.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/.next/static/chunks/next/dist/client/components/builtin/not-found-c4cc189e7b117ea2.js +1 -0
- package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/unauthorized-c4cc189e7b117ea2.js +1 -0
- package/dist/web/standalone/.next/static/chunks/webpack-cfc9a116e6450a6b.js +1 -0
- package/dist/web/standalone/.next/static/css/de141508b083f922.css +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/package.json +1 -1
- package/packages/pi-ai/dist/types.d.ts +1 -0
- package/packages/pi-ai/dist/types.d.ts.map +1 -1
- package/packages/pi-ai/dist/types.js.map +1 -1
- package/packages/pi-ai/src/types.ts +1 -1
- package/packages/pi-coding-agent/dist/core/agent-session.d.ts +1 -0
- package/packages/pi-coding-agent/dist/core/agent-session.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/agent-session.js +1 -0
- package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/bash-executor.d.ts +3 -1
- package/packages/pi-coding-agent/dist/core/bash-executor.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/bash-executor.js +10 -1
- package/packages/pi-coding-agent/dist/core/bash-executor.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/index.d.ts +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/index.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/index.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/runner.d.ts +1 -0
- package/packages/pi-coding-agent/dist/core/extensions/runner.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/runner.js +13 -0
- package/packages/pi-coding-agent/dist/core/extensions/runner.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/types.d.ts +19 -1
- package/packages/pi-coding-agent/dist/core/extensions/types.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/types.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/wrapper.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/wrapper.js +8 -0
- package/packages/pi-coding-agent/dist/core/extensions/wrapper.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/package-manager.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/package-manager.js +8 -1
- package/packages/pi-coding-agent/dist/core/package-manager.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/skills.d.ts +11 -1
- package/packages/pi-coding-agent/dist/core/skills.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/skills.js +30 -8
- package/packages/pi-coding-agent/dist/core/skills.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/slash-commands.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/slash-commands.js +1 -0
- package/packages/pi-coding-agent/dist/core/slash-commands.js.map +1 -1
- package/packages/pi-coding-agent/dist/index.d.ts +2 -2
- package/packages/pi-coding-agent/dist/index.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/index.js +1 -1
- package/packages/pi-coding-agent/dist/index.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 +3 -2
- package/packages/pi-coding-agent/dist/modes/interactive/components/footer.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js +6 -4
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.d.ts +5 -0
- package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.js +12 -0
- package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.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 +2 -1
- package/packages/pi-coding-agent/dist/modes/interactive/theme/themes.js.map +1 -1
- package/packages/pi-coding-agent/package.json +1 -1
- package/packages/pi-coding-agent/src/core/agent-session.ts +2 -1
- package/packages/pi-coding-agent/src/core/bash-executor.ts +10 -2
- package/packages/pi-coding-agent/src/core/extensions/index.ts +2 -0
- package/packages/pi-coding-agent/src/core/extensions/runner.ts +18 -0
- package/packages/pi-coding-agent/src/core/extensions/types.ts +21 -0
- package/packages/pi-coding-agent/src/core/extensions/wrapper.ts +9 -0
- package/packages/pi-coding-agent/src/core/package-manager.ts +10 -1
- package/packages/pi-coding-agent/src/core/skills.ts +35 -10
- package/packages/pi-coding-agent/src/core/slash-commands.ts +1 -0
- package/packages/pi-coding-agent/src/index.ts +4 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/footer.ts +3 -2
- package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +6 -4
- package/packages/pi-coding-agent/src/modes/interactive/slash-command-handlers.ts +15 -0
- package/packages/pi-coding-agent/src/modes/interactive/theme/themes.ts +2 -1
- package/pkg/dist/modes/interactive/theme/themes.d.ts.map +1 -1
- package/pkg/dist/modes/interactive/theme/themes.js +2 -1
- package/pkg/dist/modes/interactive/theme/themes.js.map +1 -1
- package/pkg/package.json +1 -1
- package/scripts/postinstall.js +163 -6
- package/src/resources/extensions/async-jobs/async-bash-tool.ts +3 -1
- package/src/resources/extensions/bg-shell/interaction.ts +3 -1
- package/src/resources/extensions/bg-shell/process-manager.ts +4 -1
- package/src/resources/extensions/claude-code-cli/partial-builder.ts +5 -0
- package/src/resources/extensions/claude-code-cli/tests/partial-builder.test.ts +105 -0
- package/src/resources/extensions/gsd/auto/phases.ts +15 -1
- package/src/resources/extensions/gsd/auto/session.ts +6 -0
- package/src/resources/extensions/gsd/auto-dashboard.ts +31 -3
- package/src/resources/extensions/gsd/auto-dispatch.ts +84 -51
- package/src/resources/extensions/gsd/auto-observability.ts +72 -0
- package/src/resources/extensions/gsd/auto-post-unit.ts +56 -83
- package/src/resources/extensions/gsd/auto-prompts.ts +48 -0
- package/src/resources/extensions/gsd/auto-recovery.ts +19 -26
- package/src/resources/extensions/gsd/auto-utils.ts +25 -0
- package/src/resources/extensions/gsd/auto.ts +15 -5
- package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +17 -0
- package/src/resources/extensions/gsd/crash-recovery.ts +6 -2
- package/src/resources/extensions/gsd/custom-execution-policy.ts +3 -2
- package/src/resources/extensions/gsd/custom-verification.ts +3 -1
- package/src/resources/extensions/gsd/custom-workflow-engine.ts +3 -2
- package/src/resources/extensions/gsd/dashboard-overlay.ts +7 -0
- package/src/resources/extensions/gsd/detection.ts +662 -3
- package/src/resources/extensions/gsd/dispatch-guard.ts +2 -1
- package/src/resources/extensions/gsd/docs/preferences-reference.md +15 -0
- package/src/resources/extensions/gsd/files.ts +6 -1
- package/src/resources/extensions/gsd/guided-flow.ts +11 -0
- package/src/resources/extensions/gsd/init-wizard.ts +9 -1
- package/src/resources/extensions/gsd/model-router.ts +25 -0
- package/src/resources/extensions/gsd/notifications.ts +23 -0
- package/src/resources/extensions/gsd/observability-validator.ts +456 -0
- package/src/resources/extensions/gsd/preferences-skills.ts +11 -5
- package/src/resources/extensions/gsd/preferences-types.ts +20 -0
- package/src/resources/extensions/gsd/preferences-validation.ts +26 -0
- package/src/resources/extensions/gsd/preferences.ts +3 -0
- package/src/resources/extensions/gsd/prompts/forensics.md +11 -7
- package/src/resources/extensions/gsd/prompts/validate-milestone.md +6 -1
- package/src/resources/extensions/gsd/provider-error-pause.ts +9 -0
- package/src/resources/extensions/gsd/roadmap-mutations.ts +134 -0
- package/src/resources/extensions/gsd/rtk-status.ts +53 -0
- package/src/resources/extensions/gsd/rule-registry.ts +10 -11
- package/src/resources/extensions/gsd/session-forensics.ts +7 -3
- package/src/resources/extensions/gsd/skill-catalog.ts +1085 -0
- package/src/resources/extensions/gsd/skill-discovery.ts +3 -2
- package/src/resources/extensions/gsd/skill-health.ts +2 -2
- package/src/resources/extensions/gsd/skill-telemetry.ts +15 -5
- package/src/resources/extensions/gsd/state.ts +16 -5
- package/src/resources/extensions/gsd/templates/milestone-validation.md +12 -0
- package/src/resources/extensions/gsd/templates/preferences.md +2 -0
- package/src/resources/extensions/gsd/tests/auto-dashboard.test.ts +16 -0
- package/src/resources/extensions/gsd/tests/auto-lock-creation.test.ts +2 -2
- package/src/resources/extensions/gsd/tests/auto-loop.test.ts +68 -0
- package/src/resources/extensions/gsd/tests/complete-milestone.test.ts +2 -2
- package/src/resources/extensions/gsd/tests/crash-recovery.test.ts +5 -3
- package/src/resources/extensions/gsd/tests/custom-verification.test.ts +33 -0
- package/src/resources/extensions/gsd/tests/derive-state-db.test.ts +4 -3
- package/src/resources/extensions/gsd/tests/detection.test.ts +838 -0
- package/src/resources/extensions/gsd/tests/dist-redirect.mjs +28 -9
- package/src/resources/extensions/gsd/tests/double-merge-guard.test.ts +97 -0
- package/src/resources/extensions/gsd/tests/idle-recovery.test.ts +63 -0
- package/src/resources/extensions/gsd/tests/model-router.test.ts +40 -0
- package/src/resources/extensions/gsd/tests/notifications.test.ts +28 -6
- package/src/resources/extensions/gsd/tests/plan-quality-validator.test.ts +474 -0
- package/src/resources/extensions/gsd/tests/preferences.test.ts +50 -0
- package/src/resources/extensions/gsd/tests/queue-reorder-e2e.test.ts +40 -0
- package/src/resources/extensions/gsd/tests/reactive-executor.test.ts +6 -6
- package/src/resources/extensions/gsd/tests/retry-diagnostic-reasoning.test.ts +161 -0
- package/src/resources/extensions/gsd/tests/retry-state-reset.test.ts +4 -5
- package/src/resources/extensions/gsd/tests/rewrite-count-persist.test.ts +82 -0
- package/src/resources/extensions/gsd/tests/run-uat.test.ts +146 -0
- package/src/resources/extensions/gsd/tests/sidecar-queue.test.ts +12 -12
- package/src/resources/extensions/gsd/tests/skill-catalog.test.ts +193 -0
- package/src/resources/extensions/gsd/tests/terminated-transient.test.ts +24 -0
- package/src/resources/extensions/gsd/tests/triage-dispatch.test.ts +2 -2
- package/src/resources/extensions/gsd/types.ts +2 -0
- package/src/resources/extensions/gsd/undo.ts +8 -7
- package/src/resources/extensions/gsd/unit-runtime.ts +2 -1
- package/src/resources/extensions/gsd/verification-gate.ts +3 -1
- package/src/resources/extensions/shared/rtk-session-stats.ts +249 -0
- package/src/resources/extensions/shared/rtk.ts +120 -0
- package/dist/web/standalone/.next/server/chunks/229.js +0 -12
- package/dist/web/standalone/.next/server/chunks/441.js +0 -2
- package/dist/web/standalone/.next/server/chunks/471.js +0 -13
- package/dist/web/standalone/.next/static/MQOhBnkC_TLtNn_JvZWDj/_buildManifest.js +0 -1
- package/dist/web/standalone/.next/static/chunks/4024.7c75ac378de0f2b5.js +0 -9
- package/dist/web/standalone/.next/static/chunks/app/_global-error/page-d83ba70a25a85472.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/boot/route-d83ba70a25a85472.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/bridge-terminal/input/route-d83ba70a25a85472.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/bridge-terminal/resize/route-d83ba70a25a85472.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/bridge-terminal/stream/route-d83ba70a25a85472.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/browse-directories/route-d83ba70a25a85472.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/captures/route-d83ba70a25a85472.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/cleanup/route-d83ba70a25a85472.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/dev-mode/route-d83ba70a25a85472.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/doctor/route-d83ba70a25a85472.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/export-data/route-d83ba70a25a85472.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/files/route-d83ba70a25a85472.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/forensics/route-d83ba70a25a85472.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/git/route-d83ba70a25a85472.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/history/route-d83ba70a25a85472.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/hooks/route-d83ba70a25a85472.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/inspect/route-d83ba70a25a85472.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/knowledge/route-d83ba70a25a85472.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/live-state/route-d83ba70a25a85472.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/onboarding/route-d83ba70a25a85472.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/preferences/route-d83ba70a25a85472.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/projects/route-d83ba70a25a85472.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/recovery/route-d83ba70a25a85472.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/remote-questions/route-d83ba70a25a85472.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/session/browser/route-d83ba70a25a85472.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/session/command/route-d83ba70a25a85472.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/session/events/route-d83ba70a25a85472.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/session/manage/route-d83ba70a25a85472.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/settings-data/route-d83ba70a25a85472.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/shutdown/route-d83ba70a25a85472.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/skill-health/route-d83ba70a25a85472.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/steer/route-d83ba70a25a85472.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/switch-root/route-d83ba70a25a85472.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/terminal/input/route-d83ba70a25a85472.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/terminal/resize/route-d83ba70a25a85472.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/terminal/sessions/route-d83ba70a25a85472.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/terminal/stream/route-d83ba70a25a85472.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/terminal/upload/route-d83ba70a25a85472.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/undo/route-d83ba70a25a85472.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/update/route-d83ba70a25a85472.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/visualizer/route-d83ba70a25a85472.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/page-12dd5ece0df4badc.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/app-error-d83ba70a25a85472.js +0 -1
- package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/forbidden-d83ba70a25a85472.js +0 -1
- package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-ab5a8926e07ec673.js +0 -1
- package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/not-found-d83ba70a25a85472.js +0 -1
- package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/unauthorized-d83ba70a25a85472.js +0 -1
- package/dist/web/standalone/.next/static/chunks/webpack-2473ce2c3879fff4.js +0 -1
- package/dist/web/standalone/.next/static/css/dd4ae3f58ac9b600.css +0 -1
- package/packages/pi-ai/pnpm-lock.yaml +0 -2022
- package/packages/pi-coding-agent/pnpm-lock.yaml +0 -454
- /package/dist/web/standalone/.next/static/{MQOhBnkC_TLtNn_JvZWDj → 5_KeZz1X0tXJK-d_4OhjB}/_ssgManifest.js +0 -0
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Regression tests for #2195: formatTraceSummary (used by getDeepDiagnostic →
|
|
3
|
+
* retry prompts) must NOT include lastReasoning from prior assistant text.
|
|
4
|
+
*
|
|
5
|
+
* Including prior assistant free-text in retry diagnostics causes hallucination
|
|
6
|
+
* loops when the previous turn was truncated or malformed.
|
|
7
|
+
*
|
|
8
|
+
* The crash recovery path (formatCrashRecoveryBriefing) has its own safe handling
|
|
9
|
+
* of lastReasoning and is NOT affected by this change.
|
|
10
|
+
*/
|
|
11
|
+
import { describe, test } from "node:test";
|
|
12
|
+
import assert from "node:assert/strict";
|
|
13
|
+
import { mkdirSync, writeFileSync, rmSync, mkdtempSync } from "node:fs";
|
|
14
|
+
import { join } from "node:path";
|
|
15
|
+
import { tmpdir } from "node:os";
|
|
16
|
+
|
|
17
|
+
import { extractTrace, getDeepDiagnostic } from "../session-forensics.ts";
|
|
18
|
+
|
|
19
|
+
/** Build a minimal assistant text reasoning entry. */
|
|
20
|
+
function makeAssistantText(text: string): unknown {
|
|
21
|
+
return {
|
|
22
|
+
type: "message",
|
|
23
|
+
message: {
|
|
24
|
+
role: "assistant",
|
|
25
|
+
content: [{ type: "text", text }],
|
|
26
|
+
},
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/** Build a minimal assistant tool call + tool result pair. */
|
|
31
|
+
function makeToolPair(
|
|
32
|
+
toolName: string,
|
|
33
|
+
input: Record<string, unknown>,
|
|
34
|
+
resultText: string,
|
|
35
|
+
isError: boolean,
|
|
36
|
+
): unknown[] {
|
|
37
|
+
const toolCallId = `toolu_${Math.random().toString(36).slice(2, 10)}`;
|
|
38
|
+
return [
|
|
39
|
+
{
|
|
40
|
+
type: "message",
|
|
41
|
+
message: {
|
|
42
|
+
role: "assistant",
|
|
43
|
+
content: [
|
|
44
|
+
{
|
|
45
|
+
type: "toolCall",
|
|
46
|
+
id: toolCallId,
|
|
47
|
+
name: toolName,
|
|
48
|
+
arguments: input,
|
|
49
|
+
},
|
|
50
|
+
],
|
|
51
|
+
},
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
type: "message",
|
|
55
|
+
message: {
|
|
56
|
+
role: "toolResult",
|
|
57
|
+
toolCallId,
|
|
58
|
+
toolName,
|
|
59
|
+
isError,
|
|
60
|
+
content: [{ type: "text", text: resultText }],
|
|
61
|
+
},
|
|
62
|
+
},
|
|
63
|
+
];
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
describe("retry diagnostic excludes lastReasoning (#2195)", () => {
|
|
67
|
+
test("extractTrace still captures lastReasoning in the trace object", () => {
|
|
68
|
+
const entries = [
|
|
69
|
+
makeAssistantText("I am going to write the summary file now"),
|
|
70
|
+
...makeToolPair("write", { path: "/tmp/SUMMARY.md" }, "ok", false),
|
|
71
|
+
makeAssistantText("The task is complete — all files written."),
|
|
72
|
+
];
|
|
73
|
+
|
|
74
|
+
const trace = extractTrace(entries);
|
|
75
|
+
// extractTrace should still collect lastReasoning for crash recovery
|
|
76
|
+
assert.ok(trace.lastReasoning.length > 0,
|
|
77
|
+
"extractTrace should still populate lastReasoning");
|
|
78
|
+
assert.ok(trace.lastReasoning.includes("all files written"),
|
|
79
|
+
"lastReasoning should contain the last assistant text");
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
test("getDeepDiagnostic output does NOT contain lastReasoning", () => {
|
|
83
|
+
// Create a temporary activity directory with a JSONL file
|
|
84
|
+
const tempBase = mkdtempSync(join(tmpdir(), "gsd-diag-test-"));
|
|
85
|
+
const gsdDir = join(tempBase, ".gsd");
|
|
86
|
+
const activityDir = join(gsdDir, "activity");
|
|
87
|
+
mkdirSync(activityDir, { recursive: true });
|
|
88
|
+
|
|
89
|
+
try {
|
|
90
|
+
// Build entries with both tool calls and assistant reasoning
|
|
91
|
+
const entries = [
|
|
92
|
+
makeAssistantText("Let me analyze the codebase structure first"),
|
|
93
|
+
...makeToolPair("bash", { command: "ls src/" }, "index.ts\nutils.ts", false),
|
|
94
|
+
makeAssistantText("I see the milestone/M001 branch has a significantly different ... 3. "),
|
|
95
|
+
];
|
|
96
|
+
|
|
97
|
+
// Write JSONL activity file
|
|
98
|
+
const jsonl = entries.map(e => JSON.stringify(e)).join("\n");
|
|
99
|
+
writeFileSync(join(activityDir, "2025-01-01T00-00-00.jsonl"), jsonl);
|
|
100
|
+
|
|
101
|
+
const diagnostic = getDeepDiagnostic(tempBase);
|
|
102
|
+
|
|
103
|
+
// Diagnostic should exist (we have tool calls)
|
|
104
|
+
assert.ok(diagnostic !== null, "diagnostic should not be null");
|
|
105
|
+
|
|
106
|
+
// Diagnostic should contain structured execution evidence
|
|
107
|
+
assert.ok(diagnostic!.includes("Tool calls completed:"),
|
|
108
|
+
"should include tool call count");
|
|
109
|
+
assert.ok(diagnostic!.includes("ls src/"),
|
|
110
|
+
"should include commands run");
|
|
111
|
+
|
|
112
|
+
// Diagnostic must NOT contain the assistant's free-text reasoning
|
|
113
|
+
assert.ok(!diagnostic!.includes("Last reasoning"),
|
|
114
|
+
"diagnostic must not include 'Last reasoning' label");
|
|
115
|
+
assert.ok(!diagnostic!.includes("analyze the codebase"),
|
|
116
|
+
"diagnostic must not include prior assistant text");
|
|
117
|
+
assert.ok(!diagnostic!.includes("significantly different"),
|
|
118
|
+
"diagnostic must not include truncated assistant reasoning");
|
|
119
|
+
} finally {
|
|
120
|
+
rmSync(tempBase, { recursive: true, force: true });
|
|
121
|
+
}
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
test("getDeepDiagnostic still includes errors and file operations", () => {
|
|
125
|
+
const tempBase = mkdtempSync(join(tmpdir(), "gsd-diag-test-"));
|
|
126
|
+
const gsdDir = join(tempBase, ".gsd");
|
|
127
|
+
const activityDir = join(gsdDir, "activity");
|
|
128
|
+
mkdirSync(activityDir, { recursive: true });
|
|
129
|
+
|
|
130
|
+
try {
|
|
131
|
+
const entries = [
|
|
132
|
+
makeAssistantText("Writing the plan file"),
|
|
133
|
+
...makeToolPair("write", { path: "M001/S01/S01-PLAN.md" }, "ok", false),
|
|
134
|
+
...makeToolPair("bash", { command: "npm run build" }, "Error: type mismatch", true),
|
|
135
|
+
makeAssistantText("The build failed, let me investigate"),
|
|
136
|
+
];
|
|
137
|
+
|
|
138
|
+
const jsonl = entries.map(e => JSON.stringify(e)).join("\n");
|
|
139
|
+
writeFileSync(join(activityDir, "2025-01-01T00-00-00.jsonl"), jsonl);
|
|
140
|
+
|
|
141
|
+
const diagnostic = getDeepDiagnostic(tempBase);
|
|
142
|
+
assert.ok(diagnostic !== null);
|
|
143
|
+
|
|
144
|
+
// Structured evidence should be present
|
|
145
|
+
assert.ok(diagnostic!.includes("S01-PLAN.md"),
|
|
146
|
+
"should include files written");
|
|
147
|
+
assert.ok(diagnostic!.includes("npm run build"),
|
|
148
|
+
"should include commands run");
|
|
149
|
+
assert.ok(diagnostic!.includes("type mismatch"),
|
|
150
|
+
"should include errors");
|
|
151
|
+
|
|
152
|
+
// But NOT the assistant's free-text
|
|
153
|
+
assert.ok(!diagnostic!.includes("Writing the plan"),
|
|
154
|
+
"must not include assistant reasoning");
|
|
155
|
+
assert.ok(!diagnostic!.includes("build failed"),
|
|
156
|
+
"must not include assistant reasoning about failures");
|
|
157
|
+
} finally {
|
|
158
|
+
rmSync(tempBase, { recursive: true, force: true });
|
|
159
|
+
}
|
|
160
|
+
});
|
|
161
|
+
});
|
|
@@ -16,6 +16,7 @@ import {
|
|
|
16
16
|
resolveHookArtifactPath,
|
|
17
17
|
} from "../post-unit-hooks.ts";
|
|
18
18
|
import { uncheckTaskInPlan } from "../undo.ts";
|
|
19
|
+
import { parseUnitId } from "../unit-id.ts";
|
|
19
20
|
|
|
20
21
|
// ─── Fixture Helpers ───────────────────────────────────────────────────────
|
|
21
22
|
|
|
@@ -183,8 +184,7 @@ test('Full retry reset: all steps combined', () => {
|
|
|
183
184
|
retryArtifact: "NEEDS-REWORK.md",
|
|
184
185
|
};
|
|
185
186
|
|
|
186
|
-
const
|
|
187
|
-
const [mid, sid, tid] = parts;
|
|
187
|
+
const { milestone: mid, slice: sid, task: tid } = parseUnitId(trigger.unitId);
|
|
188
188
|
|
|
189
189
|
// Simulate completedUnits
|
|
190
190
|
let completedUnits = [
|
|
@@ -264,11 +264,10 @@ test('Retry reset: idempotent when artifacts already missing', () => {
|
|
|
264
264
|
};
|
|
265
265
|
|
|
266
266
|
// These should not throw even with missing files
|
|
267
|
-
const
|
|
268
|
-
const [mid, sid, tid] = parts;
|
|
267
|
+
const { milestone: mid, slice: sid, task: tid } = parseUnitId(trigger.unitId);
|
|
269
268
|
|
|
270
269
|
// Uncheck — returns false because no PLAN file
|
|
271
|
-
const uncheckResult = uncheckTaskInPlan(base, mid, sid
|
|
270
|
+
const uncheckResult = uncheckTaskInPlan(base, mid, sid!, tid!);
|
|
272
271
|
assert.ok(!uncheckResult, "uncheck returns false when no PLAN exists");
|
|
273
272
|
|
|
274
273
|
// Summary does not exist — no crash
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Regression tests for #2203: rewrite-docs circuit breaker must persist
|
|
3
|
+
* across session restarts.
|
|
4
|
+
*
|
|
5
|
+
* The rewrite attempt counter was stored in-memory on the session object,
|
|
6
|
+
* resetting to 0 on every session restart. This allowed the rewrite-docs
|
|
7
|
+
* dispatch rule to fire indefinitely, never tripping the MAX_REWRITE_ATTEMPTS
|
|
8
|
+
* circuit breaker.
|
|
9
|
+
*
|
|
10
|
+
* The fix persists the counter to `.gsd/runtime/rewrite-count.json`.
|
|
11
|
+
*/
|
|
12
|
+
import { describe, test, beforeEach, afterEach } from "node:test";
|
|
13
|
+
import assert from "node:assert/strict";
|
|
14
|
+
import { mkdirSync, existsSync, readFileSync, writeFileSync, rmSync, mkdtempSync } from "node:fs";
|
|
15
|
+
import { join } from "node:path";
|
|
16
|
+
import { tmpdir } from "node:os";
|
|
17
|
+
|
|
18
|
+
import { getRewriteCount, setRewriteCount } from "../auto-dispatch.ts";
|
|
19
|
+
|
|
20
|
+
describe("rewrite-docs circuit breaker persistence (#2203)", () => {
|
|
21
|
+
let tempBase: string;
|
|
22
|
+
|
|
23
|
+
beforeEach(() => {
|
|
24
|
+
tempBase = mkdtempSync(join(tmpdir(), "gsd-rewrite-test-"));
|
|
25
|
+
// Create .gsd/ directory so gsdRoot resolves to it
|
|
26
|
+
mkdirSync(join(tempBase, ".gsd", "runtime"), { recursive: true });
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
afterEach(() => {
|
|
30
|
+
rmSync(tempBase, { recursive: true, force: true });
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
test("getRewriteCount returns 0 when no file exists", () => {
|
|
34
|
+
const count = getRewriteCount(tempBase);
|
|
35
|
+
assert.equal(count, 0);
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
test("setRewriteCount writes and getRewriteCount reads back", () => {
|
|
39
|
+
setRewriteCount(tempBase, 2);
|
|
40
|
+
const count = getRewriteCount(tempBase);
|
|
41
|
+
assert.equal(count, 2);
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
test("counter persists across simulated session restarts", () => {
|
|
45
|
+
// Session 1: increment to 1
|
|
46
|
+
setRewriteCount(tempBase, 1);
|
|
47
|
+
|
|
48
|
+
// "Session restart" — only the disk file survives, session object is gone
|
|
49
|
+
const countAfterRestart = getRewriteCount(tempBase);
|
|
50
|
+
assert.equal(countAfterRestart, 1, "counter should survive session restart");
|
|
51
|
+
|
|
52
|
+
// Session 2: increment to 2
|
|
53
|
+
setRewriteCount(tempBase, countAfterRestart + 1);
|
|
54
|
+
assert.equal(getRewriteCount(tempBase), 2);
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
test("setRewriteCount(0) resets the counter", () => {
|
|
58
|
+
setRewriteCount(tempBase, 3);
|
|
59
|
+
assert.equal(getRewriteCount(tempBase), 3);
|
|
60
|
+
|
|
61
|
+
setRewriteCount(tempBase, 0);
|
|
62
|
+
assert.equal(getRewriteCount(tempBase), 0);
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
test("getRewriteCount handles corrupt JSON gracefully", () => {
|
|
66
|
+
const filePath = join(tempBase, ".gsd", "runtime", "rewrite-count.json");
|
|
67
|
+
// writeFileSync is imported at the top of this file
|
|
68
|
+
writeFileSync(filePath, "not json{{{");
|
|
69
|
+
const count = getRewriteCount(tempBase);
|
|
70
|
+
assert.equal(count, 0, "corrupt file should return 0");
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
test("rewrite-count.json is written to .gsd/runtime/", () => {
|
|
74
|
+
setRewriteCount(tempBase, 1);
|
|
75
|
+
const filePath = join(tempBase, ".gsd", "runtime", "rewrite-count.json");
|
|
76
|
+
assert.ok(existsSync(filePath), "rewrite-count.json should exist");
|
|
77
|
+
|
|
78
|
+
const content = JSON.parse(readFileSync(filePath, "utf-8"));
|
|
79
|
+
assert.equal(content.count, 1);
|
|
80
|
+
assert.ok(content.updatedAt, "should include timestamp");
|
|
81
|
+
});
|
|
82
|
+
});
|
|
@@ -460,4 +460,150 @@ test('(n) stale replay guard', async () => {
|
|
|
460
460
|
}
|
|
461
461
|
});
|
|
462
462
|
|
|
463
|
+
test('(q) verdict in ASSESSMENT file skips UAT dispatch (file-based path)', async () => {
|
|
464
|
+
// Regression test for #2644: run-uat prompt writes the verdict to
|
|
465
|
+
// S{sid}-ASSESSMENT.md (via gsd_summary_save artifact_type:"ASSESSMENT"),
|
|
466
|
+
// but checkNeedsRunUat only checked S{sid}-UAT.md — causing a stuck loop.
|
|
467
|
+
const base = createFixtureBase();
|
|
468
|
+
try {
|
|
469
|
+
const roadmapDir = join(base, '.gsd', 'milestones', 'M001');
|
|
470
|
+
mkdirSync(roadmapDir, { recursive: true });
|
|
471
|
+
writeFileSync(
|
|
472
|
+
join(roadmapDir, 'M001-ROADMAP.md'),
|
|
473
|
+
[
|
|
474
|
+
'# M001: Test roadmap',
|
|
475
|
+
'',
|
|
476
|
+
'## Slices',
|
|
477
|
+
'',
|
|
478
|
+
'- [x] **S01: First slice** `risk:low` `depends:[]`',
|
|
479
|
+
'- [ ] **S02: Next slice** `risk:low` `depends:[S01]`',
|
|
480
|
+
'',
|
|
481
|
+
'## Boundary Map',
|
|
482
|
+
'',
|
|
483
|
+
].join('\n'),
|
|
484
|
+
);
|
|
485
|
+
|
|
486
|
+
// UAT spec file WITHOUT a verdict (the spec never gets one)
|
|
487
|
+
writeSliceFile(base, 'M001', 'S01', 'UAT', makeUatContent('artifact-driven'));
|
|
488
|
+
// ASSESSMENT file WITH a verdict (where run-uat actually writes it)
|
|
489
|
+
writeSliceFile(base, 'M001', 'S01', 'ASSESSMENT', '---\nverdict: PASS\n---\n# UAT Assessment\n');
|
|
490
|
+
|
|
491
|
+
const state = {
|
|
492
|
+
activeMilestone: { id: 'M001', title: 'Test roadmap' },
|
|
493
|
+
activeSlice: { id: 'S02', title: 'Next slice' },
|
|
494
|
+
activeTask: null,
|
|
495
|
+
phase: 'planning',
|
|
496
|
+
recentDecisions: [],
|
|
497
|
+
blockers: [],
|
|
498
|
+
nextAction: 'Plan S02',
|
|
499
|
+
registry: [],
|
|
500
|
+
} as const;
|
|
501
|
+
|
|
502
|
+
const result = await checkNeedsRunUat(base, 'M001', state as any, { uat_dispatch: true } as any);
|
|
503
|
+
assert.deepStrictEqual(
|
|
504
|
+
result,
|
|
505
|
+
null,
|
|
506
|
+
'verdict in ASSESSMENT file should prevent re-dispatch of run-uat',
|
|
507
|
+
);
|
|
508
|
+
} finally {
|
|
509
|
+
cleanup(base);
|
|
510
|
+
}
|
|
511
|
+
});
|
|
512
|
+
|
|
513
|
+
test('(r) no ASSESSMENT file still dispatches UAT (no false skip)', async () => {
|
|
514
|
+
// Guard: when there is no ASSESSMENT file at all, UAT should still dispatch
|
|
515
|
+
// normally. The ASSESSMENT check must not cause a false-negative skip.
|
|
516
|
+
const base = createFixtureBase();
|
|
517
|
+
try {
|
|
518
|
+
const roadmapDir = join(base, '.gsd', 'milestones', 'M001');
|
|
519
|
+
mkdirSync(roadmapDir, { recursive: true });
|
|
520
|
+
writeFileSync(
|
|
521
|
+
join(roadmapDir, 'M001-ROADMAP.md'),
|
|
522
|
+
[
|
|
523
|
+
'# M001: Test roadmap',
|
|
524
|
+
'',
|
|
525
|
+
'## Slices',
|
|
526
|
+
'',
|
|
527
|
+
'- [x] **S01: First slice** `risk:low` `depends:[]`',
|
|
528
|
+
'- [ ] **S02: Next slice** `risk:low` `depends:[S01]`',
|
|
529
|
+
'',
|
|
530
|
+
'## Boundary Map',
|
|
531
|
+
'',
|
|
532
|
+
].join('\n'),
|
|
533
|
+
);
|
|
534
|
+
|
|
535
|
+
// UAT spec file WITHOUT a verdict, and NO ASSESSMENT file
|
|
536
|
+
writeSliceFile(base, 'M001', 'S01', 'UAT', makeUatContent('artifact-driven'));
|
|
537
|
+
|
|
538
|
+
const state = {
|
|
539
|
+
activeMilestone: { id: 'M001', title: 'Test roadmap' },
|
|
540
|
+
activeSlice: { id: 'S02', title: 'Next slice' },
|
|
541
|
+
activeTask: null,
|
|
542
|
+
phase: 'planning',
|
|
543
|
+
recentDecisions: [],
|
|
544
|
+
blockers: [],
|
|
545
|
+
nextAction: 'Plan S02',
|
|
546
|
+
registry: [],
|
|
547
|
+
} as const;
|
|
548
|
+
|
|
549
|
+
const result = await checkNeedsRunUat(base, 'M001', state as any, { uat_dispatch: true } as any);
|
|
550
|
+
assert.deepStrictEqual(
|
|
551
|
+
result,
|
|
552
|
+
{ sliceId: 'S01', uatType: 'artifact-driven' },
|
|
553
|
+
'without ASSESSMENT file, UAT still dispatches normally',
|
|
554
|
+
);
|
|
555
|
+
} finally {
|
|
556
|
+
cleanup(base);
|
|
557
|
+
}
|
|
558
|
+
});
|
|
559
|
+
|
|
560
|
+
test('(s) ASSESSMENT without verdict does not skip UAT dispatch', async () => {
|
|
561
|
+
// Guard: an ASSESSMENT file that exists but has no verdict line should
|
|
562
|
+
// NOT suppress UAT dispatch — only a file with an actual verdict should.
|
|
563
|
+
const base = createFixtureBase();
|
|
564
|
+
try {
|
|
565
|
+
const roadmapDir = join(base, '.gsd', 'milestones', 'M001');
|
|
566
|
+
mkdirSync(roadmapDir, { recursive: true });
|
|
567
|
+
writeFileSync(
|
|
568
|
+
join(roadmapDir, 'M001-ROADMAP.md'),
|
|
569
|
+
[
|
|
570
|
+
'# M001: Test roadmap',
|
|
571
|
+
'',
|
|
572
|
+
'## Slices',
|
|
573
|
+
'',
|
|
574
|
+
'- [x] **S01: First slice** `risk:low` `depends:[]`',
|
|
575
|
+
'- [ ] **S02: Next slice** `risk:low` `depends:[S01]`',
|
|
576
|
+
'',
|
|
577
|
+
'## Boundary Map',
|
|
578
|
+
'',
|
|
579
|
+
].join('\n'),
|
|
580
|
+
);
|
|
581
|
+
|
|
582
|
+
// UAT spec WITHOUT verdict
|
|
583
|
+
writeSliceFile(base, 'M001', 'S01', 'UAT', makeUatContent('artifact-driven'));
|
|
584
|
+
// ASSESSMENT file WITHOUT verdict (partial/incomplete assessment)
|
|
585
|
+
writeSliceFile(base, 'M001', 'S01', 'ASSESSMENT', '# UAT Assessment\n\nStill running checks...\n');
|
|
586
|
+
|
|
587
|
+
const state = {
|
|
588
|
+
activeMilestone: { id: 'M001', title: 'Test roadmap' },
|
|
589
|
+
activeSlice: { id: 'S02', title: 'Next slice' },
|
|
590
|
+
activeTask: null,
|
|
591
|
+
phase: 'planning',
|
|
592
|
+
recentDecisions: [],
|
|
593
|
+
blockers: [],
|
|
594
|
+
nextAction: 'Plan S02',
|
|
595
|
+
registry: [],
|
|
596
|
+
} as const;
|
|
597
|
+
|
|
598
|
+
const result = await checkNeedsRunUat(base, 'M001', state as any, { uat_dispatch: true } as any);
|
|
599
|
+
assert.deepStrictEqual(
|
|
600
|
+
result,
|
|
601
|
+
{ sliceId: 'S01', uatType: 'artifact-driven' },
|
|
602
|
+
'ASSESSMENT without verdict should not suppress UAT dispatch',
|
|
603
|
+
);
|
|
604
|
+
} finally {
|
|
605
|
+
cleanup(base);
|
|
606
|
+
}
|
|
607
|
+
});
|
|
608
|
+
|
|
463
609
|
});
|
|
@@ -113,12 +113,12 @@ test("postUnitPostVerification pushes to sidecarQueue for hooks", () => {
|
|
|
113
113
|
assert.ok(triageSectionStart > -1, "auto-post-unit.ts must have a triage check section");
|
|
114
114
|
const hookSection = source.slice(hookSectionStart, triageSectionStart);
|
|
115
115
|
assert.ok(
|
|
116
|
-
hookSection.includes("s.sidecarQueue.push("),
|
|
117
|
-
"hook section must
|
|
116
|
+
hookSection.includes("enqueueSidecar(") || hookSection.includes("s.sidecarQueue.push("),
|
|
117
|
+
"hook section must enqueue to sidecarQueue (via enqueueSidecar or direct push)",
|
|
118
118
|
);
|
|
119
119
|
assert.ok(
|
|
120
|
-
hookSection.includes('
|
|
121
|
-
"hook sidecar item must
|
|
120
|
+
hookSection.includes('"hook"'),
|
|
121
|
+
"hook sidecar item must reference kind 'hook'",
|
|
122
122
|
);
|
|
123
123
|
});
|
|
124
124
|
|
|
@@ -132,12 +132,12 @@ test("postUnitPostVerification pushes to sidecarQueue for triage", () => {
|
|
|
132
132
|
assert.ok(quickTaskSectionStart > -1, "auto-post-unit.ts must have a quick-task dispatch section");
|
|
133
133
|
const triageSection = source.slice(triageSectionStart, quickTaskSectionStart);
|
|
134
134
|
assert.ok(
|
|
135
|
-
triageSection.includes("s.sidecarQueue.push("),
|
|
136
|
-
"triage section must
|
|
135
|
+
triageSection.includes("enqueueSidecar(") || triageSection.includes("s.sidecarQueue.push("),
|
|
136
|
+
"triage section must enqueue to sidecarQueue (via enqueueSidecar or direct push)",
|
|
137
137
|
);
|
|
138
138
|
assert.ok(
|
|
139
|
-
triageSection.includes('
|
|
140
|
-
"triage sidecar item must
|
|
139
|
+
triageSection.includes('"triage"'),
|
|
140
|
+
"triage sidecar item must reference kind 'triage'",
|
|
141
141
|
);
|
|
142
142
|
});
|
|
143
143
|
|
|
@@ -149,12 +149,12 @@ test("postUnitPostVerification pushes to sidecarQueue for quick-tasks", () => {
|
|
|
149
149
|
assert.ok(quickTaskSectionStart > -1, "auto-post-unit.ts must have a quick-task dispatch section");
|
|
150
150
|
const quickTaskSection = source.slice(quickTaskSectionStart);
|
|
151
151
|
assert.ok(
|
|
152
|
-
quickTaskSection.includes("s.sidecarQueue.push("),
|
|
153
|
-
"quick-task section must
|
|
152
|
+
quickTaskSection.includes("enqueueSidecar(") || quickTaskSection.includes("s.sidecarQueue.push("),
|
|
153
|
+
"quick-task section must enqueue to sidecarQueue (via enqueueSidecar or direct push)",
|
|
154
154
|
);
|
|
155
155
|
assert.ok(
|
|
156
|
-
quickTaskSection.includes('
|
|
157
|
-
"quick-task sidecar item must
|
|
156
|
+
quickTaskSection.includes('"quick-task"'),
|
|
157
|
+
"quick-task sidecar item must reference kind 'quick-task'",
|
|
158
158
|
);
|
|
159
159
|
});
|
|
160
160
|
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unit tests for GSD Skill Catalog — pack matching logic.
|
|
3
|
+
*
|
|
4
|
+
* Exercises matchPacksForProject() to verify that project signals
|
|
5
|
+
* correctly map to skill packs.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import test from "node:test";
|
|
9
|
+
import assert from "node:assert/strict";
|
|
10
|
+
import { PROJECT_FILES } from "../detection.ts";
|
|
11
|
+
import { GREENFIELD_STACKS, SKILL_CATALOG, matchPacksForProject } from "../skill-catalog.ts";
|
|
12
|
+
import type { ProjectSignals } from "../detection.ts";
|
|
13
|
+
|
|
14
|
+
function makeSignals(overrides: Partial<ProjectSignals> = {}): ProjectSignals {
|
|
15
|
+
return {
|
|
16
|
+
detectedFiles: [],
|
|
17
|
+
isGitRepo: false,
|
|
18
|
+
isMonorepo: false,
|
|
19
|
+
xcodePlatforms: [],
|
|
20
|
+
hasCI: false,
|
|
21
|
+
hasTests: false,
|
|
22
|
+
verificationCommands: [],
|
|
23
|
+
...overrides,
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function packLabels(signals: ProjectSignals): string[] {
|
|
28
|
+
return matchPacksForProject(signals).map((p) => p.label);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// ── matchAlways packs are always included ────────────────────────────────────
|
|
32
|
+
|
|
33
|
+
test("matchPacksForProject: always includes matchAlways packs", () => {
|
|
34
|
+
const labels = packLabels(makeSignals());
|
|
35
|
+
assert.ok(labels.includes("Skill Discovery"), "should include Skill Discovery");
|
|
36
|
+
assert.ok(labels.includes("Skill Authoring"), "should include Skill Authoring");
|
|
37
|
+
assert.ok(labels.includes("Browser Automation"), "should include Browser Automation");
|
|
38
|
+
assert.ok(labels.includes("Document Handling"), "should include Document Handling");
|
|
39
|
+
assert.ok(labels.includes("Code Review & Quality"), "should include Code Review & Quality");
|
|
40
|
+
assert.ok(labels.includes("Git Advanced Workflows"), "should include Git Advanced Workflows");
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
// ── Language matching ────────────────────────────────────────────────────────
|
|
44
|
+
|
|
45
|
+
test("matchPacksForProject: Python language matches Python packs", () => {
|
|
46
|
+
const labels = packLabels(makeSignals({ primaryLanguage: "python", detectedFiles: ["pyproject.toml"] }));
|
|
47
|
+
assert.ok(labels.includes("Python"), "should include Python");
|
|
48
|
+
assert.ok(labels.includes("Python Advanced"), "should include Python Advanced");
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
test("matchPacksForProject: Rust language matches Rust packs", () => {
|
|
52
|
+
const labels = packLabels(makeSignals({ primaryLanguage: "rust", detectedFiles: ["Cargo.toml"] }));
|
|
53
|
+
assert.ok(labels.includes("Rust"), "should include Rust");
|
|
54
|
+
assert.ok(labels.includes("Rust Async Patterns"), "should include Rust Async Patterns");
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
test("matchPacksForProject: Go language matches Go packs", () => {
|
|
58
|
+
const labels = packLabels(makeSignals({ primaryLanguage: "go", detectedFiles: ["go.mod"] }));
|
|
59
|
+
assert.ok(labels.includes("Go"), "should include Go");
|
|
60
|
+
assert.ok(labels.includes("Go Concurrency Patterns"), "should include Go Concurrency Patterns");
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
test("matchPacksForProject: JS/TS matches web frontend packs", () => {
|
|
64
|
+
const labels = packLabels(makeSignals({ primaryLanguage: "javascript/typescript", detectedFiles: ["package.json"] }));
|
|
65
|
+
assert.ok(labels.includes("React & Web Frontend"), "should include React");
|
|
66
|
+
assert.ok(labels.includes("TypeScript & JS Development"), "should include TS/JS Dev");
|
|
67
|
+
assert.ok(labels.includes("React State & Patterns"), "should include React State");
|
|
68
|
+
assert.ok(labels.includes("shadcn/ui"), "should include shadcn");
|
|
69
|
+
assert.ok(labels.includes("Frontend Design & UX"), "should include Frontend Design");
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
// ── File matching ────────────────────────────────────────────────────────────
|
|
73
|
+
|
|
74
|
+
test("matchPacksForProject: angular.json triggers Angular packs", () => {
|
|
75
|
+
const labels = packLabels(makeSignals({ detectedFiles: ["angular.json"] }));
|
|
76
|
+
assert.ok(labels.includes("Angular"), "should include Angular");
|
|
77
|
+
assert.ok(labels.includes("Angular Migration"), "should include Angular Migration");
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
test("matchPacksForProject: next.config.ts triggers Next.js packs", () => {
|
|
81
|
+
const labels = packLabels(makeSignals({ detectedFiles: ["next.config.ts"] }));
|
|
82
|
+
assert.ok(labels.includes("Next.js"), "should include Next.js");
|
|
83
|
+
assert.ok(labels.includes("Next.js App Router Patterns"), "should include Next.js App Router");
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
test("matchPacksForProject: *.vue triggers Vue.js", () => {
|
|
87
|
+
const labels = packLabels(makeSignals({ detectedFiles: ["*.vue"] }));
|
|
88
|
+
assert.ok(labels.includes("Vue.js"), "should include Vue.js");
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
test("matchPacksForProject: Chart.yaml triggers Kubernetes", () => {
|
|
92
|
+
const labels = packLabels(makeSignals({ detectedFiles: ["Chart.yaml"] }));
|
|
93
|
+
assert.ok(labels.includes("Kubernetes"), "should include Kubernetes");
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
test("matchPacksForProject: hardhat.config.ts triggers Blockchain", () => {
|
|
97
|
+
const labels = packLabels(makeSignals({ detectedFiles: ["hardhat.config.ts"] }));
|
|
98
|
+
assert.ok(labels.includes("Blockchain & Web3"), "should include Blockchain & Web3");
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
test("matchPacksForProject: tailwind.config.ts triggers Tailwind CSS", () => {
|
|
102
|
+
const labels = packLabels(makeSignals({ detectedFiles: ["tailwind.config.ts"] }));
|
|
103
|
+
assert.ok(labels.includes("Tailwind CSS"), "should include Tailwind CSS");
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
// ── Xcode platform matching ─────────────────────────────────────────────────
|
|
107
|
+
|
|
108
|
+
test("matchPacksForProject: iphoneos triggers iOS packs", () => {
|
|
109
|
+
const labels = packLabels(makeSignals({ xcodePlatforms: ["iphoneos"] }));
|
|
110
|
+
assert.ok(labels.includes("iOS App Frameworks"), "should include iOS App Frameworks");
|
|
111
|
+
assert.ok(labels.includes("iOS Data Frameworks"), "should include iOS Data Frameworks");
|
|
112
|
+
assert.ok(labels.includes("iOS AI & ML"), "should include iOS AI & ML");
|
|
113
|
+
assert.ok(labels.includes("iOS Engineering"), "should include iOS Engineering");
|
|
114
|
+
assert.ok(labels.includes("iOS Hardware"), "should include iOS Hardware");
|
|
115
|
+
assert.ok(labels.includes("iOS Platform"), "should include iOS Platform");
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
// ── Isolation checks — packs that should NOT match ──────────────────────────
|
|
119
|
+
|
|
120
|
+
test("matchPacksForProject: FastAPI does not match generic Python", () => {
|
|
121
|
+
const labels = packLabels(makeSignals({ primaryLanguage: "python", detectedFiles: ["pyproject.toml"] }));
|
|
122
|
+
assert.ok(!labels.includes("FastAPI"), "FastAPI should NOT match generic Python projects");
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
test("matchPacksForProject: FastAPI matches when dep:fastapi detected", () => {
|
|
126
|
+
const labels = packLabels(makeSignals({ primaryLanguage: "python", detectedFiles: ["pyproject.toml", "dep:fastapi"] }));
|
|
127
|
+
assert.ok(labels.includes("FastAPI"), "FastAPI should match when dep:fastapi is in detectedFiles");
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
test("matchPacksForProject: Spring Boot does not match via language alone", () => {
|
|
131
|
+
// Simulate Android project: has java/kotlin language but no root pom.xml/build.gradle
|
|
132
|
+
const labels = packLabels(makeSignals({ primaryLanguage: "java/kotlin", detectedFiles: ["app/build.gradle"] }));
|
|
133
|
+
assert.ok(!labels.includes("Java & Spring Boot"), "Spring Boot should NOT match via language alone");
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
test("matchPacksForProject: Spring Boot matches only dep:spring-boot", () => {
|
|
137
|
+
const positive = packLabels(makeSignals({ detectedFiles: ["dep:spring-boot"] }));
|
|
138
|
+
assert.ok(positive.includes("Java & Spring Boot"), "should include Spring Boot pack when dependency marker exists");
|
|
139
|
+
|
|
140
|
+
const androidLike = packLabels(makeSignals({ detectedFiles: ["build.gradle", "app/build.gradle"], primaryLanguage: "java/kotlin" }));
|
|
141
|
+
assert.ok(!androidLike.includes("Java & Spring Boot"), "generic Gradle + Android markers should not imply Spring Boot");
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
test("matchPacksForProject: Unity does not include Godot", () => {
|
|
145
|
+
const labels = packLabels(makeSignals({ detectedFiles: ["ProjectSettings/ProjectVersion.txt"] }));
|
|
146
|
+
assert.ok(labels.includes("Unity"), "should include Unity");
|
|
147
|
+
assert.ok(!labels.includes("Godot"), "should NOT include Godot");
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
test("matchPacksForProject: Godot does not include Unity", () => {
|
|
151
|
+
const labels = packLabels(makeSignals({ detectedFiles: ["project.godot"] }));
|
|
152
|
+
assert.ok(labels.includes("Godot"), "should include Godot");
|
|
153
|
+
assert.ok(!labels.includes("Unity"), "should NOT include Unity");
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
test("matchPacksForProject: .NET backend patterns match F# and solution markers", () => {
|
|
157
|
+
const fsprojLabels = packLabels(makeSignals({ detectedFiles: ["*.fsproj"], primaryLanguage: "fsharp" }));
|
|
158
|
+
assert.ok(fsprojLabels.includes(".NET Backend Patterns"), "should include generic .NET backend patterns for F# projects");
|
|
159
|
+
assert.ok(!fsprojLabels.includes(".NET & C#"), "should not include C#-specific pack for F# projects");
|
|
160
|
+
|
|
161
|
+
const slnLabels = packLabels(makeSignals({ detectedFiles: ["*.sln"], primaryLanguage: "dotnet" }));
|
|
162
|
+
assert.ok(slnLabels.includes(".NET Backend Patterns"), "should include generic .NET backend patterns for solution files");
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
test("SKILL_CATALOG: every matchFiles entry is backed by detection", () => {
|
|
166
|
+
const knownMarkers = new Set<string>([
|
|
167
|
+
...PROJECT_FILES,
|
|
168
|
+
"*.sqlite",
|
|
169
|
+
"*.sql",
|
|
170
|
+
"*.csproj",
|
|
171
|
+
"*.fsproj",
|
|
172
|
+
"*.sln",
|
|
173
|
+
"*.vue",
|
|
174
|
+
"dep:fastapi",
|
|
175
|
+
"dep:spring-boot",
|
|
176
|
+
]);
|
|
177
|
+
|
|
178
|
+
for (const pack of SKILL_CATALOG) {
|
|
179
|
+
for (const marker of pack.matchFiles ?? []) {
|
|
180
|
+
assert.ok(knownMarkers.has(marker), `Unknown detection marker: ${marker} (pack: ${pack.label})`);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
test("GREENFIELD_STACKS: every pack label resolves to SKILL_CATALOG", () => {
|
|
186
|
+
const labels = new Set(SKILL_CATALOG.map((pack) => pack.label));
|
|
187
|
+
|
|
188
|
+
for (const stack of GREENFIELD_STACKS) {
|
|
189
|
+
for (const packLabel of stack.packs) {
|
|
190
|
+
assert.ok(labels.has(packLabel), `Unknown pack label: ${packLabel} (stack: ${stack.id})`);
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
});
|