gsd-pi 2.10.12 → 2.12.0
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/dist/bundled-extension-paths.d.ts +2 -0
- package/dist/bundled-extension-paths.js +10 -0
- package/dist/loader.js +45 -28
- package/dist/onboarding.js +100 -0
- package/dist/resource-loader.js +12 -3
- package/dist/resources/GSD-WORKFLOW.md +661 -0
- package/dist/resources/agents/researcher.md +29 -0
- package/dist/resources/agents/scout.md +56 -0
- package/dist/resources/agents/worker.md +31 -0
- package/dist/resources/extensions/ask-user-questions.ts +289 -0
- package/dist/resources/extensions/async-jobs/async-bash-tool.ts +211 -0
- package/dist/resources/extensions/async-jobs/await-tool.ts +101 -0
- package/dist/resources/extensions/async-jobs/cancel-job-tool.ts +34 -0
- package/dist/resources/extensions/async-jobs/index.ts +133 -0
- package/dist/resources/extensions/async-jobs/job-manager.ts +211 -0
- package/dist/resources/extensions/bg-shell/index.ts +3179 -0
- package/dist/resources/extensions/browser-tools/BROWSER-TOOLS-V2-PROPOSAL.md +1277 -0
- package/dist/resources/extensions/browser-tools/capture.ts +165 -0
- package/dist/resources/extensions/browser-tools/core.d.ts +205 -0
- package/dist/resources/extensions/browser-tools/core.js +1057 -0
- package/dist/resources/extensions/browser-tools/evaluate-helpers.ts +184 -0
- package/dist/resources/extensions/browser-tools/index.ts +51 -0
- package/dist/resources/extensions/browser-tools/lifecycle.ts +270 -0
- package/dist/resources/extensions/browser-tools/package.json +24 -0
- package/dist/resources/extensions/browser-tools/refs.ts +264 -0
- package/dist/resources/extensions/browser-tools/settle.ts +197 -0
- package/dist/resources/extensions/browser-tools/state.ts +408 -0
- package/dist/resources/extensions/browser-tools/tests/browser-tools-integration.test.mjs +652 -0
- package/dist/resources/extensions/browser-tools/tests/browser-tools-unit.test.cjs +614 -0
- package/dist/resources/extensions/browser-tools/tools/assertions.ts +342 -0
- package/dist/resources/extensions/browser-tools/tools/forms.ts +801 -0
- package/dist/resources/extensions/browser-tools/tools/inspection.ts +492 -0
- package/dist/resources/extensions/browser-tools/tools/intent.ts +614 -0
- package/dist/resources/extensions/browser-tools/tools/interaction.ts +865 -0
- package/dist/resources/extensions/browser-tools/tools/navigation.ts +232 -0
- package/dist/resources/extensions/browser-tools/tools/pages.ts +303 -0
- package/dist/resources/extensions/browser-tools/tools/refs.ts +541 -0
- package/dist/resources/extensions/browser-tools/tools/screenshot.ts +83 -0
- package/dist/resources/extensions/browser-tools/tools/session.ts +400 -0
- package/dist/resources/extensions/browser-tools/tools/wait.ts +247 -0
- package/dist/resources/extensions/browser-tools/utils.ts +660 -0
- package/dist/resources/extensions/context7/index.ts +428 -0
- package/dist/resources/extensions/context7/package.json +11 -0
- package/dist/resources/extensions/get-secrets-from-user.ts +625 -0
- package/dist/resources/extensions/google-search/index.ts +336 -0
- package/dist/resources/extensions/google-search/package.json +9 -0
- package/dist/resources/extensions/gsd/activity-log.ts +116 -0
- package/dist/resources/extensions/gsd/auto.ts +3732 -0
- package/dist/resources/extensions/gsd/commands.ts +544 -0
- package/dist/resources/extensions/gsd/crash-recovery.ts +105 -0
- package/dist/resources/extensions/gsd/dashboard-overlay.ts +564 -0
- package/dist/resources/extensions/gsd/dispatch-guard.ts +78 -0
- package/dist/resources/extensions/gsd/docs/preferences-reference.md +278 -0
- package/dist/resources/extensions/gsd/doctor.ts +766 -0
- package/dist/resources/extensions/gsd/exit-command.ts +18 -0
- package/dist/resources/extensions/gsd/files.ts +857 -0
- package/dist/resources/extensions/gsd/git-service.ts +904 -0
- package/dist/resources/extensions/gsd/gitignore.ts +200 -0
- package/dist/resources/extensions/gsd/guided-flow.ts +1054 -0
- package/dist/resources/extensions/gsd/index.ts +735 -0
- package/dist/resources/extensions/gsd/metrics.ts +374 -0
- package/dist/resources/extensions/gsd/migrate/command.ts +218 -0
- package/dist/resources/extensions/gsd/migrate/index.ts +42 -0
- package/dist/resources/extensions/gsd/migrate/parser.ts +323 -0
- package/dist/resources/extensions/gsd/migrate/parsers.ts +624 -0
- package/dist/resources/extensions/gsd/migrate/preview.ts +48 -0
- package/dist/resources/extensions/gsd/migrate/transformer.ts +346 -0
- package/dist/resources/extensions/gsd/migrate/types.ts +370 -0
- package/dist/resources/extensions/gsd/migrate/validator.ts +55 -0
- package/dist/resources/extensions/gsd/migrate/writer.ts +539 -0
- package/dist/resources/extensions/gsd/native-git-bridge.ts +181 -0
- package/dist/resources/extensions/gsd/native-parser-bridge.ts +135 -0
- package/dist/resources/extensions/gsd/observability-validator.ts +408 -0
- package/dist/resources/extensions/gsd/package.json +11 -0
- package/dist/resources/extensions/gsd/paths.ts +339 -0
- package/dist/resources/extensions/gsd/post-unit-hooks.ts +449 -0
- package/dist/resources/extensions/gsd/preferences.ts +988 -0
- package/dist/resources/extensions/gsd/prompt-loader.ts +92 -0
- package/dist/resources/extensions/gsd/prompts/complete-milestone.md +25 -0
- package/dist/resources/extensions/gsd/prompts/complete-slice.md +27 -0
- package/dist/resources/extensions/gsd/prompts/discuss.md +237 -0
- package/dist/resources/extensions/gsd/prompts/doctor-heal.md +29 -0
- package/dist/resources/extensions/gsd/prompts/execute-task.md +63 -0
- package/dist/resources/extensions/gsd/prompts/guided-complete-slice.md +3 -0
- package/dist/resources/extensions/gsd/prompts/guided-discuss-milestone.md +5 -0
- package/dist/resources/extensions/gsd/prompts/guided-discuss-slice.md +61 -0
- package/dist/resources/extensions/gsd/prompts/guided-execute-task.md +3 -0
- package/dist/resources/extensions/gsd/prompts/guided-plan-milestone.md +29 -0
- package/dist/resources/extensions/gsd/prompts/guided-plan-slice.md +3 -0
- package/dist/resources/extensions/gsd/prompts/guided-research-slice.md +13 -0
- package/dist/resources/extensions/gsd/prompts/guided-resume-task.md +1 -0
- package/dist/resources/extensions/gsd/prompts/plan-milestone.md +78 -0
- package/dist/resources/extensions/gsd/prompts/plan-slice.md +55 -0
- package/dist/resources/extensions/gsd/prompts/queue.md +100 -0
- package/dist/resources/extensions/gsd/prompts/reassess-roadmap.md +48 -0
- package/dist/resources/extensions/gsd/prompts/replan-slice.md +39 -0
- package/dist/resources/extensions/gsd/prompts/research-milestone.md +37 -0
- package/dist/resources/extensions/gsd/prompts/research-slice.md +28 -0
- package/dist/resources/extensions/gsd/prompts/review-migration.md +66 -0
- package/dist/resources/extensions/gsd/prompts/run-uat.md +109 -0
- package/dist/resources/extensions/gsd/prompts/system.md +190 -0
- package/dist/resources/extensions/gsd/prompts/worktree-merge.md +123 -0
- package/dist/resources/extensions/gsd/roadmap-slices.ts +50 -0
- package/dist/resources/extensions/gsd/session-forensics.ts +500 -0
- package/dist/resources/extensions/gsd/skill-discovery.ts +137 -0
- package/dist/resources/extensions/gsd/state.ts +569 -0
- package/dist/resources/extensions/gsd/templates/context.md +76 -0
- package/dist/resources/extensions/gsd/templates/decisions.md +8 -0
- package/dist/resources/extensions/gsd/templates/milestone-summary.md +73 -0
- package/dist/resources/extensions/gsd/templates/plan.md +131 -0
- package/dist/resources/extensions/gsd/templates/preferences.md +23 -0
- package/dist/resources/extensions/gsd/templates/project.md +31 -0
- package/dist/resources/extensions/gsd/templates/reassessment.md +28 -0
- package/dist/resources/extensions/gsd/templates/requirements.md +81 -0
- package/dist/resources/extensions/gsd/templates/research.md +46 -0
- package/dist/resources/extensions/gsd/templates/roadmap.md +118 -0
- package/dist/resources/extensions/gsd/templates/secrets-manifest.md +22 -0
- package/dist/resources/extensions/gsd/templates/slice-context.md +58 -0
- package/dist/resources/extensions/gsd/templates/slice-summary.md +99 -0
- package/dist/resources/extensions/gsd/templates/state.md +19 -0
- package/dist/resources/extensions/gsd/templates/task-plan.md +52 -0
- package/dist/resources/extensions/gsd/templates/task-summary.md +57 -0
- package/dist/resources/extensions/gsd/templates/uat.md +54 -0
- package/dist/resources/extensions/gsd/tests/activity-log-prune.test.ts +297 -0
- package/dist/resources/extensions/gsd/tests/activity-log-save.test.ts +127 -0
- package/dist/resources/extensions/gsd/tests/auto-draft-pause.test.ts +109 -0
- package/dist/resources/extensions/gsd/tests/auto-preflight.test.ts +45 -0
- package/dist/resources/extensions/gsd/tests/auto-secrets-gate.test.ts +196 -0
- package/dist/resources/extensions/gsd/tests/auto-supervisor.test.mjs +53 -0
- package/dist/resources/extensions/gsd/tests/collect-from-manifest.test.ts +469 -0
- package/dist/resources/extensions/gsd/tests/complete-milestone.test.ts +200 -0
- package/dist/resources/extensions/gsd/tests/cost-projection.test.ts +134 -0
- package/dist/resources/extensions/gsd/tests/derive-state-deps.test.ts +312 -0
- package/dist/resources/extensions/gsd/tests/derive-state-draft.test.ts +299 -0
- package/dist/resources/extensions/gsd/tests/derive-state.test.ts +660 -0
- package/dist/resources/extensions/gsd/tests/discuss-prompt.test.ts +27 -0
- package/dist/resources/extensions/gsd/tests/dispatch-guard.test.ts +91 -0
- package/dist/resources/extensions/gsd/tests/doctor-fixlevel.test.ts +170 -0
- package/dist/resources/extensions/gsd/tests/doctor.test.ts +594 -0
- package/dist/resources/extensions/gsd/tests/draft-promotion.test.ts +169 -0
- package/dist/resources/extensions/gsd/tests/exit-command.test.ts +50 -0
- package/dist/resources/extensions/gsd/tests/git-service.test.ts +1788 -0
- package/dist/resources/extensions/gsd/tests/idle-recovery.test.ts +577 -0
- package/dist/resources/extensions/gsd/tests/integration-mixed-milestones.test.ts +580 -0
- package/dist/resources/extensions/gsd/tests/manifest-status.test.ts +283 -0
- package/dist/resources/extensions/gsd/tests/metrics-io.test.ts +176 -0
- package/dist/resources/extensions/gsd/tests/metrics.test.ts +188 -0
- package/dist/resources/extensions/gsd/tests/migrate-command.test.ts +369 -0
- package/dist/resources/extensions/gsd/tests/migrate-parser.test.ts +757 -0
- package/dist/resources/extensions/gsd/tests/migrate-transformer.test.ts +635 -0
- package/dist/resources/extensions/gsd/tests/migrate-validator-parsers.test.ts +414 -0
- package/dist/resources/extensions/gsd/tests/migrate-writer-integration.test.ts +297 -0
- package/dist/resources/extensions/gsd/tests/migrate-writer.test.ts +398 -0
- package/dist/resources/extensions/gsd/tests/must-have-parser.test.ts +291 -0
- package/dist/resources/extensions/gsd/tests/network-error-fallback.test.ts +54 -0
- package/dist/resources/extensions/gsd/tests/next-milestone-id.test.ts +66 -0
- package/dist/resources/extensions/gsd/tests/orphaned-branch.test.ts +353 -0
- package/dist/resources/extensions/gsd/tests/parsers.test.ts +1664 -0
- package/dist/resources/extensions/gsd/tests/plan-milestone.test.ts +133 -0
- package/dist/resources/extensions/gsd/tests/plan-quality-validator.test.ts +363 -0
- package/dist/resources/extensions/gsd/tests/post-unit-hooks.test.ts +297 -0
- package/dist/resources/extensions/gsd/tests/preferences-hooks.test.ts +226 -0
- package/dist/resources/extensions/gsd/tests/queue-draft-detection.test.ts +126 -0
- package/dist/resources/extensions/gsd/tests/reassess-prompt.test.ts +142 -0
- package/dist/resources/extensions/gsd/tests/regex-hardening.test.ts +281 -0
- package/dist/resources/extensions/gsd/tests/remote-questions.test.ts +155 -0
- package/dist/resources/extensions/gsd/tests/remote-status.test.ts +99 -0
- package/dist/resources/extensions/gsd/tests/replan-slice.test.ts +493 -0
- package/dist/resources/extensions/gsd/tests/requirements.test.ts +106 -0
- package/dist/resources/extensions/gsd/tests/resolve-ts-hooks.mjs +35 -0
- package/dist/resources/extensions/gsd/tests/resolve-ts.mjs +11 -0
- package/dist/resources/extensions/gsd/tests/roadmap-slices.test.ts +41 -0
- package/dist/resources/extensions/gsd/tests/run-uat.test.ts +316 -0
- package/dist/resources/extensions/gsd/tests/secure-env-collect.test.ts +185 -0
- package/dist/resources/extensions/gsd/tests/smart-entry-draft.test.ts +123 -0
- package/dist/resources/extensions/gsd/tests/test-helpers.ts +61 -0
- package/dist/resources/extensions/gsd/tests/unique-milestone-ids.test.ts +219 -0
- package/dist/resources/extensions/gsd/tests/unit-runtime.test.ts +234 -0
- package/dist/resources/extensions/gsd/tests/workspace-index.test.ts +75 -0
- package/dist/resources/extensions/gsd/tests/worktree-integration.test.ts +234 -0
- package/dist/resources/extensions/gsd/tests/worktree-manager.test.ts +141 -0
- package/dist/resources/extensions/gsd/tests/worktree.test.ts +597 -0
- package/dist/resources/extensions/gsd/tests/write-gate.test.ts +122 -0
- package/dist/resources/extensions/gsd/types.ts +296 -0
- package/dist/resources/extensions/gsd/unit-runtime.ts +184 -0
- package/dist/resources/extensions/gsd/workspace-index.ts +189 -0
- package/dist/resources/extensions/gsd/worktree-command.ts +845 -0
- package/dist/resources/extensions/gsd/worktree-manager.ts +459 -0
- package/dist/resources/extensions/gsd/{worktree.js → worktree.ts} +92 -61
- package/dist/resources/extensions/mac-tools/index.ts +852 -0
- package/dist/resources/extensions/mac-tools/swift-cli/Package.swift +22 -0
- package/dist/resources/extensions/mac-tools/swift-cli/Sources/main.swift +1318 -0
- package/dist/resources/extensions/mcporter/index.ts +429 -0
- package/dist/resources/extensions/remote-questions/config.ts +81 -0
- package/dist/resources/extensions/remote-questions/discord-adapter.ts +128 -0
- package/dist/resources/extensions/remote-questions/format.ts +163 -0
- package/dist/resources/extensions/remote-questions/manager.ts +192 -0
- package/dist/resources/extensions/remote-questions/remote-command.ts +361 -0
- package/dist/resources/extensions/remote-questions/slack-adapter.ts +92 -0
- package/dist/resources/extensions/remote-questions/status.ts +31 -0
- package/dist/resources/extensions/remote-questions/store.ts +77 -0
- package/dist/resources/extensions/remote-questions/types.ts +75 -0
- package/dist/resources/extensions/search-the-web/cache.ts +78 -0
- package/dist/resources/extensions/search-the-web/command-search-provider.ts +99 -0
- package/dist/resources/extensions/search-the-web/format.ts +258 -0
- package/dist/resources/extensions/search-the-web/http.ts +238 -0
- package/dist/resources/extensions/search-the-web/index.ts +65 -0
- package/dist/resources/extensions/search-the-web/native-search.ts +165 -0
- package/dist/resources/extensions/search-the-web/provider.ts +136 -0
- package/dist/resources/extensions/search-the-web/tavily.ts +116 -0
- package/dist/resources/extensions/search-the-web/tool-fetch-page.ts +581 -0
- package/dist/resources/extensions/search-the-web/tool-llm-context.ts +620 -0
- package/dist/resources/extensions/search-the-web/tool-search.ts +635 -0
- package/dist/resources/extensions/search-the-web/url-utils.ts +91 -0
- package/dist/resources/extensions/shared/bundled-extension-paths.ts +11 -0
- package/dist/resources/extensions/shared/confirm-ui.ts +126 -0
- package/dist/resources/extensions/shared/interview-ui.ts +613 -0
- package/dist/resources/extensions/shared/next-action-ui.ts +197 -0
- package/dist/resources/extensions/shared/progress-widget.ts +282 -0
- package/dist/resources/extensions/shared/terminal.ts +23 -0
- package/dist/resources/extensions/shared/thinking-widget.ts +107 -0
- package/dist/resources/extensions/shared/ui.ts +400 -0
- package/dist/resources/extensions/shared/wizard-ui.ts +551 -0
- package/dist/resources/extensions/slash-commands/audit.ts +88 -0
- package/dist/resources/extensions/slash-commands/clear.ts +10 -0
- package/dist/resources/extensions/slash-commands/create-extension.ts +297 -0
- package/dist/resources/extensions/slash-commands/create-slash-command.ts +234 -0
- package/dist/resources/extensions/slash-commands/index.ts +12 -0
- package/dist/resources/extensions/subagent/agents.ts +126 -0
- package/dist/resources/extensions/subagent/index.ts +1072 -0
- package/dist/resources/extensions/subagent/isolation.ts +498 -0
- package/dist/resources/extensions/ttsr/index.ts +163 -0
- package/dist/resources/extensions/ttsr/rule-loader.ts +121 -0
- package/dist/resources/extensions/ttsr/ttsr-interrupt.md +6 -0
- package/dist/resources/extensions/ttsr/ttsr-manager.ts +430 -0
- package/dist/resources/extensions/universal-config/discovery.ts +78 -0
- package/dist/resources/extensions/universal-config/format.ts +160 -0
- package/dist/resources/extensions/universal-config/index.ts +118 -0
- package/dist/resources/extensions/universal-config/package.json +11 -0
- package/dist/resources/extensions/universal-config/scanners.ts +579 -0
- package/dist/resources/extensions/universal-config/tests/discovery.test.ts +111 -0
- package/dist/resources/extensions/universal-config/tests/format.test.ts +111 -0
- package/dist/resources/extensions/universal-config/tests/scanners.test.ts +438 -0
- package/dist/resources/extensions/universal-config/tools.ts +60 -0
- package/dist/resources/extensions/universal-config/types.ts +116 -0
- package/dist/resources/extensions/voice/index.ts +271 -0
- package/dist/resources/extensions/voice/speech-recognizer.py +504 -0
- package/dist/resources/extensions/voice/speech-recognizer.swift +154 -0
- package/dist/resources/skills/debug-like-expert/SKILL.md +231 -0
- package/dist/resources/skills/debug-like-expert/references/debugging-mindset.md +253 -0
- package/dist/resources/skills/debug-like-expert/references/hypothesis-testing.md +373 -0
- package/dist/resources/skills/debug-like-expert/references/investigation-techniques.md +337 -0
- package/dist/resources/skills/debug-like-expert/references/verification-patterns.md +425 -0
- package/dist/resources/skills/debug-like-expert/references/when-to-research.md +361 -0
- package/dist/resources/skills/frontend-design/SKILL.md +45 -0
- package/dist/resources/skills/github-workflows/SKILL.md +92 -0
- package/dist/resources/skills/github-workflows/references/gh/SKILL.md +255 -0
- package/dist/resources/skills/github-workflows/references/gh/references/issue-stories.md +204 -0
- package/dist/resources/skills/github-workflows/references/gh/references/labels.md +170 -0
- package/dist/resources/skills/github-workflows/references/gh/references/milestones.md +158 -0
- package/dist/resources/skills/github-workflows/references/gh/references/projects-v2.md +177 -0
- package/dist/resources/skills/github-workflows/references/gh/scripts/experiment_cleanup.py +191 -0
- package/dist/resources/skills/github-workflows/references/gh/scripts/github_project_setup.py +799 -0
- package/dist/resources/skills/github-workflows/references/gh/tests/__init__.py +0 -0
- package/dist/resources/skills/github-workflows/references/gh/tests/test_github_project_setup.py +608 -0
- package/dist/resources/skills/swiftui/SKILL.md +208 -0
- package/dist/resources/skills/swiftui/references/animations.md +921 -0
- package/dist/resources/skills/swiftui/references/architecture.md +1561 -0
- package/dist/resources/skills/swiftui/references/layout-system.md +1186 -0
- package/dist/resources/skills/swiftui/references/navigation.md +1492 -0
- package/dist/resources/skills/swiftui/references/networking-async.md +214 -0
- package/dist/resources/skills/swiftui/references/performance.md +1706 -0
- package/dist/resources/skills/swiftui/references/platform-integration.md +204 -0
- package/dist/resources/skills/swiftui/references/state-management.md +1443 -0
- package/dist/resources/skills/swiftui/references/swiftdata.md +297 -0
- package/dist/resources/skills/swiftui/references/testing-debugging.md +247 -0
- package/dist/resources/skills/swiftui/references/uikit-appkit-interop.md +218 -0
- package/dist/resources/skills/swiftui/workflows/add-feature.md +191 -0
- package/dist/resources/skills/swiftui/workflows/build-new-app.md +311 -0
- package/dist/resources/skills/swiftui/workflows/debug-swiftui.md +192 -0
- package/dist/resources/skills/swiftui/workflows/optimize-performance.md +197 -0
- package/dist/resources/skills/swiftui/workflows/ship-app.md +203 -0
- package/dist/resources/skills/swiftui/workflows/write-tests.md +235 -0
- package/dist/wizard.js +1 -0
- package/package.json +8 -6
- package/packages/native/dist/fd/index.d.ts +1 -0
- package/packages/native/dist/fd/index.js +1 -0
- package/packages/native/dist/grep/index.d.ts +2 -1
- package/packages/native/dist/grep/index.js +1 -0
- package/packages/native/src/__tests__/fd.test.mjs +35 -0
- package/packages/native/src/__tests__/grep.test.mjs +26 -9
- package/packages/native/src/fd/index.ts +1 -0
- package/packages/native/src/grep/index.ts +3 -2
- package/packages/pi-agent-core/dist/agent-loop.d.ts.map +1 -1
- package/packages/pi-agent-core/dist/agent-loop.js +169 -55
- package/packages/pi-agent-core/dist/agent-loop.js.map +1 -1
- package/packages/pi-agent-core/dist/agent.d.ts +13 -1
- package/packages/pi-agent-core/dist/agent.d.ts.map +1 -1
- package/packages/pi-agent-core/dist/agent.js +16 -0
- package/packages/pi-agent-core/dist/agent.js.map +1 -1
- package/packages/pi-agent-core/dist/types.d.ts +91 -1
- package/packages/pi-agent-core/dist/types.d.ts.map +1 -1
- package/packages/pi-agent-core/dist/types.js.map +1 -1
- package/packages/pi-agent-core/src/agent-loop.ts +273 -63
- package/packages/pi-agent-core/src/agent.ts +24 -0
- package/packages/pi-agent-core/src/types.ts +98 -0
- package/packages/pi-ai/dist/env-api-keys.js +2 -0
- package/packages/pi-ai/dist/env-api-keys.js.map +1 -1
- package/packages/pi-ai/dist/models.generated.d.ts +314 -0
- package/packages/pi-ai/dist/models.generated.d.ts.map +1 -1
- package/packages/pi-ai/dist/models.generated.js +236 -0
- package/packages/pi-ai/dist/models.generated.js.map +1 -1
- package/packages/pi-ai/dist/providers/google-gemini-cli.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/google-gemini-cli.js +6 -0
- package/packages/pi-ai/dist/providers/google-gemini-cli.js.map +1 -1
- package/packages/pi-ai/dist/providers/openai-completions.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/openai-completions.js +2 -0
- package/packages/pi-ai/dist/providers/openai-completions.js.map +1 -1
- package/packages/pi-ai/dist/types.d.ts +1 -1
- package/packages/pi-ai/dist/types.d.ts.map +1 -1
- package/packages/pi-ai/dist/types.js.map +1 -1
- package/packages/pi-ai/src/env-api-keys.ts +2 -0
- package/packages/pi-ai/src/models.generated.ts +236 -0
- package/packages/pi-ai/src/providers/google-gemini-cli.ts +8 -0
- package/packages/pi-ai/src/providers/openai-completions.ts +3 -0
- package/packages/pi-ai/src/types.ts +2 -1
- package/packages/pi-coding-agent/dist/cli/args.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/cli/args.js +1 -0
- package/packages/pi-coding-agent/dist/cli/args.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/agent-session.d.ts +26 -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 +137 -22
- package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/auth-storage.d.ts +20 -0
- package/packages/pi-coding-agent/dist/core/auth-storage.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/auth-storage.js +43 -0
- package/packages/pi-coding-agent/dist/core/auth-storage.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/fallback-resolver.d.ts +51 -0
- package/packages/pi-coding-agent/dist/core/fallback-resolver.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/fallback-resolver.js +119 -0
- package/packages/pi-coding-agent/dist/core/fallback-resolver.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/fallback-resolver.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/fallback-resolver.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/fallback-resolver.test.js +183 -0
- package/packages/pi-coding-agent/dist/core/fallback-resolver.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/index.d.ts +1 -0
- package/packages/pi-coding-agent/dist/core/index.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/index.js +1 -0
- package/packages/pi-coding-agent/dist/core/index.js.map +1 -1
- 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/session-manager.d.ts +12 -1
- package/packages/pi-coding-agent/dist/core/session-manager.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/session-manager.js +37 -1
- package/packages/pi-coding-agent/dist/core/session-manager.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/session-manager.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/session-manager.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/session-manager.test.js +61 -0
- package/packages/pi-coding-agent/dist/core/session-manager.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/settings-manager.d.ts +20 -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 +47 -0
- package/packages/pi-coding-agent/dist/core/settings-manager.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/find.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/find.js +1 -0
- package/packages/pi-coding-agent/dist/core/tools/find.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 +6 -15
- package/packages/pi-coding-agent/dist/modes/interactive/components/footer.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/login-dialog.d.ts +18 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/login-dialog.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/login-dialog.js +46 -4
- package/packages/pi-coding-agent/dist/modes/interactive/components/login-dialog.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js +25 -2
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/packages/pi-coding-agent/src/cli/args.ts +1 -0
- package/packages/pi-coding-agent/src/core/agent-session.ts +167 -22
- package/packages/pi-coding-agent/src/core/auth-storage.ts +45 -0
- package/packages/pi-coding-agent/src/core/fallback-resolver.test.ts +229 -0
- package/packages/pi-coding-agent/src/core/fallback-resolver.ts +165 -0
- package/packages/pi-coding-agent/src/core/index.ts +1 -0
- package/packages/pi-coding-agent/src/core/model-resolver.ts +1 -0
- package/packages/pi-coding-agent/src/core/session-manager.test.ts +65 -0
- package/packages/pi-coding-agent/src/core/session-manager.ts +51 -1
- package/packages/pi-coding-agent/src/core/settings-manager.ts +66 -0
- package/packages/pi-coding-agent/src/core/tools/find.ts +1 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/footer.ts +6 -16
- package/packages/pi-coding-agent/src/modes/interactive/components/login-dialog.ts +49 -4
- package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +28 -2
- package/packages/pi-tui/dist/autocomplete.d.ts.map +1 -1
- package/packages/pi-tui/dist/autocomplete.js +3 -4
- package/packages/pi-tui/dist/autocomplete.js.map +1 -1
- package/packages/pi-tui/dist/components/editor.d.ts +7 -0
- package/packages/pi-tui/dist/components/editor.d.ts.map +1 -1
- package/packages/pi-tui/dist/components/editor.js +57 -50
- package/packages/pi-tui/dist/components/editor.js.map +1 -1
- package/packages/pi-tui/src/autocomplete.ts +3 -5
- package/packages/pi-tui/src/components/editor.ts +70 -49
- package/pkg/dist/core/export-html/ansi-to-html.d.ts +22 -0
- package/pkg/dist/core/export-html/ansi-to-html.d.ts.map +1 -0
- package/pkg/dist/core/export-html/ansi-to-html.js +249 -0
- package/pkg/dist/core/export-html/ansi-to-html.js.map +1 -0
- package/pkg/dist/core/export-html/index.d.ts +37 -0
- package/pkg/dist/core/export-html/index.d.ts.map +1 -0
- package/pkg/dist/core/export-html/index.js +223 -0
- package/pkg/dist/core/export-html/index.js.map +1 -0
- package/pkg/dist/core/export-html/template.css +971 -0
- package/pkg/dist/core/export-html/template.html +54 -0
- package/pkg/dist/core/export-html/template.js +1583 -0
- package/pkg/dist/core/export-html/tool-renderer.d.ts +38 -0
- package/pkg/dist/core/export-html/tool-renderer.d.ts.map +1 -0
- package/pkg/dist/core/export-html/tool-renderer.js +70 -0
- package/pkg/dist/core/export-html/tool-renderer.js.map +1 -0
- package/pkg/dist/core/export-html/vendor/highlight.min.js +1213 -0
- package/pkg/dist/core/export-html/vendor/marked.min.js +6 -0
- package/scripts/postinstall.js +30 -17
- package/src/resources/extensions/bg-shell/index.ts +51 -7
- package/src/resources/extensions/gsd/activity-log.ts +61 -14
- package/src/resources/extensions/gsd/auto.ts +288 -19
- package/src/resources/extensions/gsd/commands.ts +9 -3
- package/src/resources/extensions/gsd/dashboard-overlay.ts +55 -12
- package/src/resources/extensions/gsd/docs/preferences-reference.md +25 -0
- package/src/resources/extensions/gsd/doctor.ts +60 -3
- package/src/resources/extensions/gsd/files.ts +45 -1
- package/src/resources/extensions/gsd/git-service.ts +46 -41
- package/src/resources/extensions/gsd/guided-flow.ts +81 -9
- package/src/resources/extensions/gsd/index.ts +62 -1
- package/src/resources/extensions/gsd/native-git-bridge.ts +181 -0
- package/src/resources/extensions/gsd/paths.ts +35 -4
- package/src/resources/extensions/gsd/post-unit-hooks.ts +449 -0
- package/src/resources/extensions/gsd/preferences.ts +232 -1
- package/src/resources/extensions/gsd/prompt-loader.ts +45 -3
- package/src/resources/extensions/gsd/prompts/complete-milestone.md +1 -1
- package/src/resources/extensions/gsd/prompts/complete-slice.md +1 -3
- package/src/resources/extensions/gsd/prompts/discuss.md +10 -8
- package/src/resources/extensions/gsd/prompts/execute-task.md +4 -2
- package/src/resources/extensions/gsd/prompts/guided-complete-slice.md +3 -1
- package/src/resources/extensions/gsd/prompts/guided-discuss-milestone.md +3 -1
- package/src/resources/extensions/gsd/prompts/guided-discuss-slice.md +3 -1
- package/src/resources/extensions/gsd/prompts/guided-execute-task.md +3 -1
- package/src/resources/extensions/gsd/prompts/guided-plan-milestone.md +4 -2
- package/src/resources/extensions/gsd/prompts/guided-plan-slice.md +3 -1
- package/src/resources/extensions/gsd/prompts/guided-research-slice.md +3 -1
- package/src/resources/extensions/gsd/prompts/plan-milestone.md +9 -12
- package/src/resources/extensions/gsd/prompts/plan-slice.md +1 -3
- package/src/resources/extensions/gsd/prompts/queue.md +3 -1
- package/src/resources/extensions/gsd/prompts/research-milestone.md +1 -1
- package/src/resources/extensions/gsd/prompts/research-slice.md +1 -1
- package/src/resources/extensions/gsd/state.ts +130 -18
- package/src/resources/extensions/gsd/templates/context.md +1 -1
- package/src/resources/extensions/gsd/templates/state.md +3 -3
- package/src/resources/extensions/gsd/tests/activity-log-save.test.ts +127 -0
- package/src/resources/extensions/gsd/tests/complete-milestone.test.ts +5 -1
- package/src/resources/extensions/gsd/tests/doctor.test.ts +115 -1
- package/src/resources/extensions/gsd/tests/draft-promotion.test.ts +6 -2
- package/src/resources/extensions/gsd/tests/git-service.test.ts +35 -35
- package/src/resources/extensions/gsd/tests/idle-recovery.test.ts +8 -8
- package/src/resources/extensions/gsd/tests/integration-mixed-milestones.test.ts +4 -1
- package/src/resources/extensions/gsd/tests/network-error-fallback.test.ts +54 -0
- package/src/resources/extensions/gsd/tests/orphaned-branch.test.ts +5 -5
- package/src/resources/extensions/gsd/tests/post-unit-hooks.test.ts +297 -0
- package/src/resources/extensions/gsd/tests/preferences-hooks.test.ts +226 -0
- package/src/resources/extensions/gsd/tests/regex-hardening.test.ts +12 -0
- package/src/resources/extensions/gsd/tests/unit-runtime.test.ts +6 -0
- package/src/resources/extensions/gsd/tests/worktree-integration.test.ts +4 -4
- package/src/resources/extensions/gsd/tests/worktree-manager.test.ts +4 -4
- package/src/resources/extensions/gsd/tests/worktree.test.ts +19 -19
- package/src/resources/extensions/gsd/types.ts +109 -0
- package/src/resources/extensions/gsd/worktree-manager.ts +72 -13
- package/src/resources/extensions/gsd/worktree.ts +5 -4
- package/src/resources/extensions/search-the-web/command-search-provider.ts +8 -4
- package/src/resources/extensions/search-the-web/native-search.ts +32 -23
- package/src/resources/extensions/search-the-web/provider.ts +19 -2
- package/src/resources/extensions/search-the-web/tool-fetch-page.ts +62 -0
- package/src/resources/extensions/search-the-web/tool-llm-context.ts +62 -3
- package/src/resources/extensions/search-the-web/tool-search.ts +62 -3
- package/src/resources/extensions/shared/bundled-extension-paths.ts +11 -0
- package/src/resources/extensions/subagent/index.ts +2 -1
- package/src/resources/skills/github-workflows/SKILL.md +5 -0
- package/dist/resources/extensions/gsd/git-service.d.ts +0 -225
- package/dist/resources/extensions/gsd/git-service.js +0 -756
- package/dist/resources/extensions/gsd/preferences.d.ts +0 -122
- package/dist/resources/extensions/gsd/preferences.js +0 -616
- package/dist/resources/extensions/gsd/worktree.d.ts +0 -106
- package/dist/resources/extensions/remote-questions/config.d.ts +0 -14
- package/dist/resources/extensions/remote-questions/config.js +0 -68
- package/dist/resources/extensions/remote-questions/discord-adapter.d.ts +0 -17
- package/dist/resources/extensions/remote-questions/discord-adapter.js +0 -118
- package/dist/resources/extensions/remote-questions/format.d.ts +0 -38
- package/dist/resources/extensions/remote-questions/format.js +0 -119
- package/dist/resources/extensions/remote-questions/manager.d.ts +0 -23
- package/dist/resources/extensions/remote-questions/manager.js +0 -161
- package/dist/resources/extensions/remote-questions/remote-command.d.ts +0 -6
- package/dist/resources/extensions/remote-questions/remote-command.js +0 -358
- package/dist/resources/extensions/remote-questions/slack-adapter.d.ts +0 -15
- package/dist/resources/extensions/remote-questions/slack-adapter.js +0 -82
- package/dist/resources/extensions/remote-questions/status.d.ts +0 -9
- package/dist/resources/extensions/remote-questions/status.js +0 -25
- package/dist/resources/extensions/remote-questions/store.d.ts +0 -11
- package/dist/resources/extensions/remote-questions/store.js +0 -66
- package/dist/resources/extensions/remote-questions/types.d.ts +0 -68
- package/dist/resources/extensions/remote-questions/types.js +0 -4
|
@@ -0,0 +1,297 @@
|
|
|
1
|
+
// GSD Extension — Hook Engine Tests (Post-Unit, Pre-Dispatch, State Persistence)
|
|
2
|
+
// Copyright (c) 2026 Jeremy McSpadden <jeremy@fluxlabs.net>
|
|
3
|
+
|
|
4
|
+
import { mkdtempSync, mkdirSync, rmSync, writeFileSync, existsSync, readFileSync } from "node:fs";
|
|
5
|
+
import { join } from "node:path";
|
|
6
|
+
import { tmpdir } from "node:os";
|
|
7
|
+
import { createTestContext } from "./test-helpers.ts";
|
|
8
|
+
import {
|
|
9
|
+
checkPostUnitHooks,
|
|
10
|
+
getActiveHook,
|
|
11
|
+
resetHookState,
|
|
12
|
+
isRetryPending,
|
|
13
|
+
consumeRetryTrigger,
|
|
14
|
+
resolveHookArtifactPath,
|
|
15
|
+
runPreDispatchHooks,
|
|
16
|
+
persistHookState,
|
|
17
|
+
restoreHookState,
|
|
18
|
+
clearPersistedHookState,
|
|
19
|
+
getHookStatus,
|
|
20
|
+
formatHookStatus,
|
|
21
|
+
} from "../post-unit-hooks.ts";
|
|
22
|
+
|
|
23
|
+
const { assertEq, assertTrue, assertMatch, report } = createTestContext();
|
|
24
|
+
|
|
25
|
+
// ─── Fixture Helpers ───────────────────────────────────────────────────────
|
|
26
|
+
|
|
27
|
+
function createFixtureBase(): string {
|
|
28
|
+
const base = mkdtempSync(join(tmpdir(), "gsd-hook-test-"));
|
|
29
|
+
mkdirSync(join(base, ".gsd", "M001", "slices", "S01", "tasks"), { recursive: true });
|
|
30
|
+
return base;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
34
|
+
// Phase 1: Post-Unit Hook Tests
|
|
35
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
36
|
+
|
|
37
|
+
// ─── resolveHookArtifactPath ───────────────────────────────────────────────
|
|
38
|
+
|
|
39
|
+
console.log("\n=== resolveHookArtifactPath ===");
|
|
40
|
+
|
|
41
|
+
{
|
|
42
|
+
const base = "/project";
|
|
43
|
+
|
|
44
|
+
// Task-level
|
|
45
|
+
const taskPath = resolveHookArtifactPath(base, "M001/S01/T01", "REVIEW-PASS.md");
|
|
46
|
+
assertEq(
|
|
47
|
+
taskPath,
|
|
48
|
+
join(base, ".gsd", "M001", "slices", "S01", "tasks", "T01-REVIEW-PASS.md"),
|
|
49
|
+
"task-level artifact path",
|
|
50
|
+
);
|
|
51
|
+
|
|
52
|
+
// Slice-level
|
|
53
|
+
const slicePath = resolveHookArtifactPath(base, "M001/S01", "REVIEW-PASS.md");
|
|
54
|
+
assertEq(
|
|
55
|
+
slicePath,
|
|
56
|
+
join(base, ".gsd", "M001", "slices", "S01", "REVIEW-PASS.md"),
|
|
57
|
+
"slice-level artifact path",
|
|
58
|
+
);
|
|
59
|
+
|
|
60
|
+
// Milestone-level
|
|
61
|
+
const milestonePath = resolveHookArtifactPath(base, "M001", "REVIEW-PASS.md");
|
|
62
|
+
assertEq(
|
|
63
|
+
milestonePath,
|
|
64
|
+
join(base, ".gsd", "M001", "REVIEW-PASS.md"),
|
|
65
|
+
"milestone-level artifact path",
|
|
66
|
+
);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// ─── resetHookState ────────────────────────────────────────────────────────
|
|
70
|
+
|
|
71
|
+
console.log("\n=== resetHookState ===");
|
|
72
|
+
|
|
73
|
+
{
|
|
74
|
+
resetHookState();
|
|
75
|
+
assertEq(getActiveHook(), null, "no active hook after reset");
|
|
76
|
+
assertTrue(!isRetryPending(), "no retry pending after reset");
|
|
77
|
+
assertEq(consumeRetryTrigger(), null, "no retry trigger after reset");
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// ─── checkPostUnitHooks with no hooks configured ───────────────────────────
|
|
81
|
+
|
|
82
|
+
console.log("\n=== No hooks configured ===");
|
|
83
|
+
|
|
84
|
+
{
|
|
85
|
+
resetHookState();
|
|
86
|
+
const base = createFixtureBase();
|
|
87
|
+
try {
|
|
88
|
+
const result = checkPostUnitHooks("execute-task", "M001/S01/T01", base);
|
|
89
|
+
assertEq(result, null, "returns null when no hooks configured");
|
|
90
|
+
} finally {
|
|
91
|
+
rmSync(base, { recursive: true, force: true });
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// ─── Hook units don't trigger hooks (no hook-on-hook) ──────────────────────
|
|
96
|
+
|
|
97
|
+
console.log("\n=== Hook-on-hook prevention ===");
|
|
98
|
+
|
|
99
|
+
{
|
|
100
|
+
resetHookState();
|
|
101
|
+
const base = createFixtureBase();
|
|
102
|
+
try {
|
|
103
|
+
const result = checkPostUnitHooks("hook/code-review", "M001/S01/T01", base);
|
|
104
|
+
assertEq(result, null, "hook units don't trigger other hooks");
|
|
105
|
+
} finally {
|
|
106
|
+
rmSync(base, { recursive: true, force: true });
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// ─── consumeRetryTrigger clears state ──────────────────────────────────────
|
|
111
|
+
|
|
112
|
+
console.log("\n=== consumeRetryTrigger clears state ===");
|
|
113
|
+
|
|
114
|
+
{
|
|
115
|
+
resetHookState();
|
|
116
|
+
assertEq(consumeRetryTrigger(), null, "no trigger initially");
|
|
117
|
+
assertTrue(!isRetryPending(), "no retry initially");
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// ─── Variable substitution in prompts ──────────────────────────────────────
|
|
121
|
+
|
|
122
|
+
console.log("\n=== Variable substitution ===");
|
|
123
|
+
|
|
124
|
+
{
|
|
125
|
+
const base = "/project";
|
|
126
|
+
|
|
127
|
+
// 3-part ID
|
|
128
|
+
const path3 = resolveHookArtifactPath(base, "M002/S03/T05", "result.md");
|
|
129
|
+
assertTrue(path3.includes("M002"), "3-part ID extracts milestoneId");
|
|
130
|
+
assertTrue(path3.includes("S03"), "3-part ID extracts sliceId");
|
|
131
|
+
assertTrue(path3.includes("T05"), "3-part ID extracts taskId");
|
|
132
|
+
|
|
133
|
+
// 2-part ID
|
|
134
|
+
const path2 = resolveHookArtifactPath(base, "M002/S03", "result.md");
|
|
135
|
+
assertTrue(path2.includes("M002"), "2-part ID extracts milestoneId");
|
|
136
|
+
assertTrue(path2.includes("S03"), "2-part ID extracts sliceId");
|
|
137
|
+
|
|
138
|
+
// 1-part ID
|
|
139
|
+
const path1 = resolveHookArtifactPath(base, "M002", "result.md");
|
|
140
|
+
assertTrue(path1.includes("M002"), "1-part ID extracts milestoneId");
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
144
|
+
// Phase 2: Pre-Dispatch Hook Tests
|
|
145
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
146
|
+
|
|
147
|
+
console.log("\n=== Pre-dispatch: no hooks configured ===");
|
|
148
|
+
|
|
149
|
+
{
|
|
150
|
+
const base = createFixtureBase();
|
|
151
|
+
try {
|
|
152
|
+
const result = runPreDispatchHooks("execute-task", "M001/S01/T01", "original prompt", base);
|
|
153
|
+
assertEq(result.action, "proceed", "proceeds when no hooks");
|
|
154
|
+
assertEq(result.prompt, "original prompt", "prompt unchanged");
|
|
155
|
+
assertEq(result.firedHooks.length, 0, "no hooks fired");
|
|
156
|
+
} finally {
|
|
157
|
+
rmSync(base, { recursive: true, force: true });
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
console.log("\n=== Pre-dispatch: hook units bypass ===");
|
|
162
|
+
|
|
163
|
+
{
|
|
164
|
+
const base = createFixtureBase();
|
|
165
|
+
try {
|
|
166
|
+
const result = runPreDispatchHooks("hook/review", "M001/S01/T01", "hook prompt", base);
|
|
167
|
+
assertEq(result.action, "proceed", "hook units always proceed");
|
|
168
|
+
assertEq(result.prompt, "hook prompt", "hook prompt unchanged");
|
|
169
|
+
assertEq(result.firedHooks.length, 0, "no hooks fired for hook units");
|
|
170
|
+
} finally {
|
|
171
|
+
rmSync(base, { recursive: true, force: true });
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
176
|
+
// Phase 3: State Persistence Tests
|
|
177
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
178
|
+
|
|
179
|
+
console.log("\n=== State persistence: persist and restore ===");
|
|
180
|
+
|
|
181
|
+
{
|
|
182
|
+
const base = createFixtureBase();
|
|
183
|
+
try {
|
|
184
|
+
resetHookState();
|
|
185
|
+
|
|
186
|
+
// Persist empty state
|
|
187
|
+
persistHookState(base);
|
|
188
|
+
const filePath = join(base, ".gsd", "hook-state.json");
|
|
189
|
+
assertTrue(existsSync(filePath), "hook-state.json created");
|
|
190
|
+
|
|
191
|
+
const content = JSON.parse(readFileSync(filePath, "utf-8"));
|
|
192
|
+
assertEq(typeof content.savedAt, "string", "savedAt is a string");
|
|
193
|
+
assertEq(Object.keys(content.cycleCounts).length, 0, "empty cycle counts");
|
|
194
|
+
} finally {
|
|
195
|
+
rmSync(base, { recursive: true, force: true });
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
console.log("\n=== State persistence: restore from disk ===");
|
|
200
|
+
|
|
201
|
+
{
|
|
202
|
+
const base = createFixtureBase();
|
|
203
|
+
try {
|
|
204
|
+
resetHookState();
|
|
205
|
+
|
|
206
|
+
// Write a state file with some cycle counts
|
|
207
|
+
const stateFile = join(base, ".gsd", "hook-state.json");
|
|
208
|
+
writeFileSync(stateFile, JSON.stringify({
|
|
209
|
+
cycleCounts: {
|
|
210
|
+
"review/execute-task/M001/S01/T01": 2,
|
|
211
|
+
"simplify/execute-task/M001/S01/T02": 1,
|
|
212
|
+
},
|
|
213
|
+
savedAt: new Date().toISOString(),
|
|
214
|
+
}), "utf-8");
|
|
215
|
+
|
|
216
|
+
// Restore
|
|
217
|
+
restoreHookState(base);
|
|
218
|
+
|
|
219
|
+
// Verify by persisting and reading back
|
|
220
|
+
persistHookState(base);
|
|
221
|
+
const restored = JSON.parse(readFileSync(stateFile, "utf-8"));
|
|
222
|
+
assertEq(restored.cycleCounts["review/execute-task/M001/S01/T01"], 2, "cycle count restored for review");
|
|
223
|
+
assertEq(restored.cycleCounts["simplify/execute-task/M001/S01/T02"], 1, "cycle count restored for simplify");
|
|
224
|
+
} finally {
|
|
225
|
+
rmSync(base, { recursive: true, force: true });
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
console.log("\n=== State persistence: clear ===");
|
|
230
|
+
|
|
231
|
+
{
|
|
232
|
+
const base = createFixtureBase();
|
|
233
|
+
try {
|
|
234
|
+
resetHookState();
|
|
235
|
+
|
|
236
|
+
// Write then clear
|
|
237
|
+
const stateFile = join(base, ".gsd", "hook-state.json");
|
|
238
|
+
writeFileSync(stateFile, JSON.stringify({
|
|
239
|
+
cycleCounts: { "review/execute-task/M001/S01/T01": 3 },
|
|
240
|
+
savedAt: new Date().toISOString(),
|
|
241
|
+
}), "utf-8");
|
|
242
|
+
|
|
243
|
+
clearPersistedHookState(base);
|
|
244
|
+
|
|
245
|
+
const cleared = JSON.parse(readFileSync(stateFile, "utf-8"));
|
|
246
|
+
assertEq(Object.keys(cleared.cycleCounts).length, 0, "cycle counts cleared");
|
|
247
|
+
} finally {
|
|
248
|
+
rmSync(base, { recursive: true, force: true });
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
console.log("\n=== State persistence: restore handles missing file ===");
|
|
253
|
+
|
|
254
|
+
{
|
|
255
|
+
const base = createFixtureBase();
|
|
256
|
+
try {
|
|
257
|
+
resetHookState();
|
|
258
|
+
// Should not throw
|
|
259
|
+
restoreHookState(base);
|
|
260
|
+
assertEq(getActiveHook(), null, "no active hook after restore from missing file");
|
|
261
|
+
} finally {
|
|
262
|
+
rmSync(base, { recursive: true, force: true });
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
console.log("\n=== State persistence: restore handles corrupt file ===");
|
|
267
|
+
|
|
268
|
+
{
|
|
269
|
+
const base = createFixtureBase();
|
|
270
|
+
try {
|
|
271
|
+
resetHookState();
|
|
272
|
+
writeFileSync(join(base, ".gsd", "hook-state.json"), "not json", "utf-8");
|
|
273
|
+
// Should not throw
|
|
274
|
+
restoreHookState(base);
|
|
275
|
+
assertEq(getActiveHook(), null, "no active hook after corrupt restore");
|
|
276
|
+
} finally {
|
|
277
|
+
rmSync(base, { recursive: true, force: true });
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
282
|
+
// Phase 3: Hook Status Reporting Tests
|
|
283
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
284
|
+
|
|
285
|
+
console.log("\n=== Hook status: no hooks ===");
|
|
286
|
+
|
|
287
|
+
{
|
|
288
|
+
resetHookState();
|
|
289
|
+
const entries = getHookStatus();
|
|
290
|
+
// No preferences file = no hooks
|
|
291
|
+
assertEq(entries.length, 0, "no entries when no hooks configured");
|
|
292
|
+
|
|
293
|
+
const formatted = formatHookStatus();
|
|
294
|
+
assertMatch(formatted, /No hooks configured/, "status message says no hooks");
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
report();
|
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
// GSD Extension — Hook Preferences Parsing Tests (Post-Unit + Pre-Dispatch)
|
|
2
|
+
// Copyright (c) 2026 Jeremy McSpadden <jeremy@fluxlabs.net>
|
|
3
|
+
|
|
4
|
+
import { createTestContext } from "./test-helpers.ts";
|
|
5
|
+
|
|
6
|
+
const { assertEq, assertTrue, report } = createTestContext();
|
|
7
|
+
|
|
8
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
9
|
+
// Phase 1: Post-Unit Hook Config Tests
|
|
10
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
11
|
+
|
|
12
|
+
console.log("\n=== Post-unit hook config validation ===");
|
|
13
|
+
|
|
14
|
+
{
|
|
15
|
+
const validHook = {
|
|
16
|
+
name: "test-hook",
|
|
17
|
+
after: ["execute-task"],
|
|
18
|
+
prompt: "Test prompt",
|
|
19
|
+
max_cycles: 2,
|
|
20
|
+
model: "claude-sonnet-4-6",
|
|
21
|
+
artifact: "TEST-RESULT.md",
|
|
22
|
+
retry_on: "TEST-ISSUES.md",
|
|
23
|
+
enabled: true,
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
assertEq(validHook.name, "test-hook", "valid hook has name");
|
|
27
|
+
assertEq(validHook.after.length, 1, "valid hook has one after entry");
|
|
28
|
+
assertEq(validHook.after[0], "execute-task", "valid hook triggers after execute-task");
|
|
29
|
+
assertTrue(validHook.max_cycles! <= 10, "max_cycles within limit");
|
|
30
|
+
assertTrue(validHook.max_cycles! >= 1, "max_cycles above minimum");
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
console.log("\n=== max_cycles clamping ===");
|
|
34
|
+
|
|
35
|
+
{
|
|
36
|
+
const clampedHigh = Math.max(1, Math.min(10, Math.round(15)));
|
|
37
|
+
assertEq(clampedHigh, 10, "max_cycles above 10 clamped to 10");
|
|
38
|
+
|
|
39
|
+
const clampedLow = Math.max(1, Math.min(10, Math.round(0)));
|
|
40
|
+
assertEq(clampedLow, 1, "max_cycles below 1 clamped to 1");
|
|
41
|
+
|
|
42
|
+
const clampedNeg = Math.max(1, Math.min(10, Math.round(-5)));
|
|
43
|
+
assertEq(clampedNeg, 1, "negative max_cycles clamped to 1");
|
|
44
|
+
|
|
45
|
+
const normal = Math.max(1, Math.min(10, Math.round(3)));
|
|
46
|
+
assertEq(normal, 3, "normal max_cycles passes through");
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
console.log("\n=== Post-unit hook merging ===");
|
|
50
|
+
|
|
51
|
+
{
|
|
52
|
+
const baseHooks = [
|
|
53
|
+
{ name: "review", after: ["execute-task"], prompt: "base prompt" },
|
|
54
|
+
{ name: "lint", after: ["plan-slice"], prompt: "lint code" },
|
|
55
|
+
];
|
|
56
|
+
|
|
57
|
+
const overrideHooks = [
|
|
58
|
+
{ name: "review", after: ["execute-task", "complete-slice"], prompt: "override prompt" },
|
|
59
|
+
{ name: "security", after: ["execute-task"], prompt: "security check" },
|
|
60
|
+
];
|
|
61
|
+
|
|
62
|
+
const merged = [...baseHooks];
|
|
63
|
+
for (const hook of overrideHooks) {
|
|
64
|
+
const idx = merged.findIndex(h => h.name === hook.name);
|
|
65
|
+
if (idx >= 0) {
|
|
66
|
+
merged[idx] = hook;
|
|
67
|
+
} else {
|
|
68
|
+
merged.push(hook);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
assertEq(merged.length, 3, "merged has 3 hooks");
|
|
73
|
+
assertEq(merged[0].prompt, "override prompt", "review hook was overridden");
|
|
74
|
+
assertEq(merged[0].after.length, 2, "overridden review has 2 after entries");
|
|
75
|
+
assertEq(merged[1].name, "lint", "lint kept from base");
|
|
76
|
+
assertEq(merged[2].name, "security", "security added from override");
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
80
|
+
// Phase 2: Pre-Dispatch Hook Config Tests
|
|
81
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
82
|
+
|
|
83
|
+
console.log("\n=== Pre-dispatch hook config shape ===");
|
|
84
|
+
|
|
85
|
+
{
|
|
86
|
+
const modifyHook = {
|
|
87
|
+
name: "inject-context",
|
|
88
|
+
before: ["execute-task"],
|
|
89
|
+
action: "modify" as const,
|
|
90
|
+
prepend: "Remember to follow coding conventions.",
|
|
91
|
+
append: "Run tests after making changes.",
|
|
92
|
+
enabled: true,
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
assertEq(modifyHook.name, "inject-context", "modify hook has name");
|
|
96
|
+
assertEq(modifyHook.action, "modify", "action is modify");
|
|
97
|
+
assertTrue(!!modifyHook.prepend, "has prepend text");
|
|
98
|
+
assertTrue(!!modifyHook.append, "has append text");
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
{
|
|
102
|
+
const skipHook = {
|
|
103
|
+
name: "skip-research",
|
|
104
|
+
before: ["research-slice"],
|
|
105
|
+
action: "skip" as const,
|
|
106
|
+
skip_if: "RESEARCH-DONE.md",
|
|
107
|
+
enabled: true,
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
assertEq(skipHook.action, "skip", "action is skip");
|
|
111
|
+
assertEq(skipHook.skip_if, "RESEARCH-DONE.md", "has skip condition");
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
{
|
|
115
|
+
const replaceHook = {
|
|
116
|
+
name: "custom-planning",
|
|
117
|
+
before: ["plan-slice"],
|
|
118
|
+
action: "replace" as const,
|
|
119
|
+
prompt: "Use custom planning approach for {sliceId}",
|
|
120
|
+
unit_type: "custom-plan",
|
|
121
|
+
model: "claude-opus-4-6",
|
|
122
|
+
enabled: true,
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
assertEq(replaceHook.action, "replace", "action is replace");
|
|
126
|
+
assertTrue(!!replaceHook.prompt, "replace hook has prompt");
|
|
127
|
+
assertEq(replaceHook.unit_type, "custom-plan", "has unit_type override");
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
console.log("\n=== Pre-dispatch action validation ===");
|
|
131
|
+
|
|
132
|
+
{
|
|
133
|
+
const validActions = new Set(["modify", "skip", "replace"]);
|
|
134
|
+
assertTrue(validActions.has("modify"), "modify is valid");
|
|
135
|
+
assertTrue(validActions.has("skip"), "skip is valid");
|
|
136
|
+
assertTrue(validActions.has("replace"), "replace is valid");
|
|
137
|
+
assertTrue(!validActions.has("delete"), "delete is not valid");
|
|
138
|
+
assertTrue(!validActions.has(""), "empty string is not valid");
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
console.log("\n=== Pre-dispatch hook merging ===");
|
|
142
|
+
|
|
143
|
+
{
|
|
144
|
+
const baseHooks = [
|
|
145
|
+
{ name: "inject", before: ["execute-task"], action: "modify" as const, prepend: "base" },
|
|
146
|
+
];
|
|
147
|
+
|
|
148
|
+
const overrideHooks = [
|
|
149
|
+
{ name: "inject", before: ["execute-task"], action: "modify" as const, prepend: "override" },
|
|
150
|
+
{ name: "gate", before: ["plan-slice"], action: "skip" as const },
|
|
151
|
+
];
|
|
152
|
+
|
|
153
|
+
const merged = [...baseHooks];
|
|
154
|
+
for (const hook of overrideHooks) {
|
|
155
|
+
const idx = merged.findIndex(h => h.name === hook.name);
|
|
156
|
+
if (idx >= 0) {
|
|
157
|
+
merged[idx] = hook;
|
|
158
|
+
} else {
|
|
159
|
+
merged.push(hook);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
assertEq(merged.length, 2, "merged has 2 pre-dispatch hooks");
|
|
164
|
+
assertEq(merged[0].prepend, "override", "inject hook overridden");
|
|
165
|
+
assertEq(merged[1].name, "gate", "gate hook added");
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
169
|
+
// Known unit types validation
|
|
170
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
171
|
+
|
|
172
|
+
console.log("\n=== Known unit types ===");
|
|
173
|
+
|
|
174
|
+
{
|
|
175
|
+
const knownUnitTypes = new Set([
|
|
176
|
+
"research-milestone", "plan-milestone", "research-slice", "plan-slice",
|
|
177
|
+
"execute-task", "complete-slice", "replan-slice", "reassess-roadmap",
|
|
178
|
+
"run-uat", "fix-merge", "complete-milestone",
|
|
179
|
+
]);
|
|
180
|
+
|
|
181
|
+
assertTrue(knownUnitTypes.has("execute-task"), "execute-task is known");
|
|
182
|
+
assertTrue(knownUnitTypes.has("complete-slice"), "complete-slice is known");
|
|
183
|
+
assertTrue(knownUnitTypes.has("plan-slice"), "plan-slice is known");
|
|
184
|
+
assertTrue(!knownUnitTypes.has("hook/review"), "hook types are not in known set");
|
|
185
|
+
assertTrue(!knownUnitTypes.has("invalid-type"), "invalid types are not in known set");
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
189
|
+
// Preferences YAML format verification
|
|
190
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
191
|
+
|
|
192
|
+
console.log("\n=== Preferences YAML format ===");
|
|
193
|
+
|
|
194
|
+
{
|
|
195
|
+
const prefsContent = [
|
|
196
|
+
"---",
|
|
197
|
+
"version: 1",
|
|
198
|
+
"post_unit_hooks:",
|
|
199
|
+
" - name: code-review",
|
|
200
|
+
" after:",
|
|
201
|
+
" - execute-task",
|
|
202
|
+
" prompt: Review the changes",
|
|
203
|
+
" max_cycles: 3",
|
|
204
|
+
" artifact: REVIEW-PASS.md",
|
|
205
|
+
" retry_on: REVIEW-ISSUES.md",
|
|
206
|
+
"pre_dispatch_hooks:",
|
|
207
|
+
" - name: inject-conventions",
|
|
208
|
+
" before:",
|
|
209
|
+
" - execute-task",
|
|
210
|
+
" action: modify",
|
|
211
|
+
" append: Follow project coding conventions",
|
|
212
|
+
" - name: custom-research",
|
|
213
|
+
" before:",
|
|
214
|
+
" - research-slice",
|
|
215
|
+
" action: replace",
|
|
216
|
+
" prompt: Custom research prompt",
|
|
217
|
+
"---",
|
|
218
|
+
].join("\n");
|
|
219
|
+
|
|
220
|
+
assertTrue(prefsContent.includes("post_unit_hooks:"), "has post_unit_hooks key");
|
|
221
|
+
assertTrue(prefsContent.includes("pre_dispatch_hooks:"), "has pre_dispatch_hooks key");
|
|
222
|
+
assertTrue(prefsContent.includes("action: modify"), "has modify action");
|
|
223
|
+
assertTrue(prefsContent.includes("action: replace"), "has replace action");
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
report();
|
|
@@ -67,6 +67,18 @@ async function main(): Promise<void> {
|
|
|
67
67
|
assertEq('M001-abc123: Title'.replace(TITLE_STRIP_RE, ''), 'Title', 'strips M001-abc123: Title → Title');
|
|
68
68
|
assertEq('M042-z9a8b7: Dashboard'.replace(TITLE_STRIP_RE, ''), 'Dashboard', 'strips M042-z9a8b7: Dashboard');
|
|
69
69
|
|
|
70
|
+
// Em dash in title — current format (M001: Title) correctly preserves em dash in title body
|
|
71
|
+
assertEq(
|
|
72
|
+
'M001: Foundation — Build Core'.replace(TITLE_STRIP_RE, ''),
|
|
73
|
+
'Foundation — Build Core',
|
|
74
|
+
'strips M001: prefix and preserves em dash in title body',
|
|
75
|
+
);
|
|
76
|
+
assertEq(
|
|
77
|
+
'M001-abc123: Foundation — Build Core'.replace(TITLE_STRIP_RE, ''),
|
|
78
|
+
'Foundation — Build Core',
|
|
79
|
+
'strips M001-abc123: prefix and preserves em dash in title body (unique format)',
|
|
80
|
+
);
|
|
81
|
+
|
|
70
82
|
// Edge case: dash-style separator (M001 — Title: Subtitle preserves colon in body)
|
|
71
83
|
assertEq(
|
|
72
84
|
'M001 — Unique Milestone IDs: Foo'.replace(TITLE_STRIP_RE, ''),
|
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
readUnitRuntimeRecord,
|
|
9
9
|
writeUnitRuntimeRecord,
|
|
10
10
|
} from "../unit-runtime.ts";
|
|
11
|
+
import { clearPathCache } from '../paths.ts';
|
|
11
12
|
import { createTestContext } from './test-helpers.ts';
|
|
12
13
|
|
|
13
14
|
const { assertEq, assertTrue, report } = createTestContext();
|
|
@@ -48,6 +49,7 @@ console.log("\n=== execute-task durability inspection ===");
|
|
|
48
49
|
"utf-8",
|
|
49
50
|
);
|
|
50
51
|
writeFileSync(join(base, ".gsd", "STATE.md"), "## Next Action\nExecute T10 for S02: next thing\n", "utf-8");
|
|
52
|
+
clearPathCache();
|
|
51
53
|
|
|
52
54
|
status = await inspectExecuteTaskDurability(base, "M100/S02/T09");
|
|
53
55
|
assertEq(status!.summaryExists, true, "summary found after write");
|
|
@@ -128,6 +130,7 @@ console.log("\n=== must-haves: partially mentioned in summary ===");
|
|
|
128
130
|
);
|
|
129
131
|
writeFileSync(join(mhBase, ".gsd", "STATE.md"), "## Next Action\nExecute T02 for S02: next thing\n", "utf-8");
|
|
130
132
|
|
|
133
|
+
clearPathCache();
|
|
131
134
|
const status = await inspectExecuteTaskDurability(mhBase, "M200/S02/T01");
|
|
132
135
|
assertTrue(status !== null, "mh-partial: status exists");
|
|
133
136
|
assertEq(status!.mustHaveCount, 3, "mh-partial: mustHaveCount is 3");
|
|
@@ -155,6 +158,7 @@ console.log("\n=== must-haves: no task plan file ===");
|
|
|
155
158
|
);
|
|
156
159
|
writeFileSync(join(mhBase, ".gsd", "STATE.md"), "## Next Action\nExecute T02 for S03: next thing\n", "utf-8");
|
|
157
160
|
|
|
161
|
+
clearPathCache();
|
|
158
162
|
const status = await inspectExecuteTaskDurability(mhBase, "M200/S03/T01");
|
|
159
163
|
assertTrue(status !== null, "mh-noplan: status exists");
|
|
160
164
|
assertEq(status!.mustHaveCount, 0, "mh-noplan: mustHaveCount is 0 when no task plan");
|
|
@@ -179,6 +183,7 @@ console.log("\n=== must-haves: present but no summary file ===");
|
|
|
179
183
|
);
|
|
180
184
|
writeFileSync(join(mhBase, ".gsd", "STATE.md"), "## Next Action\nExecute T01 for S04: build parser\n", "utf-8");
|
|
181
185
|
|
|
186
|
+
clearPathCache();
|
|
182
187
|
const status = await inspectExecuteTaskDurability(mhBase, "M200/S04/T01");
|
|
183
188
|
assertTrue(status !== null, "mh-nosummary: status exists");
|
|
184
189
|
assertEq(status!.mustHaveCount, 2, "mh-nosummary: mustHaveCount is 2");
|
|
@@ -210,6 +215,7 @@ console.log("\n=== must-haves: substring matching (no backtick tokens) ===");
|
|
|
210
215
|
);
|
|
211
216
|
writeFileSync(join(mhBase, ".gsd", "STATE.md"), "## Next Action\nExecute T02 for S05: next thing\n", "utf-8");
|
|
212
217
|
|
|
218
|
+
clearPathCache();
|
|
213
219
|
const status = await inspectExecuteTaskDurability(mhBase, "M200/S05/T01");
|
|
214
220
|
assertTrue(status !== null, "mh-substr: status exists");
|
|
215
221
|
assertEq(status!.mustHaveCount, 3, "mh-substr: mustHaveCount is 3");
|
|
@@ -79,7 +79,7 @@ writeFileSync(
|
|
|
79
79
|
"utf-8",
|
|
80
80
|
);
|
|
81
81
|
run("git add .", base);
|
|
82
|
-
run(
|
|
82
|
+
run('git commit -m "chore: init"', base);
|
|
83
83
|
|
|
84
84
|
async function main(): Promise<void> {
|
|
85
85
|
// ── Verify main tree baseline ──────────────────────────────────────────────
|
|
@@ -124,7 +124,7 @@ async function main(): Promise<void> {
|
|
|
124
124
|
console.log("\n=== Work and merge slice in worktree ===");
|
|
125
125
|
writeFileSync(join(wt.path, "feature.txt"), "new feature\n", "utf-8");
|
|
126
126
|
run("git add .", wt.path);
|
|
127
|
-
run(
|
|
127
|
+
run('git commit -m "feat: add feature"', wt.path);
|
|
128
128
|
|
|
129
129
|
// switchToMain should go to worktree/alpha, NOT main
|
|
130
130
|
switchToMain(wt.path);
|
|
@@ -150,7 +150,7 @@ async function main(): Promise<void> {
|
|
|
150
150
|
|
|
151
151
|
writeFileSync(join(wt.path, "feature2.txt"), "second feature\n", "utf-8");
|
|
152
152
|
run("git add .", wt.path);
|
|
153
|
-
run(
|
|
153
|
+
run('git commit -m "feat: add feature 2"', wt.path);
|
|
154
154
|
|
|
155
155
|
switchToMain(wt.path);
|
|
156
156
|
const merge2 = mergeSliceToMain(wt.path, "M001", "S02", "Second");
|
|
@@ -167,7 +167,7 @@ async function main(): Promise<void> {
|
|
|
167
167
|
|
|
168
168
|
writeFileSync(join(base, "main-feature.txt"), "main work\n", "utf-8");
|
|
169
169
|
run("git add .", base);
|
|
170
|
-
run(
|
|
170
|
+
run('git commit -m "feat: main work"', base);
|
|
171
171
|
|
|
172
172
|
switchToMain(base);
|
|
173
173
|
assertEq(getCurrentBranch(base), "main", "main tree switchToMain goes to main");
|
|
@@ -23,8 +23,8 @@ function run(command: string, cwd: string): string {
|
|
|
23
23
|
// Set up a test repo
|
|
24
24
|
const base = mkdtempSync(join(tmpdir(), "gsd-worktree-mgr-test-"));
|
|
25
25
|
run("git init -b main", base);
|
|
26
|
-
run(
|
|
27
|
-
run(
|
|
26
|
+
run('git config user.name "Pi Test"', base);
|
|
27
|
+
run('git config user.email "pi@example.com"', base);
|
|
28
28
|
|
|
29
29
|
// Create initial project structure
|
|
30
30
|
mkdirSync(join(base, ".gsd", "milestones", "M001"), { recursive: true });
|
|
@@ -35,7 +35,7 @@ writeFileSync(
|
|
|
35
35
|
"utf-8",
|
|
36
36
|
);
|
|
37
37
|
run("git add .", base);
|
|
38
|
-
run(
|
|
38
|
+
run('git commit -m "chore: init"', base);
|
|
39
39
|
|
|
40
40
|
async function main(): Promise<void> {
|
|
41
41
|
console.log("\n=== worktreeBranchName ===");
|
|
@@ -95,7 +95,7 @@ async function main(): Promise<void> {
|
|
|
95
95
|
"utf-8",
|
|
96
96
|
);
|
|
97
97
|
run("git add .", wtPath);
|
|
98
|
-
run(
|
|
98
|
+
run('git commit -m "feat: add M002 and update M001"', wtPath);
|
|
99
99
|
|
|
100
100
|
console.log("\n=== diffWorktreeGSD ===");
|
|
101
101
|
const diff = diffWorktreeGSD(base, "feature-x");
|