gsd-pi 2.78.1-dev.84a383f51 → 2.78.1
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/cli.js +55 -95
- package/dist/headless-query.d.ts +0 -22
- package/dist/headless-query.js +4 -24
- package/dist/headless.d.ts +0 -10
- package/dist/headless.js +1 -16
- package/dist/loader.js +10 -7
- package/dist/onboarding.d.ts +0 -10
- package/dist/onboarding.js +2 -2
- package/dist/provider-migrations.d.ts +2 -2
- package/dist/provider-migrations.js +2 -5
- package/dist/resource-loader.d.ts +2 -5
- package/dist/resource-loader.js +5 -28
- package/dist/resources/extensions/browser-tools/tests/browser-tools-integration.test.mjs +601 -0
- package/dist/resources/extensions/browser-tools/tests/browser-tools-unit.test.cjs +651 -0
- package/dist/resources/extensions/browser-tools/tests/capture-sharp-optional.test.cjs +91 -0
- package/dist/resources/extensions/gsd/auto/loop.js +0 -23
- package/dist/resources/extensions/gsd/auto/phases.js +2 -2
- package/dist/resources/extensions/gsd/auto/run-unit.js +1 -3
- package/dist/resources/extensions/gsd/auto/session.js +0 -3
- package/dist/resources/extensions/gsd/auto-recovery.js +4 -43
- 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 +0 -30
- package/dist/resources/extensions/gsd/auto.js +5 -14
- package/dist/resources/extensions/gsd/bootstrap/db-tools.js +2 -14
- package/dist/resources/extensions/gsd/bootstrap/exec-tools.js +5 -7
- package/dist/resources/extensions/gsd/bootstrap/query-tools.js +2 -2
- package/dist/resources/extensions/gsd/bootstrap/register-extension.js +4 -5
- package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +31 -94
- package/dist/resources/extensions/gsd/bootstrap/register-shortcuts.js +6 -11
- package/dist/resources/extensions/gsd/bootstrap/system-context.js +8 -34
- package/dist/resources/extensions/gsd/bootstrap/write-gate.js +2 -38
- package/dist/resources/extensions/gsd/commands/catalog.js +5 -69
- package/dist/resources/extensions/gsd/commands/handlers/core.js +1 -22
- package/dist/resources/extensions/gsd/commands-mcp-status.js +1 -3
- package/dist/resources/extensions/gsd/commands-prefs-wizard.js +1 -10
- package/dist/resources/extensions/gsd/dashboard-overlay.js +1 -1
- package/dist/resources/extensions/gsd/docs/preferences-reference.md +0 -4
- package/dist/resources/extensions/gsd/doctor-runtime-checks.js +1 -39
- 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 +5 -12
- package/dist/resources/extensions/gsd/gsd-db.js +2 -11
- package/dist/resources/extensions/gsd/guided-flow.js +23 -23
- package/dist/resources/extensions/gsd/memory-store.js +31 -66
- package/dist/resources/extensions/gsd/model-router.js +9 -114
- package/dist/resources/extensions/gsd/native-git-bridge.js +1 -7
- package/dist/resources/extensions/gsd/preferences-models.js +15 -91
- package/dist/resources/extensions/gsd/preferences-types.js +0 -2
- package/dist/resources/extensions/gsd/preferences-validation.js +0 -32
- package/dist/resources/extensions/gsd/preferences.js +3 -5
- package/dist/resources/extensions/gsd/prompt-loader.js +12 -23
- package/dist/resources/extensions/gsd/slice-parallel-orchestrator.js +3 -9
- package/dist/resources/extensions/gsd/state.js +0 -42
- package/dist/resources/extensions/gsd/templates/PREFERENCES.md +0 -1
- package/dist/resources/extensions/gsd/tests/auto-supervisor.test.mjs +53 -0
- package/dist/resources/extensions/gsd/tests/dist-redirect.mjs +112 -0
- package/dist/resources/extensions/gsd/tests/resolve-ts-hooks.mjs +23 -0
- package/dist/resources/extensions/gsd/tests/resolve-ts.mjs +5 -0
- package/dist/resources/extensions/gsd/tools/memory-tools.js +1 -18
- package/dist/resources/extensions/gsd/visualizer-overlay.js +1 -1
- package/dist/resources/extensions/gsd/watch/header-renderer.js +1 -3
- package/dist/resources/extensions/gsd/worktree-command.js +46 -26
- package/dist/resources/extensions/mcp-client/index.js +3 -6
- package/dist/resources/extensions/slash-commands/create-extension.js +22 -36
- package/dist/resources/skills/create-gsd-extension/SKILL.md +5 -9
- 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 +12 -32
- 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 +608 -0
- package/dist/rtk-shared.d.ts +0 -3
- package/dist/rtk-shared.js +0 -17
- package/dist/rtk.d.ts +5 -2
- package/dist/rtk.js +20 -3
- 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 +13 -13
- 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 +4 -44
- package/dist/web/standalone/.next/required-server-files.json +3 -3
- package/dist/web/standalone/.next/server/app/_global-error/page.js +3 -3
- package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found/page.js +2 -2
- package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.rsc +3 -3
- package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +3 -3
- package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +3 -3
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/api/boot/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/boot/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/browse-directories/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/browse-directories/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/captures/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/captures/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/cleanup/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/cleanup/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/dev-mode/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/dev-mode/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/doctor/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/doctor/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/experimental/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/experimental/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/export-data/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/export-data/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/files/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/files/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/forensics/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/forensics/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/git/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/history/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/history/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/hooks/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/hooks/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/inspect/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/inspect/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/knowledge/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/knowledge/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/live-state/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/live-state/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/notifications/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/notifications/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/onboarding/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/onboarding/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/preferences/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/preferences/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/projects/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/projects/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/recovery/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/recovery/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/remote-questions/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/remote-questions/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/browser/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/browser/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/command/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/command/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/events/route.js +2 -4
- package/dist/web/standalone/.next/server/app/api/session/events/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/manage/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/manage/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/settings-data/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/settings-data/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/shutdown/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/shutdown/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/skill-health/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/skill-health/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/steer/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/steer/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/switch-root/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/switch-root/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/input/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/terminal/input/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/resize/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/terminal/resize/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js +2 -2
- 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_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/upload/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/upload/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/undo/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/undo/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/update/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/visualizer/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/visualizer/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/index.html +1 -1
- package/dist/web/standalone/.next/server/app/index.rsc +4 -4
- package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
- package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +4 -4
- package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +3 -3
- package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/page.js +2 -2
- package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app-paths-manifest.json +13 -13
- package/dist/web/standalone/.next/server/chunks/63.js +3 -3
- package/dist/web/standalone/.next/server/chunks/6897.js +1 -1
- package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
- package/dist/web/standalone/.next/server/middleware-manifest.json +5 -5
- package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
- package/dist/web/standalone/.next/server/middleware.js +2 -2
- package/dist/web/standalone/.next/server/next-font-manifest.js +1 -1
- package/dist/web/standalone/.next/server/next-font-manifest.json +1 -1
- package/dist/web/standalone/.next/server/pages/404.html +1 -1
- package/dist/web/standalone/.next/server/pages/500.html +1 -1
- package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
- package/dist/web/standalone/.next/server/webpack-runtime.js +1 -1
- package/dist/web/standalone/.next/static/chunks/2826.e9f5195e91f9cad2.js +11 -0
- package/dist/web/standalone/.next/static/chunks/3621.fc7480022c972438.js +20 -0
- package/dist/web/standalone/.next/static/chunks/app/_not-found/{page-f2a7482d42a5614b.js → page-2f24283c162b6ab3.js} +1 -1
- package/dist/web/standalone/.next/static/chunks/app/{layout-a16c7a7ecdf0c2cf.js → layout-9ecfd95f343793f0.js} +1 -1
- package/dist/web/standalone/.next/static/chunks/app/page-151349214571e2b6.js +1 -0
- package/dist/web/standalone/.next/static/chunks/main-app-d3d4c336195465f9.js +1 -0
- package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-ab5a8926e07ec673.js +1 -0
- package/dist/web/standalone/.next/static/chunks/webpack-2e68521d7c82f7c2.js +1 -0
- package/dist/web/standalone/node_modules/node-pty/build/Makefile +2 -2
- package/dist/web/standalone/node_modules/node-pty/build/Release/pty.node +0 -0
- package/dist/web/standalone/node_modules/node-pty/build/pty.target.mk +14 -14
- package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api.target.mk +14 -14
- package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_except.target.mk +14 -14
- package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_maybe.target.mk +14 -14
- package/dist/web/standalone/package.json +1 -2
- package/dist/web/standalone/server.js +1 -1
- package/package.json +1 -1
- package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
- package/packages/mcp-server/dist/workflow-tools.js +46 -74
- package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
- package/packages/mcp-server/src/workflow-tools.test.ts +0 -26
- package/packages/mcp-server/src/workflow-tools.ts +58 -93
- package/packages/mcp-server/tsconfig.tsbuildinfo +1 -1
- package/packages/pi-agent-core/tsconfig.tsbuildinfo +1 -1
- package/packages/pi-ai/dist/providers/anthropic-shared.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/anthropic-shared.js +19 -48
- package/packages/pi-ai/dist/providers/anthropic-shared.js.map +1 -1
- package/packages/pi-ai/dist/types.d.ts +0 -13
- 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 +3 -24
- 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 +0 -26
- package/packages/pi-ai/dist/utils/tests/repair-tool-json.test.js.map +1 -1
- package/packages/pi-ai/src/providers/anthropic-shared.ts +20 -52
- package/packages/pi-ai/src/types.ts +0 -13
- package/packages/pi-ai/src/utils/repair-tool-json.ts +3 -24
- package/packages/pi-ai/src/utils/tests/repair-tool-json.test.ts +0 -32
- 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 +0 -6
- 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 +0 -4
- 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 +2 -19
- 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 +0 -10
- package/packages/pi-coding-agent/dist/core/model-registry.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/model-registry.js +0 -18
- package/packages/pi-coding-agent/dist/core/model-registry.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/system-prompt.d.ts +0 -13
- package/packages/pi-coding-agent/dist/core/system-prompt.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/system-prompt.js +16 -20
- package/packages/pi-coding-agent/dist/core/system-prompt.js.map +1 -1
- 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 +1 -14
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.test.js.map +1 -1
- package/packages/pi-coding-agent/src/core/agent-session.ts +0 -7
- package/packages/pi-coding-agent/src/core/messages.ts +0 -4
- package/packages/pi-coding-agent/src/core/model-registry-auth-mode.test.ts +2 -32
- package/packages/pi-coding-agent/src/core/model-registry.ts +0 -21
- package/packages/pi-coding-agent/src/core/system-prompt.ts +15 -33
- package/packages/pi-coding-agent/src/modes/interactive/controllers/input-controller.test.ts +1 -17
- package/packages/pi-coding-agent/src/modes/interactive/controllers/input-controller.ts +1 -1
- package/packages/pi-coding-agent/tsconfig.tsbuildinfo +1 -1
- package/packages/pi-tui/dist/__tests__/autocomplete.test.js +3 -17
- package/packages/pi-tui/dist/__tests__/autocomplete.test.js.map +1 -1
- package/packages/pi-tui/src/__tests__/autocomplete.test.ts +3 -20
- package/packages/pi-tui/tsconfig.tsbuildinfo +1 -1
- package/src/resources/extensions/gsd/auto/loop.ts +2 -24
- package/src/resources/extensions/gsd/auto/phases.ts +3 -3
- package/src/resources/extensions/gsd/auto/run-unit.ts +1 -3
- package/src/resources/extensions/gsd/auto/session.ts +0 -3
- package/src/resources/extensions/gsd/auto/types.ts +0 -1
- package/src/resources/extensions/gsd/auto-recovery.ts +8 -46
- package/src/resources/extensions/gsd/auto-start.ts +1 -1
- package/src/resources/extensions/gsd/auto-tool-tracking.ts +4 -2
- package/src/resources/extensions/gsd/auto-worktree.ts +0 -38
- package/src/resources/extensions/gsd/auto.ts +4 -14
- package/src/resources/extensions/gsd/bootstrap/db-tools.ts +13 -15
- package/src/resources/extensions/gsd/bootstrap/exec-tools.ts +7 -8
- package/src/resources/extensions/gsd/bootstrap/query-tools.ts +2 -2
- package/src/resources/extensions/gsd/bootstrap/register-extension.ts +9 -10
- package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +31 -102
- package/src/resources/extensions/gsd/bootstrap/register-shortcuts.ts +6 -12
- package/src/resources/extensions/gsd/bootstrap/system-context.ts +8 -39
- package/src/resources/extensions/gsd/bootstrap/write-gate.ts +11 -39
- package/src/resources/extensions/gsd/commands/catalog.ts +5 -75
- package/src/resources/extensions/gsd/commands/handlers/core.ts +1 -22
- package/src/resources/extensions/gsd/commands-mcp-status.ts +1 -3
- package/src/resources/extensions/gsd/commands-prefs-wizard.ts +1 -15
- package/src/resources/extensions/gsd/dashboard-overlay.ts +1 -1
- package/src/resources/extensions/gsd/docs/preferences-reference.md +0 -4
- package/src/resources/extensions/gsd/doctor-runtime-checks.ts +1 -39
- package/src/resources/extensions/gsd/doctor-types.ts +1 -3
- 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 +5 -13
- package/src/resources/extensions/gsd/gsd-db.ts +2 -12
- package/src/resources/extensions/gsd/guided-flow.ts +25 -25
- package/src/resources/extensions/gsd/memory-store.ts +28 -81
- package/src/resources/extensions/gsd/model-router.ts +9 -172
- package/src/resources/extensions/gsd/native-git-bridge.ts +1 -7
- package/src/resources/extensions/gsd/preferences-models.ts +15 -101
- package/src/resources/extensions/gsd/preferences-types.ts +0 -6
- package/src/resources/extensions/gsd/preferences-validation.ts +0 -35
- package/src/resources/extensions/gsd/preferences.ts +2 -16
- package/src/resources/extensions/gsd/prompt-loader.ts +12 -26
- package/src/resources/extensions/gsd/slice-parallel-orchestrator.ts +3 -9
- package/src/resources/extensions/gsd/state.ts +0 -42
- package/src/resources/extensions/gsd/templates/PREFERENCES.md +0 -1
- package/src/resources/extensions/gsd/tests/auto-loop.test.ts +1 -178
- package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +0 -58
- package/src/resources/extensions/gsd/tests/auto-session-encapsulation.test.ts +5 -9
- package/src/resources/extensions/gsd/tests/auto-supervisor.test.mjs +4 -21
- 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 +211 -138
- package/src/resources/extensions/gsd/tests/complete-slice-verification-gate.test.ts +59 -142
- package/src/resources/extensions/gsd/tests/complete-slice.test.ts +4 -7
- package/src/resources/extensions/gsd/tests/completed-at-reconcile.test.ts +32 -89
- package/src/resources/extensions/gsd/tests/copy-planning-artifacts-samepath.test.ts +22 -0
- package/src/resources/extensions/gsd/tests/custom-engine-loop-integration.test.ts +23 -41
- package/src/resources/extensions/gsd/tests/db-path-worktree-symlink.test.ts +43 -3
- package/src/resources/extensions/gsd/tests/debug-logger.test.ts +3 -5
- package/src/resources/extensions/gsd/tests/discuss-empty-db-fallback.test.ts +87 -22
- package/src/resources/extensions/gsd/tests/discuss-queued-milestones.test.ts +118 -7
- package/src/resources/extensions/gsd/tests/discuss-slice-structured-questions.test.ts +47 -0
- package/src/resources/extensions/gsd/tests/discuss-tool-scope-leak.test.ts +60 -18
- package/src/resources/extensions/gsd/tests/double-merge-guard.test.ts +76 -14
- package/src/resources/extensions/gsd/tests/empty-content-abort-loop.test.ts +75 -0
- package/src/resources/extensions/gsd/tests/false-degraded-mode-warning.test.ts +83 -22
- package/src/resources/extensions/gsd/tests/finalize-timeout-guard.test.ts +63 -1
- package/src/resources/extensions/gsd/tests/forensics-stuck-loops.test.ts +1 -26
- package/src/resources/extensions/gsd/tests/gsd-db.test.ts +0 -30
- package/src/resources/extensions/gsd/tests/headless-answers.test.ts +4 -14
- package/src/resources/extensions/gsd/tests/health-widget.test.ts +12 -22
- package/src/resources/extensions/gsd/tests/init-prefs-routing.test.ts +1 -64
- package/src/resources/extensions/gsd/tests/integration/auto-worktree.test.ts +0 -22
- package/src/resources/extensions/gsd/tests/integration/token-savings.test.ts +23 -0
- package/src/resources/extensions/gsd/tests/memory-store.test.ts +0 -128
- package/src/resources/extensions/gsd/tests/memory-tools.test.ts +1 -33
- package/src/resources/extensions/gsd/tests/model-router.test.ts +8 -169
- package/src/resources/extensions/gsd/tests/orphaned-worktree-audit.test.ts +0 -8
- package/src/resources/extensions/gsd/tests/parallel-crash-recovery.test.ts +43 -32
- package/src/resources/extensions/gsd/tests/phases-merge-error-stops-auto.test.ts +10 -4
- package/src/resources/extensions/gsd/tests/preferences.test.ts +0 -127
- package/src/resources/extensions/gsd/tests/prompt-step-ordering.test.ts +0 -16
- package/src/resources/extensions/gsd/tests/provider-errors.test.ts +0 -7
- package/src/resources/extensions/gsd/tests/quick-turn-end-cleanup.test.ts +6 -6
- package/src/resources/extensions/gsd/tests/session-start-footer.test.ts +19 -168
- package/src/resources/extensions/gsd/tests/slice-parallel-orchestrator.test.ts +1 -7
- package/src/resources/extensions/gsd/tests/smart-entry-complete.test.ts +1 -23
- package/src/resources/extensions/gsd/tests/token-profile.test.ts +4 -51
- package/src/resources/extensions/gsd/tests/turn-epoch.test.ts +16 -7
- package/src/resources/extensions/gsd/tests/unstructured-continue-context-injection.test.ts +7 -5
- package/src/resources/extensions/gsd/tests/uok-gitops-turn-action.test.ts +1 -15
- package/src/resources/extensions/gsd/tests/visualizer-overlay.test.ts +6 -6
- package/src/resources/extensions/gsd/tests/write-gate-planning-unit.test.ts +0 -15
- package/src/resources/extensions/gsd/tools/memory-tools.ts +1 -17
- 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 +1 -3
- package/src/resources/extensions/gsd/workflow-logger.ts +0 -1
- package/src/resources/extensions/gsd/worktree-command.ts +44 -31
- package/src/resources/extensions/mcp-client/index.ts +3 -6
- package/src/resources/extensions/slash-commands/create-extension.ts +24 -38
- package/src/resources/skills/create-gsd-extension/SKILL.md +5 -9
- 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/workflows/create-extension.md +12 -32
- package/dist/cli-policy.d.ts +0 -13
- package/dist/cli-policy.js +0 -17
- package/dist/resources/.managed-resources-content-hash +0 -1
- package/dist/resources/extensions/gsd/auto-runtime-state.js +0 -31
- package/dist/resources/extensions/gsd/milestone-id-reservation.js +0 -36
- package/dist/resources/extensions/gsd/worktree-session-state.js +0 -33
- package/dist/runtime-checks.d.ts +0 -27
- package/dist/runtime-checks.js +0 -38
- package/dist/web/standalone/.next/static/chunks/2556.0527fea66e123b7f.js +0 -1
- package/dist/web/standalone/.next/static/chunks/2824.08296bc2f9654698.js +0 -1
- package/dist/web/standalone/.next/static/chunks/3026.3af53b279375f082.js +0 -1
- package/dist/web/standalone/.next/static/chunks/315.6f68ae79b67d25cf.js +0 -1
- package/dist/web/standalone/.next/static/chunks/3497.4bfc60a3b3dea717.js +0 -1
- package/dist/web/standalone/.next/static/chunks/5516.4a07c872b5c3a663.js +0 -1
- package/dist/web/standalone/.next/static/chunks/8336.31b019697882acfb.js +0 -10
- package/dist/web/standalone/.next/static/chunks/8845.c9702695e8c5a9c5.js +0 -2
- package/dist/web/standalone/.next/static/chunks/9058.01ef3a463bda88f1.js +0 -20
- package/dist/web/standalone/.next/static/chunks/9441.1081da1125d1764f.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/page-9bf2e0c50fb2ca05.js +0 -1
- package/dist/web/standalone/.next/static/chunks/main-app-fdab67f7802d7832.js +0 -1
- package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-459824ffb8c323dd.js +0 -1
- package/dist/web/standalone/.next/static/chunks/webpack-f9f0dc45e4f3ac10.js +0 -1
- package/dist/worktree-status-banner.d.ts +0 -1
- package/dist/worktree-status-banner.js +0 -132
- package/packages/mcp-server/dist/alias-telemetry.d.ts +0 -8
- package/packages/mcp-server/dist/alias-telemetry.d.ts.map +0 -1
- package/packages/mcp-server/dist/alias-telemetry.js +0 -30
- package/packages/mcp-server/dist/alias-telemetry.js.map +0 -1
- package/packages/mcp-server/src/alias-telemetry.test.ts +0 -78
- package/packages/mcp-server/src/alias-telemetry.ts +0 -30
- package/packages/pi-ai/dist/providers/anthropic-shared.cache-breakpoint.test.d.ts +0 -2
- package/packages/pi-ai/dist/providers/anthropic-shared.cache-breakpoint.test.d.ts.map +0 -1
- package/packages/pi-ai/dist/providers/anthropic-shared.cache-breakpoint.test.js +0 -231
- package/packages/pi-ai/dist/providers/anthropic-shared.cache-breakpoint.test.js.map +0 -1
- package/packages/pi-ai/src/providers/anthropic-shared.cache-breakpoint.test.ts +0 -289
- package/packages/pi-coding-agent/dist/core/token-telemetry.d.ts +0 -37
- package/packages/pi-coding-agent/dist/core/token-telemetry.d.ts.map +0 -1
- package/packages/pi-coding-agent/dist/core/token-telemetry.js +0 -49
- package/packages/pi-coding-agent/dist/core/token-telemetry.js.map +0 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-card-cleanup-and-success-runtime.test.d.ts +0 -2
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-card-cleanup-and-success-runtime.test.d.ts.map +0 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-card-cleanup-and-success-runtime.test.js +0 -133
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-card-cleanup-and-success-runtime.test.js.map +0 -1
- package/packages/pi-coding-agent/dist/tests/system-prompt-cache-stability.test.d.ts +0 -2
- package/packages/pi-coding-agent/dist/tests/system-prompt-cache-stability.test.d.ts.map +0 -1
- package/packages/pi-coding-agent/dist/tests/system-prompt-cache-stability.test.js +0 -78
- package/packages/pi-coding-agent/dist/tests/system-prompt-cache-stability.test.js.map +0 -1
- package/packages/pi-coding-agent/dist/tests/token-telemetry.test.d.ts +0 -2
- package/packages/pi-coding-agent/dist/tests/token-telemetry.test.d.ts.map +0 -1
- package/packages/pi-coding-agent/dist/tests/token-telemetry.test.js +0 -181
- package/packages/pi-coding-agent/dist/tests/token-telemetry.test.js.map +0 -1
- package/packages/pi-coding-agent/src/core/token-telemetry.ts +0 -77
- package/packages/pi-coding-agent/src/modes/interactive/components/tool-card-cleanup-and-success-runtime.test.ts +0 -212
- package/packages/pi-coding-agent/src/tests/system-prompt-cache-stability.test.ts +0 -102
- package/packages/pi-coding-agent/src/tests/token-telemetry.test.ts +0 -200
- package/packages/pi-tui/dist/components/__tests__/leak-fixes-runtime.test.d.ts +0 -2
- package/packages/pi-tui/dist/components/__tests__/leak-fixes-runtime.test.d.ts.map +0 -1
- package/packages/pi-tui/dist/components/__tests__/leak-fixes-runtime.test.js +0 -161
- package/packages/pi-tui/dist/components/__tests__/leak-fixes-runtime.test.js.map +0 -1
- package/packages/pi-tui/src/components/__tests__/leak-fixes-runtime.test.ts +0 -219
- package/src/resources/extensions/gsd/auto-runtime-state.ts +0 -51
- package/src/resources/extensions/gsd/milestone-id-reservation.ts +0 -47
- package/src/resources/extensions/gsd/tests/deferred-milestone-dir-4996.test.ts +0 -116
- package/src/resources/extensions/gsd/tests/doctor-orphan-milestone-4996.test.ts +0 -100
- package/src/resources/extensions/gsd/tests/ensure-preconditions-guard-4996.test.ts +0 -93
- package/src/resources/extensions/gsd/tests/find-missing-summaries-closed-runtime.test.ts +0 -47
- package/src/resources/extensions/gsd/tests/gitignore-bg-shell-runtime.test.ts +0 -63
- package/src/resources/extensions/gsd/tests/gsd-no-project-error-runtime.test.ts +0 -81
- package/src/resources/extensions/gsd/tests/help-menu-coverage.test.ts +0 -57
- package/src/resources/extensions/gsd/tests/import-done-milestones-runtime.test.ts +0 -145
- package/src/resources/extensions/gsd/tests/merge-self-branch-guard.test.ts +0 -124
- package/src/resources/extensions/gsd/tests/milestone-id-gap-reuse-4996.test.ts +0 -152
- package/src/resources/extensions/gsd/tests/native-git-infra-errors.test.ts +0 -50
- package/src/resources/extensions/gsd/tests/register-hooks-compaction-checkpoint.test.ts +0 -93
- package/src/resources/extensions/gsd/tests/system-context-message-routing.test.ts +0 -101
- package/src/resources/extensions/gsd/worktree-session-state.ts +0 -35
- package/src/resources/extensions/mcp-client/tests/global-config.test.ts +0 -91
- package/src/resources/skills/create-gsd-extension/templates/templates.test.ts +0 -58
- /package/dist/web/standalone/.next/static/{UF5VF4F1tB0miEtJS7LyX → 7afp7gq8-DVbxum83zRQ-}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{UF5VF4F1tB0miEtJS7LyX → 7afp7gq8-DVbxum83zRQ-}/_ssgManifest.js +0 -0
|
@@ -1,99 +1,42 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Regression test for #4129: tasks.completed_at stays NULL when status is
|
|
3
|
+
* reconciled to 'complete' via the file-existence path in state.ts.
|
|
3
4
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* timestamp, leaving completed_at NULL forever.
|
|
5
|
+
* Root cause: reconcileSliceTasks called
|
|
6
|
+
* updateTaskStatus(milestoneId, sliceId, t.id, "complete")
|
|
7
|
+
* without a completedAt timestamp, so the column stays NULL.
|
|
8
8
|
*
|
|
9
|
-
*
|
|
10
|
-
* exercises that path end-to-end and asserts the column is populated.
|
|
11
|
-
*
|
|
12
|
-
* Refs #4829 (rewrite from positional source-grep).
|
|
9
|
+
* Fix: pass new Date().toISOString() as the 5th argument.
|
|
13
10
|
*/
|
|
14
11
|
|
|
15
|
-
import { describe, test
|
|
16
|
-
import assert from
|
|
17
|
-
import {
|
|
18
|
-
import { join } from
|
|
19
|
-
import {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
// Project structure with active milestone, one slice, one task whose
|
|
36
|
-
// SUMMARY.md is already on disk — but the DB row is still "pending".
|
|
37
|
-
mkdirSync(join(basePath, '.gsd', 'milestones', 'M001', 'slices', 'S01', 'tasks'), { recursive: true });
|
|
38
|
-
|
|
39
|
-
// CONTEXT + ROADMAP so deriveState identifies M001 as active and S01 as the active slice.
|
|
40
|
-
writeFileSync(
|
|
41
|
-
join(basePath, '.gsd', 'milestones', 'M001', 'M001-CONTEXT.md'),
|
|
42
|
-
'# M001\nActive milestone.\n',
|
|
43
|
-
);
|
|
44
|
-
writeFileSync(
|
|
45
|
-
join(basePath, '.gsd', 'milestones', 'M001', 'M001-ROADMAP.md'),
|
|
46
|
-
`# M001\n\n## Slices\n\n- [ ] **S01: Slice** \`risk:low\` \`depends:[]\`\n - After this: works\n`,
|
|
47
|
-
);
|
|
48
|
-
|
|
49
|
-
// Plan file for the slice so reconcile can populate task list if DB is empty.
|
|
50
|
-
writeFileSync(
|
|
51
|
-
join(basePath, '.gsd', 'milestones', 'M001', 'slices', 'S01', 'S01-PLAN.md'),
|
|
52
|
-
`# S01: Slice\n\n## Tasks\n\n- [ ] **T01: Test task** \`est:30m\`\n - Do: x\n - Verify: y\n`,
|
|
53
|
-
);
|
|
54
|
-
|
|
55
|
-
// The summary file: this is the on-disk evidence that flips the task
|
|
56
|
-
// status to "complete" inside reconcileSliceTasks.
|
|
57
|
-
writeFileSync(
|
|
58
|
-
join(basePath, '.gsd', 'milestones', 'M001', 'slices', 'S01', 'tasks', 'T01-SUMMARY.md'),
|
|
59
|
-
'---\nid: T01\nparent: S01\nmilestone: M001\nblocker_discovered: false\n---\n# T01\n',
|
|
60
|
-
);
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
describe('completed_at reconcile (#4129)', () => {
|
|
64
|
-
beforeEach(() => {
|
|
65
|
-
setupProject();
|
|
66
|
-
openDatabase(join(basePath, '.gsd', 'gsd.db'));
|
|
67
|
-
insertMilestone({ id: 'M001', title: 'M001', status: 'active' });
|
|
68
|
-
insertSlice({ id: 'S01', milestoneId: 'M001', title: 'Slice', status: 'active' });
|
|
69
|
-
// Task is "pending" in DB, but SUMMARY.md exists on disk → reconcile flips it.
|
|
70
|
-
insertTask({ id: 'T01', sliceId: 'S01', milestoneId: 'M001', title: 'Test task', status: 'pending' });
|
|
71
|
-
invalidateStateCache();
|
|
72
|
-
});
|
|
73
|
-
|
|
74
|
-
afterEach(() => {
|
|
75
|
-
closeDatabase();
|
|
76
|
-
try { rmSync(basePath, { recursive: true, force: true }); } catch { /* */ }
|
|
12
|
+
import { describe, test } from "node:test";
|
|
13
|
+
import assert from "node:assert/strict";
|
|
14
|
+
import { readFileSync } from "node:fs";
|
|
15
|
+
import { join, dirname } from "node:path";
|
|
16
|
+
import { fileURLToPath } from "node:url";
|
|
17
|
+
|
|
18
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
19
|
+
const stateSource = readFileSync(join(__dirname, "..", "state.ts"), "utf-8");
|
|
20
|
+
|
|
21
|
+
describe("completed-at reconcile (#4129)", () => {
|
|
22
|
+
test("reconcileSliceTasks passes a completedAt timestamp when setting status to complete", () => {
|
|
23
|
+
// Before the fix, state.ts had:
|
|
24
|
+
// updateTaskStatus(milestoneId, sliceId, t.id, "complete")
|
|
25
|
+
// which leaves completed_at NULL in the DB.
|
|
26
|
+
// After the fix, a timestamp must be passed as the 5th argument.
|
|
27
|
+
assert.doesNotMatch(
|
|
28
|
+
stateSource,
|
|
29
|
+
/updateTaskStatus\(\s*milestoneId\s*,\s*sliceId\s*,\s*t\.id\s*,\s*["']complete["']\s*\)/,
|
|
30
|
+
"updateTaskStatus must not be called without a completedAt timestamp when reconciling tasks to 'complete' (#4129)",
|
|
31
|
+
);
|
|
77
32
|
});
|
|
78
33
|
|
|
79
|
-
test(
|
|
80
|
-
|
|
81
|
-
assert.
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
await deriveStateFromDb(basePath);
|
|
86
|
-
|
|
87
|
-
const after = getTask('M001', 'S01', 'T01');
|
|
88
|
-
assert.strictEqual(after?.status, 'complete', 'task should be flipped to complete');
|
|
89
|
-
assert.ok(
|
|
90
|
-
typeof after?.completed_at === 'string' && after.completed_at.length > 0,
|
|
91
|
-
`completed_at must be populated by reconcileSliceTasks (#4129); got ${JSON.stringify(after?.completed_at)}`,
|
|
92
|
-
);
|
|
93
|
-
// Sanity: timestamp parses as a valid ISO date.
|
|
94
|
-
assert.ok(
|
|
95
|
-
!Number.isNaN(Date.parse(after!.completed_at!)),
|
|
96
|
-
`completed_at should be a valid ISO timestamp, got ${after!.completed_at}`,
|
|
34
|
+
test("reconcileSliceTasks passes new Date().toISOString() as the completedAt argument", () => {
|
|
35
|
+
// Positive assertion: the fixed call must include a timestamp.
|
|
36
|
+
assert.match(
|
|
37
|
+
stateSource,
|
|
38
|
+
/updateTaskStatus\(\s*milestoneId\s*,\s*sliceId\s*,\s*t\.id\s*,\s*["']complete["']\s*,\s*new Date\(\)\.toISOString\(\)\s*\)/,
|
|
39
|
+
"reconcileSliceTasks must pass new Date().toISOString() as completedAt when setting task status to 'complete' (#4129)",
|
|
97
40
|
);
|
|
98
41
|
});
|
|
99
42
|
});
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import test from "node:test";
|
|
2
|
+
import assert from "node:assert/strict";
|
|
3
|
+
import { readFileSync } from "node:fs";
|
|
4
|
+
import { join } from "node:path";
|
|
5
|
+
import { extractSourceRegion } from "./test-helpers.ts";
|
|
6
|
+
|
|
7
|
+
test("copyPlanningArtifacts skips when source and destination .gsd resolve to the same path", () => {
|
|
8
|
+
const srcPath = join(import.meta.dirname, "..", "auto-worktree.ts");
|
|
9
|
+
const src = readFileSync(srcPath, "utf-8");
|
|
10
|
+
|
|
11
|
+
const fnIdx = src.indexOf("function copyPlanningArtifacts");
|
|
12
|
+
assert.ok(fnIdx !== -1, "copyPlanningArtifacts function exists");
|
|
13
|
+
|
|
14
|
+
const fnBody = extractSourceRegion(src, "function copyPlanningArtifacts");
|
|
15
|
+
|
|
16
|
+
const guardIdx = fnBody.indexOf("if (isSamePath(srcGsd, dstGsd)) return;");
|
|
17
|
+
const copyIdx = fnBody.indexOf("safeCopyRecursive(join(srcGsd, \"milestones\")");
|
|
18
|
+
|
|
19
|
+
assert.ok(guardIdx !== -1, "copyPlanningArtifacts should guard same-path .gsd copies");
|
|
20
|
+
assert.ok(copyIdx !== -1, "copyPlanningArtifacts should still copy milestones when paths differ");
|
|
21
|
+
assert.ok(guardIdx < copyIdx, "same-path guard should run before any copy attempt");
|
|
22
|
+
});
|
|
@@ -12,7 +12,7 @@ import { mkdtempSync, rmSync, existsSync } from "node:fs";
|
|
|
12
12
|
import { join } from "node:path";
|
|
13
13
|
import { tmpdir } from "node:os";
|
|
14
14
|
|
|
15
|
-
import { autoLoop, resolveAgentEnd,
|
|
15
|
+
import { autoLoop, resolveAgentEnd, _resetPendingResolve } from "../auto-loop.js";
|
|
16
16
|
import type { LoopDeps } from "../auto/loop-deps.js";
|
|
17
17
|
import type { SessionLockStatus } from "../session-lock.js";
|
|
18
18
|
import { writeGraph, readGraph, type WorkflowGraph, type GraphStep } from "../graph.ts";
|
|
@@ -29,17 +29,6 @@ function makeTmpDir(): string {
|
|
|
29
29
|
return dir;
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
-
async function resolveNextAgentEnd(timeoutMs = 3_000): Promise<void> {
|
|
33
|
-
const deadline = Date.now() + timeoutMs;
|
|
34
|
-
while (!_hasPendingResolveForTest()) {
|
|
35
|
-
if (Date.now() > deadline) {
|
|
36
|
-
throw new Error("Timed out waiting for pending agent_end resolver");
|
|
37
|
-
}
|
|
38
|
-
await new Promise((r) => setTimeout(r, 5));
|
|
39
|
-
}
|
|
40
|
-
resolveAgentEnd({ messages: [{ role: "assistant" }] });
|
|
41
|
-
}
|
|
42
|
-
|
|
43
32
|
afterEach(() => {
|
|
44
33
|
_resetPendingResolve();
|
|
45
34
|
for (const d of tmpDirs) {
|
|
@@ -287,16 +276,19 @@ describe("Custom engine loop integration", () => {
|
|
|
287
276
|
// We need to resolve resolveAgentEnd for each step.
|
|
288
277
|
|
|
289
278
|
// Step 1: step-a
|
|
279
|
+
await new Promise((r) => setTimeout(r, 80));
|
|
290
280
|
unitCount++;
|
|
291
|
-
|
|
281
|
+
resolveAgentEnd({ messages: [{ role: "assistant" }] });
|
|
292
282
|
|
|
293
283
|
// Step 2: step-b
|
|
284
|
+
await new Promise((r) => setTimeout(r, 80));
|
|
294
285
|
unitCount++;
|
|
295
|
-
|
|
286
|
+
resolveAgentEnd({ messages: [{ role: "assistant" }] });
|
|
296
287
|
|
|
297
288
|
// Step 3: step-c
|
|
289
|
+
await new Promise((r) => setTimeout(r, 80));
|
|
298
290
|
unitCount++;
|
|
299
|
-
|
|
291
|
+
resolveAgentEnd({ messages: [{ role: "assistant" }] });
|
|
300
292
|
|
|
301
293
|
// After step-c completes, engine.reconcile marks it complete, then
|
|
302
294
|
// next deriveState sees isComplete=true → stopAuto → loop exits
|
|
@@ -406,7 +398,8 @@ describe("Custom engine loop integration", () => {
|
|
|
406
398
|
|
|
407
399
|
const loopPromise = autoLoop(ctx, pi, s, deps);
|
|
408
400
|
|
|
409
|
-
await
|
|
401
|
+
await new Promise((r) => setTimeout(r, 80));
|
|
402
|
+
resolveAgentEnd({ messages: [{ role: "assistant" }] });
|
|
410
403
|
|
|
411
404
|
await loopPromise;
|
|
412
405
|
|
|
@@ -467,10 +460,12 @@ describe("Custom engine loop integration", () => {
|
|
|
467
460
|
const loopPromise = autoLoop(ctx, pi, s, deps);
|
|
468
461
|
|
|
469
462
|
// Resolve step-a
|
|
470
|
-
await
|
|
463
|
+
await new Promise((r) => setTimeout(r, 80));
|
|
464
|
+
resolveAgentEnd({ messages: [{ role: "assistant" }] });
|
|
471
465
|
|
|
472
466
|
// Resolve step-b
|
|
473
|
-
await
|
|
467
|
+
await new Promise((r) => setTimeout(r, 80));
|
|
468
|
+
resolveAgentEnd({ messages: [{ role: "assistant" }] });
|
|
474
469
|
|
|
475
470
|
await loopPromise;
|
|
476
471
|
|
|
@@ -519,9 +514,7 @@ describe("Custom engine loop integration", () => {
|
|
|
519
514
|
});
|
|
520
515
|
|
|
521
516
|
const resolver = setInterval(() => {
|
|
522
|
-
|
|
523
|
-
resolveAgentEnd({ messages: [{ role: "assistant" }] });
|
|
524
|
-
}
|
|
517
|
+
resolveAgentEnd({ messages: [{ role: "assistant" }] });
|
|
525
518
|
}, 25);
|
|
526
519
|
let timeout: NodeJS.Timeout | undefined;
|
|
527
520
|
try {
|
|
@@ -576,9 +569,7 @@ describe("Custom engine loop integration", () => {
|
|
|
576
569
|
});
|
|
577
570
|
const deps1 = makeMockDeps();
|
|
578
571
|
const resolver1 = setInterval(() => {
|
|
579
|
-
|
|
580
|
-
resolveAgentEnd({ messages: [{ role: "assistant" }] });
|
|
581
|
-
}
|
|
572
|
+
resolveAgentEnd({ messages: [{ role: "assistant" }] });
|
|
582
573
|
if (pi1.calls.length >= 2) {
|
|
583
574
|
s1.active = false;
|
|
584
575
|
}
|
|
@@ -623,9 +614,7 @@ describe("Custom engine loop integration", () => {
|
|
|
623
614
|
},
|
|
624
615
|
});
|
|
625
616
|
const resolver2 = setInterval(() => {
|
|
626
|
-
|
|
627
|
-
resolveAgentEnd({ messages: [{ role: "assistant" }] });
|
|
628
|
-
}
|
|
617
|
+
resolveAgentEnd({ messages: [{ role: "assistant" }] });
|
|
629
618
|
}, 25);
|
|
630
619
|
let timeout2: NodeJS.Timeout | undefined;
|
|
631
620
|
try {
|
|
@@ -651,12 +640,7 @@ describe("Custom engine loop integration", () => {
|
|
|
651
640
|
assert.match(stopEntry ?? "", /requested retry 4 times without passing/);
|
|
652
641
|
});
|
|
653
642
|
|
|
654
|
-
it("
|
|
655
|
-
// Note (#4831): renamed from "GRAPH.yaml step stays pending when session
|
|
656
|
-
// deactivates before reconcile" — the assertion body never proved the
|
|
657
|
-
// pending-on-deactivate claim and even comments that "the reconcile
|
|
658
|
-
// will still run for step-b". The behaviour this test actually pins is:
|
|
659
|
-
// both steps reconcile complete and stopAuto fires once isComplete.
|
|
643
|
+
it("GRAPH.yaml step stays pending when session deactivates before reconcile", async () => {
|
|
660
644
|
_resetPendingResolve();
|
|
661
645
|
|
|
662
646
|
// Two-step workflow: a → b. We will complete step-a, then force a break
|
|
@@ -688,30 +672,28 @@ describe("Custom engine loop integration", () => {
|
|
|
688
672
|
const loopPromise = autoLoop(ctx, pi, s, deps);
|
|
689
673
|
|
|
690
674
|
// Resolve step-a successfully
|
|
691
|
-
await
|
|
675
|
+
await new Promise((r) => setTimeout(r, 80));
|
|
676
|
+
resolveAgentEnd({ messages: [{ role: "assistant" }] });
|
|
692
677
|
|
|
693
678
|
// Step-b enters runUnit — deactivate the session before resolving.
|
|
694
679
|
// runUnit checks s.active after newSession and returns cancelled if false.
|
|
695
680
|
// But since newSession resolves synchronously in our mock (before the
|
|
696
681
|
// active check), the unit still runs. Instead, let's just cancel it.
|
|
682
|
+
await new Promise((r) => setTimeout(r, 80));
|
|
697
683
|
// Resolve as cancelled to simulate a failed session
|
|
698
|
-
|
|
684
|
+
resolveAgentEnd({ messages: [{ role: "assistant" }] });
|
|
699
685
|
|
|
700
686
|
// The reconcile will still run for step-b in this flow since
|
|
701
687
|
// runUnitPhase returns "next" (not "break") for completed units.
|
|
702
688
|
// After both steps complete, the engine detects isComplete and stops.
|
|
703
689
|
await loopPromise;
|
|
704
690
|
|
|
705
|
-
//
|
|
706
|
-
// engine drives the workflow through isComplete rather than leaving any
|
|
707
|
-
// step pending.
|
|
691
|
+
// Verify step-a is complete
|
|
708
692
|
const finalGraph = readGraph(runDir);
|
|
709
693
|
const stepA = finalGraph.steps.find(s => s.id === "step-a");
|
|
710
|
-
const stepB = finalGraph.steps.find(s => s.id === "step-b");
|
|
711
694
|
assert.equal(stepA?.status, "complete", "Step-a should be complete");
|
|
712
|
-
assert.equal(stepB?.status, "complete", "Step-b should be complete");
|
|
713
695
|
|
|
714
|
-
//
|
|
696
|
+
// Verify the loop stopped appropriately
|
|
715
697
|
assert.ok(
|
|
716
698
|
deps.callLog.some((e: string) => e.startsWith("stopAuto:")),
|
|
717
699
|
"stopAuto should have been called",
|
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
* retrying can never succeed and causes cost spikes.
|
|
17
17
|
*/
|
|
18
18
|
|
|
19
|
+
import { readFileSync } from "node:fs";
|
|
19
20
|
import { join, sep } from "node:path";
|
|
20
21
|
import { createTestContext } from "./test-helpers.ts";
|
|
21
22
|
|
|
@@ -88,8 +89,47 @@ assertEq(
|
|
|
88
89
|
"Non-worktree path is unchanged",
|
|
89
90
|
);
|
|
90
91
|
|
|
91
|
-
//
|
|
92
|
-
|
|
93
|
-
|
|
92
|
+
// ── Part 2: ensureDbOpen returns structured failure context ──────────────
|
|
93
|
+
|
|
94
|
+
console.log("\n=== #2517 Part 2: ensureDbOpen structured diagnostics ===");
|
|
95
|
+
|
|
96
|
+
const dynamicToolsSrc = readFileSync(
|
|
97
|
+
join(import.meta.dirname, "..", "bootstrap", "dynamic-tools.ts"),
|
|
98
|
+
"utf-8",
|
|
99
|
+
);
|
|
100
|
+
|
|
101
|
+
// ensureDbOpen should surface diagnostic context, not just boolean false
|
|
102
|
+
// Check that the catch block logs error details via workflow-logger
|
|
103
|
+
assertTrue(
|
|
104
|
+
dynamicToolsSrc.includes("ensureDbOpen failed") && dynamicToolsSrc.includes("logWarning"),
|
|
105
|
+
"ensureDbOpen catch block surfaces diagnostic information via logWarning instead of bare false (#2517)",
|
|
106
|
+
);
|
|
107
|
+
|
|
108
|
+
// ── Part 3: post-unit does NOT artifact-retry on db_unavailable ──────────
|
|
109
|
+
|
|
110
|
+
console.log("\n=== #2517 Part 3: post-unit db_unavailable is infra-fatal ===");
|
|
111
|
+
|
|
112
|
+
const postUnitSrc = readFileSync(
|
|
113
|
+
join(import.meta.dirname, "..", "auto-post-unit.ts"),
|
|
114
|
+
"utf-8",
|
|
115
|
+
);
|
|
116
|
+
|
|
117
|
+
// The artifact retry block should check DB availability and skip retry
|
|
118
|
+
// when the DB is unavailable (infra failure, not a missing artifact).
|
|
119
|
+
assertTrue(
|
|
120
|
+
postUnitSrc.includes("db_unavailable") || postUnitSrc.includes("isDbAvailable"),
|
|
121
|
+
"post-unit artifact retry path checks DB availability to avoid retry loop (#2517)",
|
|
122
|
+
);
|
|
123
|
+
|
|
124
|
+
// Verify the retry block is guarded: when !isDbAvailable(), the code must
|
|
125
|
+
// NOT return "retry". The pattern should be: if (!verified && !isDbAvailable()) { skip }
|
|
126
|
+
// followed by else if (!verified) { ... return "retry" }
|
|
127
|
+
const dbUnavailableGuard = postUnitSrc.match(
|
|
128
|
+
/!triggerArtifactVerified\s*&&\s*!isDbAvailable\(\)/,
|
|
129
|
+
);
|
|
130
|
+
assertTrue(
|
|
131
|
+
!!dbUnavailableGuard,
|
|
132
|
+
"The retry block explicitly guards against !isDbAvailable() before returning 'retry' (#2517)",
|
|
133
|
+
);
|
|
94
134
|
|
|
95
135
|
report();
|
|
@@ -167,11 +167,9 @@ test('auto-prunes old debug logs', () => {
|
|
|
167
167
|
enableDebug(tmp);
|
|
168
168
|
|
|
169
169
|
const files = readdirSync(debugDir).filter(f => f.startsWith('debug-') && f.endsWith('.log'));
|
|
170
|
-
//
|
|
171
|
-
//
|
|
172
|
-
|
|
173
|
-
// (Refs #4831).
|
|
174
|
-
assert.ok(files.length <= 5, `should have pruned old logs to <= 5, got ${files.length}`);
|
|
170
|
+
// Should have at most MAX_DEBUG_LOGS (5) = 5 old + 1 new, but pruned to 5 total
|
|
171
|
+
// Actually: prunes to < 5 old, then creates 1 new = at most 5
|
|
172
|
+
assert.ok(files.length <= 6, `should have pruned old logs, got ${files.length}`);
|
|
175
173
|
|
|
176
174
|
disableDebug();
|
|
177
175
|
});
|
|
@@ -1,22 +1,28 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* discuss-empty-db-fallback.test.ts — Tests for #2892.
|
|
3
3
|
*
|
|
4
|
-
* When the DB is open but empty (e.g
|
|
5
|
-
* getMilestoneSlices() returns []
|
|
6
|
-
*
|
|
7
|
-
* slices
|
|
8
|
-
*
|
|
9
|
-
* slices and completed checkboxes (`[x]`) yield `done=true`.
|
|
10
|
-
*
|
|
11
|
-
* The earlier source-grep / regex-on-showDiscuss-body tests (audit verdicts
|
|
12
|
-
* SOURCE_GREP / POSITIONAL — see #4826/#4829) were dropped; they pinned a
|
|
13
|
-
* specific surface form rather than behaviour.
|
|
4
|
+
* When the DB is open but empty (e.g., after crash/truncation),
|
|
5
|
+
* getMilestoneSlices() returns [] and showDiscuss() incorrectly declares
|
|
6
|
+
* "All slices are complete." The fix adds a roadmap fallback: when the DB
|
|
7
|
+
* returns zero slices but a ROADMAP file exists, parse slices from the
|
|
8
|
+
* roadmap instead of treating zero slices as "all complete."
|
|
14
9
|
*/
|
|
15
10
|
|
|
16
11
|
import { describe, test } from "node:test";
|
|
17
12
|
import assert from "node:assert/strict";
|
|
13
|
+
import { readFileSync } from "node:fs";
|
|
14
|
+
import { fileURLToPath } from "node:url";
|
|
15
|
+
import { dirname, join } from "node:path";
|
|
18
16
|
import { parseRoadmapSlices } from "../roadmap-slices.ts";
|
|
19
17
|
|
|
18
|
+
// ─── Helpers ─────────────────────────────────────────────────────────────────
|
|
19
|
+
|
|
20
|
+
function readGuidedFlowSource(): string {
|
|
21
|
+
const thisFile = fileURLToPath(import.meta.url);
|
|
22
|
+
const thisDir = dirname(thisFile);
|
|
23
|
+
return readFileSync(join(thisDir, "..", "guided-flow.ts"), "utf-8");
|
|
24
|
+
}
|
|
25
|
+
|
|
20
26
|
const SAMPLE_ROADMAP = `# M012 Roadmap
|
|
21
27
|
|
|
22
28
|
## Slices
|
|
@@ -28,23 +34,80 @@ const SAMPLE_ROADMAP = `# M012 Roadmap
|
|
|
28
34
|
> After this: dashboard renders
|
|
29
35
|
`;
|
|
30
36
|
|
|
31
|
-
|
|
32
|
-
|
|
37
|
+
// ─── Tests ───────────────────────────────────────────────────────────────────
|
|
38
|
+
|
|
39
|
+
describe("discuss-empty-db-fallback (#2892)", () => {
|
|
40
|
+
|
|
41
|
+
test("1. parseRoadmapSlices extracts slices from a valid ROADMAP", () => {
|
|
33
42
|
const slices = parseRoadmapSlices(SAMPLE_ROADMAP);
|
|
34
43
|
assert.strictEqual(slices.length, 3, "should parse 3 slices from sample roadmap");
|
|
35
|
-
|
|
36
|
-
assert.
|
|
44
|
+
assert.strictEqual(slices[0]!.id, "S01");
|
|
45
|
+
assert.strictEqual(slices[1]!.id, "S02");
|
|
46
|
+
assert.strictEqual(slices[2]!.id, "S03");
|
|
47
|
+
// All slices are incomplete ([ ] not [x])
|
|
48
|
+
assert.ok(slices.every(s => !s.done), "all slices should be incomplete");
|
|
37
49
|
});
|
|
38
50
|
|
|
39
|
-
test("
|
|
40
|
-
const
|
|
51
|
+
test("2. guided-flow imports parseRoadmapSlices for roadmap fallback", () => {
|
|
52
|
+
const source = readGuidedFlowSource();
|
|
53
|
+
assert.ok(
|
|
54
|
+
source.includes("parseRoadmapSlices"),
|
|
55
|
+
"guided-flow must import parseRoadmapSlices to support roadmap fallback when DB is empty",
|
|
56
|
+
);
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
test("3. guided-flow has roadmap fallback when normSlices is empty but roadmapContent exists", () => {
|
|
60
|
+
const source = readGuidedFlowSource();
|
|
61
|
+
// The fix must add a fallback that checks normSlices.length === 0 && roadmapContent
|
|
62
|
+
// and repopulates normSlices from the roadmap before the pendingSlices guard.
|
|
63
|
+
//
|
|
64
|
+
// Pattern: after DB query produces normSlices, if empty + roadmap exists,
|
|
65
|
+
// fall back to parseRoadmapSlices(roadmapContent).
|
|
66
|
+
const fallbackPattern = /normSlices\.length\s*===\s*0\s*&&\s*roadmapContent/;
|
|
41
67
|
assert.ok(
|
|
42
|
-
|
|
43
|
-
"
|
|
68
|
+
fallbackPattern.test(source),
|
|
69
|
+
"guided-flow must check normSlices.length === 0 && roadmapContent to trigger roadmap fallback",
|
|
44
70
|
);
|
|
45
71
|
});
|
|
46
72
|
|
|
47
|
-
test("
|
|
73
|
+
test("4. guided-flow no longer has unguarded pendingSlices === 0 exit after DB-only query", () => {
|
|
74
|
+
const source = readGuidedFlowSource();
|
|
75
|
+
// Extract the showDiscuss function body
|
|
76
|
+
const fnMatch = source.match(
|
|
77
|
+
/async function showDiscuss\s*\([^)]*\)[^{]*\{([\s\S]*?)\nfunction\s/,
|
|
78
|
+
);
|
|
79
|
+
assert.ok(!!fnMatch, "showDiscuss function body must be found");
|
|
80
|
+
|
|
81
|
+
if (fnMatch) {
|
|
82
|
+
const body = fnMatch[1]!;
|
|
83
|
+
// After the DB query block (isDbAvailable/getMilestoneSlices), there should
|
|
84
|
+
// be a roadmap fallback BEFORE the pendingSlices.length === 0 check.
|
|
85
|
+
// Find the getMilestoneSlices call and the pendingSlices === 0 check
|
|
86
|
+
const dbQueryIdx = body.indexOf("getMilestoneSlices");
|
|
87
|
+
const fallbackIdx = body.indexOf("parseRoadmapSlices");
|
|
88
|
+
const pendingGuardIdx = body.indexOf('pendingSlices.length === 0');
|
|
89
|
+
|
|
90
|
+
assert.ok(dbQueryIdx > 0, "getMilestoneSlices call must exist");
|
|
91
|
+
assert.ok(fallbackIdx > 0, "parseRoadmapSlices fallback must exist");
|
|
92
|
+
assert.ok(pendingGuardIdx > 0, "pendingSlices.length === 0 guard must exist");
|
|
93
|
+
assert.ok(
|
|
94
|
+
fallbackIdx > dbQueryIdx && fallbackIdx < pendingGuardIdx,
|
|
95
|
+
"parseRoadmapSlices fallback must appear BETWEEN DB query and pendingSlices === 0 guard",
|
|
96
|
+
);
|
|
97
|
+
}
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
test("5. roadmap-parsed slices map to NormSlice format with done=false by default", () => {
|
|
101
|
+
// When falling back to roadmap, incomplete slices ([ ]) should map to done:false,
|
|
102
|
+
// ensuring they appear as pending and are NOT falsely reported as complete.
|
|
103
|
+
const slices = parseRoadmapSlices(SAMPLE_ROADMAP);
|
|
104
|
+
const normSlices = slices.map(s => ({ id: s.id, done: s.done, title: s.title }));
|
|
105
|
+
const pendingSlices = normSlices.filter(s => !s.done);
|
|
106
|
+
assert.strictEqual(pendingSlices.length, 3,
|
|
107
|
+
"all 3 incomplete roadmap slices should be pending — not falsely treated as complete");
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
test("6. roadmap with completed slices correctly reports them as done", () => {
|
|
48
111
|
const completedRoadmap = `# M012 Roadmap
|
|
49
112
|
|
|
50
113
|
## Slices
|
|
@@ -56,7 +119,9 @@ describe("discuss-empty-db-fallback parser contract (#2892)", () => {
|
|
|
56
119
|
> After this: dashboard renders
|
|
57
120
|
`;
|
|
58
121
|
const slices = parseRoadmapSlices(completedRoadmap);
|
|
59
|
-
const
|
|
60
|
-
|
|
122
|
+
const normSlices = slices.map(s => ({ id: s.id, done: s.done, title: s.title }));
|
|
123
|
+
const pendingSlices = normSlices.filter(s => !s.done);
|
|
124
|
+
assert.strictEqual(pendingSlices.length, 1, "only S02 should be pending");
|
|
125
|
+
assert.strictEqual(pendingSlices[0]!.id, "S02");
|
|
61
126
|
});
|
|
62
127
|
});
|