gsd-pi 2.58.0 → 2.59.0-dev.023bd39
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/cli.js +60 -35
- package/dist/headless-ui.d.ts +17 -0
- package/dist/headless-ui.js +97 -3
- package/dist/headless.js +67 -6
- package/dist/help-text.js +1 -0
- package/dist/onboarding.js +44 -0
- package/dist/resource-loader.js +16 -1
- package/dist/resources/agents/researcher.md +1 -1
- package/dist/resources/extensions/ask-user-questions.js +16 -3
- package/dist/resources/extensions/async-jobs/extension-manifest.json +1 -1
- package/dist/resources/extensions/bg-shell/extension-manifest.json +1 -1
- package/dist/resources/extensions/browser-tools/extension-manifest.json +1 -1
- package/dist/resources/extensions/claude-code-cli/partial-builder.js +14 -6
- package/dist/resources/extensions/claude-code-cli/stream-adapter.js +59 -36
- package/dist/resources/extensions/context7/extension-manifest.json +1 -1
- package/dist/resources/extensions/get-secrets-from-user.js +8 -5
- package/dist/resources/extensions/google-search/extension-manifest.json +1 -1
- package/dist/resources/extensions/google-search/index.js +2 -1
- package/dist/resources/extensions/gsd/auto/phases.js +25 -21
- package/dist/resources/extensions/gsd/auto-artifact-paths.js +2 -2
- package/dist/resources/extensions/gsd/auto-dashboard.js +37 -20
- package/dist/resources/extensions/gsd/auto-dispatch.js +17 -2
- package/dist/resources/extensions/gsd/auto-model-selection.js +26 -3
- package/dist/resources/extensions/gsd/auto-post-unit.js +16 -4
- package/dist/resources/extensions/gsd/auto-prompts.js +1 -1
- package/dist/resources/extensions/gsd/auto-recovery.js +13 -5
- package/dist/resources/extensions/gsd/auto-start.js +35 -22
- package/dist/resources/extensions/gsd/auto-worktree.js +199 -12
- package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +32 -0
- package/dist/resources/extensions/gsd/bootstrap/db-tools.js +80 -8
- package/dist/resources/extensions/gsd/bootstrap/dynamic-tools.js +32 -1
- package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +42 -34
- package/dist/resources/extensions/gsd/bootstrap/system-context.js +66 -12
- package/dist/resources/extensions/gsd/bootstrap/write-gate.js +67 -0
- package/dist/resources/extensions/gsd/captures.js +56 -4
- package/dist/resources/extensions/gsd/codebase-generator.js +279 -0
- package/dist/resources/extensions/gsd/commands/catalog.js +10 -1
- package/dist/resources/extensions/gsd/commands/handlers/ops.js +5 -0
- package/dist/resources/extensions/gsd/commands-codebase.js +115 -0
- package/dist/resources/extensions/gsd/commands-prefs-wizard.js +41 -4
- package/dist/resources/extensions/gsd/complexity-classifier.js +8 -6
- package/dist/resources/extensions/gsd/db-writer.js +116 -8
- package/dist/resources/extensions/gsd/doctor-git-checks.js +76 -1
- package/dist/resources/extensions/gsd/doctor-proactive.js +34 -1
- package/dist/resources/extensions/gsd/doctor-providers.js +2 -1
- package/dist/resources/extensions/gsd/doctor-runtime-checks.js +5 -4
- package/dist/resources/extensions/gsd/doctor.js +3 -1
- package/dist/resources/extensions/gsd/error-classifier.js +12 -10
- package/dist/resources/extensions/gsd/extension-manifest.json +16 -1
- package/dist/resources/extensions/gsd/forensics.js +123 -20
- package/dist/resources/extensions/gsd/git-service.js +105 -2
- package/dist/resources/extensions/gsd/gitignore.js +33 -0
- package/dist/resources/extensions/gsd/gsd-db.js +36 -9
- package/dist/resources/extensions/gsd/guided-flow.js +106 -44
- package/dist/resources/extensions/gsd/health-widget-core.js +31 -0
- package/dist/resources/extensions/gsd/health-widget.js +17 -0
- package/dist/resources/extensions/gsd/index.js +1 -1
- package/dist/resources/extensions/gsd/memory-extractor.js +7 -0
- package/dist/resources/extensions/gsd/migrate-external.js +8 -1
- package/dist/resources/extensions/gsd/milestone-validation-gates.js +45 -0
- package/dist/resources/extensions/gsd/model-cost-table.js +18 -0
- package/dist/resources/extensions/gsd/model-router.js +35 -1
- package/dist/resources/extensions/gsd/native-git-bridge.js +39 -0
- package/dist/resources/extensions/gsd/notifications.js +16 -1
- package/dist/resources/extensions/gsd/parallel-eligibility.js +13 -2
- package/dist/resources/extensions/gsd/parallel-merge.js +78 -5
- package/dist/resources/extensions/gsd/parsers-legacy.js +20 -3
- package/dist/resources/extensions/gsd/paths.js +45 -0
- package/dist/resources/extensions/gsd/preferences-models.js +14 -1
- package/dist/resources/extensions/gsd/preferences-types.js +3 -1
- package/dist/resources/extensions/gsd/preferences.js +13 -16
- package/dist/resources/extensions/gsd/prompt-loader.js +4 -1
- package/dist/resources/extensions/gsd/prompts/complete-milestone.md +1 -1
- package/dist/resources/extensions/gsd/prompts/complete-slice.md +4 -2
- package/dist/resources/extensions/gsd/prompts/discuss-headless.md +1 -1
- package/dist/resources/extensions/gsd/prompts/discuss.md +1 -1
- package/dist/resources/extensions/gsd/prompts/execute-task.md +3 -1
- package/dist/resources/extensions/gsd/prompts/forensics.md +2 -2
- package/dist/resources/extensions/gsd/prompts/guided-discuss-milestone.md +1 -1
- package/dist/resources/extensions/gsd/prompts/guided-discuss-slice.md +1 -1
- package/dist/resources/extensions/gsd/prompts/plan-slice.md +2 -0
- package/dist/resources/extensions/gsd/prompts/rethink.md +1 -1
- package/dist/resources/extensions/gsd/prompts/triage-captures.md +1 -0
- package/dist/resources/extensions/gsd/repo-identity.js +205 -11
- package/dist/resources/extensions/gsd/rethink.js +5 -0
- package/dist/resources/extensions/gsd/roadmap-slices.js +5 -4
- package/dist/resources/extensions/gsd/state.js +85 -27
- package/dist/resources/extensions/gsd/tests/dist-redirect.mjs +20 -1
- package/dist/resources/extensions/gsd/tools/complete-task.js +34 -71
- package/dist/resources/extensions/gsd/tools/plan-milestone.js +12 -2
- package/dist/resources/extensions/gsd/tools/reassess-roadmap.js +29 -1
- package/dist/resources/extensions/gsd/tools/validate-milestone.js +14 -3
- package/dist/resources/extensions/gsd/triage-resolution.js +22 -7
- package/dist/resources/extensions/gsd/undo.js +2 -2
- package/dist/resources/extensions/gsd/unit-ownership.js +164 -33
- package/dist/resources/extensions/gsd/verdict-parser.js +20 -8
- package/dist/resources/extensions/gsd/watch/header-renderer.js +241 -0
- package/dist/resources/extensions/gsd/workflow-manifest.js +24 -5
- package/dist/resources/extensions/gsd/workflow-projections.js +95 -63
- package/dist/resources/extensions/gsd/workflow-reconcile.js +35 -5
- package/dist/resources/extensions/gsd/workspace-index.js +24 -0
- package/dist/resources/extensions/gsd/worktree-manager.js +105 -1
- package/dist/resources/extensions/gsd/worktree-resolver.js +20 -3
- package/dist/resources/extensions/mcp-client/index.js +11 -7
- package/dist/resources/extensions/ollama/index.js +112 -0
- package/dist/resources/extensions/ollama/model-capabilities.js +115 -0
- package/dist/resources/extensions/ollama/ollama-client.js +168 -0
- package/dist/resources/extensions/ollama/ollama-commands.js +194 -0
- package/dist/resources/extensions/ollama/ollama-discovery.js +69 -0
- package/dist/resources/extensions/ollama/ollama-tool.js +184 -0
- package/dist/resources/extensions/ollama/types.js +2 -0
- package/dist/resources/extensions/search-the-web/extension-manifest.json +1 -1
- package/dist/resources/extensions/search-the-web/url-utils.js +17 -0
- package/dist/resources/extensions/shared/interview-ui.js +11 -1
- package/dist/resources/skills/btw/SKILL.md +42 -0
- package/dist/resources/skills/create-gsd-extension/SKILL.md +5 -3
- package/dist/resources/skills/create-gsd-extension/references/key-rules-gotchas.md +5 -4
- package/dist/resources/skills/create-gsd-extension/workflows/add-capability.md +2 -2
- package/dist/resources/skills/create-gsd-extension/workflows/create-extension.md +4 -4
- package/dist/resources/skills/create-gsd-extension/workflows/debug-extension.md +5 -3
- package/dist/security-overrides.d.ts +11 -0
- package/dist/security-overrides.js +41 -0
- package/dist/startup-model-validation.d.ts +39 -0
- package/dist/startup-model-validation.js +50 -0
- package/dist/web/standalone/.next/BUILD_ID +1 -1
- package/dist/web/standalone/.next/app-path-routes-manifest.json +14 -14
- 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 +1 -1
- package/dist/web/standalone/.next/required-server-files.json +4 -4
- 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 +2 -2
- package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found/page.js +2 -2
- package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.rsc +4 -4
- package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +4 -4
- package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +4 -4
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
- package/dist/web/standalone/.next/server/app/api/boot/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/boot/route_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/onboarding/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/onboarding/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/preferences/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/preferences/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/projects/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/projects/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/recovery/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/recovery/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/remote-questions/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/remote-questions/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/browser/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/browser/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/command/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/command/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/events/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/session/events/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/manage/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/manage/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/settings-data/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/settings-data/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/shutdown/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/shutdown/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/skill-health/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/skill-health/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/steer/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/steer/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/switch-root/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/switch-root/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/input/route.js +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 +5 -5
- package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
- package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +5 -5
- package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +4 -4
- package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +2 -2
- package/dist/web/standalone/.next/server/app/page.js +2 -2
- package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app-paths-manifest.json +14 -14
- package/dist/web/standalone/.next/server/chunks/2229.js +2 -2
- package/dist/web/standalone/.next/server/chunks/7471.js +3 -3
- package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
- package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
- package/dist/web/standalone/.next/server/middleware.js +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 +2 -2
- package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
- package/dist/web/standalone/.next/static/chunks/6502.7593d7797a4b3999.js +9 -0
- package/dist/web/standalone/.next/static/chunks/app/_not-found/{page-2f24283c162b6ab3.js → page-f2a7482d42a5614b.js} +1 -1
- package/dist/web/standalone/.next/static/chunks/app/{layout-9ecfd95f343793f0.js → layout-a16c7a7ecdf0c2cf.js} +1 -1
- package/dist/web/standalone/.next/static/chunks/app/page-0c485498795110d6.js +1 -0
- package/dist/web/standalone/.next/static/chunks/main-app-fdab67f7802d7832.js +1 -0
- package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-459824ffb8c323dd.js +1 -0
- package/dist/web/standalone/.next/static/chunks/{webpack-61d3afac6d0f0ce7.js → webpack-a1c1e452c6b32d04.js} +1 -1
- package/dist/web/standalone/.next/static/css/f6e8833d46e738d8.css +1 -0
- package/dist/web/standalone/node_modules/node-pty/build/Makefile +2 -2
- package/dist/web/standalone/node_modules/node-pty/build/Release/pty.node +0 -0
- package/dist/web/standalone/node_modules/node-pty/build/pty.target.mk +14 -14
- package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api.target.mk +14 -14
- package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_except.target.mk +14 -14
- package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_maybe.target.mk +14 -14
- package/dist/web/standalone/server.js +1 -1
- package/dist/web-mode.js +2 -1
- package/dist/welcome-screen.d.ts +1 -0
- package/dist/welcome-screen.js +32 -6
- package/package.json +2 -2
- package/packages/daemon/src/daemon.ts +1 -1
- package/packages/daemon/src/discord-bot.ts +11 -0
- package/packages/daemon/src/event-bridge.ts +15 -9
- package/packages/daemon/src/event-formatter.ts +30 -2
- package/packages/daemon/src/message-batcher.test.ts +2 -2
- package/packages/daemon/src/message-batcher.ts +9 -3
- package/packages/daemon/src/orchestrator.test.ts +1 -0
- package/packages/daemon/src/orchestrator.ts +106 -2
- package/packages/native/dist/ast/index.js +9 -5
- package/packages/native/dist/ast/types.js +2 -1
- package/packages/native/dist/clipboard/index.js +12 -7
- package/packages/native/dist/clipboard/types.js +2 -1
- package/packages/native/dist/diff/index.js +12 -7
- package/packages/native/dist/diff/types.js +2 -1
- package/packages/native/dist/fd/index.js +6 -3
- package/packages/native/dist/fd/types.js +2 -1
- package/packages/native/dist/glob/index.js +9 -5
- package/packages/native/dist/glob/types.js +2 -1
- package/packages/native/dist/grep/index.js +9 -5
- package/packages/native/dist/grep/types.js +2 -1
- package/packages/native/dist/gsd-parser/index.js +18 -11
- package/packages/native/dist/gsd-parser/types.js +2 -1
- package/packages/native/dist/highlight/index.js +12 -7
- package/packages/native/dist/highlight/types.js +2 -1
- package/packages/native/dist/html/index.js +6 -3
- package/packages/native/dist/html/types.js +2 -1
- package/packages/native/dist/image/index.js +10 -5
- package/packages/native/dist/image/types.js +7 -4
- package/packages/native/dist/index.js +70 -17
- package/packages/native/dist/json-parse/index.js +13 -8
- package/packages/native/dist/native.js +47 -10
- package/packages/native/dist/ps/index.js +15 -9
- package/packages/native/dist/ps/types.js +2 -1
- package/packages/native/dist/stream-process/index.js +12 -7
- package/packages/native/dist/text/index.js +24 -14
- package/packages/native/dist/text/types.js +5 -2
- package/packages/native/dist/truncate/index.js +12 -7
- package/packages/native/dist/ttsr/index.js +12 -7
- package/packages/native/dist/ttsr/types.js +2 -1
- package/packages/native/dist/xxhash/index.js +9 -5
- package/packages/native/package.json +19 -19
- package/packages/native/src/__tests__/module-compat.test.mjs +91 -0
- package/packages/native/src/native.ts +9 -8
- package/packages/pi-agent-core/dist/agent-loop.js +3 -2
- package/packages/pi-agent-core/dist/agent-loop.js.map +1 -1
- package/packages/pi-agent-core/dist/proxy.d.ts +1 -1
- package/packages/pi-agent-core/dist/proxy.d.ts.map +1 -1
- package/packages/pi-agent-core/dist/proxy.js.map +1 -1
- package/packages/pi-agent-core/src/agent-loop.test.ts +45 -0
- package/packages/pi-agent-core/src/agent-loop.ts +3 -2
- package/packages/pi-agent-core/src/proxy.ts +1 -1
- package/packages/pi-ai/dist/env-api-keys.js +1 -0
- package/packages/pi-ai/dist/env-api-keys.js.map +1 -1
- package/packages/pi-ai/dist/index.d.ts +1 -0
- package/packages/pi-ai/dist/index.d.ts.map +1 -1
- package/packages/pi-ai/dist/index.js +1 -0
- package/packages/pi-ai/dist/index.js.map +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 -2
- package/packages/pi-ai/dist/providers/anthropic-shared.js.map +1 -1
- package/packages/pi-ai/dist/providers/anthropic-shared.test.d.ts +2 -0
- package/packages/pi-ai/dist/providers/anthropic-shared.test.d.ts.map +1 -0
- package/packages/pi-ai/dist/providers/anthropic-shared.test.js +25 -0
- package/packages/pi-ai/dist/providers/anthropic-shared.test.js.map +1 -0
- package/packages/pi-ai/dist/types.d.ts +3 -3
- 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/json-parse.d.ts +3 -0
- package/packages/pi-ai/dist/utils/json-parse.d.ts.map +1 -1
- package/packages/pi-ai/dist/utils/json-parse.js +24 -1
- package/packages/pi-ai/dist/utils/json-parse.js.map +1 -1
- package/packages/pi-ai/dist/utils/repair-tool-json.d.ts +37 -0
- package/packages/pi-ai/dist/utils/repair-tool-json.d.ts.map +1 -0
- package/packages/pi-ai/dist/utils/repair-tool-json.js +75 -0
- package/packages/pi-ai/dist/utils/repair-tool-json.js.map +1 -0
- package/packages/pi-ai/dist/utils/tests/repair-tool-json.test.d.ts +2 -0
- package/packages/pi-ai/dist/utils/tests/repair-tool-json.test.d.ts.map +1 -0
- package/packages/pi-ai/dist/utils/tests/repair-tool-json.test.js +73 -0
- package/packages/pi-ai/dist/utils/tests/repair-tool-json.test.js.map +1 -0
- package/packages/pi-ai/src/env-api-keys.ts +1 -0
- package/packages/pi-ai/src/index.ts +1 -0
- package/packages/pi-ai/src/providers/anthropic-shared.test.ts +29 -0
- package/packages/pi-ai/src/providers/anthropic-shared.ts +17 -2
- package/packages/pi-ai/src/types.ts +3 -2
- package/packages/pi-ai/src/utils/json-parse.ts +28 -1
- package/packages/pi-ai/src/utils/repair-tool-json.ts +88 -0
- package/packages/pi-ai/src/utils/tests/repair-tool-json.test.ts +102 -0
- package/packages/pi-coding-agent/dist/core/agent-session.d.ts +4 -0
- package/packages/pi-coding-agent/dist/core/agent-session.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/agent-session.js +31 -0
- package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/compaction/compaction.d.ts +17 -1
- package/packages/pi-coding-agent/dist/core/compaction/compaction.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/compaction/compaction.js +62 -2
- package/packages/pi-coding-agent/dist/core/compaction/compaction.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/compaction/compaction.test.d.ts +6 -0
- package/packages/pi-coding-agent/dist/core/compaction/compaction.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/compaction/compaction.test.js +176 -0
- package/packages/pi-coding-agent/dist/core/compaction/compaction.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/exec.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/exec.js +3 -1
- package/packages/pi-coding-agent/dist/core/exec.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/extension-manifest.d.ts +28 -0
- package/packages/pi-coding-agent/dist/core/extensions/extension-manifest.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/extensions/extension-manifest.js +37 -0
- package/packages/pi-coding-agent/dist/core/extensions/extension-manifest.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/extensions/extension-manifest.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/extensions/extension-manifest.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/extensions/extension-manifest.test.js +63 -0
- package/packages/pi-coding-agent/dist/core/extensions/extension-manifest.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/extensions/extension-sort.d.ts +19 -0
- package/packages/pi-coding-agent/dist/core/extensions/extension-sort.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/extensions/extension-sort.js +115 -0
- package/packages/pi-coding-agent/dist/core/extensions/extension-sort.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/extensions/extension-sort.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/extensions/extension-sort.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/extensions/extension-sort.test.js +109 -0
- package/packages/pi-coding-agent/dist/core/extensions/extension-sort.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/extensions/index.d.ts +4 -0
- package/packages/pi-coding-agent/dist/core/extensions/index.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/index.js +2 -0
- package/packages/pi-coding-agent/dist/core/extensions/index.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/loader.d.ts +5 -0
- package/packages/pi-coding-agent/dist/core/extensions/loader.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/loader.js +5 -0
- package/packages/pi-coding-agent/dist/core/extensions/loader.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/image-overflow-recovery.d.ts +44 -0
- package/packages/pi-coding-agent/dist/core/image-overflow-recovery.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/image-overflow-recovery.js +97 -0
- package/packages/pi-coding-agent/dist/core/image-overflow-recovery.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/image-overflow-recovery.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/image-overflow-recovery.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/image-overflow-recovery.test.js +181 -0
- package/packages/pi-coding-agent/dist/core/image-overflow-recovery.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/index.d.ts +1 -1
- package/packages/pi-coding-agent/dist/core/index.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/index.js +1 -1
- package/packages/pi-coding-agent/dist/core/index.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/lsp/index.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/lsp/index.js +3 -0
- package/packages/pi-coding-agent/dist/core/lsp/index.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/lsp/lspmux.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/lsp/lspmux.js +3 -0
- package/packages/pi-coding-agent/dist/core/lsp/lspmux.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 +31 -2
- package/packages/pi-coding-agent/dist/core/messages.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/messages.test.d.ts +9 -0
- package/packages/pi-coding-agent/dist/core/messages.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/messages.test.js +86 -0
- package/packages/pi-coding-agent/dist/core/messages.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/model-resolver.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/model-resolver.js +1 -0
- package/packages/pi-coding-agent/dist/core/model-resolver.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/resolve-config-value.d.ts +8 -0
- package/packages/pi-coding-agent/dist/core/resolve-config-value.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/resolve-config-value.js +23 -2
- package/packages/pi-coding-agent/dist/core/resolve-config-value.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/resolve-config-value.test.js +89 -2
- package/packages/pi-coding-agent/dist/core/resolve-config-value.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/resource-loader.d.ts +10 -0
- package/packages/pi-coding-agent/dist/core/resource-loader.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/resource-loader.js +12 -1
- package/packages/pi-coding-agent/dist/core/resource-loader.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/retry-handler.d.ts +6 -0
- package/packages/pi-coding-agent/dist/core/retry-handler.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/retry-handler.js +48 -1
- package/packages/pi-coding-agent/dist/core/retry-handler.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/retry-handler.test.d.ts +9 -0
- package/packages/pi-coding-agent/dist/core/retry-handler.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/retry-handler.test.js +193 -0
- package/packages/pi-coding-agent/dist/core/retry-handler.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/settings-manager-security.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/settings-manager-security.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/settings-manager-security.test.js +83 -0
- package/packages/pi-coding-agent/dist/core/settings-manager-security.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/settings-manager.d.ts +14 -0
- package/packages/pi-coding-agent/dist/core/settings-manager.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/settings-manager.js +36 -3
- package/packages/pi-coding-agent/dist/core/settings-manager.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/hashline-read.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/hashline-read.js +10 -3
- package/packages/pi-coding-agent/dist/core/tools/hashline-read.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/read.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/read.js +13 -4
- package/packages/pi-coding-agent/dist/core/tools/read.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/spawn-shell-windows.test.d.ts +16 -0
- package/packages/pi-coding-agent/dist/core/tools/spawn-shell-windows.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/tools/spawn-shell-windows.test.js +80 -0
- package/packages/pi-coding-agent/dist/core/tools/spawn-shell-windows.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/index.d.ts +3 -2
- package/packages/pi-coding-agent/dist/index.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/index.js +2 -1
- package/packages/pi-coding-agent/dist/index.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/armin.d.ts +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/armin.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/armin.js +9 -8
- package/packages/pi-coding-agent/dist/modes/interactive/components/armin.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.js +0 -3
- package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/bash-execution.d.ts +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/bash-execution.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/bash-execution.js +2 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/bash-execution.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/bordered-loader.js +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/bordered-loader.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/branch-summary-message.js +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/branch-summary-message.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/compaction-summary-message.js +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/compaction-summary-message.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/config-selector.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/config-selector.js +5 -2
- package/packages/pi-coding-agent/dist/modes/interactive/components/config-selector.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/countdown-timer.d.ts +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/countdown-timer.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/countdown-timer.js +4 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/countdown-timer.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/custom-message.js +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/custom-message.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/daxnuts.d.ts +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/daxnuts.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/daxnuts.js +4 -2
- package/packages/pi-coding-agent/dist/modes/interactive/components/daxnuts.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/diff.js +2 -2
- package/packages/pi-coding-agent/dist/modes/interactive/components/diff.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/dynamic-border.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/dynamic-border.js +8 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/dynamic-border.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/extension-input.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/extension-input.js +2 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/extension-input.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/extension-selector.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/extension-selector.js +4 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/extension-selector.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/footer.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/footer.js +26 -12
- package/packages/pi-coding-agent/dist/modes/interactive/components/footer.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/oauth-selector.js +4 -4
- package/packages/pi-coding-agent/dist/modes/interactive/components/oauth-selector.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/provider-manager.d.ts +3 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/provider-manager.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/provider-manager.js +46 -14
- package/packages/pi-coding-agent/dist/modes/interactive/components/provider-manager.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/scoped-models-selector.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/scoped-models-selector.js +2 -8
- package/packages/pi-coding-agent/dist/modes/interactive/components/scoped-models-selector.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/session-selector.js +4 -4
- package/packages/pi-coding-agent/dist/modes/interactive/components/session-selector.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/skill-invocation-message.js +2 -2
- package/packages/pi-coding-agent/dist/modes/interactive/components/skill-invocation-message.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js +8 -3
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/user-message-selector.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/user-message-selector.js +3 -2
- package/packages/pi-coding-agent/dist/modes/interactive/components/user-message-selector.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js +19 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.d.ts +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.js +22 -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.d.ts +2 -0
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.test.js +122 -0
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts +2 -0
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js +57 -4
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.js +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/theme/themes.js +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/theme/themes.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/rpc/remote-terminal.d.ts +1 -0
- package/packages/pi-coding-agent/dist/modes/rpc/remote-terminal.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/rpc/remote-terminal.js +5 -0
- package/packages/pi-coding-agent/dist/modes/rpc/remote-terminal.js.map +1 -1
- package/packages/pi-coding-agent/package.json +1 -1
- package/packages/pi-coding-agent/src/core/agent-session.ts +38 -1
- package/packages/pi-coding-agent/src/core/compaction/compaction.test.ts +236 -0
- package/packages/pi-coding-agent/src/core/compaction/compaction.ts +94 -1
- package/packages/pi-coding-agent/src/core/exec.ts +3 -1
- package/packages/pi-coding-agent/src/core/extensions/extension-manifest.test.ts +77 -0
- package/packages/pi-coding-agent/src/core/extensions/extension-manifest.ts +62 -0
- package/packages/pi-coding-agent/src/core/extensions/extension-sort.test.ts +134 -0
- package/packages/pi-coding-agent/src/core/extensions/extension-sort.ts +137 -0
- package/packages/pi-coding-agent/src/core/extensions/index.ts +4 -0
- package/packages/pi-coding-agent/src/core/extensions/loader.ts +5 -0
- package/packages/pi-coding-agent/src/core/image-overflow-recovery.test.ts +228 -0
- package/packages/pi-coding-agent/src/core/image-overflow-recovery.ts +118 -0
- package/packages/pi-coding-agent/src/core/index.ts +6 -0
- package/packages/pi-coding-agent/src/core/lsp/index.ts +3 -0
- package/packages/pi-coding-agent/src/core/lsp/lspmux.ts +3 -0
- package/packages/pi-coding-agent/src/core/messages.test.ts +114 -0
- package/packages/pi-coding-agent/src/core/messages.ts +29 -2
- package/packages/pi-coding-agent/src/core/model-resolver.ts +1 -0
- package/packages/pi-coding-agent/src/core/resolve-config-value.test.ts +111 -1
- package/packages/pi-coding-agent/src/core/resolve-config-value.ts +26 -2
- package/packages/pi-coding-agent/src/core/resource-loader.ts +20 -1
- package/packages/pi-coding-agent/src/core/retry-handler.test.ts +255 -0
- package/packages/pi-coding-agent/src/core/retry-handler.ts +52 -1
- package/packages/pi-coding-agent/src/core/settings-manager-security.test.ts +102 -0
- package/packages/pi-coding-agent/src/core/settings-manager.ts +44 -3
- package/packages/pi-coding-agent/src/core/tools/hashline-read.ts +11 -3
- package/packages/pi-coding-agent/src/core/tools/read.ts +14 -4
- package/packages/pi-coding-agent/src/core/tools/spawn-shell-windows.test.ts +92 -0
- package/packages/pi-coding-agent/src/index.ts +11 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/armin.ts +9 -9
- package/packages/pi-coding-agent/src/modes/interactive/components/assistant-message.ts +0 -2
- package/packages/pi-coding-agent/src/modes/interactive/components/bash-execution.ts +3 -1
- package/packages/pi-coding-agent/src/modes/interactive/components/bordered-loader.ts +1 -1
- package/packages/pi-coding-agent/src/modes/interactive/components/branch-summary-message.ts +1 -1
- package/packages/pi-coding-agent/src/modes/interactive/components/compaction-summary-message.ts +1 -1
- package/packages/pi-coding-agent/src/modes/interactive/components/config-selector.ts +7 -2
- package/packages/pi-coding-agent/src/modes/interactive/components/countdown-timer.ts +3 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/custom-message.ts +1 -1
- package/packages/pi-coding-agent/src/modes/interactive/components/daxnuts.ts +4 -3
- package/packages/pi-coding-agent/src/modes/interactive/components/diff.ts +2 -2
- package/packages/pi-coding-agent/src/modes/interactive/components/dynamic-border.ts +3 -1
- package/packages/pi-coding-agent/src/modes/interactive/components/extension-input.ts +1 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/extension-selector.ts +4 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/footer.ts +27 -13
- package/packages/pi-coding-agent/src/modes/interactive/components/oauth-selector.ts +4 -4
- package/packages/pi-coding-agent/src/modes/interactive/components/provider-manager.ts +45 -14
- package/packages/pi-coding-agent/src/modes/interactive/components/scoped-models-selector.ts +2 -7
- package/packages/pi-coding-agent/src/modes/interactive/components/session-selector.ts +4 -4
- package/packages/pi-coding-agent/src/modes/interactive/components/skill-invocation-message.ts +2 -2
- package/packages/pi-coding-agent/src/modes/interactive/components/tool-execution.ts +8 -3
- package/packages/pi-coding-agent/src/modes/interactive/components/user-message-selector.ts +3 -2
- package/packages/pi-coding-agent/src/modes/interactive/controllers/chat-controller.ts +24 -1
- package/packages/pi-coding-agent/src/modes/interactive/controllers/input-controller.test.ts +156 -0
- package/packages/pi-coding-agent/src/modes/interactive/controllers/input-controller.ts +21 -1
- package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +73 -3
- package/packages/pi-coding-agent/src/modes/interactive/slash-command-handlers.ts +1 -1
- package/packages/pi-coding-agent/src/modes/interactive/theme/themes.ts +1 -1
- package/packages/pi-coding-agent/src/modes/rpc/remote-terminal.ts +6 -0
- package/packages/pi-tui/dist/terminal.d.ts +2 -0
- package/packages/pi-tui/dist/terminal.d.ts.map +1 -1
- package/packages/pi-tui/dist/terminal.js +9 -0
- package/packages/pi-tui/dist/terminal.js.map +1 -1
- package/packages/pi-tui/dist/tui.d.ts.map +1 -1
- package/packages/pi-tui/dist/tui.js +9 -0
- package/packages/pi-tui/dist/tui.js.map +1 -1
- package/packages/pi-tui/src/terminal.ts +14 -0
- package/packages/pi-tui/src/tui.ts +8 -0
- package/pkg/dist/modes/interactive/theme/themes.js +1 -1
- package/pkg/dist/modes/interactive/theme/themes.js.map +1 -1
- package/pkg/package.json +1 -1
- package/scripts/ensure-workspace-builds.cjs +45 -14
- package/src/resources/agents/researcher.md +1 -1
- package/src/resources/extensions/ask-user-questions.ts +21 -3
- package/src/resources/extensions/async-jobs/extension-manifest.json +1 -1
- package/src/resources/extensions/bg-shell/extension-manifest.json +1 -1
- package/src/resources/extensions/browser-tools/extension-manifest.json +1 -1
- package/src/resources/extensions/claude-code-cli/partial-builder.ts +13 -6
- package/src/resources/extensions/claude-code-cli/stream-adapter.ts +63 -35
- package/src/resources/extensions/claude-code-cli/tests/partial-builder.test.ts +28 -0
- package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +108 -1
- package/src/resources/extensions/context7/extension-manifest.json +1 -1
- package/src/resources/extensions/get-secrets-from-user.ts +8 -5
- package/src/resources/extensions/google-search/extension-manifest.json +1 -1
- package/src/resources/extensions/google-search/index.ts +2 -1
- package/src/resources/extensions/gsd/auto/loop-deps.ts +1 -0
- package/src/resources/extensions/gsd/auto/phases.ts +43 -34
- package/src/resources/extensions/gsd/auto-artifact-paths.ts +2 -2
- package/src/resources/extensions/gsd/auto-dashboard.ts +37 -19
- package/src/resources/extensions/gsd/auto-dispatch.ts +18 -2
- package/src/resources/extensions/gsd/auto-model-selection.ts +26 -5
- package/src/resources/extensions/gsd/auto-post-unit.ts +18 -4
- package/src/resources/extensions/gsd/auto-prompts.ts +1 -1
- package/src/resources/extensions/gsd/auto-recovery.ts +12 -5
- package/src/resources/extensions/gsd/auto-start.ts +35 -26
- package/src/resources/extensions/gsd/auto-worktree.ts +193 -9
- package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +31 -0
- package/src/resources/extensions/gsd/bootstrap/db-tools.ts +85 -8
- package/src/resources/extensions/gsd/bootstrap/dynamic-tools.ts +38 -1
- package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +41 -35
- package/src/resources/extensions/gsd/bootstrap/system-context.ts +72 -12
- package/src/resources/extensions/gsd/bootstrap/write-gate.ts +75 -0
- package/src/resources/extensions/gsd/captures.ts +63 -3
- package/src/resources/extensions/gsd/codebase-generator.ts +351 -0
- package/src/resources/extensions/gsd/commands/catalog.ts +10 -1
- package/src/resources/extensions/gsd/commands/handlers/ops.ts +5 -0
- package/src/resources/extensions/gsd/commands-codebase.ts +164 -0
- package/src/resources/extensions/gsd/commands-prefs-wizard.ts +46 -4
- package/src/resources/extensions/gsd/complexity-classifier.ts +8 -6
- package/src/resources/extensions/gsd/db-writer.ts +140 -7
- package/src/resources/extensions/gsd/doctor-git-checks.ts +75 -1
- package/src/resources/extensions/gsd/doctor-proactive.ts +35 -1
- package/src/resources/extensions/gsd/doctor-providers.ts +2 -1
- package/src/resources/extensions/gsd/doctor-runtime-checks.ts +5 -4
- package/src/resources/extensions/gsd/doctor-types.ts +2 -0
- package/src/resources/extensions/gsd/doctor.ts +3 -1
- package/src/resources/extensions/gsd/error-classifier.ts +13 -11
- package/src/resources/extensions/gsd/extension-manifest.json +16 -1
- package/src/resources/extensions/gsd/forensics.ts +144 -20
- package/src/resources/extensions/gsd/git-service.ts +119 -3
- package/src/resources/extensions/gsd/gitignore.ts +33 -0
- package/src/resources/extensions/gsd/gsd-db.ts +43 -7
- package/src/resources/extensions/gsd/guided-flow.ts +114 -45
- package/src/resources/extensions/gsd/health-widget-core.ts +34 -0
- package/src/resources/extensions/gsd/health-widget.ts +17 -0
- package/src/resources/extensions/gsd/index.ts +1 -0
- package/src/resources/extensions/gsd/memory-extractor.ts +8 -0
- package/src/resources/extensions/gsd/migrate-external.ts +9 -1
- package/src/resources/extensions/gsd/milestone-validation-gates.ts +56 -0
- package/src/resources/extensions/gsd/model-cost-table.ts +19 -0
- package/src/resources/extensions/gsd/model-router.ts +35 -1
- package/src/resources/extensions/gsd/native-git-bridge.ts +41 -0
- package/src/resources/extensions/gsd/notifications.ts +16 -0
- package/src/resources/extensions/gsd/parallel-eligibility.ts +15 -2
- package/src/resources/extensions/gsd/parallel-merge.ts +87 -4
- package/src/resources/extensions/gsd/parsers-legacy.ts +22 -3
- package/src/resources/extensions/gsd/paths.ts +44 -0
- package/src/resources/extensions/gsd/preferences-models.ts +14 -1
- package/src/resources/extensions/gsd/preferences-types.ts +10 -1
- package/src/resources/extensions/gsd/preferences.ts +13 -15
- package/src/resources/extensions/gsd/prompt-loader.ts +4 -1
- package/src/resources/extensions/gsd/prompts/complete-milestone.md +1 -1
- package/src/resources/extensions/gsd/prompts/complete-slice.md +4 -2
- package/src/resources/extensions/gsd/prompts/discuss-headless.md +1 -1
- package/src/resources/extensions/gsd/prompts/discuss.md +1 -1
- package/src/resources/extensions/gsd/prompts/execute-task.md +3 -1
- package/src/resources/extensions/gsd/prompts/forensics.md +2 -2
- package/src/resources/extensions/gsd/prompts/guided-discuss-milestone.md +1 -1
- package/src/resources/extensions/gsd/prompts/guided-discuss-slice.md +1 -1
- package/src/resources/extensions/gsd/prompts/plan-slice.md +2 -0
- package/src/resources/extensions/gsd/prompts/rethink.md +1 -1
- package/src/resources/extensions/gsd/prompts/triage-captures.md +1 -0
- package/src/resources/extensions/gsd/repo-identity.ts +186 -11
- package/src/resources/extensions/gsd/rethink.ts +6 -0
- package/src/resources/extensions/gsd/roadmap-slices.ts +5 -4
- package/src/resources/extensions/gsd/state.ts +84 -32
- package/src/resources/extensions/gsd/tests/auto-loop.test.ts +29 -0
- package/src/resources/extensions/gsd/tests/auto-mode-interactive-guard.test.ts +71 -0
- package/src/resources/extensions/gsd/tests/auto-model-selection.test.ts +71 -1
- package/src/resources/extensions/gsd/tests/captures.test.ts +103 -0
- package/src/resources/extensions/gsd/tests/cli-provider-rate-limit.test.ts +47 -0
- package/src/resources/extensions/gsd/tests/codebase-generator.test.ts +488 -0
- package/src/resources/extensions/gsd/tests/complete-milestone.test.ts +27 -0
- package/src/resources/extensions/gsd/tests/complete-slice.test.ts +21 -0
- package/src/resources/extensions/gsd/tests/completion-hierarchy-guards.test.ts +192 -0
- package/src/resources/extensions/gsd/tests/complexity-classifier.test.ts +4 -4
- package/src/resources/extensions/gsd/tests/db-path-worktree-symlink.test.ts +131 -0
- package/src/resources/extensions/gsd/tests/db-writer.test.ts +7 -12
- package/src/resources/extensions/gsd/tests/derive-state-db.test.ts +78 -5
- package/src/resources/extensions/gsd/tests/derive-state.test.ts +29 -0
- package/src/resources/extensions/gsd/tests/discord-invite-links.test.ts +47 -0
- package/src/resources/extensions/gsd/tests/discuss-empty-db-fallback.test.ts +127 -0
- package/src/resources/extensions/gsd/tests/discuss-queued-milestones.test.ts +40 -0
- package/src/resources/extensions/gsd/tests/dist-redirect.mjs +20 -1
- package/src/resources/extensions/gsd/tests/doctor-providers.test.ts +117 -0
- package/src/resources/extensions/gsd/tests/dynamic-routing-default.test.ts +20 -0
- package/src/resources/extensions/gsd/tests/empty-content-abort-loop.test.ts +74 -0
- package/src/resources/extensions/gsd/tests/event-replay-idempotency.test.ts +140 -0
- package/src/resources/extensions/gsd/tests/forensics-context-persist.test.ts +129 -0
- package/src/resources/extensions/gsd/tests/forensics-db-completion.test.ts +96 -0
- package/src/resources/extensions/gsd/tests/forensics-dedup.test.ts +31 -0
- package/src/resources/extensions/gsd/tests/gsd-tools.test.ts +125 -12
- package/src/resources/extensions/gsd/tests/gsdroot-worktree-detection.test.ts +164 -0
- package/src/resources/extensions/gsd/tests/guided-flow-dynamic-routing.test.ts +135 -0
- package/src/resources/extensions/gsd/tests/guided-flow-session-isolation.test.ts +97 -0
- package/src/resources/extensions/gsd/tests/health-widget.test.ts +67 -0
- package/src/resources/extensions/gsd/tests/hook-key-parsing.test.ts +107 -0
- package/src/resources/extensions/gsd/tests/integration/auto-recovery.test.ts +111 -1
- package/src/resources/extensions/gsd/tests/integration/auto-worktree-milestone-merge.test.ts +134 -0
- package/src/resources/extensions/gsd/tests/integration/auto-worktree.test.ts +59 -0
- package/src/resources/extensions/gsd/tests/integration/doctor-false-positives.test.ts +243 -0
- package/src/resources/extensions/gsd/tests/integration/doctor-git.test.ts +72 -0
- package/src/resources/extensions/gsd/tests/integration/git-service.test.ts +68 -0
- package/src/resources/extensions/gsd/tests/integration/gitignore-staging-2570.test.ts +150 -0
- package/src/resources/extensions/gsd/tests/integration/parallel-merge.test.ts +110 -0
- package/src/resources/extensions/gsd/tests/integration/run-uat.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/integration/state-machine-live-validation.test.ts +959 -0
- package/src/resources/extensions/gsd/tests/memory-extractor.test.ts +85 -2
- package/src/resources/extensions/gsd/tests/migrate-external-worktree.test.ts +105 -0
- package/src/resources/extensions/gsd/tests/milestone-status-authoritative.test.ts +116 -0
- package/src/resources/extensions/gsd/tests/model-cost-table.test.ts +34 -0
- package/src/resources/extensions/gsd/tests/model-router.test.ts +68 -3
- package/src/resources/extensions/gsd/tests/model-unittype-mapping.test.ts +28 -0
- package/src/resources/extensions/gsd/tests/notifications.test.ts +45 -0
- package/src/resources/extensions/gsd/tests/parallel-commit-scope.test.ts +159 -0
- package/src/resources/extensions/gsd/tests/parallel-eligibility-ghost.test.ts +150 -0
- package/src/resources/extensions/gsd/tests/plan-milestone-title.test.ts +70 -0
- package/src/resources/extensions/gsd/tests/plan-milestone.test.ts +33 -1
- package/src/resources/extensions/gsd/tests/project-relocation-recovery.test.ts +297 -0
- package/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +29 -0
- package/src/resources/extensions/gsd/tests/prompt-loader-replacement.test.ts +178 -0
- package/src/resources/extensions/gsd/tests/prompt-tool-names.test.ts +69 -0
- package/src/resources/extensions/gsd/tests/provider-errors.test.ts +38 -0
- package/src/resources/extensions/gsd/tests/queue-execution-guard.test.ts +157 -0
- package/src/resources/extensions/gsd/tests/quick-turn-end-cleanup.test.ts +90 -0
- package/src/resources/extensions/gsd/tests/reassess-handler.test.ts +117 -0
- package/src/resources/extensions/gsd/tests/reconciliation-edge-cases.test.ts +162 -0
- package/src/resources/extensions/gsd/tests/roadmap-slices.test.ts +97 -0
- package/src/resources/extensions/gsd/tests/secure-env-collect.test.ts +134 -0
- package/src/resources/extensions/gsd/tests/slice-disk-reconcile.test.ts +233 -0
- package/src/resources/extensions/gsd/tests/stash-queued-context-files.test.ts +305 -0
- package/src/resources/extensions/gsd/tests/state-corruption-2945.test.ts +405 -0
- package/src/resources/extensions/gsd/tests/state-derivation-parity.test.ts +257 -0
- package/src/resources/extensions/gsd/tests/state-machine-full-walkthrough.test.ts +1628 -0
- package/src/resources/extensions/gsd/tests/stop-auto-race-null-unit.test.ts +106 -0
- package/src/resources/extensions/gsd/tests/stuck-detection-coverage.test.ts +174 -0
- package/src/resources/extensions/gsd/tests/summary-render-parity.test.ts +221 -0
- package/src/resources/extensions/gsd/tests/terminated-transient.test.ts +44 -0
- package/src/resources/extensions/gsd/tests/tool-naming.test.ts +2 -1
- package/src/resources/extensions/gsd/tests/triage-resolution.test.ts +8 -0
- package/src/resources/extensions/gsd/tests/uat-stuck-loop-orphaned-worktree.test.ts +289 -0
- package/src/resources/extensions/gsd/tests/unit-ownership.test.ts +100 -17
- package/src/resources/extensions/gsd/tests/vacuum-recovery.test.ts +154 -0
- package/src/resources/extensions/gsd/tests/validate-milestone-write-order.test.ts +4 -1
- package/src/resources/extensions/gsd/tests/verdict-parser.test.ts +156 -0
- package/src/resources/extensions/gsd/tests/verification-operational-gate.test.ts +82 -0
- package/src/resources/extensions/gsd/tests/workflow-logger.test.ts +48 -0
- package/src/resources/extensions/gsd/tests/workflow-manifest.test.ts +92 -0
- package/src/resources/extensions/gsd/tests/workflow-projections.test.ts +4 -2
- package/src/resources/extensions/gsd/tests/worktree-db-respawn-truncation.test.ts +140 -0
- package/src/resources/extensions/gsd/tests/worktree-nested-git-safety.test.ts +101 -0
- package/src/resources/extensions/gsd/tests/worktree-resolver.test.ts +48 -1
- package/src/resources/extensions/gsd/tests/worktree-sync-milestones.test.ts +29 -5
- package/src/resources/extensions/gsd/tests/zombie-gsd-state.test.ts +95 -0
- package/src/resources/extensions/gsd/tools/complete-task.ts +36 -74
- package/src/resources/extensions/gsd/tools/plan-milestone.ts +13 -1
- package/src/resources/extensions/gsd/tools/reassess-roadmap.ts +36 -0
- package/src/resources/extensions/gsd/tools/validate-milestone.ts +20 -2
- package/src/resources/extensions/gsd/triage-resolution.ts +23 -6
- package/src/resources/extensions/gsd/types.ts +4 -2
- package/src/resources/extensions/gsd/undo.ts +2 -2
- package/src/resources/extensions/gsd/unit-ownership.ts +206 -35
- package/src/resources/extensions/gsd/verdict-parser.ts +21 -6
- package/src/resources/extensions/gsd/watch/header-renderer.ts +275 -0
- package/src/resources/extensions/gsd/workflow-logger.ts +3 -1
- package/src/resources/extensions/gsd/workflow-manifest.ts +22 -5
- package/src/resources/extensions/gsd/workflow-projections.ts +97 -64
- package/src/resources/extensions/gsd/workflow-reconcile.ts +39 -10
- package/src/resources/extensions/gsd/workspace-index.ts +30 -0
- package/src/resources/extensions/gsd/worktree-manager.ts +120 -1
- package/src/resources/extensions/gsd/worktree-resolver.ts +22 -3
- package/src/resources/extensions/mcp-client/index.ts +13 -7
- package/src/resources/extensions/mcp-client/tests/server-name-spaces.test.ts +55 -0
- package/src/resources/extensions/ollama/index.ts +130 -0
- package/src/resources/extensions/ollama/model-capabilities.ts +145 -0
- package/src/resources/extensions/ollama/ollama-client.ts +196 -0
- package/src/resources/extensions/ollama/ollama-commands.ts +248 -0
- package/src/resources/extensions/ollama/ollama-discovery.ts +106 -0
- package/src/resources/extensions/ollama/ollama-tool.ts +218 -0
- package/src/resources/extensions/ollama/tests/model-capabilities.test.ts +162 -0
- package/src/resources/extensions/ollama/tests/ollama-client.test.ts +38 -0
- package/src/resources/extensions/ollama/tests/ollama-discovery.test.ts +28 -0
- package/src/resources/extensions/ollama/types.ts +130 -0
- package/src/resources/extensions/search-the-web/extension-manifest.json +1 -1
- package/src/resources/extensions/search-the-web/url-utils.ts +19 -0
- package/src/resources/extensions/shared/interview-ui.ts +12 -1
- package/src/resources/extensions/shared/tests/ask-user-freetext.test.ts +156 -0
- package/src/resources/skills/btw/SKILL.md +42 -0
- package/src/resources/skills/create-gsd-extension/SKILL.md +5 -3
- package/src/resources/skills/create-gsd-extension/references/key-rules-gotchas.md +5 -4
- package/src/resources/skills/create-gsd-extension/workflows/add-capability.md +2 -2
- package/src/resources/skills/create-gsd-extension/workflows/create-extension.md +4 -4
- package/src/resources/skills/create-gsd-extension/workflows/debug-extension.md +5 -3
- package/dist/web/standalone/.next/static/chunks/6502.8b732f67a11b11b4.js +0 -9
- package/dist/web/standalone/.next/static/chunks/app/page-62be3b5fa91e4c8f.js +0 -1
- package/dist/web/standalone/.next/static/chunks/main-app-d3d4c336195465f9.js +0 -1
- package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-ab5a8926e07ec673.js +0 -1
- package/dist/web/standalone/.next/static/css/a58ef8a151aa0493.css +0 -1
- package/src/resources/extensions/gsd/tests/empty-db-reconciliation.test.ts +0 -79
- /package/dist/web/standalone/.next/static/{IoheXIe-5DH7ieX8AUo8U → QlWL-8CXgQpzV3ehkNMzh}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{IoheXIe-5DH7ieX8AUo8U → QlWL-8CXgQpzV3ehkNMzh}/_ssgManifest.js +0 -0
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
// GSD State Machine Regression Tests — Completion Hierarchy & State Derivation (#3161)
|
|
2
|
+
|
|
3
|
+
import { describe, test, beforeEach, afterEach } from "node:test";
|
|
4
|
+
import assert from "node:assert/strict";
|
|
5
|
+
|
|
6
|
+
import {
|
|
7
|
+
openDatabase,
|
|
8
|
+
closeDatabase,
|
|
9
|
+
insertMilestone,
|
|
10
|
+
insertSlice,
|
|
11
|
+
insertTask,
|
|
12
|
+
getTask,
|
|
13
|
+
getSlice,
|
|
14
|
+
getMilestone,
|
|
15
|
+
getSliceTasks,
|
|
16
|
+
updateTaskStatus,
|
|
17
|
+
updateSliceStatus,
|
|
18
|
+
} from "../gsd-db.ts";
|
|
19
|
+
import { isClosedStatus } from "../status-guards.ts";
|
|
20
|
+
|
|
21
|
+
// ─── Setup / Teardown ──────────────────────────────────────────────────────
|
|
22
|
+
|
|
23
|
+
beforeEach(() => {
|
|
24
|
+
openDatabase(":memory:");
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
afterEach(() => {
|
|
28
|
+
try { closeDatabase(); } catch { /* swallow */ }
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
32
|
+
// Tests
|
|
33
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
34
|
+
|
|
35
|
+
describe("completion-hierarchy-guards", () => {
|
|
36
|
+
|
|
37
|
+
// ─── Test 1: isClosedStatus ─────────────────────────────────────────────
|
|
38
|
+
test("isClosedStatus returns true for 'complete' and 'done'", () => {
|
|
39
|
+
assert.ok(isClosedStatus("complete"), "'complete' should be closed");
|
|
40
|
+
assert.ok(isClosedStatus("done"), "'done' should be closed");
|
|
41
|
+
assert.ok(!isClosedStatus("pending"), "'pending' should not be closed");
|
|
42
|
+
assert.ok(!isClosedStatus("in-progress"), "'in-progress' should not be closed");
|
|
43
|
+
assert.ok(!isClosedStatus("blocked"), "'blocked' should not be closed");
|
|
44
|
+
assert.ok(!isClosedStatus(""), "empty string should not be closed");
|
|
45
|
+
assert.ok(!isClosedStatus("active"), "'active' should not be closed");
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
// ─── Test 2: vacuous truth guard — slice with zero tasks ───────────────
|
|
49
|
+
test("cannot complete slice with zero tasks — vacuous truth guard", () => {
|
|
50
|
+
insertMilestone({ id: "M001" });
|
|
51
|
+
insertSlice({ id: "S01", milestoneId: "M001" });
|
|
52
|
+
|
|
53
|
+
const tasks = getSliceTasks("M001", "S01");
|
|
54
|
+
assert.equal(tasks.length, 0, "newly inserted slice has zero tasks");
|
|
55
|
+
|
|
56
|
+
// The guard: a slice with no tasks is not completable.
|
|
57
|
+
// isSliceComplete from state.ts: plan.tasks.length > 0 && every done.
|
|
58
|
+
// Here we replicate the DB-side equivalent: zero tasks means guard fires.
|
|
59
|
+
const isCompletable = tasks.length > 0 && tasks.every(t => isClosedStatus(t.status));
|
|
60
|
+
assert.equal(isCompletable, false, "vacuous truth guard: zero tasks → not completable");
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
// ─── Test 3: cannot complete slice with incomplete tasks ─────────────────
|
|
64
|
+
test("cannot complete slice with incomplete tasks", () => {
|
|
65
|
+
insertMilestone({ id: "M001" });
|
|
66
|
+
insertSlice({ id: "S01", milestoneId: "M001" });
|
|
67
|
+
insertTask({ id: "T01", sliceId: "S01", milestoneId: "M001", status: "done" });
|
|
68
|
+
insertTask({ id: "T02", sliceId: "S01", milestoneId: "M001", status: "pending" });
|
|
69
|
+
|
|
70
|
+
const tasks = getSliceTasks("M001", "S01");
|
|
71
|
+
assert.equal(tasks.length, 2, "slice has 2 tasks");
|
|
72
|
+
|
|
73
|
+
const incompleteTasks = tasks.filter(t => !isClosedStatus(t.status));
|
|
74
|
+
assert.equal(incompleteTasks.length, 1, "exactly one task is not closed");
|
|
75
|
+
assert.equal(incompleteTasks[0]?.id, "T02", "the incomplete task is T02");
|
|
76
|
+
assert.equal(incompleteTasks[0]?.status, "pending", "incomplete task status is 'pending'");
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
// ─── Test 4: phantom parent milestone and slice (H6) ────────────────────
|
|
80
|
+
test("task completion auto-creates phantom parent milestone and slice (H6)", () => {
|
|
81
|
+
// H6 finding: insertMilestone/insertSlice accept empty titles — phantom
|
|
82
|
+
// parents can be created without substantive content.
|
|
83
|
+
insertMilestone({ id: "M001" });
|
|
84
|
+
insertSlice({ id: "S01", milestoneId: "M001" });
|
|
85
|
+
|
|
86
|
+
const milestone = getMilestone("M001");
|
|
87
|
+
assert.ok(milestone !== null, "phantom milestone M001 should exist in DB");
|
|
88
|
+
assert.equal(milestone!.title, "", "phantom milestone has empty title by default");
|
|
89
|
+
|
|
90
|
+
const slice = getSlice("M001", "S01");
|
|
91
|
+
assert.ok(slice !== null, "phantom slice S01 should exist in DB");
|
|
92
|
+
assert.equal(slice!.title, "", "phantom slice has empty title by default");
|
|
93
|
+
|
|
94
|
+
// This documents the H6 finding: the DB allows phantom parents with
|
|
95
|
+
// no meaningful content, which can silently accept task completion calls.
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
// ─── Test 5: double task completion is detectable via isClosedStatus ────
|
|
99
|
+
test("double task completion is detectable via isClosedStatus", () => {
|
|
100
|
+
insertMilestone({ id: "M001" });
|
|
101
|
+
insertSlice({ id: "S01", milestoneId: "M001" });
|
|
102
|
+
insertTask({ id: "T01", sliceId: "S01", milestoneId: "M001", status: "done" });
|
|
103
|
+
|
|
104
|
+
const task = getTask("M001", "S01", "T01");
|
|
105
|
+
assert.ok(task !== null, "task T01 should exist");
|
|
106
|
+
assert.ok(
|
|
107
|
+
isClosedStatus(task!.status),
|
|
108
|
+
"isClosedStatus detects already-closed task — prevents double completion",
|
|
109
|
+
);
|
|
110
|
+
|
|
111
|
+
// The guard that prevents double completion: check isClosedStatus before
|
|
112
|
+
// calling updateTaskStatus again.
|
|
113
|
+
const wouldDoubleComplete = isClosedStatus(task!.status);
|
|
114
|
+
assert.ok(wouldDoubleComplete, "guard fires: task is already closed");
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
// ─── Test 6: updateSliceStatus rollback loses original status (M11) ─────
|
|
118
|
+
test("updateSliceStatus rollback goes to 'pending' not original status (M11)", () => {
|
|
119
|
+
insertMilestone({ id: "M001" });
|
|
120
|
+
// Insert with an explicit non-pending status to simulate an in-progress slice
|
|
121
|
+
insertSlice({ id: "S01", milestoneId: "M001", status: "pending" });
|
|
122
|
+
|
|
123
|
+
// Manually advance to "in_progress" equivalent via updateSliceStatus
|
|
124
|
+
updateSliceStatus("M001", "S01", "in_progress");
|
|
125
|
+
const afterProgress = getSlice("M001", "S01");
|
|
126
|
+
assert.equal(afterProgress!.status, "in_progress", "slice is in_progress after update");
|
|
127
|
+
|
|
128
|
+
// Simulate completion
|
|
129
|
+
updateSliceStatus("M001", "S01", "complete", new Date().toISOString());
|
|
130
|
+
const afterComplete = getSlice("M001", "S01");
|
|
131
|
+
assert.equal(afterComplete!.status, "complete", "slice is complete after completion");
|
|
132
|
+
|
|
133
|
+
// Simulate rollback — the DB only stores current status, not history.
|
|
134
|
+
// Rolling back means setting to "pending" — the original "in_progress" is lost.
|
|
135
|
+
updateSliceStatus("M001", "S01", "pending");
|
|
136
|
+
const afterRollback = getSlice("M001", "S01");
|
|
137
|
+
assert.equal(
|
|
138
|
+
afterRollback!.status,
|
|
139
|
+
"pending",
|
|
140
|
+
"M11: rollback sets status to 'pending', original 'in_progress' is lost",
|
|
141
|
+
);
|
|
142
|
+
// Document: there is no completed_at or status history to recover from.
|
|
143
|
+
// The rollback silently discards the in_progress state.
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
// ─── Test 7: milestone completion requires all slices closed ─────────────
|
|
147
|
+
test("milestone completion requires all slices closed", () => {
|
|
148
|
+
insertMilestone({ id: "M001" });
|
|
149
|
+
insertSlice({ id: "S01", milestoneId: "M001", status: "done" });
|
|
150
|
+
insertSlice({ id: "S02", milestoneId: "M001", status: "pending" });
|
|
151
|
+
|
|
152
|
+
const s01 = getSlice("M001", "S01");
|
|
153
|
+
const s02 = getSlice("M001", "S02");
|
|
154
|
+
|
|
155
|
+
assert.ok(s01 !== null, "S01 exists");
|
|
156
|
+
assert.ok(s02 !== null, "S02 exists");
|
|
157
|
+
|
|
158
|
+
const slices = [s01!, s02!];
|
|
159
|
+
const incompleteSlices = slices.filter(s => !isClosedStatus(s.status));
|
|
160
|
+
assert.ok(
|
|
161
|
+
incompleteSlices.length > 0,
|
|
162
|
+
"milestone is not completable — has incomplete slices",
|
|
163
|
+
);
|
|
164
|
+
assert.equal(incompleteSlices[0]?.id, "S02", "S02 is the incomplete slice");
|
|
165
|
+
assert.equal(incompleteSlices[0]?.status, "pending", "S02 status is 'pending'");
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
// ─── Test 8: closed parent blocks child completion ───────────────────────
|
|
169
|
+
test("closed parent blocks child completion", () => {
|
|
170
|
+
// Insert a milestone already in 'complete' state
|
|
171
|
+
insertMilestone({ id: "M001", status: "complete" });
|
|
172
|
+
insertSlice({ id: "S01", milestoneId: "M001" });
|
|
173
|
+
|
|
174
|
+
const milestone = getMilestone("M001");
|
|
175
|
+
assert.ok(milestone !== null, "milestone M001 exists");
|
|
176
|
+
assert.ok(
|
|
177
|
+
isClosedStatus(milestone!.status),
|
|
178
|
+
"parent milestone is closed — isClosedStatus returns true",
|
|
179
|
+
);
|
|
180
|
+
|
|
181
|
+
// The guard in complete-slice checks parent status via isClosedStatus.
|
|
182
|
+
// If isClosedStatus(milestone.status) === true, the child cannot be completed.
|
|
183
|
+
const parentIsClosed = isClosedStatus(milestone!.status);
|
|
184
|
+
assert.ok(parentIsClosed, "closed parent guard fires: milestone.status is 'complete'");
|
|
185
|
+
|
|
186
|
+
// Verify the slice itself is not yet closed
|
|
187
|
+
const slice = getSlice("M001", "S01");
|
|
188
|
+
assert.ok(slice !== null, "slice S01 exists");
|
|
189
|
+
assert.ok(!isClosedStatus(slice!.status), "slice S01 is not yet closed (parent is already closed)");
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
});
|
|
@@ -41,14 +41,14 @@ test("research-slice classifies as standard", () => {
|
|
|
41
41
|
assert.equal(result.tier, "standard");
|
|
42
42
|
});
|
|
43
43
|
|
|
44
|
-
test("plan-milestone classifies as
|
|
44
|
+
test("plan-milestone classifies as heavy", () => {
|
|
45
45
|
const result = classifyUnitComplexity("plan-milestone", "M001", "/tmp/fake");
|
|
46
|
-
assert.equal(result.tier, "
|
|
46
|
+
assert.equal(result.tier, "heavy");
|
|
47
47
|
});
|
|
48
48
|
|
|
49
|
-
test("plan-slice classifies as
|
|
49
|
+
test("plan-slice classifies as heavy", () => {
|
|
50
50
|
const result = classifyUnitComplexity("plan-slice", "M001/S01", "/tmp/fake");
|
|
51
|
-
assert.equal(result.tier, "
|
|
51
|
+
assert.equal(result.tier, "heavy");
|
|
52
52
|
});
|
|
53
53
|
|
|
54
54
|
test("replan-slice classifies as heavy", () => {
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* db-path-worktree-symlink.test.ts — #2517
|
|
3
|
+
*
|
|
4
|
+
* Regression test for the db_unavailable loop in worktree/symlink layouts.
|
|
5
|
+
*
|
|
6
|
+
* The path resolver must handle BOTH worktree path families:
|
|
7
|
+
* - /.gsd/worktrees/<MID>/... (direct layout)
|
|
8
|
+
* - /.gsd/projects/<hash>/worktrees/<MID>/... (symlink-resolved layout)
|
|
9
|
+
*
|
|
10
|
+
* When the second layout is not recognised, ensureDbOpen derives a wrong DB
|
|
11
|
+
* path, the open fails silently, and every completion tool call returns
|
|
12
|
+
* db_unavailable — triggering an artifact retry re-dispatch loop.
|
|
13
|
+
*
|
|
14
|
+
* Additionally, the post-unit artifact retry path must NOT retry when the
|
|
15
|
+
* completion tool failed due to db_unavailable (infra failure), because
|
|
16
|
+
* retrying can never succeed and causes cost spikes.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
import { readFileSync } from "node:fs";
|
|
20
|
+
import { join, sep } from "node:path";
|
|
21
|
+
import { createTestContext } from "./test-helpers.ts";
|
|
22
|
+
|
|
23
|
+
const { assertEq, assertTrue, report } = createTestContext();
|
|
24
|
+
|
|
25
|
+
// ── Part 1: resolveProjectRootDbPath handles symlink-resolved layout ─────
|
|
26
|
+
|
|
27
|
+
console.log("\n=== #2517 Part 1: resolveProjectRootDbPath symlink layout ===");
|
|
28
|
+
|
|
29
|
+
// Import the resolver directly
|
|
30
|
+
const { resolveProjectRootDbPath } = await import("../bootstrap/dynamic-tools.js");
|
|
31
|
+
|
|
32
|
+
// Standard worktree layout (already works)
|
|
33
|
+
const standardPath = `/home/user/myproject/.gsd/worktrees/M001/work`;
|
|
34
|
+
const standardResult = resolveProjectRootDbPath(standardPath);
|
|
35
|
+
assertEq(
|
|
36
|
+
standardResult,
|
|
37
|
+
join("/home/user/myproject", ".gsd", "gsd.db"),
|
|
38
|
+
"Standard worktree layout resolves to project root DB path",
|
|
39
|
+
);
|
|
40
|
+
|
|
41
|
+
// Symlink-resolved layout (the regression — /.gsd/projects/<hash>/worktrees/...)
|
|
42
|
+
const symlinkPath = `/home/user/myproject/.gsd/projects/abc123def/worktrees/M001/work`;
|
|
43
|
+
const symlinkResult = resolveProjectRootDbPath(symlinkPath);
|
|
44
|
+
assertEq(
|
|
45
|
+
symlinkResult,
|
|
46
|
+
join("/home/user/myproject", ".gsd", "gsd.db"),
|
|
47
|
+
"Symlink-resolved layout (/.gsd/projects/<hash>/worktrees/) resolves to project root DB path (#2517)",
|
|
48
|
+
);
|
|
49
|
+
|
|
50
|
+
// Windows-style separators for symlink layout
|
|
51
|
+
if (sep === "\\") {
|
|
52
|
+
const winSymlinkPath = `C:\\Users\\dev\\project\\.gsd\\projects\\abc123def\\worktrees\\M001\\work`;
|
|
53
|
+
const winResult = resolveProjectRootDbPath(winSymlinkPath);
|
|
54
|
+
assertEq(
|
|
55
|
+
winResult,
|
|
56
|
+
join("C:\\Users\\dev\\project", ".gsd", "gsd.db"),
|
|
57
|
+
"Windows symlink layout resolves correctly",
|
|
58
|
+
);
|
|
59
|
+
} else {
|
|
60
|
+
// On non-Windows, test forward-slash variant explicitly
|
|
61
|
+
const fwdSymlinkPath = `/home/user/myproject/.gsd/projects/abc123def/worktrees/M001/work`;
|
|
62
|
+
const fwdResult = resolveProjectRootDbPath(fwdSymlinkPath);
|
|
63
|
+
assertEq(
|
|
64
|
+
fwdResult,
|
|
65
|
+
join("/home/user/myproject", ".gsd", "gsd.db"),
|
|
66
|
+
"Forward-slash symlink layout resolves correctly on POSIX",
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// Edge: deeper nesting under projects/<hash>/worktrees
|
|
71
|
+
const deepSymlinkPath = `/home/user/myproject/.gsd/projects/deadbeef42/worktrees/M003/sub/dir`;
|
|
72
|
+
const deepResult = resolveProjectRootDbPath(deepSymlinkPath);
|
|
73
|
+
assertEq(
|
|
74
|
+
deepResult,
|
|
75
|
+
join("/home/user/myproject", ".gsd", "gsd.db"),
|
|
76
|
+
"Deep symlink worktree path still resolves to project root DB",
|
|
77
|
+
);
|
|
78
|
+
|
|
79
|
+
// Non-worktree path should be unchanged
|
|
80
|
+
const normalPath = `/home/user/myproject`;
|
|
81
|
+
const normalResult = resolveProjectRootDbPath(normalPath);
|
|
82
|
+
assertEq(
|
|
83
|
+
normalResult,
|
|
84
|
+
join("/home/user/myproject", ".gsd", "gsd.db"),
|
|
85
|
+
"Non-worktree path is unchanged",
|
|
86
|
+
);
|
|
87
|
+
|
|
88
|
+
// ── Part 2: ensureDbOpen returns structured failure context ──────────────
|
|
89
|
+
|
|
90
|
+
console.log("\n=== #2517 Part 2: ensureDbOpen structured diagnostics ===");
|
|
91
|
+
|
|
92
|
+
const dynamicToolsSrc = readFileSync(
|
|
93
|
+
join(import.meta.dirname, "..", "bootstrap", "dynamic-tools.ts"),
|
|
94
|
+
"utf-8",
|
|
95
|
+
);
|
|
96
|
+
|
|
97
|
+
// ensureDbOpen should return a structured result, not just boolean false
|
|
98
|
+
// Check that the catch block provides diagnostic information
|
|
99
|
+
assertTrue(
|
|
100
|
+
dynamicToolsSrc.includes("resolvedPath") || dynamicToolsSrc.includes("diagnostic"),
|
|
101
|
+
"ensureDbOpen catch block surfaces diagnostic information (resolvedPath or diagnostic) instead of bare false (#2517)",
|
|
102
|
+
);
|
|
103
|
+
|
|
104
|
+
// ── Part 3: post-unit does NOT artifact-retry on db_unavailable ──────────
|
|
105
|
+
|
|
106
|
+
console.log("\n=== #2517 Part 3: post-unit db_unavailable is infra-fatal ===");
|
|
107
|
+
|
|
108
|
+
const postUnitSrc = readFileSync(
|
|
109
|
+
join(import.meta.dirname, "..", "auto-post-unit.ts"),
|
|
110
|
+
"utf-8",
|
|
111
|
+
);
|
|
112
|
+
|
|
113
|
+
// The artifact retry block should check DB availability and skip retry
|
|
114
|
+
// when the DB is unavailable (infra failure, not a missing artifact).
|
|
115
|
+
assertTrue(
|
|
116
|
+
postUnitSrc.includes("db_unavailable") || postUnitSrc.includes("isDbAvailable"),
|
|
117
|
+
"post-unit artifact retry path checks DB availability to avoid retry loop (#2517)",
|
|
118
|
+
);
|
|
119
|
+
|
|
120
|
+
// Verify the retry block is guarded: when !isDbAvailable(), the code must
|
|
121
|
+
// NOT return "retry". The pattern should be: if (!verified && !isDbAvailable()) { skip }
|
|
122
|
+
// followed by else if (!verified) { ... return "retry" }
|
|
123
|
+
const dbUnavailableGuard = postUnitSrc.match(
|
|
124
|
+
/!triggerArtifactVerified\s*&&\s*!isDbAvailable\(\)/,
|
|
125
|
+
);
|
|
126
|
+
assertTrue(
|
|
127
|
+
!!dbUnavailableGuard,
|
|
128
|
+
"The retry block explicitly guards against !isDbAvailable() before returning 'retry' (#2517)",
|
|
129
|
+
);
|
|
130
|
+
|
|
131
|
+
report();
|
|
@@ -416,23 +416,18 @@ describe('db-writer', () => {
|
|
|
416
416
|
}
|
|
417
417
|
});
|
|
418
418
|
|
|
419
|
-
test('updateRequirementInDb — not found', async () => {
|
|
419
|
+
test('updateRequirementInDb — upserts when not found (#2919)', async () => {
|
|
420
420
|
const tmpDir = makeTmpDir();
|
|
421
421
|
const dbPath = path.join(tmpDir, '.gsd', 'gsd.db');
|
|
422
422
|
openDatabase(dbPath);
|
|
423
423
|
|
|
424
424
|
try {
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
(err as Error).message.includes('R999'),
|
|
432
|
-
'error message mentions the missing ID',
|
|
433
|
-
);
|
|
434
|
-
}
|
|
435
|
-
assert.ok(threw, 'throws when requirement not found');
|
|
425
|
+
// Previously threw; now upserts a skeleton requirement with the provided updates
|
|
426
|
+
await updateRequirementInDb('R999', { status: 'validated' }, tmpDir);
|
|
427
|
+
const created = getRequirementById('R999');
|
|
428
|
+
assert.ok(created !== null, 'R999 should be created by upsert');
|
|
429
|
+
assert.deepStrictEqual(created!.status, 'validated', 'Upserted requirement should have validated status');
|
|
430
|
+
assert.deepStrictEqual(created!.id, 'R999', 'Upserted requirement should keep the provided ID');
|
|
436
431
|
} finally {
|
|
437
432
|
closeDatabase();
|
|
438
433
|
cleanupDir(tmpDir);
|
|
@@ -4,7 +4,7 @@ import { mkdtempSync, mkdirSync, rmSync, writeFileSync } from 'node:fs';
|
|
|
4
4
|
import { join } from 'node:path';
|
|
5
5
|
import { tmpdir } from 'node:os';
|
|
6
6
|
|
|
7
|
-
import { deriveState, invalidateStateCache, _deriveStateImpl, deriveStateFromDb } from '../state.ts';
|
|
7
|
+
import { deriveState, invalidateStateCache, _deriveStateImpl, deriveStateFromDb, isGhostMilestone } from '../state.ts';
|
|
8
8
|
import {
|
|
9
9
|
openDatabase,
|
|
10
10
|
closeDatabase,
|
|
@@ -934,8 +934,8 @@ describe('derive-state-db', async () => {
|
|
|
934
934
|
}
|
|
935
935
|
});
|
|
936
936
|
|
|
937
|
-
// ─── Test 21: Ghost milestone skipped
|
|
938
|
-
test('derive-state-db: ghost milestone skipped', async () => {
|
|
937
|
+
// ─── Test 21: Ghost milestone skipped (no DB row, no worktree) ─────────
|
|
938
|
+
test('derive-state-db: ghost milestone skipped when no DB row and no worktree', async () => {
|
|
939
939
|
const base = createFixtureBase();
|
|
940
940
|
try {
|
|
941
941
|
// Ghost: milestone dir exists with only META.json, no context/roadmap/summary
|
|
@@ -948,8 +948,7 @@ describe('derive-state-db', async () => {
|
|
|
948
948
|
const fileState = await _deriveStateImpl(base);
|
|
949
949
|
|
|
950
950
|
openDatabase(':memory:');
|
|
951
|
-
//
|
|
952
|
-
insertMilestone({ id: 'M001', title: '', status: 'active' });
|
|
951
|
+
// Only insert M002 — M001 has no DB row (simulates row loss / never inserted)
|
|
953
952
|
insertMilestone({ id: 'M002', title: 'Real', status: 'active' });
|
|
954
953
|
|
|
955
954
|
invalidateStateCache();
|
|
@@ -1051,4 +1050,78 @@ describe('derive-state-db', async () => {
|
|
|
1051
1050
|
closeDatabase();
|
|
1052
1051
|
}
|
|
1053
1052
|
});
|
|
1053
|
+
|
|
1054
|
+
// ─── Queued milestone with worktree not flagged as ghost (#2921) ──────
|
|
1055
|
+
test('derive-state-db: queued milestone with worktree not flagged as ghost (#2921)', async () => {
|
|
1056
|
+
const base = createFixtureBase();
|
|
1057
|
+
try {
|
|
1058
|
+
// M001: complete milestone with summary
|
|
1059
|
+
writeFile(base, 'milestones/M001/M001-SUMMARY.md', '# M001 Summary\n\nDone.');
|
|
1060
|
+
|
|
1061
|
+
// M002: queued milestone — directory + slices dir exists, but no content files.
|
|
1062
|
+
// This is what happens when ensureMilestoneDbRow creates M002 but the DB row
|
|
1063
|
+
// is lost during worktree teardown.
|
|
1064
|
+
mkdirSync(join(base, '.gsd', 'milestones', 'M002', 'slices'), { recursive: true });
|
|
1065
|
+
|
|
1066
|
+
// A worktree exists for M002, proving it's a legitimate milestone
|
|
1067
|
+
mkdirSync(join(base, '.gsd', 'worktrees', 'M002'), { recursive: true });
|
|
1068
|
+
|
|
1069
|
+
// isGhostMilestone should NOT treat M002 as ghost when worktree exists
|
|
1070
|
+
assert.ok(!isGhostMilestone(base, 'M002'), 'ghost-wt: M002 with worktree is NOT a ghost');
|
|
1071
|
+
|
|
1072
|
+
// DB has M001 complete but M002 row was lost
|
|
1073
|
+
openDatabase(':memory:');
|
|
1074
|
+
insertMilestone({ id: 'M001', title: 'First', status: 'complete' });
|
|
1075
|
+
// No M002 row — simulates DB row loss during worktree teardown
|
|
1076
|
+
|
|
1077
|
+
invalidateStateCache();
|
|
1078
|
+
const dbState = await deriveStateFromDb(base);
|
|
1079
|
+
|
|
1080
|
+
// M002 should be reconciled from disk (not skipped as ghost) and become active
|
|
1081
|
+
const m002Entry = dbState.registry.find(e => e.id === 'M002');
|
|
1082
|
+
assert.ok(m002Entry !== undefined, 'ghost-wt: M002 should be in registry');
|
|
1083
|
+
assert.deepStrictEqual(dbState.activeMilestone?.id, 'M002', 'ghost-wt: M002 should be active');
|
|
1084
|
+
// Should NOT be phase: complete
|
|
1085
|
+
assert.notEqual(dbState.phase, 'complete', 'ghost-wt: phase should not be complete');
|
|
1086
|
+
|
|
1087
|
+
closeDatabase();
|
|
1088
|
+
} finally {
|
|
1089
|
+
closeDatabase();
|
|
1090
|
+
cleanup(base);
|
|
1091
|
+
}
|
|
1092
|
+
});
|
|
1093
|
+
|
|
1094
|
+
// ─── Queued milestone with DB row not flagged as ghost (#2921) ────────
|
|
1095
|
+
test('derive-state-db: queued milestone with DB row not flagged as ghost (#2921)', async () => {
|
|
1096
|
+
const base = createFixtureBase();
|
|
1097
|
+
try {
|
|
1098
|
+
// M001: complete milestone with summary
|
|
1099
|
+
writeFile(base, 'milestones/M001/M001-SUMMARY.md', '# M001 Summary\n\nDone.');
|
|
1100
|
+
|
|
1101
|
+
// M002: queued milestone — directory exists, no content files, but has DB row
|
|
1102
|
+
mkdirSync(join(base, '.gsd', 'milestones', 'M002', 'slices'), { recursive: true });
|
|
1103
|
+
|
|
1104
|
+
// DB has both M001 complete and M002 queued
|
|
1105
|
+
openDatabase(':memory:');
|
|
1106
|
+
insertMilestone({ id: 'M001', title: 'First', status: 'complete' });
|
|
1107
|
+
insertMilestone({ id: 'M002', title: 'Second', status: 'queued' });
|
|
1108
|
+
|
|
1109
|
+
// isGhostMilestone should NOT treat M002 as ghost when DB row exists
|
|
1110
|
+
assert.ok(!isGhostMilestone(base, 'M002'), 'ghost-dbrow: M002 with DB row is NOT a ghost');
|
|
1111
|
+
|
|
1112
|
+
invalidateStateCache();
|
|
1113
|
+
const dbState = await deriveStateFromDb(base);
|
|
1114
|
+
|
|
1115
|
+
// M002 should not be skipped
|
|
1116
|
+
const m002Entry = dbState.registry.find(e => e.id === 'M002');
|
|
1117
|
+
assert.ok(m002Entry !== undefined, 'ghost-dbrow: M002 should be in registry');
|
|
1118
|
+
assert.deepStrictEqual(dbState.activeMilestone?.id, 'M002', 'ghost-dbrow: M002 should be active');
|
|
1119
|
+
assert.notEqual(dbState.phase, 'complete', 'ghost-dbrow: phase should not be complete');
|
|
1120
|
+
|
|
1121
|
+
closeDatabase();
|
|
1122
|
+
} finally {
|
|
1123
|
+
closeDatabase();
|
|
1124
|
+
cleanup(base);
|
|
1125
|
+
}
|
|
1126
|
+
});
|
|
1054
1127
|
});
|
|
@@ -930,6 +930,35 @@ slice: S01
|
|
|
930
930
|
}
|
|
931
931
|
});
|
|
932
932
|
|
|
933
|
+
// ─── Test: queued milestone with worktree not flagged as ghost (#2921) ──
|
|
934
|
+
test('queued milestone with worktree not flagged as ghost (#2921)', async () => {
|
|
935
|
+
const base = createFixtureBase();
|
|
936
|
+
try {
|
|
937
|
+
// Create a milestone directory with only an empty slices subdir — no content files.
|
|
938
|
+
// This would normally be a ghost, but it has a worktree directory.
|
|
939
|
+
const milestoneDir = join(base, '.gsd', 'milestones', 'M002');
|
|
940
|
+
mkdirSync(join(milestoneDir, 'slices'), { recursive: true });
|
|
941
|
+
|
|
942
|
+
// Create a worktree directory for M002, simulating an active worktree
|
|
943
|
+
const worktreeDir = join(base, '.gsd', 'worktrees', 'M002');
|
|
944
|
+
mkdirSync(worktreeDir, { recursive: true });
|
|
945
|
+
|
|
946
|
+
// isGhostMilestone should return false because the worktree exists
|
|
947
|
+
assert.ok(!isGhostMilestone(base, 'M002'), 'M002 with worktree should NOT be a ghost');
|
|
948
|
+
|
|
949
|
+
// Also create a completed M001 so deriveState has something before M002
|
|
950
|
+
writeMilestoneSummary(base, 'M001', '# M001 Summary\n\nDone.');
|
|
951
|
+
|
|
952
|
+
const state = await deriveState(base);
|
|
953
|
+
// M002 should appear in the registry (not filtered as ghost)
|
|
954
|
+
const m002Entry = state.registry.find(e => e.id === 'M002');
|
|
955
|
+
assert.ok(m002Entry !== undefined, 'M002 should be in registry when worktree exists');
|
|
956
|
+
assert.deepStrictEqual(state.activeMilestone?.id, 'M002', 'M002 should be active milestone');
|
|
957
|
+
} finally {
|
|
958
|
+
cleanup(base);
|
|
959
|
+
}
|
|
960
|
+
});
|
|
961
|
+
|
|
933
962
|
// ─── Test: zero-slice roadmap → pre-planning, not blocked (#1785) ────
|
|
934
963
|
test('zero-slice roadmap → pre-planning, not blocked (#1785)', async () => {
|
|
935
964
|
const base = createFixtureBase();
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import assert from "node:assert/strict";
|
|
2
|
+
import { describe, it } from "node:test";
|
|
3
|
+
import { readFileSync } from "node:fs";
|
|
4
|
+
import { join } from "node:path";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Validates that all Discord invite links in user-facing files point to valid,
|
|
8
|
+
* consistent invite URLs — not expired vanity links.
|
|
9
|
+
*
|
|
10
|
+
* Regression test for https://github.com/gsd-build/gsd-2/issues/2699
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
const ROOT = process.cwd();
|
|
14
|
+
|
|
15
|
+
/** Canonical Discord invite for the GSD community. */
|
|
16
|
+
const VALID_INVITE = "https://discord.com/invite/nKXTsAcmbT";
|
|
17
|
+
|
|
18
|
+
/** Files that contain user-facing Discord invite links. */
|
|
19
|
+
const FILES_WITH_INVITE_LINKS: string[] = [
|
|
20
|
+
"README.md",
|
|
21
|
+
"docs/what-is-pi/15-pi-packages-the-ecosystem.md",
|
|
22
|
+
];
|
|
23
|
+
|
|
24
|
+
describe("Discord invite links (#2699)", () => {
|
|
25
|
+
for (const relPath of FILES_WITH_INVITE_LINKS) {
|
|
26
|
+
it(`${relPath} contains only the canonical Discord invite`, () => {
|
|
27
|
+
const content = readFileSync(join(ROOT, relPath), "utf8");
|
|
28
|
+
|
|
29
|
+
// Extract all Discord invite URLs (discord.gg/X or discord.com/invite/X)
|
|
30
|
+
const invitePattern = /https?:\/\/(?:discord\.gg|discord\.com\/invite)\/[A-Za-z0-9]+/g;
|
|
31
|
+
const matches = content.match(invitePattern);
|
|
32
|
+
|
|
33
|
+
assert.ok(
|
|
34
|
+
matches && matches.length > 0,
|
|
35
|
+
`Expected at least one Discord invite link in ${relPath}`,
|
|
36
|
+
);
|
|
37
|
+
|
|
38
|
+
for (const link of matches) {
|
|
39
|
+
assert.equal(
|
|
40
|
+
link,
|
|
41
|
+
VALID_INVITE,
|
|
42
|
+
`Invalid Discord invite in ${relPath}: found "${link}", expected "${VALID_INVITE}"`,
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
});
|