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,122 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unit tests for the CONTEXT.md write-gate (D031 guard chain).
|
|
3
|
+
*
|
|
4
|
+
* Exercises shouldBlockContextWrite() — a pure function that implements:
|
|
5
|
+
* (a) toolName !== "write" → pass
|
|
6
|
+
* (b) milestoneId null → pass (not in discussion)
|
|
7
|
+
* (c) path doesn't match /M\d+-CONTEXT\.md$/ → pass
|
|
8
|
+
* (d) depthVerified → pass
|
|
9
|
+
* (e) else → block with actionable reason
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import test from 'node:test';
|
|
13
|
+
import assert from 'node:assert/strict';
|
|
14
|
+
import { shouldBlockContextWrite } from '../index.ts';
|
|
15
|
+
|
|
16
|
+
// ─── Scenario 1: Blocks CONTEXT.md write during discussion without depth verification (absolute path) ──
|
|
17
|
+
|
|
18
|
+
test('write-gate: blocks CONTEXT.md write during discussion without depth verification (absolute path)', () => {
|
|
19
|
+
const result = shouldBlockContextWrite(
|
|
20
|
+
'write',
|
|
21
|
+
'/Users/dev/project/.gsd/milestones/M001/M001-CONTEXT.md',
|
|
22
|
+
'M001',
|
|
23
|
+
false,
|
|
24
|
+
);
|
|
25
|
+
assert.strictEqual(result.block, true, 'should block the write');
|
|
26
|
+
assert.ok(result.reason, 'should provide a reason');
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
// ─── Scenario 2: Blocks CONTEXT.md write during discussion without depth verification (relative path) ──
|
|
30
|
+
|
|
31
|
+
test('write-gate: blocks CONTEXT.md write during discussion without depth verification (relative path)', () => {
|
|
32
|
+
const result = shouldBlockContextWrite(
|
|
33
|
+
'write',
|
|
34
|
+
'.gsd/milestones/M005/M005-CONTEXT.md',
|
|
35
|
+
'M005',
|
|
36
|
+
false,
|
|
37
|
+
);
|
|
38
|
+
assert.strictEqual(result.block, true, 'should block the write');
|
|
39
|
+
assert.ok(result.reason, 'should provide a reason');
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
// ─── Scenario 3: Allows CONTEXT.md write after depth verification ──
|
|
43
|
+
|
|
44
|
+
test('write-gate: allows CONTEXT.md write after depth verification', () => {
|
|
45
|
+
const result = shouldBlockContextWrite(
|
|
46
|
+
'write',
|
|
47
|
+
'/Users/dev/project/.gsd/milestones/M001/M001-CONTEXT.md',
|
|
48
|
+
'M001',
|
|
49
|
+
true,
|
|
50
|
+
);
|
|
51
|
+
assert.strictEqual(result.block, false, 'should not block after depth verification');
|
|
52
|
+
assert.strictEqual(result.reason, undefined, 'should have no reason');
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
// ─── Scenario 4: Allows CONTEXT.md write outside discussion phase (milestoneId null) ──
|
|
56
|
+
|
|
57
|
+
test('write-gate: allows CONTEXT.md write outside discussion phase', () => {
|
|
58
|
+
const result = shouldBlockContextWrite(
|
|
59
|
+
'write',
|
|
60
|
+
'.gsd/milestones/M001/M001-CONTEXT.md',
|
|
61
|
+
null,
|
|
62
|
+
false,
|
|
63
|
+
);
|
|
64
|
+
assert.strictEqual(result.block, false, 'should not block outside discussion phase');
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
// ─── Scenario 5: Allows non-CONTEXT.md writes during discussion ──
|
|
68
|
+
|
|
69
|
+
test('write-gate: allows non-CONTEXT.md writes during discussion', () => {
|
|
70
|
+
// DISCUSSION.md
|
|
71
|
+
const r1 = shouldBlockContextWrite(
|
|
72
|
+
'write',
|
|
73
|
+
'.gsd/milestones/M001/M001-DISCUSSION.md',
|
|
74
|
+
'M001',
|
|
75
|
+
false,
|
|
76
|
+
);
|
|
77
|
+
assert.strictEqual(r1.block, false, 'DISCUSSION.md should pass');
|
|
78
|
+
|
|
79
|
+
// Slice file
|
|
80
|
+
const r2 = shouldBlockContextWrite(
|
|
81
|
+
'write',
|
|
82
|
+
'.gsd/milestones/M001/slices/S01/S01-PLAN.md',
|
|
83
|
+
'M001',
|
|
84
|
+
false,
|
|
85
|
+
);
|
|
86
|
+
assert.strictEqual(r2.block, false, 'slice plan should pass');
|
|
87
|
+
|
|
88
|
+
// Regular code file
|
|
89
|
+
const r3 = shouldBlockContextWrite(
|
|
90
|
+
'write',
|
|
91
|
+
'src/index.ts',
|
|
92
|
+
'M001',
|
|
93
|
+
false,
|
|
94
|
+
);
|
|
95
|
+
assert.strictEqual(r3.block, false, 'regular code file should pass');
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
// ─── Scenario 6: Regex specificity — doesn't match S01-CONTEXT.md ──
|
|
99
|
+
|
|
100
|
+
test('write-gate: regex does not match slice context files (S01-CONTEXT.md)', () => {
|
|
101
|
+
const result = shouldBlockContextWrite(
|
|
102
|
+
'write',
|
|
103
|
+
'.gsd/milestones/M001/slices/S01/S01-CONTEXT.md',
|
|
104
|
+
'M001',
|
|
105
|
+
false,
|
|
106
|
+
);
|
|
107
|
+
assert.strictEqual(result.block, false, 'S01-CONTEXT.md should not be blocked');
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
// ─── Scenario 7: Error message contains actionable instruction ──
|
|
111
|
+
|
|
112
|
+
test('write-gate: blocked reason contains depth_verification keyword', () => {
|
|
113
|
+
const result = shouldBlockContextWrite(
|
|
114
|
+
'write',
|
|
115
|
+
'.gsd/milestones/M999/M999-CONTEXT.md',
|
|
116
|
+
'M999',
|
|
117
|
+
false,
|
|
118
|
+
);
|
|
119
|
+
assert.strictEqual(result.block, true);
|
|
120
|
+
assert.ok(result.reason!.includes('depth_verification'), 'reason should mention depth_verification question id');
|
|
121
|
+
assert.ok(result.reason!.includes('ask_user_questions'), 'reason should mention ask_user_questions tool');
|
|
122
|
+
});
|
|
@@ -0,0 +1,296 @@
|
|
|
1
|
+
// GSD Extension — Core Type Definitions
|
|
2
|
+
// Types consumed by state derivation, file parsing, and status display.
|
|
3
|
+
// Pure interfaces — no logic, no runtime dependencies.
|
|
4
|
+
|
|
5
|
+
// ─── Enums & Literal Unions ────────────────────────────────────────────────
|
|
6
|
+
|
|
7
|
+
export type RiskLevel = 'low' | 'medium' | 'high';
|
|
8
|
+
export type Phase = 'pre-planning' | 'needs-discussion' | 'discussing' | 'researching' | 'planning' | 'executing' | 'verifying' | 'summarizing' | 'advancing' | 'completing-milestone' | 'replanning-slice' | 'complete' | 'paused' | 'blocked';
|
|
9
|
+
export type ContinueStatus = 'in_progress' | 'interrupted' | 'compacted';
|
|
10
|
+
|
|
11
|
+
// ─── Roadmap (Milestone-level) ─────────────────────────────────────────────
|
|
12
|
+
|
|
13
|
+
export interface RoadmapSliceEntry {
|
|
14
|
+
id: string; // e.g. "S01"
|
|
15
|
+
title: string; // e.g. "Types + File I/O + Git Operations"
|
|
16
|
+
risk: RiskLevel;
|
|
17
|
+
depends: string[]; // e.g. ["S01", "S02"]
|
|
18
|
+
done: boolean;
|
|
19
|
+
demo: string; // the "After this:" sentence
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export interface BoundaryMapEntry {
|
|
23
|
+
fromSlice: string; // e.g. "S01"
|
|
24
|
+
toSlice: string; // e.g. "S02" or "terminal"
|
|
25
|
+
produces: string; // raw text block of what this slice produces
|
|
26
|
+
consumes: string; // raw text block of what it consumes (or "nothing")
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export interface Roadmap {
|
|
30
|
+
title: string; // e.g. "M001: GSD Extension — Hierarchical Planning with Auto Mode"
|
|
31
|
+
vision: string;
|
|
32
|
+
successCriteria: string[];
|
|
33
|
+
slices: RoadmapSliceEntry[];
|
|
34
|
+
boundaryMap: BoundaryMapEntry[];
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// ─── Slice Plan ────────────────────────────────────────────────────────────
|
|
38
|
+
|
|
39
|
+
export interface TaskPlanEntry {
|
|
40
|
+
id: string; // e.g. "T01"
|
|
41
|
+
title: string; // e.g. "Core Type Definitions"
|
|
42
|
+
description: string;
|
|
43
|
+
done: boolean;
|
|
44
|
+
estimate: string; // e.g. "30m", "2h" — informational only
|
|
45
|
+
files?: string[]; // e.g. ["types.ts", "files.ts"] — extracted from "- Files:" subline
|
|
46
|
+
verify?: string; // e.g. "run tests" — extracted from "- Verify:" subline
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export interface SlicePlan {
|
|
50
|
+
id: string; // e.g. "S01"
|
|
51
|
+
title: string; // from the H1
|
|
52
|
+
goal: string;
|
|
53
|
+
demo: string;
|
|
54
|
+
mustHaves: string[]; // top-level must-have bullet points
|
|
55
|
+
tasks: TaskPlanEntry[];
|
|
56
|
+
filesLikelyTouched: string[];
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// ─── Summary (Task & Slice level) ──────────────────────────────────────────
|
|
60
|
+
|
|
61
|
+
export interface SummaryRequires {
|
|
62
|
+
slice: string;
|
|
63
|
+
provides: string;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export interface SummaryFrontmatter {
|
|
67
|
+
id: string;
|
|
68
|
+
parent: string;
|
|
69
|
+
milestone: string;
|
|
70
|
+
provides: string[];
|
|
71
|
+
requires: SummaryRequires[];
|
|
72
|
+
affects: string[];
|
|
73
|
+
key_files: string[];
|
|
74
|
+
key_decisions: string[];
|
|
75
|
+
patterns_established: string[];
|
|
76
|
+
drill_down_paths: string[];
|
|
77
|
+
observability_surfaces: string[];
|
|
78
|
+
duration: string;
|
|
79
|
+
verification_result: string;
|
|
80
|
+
completed_at: string;
|
|
81
|
+
blocker_discovered: boolean;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export interface FileModified {
|
|
85
|
+
path: string;
|
|
86
|
+
description: string;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export interface Summary {
|
|
90
|
+
frontmatter: SummaryFrontmatter;
|
|
91
|
+
title: string;
|
|
92
|
+
oneLiner: string;
|
|
93
|
+
whatHappened: string;
|
|
94
|
+
deviations: string;
|
|
95
|
+
filesModified: FileModified[];
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// ─── Continue-Here ─────────────────────────────────────────────────────────
|
|
99
|
+
|
|
100
|
+
export interface ContinueFrontmatter {
|
|
101
|
+
milestone: string;
|
|
102
|
+
slice: string;
|
|
103
|
+
task: string;
|
|
104
|
+
step: number;
|
|
105
|
+
totalSteps: number;
|
|
106
|
+
status: ContinueStatus;
|
|
107
|
+
savedAt: string;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
export interface Continue {
|
|
111
|
+
frontmatter: ContinueFrontmatter;
|
|
112
|
+
completedWork: string;
|
|
113
|
+
remainingWork: string;
|
|
114
|
+
decisions: string;
|
|
115
|
+
context: string;
|
|
116
|
+
nextAction: string;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// ─── Secrets Manifest ──────────────────────────────────────────────────────
|
|
120
|
+
|
|
121
|
+
export type SecretsManifestEntryStatus = 'pending' | 'collected' | 'skipped';
|
|
122
|
+
|
|
123
|
+
export interface SecretsManifestEntry {
|
|
124
|
+
key: string; // e.g. "OPENAI_API_KEY"
|
|
125
|
+
service: string; // e.g. "OpenAI"
|
|
126
|
+
dashboardUrl: string; // e.g. "https://platform.openai.com/api-keys" — empty if unknown
|
|
127
|
+
guidance: string[]; // numbered setup steps
|
|
128
|
+
formatHint: string; // e.g. "starts with sk-" — empty if unknown
|
|
129
|
+
status: SecretsManifestEntryStatus;
|
|
130
|
+
destination: string; // e.g. "dotenv", "vercel", "convex"
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
export interface SecretsManifest {
|
|
134
|
+
milestone: string; // e.g. "M001"
|
|
135
|
+
generatedAt: string; // ISO 8601 timestamp
|
|
136
|
+
entries: SecretsManifestEntry[];
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
export interface ManifestStatus {
|
|
140
|
+
pending: string[]; // manifest status = pending AND not in env
|
|
141
|
+
collected: string[]; // manifest status = collected AND not in env
|
|
142
|
+
skipped: string[]; // manifest status = skipped
|
|
143
|
+
existing: string[]; // key present in .env or process.env (regardless of manifest status)
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// ─── GSD State (Derived Dashboard) ────────────────────────────────────────
|
|
147
|
+
|
|
148
|
+
export interface ActiveRef {
|
|
149
|
+
id: string;
|
|
150
|
+
title: string;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
export interface MilestoneRegistryEntry {
|
|
154
|
+
id: string;
|
|
155
|
+
title: string;
|
|
156
|
+
status: 'complete' | 'active' | 'pending';
|
|
157
|
+
/** Milestone IDs that must be complete before this milestone becomes active. Populated from CONTEXT.md YAML frontmatter. */
|
|
158
|
+
dependsOn?: string[];
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
export interface RequirementCounts {
|
|
162
|
+
active: number;
|
|
163
|
+
validated: number;
|
|
164
|
+
deferred: number;
|
|
165
|
+
outOfScope: number;
|
|
166
|
+
blocked: number;
|
|
167
|
+
total: number;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
export interface GSDState {
|
|
171
|
+
activeMilestone: ActiveRef | null;
|
|
172
|
+
activeSlice: ActiveRef | null;
|
|
173
|
+
activeTask: ActiveRef | null;
|
|
174
|
+
phase: Phase;
|
|
175
|
+
recentDecisions: string[];
|
|
176
|
+
blockers: string[];
|
|
177
|
+
nextAction: string;
|
|
178
|
+
activeBranch?: string;
|
|
179
|
+
activeWorkspace?: string;
|
|
180
|
+
registry: MilestoneRegistryEntry[];
|
|
181
|
+
requirements?: RequirementCounts;
|
|
182
|
+
progress?: {
|
|
183
|
+
milestones: { done: number; total: number };
|
|
184
|
+
slices?: { done: number; total: number };
|
|
185
|
+
tasks?: { done: number; total: number };
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
// ─── Post-Unit Hook Types ─────────────────────────────────────────────────
|
|
190
|
+
|
|
191
|
+
export interface PostUnitHookConfig {
|
|
192
|
+
/** Unique hook identifier — used in idempotency keys and logging. */
|
|
193
|
+
name: string;
|
|
194
|
+
/** Unit types that trigger this hook (e.g., ["execute-task"]). */
|
|
195
|
+
after: string[];
|
|
196
|
+
/** Prompt sent to the LLM session. Supports {milestoneId}, {sliceId}, {taskId} substitutions. */
|
|
197
|
+
prompt: string;
|
|
198
|
+
/** Max times this hook can fire for the same trigger unit. Default 1, max 10. */
|
|
199
|
+
max_cycles?: number;
|
|
200
|
+
/** Model override for hook sessions. */
|
|
201
|
+
model?: string;
|
|
202
|
+
/** Expected output file name (relative to task/slice dir). Used for idempotency — skip if exists. */
|
|
203
|
+
artifact?: string;
|
|
204
|
+
/** If this file is produced instead of artifact, re-run the trigger unit then re-run hooks. */
|
|
205
|
+
retry_on?: string;
|
|
206
|
+
/** Agent definition file to use. */
|
|
207
|
+
agent?: string;
|
|
208
|
+
/** Set false to disable without removing config. Default true. */
|
|
209
|
+
enabled?: boolean;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
export interface HookExecutionState {
|
|
213
|
+
/** Hook name. */
|
|
214
|
+
hookName: string;
|
|
215
|
+
/** The unit type that triggered this hook. */
|
|
216
|
+
triggerUnitType: string;
|
|
217
|
+
/** The unit ID that triggered this hook. */
|
|
218
|
+
triggerUnitId: string;
|
|
219
|
+
/** Current cycle (1-based). */
|
|
220
|
+
cycle: number;
|
|
221
|
+
/** Whether the hook completed with a retry signal (retry_on artifact found). */
|
|
222
|
+
pendingRetry: boolean;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
export interface HookDispatchResult {
|
|
226
|
+
/** Hook name for display. */
|
|
227
|
+
hookName: string;
|
|
228
|
+
/** The prompt to send. */
|
|
229
|
+
prompt: string;
|
|
230
|
+
/** Model override, if configured. */
|
|
231
|
+
model?: string;
|
|
232
|
+
/** Synthetic unit type, e.g. "hook/code-review". */
|
|
233
|
+
unitType: string;
|
|
234
|
+
/** The trigger unit's ID, reused for the hook. */
|
|
235
|
+
unitId: string;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
// ─── Pre-Dispatch Hook Types ──────────────────────────────────────────────
|
|
239
|
+
|
|
240
|
+
export interface PreDispatchHookConfig {
|
|
241
|
+
/** Unique hook identifier. */
|
|
242
|
+
name: string;
|
|
243
|
+
/** Unit types this hook intercepts before dispatch (e.g., ["execute-task"]). */
|
|
244
|
+
before: string[];
|
|
245
|
+
/** Action to take: "modify" mutates the prompt, "skip" skips the unit, "replace" swaps it. */
|
|
246
|
+
action: 'modify' | 'skip' | 'replace';
|
|
247
|
+
/** For "modify": text prepended to the unit prompt. Supports {milestoneId}, {sliceId}, {taskId}. */
|
|
248
|
+
prepend?: string;
|
|
249
|
+
/** For "modify": text appended to the unit prompt. Supports {milestoneId}, {sliceId}, {taskId}. */
|
|
250
|
+
append?: string;
|
|
251
|
+
/** For "replace": the replacement prompt. Supports {milestoneId}, {sliceId}, {taskId}. */
|
|
252
|
+
prompt?: string;
|
|
253
|
+
/** For "replace": override the unit type label. */
|
|
254
|
+
unit_type?: string;
|
|
255
|
+
/** For "skip": optional condition file — only skip if this file exists (relative to unit dir). */
|
|
256
|
+
skip_if?: string;
|
|
257
|
+
/** Model override when this hook fires. */
|
|
258
|
+
model?: string;
|
|
259
|
+
/** Set false to disable without removing config. Default true. */
|
|
260
|
+
enabled?: boolean;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
export interface PreDispatchResult {
|
|
264
|
+
/** What happened: the unit proceeds with modifications, was skipped, or was replaced. */
|
|
265
|
+
action: 'proceed' | 'skip' | 'replace';
|
|
266
|
+
/** Modified/replacement prompt (for "proceed" and "replace"). */
|
|
267
|
+
prompt?: string;
|
|
268
|
+
/** Override unit type (for "replace"). */
|
|
269
|
+
unitType?: string;
|
|
270
|
+
/** Model override. */
|
|
271
|
+
model?: string;
|
|
272
|
+
/** Names of hooks that fired, for logging. */
|
|
273
|
+
firedHooks: string[];
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
// ─── Hook State Persistence Types ─────────────────────────────────────────
|
|
277
|
+
|
|
278
|
+
export interface PersistedHookState {
|
|
279
|
+
/** Cycle counts keyed as "hookName/triggerUnitType/triggerUnitId". */
|
|
280
|
+
cycleCounts: Record<string, number>;
|
|
281
|
+
/** Timestamp of last state save. */
|
|
282
|
+
savedAt: string;
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
export interface HookStatusEntry {
|
|
286
|
+
/** Hook name. */
|
|
287
|
+
name: string;
|
|
288
|
+
/** Hook type: "post" or "pre". */
|
|
289
|
+
type: 'post' | 'pre';
|
|
290
|
+
/** Whether hook is enabled. */
|
|
291
|
+
enabled: boolean;
|
|
292
|
+
/** What unit types it targets. */
|
|
293
|
+
targets: string[];
|
|
294
|
+
/** Current cycle counts for active triggers. */
|
|
295
|
+
activeCycles: Record<string, number>;
|
|
296
|
+
}
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
import { existsSync, mkdirSync, readdirSync, readFileSync, writeFileSync, unlinkSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import {
|
|
4
|
+
gsdRoot,
|
|
5
|
+
relSliceFile,
|
|
6
|
+
relTaskFile,
|
|
7
|
+
resolveSliceFile,
|
|
8
|
+
resolveTaskFile,
|
|
9
|
+
} from "./paths.js";
|
|
10
|
+
import { loadFile, parseTaskPlanMustHaves, countMustHavesMentionedInSummary } from "./files.js";
|
|
11
|
+
|
|
12
|
+
export type UnitRuntimePhase =
|
|
13
|
+
| "dispatched"
|
|
14
|
+
| "wrapup-warning-sent"
|
|
15
|
+
| "timeout"
|
|
16
|
+
| "recovered"
|
|
17
|
+
| "finalized"
|
|
18
|
+
| "paused"
|
|
19
|
+
| "skipped";
|
|
20
|
+
|
|
21
|
+
export interface ExecuteTaskRecoveryStatus {
|
|
22
|
+
planPath: string;
|
|
23
|
+
summaryPath: string;
|
|
24
|
+
summaryExists: boolean;
|
|
25
|
+
taskChecked: boolean;
|
|
26
|
+
nextActionAdvanced: boolean;
|
|
27
|
+
mustHaveCount: number;
|
|
28
|
+
mustHavesMentionedInSummary: number;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export interface AutoUnitRuntimeRecord {
|
|
32
|
+
version: 1;
|
|
33
|
+
unitType: string;
|
|
34
|
+
unitId: string;
|
|
35
|
+
startedAt: number;
|
|
36
|
+
updatedAt: number;
|
|
37
|
+
phase: UnitRuntimePhase;
|
|
38
|
+
wrapupWarningSent: boolean;
|
|
39
|
+
timeoutAt: number | null;
|
|
40
|
+
lastProgressAt: number;
|
|
41
|
+
progressCount: number;
|
|
42
|
+
lastProgressKind: string;
|
|
43
|
+
recovery?: ExecuteTaskRecoveryStatus;
|
|
44
|
+
recoveryAttempts?: number;
|
|
45
|
+
lastRecoveryReason?: "idle" | "hard";
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function runtimeDir(basePath: string): string {
|
|
49
|
+
return join(gsdRoot(basePath), "runtime", "units");
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function runtimePath(basePath: string, unitType: string, unitId: string): string {
|
|
53
|
+
return join(runtimeDir(basePath), `${unitType}-${unitId.replace(/[\/]/g, "-")}.json`);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export function writeUnitRuntimeRecord(
|
|
57
|
+
basePath: string,
|
|
58
|
+
unitType: string,
|
|
59
|
+
unitId: string,
|
|
60
|
+
startedAt: number,
|
|
61
|
+
updates: Partial<AutoUnitRuntimeRecord> = {},
|
|
62
|
+
): AutoUnitRuntimeRecord {
|
|
63
|
+
const dir = runtimeDir(basePath);
|
|
64
|
+
mkdirSync(dir, { recursive: true });
|
|
65
|
+
const path = runtimePath(basePath, unitType, unitId);
|
|
66
|
+
const prev = readUnitRuntimeRecord(basePath, unitType, unitId);
|
|
67
|
+
const next: AutoUnitRuntimeRecord = {
|
|
68
|
+
version: 1,
|
|
69
|
+
unitType,
|
|
70
|
+
unitId,
|
|
71
|
+
startedAt,
|
|
72
|
+
updatedAt: Date.now(),
|
|
73
|
+
phase: updates.phase ?? prev?.phase ?? "dispatched",
|
|
74
|
+
wrapupWarningSent: updates.wrapupWarningSent ?? prev?.wrapupWarningSent ?? false,
|
|
75
|
+
timeoutAt: updates.timeoutAt ?? prev?.timeoutAt ?? null,
|
|
76
|
+
lastProgressAt: updates.lastProgressAt ?? prev?.lastProgressAt ?? Date.now(),
|
|
77
|
+
progressCount: updates.progressCount ?? prev?.progressCount ?? 0,
|
|
78
|
+
lastProgressKind: updates.lastProgressKind ?? prev?.lastProgressKind ?? "dispatch",
|
|
79
|
+
recovery: updates.recovery ?? prev?.recovery,
|
|
80
|
+
recoveryAttempts: updates.recoveryAttempts ?? prev?.recoveryAttempts ?? 0,
|
|
81
|
+
lastRecoveryReason: updates.lastRecoveryReason ?? prev?.lastRecoveryReason,
|
|
82
|
+
};
|
|
83
|
+
writeFileSync(path, JSON.stringify(next, null, 2) + "\n", "utf-8");
|
|
84
|
+
return next;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export function readUnitRuntimeRecord(basePath: string, unitType: string, unitId: string): AutoUnitRuntimeRecord | null {
|
|
88
|
+
const path = runtimePath(basePath, unitType, unitId);
|
|
89
|
+
if (!existsSync(path)) return null;
|
|
90
|
+
try {
|
|
91
|
+
return JSON.parse(readFileSync(path, "utf-8")) as AutoUnitRuntimeRecord;
|
|
92
|
+
} catch {
|
|
93
|
+
return null;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
export function clearUnitRuntimeRecord(basePath: string, unitType: string, unitId: string): void {
|
|
98
|
+
const path = runtimePath(basePath, unitType, unitId);
|
|
99
|
+
if (existsSync(path)) unlinkSync(path);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Return all runtime records currently on disk for `basePath`.
|
|
104
|
+
* Returns an empty array if the runtime directory does not exist.
|
|
105
|
+
*/
|
|
106
|
+
export function listUnitRuntimeRecords(basePath: string): AutoUnitRuntimeRecord[] {
|
|
107
|
+
const dir = runtimeDir(basePath);
|
|
108
|
+
if (!existsSync(dir)) return [];
|
|
109
|
+
const results: AutoUnitRuntimeRecord[] = [];
|
|
110
|
+
for (const file of readdirSync(dir)) {
|
|
111
|
+
if (!file.endsWith(".json")) continue;
|
|
112
|
+
try {
|
|
113
|
+
const raw = readFileSync(join(dir, file), "utf-8");
|
|
114
|
+
const record = JSON.parse(raw) as AutoUnitRuntimeRecord;
|
|
115
|
+
results.push(record);
|
|
116
|
+
} catch {
|
|
117
|
+
// Skip malformed files
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
return results;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
export async function inspectExecuteTaskDurability(
|
|
124
|
+
basePath: string,
|
|
125
|
+
unitId: string,
|
|
126
|
+
): Promise<ExecuteTaskRecoveryStatus | null> {
|
|
127
|
+
const [mid, sid, tid] = unitId.split("/");
|
|
128
|
+
if (!mid || !sid || !tid) return null;
|
|
129
|
+
|
|
130
|
+
const planAbs = resolveSliceFile(basePath, mid, sid, "PLAN");
|
|
131
|
+
const summaryAbs = resolveTaskFile(basePath, mid, sid, tid, "SUMMARY");
|
|
132
|
+
const stateAbs = join(gsdRoot(basePath), "STATE.md");
|
|
133
|
+
|
|
134
|
+
const planPath = relSliceFile(basePath, mid, sid, "PLAN");
|
|
135
|
+
const summaryPath = relTaskFile(basePath, mid, sid, tid, "SUMMARY");
|
|
136
|
+
|
|
137
|
+
const planContent = planAbs ? await loadFile(planAbs) : null;
|
|
138
|
+
const stateContent = existsSync(stateAbs) ? readFileSync(stateAbs, "utf-8") : "";
|
|
139
|
+
const summaryExists = !!(summaryAbs && existsSync(summaryAbs));
|
|
140
|
+
|
|
141
|
+
const escapedTid = tid.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
142
|
+
const taskChecked = !!planContent && new RegExp(`^- \\[[xX]\\] \\*\\*${escapedTid}:`, "m").test(planContent);
|
|
143
|
+
const nextActionAdvanced = !new RegExp(`Execute ${tid}\\b`).test(stateContent);
|
|
144
|
+
|
|
145
|
+
// Must-have coverage: load task plan and count mentions in summary
|
|
146
|
+
let mustHaveCount = 0;
|
|
147
|
+
let mustHavesMentionedInSummary = 0;
|
|
148
|
+
|
|
149
|
+
const taskPlanAbs = resolveTaskFile(basePath, mid, sid, tid, "PLAN");
|
|
150
|
+
if (taskPlanAbs) {
|
|
151
|
+
const taskPlanContent = await loadFile(taskPlanAbs);
|
|
152
|
+
if (taskPlanContent) {
|
|
153
|
+
const mustHaves = parseTaskPlanMustHaves(taskPlanContent);
|
|
154
|
+
mustHaveCount = mustHaves.length;
|
|
155
|
+
if (mustHaveCount > 0 && summaryExists && summaryAbs) {
|
|
156
|
+
const summaryContent = await loadFile(summaryAbs);
|
|
157
|
+
if (summaryContent) {
|
|
158
|
+
mustHavesMentionedInSummary = countMustHavesMentionedInSummary(mustHaves, summaryContent);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
return {
|
|
165
|
+
planPath,
|
|
166
|
+
summaryPath,
|
|
167
|
+
summaryExists,
|
|
168
|
+
taskChecked,
|
|
169
|
+
nextActionAdvanced,
|
|
170
|
+
mustHaveCount,
|
|
171
|
+
mustHavesMentionedInSummary,
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
export function formatExecuteTaskRecoveryStatus(status: ExecuteTaskRecoveryStatus): string {
|
|
176
|
+
const missing = [] as string[];
|
|
177
|
+
if (!status.summaryExists) missing.push(`summary missing (${status.summaryPath})`);
|
|
178
|
+
if (!status.taskChecked) missing.push(`task checkbox unchecked in ${status.planPath}`);
|
|
179
|
+
if (!status.nextActionAdvanced) missing.push("state next action still points at the timed-out task");
|
|
180
|
+
if (status.mustHaveCount > 0 && status.mustHavesMentionedInSummary < status.mustHaveCount) {
|
|
181
|
+
missing.push(`must-have gap: ${status.mustHavesMentionedInSummary} of ${status.mustHaveCount} must-haves addressed in summary`);
|
|
182
|
+
}
|
|
183
|
+
return missing.length > 0 ? missing.join("; ") : "all durable task artifacts present";
|
|
184
|
+
}
|