gsd-pi 2.58.0-dev.d63175c → 2.58.0-dev.e002a57
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/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 +17 -17
- package/dist/web/standalone/.next/build-manifest.json +3 -3
- package/dist/web/standalone/.next/prerender-manifest.json +3 -3
- package/dist/web/standalone/.next/react-loadable-manifest.json +1 -1
- package/dist/web/standalone/.next/required-server-files.json +1 -1
- package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.html +2 -2
- package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found/page_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 +2 -2
- package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +2 -2
- 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 +2 -2
- 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_client-reference-manifest.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_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/browse-directories/route_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_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_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_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_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_client-reference-manifest.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_client-reference-manifest.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_client-reference-manifest.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_client-reference-manifest.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_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/events/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/manage/route_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_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_client-reference-manifest.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_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/resize/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/sessions/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/stream/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/upload/route_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 +2 -2
- package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +2 -2
- package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +2 -2
- package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +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 +17 -17
- package/dist/web/standalone/.next/server/chunks/2229.js +2 -2
- 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/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/{webpack-61d3afac6d0f0ce7.js → webpack-a1c1e452c6b32d04.js} +1 -1
- package/dist/web/standalone/.next/static/css/f6e8833d46e738d8.css +1 -0
- 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/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.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.js +16 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts +1 -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 +27 -4
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.js +6 -0
- package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/theme/themes.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/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.ts +14 -1
- package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +35 -3
- package/packages/pi-coding-agent/src/modes/interactive/slash-command-handlers.ts +7 -0
- 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/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/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/css/a58ef8a151aa0493.css +0 -1
- package/src/resources/extensions/gsd/tests/empty-db-reconciliation.test.ts +0 -79
- /package/dist/web/standalone/.next/static/{5DLsjFHdSB6_a1EDQVjr7 → nUA6d2OJrDSVq9RNb-c8b}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{5DLsjFHdSB6_a1EDQVjr7 → nUA6d2OJrDSVq9RNb-c8b}/_ssgManifest.js +0 -0
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unit tests for the queue-mode execution guard (#2545).
|
|
3
|
+
*
|
|
4
|
+
* When queue phase is active, the agent should only create milestones —
|
|
5
|
+
* not execute work. This guard blocks write/edit/bash tool calls that
|
|
6
|
+
* target source code (non-.gsd/ paths) during queue mode.
|
|
7
|
+
*
|
|
8
|
+
* Exercises shouldBlockQueueExecution() — a pure function that checks:
|
|
9
|
+
* (a) queuePhaseActive false → pass (not in queue mode)
|
|
10
|
+
* (b) toolName is read-only (read, grep, find, ls) → pass
|
|
11
|
+
* (c) toolName is ask_user_questions → pass (discussion tool)
|
|
12
|
+
* (d) write/edit to .gsd/ path → pass (planning artifacts)
|
|
13
|
+
* (e) write/edit to source path → block
|
|
14
|
+
* (f) bash command → block (could execute work)
|
|
15
|
+
* (g) registered GSD tools (gsd_milestone_generate_id, gsd_summary_save) → pass
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
import test from 'node:test';
|
|
19
|
+
import assert from 'node:assert/strict';
|
|
20
|
+
import { shouldBlockQueueExecution } from '../bootstrap/write-gate.ts';
|
|
21
|
+
|
|
22
|
+
// ─── Scenario 1: Not in queue mode — all tools pass ──
|
|
23
|
+
|
|
24
|
+
test('queue-guard: allows all tools when queue phase is not active', () => {
|
|
25
|
+
const r1 = shouldBlockQueueExecution('write', '/src/index.ts', false);
|
|
26
|
+
assert.strictEqual(r1.block, false, 'write should pass outside queue mode');
|
|
27
|
+
|
|
28
|
+
const r2 = shouldBlockQueueExecution('bash', 'npm test', false);
|
|
29
|
+
assert.strictEqual(r2.block, false, 'bash should pass outside queue mode');
|
|
30
|
+
|
|
31
|
+
const r3 = shouldBlockQueueExecution('edit', '/src/index.ts', false);
|
|
32
|
+
assert.strictEqual(r3.block, false, 'edit should pass outside queue mode');
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
// ─── Scenario 2: Read-only tools always pass in queue mode ──
|
|
36
|
+
|
|
37
|
+
test('queue-guard: allows read-only tools during queue mode', () => {
|
|
38
|
+
for (const tool of ['read', 'grep', 'find', 'ls', 'glob']) {
|
|
39
|
+
const result = shouldBlockQueueExecution(tool, '/src/index.ts', true);
|
|
40
|
+
assert.strictEqual(result.block, false, `${tool} should pass in queue mode`);
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
// ─── Scenario 3: Discussion/planning tools pass in queue mode ──
|
|
45
|
+
|
|
46
|
+
test('queue-guard: allows discussion and planning tools during queue mode', () => {
|
|
47
|
+
const r1 = shouldBlockQueueExecution('ask_user_questions', '', true);
|
|
48
|
+
assert.strictEqual(r1.block, false, 'ask_user_questions should pass');
|
|
49
|
+
|
|
50
|
+
const r2 = shouldBlockQueueExecution('gsd_milestone_generate_id', '', true);
|
|
51
|
+
assert.strictEqual(r2.block, false, 'gsd_milestone_generate_id should pass');
|
|
52
|
+
|
|
53
|
+
const r3 = shouldBlockQueueExecution('gsd_summary_save', '', true);
|
|
54
|
+
assert.strictEqual(r3.block, false, 'gsd_summary_save should pass');
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
// ─── Scenario 4: Write to .gsd/ paths passes (planning artifacts) ──
|
|
58
|
+
|
|
59
|
+
test('queue-guard: allows writes to .gsd/ paths during queue mode', () => {
|
|
60
|
+
const r1 = shouldBlockQueueExecution('write', '.gsd/milestones/M001/M001-CONTEXT.md', true);
|
|
61
|
+
assert.strictEqual(r1.block, false, 'write to .gsd/ should pass');
|
|
62
|
+
|
|
63
|
+
const r2 = shouldBlockQueueExecution('write', '/project/.gsd/PROJECT.md', true);
|
|
64
|
+
assert.strictEqual(r2.block, false, 'write to .gsd/PROJECT.md should pass');
|
|
65
|
+
|
|
66
|
+
const r3 = shouldBlockQueueExecution('edit', '.gsd/QUEUE.md', true);
|
|
67
|
+
assert.strictEqual(r3.block, false, 'edit to .gsd/QUEUE.md should pass');
|
|
68
|
+
|
|
69
|
+
const r4 = shouldBlockQueueExecution('write', '.gsd/REQUIREMENTS.md', true);
|
|
70
|
+
assert.strictEqual(r4.block, false, 'write to .gsd/REQUIREMENTS.md should pass');
|
|
71
|
+
|
|
72
|
+
const r5 = shouldBlockQueueExecution('write', '.gsd/DECISIONS.md', true);
|
|
73
|
+
assert.strictEqual(r5.block, false, 'write to .gsd/DECISIONS.md should pass');
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
// ─── Scenario 5: Write/edit to source code paths blocked ──
|
|
77
|
+
|
|
78
|
+
test('queue-guard: blocks writes to source code during queue mode', () => {
|
|
79
|
+
const r1 = shouldBlockQueueExecution('write', 'src/index.ts', true);
|
|
80
|
+
assert.strictEqual(r1.block, true, 'write to src/ should be blocked');
|
|
81
|
+
assert.ok(r1.reason, 'should provide a reason');
|
|
82
|
+
assert.ok(r1.reason!.includes('queue'), 'reason should mention queue');
|
|
83
|
+
|
|
84
|
+
const r2 = shouldBlockQueueExecution('write', '/project/src/components/App.tsx', true);
|
|
85
|
+
assert.strictEqual(r2.block, true, 'write to component file should be blocked');
|
|
86
|
+
|
|
87
|
+
const r3 = shouldBlockQueueExecution('edit', 'package.json', true);
|
|
88
|
+
assert.strictEqual(r3.block, true, 'edit to package.json should be blocked');
|
|
89
|
+
|
|
90
|
+
const r4 = shouldBlockQueueExecution('edit', '/project/lib/utils.ts', true);
|
|
91
|
+
assert.strictEqual(r4.block, true, 'edit to lib/ should be blocked');
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
// ─── Scenario 6: Bash commands blocked during queue mode ──
|
|
95
|
+
|
|
96
|
+
test('queue-guard: blocks bash commands during queue mode', () => {
|
|
97
|
+
const r1 = shouldBlockQueueExecution('bash', 'npm install some-package', true);
|
|
98
|
+
assert.strictEqual(r1.block, true, 'npm install should be blocked');
|
|
99
|
+
assert.ok(r1.reason, 'should provide a reason');
|
|
100
|
+
|
|
101
|
+
const r2 = shouldBlockQueueExecution('bash', 'node src/index.ts', true);
|
|
102
|
+
assert.strictEqual(r2.block, true, 'running node should be blocked');
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
// ─── Scenario 7: Bash read-only commands pass during queue mode ──
|
|
106
|
+
|
|
107
|
+
test('queue-guard: allows read-only bash commands during queue mode', () => {
|
|
108
|
+
const r1 = shouldBlockQueueExecution('bash', 'cat src/index.ts', true);
|
|
109
|
+
assert.strictEqual(r1.block, false, 'cat should pass');
|
|
110
|
+
|
|
111
|
+
const r2 = shouldBlockQueueExecution('bash', 'ls -la src/', true);
|
|
112
|
+
assert.strictEqual(r2.block, false, 'ls should pass');
|
|
113
|
+
|
|
114
|
+
const r3 = shouldBlockQueueExecution('bash', 'git log --oneline -10', true);
|
|
115
|
+
assert.strictEqual(r3.block, false, 'git log should pass');
|
|
116
|
+
|
|
117
|
+
const r4 = shouldBlockQueueExecution('bash', 'find . -name "*.ts"', true);
|
|
118
|
+
assert.strictEqual(r4.block, false, 'find should pass');
|
|
119
|
+
|
|
120
|
+
const r5 = shouldBlockQueueExecution('bash', 'grep -rn "TODO" src/', true);
|
|
121
|
+
assert.strictEqual(r5.block, false, 'grep should pass');
|
|
122
|
+
|
|
123
|
+
const r6 = shouldBlockQueueExecution('bash', 'head -20 src/index.ts', true);
|
|
124
|
+
assert.strictEqual(r6.block, false, 'head should pass');
|
|
125
|
+
|
|
126
|
+
const r7 = shouldBlockQueueExecution('bash', 'wc -l src/index.ts', true);
|
|
127
|
+
assert.strictEqual(r7.block, false, 'wc should pass');
|
|
128
|
+
|
|
129
|
+
const r8 = shouldBlockQueueExecution('bash', 'git diff HEAD~1', true);
|
|
130
|
+
assert.strictEqual(r8.block, false, 'git diff should pass');
|
|
131
|
+
|
|
132
|
+
const r9 = shouldBlockQueueExecution('bash', 'gh issue view 42', true);
|
|
133
|
+
assert.strictEqual(r9.block, false, 'gh issue view should pass');
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
// ─── Scenario 8: mkdir for .gsd/ milestone directories passes ──
|
|
137
|
+
|
|
138
|
+
test('queue-guard: allows mkdir for .gsd/ milestone directories', () => {
|
|
139
|
+
const r1 = shouldBlockQueueExecution('bash', 'mkdir -p .gsd/milestones/M010/slices', true);
|
|
140
|
+
assert.strictEqual(r1.block, false, 'mkdir -p .gsd/ should pass');
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
// ─── Scenario 9: Web search and library tools pass ──
|
|
144
|
+
|
|
145
|
+
test('queue-guard: allows web search and library tools during queue mode', () => {
|
|
146
|
+
const r1 = shouldBlockQueueExecution('search-the-web', '', true);
|
|
147
|
+
assert.strictEqual(r1.block, false, 'search-the-web should pass');
|
|
148
|
+
|
|
149
|
+
const r2 = shouldBlockQueueExecution('resolve_library', '', true);
|
|
150
|
+
assert.strictEqual(r2.block, false, 'resolve_library should pass');
|
|
151
|
+
|
|
152
|
+
const r3 = shouldBlockQueueExecution('get_library_docs', '', true);
|
|
153
|
+
assert.strictEqual(r3.block, false, 'get_library_docs should pass');
|
|
154
|
+
|
|
155
|
+
const r4 = shouldBlockQueueExecution('fetch_page', '', true);
|
|
156
|
+
assert.strictEqual(r4.block, false, 'fetch_page should pass');
|
|
157
|
+
});
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tests that cleanupQuickBranch is called on turn_end to squash-merge the
|
|
3
|
+
* quick branch back to the original branch after the agent completes.
|
|
4
|
+
*
|
|
5
|
+
* Relates to #2668: /gsd quick does not squash-merge branch back after agent
|
|
6
|
+
* completes task. cleanupQuickBranch() exists but is never invoked.
|
|
7
|
+
*
|
|
8
|
+
* The fix registers a turn_end hook in register-hooks.ts that calls
|
|
9
|
+
* cleanupQuickBranch() after each turn, which is a no-op when no quick-task
|
|
10
|
+
* state is pending.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import { describe, it } from "node:test";
|
|
14
|
+
import assert from "node:assert/strict";
|
|
15
|
+
import { readFileSync } from "node:fs";
|
|
16
|
+
import { join } from "node:path";
|
|
17
|
+
|
|
18
|
+
// ─── Structural test: verify turn_end hook exists in register-hooks.ts ──────
|
|
19
|
+
|
|
20
|
+
describe("quick task turn_end cleanup (#2668)", () => {
|
|
21
|
+
const hooksSource = readFileSync(
|
|
22
|
+
join(import.meta.dirname, "..", "bootstrap", "register-hooks.ts"),
|
|
23
|
+
"utf-8",
|
|
24
|
+
);
|
|
25
|
+
|
|
26
|
+
it("register-hooks.ts imports cleanupQuickBranch from quick.ts", () => {
|
|
27
|
+
assert.ok(
|
|
28
|
+
hooksSource.includes("cleanupQuickBranch"),
|
|
29
|
+
"register-hooks.ts must reference cleanupQuickBranch",
|
|
30
|
+
);
|
|
31
|
+
|
|
32
|
+
// Verify it's imported (not just mentioned in a comment)
|
|
33
|
+
const importMatch = hooksSource.match(
|
|
34
|
+
/import\s*\{[^}]*cleanupQuickBranch[^}]*\}\s*from\s*["'][^"']*quick/,
|
|
35
|
+
);
|
|
36
|
+
assert.ok(
|
|
37
|
+
importMatch,
|
|
38
|
+
"cleanupQuickBranch must be imported from quick module",
|
|
39
|
+
);
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
it("registers a turn_end handler that calls cleanupQuickBranch", () => {
|
|
43
|
+
// Find the turn_end registration
|
|
44
|
+
const turnEndMatch = hooksSource.match(
|
|
45
|
+
/pi\.on\(\s*["']turn_end["']/,
|
|
46
|
+
);
|
|
47
|
+
assert.ok(
|
|
48
|
+
turnEndMatch,
|
|
49
|
+
"register-hooks.ts must register a turn_end handler",
|
|
50
|
+
);
|
|
51
|
+
|
|
52
|
+
// Extract the turn_end handler body — find everything from the pi.on("turn_end"
|
|
53
|
+
// to the matching closing });
|
|
54
|
+
const turnEndIdx = hooksSource.indexOf(turnEndMatch[0]);
|
|
55
|
+
assert.ok(turnEndIdx !== -1);
|
|
56
|
+
|
|
57
|
+
// Get the rest of the source from that point
|
|
58
|
+
const rest = hooksSource.slice(turnEndIdx);
|
|
59
|
+
|
|
60
|
+
// The handler must call cleanupQuickBranch
|
|
61
|
+
// Look for cleanupQuickBranch within the first handler body (up to first `});`)
|
|
62
|
+
const handlerEnd = rest.indexOf("});");
|
|
63
|
+
assert.ok(handlerEnd !== -1, "turn_end handler has a closing });");
|
|
64
|
+
|
|
65
|
+
const handlerBody = rest.slice(0, handlerEnd);
|
|
66
|
+
assert.ok(
|
|
67
|
+
handlerBody.includes("cleanupQuickBranch"),
|
|
68
|
+
"turn_end handler must call cleanupQuickBranch",
|
|
69
|
+
);
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
it("turn_end handler calls cleanupQuickBranch without arguments (uses cwd default)", () => {
|
|
73
|
+
// cleanupQuickBranch(basePath = process.cwd()) — calling without args is correct
|
|
74
|
+
// because the handler runs in the same process where handleQuick set up cwd
|
|
75
|
+
const turnEndIdx = hooksSource.indexOf('pi.on("turn_end"') !== -1
|
|
76
|
+
? hooksSource.indexOf('pi.on("turn_end"')
|
|
77
|
+
: hooksSource.indexOf("pi.on('turn_end'");
|
|
78
|
+
assert.ok(turnEndIdx !== -1);
|
|
79
|
+
|
|
80
|
+
const rest = hooksSource.slice(turnEndIdx);
|
|
81
|
+
const handlerEnd = rest.indexOf("});");
|
|
82
|
+
const handlerBody = rest.slice(0, handlerEnd);
|
|
83
|
+
|
|
84
|
+
// Should call cleanupQuickBranch() — either bare or with no-arg form
|
|
85
|
+
assert.ok(
|
|
86
|
+
handlerBody.includes("cleanupQuickBranch("),
|
|
87
|
+
"turn_end handler invokes cleanupQuickBranch()",
|
|
88
|
+
);
|
|
89
|
+
});
|
|
90
|
+
});
|
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
closeDatabase,
|
|
10
10
|
insertMilestone,
|
|
11
11
|
insertSlice,
|
|
12
|
+
insertAssessment,
|
|
12
13
|
getSlice,
|
|
13
14
|
getMilestoneSlices,
|
|
14
15
|
getAssessment,
|
|
@@ -323,3 +324,119 @@ test('handleReassessRoadmap returns structured error payloads with actionable me
|
|
|
323
324
|
cleanup(base);
|
|
324
325
|
}
|
|
325
326
|
});
|
|
327
|
+
|
|
328
|
+
// ─── Bug #2957: Stale VALIDATION survives roadmap remediation ────────────
|
|
329
|
+
|
|
330
|
+
test('handleReassessRoadmap invalidates stale milestone-validation when roadmap changes (#2957)', async () => {
|
|
331
|
+
const base = makeTmpBase();
|
|
332
|
+
openDatabase(join(base, '.gsd', 'gsd.db'));
|
|
333
|
+
|
|
334
|
+
try {
|
|
335
|
+
// Seed: M001 with S01-S04 all complete, plus a stale VALIDATION with needs-remediation
|
|
336
|
+
insertMilestone({ id: 'M001', title: 'Test Milestone', status: 'active' });
|
|
337
|
+
insertSlice({ id: 'S01', milestoneId: 'M001', title: 'Slice One', status: 'complete', demo: 'Demo' });
|
|
338
|
+
insertSlice({ id: 'S02', milestoneId: 'M001', title: 'Slice Two', status: 'complete', demo: 'Demo' });
|
|
339
|
+
insertSlice({ id: 'S03', milestoneId: 'M001', title: 'Slice Three', status: 'complete', demo: 'Demo' });
|
|
340
|
+
insertSlice({ id: 'S04', milestoneId: 'M001', title: 'Slice Four', status: 'complete', demo: 'Demo' });
|
|
341
|
+
|
|
342
|
+
// Insert milestone-validation assessment with needs-remediation verdict (stale)
|
|
343
|
+
const validationPath = join('.gsd', 'milestones', 'M001', 'M001-VALIDATION.md');
|
|
344
|
+
insertAssessment({
|
|
345
|
+
path: validationPath,
|
|
346
|
+
milestoneId: 'M001',
|
|
347
|
+
sliceId: null,
|
|
348
|
+
taskId: null,
|
|
349
|
+
status: 'needs-remediation',
|
|
350
|
+
scope: 'milestone-validation',
|
|
351
|
+
fullContent: '---\nverdict: needs-remediation\nremediation_round: 0\n---\n\n# Validation\nNeeds remediation.',
|
|
352
|
+
});
|
|
353
|
+
|
|
354
|
+
// Verify the validation row exists before reassess
|
|
355
|
+
const adapter = _getAdapter()!;
|
|
356
|
+
const before = adapter.prepare(
|
|
357
|
+
`SELECT * FROM assessments WHERE milestone_id = 'M001' AND scope = 'milestone-validation'`,
|
|
358
|
+
).get() as Record<string, unknown> | undefined;
|
|
359
|
+
assert.ok(before, 'milestone-validation row should exist before reassess');
|
|
360
|
+
|
|
361
|
+
// Now reassess the roadmap: add remediation slice S05
|
|
362
|
+
// This simulates the scenario from #2957 where validation produced needs-remediation
|
|
363
|
+
// and then roadmap was reassessed to add a remediation slice
|
|
364
|
+
const result = await handleReassessRoadmap({
|
|
365
|
+
milestoneId: 'M001',
|
|
366
|
+
completedSliceId: 'S04',
|
|
367
|
+
verdict: 'on-track',
|
|
368
|
+
assessment: 'S04 completed. Adding remediation slice S05.',
|
|
369
|
+
sliceChanges: {
|
|
370
|
+
modified: [],
|
|
371
|
+
added: [
|
|
372
|
+
{
|
|
373
|
+
sliceId: 'S05',
|
|
374
|
+
title: 'Remediation Slice',
|
|
375
|
+
risk: 'low',
|
|
376
|
+
depends: ['S04'],
|
|
377
|
+
demo: 'Fix the issues found during validation.',
|
|
378
|
+
},
|
|
379
|
+
],
|
|
380
|
+
removed: [],
|
|
381
|
+
},
|
|
382
|
+
}, base);
|
|
383
|
+
|
|
384
|
+
assert.ok(!('error' in result), `unexpected error: ${'error' in result ? result.error : ''}`);
|
|
385
|
+
|
|
386
|
+
// The stale milestone-validation row must be deleted after roadmap changes
|
|
387
|
+
const after = adapter.prepare(
|
|
388
|
+
`SELECT * FROM assessments WHERE milestone_id = 'M001' AND scope = 'milestone-validation'`,
|
|
389
|
+
).get() as Record<string, unknown> | undefined;
|
|
390
|
+
assert.equal(after, undefined, 'milestone-validation row should be deleted after roadmap changes — stale validation must not survive remediation (#2957)');
|
|
391
|
+
} finally {
|
|
392
|
+
cleanup(base);
|
|
393
|
+
}
|
|
394
|
+
});
|
|
395
|
+
|
|
396
|
+
test('handleReassessRoadmap does NOT invalidate validation when no roadmap structural changes (#2957)', async () => {
|
|
397
|
+
const base = makeTmpBase();
|
|
398
|
+
openDatabase(join(base, '.gsd', 'gsd.db'));
|
|
399
|
+
|
|
400
|
+
try {
|
|
401
|
+
// Seed: M001 with slices, plus a validation with pass verdict
|
|
402
|
+
insertMilestone({ id: 'M001', title: 'Test Milestone', status: 'active' });
|
|
403
|
+
insertSlice({ id: 'S01', milestoneId: 'M001', title: 'Slice One', status: 'complete', demo: 'Demo' });
|
|
404
|
+
insertSlice({ id: 'S02', milestoneId: 'M001', title: 'Slice Two', status: 'pending', demo: 'Demo' });
|
|
405
|
+
|
|
406
|
+
// Insert milestone-validation assessment with pass verdict
|
|
407
|
+
const validationPath = join('.gsd', 'milestones', 'M001', 'M001-VALIDATION.md');
|
|
408
|
+
insertAssessment({
|
|
409
|
+
path: validationPath,
|
|
410
|
+
milestoneId: 'M001',
|
|
411
|
+
sliceId: null,
|
|
412
|
+
taskId: null,
|
|
413
|
+
status: 'pass',
|
|
414
|
+
scope: 'milestone-validation',
|
|
415
|
+
fullContent: '---\nverdict: pass\nremediation_round: 0\n---\n\n# Validation\nAll good.',
|
|
416
|
+
});
|
|
417
|
+
|
|
418
|
+
// Reassess with no structural changes (empty added/modified/removed)
|
|
419
|
+
const result = await handleReassessRoadmap({
|
|
420
|
+
milestoneId: 'M001',
|
|
421
|
+
completedSliceId: 'S01',
|
|
422
|
+
verdict: 'confirmed',
|
|
423
|
+
assessment: 'S01 completed. No changes needed.',
|
|
424
|
+
sliceChanges: {
|
|
425
|
+
modified: [],
|
|
426
|
+
added: [],
|
|
427
|
+
removed: [],
|
|
428
|
+
},
|
|
429
|
+
}, base);
|
|
430
|
+
|
|
431
|
+
assert.ok(!('error' in result), `unexpected error: ${'error' in result ? result.error : ''}`);
|
|
432
|
+
|
|
433
|
+
// Validation should still exist when no structural changes occurred
|
|
434
|
+
const adapter = _getAdapter()!;
|
|
435
|
+
const row = adapter.prepare(
|
|
436
|
+
`SELECT * FROM assessments WHERE milestone_id = 'M001' AND scope = 'milestone-validation'`,
|
|
437
|
+
).get() as Record<string, unknown> | undefined;
|
|
438
|
+
assert.ok(row, 'milestone-validation row should survive when no structural changes occurred');
|
|
439
|
+
} finally {
|
|
440
|
+
cleanup(base);
|
|
441
|
+
}
|
|
442
|
+
});
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
// GSD State Machine Regression Tests — Event Replay & Reconciliation (#3161)
|
|
2
|
+
|
|
3
|
+
import { describe, test, afterEach } from "node:test";
|
|
4
|
+
import assert from "node:assert/strict";
|
|
5
|
+
import { createHash } from "node:crypto";
|
|
6
|
+
import * as fs from "node:fs";
|
|
7
|
+
import * as path from "node:path";
|
|
8
|
+
import * as os from "node:os";
|
|
9
|
+
import { findForkPoint, readEvents, appendEvent } from "../workflow-events.ts";
|
|
10
|
+
import type { WorkflowEvent } from "../workflow-events.ts";
|
|
11
|
+
import { extractEntityKey, detectConflicts } from "../workflow-reconcile.ts";
|
|
12
|
+
|
|
13
|
+
// ─── Helper: build a full WorkflowEvent from cmd + params ────────────────────
|
|
14
|
+
|
|
15
|
+
function makeEvent(cmd: string, params: Record<string, unknown>, ts?: string): WorkflowEvent {
|
|
16
|
+
const hash = createHash("sha256")
|
|
17
|
+
.update(JSON.stringify({ cmd, params }))
|
|
18
|
+
.digest("hex")
|
|
19
|
+
.slice(0, 16);
|
|
20
|
+
return { cmd, params, ts: ts ?? new Date().toISOString(), hash, actor: "agent", session_id: "test-session" };
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// ─── Temp dir management ─────────────────────────────────────────────────────
|
|
24
|
+
|
|
25
|
+
const tempDirs: string[] = [];
|
|
26
|
+
|
|
27
|
+
function tempDir(): string {
|
|
28
|
+
const dir = fs.mkdtempSync(path.join(os.tmpdir(), "gsd-recon-test-"));
|
|
29
|
+
tempDirs.push(dir);
|
|
30
|
+
return dir;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
afterEach(() => {
|
|
34
|
+
for (const dir of tempDirs.splice(0)) {
|
|
35
|
+
try { fs.rmSync(dir, { recursive: true, force: true }); } catch { /* best effort */ }
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
// ─── Tests ────────────────────────────────────────────────────────────────────
|
|
40
|
+
|
|
41
|
+
describe("reconciliation-edge-cases", () => {
|
|
42
|
+
|
|
43
|
+
// findForkPoint
|
|
44
|
+
test("findForkPoint returns -1 for completely diverged logs", () => {
|
|
45
|
+
const eA = makeEvent("complete_task", { milestoneId: "M001", sliceId: "S01", taskId: "T01" });
|
|
46
|
+
const eB = makeEvent("complete_task", { milestoneId: "M001", sliceId: "S01", taskId: "T02" });
|
|
47
|
+
|
|
48
|
+
const logA: WorkflowEvent[] = [eA];
|
|
49
|
+
const logB: WorkflowEvent[] = [eB];
|
|
50
|
+
|
|
51
|
+
assert.equal(findForkPoint(logA, logB), -1, "completely diverged logs should return -1");
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
test("findForkPoint returns last index when one log is prefix of another", () => {
|
|
55
|
+
const e1 = makeEvent("start_task", { milestoneId: "M001", sliceId: "S01", taskId: "T01" });
|
|
56
|
+
const e2 = makeEvent("complete_task", { milestoneId: "M001", sliceId: "S01", taskId: "T01" });
|
|
57
|
+
const e3 = makeEvent("complete_slice", { milestoneId: "M001", sliceId: "S01" });
|
|
58
|
+
|
|
59
|
+
const logA: WorkflowEvent[] = [e1, e2];
|
|
60
|
+
const logB: WorkflowEvent[] = [e1, e2, e3];
|
|
61
|
+
|
|
62
|
+
assert.equal(findForkPoint(logA, logB), 1, "prefix log should fork at last shared index");
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
test("findForkPoint returns -1 for empty logs", () => {
|
|
66
|
+
assert.equal(findForkPoint([], []), -1, "two empty logs should return -1");
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
// extractEntityKey
|
|
70
|
+
test("extractEntityKey returns null for malformed events (missing taskId)", () => {
|
|
71
|
+
const event = makeEvent("complete_task", {});
|
|
72
|
+
// params has no taskId — should return null rather than return a bad key
|
|
73
|
+
assert.equal(extractEntityKey(event), null, "missing taskId should yield null entity key");
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
test("extractEntityKey returns null for unknown commands", () => {
|
|
77
|
+
const event = makeEvent("future_cmd", { foo: "bar" });
|
|
78
|
+
assert.equal(extractEntityKey(event), null, "unknown command should yield null entity key");
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
test("plan_slice and complete_slice use different entity types", () => {
|
|
82
|
+
const planEvent = makeEvent("plan_slice", { sliceId: "S01" });
|
|
83
|
+
const completeEvent = makeEvent("complete_slice", { sliceId: "S01" });
|
|
84
|
+
|
|
85
|
+
const planKey = extractEntityKey(planEvent);
|
|
86
|
+
const completeKey = extractEntityKey(completeEvent);
|
|
87
|
+
|
|
88
|
+
assert.ok(planKey !== null, "plan_slice should produce an entity key");
|
|
89
|
+
assert.ok(completeKey !== null, "complete_slice should produce an entity key");
|
|
90
|
+
assert.equal(planKey!.type, "slice_plan", "plan_slice entity type should be 'slice_plan'");
|
|
91
|
+
assert.equal(completeKey!.type, "slice", "complete_slice entity type should be 'slice'");
|
|
92
|
+
assert.notEqual(
|
|
93
|
+
planKey!.type,
|
|
94
|
+
completeKey!.type,
|
|
95
|
+
"plan_slice and complete_slice must map to different entity types",
|
|
96
|
+
);
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
// detectConflicts
|
|
100
|
+
test("detectConflicts finds no conflicts when entities do not overlap", () => {
|
|
101
|
+
const mainDiverged: WorkflowEvent[] = [
|
|
102
|
+
makeEvent("complete_task", { milestoneId: "M001", sliceId: "S01", taskId: "T01" }),
|
|
103
|
+
];
|
|
104
|
+
const wtDiverged: WorkflowEvent[] = [
|
|
105
|
+
makeEvent("complete_task", { milestoneId: "M001", sliceId: "S01", taskId: "T02" }),
|
|
106
|
+
];
|
|
107
|
+
|
|
108
|
+
const conflicts = detectConflicts(mainDiverged, wtDiverged);
|
|
109
|
+
assert.equal(conflicts.length, 0, "non-overlapping task edits should produce no conflicts");
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
test("detectConflicts flags conflict when both sides touch the same task", () => {
|
|
113
|
+
const mainDiverged: WorkflowEvent[] = [
|
|
114
|
+
makeEvent("start_task", { milestoneId: "M001", sliceId: "S01", taskId: "T01" }),
|
|
115
|
+
];
|
|
116
|
+
const wtDiverged: WorkflowEvent[] = [
|
|
117
|
+
makeEvent("complete_task", { milestoneId: "M001", sliceId: "S01", taskId: "T01" }),
|
|
118
|
+
];
|
|
119
|
+
|
|
120
|
+
const conflicts = detectConflicts(mainDiverged, wtDiverged);
|
|
121
|
+
assert.equal(conflicts.length, 1, "same task touched by both sides should produce exactly one conflict");
|
|
122
|
+
|
|
123
|
+
const conflict = conflicts[0]!;
|
|
124
|
+
assert.equal(conflict.entityType, "task", "conflict entityType should be 'task'");
|
|
125
|
+
assert.equal(conflict.entityId, "T01", "conflict entityId should be 'T01'");
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
test("detectConflicts ignores events with null entity keys", () => {
|
|
129
|
+
// Events with unknown commands produce null keys and must not cause false conflicts.
|
|
130
|
+
const mainDiverged: WorkflowEvent[] = [
|
|
131
|
+
makeEvent("unknown_future_cmd", { milestoneId: "M001" }),
|
|
132
|
+
];
|
|
133
|
+
const wtDiverged: WorkflowEvent[] = [
|
|
134
|
+
makeEvent("another_unknown_cmd", { milestoneId: "M001" }),
|
|
135
|
+
];
|
|
136
|
+
|
|
137
|
+
const conflicts = detectConflicts(mainDiverged, wtDiverged);
|
|
138
|
+
assert.equal(conflicts.length, 0, "unknown commands with null entity keys should not produce conflicts");
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
// appendEvent — filesystem creation
|
|
142
|
+
test("appendEvent creates event log if directory does not exist", () => {
|
|
143
|
+
const base = tempDir();
|
|
144
|
+
// Remove the .gsd directory if it somehow exists — appendEvent should create it.
|
|
145
|
+
const gsdDir = path.join(base, ".gsd");
|
|
146
|
+
if (fs.existsSync(gsdDir)) fs.rmSync(gsdDir, { recursive: true, force: true });
|
|
147
|
+
|
|
148
|
+
appendEvent(base, {
|
|
149
|
+
cmd: "complete_task",
|
|
150
|
+
params: { milestoneId: "M001", sliceId: "S01", taskId: "T01" },
|
|
151
|
+
ts: new Date().toISOString(),
|
|
152
|
+
actor: "agent",
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
const logPath = path.join(base, ".gsd", "event-log.jsonl");
|
|
156
|
+
assert.ok(fs.existsSync(logPath), "event-log.jsonl should be created by appendEvent");
|
|
157
|
+
|
|
158
|
+
const events = readEvents(logPath);
|
|
159
|
+
assert.equal(events.length, 1, "event log should contain exactly one event");
|
|
160
|
+
assert.equal(events[0]!.cmd, "complete_task", "persisted event should have the correct cmd");
|
|
161
|
+
});
|
|
162
|
+
});
|
|
@@ -296,3 +296,100 @@ Do the second thing.
|
|
|
296
296
|
assert.equal(slices[0]?.id, "S01");
|
|
297
297
|
assert.equal(slices[1]?.id, "S02");
|
|
298
298
|
});
|
|
299
|
+
|
|
300
|
+
// ── Regression tests for #2567 ─────────────────────────────────────────────
|
|
301
|
+
// Prose H3 parser fails on common LLM-generated patterns: numbered prefixes,
|
|
302
|
+
// parenthetical numbering, bracketed IDs, and indented headings.
|
|
303
|
+
|
|
304
|
+
test("parseRoadmapSlices: numbered H3 headers under ## Slices (#2567)", () => {
|
|
305
|
+
const numberedContent = `# M002: My Milestone
|
|
306
|
+
|
|
307
|
+
**Vision:** Ship the product.
|
|
308
|
+
|
|
309
|
+
## Slices
|
|
310
|
+
|
|
311
|
+
### 1. S01: Setup Environment
|
|
312
|
+
Set up the dev environment and tooling.
|
|
313
|
+
|
|
314
|
+
### 2. S02: Build Core
|
|
315
|
+
Implement the core logic.
|
|
316
|
+
**Depends on:** S01
|
|
317
|
+
|
|
318
|
+
### 3. S03: Polish UI
|
|
319
|
+
Final polish and theming.
|
|
320
|
+
**Depends on:** S01, S02
|
|
321
|
+
`;
|
|
322
|
+
const slices = parseRoadmapSlices(numberedContent);
|
|
323
|
+
assert.equal(slices.length, 3, "should parse 3 slices from numbered H3 headers");
|
|
324
|
+
assert.equal(slices[0]?.id, "S01");
|
|
325
|
+
assert.equal(slices[0]?.title, "Setup Environment");
|
|
326
|
+
assert.equal(slices[1]?.id, "S02");
|
|
327
|
+
assert.deepEqual(slices[1]?.depends, ["S01"]);
|
|
328
|
+
assert.equal(slices[2]?.id, "S03");
|
|
329
|
+
assert.deepEqual(slices[2]?.depends, ["S01", "S02"]);
|
|
330
|
+
});
|
|
331
|
+
|
|
332
|
+
test("parseRoadmapSlices: parenthetical-numbered H3 headers (#2567)", () => {
|
|
333
|
+
const parenContent = `# M002: Milestone
|
|
334
|
+
|
|
335
|
+
**Vision:** Ship.
|
|
336
|
+
|
|
337
|
+
## Slices
|
|
338
|
+
|
|
339
|
+
### (1) S01: Setup
|
|
340
|
+
Setup work.
|
|
341
|
+
|
|
342
|
+
### (2) S02: Build
|
|
343
|
+
Build work.
|
|
344
|
+
**Depends on:** S01
|
|
345
|
+
`;
|
|
346
|
+
const slices = parseRoadmapSlices(parenContent);
|
|
347
|
+
assert.equal(slices.length, 2, "should parse slices with parenthetical numbering");
|
|
348
|
+
assert.equal(slices[0]?.id, "S01");
|
|
349
|
+
assert.equal(slices[0]?.title, "Setup");
|
|
350
|
+
assert.equal(slices[1]?.id, "S02");
|
|
351
|
+
assert.deepEqual(slices[1]?.depends, ["S01"]);
|
|
352
|
+
});
|
|
353
|
+
|
|
354
|
+
test("parseRoadmapSlices: bracketed slice IDs in H3 headers (#2567)", () => {
|
|
355
|
+
const bracketContent = `# M002: Milestone
|
|
356
|
+
|
|
357
|
+
**Vision:** Ship.
|
|
358
|
+
|
|
359
|
+
## Slices
|
|
360
|
+
|
|
361
|
+
### [S01] Setup Environment
|
|
362
|
+
Setup work.
|
|
363
|
+
|
|
364
|
+
### [S02] Build Core
|
|
365
|
+
Build work.
|
|
366
|
+
**Depends on:** S01
|
|
367
|
+
`;
|
|
368
|
+
const slices = parseRoadmapSlices(bracketContent);
|
|
369
|
+
assert.equal(slices.length, 2, "should parse slices with bracketed IDs");
|
|
370
|
+
assert.equal(slices[0]?.id, "S01");
|
|
371
|
+
assert.equal(slices[0]?.title, "Setup Environment");
|
|
372
|
+
assert.equal(slices[1]?.id, "S02");
|
|
373
|
+
assert.deepEqual(slices[1]?.depends, ["S01"]);
|
|
374
|
+
});
|
|
375
|
+
|
|
376
|
+
test("parseRoadmapSlices: indented H3 headers under ## Slices (#2567)", () => {
|
|
377
|
+
const indentedContent = `# M002: Milestone
|
|
378
|
+
|
|
379
|
+
**Vision:** Ship.
|
|
380
|
+
|
|
381
|
+
## Slices
|
|
382
|
+
|
|
383
|
+
### S01: Setup
|
|
384
|
+
Setup work.
|
|
385
|
+
|
|
386
|
+
### S02: Build
|
|
387
|
+
Build work.
|
|
388
|
+
`;
|
|
389
|
+
const slices = parseRoadmapSlices(indentedContent);
|
|
390
|
+
assert.equal(slices.length, 2, "should parse slices from indented H3 headers");
|
|
391
|
+
assert.equal(slices[0]?.id, "S01");
|
|
392
|
+
assert.equal(slices[0]?.title, "Setup");
|
|
393
|
+
assert.equal(slices[1]?.id, "S02");
|
|
394
|
+
assert.equal(slices[1]?.title, "Build");
|
|
395
|
+
});
|