gsd-pi 2.78.0-dev.aeeb2ca00 → 2.78.1-dev.84a383f51
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 +7 -7
- package/dist/claude-cli-check.js +64 -37
- package/dist/cli-policy.d.ts +13 -0
- package/dist/cli-policy.js +17 -0
- package/dist/cli.js +95 -55
- package/dist/headless-query.d.ts +22 -0
- package/dist/headless-query.js +24 -4
- package/dist/headless.d.ts +10 -0
- package/dist/headless.js +16 -1
- package/dist/loader.js +7 -10
- package/dist/onboarding.d.ts +10 -0
- package/dist/onboarding.js +2 -2
- package/dist/provider-migrations.d.ts +2 -2
- package/dist/provider-migrations.js +5 -2
- package/dist/resource-loader.d.ts +5 -2
- package/dist/resource-loader.js +28 -5
- package/dist/resources/.managed-resources-content-hash +1 -0
- package/dist/resources/extensions/claude-code-cli/readiness.js +77 -45
- package/dist/resources/extensions/gsd/auto/loop.js +23 -0
- package/dist/resources/extensions/gsd/auto/phases.js +2 -2
- package/dist/resources/extensions/gsd/auto/run-unit.js +3 -1
- package/dist/resources/extensions/gsd/auto/session.js +3 -0
- package/dist/resources/extensions/gsd/auto-recovery.js +43 -4
- package/dist/resources/extensions/gsd/auto-runtime-state.js +31 -0
- package/dist/resources/extensions/gsd/auto-start.js +1 -1
- package/dist/resources/extensions/gsd/auto-tool-tracking.js +2 -2
- package/dist/resources/extensions/gsd/auto-worktree.js +30 -0
- package/dist/resources/extensions/gsd/auto.js +14 -5
- package/dist/resources/extensions/gsd/bootstrap/db-tools.js +14 -2
- package/dist/resources/extensions/gsd/bootstrap/exec-tools.js +7 -5
- package/dist/resources/extensions/gsd/bootstrap/query-tools.js +2 -2
- package/dist/resources/extensions/gsd/bootstrap/register-extension.js +5 -4
- package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +94 -31
- package/dist/resources/extensions/gsd/bootstrap/register-shortcuts.js +11 -6
- package/dist/resources/extensions/gsd/bootstrap/system-context.js +34 -8
- package/dist/resources/extensions/gsd/bootstrap/write-gate.js +38 -2
- package/dist/resources/extensions/gsd/commands/catalog.js +69 -5
- package/dist/resources/extensions/gsd/commands/handlers/core.js +22 -1
- package/dist/resources/extensions/gsd/commands-mcp-status.js +3 -1
- package/dist/resources/extensions/gsd/commands-prefs-wizard.js +10 -1
- package/dist/resources/extensions/gsd/dashboard-overlay.js +1 -1
- package/dist/resources/extensions/gsd/docs/preferences-reference.md +4 -0
- package/dist/resources/extensions/gsd/doctor-runtime-checks.js +39 -1
- package/dist/resources/extensions/gsd/error-classifier.js +1 -1
- package/dist/resources/extensions/gsd/forensics.js +2 -2
- package/dist/resources/extensions/gsd/git-service.js +12 -5
- package/dist/resources/extensions/gsd/gsd-db.js +11 -2
- package/dist/resources/extensions/gsd/guided-flow.js +23 -23
- package/dist/resources/extensions/gsd/memory-store.js +66 -31
- package/dist/resources/extensions/gsd/milestone-id-reservation.js +36 -0
- package/dist/resources/extensions/gsd/model-router.js +114 -9
- package/dist/resources/extensions/gsd/native-git-bridge.js +7 -1
- package/dist/resources/extensions/gsd/preferences-models.js +91 -15
- package/dist/resources/extensions/gsd/preferences-types.js +2 -0
- package/dist/resources/extensions/gsd/preferences-validation.js +32 -0
- package/dist/resources/extensions/gsd/preferences.js +5 -3
- package/dist/resources/extensions/gsd/prompt-loader.js +23 -12
- package/dist/resources/extensions/gsd/slice-parallel-orchestrator.js +9 -3
- package/dist/resources/extensions/gsd/state.js +42 -0
- package/dist/resources/extensions/gsd/templates/PREFERENCES.md +1 -0
- package/dist/resources/extensions/gsd/tools/memory-tools.js +18 -1
- package/dist/resources/extensions/gsd/visualizer-overlay.js +1 -1
- package/dist/resources/extensions/gsd/watch/header-renderer.js +3 -1
- package/dist/resources/extensions/gsd/worktree-command.js +26 -46
- package/dist/resources/extensions/gsd/worktree-session-state.js +33 -0
- package/dist/resources/extensions/mcp-client/index.js +6 -3
- package/dist/resources/extensions/slash-commands/create-extension.js +36 -22
- package/dist/resources/skills/create-gsd-extension/SKILL.md +9 -5
- package/dist/resources/skills/create-gsd-extension/references/custom-commands.md +1 -1
- package/dist/resources/skills/create-gsd-extension/references/custom-rendering.md +5 -5
- package/dist/resources/skills/create-gsd-extension/references/custom-tools.md +4 -4
- package/dist/resources/skills/create-gsd-extension/references/custom-ui.md +6 -6
- package/dist/resources/skills/create-gsd-extension/references/events-reference.md +3 -3
- package/dist/resources/skills/create-gsd-extension/references/packaging-distribution.md +1 -1
- package/dist/resources/skills/create-gsd-extension/references/remote-execution-overrides.md +3 -3
- package/dist/resources/skills/create-gsd-extension/workflows/create-extension.md +32 -12
- package/dist/rtk-shared.d.ts +3 -0
- package/dist/rtk-shared.js +17 -0
- package/dist/rtk.d.ts +2 -5
- package/dist/rtk.js +3 -20
- package/dist/runtime-checks.d.ts +27 -0
- package/dist/runtime-checks.js +38 -0
- 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/react-loadable-manifest.json +44 -4
- package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/api/boot/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/events/route.js +4 -2
- package/dist/web/standalone/.next/server/app/api/shutdown/route.js +1 -1
- package/dist/web/standalone/.next/server/app/index.html +1 -1
- package/dist/web/standalone/.next/server/app/index.rsc +2 -2
- package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
- package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +2 -2
- package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app-paths-manifest.json +12 -12
- package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
- package/dist/web/standalone/.next/server/middleware-manifest.json +5 -5
- package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
- package/dist/web/standalone/.next/server/pages/404.html +1 -1
- package/dist/web/standalone/.next/server/pages/500.html +1 -1
- package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
- package/dist/web/standalone/.next/server/webpack-runtime.js +1 -1
- package/dist/web/standalone/.next/static/chunks/2556.0527fea66e123b7f.js +1 -0
- package/dist/web/standalone/.next/static/chunks/2824.08296bc2f9654698.js +1 -0
- package/dist/web/standalone/.next/static/chunks/3026.3af53b279375f082.js +1 -0
- package/dist/web/standalone/.next/static/chunks/315.6f68ae79b67d25cf.js +1 -0
- package/dist/web/standalone/.next/static/chunks/3497.4bfc60a3b3dea717.js +1 -0
- package/dist/web/standalone/.next/static/chunks/5516.4a07c872b5c3a663.js +1 -0
- package/dist/web/standalone/.next/static/chunks/8336.31b019697882acfb.js +10 -0
- package/dist/web/standalone/.next/static/chunks/8845.c9702695e8c5a9c5.js +2 -0
- package/dist/web/standalone/.next/static/chunks/9058.01ef3a463bda88f1.js +20 -0
- package/dist/web/standalone/.next/static/chunks/9441.1081da1125d1764f.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/{page-5b113fd32bc2a1c3.js → page-9bf2e0c50fb2ca05.js} +1 -1
- package/dist/web/standalone/.next/static/chunks/webpack-f9f0dc45e4f3ac10.js +1 -0
- package/dist/web/standalone/package.json +2 -1
- package/dist/worktree-status-banner.d.ts +1 -0
- package/dist/worktree-status-banner.js +132 -0
- package/package.json +1 -1
- package/packages/daemon/package.json +2 -2
- package/packages/mcp-server/dist/alias-telemetry.d.ts +8 -0
- package/packages/mcp-server/dist/alias-telemetry.d.ts.map +1 -0
- package/packages/mcp-server/dist/alias-telemetry.js +30 -0
- package/packages/mcp-server/dist/alias-telemetry.js.map +1 -0
- package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
- package/packages/mcp-server/dist/workflow-tools.js +74 -46
- package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
- package/packages/mcp-server/package.json +2 -2
- package/packages/mcp-server/src/alias-telemetry.test.ts +78 -0
- package/packages/mcp-server/src/alias-telemetry.ts +30 -0
- package/packages/mcp-server/src/workflow-tools.test.ts +26 -0
- package/packages/mcp-server/src/workflow-tools.ts +93 -58
- 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/providers/anthropic-shared.cache-breakpoint.test.d.ts +2 -0
- package/packages/pi-ai/dist/providers/anthropic-shared.cache-breakpoint.test.d.ts.map +1 -0
- package/packages/pi-ai/dist/providers/anthropic-shared.cache-breakpoint.test.js +231 -0
- package/packages/pi-ai/dist/providers/anthropic-shared.cache-breakpoint.test.js.map +1 -0
- package/packages/pi-ai/dist/providers/anthropic-shared.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/anthropic-shared.js +48 -19
- package/packages/pi-ai/dist/providers/anthropic-shared.js.map +1 -1
- package/packages/pi-ai/dist/types.d.ts +13 -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/dist/utils/repair-tool-json.d.ts.map +1 -1
- package/packages/pi-ai/dist/utils/repair-tool-json.js +24 -3
- package/packages/pi-ai/dist/utils/repair-tool-json.js.map +1 -1
- package/packages/pi-ai/dist/utils/tests/repair-tool-json.test.js +26 -0
- package/packages/pi-ai/dist/utils/tests/repair-tool-json.test.js.map +1 -1
- package/packages/pi-ai/package.json +1 -1
- package/packages/pi-ai/src/providers/anthropic-shared.cache-breakpoint.test.ts +289 -0
- package/packages/pi-ai/src/providers/anthropic-shared.ts +52 -20
- package/packages/pi-ai/src/types.ts +13 -0
- package/packages/pi-ai/src/utils/repair-tool-json.ts +24 -3
- package/packages/pi-ai/src/utils/tests/repair-tool-json.test.ts +32 -0
- package/packages/pi-ai/tsconfig.tsbuildinfo +1 -1
- package/packages/pi-coding-agent/dist/core/agent-session.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/agent-session.js +6 -0
- package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/messages.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/messages.js +4 -0
- package/packages/pi-coding-agent/dist/core/messages.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/model-registry-auth-mode.test.js +19 -2
- package/packages/pi-coding-agent/dist/core/model-registry-auth-mode.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/model-registry.d.ts +10 -0
- package/packages/pi-coding-agent/dist/core/model-registry.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/model-registry.js +18 -0
- package/packages/pi-coding-agent/dist/core/model-registry.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/system-prompt.d.ts +13 -0
- package/packages/pi-coding-agent/dist/core/system-prompt.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/system-prompt.js +20 -16
- package/packages/pi-coding-agent/dist/core/system-prompt.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/token-telemetry.d.ts +37 -0
- package/packages/pi-coding-agent/dist/core/token-telemetry.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/token-telemetry.js +49 -0
- package/packages/pi-coding-agent/dist/core/token-telemetry.js.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-card-cleanup-and-success-runtime.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-card-cleanup-and-success-runtime.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-card-cleanup-and-success-runtime.test.js +133 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-card-cleanup-and-success-runtime.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.js +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.test.js +14 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/tests/system-prompt-cache-stability.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/tests/system-prompt-cache-stability.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/tests/system-prompt-cache-stability.test.js +78 -0
- package/packages/pi-coding-agent/dist/tests/system-prompt-cache-stability.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/tests/token-telemetry.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/tests/token-telemetry.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/tests/token-telemetry.test.js +181 -0
- package/packages/pi-coding-agent/dist/tests/token-telemetry.test.js.map +1 -0
- package/packages/pi-coding-agent/package.json +1 -1
- package/packages/pi-coding-agent/src/core/agent-session.ts +7 -0
- package/packages/pi-coding-agent/src/core/messages.ts +4 -0
- package/packages/pi-coding-agent/src/core/model-registry-auth-mode.test.ts +32 -2
- package/packages/pi-coding-agent/src/core/model-registry.ts +21 -0
- package/packages/pi-coding-agent/src/core/system-prompt.ts +33 -15
- package/packages/pi-coding-agent/src/core/token-telemetry.ts +77 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/tool-card-cleanup-and-success-runtime.test.ts +212 -0
- package/packages/pi-coding-agent/src/modes/interactive/controllers/input-controller.test.ts +17 -1
- package/packages/pi-coding-agent/src/modes/interactive/controllers/input-controller.ts +1 -1
- package/packages/pi-coding-agent/src/tests/system-prompt-cache-stability.test.ts +102 -0
- package/packages/pi-coding-agent/src/tests/token-telemetry.test.ts +200 -0
- package/packages/pi-coding-agent/tsconfig.tsbuildinfo +1 -1
- package/packages/pi-tui/dist/__tests__/autocomplete.test.js +17 -3
- package/packages/pi-tui/dist/__tests__/autocomplete.test.js.map +1 -1
- package/packages/pi-tui/dist/components/__tests__/leak-fixes-runtime.test.d.ts +2 -0
- package/packages/pi-tui/dist/components/__tests__/leak-fixes-runtime.test.d.ts.map +1 -0
- package/packages/pi-tui/dist/components/__tests__/leak-fixes-runtime.test.js +161 -0
- package/packages/pi-tui/dist/components/__tests__/leak-fixes-runtime.test.js.map +1 -0
- package/packages/pi-tui/package.json +1 -1
- package/packages/pi-tui/src/__tests__/autocomplete.test.ts +20 -3
- package/packages/pi-tui/src/components/__tests__/leak-fixes-runtime.test.ts +219 -0
- package/packages/pi-tui/tsconfig.tsbuildinfo +1 -1
- package/packages/rpc-client/package.json +1 -1
- package/pkg/package.json +1 -1
- package/src/resources/extensions/claude-code-cli/readiness.ts +78 -46
- package/src/resources/extensions/gsd/auto/loop.ts +24 -2
- package/src/resources/extensions/gsd/auto/phases.ts +3 -3
- package/src/resources/extensions/gsd/auto/run-unit.ts +3 -1
- package/src/resources/extensions/gsd/auto/session.ts +3 -0
- package/src/resources/extensions/gsd/auto/types.ts +1 -0
- package/src/resources/extensions/gsd/auto-recovery.ts +46 -8
- package/src/resources/extensions/gsd/auto-runtime-state.ts +51 -0
- package/src/resources/extensions/gsd/auto-start.ts +1 -1
- package/src/resources/extensions/gsd/auto-tool-tracking.ts +2 -4
- package/src/resources/extensions/gsd/auto-worktree.ts +38 -0
- package/src/resources/extensions/gsd/auto.ts +14 -4
- package/src/resources/extensions/gsd/bootstrap/db-tools.ts +15 -13
- package/src/resources/extensions/gsd/bootstrap/exec-tools.ts +8 -7
- package/src/resources/extensions/gsd/bootstrap/query-tools.ts +2 -2
- package/src/resources/extensions/gsd/bootstrap/register-extension.ts +10 -9
- package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +102 -31
- package/src/resources/extensions/gsd/bootstrap/register-shortcuts.ts +12 -6
- package/src/resources/extensions/gsd/bootstrap/system-context.ts +39 -8
- package/src/resources/extensions/gsd/bootstrap/write-gate.ts +39 -11
- package/src/resources/extensions/gsd/commands/catalog.ts +75 -5
- package/src/resources/extensions/gsd/commands/handlers/core.ts +22 -1
- package/src/resources/extensions/gsd/commands-mcp-status.ts +3 -1
- package/src/resources/extensions/gsd/commands-prefs-wizard.ts +15 -1
- package/src/resources/extensions/gsd/dashboard-overlay.ts +1 -1
- package/src/resources/extensions/gsd/docs/preferences-reference.md +4 -0
- package/src/resources/extensions/gsd/doctor-runtime-checks.ts +39 -1
- package/src/resources/extensions/gsd/doctor-types.ts +3 -1
- package/src/resources/extensions/gsd/error-classifier.ts +1 -1
- package/src/resources/extensions/gsd/forensics.ts +2 -2
- package/src/resources/extensions/gsd/git-service.ts +13 -5
- package/src/resources/extensions/gsd/gsd-db.ts +12 -2
- package/src/resources/extensions/gsd/guided-flow.ts +25 -25
- package/src/resources/extensions/gsd/memory-store.ts +81 -28
- package/src/resources/extensions/gsd/milestone-id-reservation.ts +47 -0
- package/src/resources/extensions/gsd/model-router.ts +172 -9
- package/src/resources/extensions/gsd/native-git-bridge.ts +7 -1
- package/src/resources/extensions/gsd/preferences-models.ts +101 -15
- package/src/resources/extensions/gsd/preferences-types.ts +6 -0
- package/src/resources/extensions/gsd/preferences-validation.ts +35 -0
- package/src/resources/extensions/gsd/preferences.ts +16 -2
- package/src/resources/extensions/gsd/prompt-loader.ts +26 -12
- package/src/resources/extensions/gsd/slice-parallel-orchestrator.ts +9 -3
- package/src/resources/extensions/gsd/state.ts +42 -0
- package/src/resources/extensions/gsd/templates/PREFERENCES.md +1 -0
- package/src/resources/extensions/gsd/tests/auto-loop.test.ts +178 -1
- package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +58 -0
- package/src/resources/extensions/gsd/tests/auto-session-encapsulation.test.ts +9 -5
- package/src/resources/extensions/gsd/tests/auto-supervisor.test.mjs +21 -4
- package/src/resources/extensions/gsd/tests/bootstrap-derive-state-db-open.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/budget-prediction.test.ts +138 -211
- package/src/resources/extensions/gsd/tests/complete-slice-verification-gate.test.ts +142 -59
- package/src/resources/extensions/gsd/tests/complete-slice.test.ts +7 -4
- package/src/resources/extensions/gsd/tests/completed-at-reconcile.test.ts +89 -32
- package/src/resources/extensions/gsd/tests/custom-engine-loop-integration.test.ts +41 -23
- package/src/resources/extensions/gsd/tests/db-path-worktree-symlink.test.ts +3 -43
- package/src/resources/extensions/gsd/tests/debug-logger.test.ts +5 -3
- package/src/resources/extensions/gsd/tests/deferred-milestone-dir-4996.test.ts +116 -0
- package/src/resources/extensions/gsd/tests/discuss-empty-db-fallback.test.ts +22 -87
- package/src/resources/extensions/gsd/tests/discuss-queued-milestones.test.ts +7 -118
- package/src/resources/extensions/gsd/tests/discuss-tool-scope-leak.test.ts +18 -60
- package/src/resources/extensions/gsd/tests/doctor-orphan-milestone-4996.test.ts +100 -0
- package/src/resources/extensions/gsd/tests/double-merge-guard.test.ts +14 -76
- package/src/resources/extensions/gsd/tests/ensure-preconditions-guard-4996.test.ts +93 -0
- package/src/resources/extensions/gsd/tests/false-degraded-mode-warning.test.ts +22 -83
- package/src/resources/extensions/gsd/tests/finalize-timeout-guard.test.ts +1 -63
- package/src/resources/extensions/gsd/tests/find-missing-summaries-closed-runtime.test.ts +47 -0
- package/src/resources/extensions/gsd/tests/forensics-stuck-loops.test.ts +26 -1
- package/src/resources/extensions/gsd/tests/gitignore-bg-shell-runtime.test.ts +63 -0
- package/src/resources/extensions/gsd/tests/gsd-db.test.ts +30 -0
- package/src/resources/extensions/gsd/tests/gsd-no-project-error-runtime.test.ts +81 -0
- package/src/resources/extensions/gsd/tests/headless-answers.test.ts +14 -4
- package/src/resources/extensions/gsd/tests/health-widget.test.ts +22 -12
- package/src/resources/extensions/gsd/tests/help-menu-coverage.test.ts +57 -0
- package/src/resources/extensions/gsd/tests/import-done-milestones-runtime.test.ts +145 -0
- package/src/resources/extensions/gsd/tests/init-prefs-routing.test.ts +64 -1
- package/src/resources/extensions/gsd/tests/integration/auto-worktree.test.ts +22 -0
- package/src/resources/extensions/gsd/tests/integration/token-savings.test.ts +0 -23
- package/src/resources/extensions/gsd/tests/memory-store.test.ts +128 -0
- package/src/resources/extensions/gsd/tests/memory-tools.test.ts +33 -1
- package/src/resources/extensions/gsd/tests/merge-self-branch-guard.test.ts +124 -0
- package/src/resources/extensions/gsd/tests/milestone-id-gap-reuse-4996.test.ts +152 -0
- package/src/resources/extensions/gsd/tests/model-router.test.ts +169 -8
- package/src/resources/extensions/gsd/tests/native-git-infra-errors.test.ts +50 -0
- package/src/resources/extensions/gsd/tests/orphaned-worktree-audit.test.ts +8 -0
- package/src/resources/extensions/gsd/tests/parallel-crash-recovery.test.ts +32 -43
- package/src/resources/extensions/gsd/tests/phases-merge-error-stops-auto.test.ts +4 -10
- package/src/resources/extensions/gsd/tests/preferences.test.ts +127 -0
- package/src/resources/extensions/gsd/tests/prompt-step-ordering.test.ts +16 -0
- package/src/resources/extensions/gsd/tests/provider-errors.test.ts +7 -0
- package/src/resources/extensions/gsd/tests/quick-turn-end-cleanup.test.ts +6 -6
- package/src/resources/extensions/gsd/tests/register-hooks-compaction-checkpoint.test.ts +93 -0
- package/src/resources/extensions/gsd/tests/session-start-footer.test.ts +168 -19
- package/src/resources/extensions/gsd/tests/slice-parallel-orchestrator.test.ts +7 -1
- package/src/resources/extensions/gsd/tests/smart-entry-complete.test.ts +23 -1
- package/src/resources/extensions/gsd/tests/system-context-message-routing.test.ts +101 -0
- package/src/resources/extensions/gsd/tests/token-profile.test.ts +51 -4
- package/src/resources/extensions/gsd/tests/turn-epoch.test.ts +7 -16
- package/src/resources/extensions/gsd/tests/unstructured-continue-context-injection.test.ts +5 -7
- package/src/resources/extensions/gsd/tests/uok-gitops-turn-action.test.ts +15 -1
- package/src/resources/extensions/gsd/tests/visualizer-overlay.test.ts +6 -6
- package/src/resources/extensions/gsd/tests/write-gate-planning-unit.test.ts +15 -0
- package/src/resources/extensions/gsd/tools/memory-tools.ts +17 -1
- package/src/resources/extensions/gsd/unit-context-manifest.ts +8 -8
- package/src/resources/extensions/gsd/visualizer-overlay.ts +1 -1
- package/src/resources/extensions/gsd/watch/header-renderer.ts +3 -1
- package/src/resources/extensions/gsd/workflow-logger.ts +1 -0
- package/src/resources/extensions/gsd/worktree-command.ts +31 -44
- package/src/resources/extensions/gsd/worktree-session-state.ts +35 -0
- package/src/resources/extensions/mcp-client/index.ts +6 -3
- package/src/resources/extensions/mcp-client/tests/global-config.test.ts +91 -0
- package/src/resources/extensions/slash-commands/create-extension.ts +38 -24
- package/src/resources/skills/create-gsd-extension/SKILL.md +9 -5
- package/src/resources/skills/create-gsd-extension/references/custom-commands.md +1 -1
- package/src/resources/skills/create-gsd-extension/references/custom-rendering.md +5 -5
- package/src/resources/skills/create-gsd-extension/references/custom-tools.md +4 -4
- package/src/resources/skills/create-gsd-extension/references/custom-ui.md +6 -6
- package/src/resources/skills/create-gsd-extension/references/events-reference.md +3 -3
- package/src/resources/skills/create-gsd-extension/references/packaging-distribution.md +1 -1
- package/src/resources/skills/create-gsd-extension/references/remote-execution-overrides.md +3 -3
- package/src/resources/skills/create-gsd-extension/templates/extension-skeleton.ts +2 -2
- package/src/resources/skills/create-gsd-extension/templates/stateful-tool-skeleton.ts +3 -3
- package/src/resources/skills/create-gsd-extension/templates/templates.test.ts +58 -0
- package/src/resources/skills/create-gsd-extension/workflows/create-extension.md +32 -12
- package/dist/resources/extensions/browser-tools/tests/browser-tools-integration.test.mjs +0 -601
- package/dist/resources/extensions/browser-tools/tests/browser-tools-unit.test.cjs +0 -651
- package/dist/resources/extensions/browser-tools/tests/capture-sharp-optional.test.cjs +0 -91
- package/dist/resources/extensions/gsd/tests/auto-supervisor.test.mjs +0 -53
- package/dist/resources/extensions/gsd/tests/dist-redirect.mjs +0 -112
- package/dist/resources/extensions/gsd/tests/resolve-ts-hooks.mjs +0 -23
- package/dist/resources/extensions/gsd/tests/resolve-ts.mjs +0 -5
- package/dist/resources/skills/github-workflows/references/gh/tests/__init__.py +0 -0
- package/dist/resources/skills/github-workflows/references/gh/tests/test_github_project_setup.py +0 -608
- package/dist/web/standalone/.next/static/chunks/2826.e9f5195e91f9cad2.js +0 -11
- package/dist/web/standalone/.next/static/chunks/3621.fc7480022c972438.js +0 -20
- package/dist/web/standalone/.next/static/chunks/webpack-2e68521d7c82f7c2.js +0 -1
- package/src/resources/extensions/gsd/tests/copy-planning-artifacts-samepath.test.ts +0 -22
- package/src/resources/extensions/gsd/tests/discuss-slice-structured-questions.test.ts +0 -47
- package/src/resources/extensions/gsd/tests/empty-content-abort-loop.test.ts +0 -75
- /package/dist/web/standalone/.next/static/{cAJH99yNS1UPbeSEiNRrV → UF5VF4F1tB0miEtJS7LyX}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{cAJH99yNS1UPbeSEiNRrV → UF5VF4F1tB0miEtJS7LyX}/_ssgManifest.js +0 -0
|
@@ -1,220 +1,147 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* budget-prediction.test.ts — unit tests for budget prediction math
|
|
3
|
+
* (`getAverageCostPerUnitType`, `predictRemainingCost`) exported from
|
|
4
|
+
* `metrics.ts`.
|
|
3
5
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
6
|
+
* The previous version (PR #582, `972dd05f4`) re-implemented both
|
|
7
|
+
* functions inline, citing a `paths.js → @gsd/pi-coding-agent` import
|
|
8
|
+
* chain as the reason. That chain concern is no longer valid — the
|
|
9
|
+
* real exports import cleanly from `metrics.ts`. All 10 math tests
|
|
10
|
+
* were then exercising the test's own copy of the functions, not the
|
|
11
|
+
* product code. #4840 documented the false-coverage case.
|
|
12
|
+
*
|
|
13
|
+
* This rewrite imports the real functions, deletes the inline copies,
|
|
14
|
+
* drops the 3 source-grep tests (`metricsSrc.includes(...)`) and the
|
|
15
|
+
* 2 dashboard `includes` tests (dashboard integration should be a
|
|
16
|
+
* behaviour test against the dashboard builder, not a grep), and
|
|
17
|
+
* deletes the synthesized `downgrade:` test that exercised a local
|
|
18
|
+
* closure instead of product code. See #4784 / #4840.
|
|
7
19
|
*/
|
|
8
20
|
|
|
9
|
-
import test from "node:test";
|
|
21
|
+
import { describe, test } from "node:test";
|
|
10
22
|
import assert from "node:assert/strict";
|
|
11
|
-
import { readFileSync } from "node:fs";
|
|
12
|
-
import { join, dirname } from "node:path";
|
|
13
|
-
import { fileURLToPath } from "node:url";
|
|
14
|
-
|
|
15
|
-
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
16
|
-
const metricsSrc = readFileSync(join(__dirname, "..", "metrics.ts"), "utf-8");
|
|
17
|
-
const dashboardSrc = readFileSync(join(__dirname, "..", "auto-dashboard.ts"), "utf-8");
|
|
18
|
-
|
|
19
|
-
// ─── Extract pure functions from metrics.ts source ────────────────────────
|
|
20
|
-
// Can't import directly due to paths.js → @gsd/pi-coding-agent import chain.
|
|
21
|
-
// Extract and evaluate the pure math functions.
|
|
22
|
-
|
|
23
|
-
interface MockUnitMetrics {
|
|
24
|
-
type: string;
|
|
25
|
-
cost: number;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
// Re-implement the functions under test (verified against source below)
|
|
29
|
-
function getAverageCostPerUnitType(units: MockUnitMetrics[]): Map<string, number> {
|
|
30
|
-
const sums = new Map<string, { total: number; count: number }>();
|
|
31
|
-
for (const u of units) {
|
|
32
|
-
const entry = sums.get(u.type) ?? { total: 0, count: 0 };
|
|
33
|
-
entry.total += u.cost;
|
|
34
|
-
entry.count += 1;
|
|
35
|
-
sums.set(u.type, entry);
|
|
36
|
-
}
|
|
37
|
-
const avgs = new Map<string, number>();
|
|
38
|
-
for (const [type, { total, count }] of sums) {
|
|
39
|
-
avgs.set(type, total / count);
|
|
40
|
-
}
|
|
41
|
-
return avgs;
|
|
42
|
-
}
|
|
43
23
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
return
|
|
24
|
+
import {
|
|
25
|
+
getAverageCostPerUnitType,
|
|
26
|
+
predictRemainingCost,
|
|
27
|
+
} from "../metrics.ts";
|
|
28
|
+
import type { UnitMetrics } from "../metrics.ts";
|
|
29
|
+
|
|
30
|
+
// ─── Fixture helper ───────────────────────────────────────────────────────
|
|
31
|
+
// UnitMetrics has several required fields; this builder lets each test
|
|
32
|
+
// specify only the fields that matter for the cost math.
|
|
33
|
+
|
|
34
|
+
function makeUnit(partial: Partial<UnitMetrics> & { type: string; cost: number }): UnitMetrics {
|
|
35
|
+
return {
|
|
36
|
+
id: "M001/S01/T01",
|
|
37
|
+
model: "test-model",
|
|
38
|
+
startedAt: 0,
|
|
39
|
+
finishedAt: 0,
|
|
40
|
+
tokens: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },
|
|
41
|
+
toolCalls: 0,
|
|
42
|
+
assistantMessages: 0,
|
|
43
|
+
userMessages: 0,
|
|
44
|
+
...partial,
|
|
45
|
+
};
|
|
56
46
|
}
|
|
57
47
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
})
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
});
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
["plan-slice", 0.10
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
});
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
[
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
})
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
//
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
);
|
|
157
|
-
});
|
|
158
|
-
|
|
159
|
-
test("dashboard: AutoDashboardData includes profileDowngraded field", () => {
|
|
160
|
-
assert.ok(
|
|
161
|
-
dashboardSrc.includes("profileDowngraded"),
|
|
162
|
-
"AutoDashboardData should have profileDowngraded field",
|
|
163
|
-
);
|
|
164
|
-
});
|
|
165
|
-
|
|
166
|
-
// ═══════════════════════════════════════════════════════════════════════════
|
|
167
|
-
// Budget Prediction — End-to-End Math
|
|
168
|
-
// ═══════════════════════════════════════════════════════════════════════════
|
|
169
|
-
|
|
170
|
-
test("e2e: budget ceiling exceeded triggers downgrade prediction", () => {
|
|
171
|
-
const units: MockUnitMetrics[] = [
|
|
172
|
-
{ type: "execute-task", cost: 0.50 },
|
|
173
|
-
{ type: "execute-task", cost: 0.60 },
|
|
174
|
-
{ type: "plan-slice", cost: 0.30 },
|
|
175
|
-
{ type: "complete-slice", cost: 0.20 },
|
|
176
|
-
];
|
|
177
|
-
const totalSpent = units.reduce((sum, u) => sum + u.cost, 0); // 1.60
|
|
178
|
-
const avgs = getAverageCostPerUnitType(units);
|
|
179
|
-
const remaining = ["execute-task", "execute-task", "execute-task"];
|
|
180
|
-
const predictedRemaining = predictRemainingCost(avgs, remaining);
|
|
181
|
-
const predictedTotal = totalSpent + predictedRemaining;
|
|
182
|
-
const budgetCeiling = 2.50;
|
|
183
|
-
assert.ok(predictedTotal > budgetCeiling, "should predict budget exhaustion");
|
|
184
|
-
});
|
|
185
|
-
|
|
186
|
-
test("e2e: budget ceiling not exceeded does not trigger", () => {
|
|
187
|
-
const units: MockUnitMetrics[] = [
|
|
188
|
-
{ type: "execute-task", cost: 0.10 },
|
|
189
|
-
{ type: "plan-slice", cost: 0.05 },
|
|
190
|
-
];
|
|
191
|
-
const totalSpent = units.reduce((sum, u) => sum + u.cost, 0); // 0.15
|
|
192
|
-
const avgs = getAverageCostPerUnitType(units);
|
|
193
|
-
const remaining = ["execute-task", "complete-slice"];
|
|
194
|
-
const predictedRemaining = predictRemainingCost(avgs, remaining);
|
|
195
|
-
const predictedTotal = totalSpent + predictedRemaining;
|
|
196
|
-
const budgetCeiling = 5.00;
|
|
197
|
-
assert.ok(predictedTotal <= budgetCeiling, "should not predict budget exhaustion");
|
|
198
|
-
});
|
|
199
|
-
|
|
200
|
-
// ═══════════════════════════════════════════════════════════════════════════
|
|
201
|
-
// Downgrade Logic
|
|
202
|
-
// ═══════════════════════════════════════════════════════════════════════════
|
|
203
|
-
|
|
204
|
-
test("downgrade: one-way per D048 — downgrade should not be reversible", () => {
|
|
205
|
-
// Simulate: first prediction triggers downgrade, second doesn't reverse it
|
|
206
|
-
let downgraded = false;
|
|
207
|
-
|
|
208
|
-
function checkDowngrade(predictedTotal: number, ceiling: number) {
|
|
209
|
-
if (!downgraded && predictedTotal > ceiling) {
|
|
210
|
-
downgraded = true;
|
|
211
|
-
}
|
|
212
|
-
// Never reverse — per D048
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
checkDowngrade(3.00, 2.50); // triggers
|
|
216
|
-
assert.ok(downgraded, "should downgrade when prediction exceeds ceiling");
|
|
217
|
-
|
|
218
|
-
checkDowngrade(1.50, 2.50); // doesn't reverse
|
|
219
|
-
assert.ok(downgraded, "should stay downgraded (one-way per D048)");
|
|
48
|
+
describe("getAverageCostPerUnitType (metrics.ts)", () => {
|
|
49
|
+
test("returns correct averages per unit type", () => {
|
|
50
|
+
const units = [
|
|
51
|
+
makeUnit({ type: "execute-task", cost: 0.1 }),
|
|
52
|
+
makeUnit({ type: "execute-task", cost: 0.2 }),
|
|
53
|
+
makeUnit({ type: "plan-slice", cost: 0.05 }),
|
|
54
|
+
makeUnit({ type: "plan-slice", cost: 0.15 }),
|
|
55
|
+
makeUnit({ type: "complete-slice", cost: 0.08 }),
|
|
56
|
+
];
|
|
57
|
+
const avgs = getAverageCostPerUnitType(units);
|
|
58
|
+
assert.ok(Math.abs(avgs.get("execute-task")! - 0.15) < 0.001, "execute-task avg");
|
|
59
|
+
assert.ok(Math.abs(avgs.get("plan-slice")! - 0.10) < 0.001, "plan-slice avg");
|
|
60
|
+
assert.ok(Math.abs(avgs.get("complete-slice")! - 0.08) < 0.001, "complete-slice avg");
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
test("returns empty map for empty input", () => {
|
|
64
|
+
assert.equal(getAverageCostPerUnitType([]).size, 0);
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
test("single unit per type returns exact cost", () => {
|
|
68
|
+
const avgs = getAverageCostPerUnitType([makeUnit({ type: "execute-task", cost: 0.42 })]);
|
|
69
|
+
assert.ok(Math.abs(avgs.get("execute-task")! - 0.42) < 0.001);
|
|
70
|
+
});
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
describe("predictRemainingCost (metrics.ts)", () => {
|
|
74
|
+
test("calculates remaining cost from known averages", () => {
|
|
75
|
+
const avgs = new Map([
|
|
76
|
+
["execute-task", 0.15],
|
|
77
|
+
["plan-slice", 0.10],
|
|
78
|
+
["complete-slice", 0.08],
|
|
79
|
+
]);
|
|
80
|
+
const remaining = ["execute-task", "execute-task", "complete-slice"];
|
|
81
|
+
const cost = predictRemainingCost(avgs, remaining);
|
|
82
|
+
// 2 × 0.15 + 0.08 = 0.38
|
|
83
|
+
assert.ok(Math.abs(cost - 0.38) < 0.001);
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
test("uses overall average for unknown unit types", () => {
|
|
87
|
+
const avgs = new Map([
|
|
88
|
+
["execute-task", 0.10],
|
|
89
|
+
["plan-slice", 0.20],
|
|
90
|
+
]);
|
|
91
|
+
const remaining = ["execute-task", "unknown-type"];
|
|
92
|
+
// unknown: (0.10 + 0.20) / 2 = 0.15 → total 0.10 + 0.15 = 0.25
|
|
93
|
+
assert.ok(Math.abs(predictRemainingCost(avgs, remaining) - 0.25) < 0.001);
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
test("returns 0 for empty remaining list", () => {
|
|
97
|
+
const avgs = new Map([["execute-task", 0.15]]);
|
|
98
|
+
assert.equal(predictRemainingCost(avgs, []), 0);
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
test("uses fallback when no averages are known", () => {
|
|
102
|
+
const cost = predictRemainingCost(new Map(), ["execute-task", "plan-slice"], 0.10);
|
|
103
|
+
assert.ok(Math.abs(cost - 0.20) < 0.001);
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
test("returns 0 when no averages and no fallback", () => {
|
|
107
|
+
assert.equal(predictRemainingCost(new Map(), ["execute-task"]), 0);
|
|
108
|
+
});
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
describe("end-to-end budget prediction (composes the real functions)", () => {
|
|
112
|
+
test("budget ceiling exceeded is detectable from real averages + projection", () => {
|
|
113
|
+
const units = [
|
|
114
|
+
makeUnit({ type: "execute-task", cost: 0.5 }),
|
|
115
|
+
makeUnit({ type: "execute-task", cost: 0.6 }),
|
|
116
|
+
makeUnit({ type: "plan-slice", cost: 0.3 }),
|
|
117
|
+
makeUnit({ type: "complete-slice", cost: 0.2 }),
|
|
118
|
+
];
|
|
119
|
+
const totalSpent = units.reduce((sum, u) => sum + u.cost, 0); // 1.60
|
|
120
|
+
const avgs = getAverageCostPerUnitType(units);
|
|
121
|
+
const predicted = predictRemainingCost(avgs, [
|
|
122
|
+
"execute-task",
|
|
123
|
+
"execute-task",
|
|
124
|
+
"execute-task",
|
|
125
|
+
]);
|
|
126
|
+
// avg execute-task = 0.55, predicted remaining = 3 × 0.55 = 1.65
|
|
127
|
+
// total = 1.60 + 1.65 = 3.25 > 2.50 ceiling
|
|
128
|
+
assert.ok(
|
|
129
|
+
totalSpent + predicted > 2.5,
|
|
130
|
+
"spent + predicted should exceed test ceiling",
|
|
131
|
+
);
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
test("budget ceiling not exceeded when averages stay low", () => {
|
|
135
|
+
const units = [
|
|
136
|
+
makeUnit({ type: "execute-task", cost: 0.1 }),
|
|
137
|
+
makeUnit({ type: "plan-slice", cost: 0.05 }),
|
|
138
|
+
];
|
|
139
|
+
const totalSpent = units.reduce((sum, u) => sum + u.cost, 0); // 0.15
|
|
140
|
+
const avgs = getAverageCostPerUnitType(units);
|
|
141
|
+
const predicted = predictRemainingCost(avgs, ["execute-task", "complete-slice"]);
|
|
142
|
+
assert.ok(
|
|
143
|
+
totalSpent + predicted <= 5.0,
|
|
144
|
+
"spent + predicted should stay under test ceiling",
|
|
145
|
+
);
|
|
146
|
+
});
|
|
220
147
|
});
|
|
@@ -1,73 +1,156 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Behavioural regression test for #3580 — complete-slice verification gate.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
* or failed slice
|
|
6
|
-
*
|
|
7
|
-
*
|
|
4
|
+
* The gate must reject completion when the verification or UAT content
|
|
5
|
+
* indicates a blocked or failed slice. Drives the real handler with
|
|
6
|
+
* blocked-signal fixtures and asserts on the returned error. Replaces an
|
|
7
|
+
* earlier test file that only string-matched the BLOCKED_SIGNALS regex
|
|
8
|
+
* literal in the source (Refs #4826/#4831).
|
|
8
9
|
*/
|
|
9
10
|
|
|
10
|
-
import { describe,
|
|
11
|
-
import assert from 'node:assert/strict'
|
|
12
|
-
import
|
|
13
|
-
import
|
|
14
|
-
import
|
|
11
|
+
import { describe, test, beforeEach, afterEach } from 'node:test';
|
|
12
|
+
import assert from 'node:assert/strict';
|
|
13
|
+
import * as fs from 'node:fs';
|
|
14
|
+
import * as path from 'node:path';
|
|
15
|
+
import * as os from 'node:os';
|
|
15
16
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
17
|
+
import {
|
|
18
|
+
openDatabase,
|
|
19
|
+
closeDatabase,
|
|
20
|
+
insertMilestone,
|
|
21
|
+
insertSlice,
|
|
22
|
+
insertTask,
|
|
23
|
+
} from '../gsd-db.ts';
|
|
24
|
+
import { handleCompleteSlice } from '../tools/complete-slice.ts';
|
|
25
|
+
import type { CompleteSliceParams } from '../types.ts';
|
|
26
|
+
|
|
27
|
+
function tempDbPath(): string {
|
|
28
|
+
const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'gsd-blocked-gate-'));
|
|
29
|
+
return path.join(dir, 'test.db');
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function cleanupDb(dbPath: string): void {
|
|
33
|
+
closeDatabase();
|
|
34
|
+
try { fs.rmSync(path.dirname(dbPath), { recursive: true, force: true }); } catch { /* */ }
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function makeProject(): string {
|
|
38
|
+
const basePath = fs.mkdtempSync(path.join(os.tmpdir(), 'gsd-gate-proj-'));
|
|
39
|
+
fs.mkdirSync(path.join(basePath, '.gsd', 'milestones', 'M001', 'slices', 'S01', 'tasks'), { recursive: true });
|
|
40
|
+
fs.writeFileSync(
|
|
41
|
+
path.join(basePath, '.gsd', 'milestones', 'M001', 'M001-ROADMAP.md'),
|
|
42
|
+
`# M001\n\n## Slices\n- [ ] **S01: Test** \`risk:low\` \`depends:[]\`\n - After this: works\n`,
|
|
43
|
+
);
|
|
44
|
+
return basePath;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function makeParams(overrides: Partial<CompleteSliceParams>): CompleteSliceParams {
|
|
48
|
+
return {
|
|
49
|
+
sliceId: 'S01',
|
|
50
|
+
milestoneId: 'M001',
|
|
51
|
+
sliceTitle: 'Test Slice',
|
|
52
|
+
oneLiner: 'one liner',
|
|
53
|
+
narrative: 'narrative',
|
|
54
|
+
verification: 'all green',
|
|
55
|
+
deviations: 'None.',
|
|
56
|
+
knownLimitations: 'None.',
|
|
57
|
+
followUps: 'None.',
|
|
58
|
+
keyFiles: [],
|
|
59
|
+
keyDecisions: [],
|
|
60
|
+
patternsEstablished: [],
|
|
61
|
+
observabilitySurfaces: [],
|
|
62
|
+
provides: [],
|
|
63
|
+
requirementsSurfaced: [],
|
|
64
|
+
drillDownPaths: [],
|
|
65
|
+
affects: [],
|
|
66
|
+
requirementsAdvanced: [],
|
|
67
|
+
requirementsValidated: [],
|
|
68
|
+
requirementsInvalidated: [],
|
|
69
|
+
filesModified: [],
|
|
70
|
+
requires: [],
|
|
71
|
+
uatContent: 'UAT body.',
|
|
72
|
+
...overrides,
|
|
73
|
+
};
|
|
74
|
+
}
|
|
20
75
|
|
|
21
76
|
describe('complete-slice verification gate (#3580)', () => {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
)
|
|
27
|
-
|
|
77
|
+
let dbPath: string;
|
|
78
|
+
let basePath: string;
|
|
79
|
+
|
|
80
|
+
beforeEach(() => {
|
|
81
|
+
dbPath = tempDbPath();
|
|
82
|
+
openDatabase(dbPath);
|
|
83
|
+
basePath = makeProject();
|
|
84
|
+
insertMilestone({ id: 'M001' });
|
|
85
|
+
insertSlice({ id: 'S01', milestoneId: 'M001' });
|
|
86
|
+
insertTask({ id: 'T01', sliceId: 'S01', milestoneId: 'M001', status: 'complete', title: 'T1' });
|
|
87
|
+
});
|
|
28
88
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
const lineEnd = src.indexOf(';', idx)
|
|
34
|
-
const definition = src.slice(idx, lineEnd)
|
|
89
|
+
afterEach(() => {
|
|
90
|
+
cleanupDb(dbPath);
|
|
91
|
+
try { fs.rmSync(basePath, { recursive: true, force: true }); } catch { /* */ }
|
|
92
|
+
});
|
|
35
93
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
)
|
|
94
|
+
test('rejects when verification text contains "verification failed"', async () => {
|
|
95
|
+
const result = await handleCompleteSlice(
|
|
96
|
+
makeParams({ verification: 'verification failed: the regression came back' }),
|
|
97
|
+
basePath,
|
|
98
|
+
);
|
|
99
|
+
assert.ok('error' in result, 'expected handler to return an error');
|
|
100
|
+
assert.match((result as { error: string }).error, /blocked|failed|do not complete/i);
|
|
101
|
+
});
|
|
41
102
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
103
|
+
test('rejects when uatContent contains "verification_result: failed"', async () => {
|
|
104
|
+
const result = await handleCompleteSlice(
|
|
105
|
+
makeParams({ uatContent: '## Result\nverification_result: failed\n' }),
|
|
106
|
+
basePath,
|
|
107
|
+
);
|
|
108
|
+
assert.ok('error' in result, 'expected handler to return an error');
|
|
109
|
+
assert.match((result as { error: string }).error, /blocked|failed|do not complete/i);
|
|
110
|
+
});
|
|
46
111
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
112
|
+
test('rejects when verification declares "status: blocked"', async () => {
|
|
113
|
+
const result = await handleCompleteSlice(
|
|
114
|
+
makeParams({ verification: 'status: blocked — db unavailable' }),
|
|
115
|
+
basePath,
|
|
116
|
+
);
|
|
117
|
+
assert.ok('error' in result, 'expected handler to return an error');
|
|
118
|
+
assert.match((result as { error: string }).error, /blocked|failed|do not complete/i);
|
|
119
|
+
});
|
|
52
120
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
121
|
+
test('rejects when uatContent says "slice is blocked"', async () => {
|
|
122
|
+
const result = await handleCompleteSlice(
|
|
123
|
+
makeParams({ uatContent: 'slice is blocked on upstream' }),
|
|
124
|
+
basePath,
|
|
125
|
+
);
|
|
126
|
+
assert.ok('error' in result, 'expected handler to return an error');
|
|
127
|
+
assert.match((result as { error: string }).error, /blocked|failed|do not complete/i);
|
|
128
|
+
});
|
|
57
129
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
130
|
+
test('rejects when verification says "cannot complete"', async () => {
|
|
131
|
+
const result = await handleCompleteSlice(
|
|
132
|
+
makeParams({ verification: 'cannot complete: requirements unmet' }),
|
|
133
|
+
basePath,
|
|
134
|
+
);
|
|
135
|
+
assert.ok('error' in result, 'expected handler to return an error');
|
|
136
|
+
assert.match((result as { error: string }).error, /blocked|failed|do not complete/i);
|
|
137
|
+
});
|
|
62
138
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
)
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
)
|
|
72
|
-
|
|
73
|
-
|
|
139
|
+
test('passes the gate when verification + uatContent are clean', async () => {
|
|
140
|
+
// Sanity: the gate is not over-eager. Clean inputs reach the rest of
|
|
141
|
+
// the handler. (This call may still fail downstream because we provide
|
|
142
|
+
// a thin fixture; the only guarantee here is that the error — if any —
|
|
143
|
+
// is NOT the blocked-signals error.)
|
|
144
|
+
const result = await handleCompleteSlice(
|
|
145
|
+
makeParams({ verification: 'all 8 sections pass', uatContent: 'green across the board' }),
|
|
146
|
+
basePath,
|
|
147
|
+
);
|
|
148
|
+
if ('error' in result) {
|
|
149
|
+
assert.doesNotMatch(
|
|
150
|
+
result.error,
|
|
151
|
+
/blocked\/failed state — do not complete/,
|
|
152
|
+
`clean inputs should not be rejected by the BLOCKED_SIGNALS gate, got: ${result.error}`,
|
|
153
|
+
);
|
|
154
|
+
}
|
|
155
|
+
});
|
|
156
|
+
});
|
|
@@ -13,6 +13,7 @@ import {
|
|
|
13
13
|
getSlice,
|
|
14
14
|
updateSliceStatus,
|
|
15
15
|
getSliceTasks,
|
|
16
|
+
SCHEMA_VERSION,
|
|
16
17
|
} from '../gsd-db.ts';
|
|
17
18
|
import { handleCompleteSlice } from '../tools/complete-slice.ts';
|
|
18
19
|
import type { CompleteSliceParams } from '../types.ts';
|
|
@@ -115,19 +116,21 @@ Run the test suite and verify all assertions pass.
|
|
|
115
116
|
}
|
|
116
117
|
|
|
117
118
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
118
|
-
// complete-slice:
|
|
119
|
+
// complete-slice: fresh DB migrates to current schema version
|
|
119
120
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
120
121
|
|
|
121
|
-
console.log('\n=== complete-slice: schema
|
|
122
|
+
console.log('\n=== complete-slice: fresh DB migrates to current schema version ===');
|
|
122
123
|
{
|
|
123
124
|
const dbPath = tempDbPath();
|
|
124
125
|
openDatabase(dbPath);
|
|
125
126
|
|
|
126
127
|
const adapter = _getAdapter()!;
|
|
127
128
|
|
|
128
|
-
//
|
|
129
|
+
// Pin schema version against the source-of-truth constant so this test
|
|
130
|
+
// survives migration bumps but still catches a "fresh DB was not migrated"
|
|
131
|
+
// regression.
|
|
129
132
|
const versionRow = adapter.prepare('SELECT MAX(version) as v FROM schema_version').get();
|
|
130
|
-
assertEq(versionRow?.['v'],
|
|
133
|
+
assertEq(versionRow?.['v'], SCHEMA_VERSION, 'fresh DB should be migrated to current SCHEMA_VERSION');
|
|
131
134
|
|
|
132
135
|
// Verify slices table has full_summary_md and full_uat_md columns
|
|
133
136
|
const cols = adapter.prepare("PRAGMA table_info(slices)").all();
|