gsd-remix 1.0.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/LICENSE +21 -0
- package/README.md +939 -0
- package/README.zh-CN.md +876 -0
- package/agents/gsd-advisor-researcher.md +127 -0
- package/agents/gsd-ai-researcher.md +133 -0
- package/agents/gsd-assumptions-analyzer.md +105 -0
- package/agents/gsd-code-fixer.md +517 -0
- package/agents/gsd-code-reviewer.md +371 -0
- package/agents/gsd-codebase-mapper.md +781 -0
- package/agents/gsd-debug-session-manager.md +314 -0
- package/agents/gsd-debugger.md +1452 -0
- package/agents/gsd-doc-classifier.md +168 -0
- package/agents/gsd-doc-synthesizer.md +204 -0
- package/agents/gsd-doc-verifier.md +217 -0
- package/agents/gsd-doc-writer.md +615 -0
- package/agents/gsd-domain-researcher.md +153 -0
- package/agents/gsd-eval-auditor.md +191 -0
- package/agents/gsd-eval-planner.md +154 -0
- package/agents/gsd-executor.md +603 -0
- package/agents/gsd-framework-selector.md +160 -0
- package/agents/gsd-integration-checker.md +470 -0
- package/agents/gsd-intel-updater.md +334 -0
- package/agents/gsd-nyquist-auditor.md +203 -0
- package/agents/gsd-pattern-mapper.md +335 -0
- package/agents/gsd-phase-researcher.md +841 -0
- package/agents/gsd-plan-checker.md +978 -0
- package/agents/gsd-planner.md +1251 -0
- package/agents/gsd-project-researcher.md +677 -0
- package/agents/gsd-research-synthesizer.md +247 -0
- package/agents/gsd-roadmapper.md +688 -0
- package/agents/gsd-security-auditor.md +155 -0
- package/agents/gsd-ui-auditor.md +495 -0
- package/agents/gsd-ui-checker.md +309 -0
- package/agents/gsd-ui-researcher.md +380 -0
- package/agents/gsd-user-profiler.md +171 -0
- package/agents/gsd-verifier.md +830 -0
- package/bin/install.js +7062 -0
- package/commands/gsd/add-backlog.md +79 -0
- package/commands/gsd/add-phase.md +43 -0
- package/commands/gsd/add-tests.md +41 -0
- package/commands/gsd/add-todo.md +47 -0
- package/commands/gsd/ai-integration-phase.md +36 -0
- package/commands/gsd/analyze-dependencies.md +34 -0
- package/commands/gsd/audit-fix.md +33 -0
- package/commands/gsd/audit-milestone.md +36 -0
- package/commands/gsd/audit-uat.md +24 -0
- package/commands/gsd/autonomous.md +46 -0
- package/commands/gsd/check-todos.md +45 -0
- package/commands/gsd/cleanup.md +23 -0
- package/commands/gsd/code-review-fix.md +52 -0
- package/commands/gsd/code-review.md +55 -0
- package/commands/gsd/complete-milestone.md +136 -0
- package/commands/gsd/debug.md +263 -0
- package/commands/gsd/discuss-phase.md +69 -0
- package/commands/gsd/do.md +30 -0
- package/commands/gsd/docs-update.md +48 -0
- package/commands/gsd/eval-review.md +32 -0
- package/commands/gsd/execute-phase.md +63 -0
- package/commands/gsd/explore.md +27 -0
- package/commands/gsd/extract_learnings.md +22 -0
- package/commands/gsd/fast.md +30 -0
- package/commands/gsd/forensics.md +56 -0
- package/commands/gsd/from-gsd2.md +47 -0
- package/commands/gsd/graphify.md +201 -0
- package/commands/gsd/health.md +22 -0
- package/commands/gsd/help.md +24 -0
- package/commands/gsd/import.md +37 -0
- package/commands/gsd/inbox.md +38 -0
- package/commands/gsd/ingest-docs.md +42 -0
- package/commands/gsd/insert-phase.md +32 -0
- package/commands/gsd/intel.md +179 -0
- package/commands/gsd/join-discord.md +19 -0
- package/commands/gsd/list-phase-assumptions.md +46 -0
- package/commands/gsd/list-workspaces.md +19 -0
- package/commands/gsd/manager.md +40 -0
- package/commands/gsd/map-codebase.md +71 -0
- package/commands/gsd/milestone-summary.md +51 -0
- package/commands/gsd/new-milestone.md +44 -0
- package/commands/gsd/new-project.md +46 -0
- package/commands/gsd/new-workspace.md +44 -0
- package/commands/gsd/next.md +28 -0
- package/commands/gsd/note.md +34 -0
- package/commands/gsd/pause-work.md +38 -0
- package/commands/gsd/plan-milestone-gaps.md +34 -0
- package/commands/gsd/plan-phase.md +52 -0
- package/commands/gsd/plan-review-convergence.md +52 -0
- package/commands/gsd/plant-seed.md +28 -0
- package/commands/gsd/pr-branch.md +25 -0
- package/commands/gsd/profile-user.md +46 -0
- package/commands/gsd/progress.md +25 -0
- package/commands/gsd/quick.md +173 -0
- package/commands/gsd/reapply-patches.md +331 -0
- package/commands/gsd/remove-phase.md +31 -0
- package/commands/gsd/remove-workspace.md +26 -0
- package/commands/gsd/research-phase.md +195 -0
- package/commands/gsd/resume-work.md +40 -0
- package/commands/gsd/review-backlog.md +62 -0
- package/commands/gsd/review.md +40 -0
- package/commands/gsd/scan.md +26 -0
- package/commands/gsd/secure-phase.md +35 -0
- package/commands/gsd/session-report.md +19 -0
- package/commands/gsd/set-profile.md +12 -0
- package/commands/gsd/settings.md +36 -0
- package/commands/gsd/ship.md +23 -0
- package/commands/gsd/sketch-wrap-up.md +31 -0
- package/commands/gsd/sketch.md +49 -0
- package/commands/gsd/spec-phase.md +62 -0
- package/commands/gsd/spike-wrap-up.md +31 -0
- package/commands/gsd/spike.md +46 -0
- package/commands/gsd/stats.md +18 -0
- package/commands/gsd/sync-skills.md +19 -0
- package/commands/gsd/thread.md +227 -0
- package/commands/gsd/ui-phase.md +34 -0
- package/commands/gsd/ui-review.md +32 -0
- package/commands/gsd/ultraplan-phase.md +33 -0
- package/commands/gsd/undo.md +34 -0
- package/commands/gsd/update.md +37 -0
- package/commands/gsd/validate-phase.md +35 -0
- package/commands/gsd/verify-work.md +38 -0
- package/commands/gsd/workstreams.md +69 -0
- package/get-shit-done/bin/gsd-tools.cjs +1263 -0
- package/get-shit-done/bin/lib/artifacts.cjs +52 -0
- package/get-shit-done/bin/lib/audit.cjs +757 -0
- package/get-shit-done/bin/lib/commands.cjs +1023 -0
- package/get-shit-done/bin/lib/config-schema.cjs +79 -0
- package/get-shit-done/bin/lib/config.cjs +463 -0
- package/get-shit-done/bin/lib/core.cjs +1794 -0
- package/get-shit-done/bin/lib/docs.cjs +267 -0
- package/get-shit-done/bin/lib/frontmatter.cjs +379 -0
- package/get-shit-done/bin/lib/graphify.cjs +494 -0
- package/get-shit-done/bin/lib/gsd2-import.cjs +511 -0
- package/get-shit-done/bin/lib/init.cjs +1878 -0
- package/get-shit-done/bin/lib/intel.cjs +639 -0
- package/get-shit-done/bin/lib/learnings.cjs +378 -0
- package/get-shit-done/bin/lib/milestone.cjs +283 -0
- package/get-shit-done/bin/lib/model-profiles.cjs +71 -0
- package/get-shit-done/bin/lib/phase.cjs +1058 -0
- package/get-shit-done/bin/lib/profile-output.cjs +1080 -0
- package/get-shit-done/bin/lib/profile-pipeline.cjs +539 -0
- package/get-shit-done/bin/lib/roadmap.cjs +523 -0
- package/get-shit-done/bin/lib/schema-detect.cjs +238 -0
- package/get-shit-done/bin/lib/security.cjs +504 -0
- package/get-shit-done/bin/lib/state.cjs +1649 -0
- package/get-shit-done/bin/lib/template.cjs +226 -0
- package/get-shit-done/bin/lib/uat.cjs +288 -0
- package/get-shit-done/bin/lib/verify.cjs +1184 -0
- package/get-shit-done/bin/lib/workstream.cjs +495 -0
- package/get-shit-done/bin/repair-sdk.cjs +177 -0
- package/get-shit-done/contexts/dev.md +21 -0
- package/get-shit-done/contexts/research.md +22 -0
- package/get-shit-done/contexts/review.md +22 -0
- package/get-shit-done/references/agent-contracts.md +79 -0
- package/get-shit-done/references/ai-evals.md +156 -0
- package/get-shit-done/references/ai-frameworks.md +186 -0
- package/get-shit-done/references/artifact-types.md +131 -0
- package/get-shit-done/references/autonomous-smart-discuss.md +277 -0
- package/get-shit-done/references/checkpoints.md +808 -0
- package/get-shit-done/references/common-bug-patterns.md +114 -0
- package/get-shit-done/references/context-budget.md +49 -0
- package/get-shit-done/references/continuation-format.md +253 -0
- package/get-shit-done/references/debugger-philosophy.md +76 -0
- package/get-shit-done/references/decimal-phase-calculation.md +64 -0
- package/get-shit-done/references/doc-conflict-engine.md +91 -0
- package/get-shit-done/references/domain-probes.md +125 -0
- package/get-shit-done/references/executor-examples.md +110 -0
- package/get-shit-done/references/few-shot-examples/plan-checker.md +73 -0
- package/get-shit-done/references/few-shot-examples/verifier.md +109 -0
- package/get-shit-done/references/gate-prompts.md +100 -0
- package/get-shit-done/references/gates.md +70 -0
- package/get-shit-done/references/git-integration.md +295 -0
- package/get-shit-done/references/git-planning-commit.md +40 -0
- package/get-shit-done/references/ios-scaffold.md +123 -0
- package/get-shit-done/references/mandatory-initial-read.md +2 -0
- package/get-shit-done/references/model-profile-resolution.md +38 -0
- package/get-shit-done/references/model-profiles.md +145 -0
- package/get-shit-done/references/phase-argument-parsing.md +61 -0
- package/get-shit-done/references/planner-antipatterns.md +89 -0
- package/get-shit-done/references/planner-gap-closure.md +62 -0
- package/get-shit-done/references/planner-reviews.md +39 -0
- package/get-shit-done/references/planner-revision.md +87 -0
- package/get-shit-done/references/planner-source-audit.md +73 -0
- package/get-shit-done/references/planning-config.md +460 -0
- package/get-shit-done/references/project-skills-discovery.md +19 -0
- package/get-shit-done/references/questioning.md +162 -0
- package/get-shit-done/references/revision-loop.md +97 -0
- package/get-shit-done/references/sketch-interactivity.md +41 -0
- package/get-shit-done/references/sketch-theme-system.md +94 -0
- package/get-shit-done/references/sketch-tooling.md +45 -0
- package/get-shit-done/references/sketch-variant-patterns.md +81 -0
- package/get-shit-done/references/tdd.md +330 -0
- package/get-shit-done/references/thinking-models-debug.md +44 -0
- package/get-shit-done/references/thinking-models-execution.md +50 -0
- package/get-shit-done/references/thinking-models-planning.md +62 -0
- package/get-shit-done/references/thinking-models-research.md +50 -0
- package/get-shit-done/references/thinking-models-verification.md +55 -0
- package/get-shit-done/references/thinking-partner.md +96 -0
- package/get-shit-done/references/ui-brand.md +160 -0
- package/get-shit-done/references/universal-anti-patterns.md +63 -0
- package/get-shit-done/references/user-profiling.md +681 -0
- package/get-shit-done/references/verification-overrides.md +227 -0
- package/get-shit-done/references/verification-patterns.md +612 -0
- package/get-shit-done/references/workstream-flag.md +111 -0
- package/get-shit-done/templates/AI-SPEC.md +246 -0
- package/get-shit-done/templates/DEBUG.md +169 -0
- package/get-shit-done/templates/README.md +76 -0
- package/get-shit-done/templates/SECURITY.md +61 -0
- package/get-shit-done/templates/UAT.md +265 -0
- package/get-shit-done/templates/UI-SPEC.md +100 -0
- package/get-shit-done/templates/VALIDATION.md +76 -0
- package/get-shit-done/templates/claude-md.md +145 -0
- package/get-shit-done/templates/codebase/architecture.md +255 -0
- package/get-shit-done/templates/codebase/concerns.md +310 -0
- package/get-shit-done/templates/codebase/conventions.md +307 -0
- package/get-shit-done/templates/codebase/integrations.md +280 -0
- package/get-shit-done/templates/codebase/stack.md +186 -0
- package/get-shit-done/templates/codebase/structure.md +285 -0
- package/get-shit-done/templates/codebase/testing.md +480 -0
- package/get-shit-done/templates/config.json +56 -0
- package/get-shit-done/templates/context.md +352 -0
- package/get-shit-done/templates/continue-here.md +78 -0
- package/get-shit-done/templates/copilot-instructions.md +7 -0
- package/get-shit-done/templates/debug-subagent-prompt.md +91 -0
- package/get-shit-done/templates/dev-preferences.md +21 -0
- package/get-shit-done/templates/discovery.md +146 -0
- package/get-shit-done/templates/discussion-log.md +63 -0
- package/get-shit-done/templates/milestone-archive.md +123 -0
- package/get-shit-done/templates/milestone.md +115 -0
- package/get-shit-done/templates/phase-prompt.md +610 -0
- package/get-shit-done/templates/planner-subagent-prompt.md +117 -0
- package/get-shit-done/templates/project.md +186 -0
- package/get-shit-done/templates/requirements.md +231 -0
- package/get-shit-done/templates/research-project/ARCHITECTURE.md +204 -0
- package/get-shit-done/templates/research-project/FEATURES.md +147 -0
- package/get-shit-done/templates/research-project/PITFALLS.md +200 -0
- package/get-shit-done/templates/research-project/STACK.md +120 -0
- package/get-shit-done/templates/research-project/SUMMARY.md +170 -0
- package/get-shit-done/templates/research.md +592 -0
- package/get-shit-done/templates/retrospective.md +54 -0
- package/get-shit-done/templates/roadmap.md +202 -0
- package/get-shit-done/templates/spec.md +307 -0
- package/get-shit-done/templates/state.md +184 -0
- package/get-shit-done/templates/summary-complex.md +59 -0
- package/get-shit-done/templates/summary-minimal.md +41 -0
- package/get-shit-done/templates/summary-standard.md +48 -0
- package/get-shit-done/templates/summary.md +248 -0
- package/get-shit-done/templates/user-profile.md +146 -0
- package/get-shit-done/templates/user-setup.md +311 -0
- package/get-shit-done/templates/verification-report.md +322 -0
- package/get-shit-done/workflows/add-phase.md +112 -0
- package/get-shit-done/workflows/add-tests.md +354 -0
- package/get-shit-done/workflows/add-todo.md +160 -0
- package/get-shit-done/workflows/ai-integration-phase.md +284 -0
- package/get-shit-done/workflows/analyze-dependencies.md +96 -0
- package/get-shit-done/workflows/audit-fix.md +175 -0
- package/get-shit-done/workflows/audit-milestone.md +340 -0
- package/get-shit-done/workflows/audit-uat.md +109 -0
- package/get-shit-done/workflows/autonomous.md +789 -0
- package/get-shit-done/workflows/check-todos.md +179 -0
- package/get-shit-done/workflows/cleanup.md +154 -0
- package/get-shit-done/workflows/code-review-fix.md +497 -0
- package/get-shit-done/workflows/code-review.md +515 -0
- package/get-shit-done/workflows/complete-milestone.md +847 -0
- package/get-shit-done/workflows/diagnose-issues.md +238 -0
- package/get-shit-done/workflows/discovery-phase.md +291 -0
- package/get-shit-done/workflows/discuss-phase-assumptions.md +670 -0
- package/get-shit-done/workflows/discuss-phase-power.md +308 -0
- package/get-shit-done/workflows/discuss-phase.md +1378 -0
- package/get-shit-done/workflows/do.md +110 -0
- package/get-shit-done/workflows/docs-update.md +1155 -0
- package/get-shit-done/workflows/eval-review.md +155 -0
- package/get-shit-done/workflows/execute-phase.md +1677 -0
- package/get-shit-done/workflows/execute-plan.md +533 -0
- package/get-shit-done/workflows/explore.md +141 -0
- package/get-shit-done/workflows/extract_learnings.md +242 -0
- package/get-shit-done/workflows/fast.md +105 -0
- package/get-shit-done/workflows/forensics.md +265 -0
- package/get-shit-done/workflows/graduation.md +195 -0
- package/get-shit-done/workflows/health.md +314 -0
- package/get-shit-done/workflows/help.md +667 -0
- package/get-shit-done/workflows/import.md +246 -0
- package/get-shit-done/workflows/inbox.md +387 -0
- package/get-shit-done/workflows/ingest-docs.md +328 -0
- package/get-shit-done/workflows/insert-phase.md +130 -0
- package/get-shit-done/workflows/list-phase-assumptions.md +178 -0
- package/get-shit-done/workflows/list-workspaces.md +56 -0
- package/get-shit-done/workflows/manager.md +365 -0
- package/get-shit-done/workflows/map-codebase.md +393 -0
- package/get-shit-done/workflows/milestone-summary.md +223 -0
- package/get-shit-done/workflows/new-milestone.md +611 -0
- package/get-shit-done/workflows/new-project.md +1391 -0
- package/get-shit-done/workflows/new-workspace.md +239 -0
- package/get-shit-done/workflows/next.md +220 -0
- package/get-shit-done/workflows/node-repair.md +92 -0
- package/get-shit-done/workflows/note.md +158 -0
- package/get-shit-done/workflows/pause-work.md +243 -0
- package/get-shit-done/workflows/plan-milestone-gaps.md +273 -0
- package/get-shit-done/workflows/plan-phase.md +1349 -0
- package/get-shit-done/workflows/plan-review-convergence.md +254 -0
- package/get-shit-done/workflows/plant-seed.md +172 -0
- package/get-shit-done/workflows/pr-branch.md +157 -0
- package/get-shit-done/workflows/profile-user.md +452 -0
- package/get-shit-done/workflows/progress.md +619 -0
- package/get-shit-done/workflows/quick.md +970 -0
- package/get-shit-done/workflows/remove-phase.md +155 -0
- package/get-shit-done/workflows/remove-workspace.md +92 -0
- package/get-shit-done/workflows/research-phase.md +89 -0
- package/get-shit-done/workflows/resume-project.md +326 -0
- package/get-shit-done/workflows/review.md +344 -0
- package/get-shit-done/workflows/scan.md +102 -0
- package/get-shit-done/workflows/secure-phase.md +166 -0
- package/get-shit-done/workflows/session-report.md +146 -0
- package/get-shit-done/workflows/settings.md +319 -0
- package/get-shit-done/workflows/ship.md +302 -0
- package/get-shit-done/workflows/sketch-wrap-up.md +283 -0
- package/get-shit-done/workflows/sketch.md +286 -0
- package/get-shit-done/workflows/spec-phase.md +262 -0
- package/get-shit-done/workflows/spike-wrap-up.md +281 -0
- package/get-shit-done/workflows/spike.md +362 -0
- package/get-shit-done/workflows/stats.md +60 -0
- package/get-shit-done/workflows/sync-skills.md +182 -0
- package/get-shit-done/workflows/transition.md +693 -0
- package/get-shit-done/workflows/ui-phase.md +323 -0
- package/get-shit-done/workflows/ui-review.md +190 -0
- package/get-shit-done/workflows/ultraplan-phase.md +189 -0
- package/get-shit-done/workflows/undo.md +314 -0
- package/get-shit-done/workflows/update.md +587 -0
- package/get-shit-done/workflows/validate-phase.md +176 -0
- package/get-shit-done/workflows/verify-phase.md +465 -0
- package/get-shit-done/workflows/verify-work.md +740 -0
- package/hooks/dist/gsd-check-update-worker.js +108 -0
- package/hooks/dist/gsd-check-update.js +64 -0
- package/hooks/dist/gsd-context-monitor.js +192 -0
- package/hooks/dist/gsd-phase-boundary.sh +28 -0
- package/hooks/dist/gsd-prompt-guard.js +97 -0
- package/hooks/dist/gsd-read-guard.js +82 -0
- package/hooks/dist/gsd-read-injection-scanner.js +152 -0
- package/hooks/dist/gsd-session-state.sh +34 -0
- package/hooks/dist/gsd-statusline.js +293 -0
- package/hooks/dist/gsd-validate-commit.sh +48 -0
- package/hooks/dist/gsd-workflow-guard.js +94 -0
- package/hooks/gsd-check-update-worker.js +108 -0
- package/hooks/gsd-check-update.js +64 -0
- package/hooks/gsd-context-monitor.js +192 -0
- package/hooks/gsd-phase-boundary.sh +28 -0
- package/hooks/gsd-prompt-guard.js +97 -0
- package/hooks/gsd-read-guard.js +82 -0
- package/hooks/gsd-read-injection-scanner.js +152 -0
- package/hooks/gsd-session-state.sh +34 -0
- package/hooks/gsd-statusline.js +293 -0
- package/hooks/gsd-validate-commit.sh +48 -0
- package/hooks/gsd-workflow-guard.js +94 -0
- package/package.json +59 -0
- package/scripts/base64-scan.sh +262 -0
- package/scripts/build-hooks.js +95 -0
- package/scripts/gen-inventory-manifest.cjs +109 -0
- package/scripts/prompt-injection-scan.sh +201 -0
- package/scripts/run-tests.cjs +33 -0
- package/scripts/secret-scan.sh +227 -0
- package/sdk/package-lock.json +1998 -0
- package/sdk/package.json +52 -0
- package/sdk/prompts/agents/gsd-executor.md +110 -0
- package/sdk/prompts/agents/gsd-phase-researcher.md +158 -0
- package/sdk/prompts/agents/gsd-plan-checker.md +160 -0
- package/sdk/prompts/agents/gsd-planner.md +214 -0
- package/sdk/prompts/agents/gsd-project-researcher.md +323 -0
- package/sdk/prompts/agents/gsd-research-synthesizer.md +237 -0
- package/sdk/prompts/agents/gsd-roadmapper.md +670 -0
- package/sdk/prompts/agents/gsd-verifier.md +159 -0
- package/sdk/prompts/templates/project.md +186 -0
- package/sdk/prompts/templates/requirements.md +231 -0
- package/sdk/prompts/templates/research-project/ARCHITECTURE.md +204 -0
- package/sdk/prompts/templates/research-project/FEATURES.md +147 -0
- package/sdk/prompts/templates/research-project/PITFALLS.md +200 -0
- package/sdk/prompts/templates/research-project/STACK.md +120 -0
- package/sdk/prompts/templates/research-project/SUMMARY.md +170 -0
- package/sdk/prompts/templates/roadmap.md +202 -0
- package/sdk/prompts/templates/state.md +175 -0
- package/sdk/prompts/workflows/discuss-phase.md +126 -0
- package/sdk/prompts/workflows/execute-plan.md +106 -0
- package/sdk/prompts/workflows/plan-phase.md +84 -0
- package/sdk/prompts/workflows/research-phase.md +45 -0
- package/sdk/prompts/workflows/verify-phase.md +142 -0
- package/sdk/src/assembled-prompts.test.ts +349 -0
- package/sdk/src/cli-transport.test.ts +388 -0
- package/sdk/src/cli-transport.ts +130 -0
- package/sdk/src/cli.test.ts +383 -0
- package/sdk/src/cli.ts +670 -0
- package/sdk/src/config.test.ts +168 -0
- package/sdk/src/config.ts +177 -0
- package/sdk/src/context-engine.test.ts +295 -0
- package/sdk/src/context-engine.ts +170 -0
- package/sdk/src/context-truncation.test.ts +163 -0
- package/sdk/src/context-truncation.ts +233 -0
- package/sdk/src/e2e.integration.test.ts +178 -0
- package/sdk/src/errors.ts +72 -0
- package/sdk/src/event-stream.test.ts +661 -0
- package/sdk/src/event-stream.ts +441 -0
- package/sdk/src/failure-memory.test.ts +457 -0
- package/sdk/src/failure-memory.ts +1324 -0
- package/sdk/src/golden/capture.ts +95 -0
- package/sdk/src/golden/fixtures/generate-slug.golden.json +1 -0
- package/sdk/src/golden/fixtures/profile-sample-sessions/demo-project/sample.jsonl +3 -0
- package/sdk/src/golden/fixtures/summary-extract-sample.md +26 -0
- package/sdk/src/golden/fixtures/uat-render-checkpoint-sample.md +15 -0
- package/sdk/src/golden/golden-integration-covered.ts +30 -0
- package/sdk/src/golden/golden-mutation-covered.ts +7 -0
- package/sdk/src/golden/golden-policy.test.ts +8 -0
- package/sdk/src/golden/golden-policy.ts +112 -0
- package/sdk/src/golden/golden.integration.test.ts +373 -0
- package/sdk/src/golden/init-golden-normalize.ts +15 -0
- package/sdk/src/golden/read-only-golden-rows.ts +77 -0
- package/sdk/src/golden/read-only-parity.integration.test.ts +125 -0
- package/sdk/src/golden/registry-canonical-commands.ts +31 -0
- package/sdk/src/gsd-tools.test.ts +409 -0
- package/sdk/src/gsd-tools.ts +595 -0
- package/sdk/src/headless-prompts.test.ts +159 -0
- package/sdk/src/index.ts +333 -0
- package/sdk/src/init-e2e.integration.test.ts +136 -0
- package/sdk/src/init-runner.test.ts +783 -0
- package/sdk/src/init-runner.ts +735 -0
- package/sdk/src/lifecycle-e2e.integration.test.ts +258 -0
- package/sdk/src/logger.test.ts +149 -0
- package/sdk/src/logger.ts +113 -0
- package/sdk/src/milestone-runner.test.ts +421 -0
- package/sdk/src/phase-prompt.test.ts +538 -0
- package/sdk/src/phase-prompt.ts +264 -0
- package/sdk/src/phase-runner-types.test.ts +421 -0
- package/sdk/src/phase-runner.integration.test.ts +377 -0
- package/sdk/src/phase-runner.test.ts +2333 -0
- package/sdk/src/phase-runner.ts +1203 -0
- package/sdk/src/plan-parser.test.ts +528 -0
- package/sdk/src/plan-parser.ts +427 -0
- package/sdk/src/prompt-builder.test.ts +306 -0
- package/sdk/src/prompt-builder.ts +193 -0
- package/sdk/src/prompt-sanitizer.test.ts +260 -0
- package/sdk/src/prompt-sanitizer.ts +71 -0
- package/sdk/src/query/QUERY-HANDLERS.md +317 -0
- package/sdk/src/query/audit-open.ts +722 -0
- package/sdk/src/query/check-auto-mode.test.ts +77 -0
- package/sdk/src/query/check-auto-mode.ts +50 -0
- package/sdk/src/query/check-completion.test.ts +113 -0
- package/sdk/src/query/check-completion.ts +182 -0
- package/sdk/src/query/check-gates.test.ts +103 -0
- package/sdk/src/query/check-gates.ts +112 -0
- package/sdk/src/query/check-ship-ready.test.ts +77 -0
- package/sdk/src/query/check-ship-ready.ts +103 -0
- package/sdk/src/query/check-verification-status.test.ts +143 -0
- package/sdk/src/query/check-verification-status.ts +160 -0
- package/sdk/src/query/commit.test.ts +202 -0
- package/sdk/src/query/commit.ts +301 -0
- package/sdk/src/query/config-gates.test.ts +89 -0
- package/sdk/src/query/config-gates.ts +69 -0
- package/sdk/src/query/config-mutation.test.ts +365 -0
- package/sdk/src/query/config-mutation.ts +497 -0
- package/sdk/src/query/config-query.test.ts +161 -0
- package/sdk/src/query/config-query.ts +190 -0
- package/sdk/src/query/context-history.test.ts +165 -0
- package/sdk/src/query/context-history.ts +467 -0
- package/sdk/src/query/decomposed-handlers.test.ts +365 -0
- package/sdk/src/query/detect-custom-files.ts +97 -0
- package/sdk/src/query/detect-phase-type.test.ts +105 -0
- package/sdk/src/query/detect-phase-type.ts +141 -0
- package/sdk/src/query/docs-init.ts +257 -0
- package/sdk/src/query/failure-capture.ts +58 -0
- package/sdk/src/query/frontmatter-array.test.ts +14 -0
- package/sdk/src/query/frontmatter-mutation.test.ts +259 -0
- package/sdk/src/query/frontmatter-mutation.ts +343 -0
- package/sdk/src/query/frontmatter.test.ts +281 -0
- package/sdk/src/query/frontmatter.ts +397 -0
- package/sdk/src/query/helpers.test.ts +426 -0
- package/sdk/src/query/helpers.ts +482 -0
- package/sdk/src/query/index.ts +586 -0
- package/sdk/src/query/init-complex.test.ts +232 -0
- package/sdk/src/query/init-complex.ts +578 -0
- package/sdk/src/query/init.test.ts +522 -0
- package/sdk/src/query/init.ts +1046 -0
- package/sdk/src/query/intel.test.ts +90 -0
- package/sdk/src/query/intel.ts +404 -0
- package/sdk/src/query/normalize-query-command.test.ts +50 -0
- package/sdk/src/query/normalize-query-command.ts +56 -0
- package/sdk/src/query/phase-lifecycle.test.ts +1126 -0
- package/sdk/src/query/phase-lifecycle.ts +1799 -0
- package/sdk/src/query/phase-list-queries.test.ts +88 -0
- package/sdk/src/query/phase-list-queries.ts +152 -0
- package/sdk/src/query/phase-ready.test.ts +65 -0
- package/sdk/src/query/phase-ready.ts +158 -0
- package/sdk/src/query/phase.test.ts +307 -0
- package/sdk/src/query/phase.ts +340 -0
- package/sdk/src/query/pipeline.test.ts +169 -0
- package/sdk/src/query/pipeline.ts +243 -0
- package/sdk/src/query/plan-execution-route.test.ts +166 -0
- package/sdk/src/query/plan-execution-route.ts +209 -0
- package/sdk/src/query/plan-task-structure.test.ts +65 -0
- package/sdk/src/query/plan-task-structure.ts +63 -0
- package/sdk/src/query/profile-extract-messages.ts +247 -0
- package/sdk/src/query/profile-output.ts +908 -0
- package/sdk/src/query/profile-questionnaire-data.ts +181 -0
- package/sdk/src/query/profile-sample.ts +184 -0
- package/sdk/src/query/profile-scan-sessions.ts +174 -0
- package/sdk/src/query/profile.test.ts +74 -0
- package/sdk/src/query/profile.ts +337 -0
- package/sdk/src/query/progress.test.ts +156 -0
- package/sdk/src/query/progress.ts +566 -0
- package/sdk/src/query/registry.test.ts +216 -0
- package/sdk/src/query/registry.ts +174 -0
- package/sdk/src/query/requirements-extract-from-plans.test.ts +58 -0
- package/sdk/src/query/requirements-extract-from-plans.ts +86 -0
- package/sdk/src/query/roadmap-update-plan-progress.ts +132 -0
- package/sdk/src/query/roadmap.test.ts +359 -0
- package/sdk/src/query/roadmap.ts +591 -0
- package/sdk/src/query/route-next-action.test.ts +61 -0
- package/sdk/src/query/route-next-action.ts +345 -0
- package/sdk/src/query/runtime-health.ts +7 -0
- package/sdk/src/query/schema-detect.ts +189 -0
- package/sdk/src/query/skill-manifest.ts +214 -0
- package/sdk/src/query/skills.test.ts +80 -0
- package/sdk/src/query/skills.ts +62 -0
- package/sdk/src/query/state-mutation.test.ts +450 -0
- package/sdk/src/query/state-mutation.ts +1444 -0
- package/sdk/src/query/state-project-load.ts +109 -0
- package/sdk/src/query/state.test.ts +347 -0
- package/sdk/src/query/state.ts +397 -0
- package/sdk/src/query/summary.test.ts +95 -0
- package/sdk/src/query/summary.ts +296 -0
- package/sdk/src/query/template.test.ts +180 -0
- package/sdk/src/query/template.ts +242 -0
- package/sdk/src/query/uat.test.ts +77 -0
- package/sdk/src/query/uat.ts +314 -0
- package/sdk/src/query/utils.test.ts +82 -0
- package/sdk/src/query/utils.ts +92 -0
- package/sdk/src/query/validate.test.ts +656 -0
- package/sdk/src/query/validate.ts +807 -0
- package/sdk/src/query/verify.test.ts +414 -0
- package/sdk/src/query/verify.ts +645 -0
- package/sdk/src/query/websearch.test.ts +31 -0
- package/sdk/src/query/websearch.ts +82 -0
- package/sdk/src/query/workspace.test.ts +119 -0
- package/sdk/src/query/workspace.ts +131 -0
- package/sdk/src/query/workstream.test.ts +51 -0
- package/sdk/src/query/workstream.ts +434 -0
- package/sdk/src/research-gate.test.ts +190 -0
- package/sdk/src/research-gate.ts +94 -0
- package/sdk/src/runtime-health.test.ts +176 -0
- package/sdk/src/runtime-health.ts +387 -0
- package/sdk/src/session-runner.test.ts +98 -0
- package/sdk/src/session-runner.ts +299 -0
- package/sdk/src/tool-scoping.test.ts +160 -0
- package/sdk/src/tool-scoping.ts +61 -0
- package/sdk/src/types.ts +917 -0
- package/sdk/src/workstream-utils.ts +33 -0
- package/sdk/src/ws-flag.test.ts +285 -0
- package/sdk/src/ws-transport.test.ts +161 -0
- package/sdk/src/ws-transport.ts +93 -0
- package/sdk/tsconfig.json +20 -0
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unit tests for session-runner.ts
|
|
3
|
+
*
|
|
4
|
+
* Regression test for #2194: runPhaseStepSession was passing the full prompt
|
|
5
|
+
* string as both the user-visible prompt: message and systemPrompt.append,
|
|
6
|
+
* doubling the token cost on every phase step invocation.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
10
|
+
import { PhaseStepType } from './types.js';
|
|
11
|
+
import { CONFIG_DEFAULTS } from './config.js';
|
|
12
|
+
import type { GSDConfig } from './config.js';
|
|
13
|
+
|
|
14
|
+
// ─── Mock the Agent SDK ───────────────────────────────────────────────────────
|
|
15
|
+
|
|
16
|
+
// Capture the query call options so we can assert on them without making real API calls.
|
|
17
|
+
const mockQueryCalls: Array<{ prompt: string; options: Record<string, unknown> }> = [];
|
|
18
|
+
|
|
19
|
+
vi.mock('@anthropic-ai/claude-agent-sdk', () => {
|
|
20
|
+
async function* fakeQueryStream() {
|
|
21
|
+
// Yield a minimal success result message so processQueryStream completes.
|
|
22
|
+
yield {
|
|
23
|
+
type: 'result',
|
|
24
|
+
subtype: 'success',
|
|
25
|
+
session_id: 'test-session',
|
|
26
|
+
total_cost_usd: 0,
|
|
27
|
+
duration_ms: 1,
|
|
28
|
+
num_turns: 1,
|
|
29
|
+
usage: {
|
|
30
|
+
input_tokens: 10,
|
|
31
|
+
output_tokens: 5,
|
|
32
|
+
cache_read_input_tokens: 0,
|
|
33
|
+
cache_creation_input_tokens: 0,
|
|
34
|
+
},
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
return {
|
|
39
|
+
query: vi.fn((args: { prompt: string; options: Record<string, unknown> }) => {
|
|
40
|
+
mockQueryCalls.push({ prompt: args.prompt, options: args.options });
|
|
41
|
+
return fakeQueryStream();
|
|
42
|
+
}),
|
|
43
|
+
};
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
// ─── Import SUT after mock is hoisted ────────────────────────────────────────
|
|
47
|
+
|
|
48
|
+
import { runPhaseStepSession } from './session-runner.js';
|
|
49
|
+
|
|
50
|
+
// ─── Helpers ─────────────────────────────────────────────────────────────────
|
|
51
|
+
|
|
52
|
+
function makeConfig(overrides: Partial<GSDConfig> = {}): GSDConfig {
|
|
53
|
+
return { ...CONFIG_DEFAULTS, ...overrides };
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// ─── Tests ───────────────────────────────────────────────────────────────────
|
|
57
|
+
|
|
58
|
+
describe('runPhaseStepSession', () => {
|
|
59
|
+
beforeEach(() => {
|
|
60
|
+
mockQueryCalls.length = 0;
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
it('does not duplicate the prompt in both the user message and systemPrompt.append', async () => {
|
|
64
|
+
const fullPrompt = 'You are a researcher. Investigate the topic thoroughly.\n\n## Context\nDetailed instructions here...';
|
|
65
|
+
|
|
66
|
+
await runPhaseStepSession(fullPrompt, PhaseStepType.Research, makeConfig());
|
|
67
|
+
|
|
68
|
+
expect(mockQueryCalls).toHaveLength(1);
|
|
69
|
+
|
|
70
|
+
const call = mockQueryCalls[0];
|
|
71
|
+
const appendValue = (call.options.systemPrompt as { append?: string })?.append;
|
|
72
|
+
|
|
73
|
+
// The full prompt must appear in systemPrompt.append (that is its correct location).
|
|
74
|
+
expect(appendValue).toBe(fullPrompt);
|
|
75
|
+
|
|
76
|
+
// The user-visible prompt: must NOT be the full prompt — it should be a short directive.
|
|
77
|
+
expect(call.prompt).not.toBe(fullPrompt);
|
|
78
|
+
expect(call.prompt.length).toBeLessThan(fullPrompt.length);
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
it('passes the full prompt in systemPrompt.append', async () => {
|
|
82
|
+
const fullPrompt = 'Complex multi-line\nprompt with $VARIABLES and $(command) patterns.';
|
|
83
|
+
|
|
84
|
+
await runPhaseStepSession(fullPrompt, PhaseStepType.Execute, makeConfig());
|
|
85
|
+
|
|
86
|
+
const call = mockQueryCalls[0];
|
|
87
|
+
const appendValue = (call.options.systemPrompt as { append?: string })?.append;
|
|
88
|
+
|
|
89
|
+
expect(appendValue).toBe(fullPrompt);
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
it('returns a successful PlanResult', async () => {
|
|
93
|
+
const result = await runPhaseStepSession('Test prompt', PhaseStepType.Verify, makeConfig());
|
|
94
|
+
|
|
95
|
+
expect(result.success).toBe(true);
|
|
96
|
+
expect(result.sessionId).toBe('test-session');
|
|
97
|
+
});
|
|
98
|
+
});
|
|
@@ -0,0 +1,299 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Session runner — orchestrates Agent SDK query() calls for plan execution.
|
|
3
|
+
*
|
|
4
|
+
* Takes a parsed plan, builds the executor prompt, configures query() options,
|
|
5
|
+
* processes the message stream, and extracts results into a typed PlanResult.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { query } from '@anthropic-ai/claude-agent-sdk';
|
|
9
|
+
import type { SDKMessage, SDKResultMessage, SDKResultSuccess, SDKResultError } from '@anthropic-ai/claude-agent-sdk';
|
|
10
|
+
import type { ParsedPlan, PlanResult, SessionOptions, SessionUsage, GSDCostUpdateEvent, PhaseStepType } from './types.js';
|
|
11
|
+
import { GSDEventType, PhaseType } from './types.js';
|
|
12
|
+
import type { GSDConfig } from './config.js';
|
|
13
|
+
import { buildExecutorPrompt, parseAgentTools, DEFAULT_ALLOWED_TOOLS } from './prompt-builder.js';
|
|
14
|
+
import type { GSDEventStream, EventStreamContext } from './event-stream.js';
|
|
15
|
+
import { getToolsForPhase } from './tool-scoping.js';
|
|
16
|
+
|
|
17
|
+
// ─── Model resolution ────────────────────────────────────────────────────────
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Resolve model identifier from options or config profile.
|
|
21
|
+
*
|
|
22
|
+
* Priority: explicit model option > config model_profile > default.
|
|
23
|
+
*/
|
|
24
|
+
function resolveModel(options?: SessionOptions, config?: GSDConfig): string | undefined {
|
|
25
|
+
if (options?.model) return options.model;
|
|
26
|
+
|
|
27
|
+
// Map model_profile names to model IDs
|
|
28
|
+
if (config?.model_profile) {
|
|
29
|
+
const profileMap: Record<string, string> = {
|
|
30
|
+
balanced: 'claude-sonnet-4-6',
|
|
31
|
+
quality: 'claude-opus-4-6',
|
|
32
|
+
speed: 'claude-haiku-4-5',
|
|
33
|
+
};
|
|
34
|
+
return profileMap[config.model_profile] ?? config.model_profile;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
return undefined; // Let SDK use its default
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// ─── Session runner ──────────────────────────────────────────────────────────
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Run a plan execution session via the Agent SDK query() function.
|
|
44
|
+
*
|
|
45
|
+
* Builds the executor prompt from the parsed plan, configures query() with
|
|
46
|
+
* appropriate permissions, tool restrictions, and budget limits, then iterates
|
|
47
|
+
* the message stream to extract the result.
|
|
48
|
+
*
|
|
49
|
+
* @param plan - Parsed plan structure
|
|
50
|
+
* @param config - GSD project configuration
|
|
51
|
+
* @param options - Session overrides (maxTurns, budget, model, etc.)
|
|
52
|
+
* @param agentDef - Raw agent definition content (optional, for tool/role extraction)
|
|
53
|
+
* @returns Typed PlanResult with cost, duration, success/error status
|
|
54
|
+
*/
|
|
55
|
+
export async function runPlanSession(
|
|
56
|
+
plan: ParsedPlan,
|
|
57
|
+
config: GSDConfig,
|
|
58
|
+
options?: SessionOptions,
|
|
59
|
+
agentDef?: string,
|
|
60
|
+
eventStream?: GSDEventStream,
|
|
61
|
+
streamContext?: EventStreamContext,
|
|
62
|
+
): Promise<PlanResult> {
|
|
63
|
+
// Build the executor prompt
|
|
64
|
+
const executorPrompt = buildExecutorPrompt(plan, agentDef);
|
|
65
|
+
|
|
66
|
+
// Resolve allowed tools — from agent definition or defaults
|
|
67
|
+
const allowedTools = options?.allowedTools ??
|
|
68
|
+
(agentDef ? parseAgentTools(agentDef) : DEFAULT_ALLOWED_TOOLS);
|
|
69
|
+
|
|
70
|
+
// Resolve model
|
|
71
|
+
const model = resolveModel(options, config);
|
|
72
|
+
|
|
73
|
+
// Configure query options
|
|
74
|
+
const maxTurns = options?.maxTurns ?? 50;
|
|
75
|
+
const maxBudgetUsd = options?.maxBudgetUsd ?? 5.0;
|
|
76
|
+
const cwd = options?.cwd ?? process.cwd();
|
|
77
|
+
|
|
78
|
+
const queryStream = query({
|
|
79
|
+
prompt: `Execute this plan:\n\n${plan.objective || 'Execute the plan tasks below.'}`,
|
|
80
|
+
options: {
|
|
81
|
+
systemPrompt: {
|
|
82
|
+
type: 'preset',
|
|
83
|
+
preset: 'claude_code',
|
|
84
|
+
append: executorPrompt,
|
|
85
|
+
},
|
|
86
|
+
settingSources: ['project'],
|
|
87
|
+
allowedTools,
|
|
88
|
+
permissionMode: 'bypassPermissions',
|
|
89
|
+
allowDangerouslySkipPermissions: true,
|
|
90
|
+
maxTurns,
|
|
91
|
+
maxBudgetUsd,
|
|
92
|
+
cwd,
|
|
93
|
+
...(model ? { model } : {}),
|
|
94
|
+
},
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
return processQueryStream(queryStream, eventStream, streamContext);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// ─── Result extraction ───────────────────────────────────────────────────────
|
|
101
|
+
|
|
102
|
+
function isResultMessage(msg: SDKMessage): msg is SDKResultMessage {
|
|
103
|
+
return msg.type === 'result';
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function isSuccessResult(msg: SDKResultMessage): msg is SDKResultSuccess {
|
|
107
|
+
return msg.subtype === 'success';
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
function isErrorResult(msg: SDKResultMessage): msg is SDKResultError {
|
|
111
|
+
return msg.subtype !== 'success';
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
function emptyUsage(): SessionUsage {
|
|
115
|
+
return {
|
|
116
|
+
inputTokens: 0,
|
|
117
|
+
outputTokens: 0,
|
|
118
|
+
cacheReadInputTokens: 0,
|
|
119
|
+
cacheCreationInputTokens: 0,
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
function extractUsage(msg: SDKResultMessage): SessionUsage {
|
|
124
|
+
const u = msg.usage;
|
|
125
|
+
return {
|
|
126
|
+
inputTokens: u.input_tokens ?? 0,
|
|
127
|
+
outputTokens: u.output_tokens ?? 0,
|
|
128
|
+
cacheReadInputTokens: u.cache_read_input_tokens ?? 0,
|
|
129
|
+
cacheCreationInputTokens: u.cache_creation_input_tokens ?? 0,
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
function extractResult(msg: SDKResultMessage): PlanResult {
|
|
134
|
+
const base = {
|
|
135
|
+
sessionId: msg.session_id,
|
|
136
|
+
totalCostUsd: msg.total_cost_usd,
|
|
137
|
+
durationMs: msg.duration_ms,
|
|
138
|
+
usage: extractUsage(msg),
|
|
139
|
+
numTurns: msg.num_turns,
|
|
140
|
+
};
|
|
141
|
+
|
|
142
|
+
if (isSuccessResult(msg)) {
|
|
143
|
+
return {
|
|
144
|
+
...base,
|
|
145
|
+
success: true,
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// Error result
|
|
150
|
+
const errorMsg = msg as SDKResultError;
|
|
151
|
+
return {
|
|
152
|
+
...base,
|
|
153
|
+
success: false,
|
|
154
|
+
error: {
|
|
155
|
+
subtype: errorMsg.subtype,
|
|
156
|
+
messages: errorMsg.errors ?? [],
|
|
157
|
+
},
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// ─── Shared stream processing ────────────────────────────────────────────────
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* Process a query() message stream, emit events, and extract the result.
|
|
165
|
+
* Shared between runPlanSession and runPhaseStepSession to avoid duplication.
|
|
166
|
+
*/
|
|
167
|
+
async function processQueryStream(
|
|
168
|
+
queryStream: AsyncIterable<SDKMessage>,
|
|
169
|
+
eventStream?: GSDEventStream,
|
|
170
|
+
streamContext?: EventStreamContext,
|
|
171
|
+
): Promise<PlanResult> {
|
|
172
|
+
let resultMessage: SDKResultMessage | undefined;
|
|
173
|
+
|
|
174
|
+
try {
|
|
175
|
+
for await (const message of queryStream) {
|
|
176
|
+
if (eventStream) {
|
|
177
|
+
eventStream.mapAndEmit(message, streamContext ?? {});
|
|
178
|
+
}
|
|
179
|
+
if (isResultMessage(message)) {
|
|
180
|
+
resultMessage = message;
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
} catch (err) {
|
|
184
|
+
return {
|
|
185
|
+
success: false,
|
|
186
|
+
sessionId: '',
|
|
187
|
+
totalCostUsd: 0,
|
|
188
|
+
durationMs: 0,
|
|
189
|
+
usage: emptyUsage(),
|
|
190
|
+
numTurns: 0,
|
|
191
|
+
error: {
|
|
192
|
+
subtype: 'error_during_execution',
|
|
193
|
+
messages: [err instanceof Error ? err.message : String(err)],
|
|
194
|
+
},
|
|
195
|
+
};
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
if (!resultMessage) {
|
|
199
|
+
return {
|
|
200
|
+
success: false,
|
|
201
|
+
sessionId: '',
|
|
202
|
+
totalCostUsd: 0,
|
|
203
|
+
durationMs: 0,
|
|
204
|
+
usage: emptyUsage(),
|
|
205
|
+
numTurns: 0,
|
|
206
|
+
error: {
|
|
207
|
+
subtype: 'error_during_execution',
|
|
208
|
+
messages: ['No result message received from query stream'],
|
|
209
|
+
},
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
const result = extractResult(resultMessage);
|
|
214
|
+
|
|
215
|
+
if (eventStream) {
|
|
216
|
+
const cost = eventStream.getCost();
|
|
217
|
+
eventStream.emitEvent({
|
|
218
|
+
type: GSDEventType.CostUpdate,
|
|
219
|
+
timestamp: new Date().toISOString(),
|
|
220
|
+
sessionId: resultMessage.session_id,
|
|
221
|
+
phase: streamContext?.phase,
|
|
222
|
+
planName: streamContext?.planName,
|
|
223
|
+
sessionCostUsd: result.totalCostUsd,
|
|
224
|
+
cumulativeCostUsd: cost.cumulative,
|
|
225
|
+
} as GSDCostUpdateEvent);
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
return result;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
// ─── Phase step session runner ───────────────────────────────────────────────
|
|
232
|
+
|
|
233
|
+
/**
|
|
234
|
+
* Map PhaseStepType to PhaseType for tool scoping.
|
|
235
|
+
* PhaseStepType includes 'advance' which has no session-level equivalent.
|
|
236
|
+
*/
|
|
237
|
+
function stepTypeToPhaseType(step: PhaseStepType): PhaseType {
|
|
238
|
+
const mapping: Record<string, PhaseType> = {
|
|
239
|
+
discuss: PhaseType.Discuss,
|
|
240
|
+
research: PhaseType.Research,
|
|
241
|
+
plan: PhaseType.Plan,
|
|
242
|
+
plan_check: PhaseType.Verify,
|
|
243
|
+
execute: PhaseType.Execute,
|
|
244
|
+
verify: PhaseType.Verify,
|
|
245
|
+
};
|
|
246
|
+
return mapping[step] ?? PhaseType.Execute;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
/**
|
|
250
|
+
* Run a phase step session via the Agent SDK query() function.
|
|
251
|
+
*
|
|
252
|
+
* Unlike runPlanSession which takes a ParsedPlan, this accepts a raw prompt
|
|
253
|
+
* string and a phase step type. The prompt becomes the system prompt append,
|
|
254
|
+
* and tools are scoped by phase type.
|
|
255
|
+
*
|
|
256
|
+
* @param prompt - Raw prompt string to append to the system prompt
|
|
257
|
+
* @param phaseStep - Phase step type (determines tool scoping)
|
|
258
|
+
* @param config - GSD project configuration
|
|
259
|
+
* @param options - Session overrides (maxTurns, budget, model, etc.)
|
|
260
|
+
* @param eventStream - Optional event stream for observability
|
|
261
|
+
* @param streamContext - Optional context for event tagging
|
|
262
|
+
* @returns Typed PlanResult with cost, duration, success/error status
|
|
263
|
+
*/
|
|
264
|
+
export async function runPhaseStepSession(
|
|
265
|
+
prompt: string,
|
|
266
|
+
phaseStep: PhaseStepType,
|
|
267
|
+
config: GSDConfig,
|
|
268
|
+
options?: SessionOptions,
|
|
269
|
+
eventStream?: GSDEventStream,
|
|
270
|
+
streamContext?: EventStreamContext,
|
|
271
|
+
): Promise<PlanResult> {
|
|
272
|
+
const phaseType = stepTypeToPhaseType(phaseStep);
|
|
273
|
+
const allowedTools = options?.allowedTools ?? getToolsForPhase(phaseType);
|
|
274
|
+
const model = resolveModel(options, config);
|
|
275
|
+
const maxTurns = options?.maxTurns ?? 50;
|
|
276
|
+
const maxBudgetUsd = options?.maxBudgetUsd ?? 5.0;
|
|
277
|
+
const cwd = options?.cwd ?? process.cwd();
|
|
278
|
+
|
|
279
|
+
const queryStream = query({
|
|
280
|
+
prompt: `Execute this phase step: ${phaseStep}`,
|
|
281
|
+
options: {
|
|
282
|
+
systemPrompt: {
|
|
283
|
+
type: 'preset',
|
|
284
|
+
preset: 'claude_code',
|
|
285
|
+
append: prompt,
|
|
286
|
+
},
|
|
287
|
+
settingSources: ['project'],
|
|
288
|
+
allowedTools,
|
|
289
|
+
permissionMode: 'bypassPermissions',
|
|
290
|
+
allowDangerouslySkipPermissions: true,
|
|
291
|
+
maxTurns,
|
|
292
|
+
maxBudgetUsd,
|
|
293
|
+
cwd,
|
|
294
|
+
...(model ? { model } : {}),
|
|
295
|
+
},
|
|
296
|
+
});
|
|
297
|
+
|
|
298
|
+
return processQueryStream(queryStream, eventStream, streamContext);
|
|
299
|
+
}
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import { getToolsForPhase, PHASE_AGENT_MAP, PHASE_DEFAULT_TOOLS } from './tool-scoping.js';
|
|
3
|
+
import { PhaseType } from './types.js';
|
|
4
|
+
|
|
5
|
+
// ─── Tests ───────────────────────────────────────────────────────────────────
|
|
6
|
+
|
|
7
|
+
describe('getToolsForPhase', () => {
|
|
8
|
+
describe('default tools per phase', () => {
|
|
9
|
+
it('research phase: read-only + web search, no Write/Edit', () => {
|
|
10
|
+
const tools = getToolsForPhase(PhaseType.Research);
|
|
11
|
+
expect(tools).toContain('Read');
|
|
12
|
+
expect(tools).toContain('Grep');
|
|
13
|
+
expect(tools).toContain('Glob');
|
|
14
|
+
expect(tools).toContain('Bash');
|
|
15
|
+
expect(tools).toContain('WebSearch');
|
|
16
|
+
expect(tools).not.toContain('Write');
|
|
17
|
+
expect(tools).not.toContain('Edit');
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
it('execute phase: full read/write', () => {
|
|
21
|
+
const tools = getToolsForPhase(PhaseType.Execute);
|
|
22
|
+
expect(tools).toContain('Read');
|
|
23
|
+
expect(tools).toContain('Write');
|
|
24
|
+
expect(tools).toContain('Edit');
|
|
25
|
+
expect(tools).toContain('Bash');
|
|
26
|
+
expect(tools).toContain('Grep');
|
|
27
|
+
expect(tools).toContain('Glob');
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
it('verify phase: read-only, no Write/Edit', () => {
|
|
31
|
+
const tools = getToolsForPhase(PhaseType.Verify);
|
|
32
|
+
expect(tools).toContain('Read');
|
|
33
|
+
expect(tools).toContain('Bash');
|
|
34
|
+
expect(tools).toContain('Grep');
|
|
35
|
+
expect(tools).toContain('Glob');
|
|
36
|
+
expect(tools).not.toContain('Write');
|
|
37
|
+
expect(tools).not.toContain('Edit');
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
it('discuss phase: read-only, no Write/Edit', () => {
|
|
41
|
+
const tools = getToolsForPhase(PhaseType.Discuss);
|
|
42
|
+
expect(tools).toContain('Read');
|
|
43
|
+
expect(tools).toContain('Bash');
|
|
44
|
+
expect(tools).toContain('Grep');
|
|
45
|
+
expect(tools).toContain('Glob');
|
|
46
|
+
expect(tools).not.toContain('Write');
|
|
47
|
+
expect(tools).not.toContain('Edit');
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
it('plan phase: read/write + web, has Write but no Edit', () => {
|
|
51
|
+
const tools = getToolsForPhase(PhaseType.Plan);
|
|
52
|
+
expect(tools).toContain('Read');
|
|
53
|
+
expect(tools).toContain('Write');
|
|
54
|
+
expect(tools).toContain('Bash');
|
|
55
|
+
expect(tools).toContain('Glob');
|
|
56
|
+
expect(tools).toContain('Grep');
|
|
57
|
+
expect(tools).toContain('WebFetch');
|
|
58
|
+
});
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
describe('returns copies, not references', () => {
|
|
62
|
+
it('mutating returned array does not affect future calls', () => {
|
|
63
|
+
const tools1 = getToolsForPhase(PhaseType.Execute);
|
|
64
|
+
tools1.push('CustomTool');
|
|
65
|
+
const tools2 = getToolsForPhase(PhaseType.Execute);
|
|
66
|
+
expect(tools2).not.toContain('CustomTool');
|
|
67
|
+
});
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
describe('agent definition override', () => {
|
|
71
|
+
it('parses tools from agent def frontmatter when provided', () => {
|
|
72
|
+
const agentDef = `---
|
|
73
|
+
name: test-agent
|
|
74
|
+
tools: Bash, Grep, CustomTool
|
|
75
|
+
---
|
|
76
|
+
|
|
77
|
+
<role>Test agent</role>`;
|
|
78
|
+
|
|
79
|
+
const tools = getToolsForPhase(PhaseType.Execute, agentDef);
|
|
80
|
+
expect(tools).toEqual(['Bash', 'Grep', 'CustomTool']);
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
it('falls back to defaults when agent def has no tools line', () => {
|
|
84
|
+
const agentDef = `---
|
|
85
|
+
name: test-agent
|
|
86
|
+
---
|
|
87
|
+
|
|
88
|
+
<role>Test agent</role>`;
|
|
89
|
+
|
|
90
|
+
const tools = getToolsForPhase(PhaseType.Execute, agentDef);
|
|
91
|
+
// parseAgentTools returns DEFAULT_ALLOWED_TOOLS when no tools: line found
|
|
92
|
+
expect(tools).toEqual(['Read', 'Write', 'Edit', 'Bash', 'Grep', 'Glob']);
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
it('falls back to defaults when agent def has no frontmatter', () => {
|
|
96
|
+
const agentDef = '<role>Test agent with no frontmatter</role>';
|
|
97
|
+
|
|
98
|
+
const tools = getToolsForPhase(PhaseType.Research, agentDef);
|
|
99
|
+
// parseAgentTools returns DEFAULT_ALLOWED_TOOLS for no frontmatter
|
|
100
|
+
expect(tools).toEqual(['Read', 'Write', 'Edit', 'Bash', 'Grep', 'Glob']);
|
|
101
|
+
});
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
describe('R015 compliance', () => {
|
|
105
|
+
it('research has no Write or Edit on source', () => {
|
|
106
|
+
const tools = getToolsForPhase(PhaseType.Research);
|
|
107
|
+
expect(tools).not.toContain('Write');
|
|
108
|
+
expect(tools).not.toContain('Edit');
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
it('execute has Write and Edit for source modification', () => {
|
|
112
|
+
const tools = getToolsForPhase(PhaseType.Execute);
|
|
113
|
+
expect(tools).toContain('Write');
|
|
114
|
+
expect(tools).toContain('Edit');
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
it('verify has no Write or Edit (read-only verification)', () => {
|
|
118
|
+
const tools = getToolsForPhase(PhaseType.Verify);
|
|
119
|
+
expect(tools).not.toContain('Write');
|
|
120
|
+
expect(tools).not.toContain('Edit');
|
|
121
|
+
});
|
|
122
|
+
});
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
describe('PHASE_AGENT_MAP', () => {
|
|
126
|
+
it('maps all phase types', () => {
|
|
127
|
+
for (const phase of Object.values(PhaseType)) {
|
|
128
|
+
expect(phase in PHASE_AGENT_MAP).toBe(true);
|
|
129
|
+
}
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
it('execute maps to gsd-executor.md', () => {
|
|
133
|
+
expect(PHASE_AGENT_MAP[PhaseType.Execute]).toBe('gsd-executor.md');
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
it('research maps to gsd-phase-researcher.md', () => {
|
|
137
|
+
expect(PHASE_AGENT_MAP[PhaseType.Research]).toBe('gsd-phase-researcher.md');
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
it('plan maps to gsd-planner.md', () => {
|
|
141
|
+
expect(PHASE_AGENT_MAP[PhaseType.Plan]).toBe('gsd-planner.md');
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
it('verify maps to gsd-verifier.md', () => {
|
|
145
|
+
expect(PHASE_AGENT_MAP[PhaseType.Verify]).toBe('gsd-verifier.md');
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
it('discuss maps to null (no dedicated agent)', () => {
|
|
149
|
+
expect(PHASE_AGENT_MAP[PhaseType.Discuss]).toBeNull();
|
|
150
|
+
});
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
describe('PHASE_DEFAULT_TOOLS', () => {
|
|
154
|
+
it('covers all phase types', () => {
|
|
155
|
+
for (const phase of Object.values(PhaseType)) {
|
|
156
|
+
expect(PHASE_DEFAULT_TOOLS[phase]).toBeDefined();
|
|
157
|
+
expect(PHASE_DEFAULT_TOOLS[phase].length).toBeGreaterThan(0);
|
|
158
|
+
}
|
|
159
|
+
});
|
|
160
|
+
});
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool scoping — maps phase types to allowed tool sets.
|
|
3
|
+
*
|
|
4
|
+
* Per R015, different phases get different tool access:
|
|
5
|
+
* - Research: read-only + web search (no Write/Edit on source)
|
|
6
|
+
* - Execute: full read/write
|
|
7
|
+
* - Verify: read-only (no Write/Edit)
|
|
8
|
+
* - Discuss: read-only
|
|
9
|
+
* - Plan: read/write + web (for creating plan files)
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import { PhaseType } from './types.js';
|
|
13
|
+
import { parseAgentTools } from './prompt-builder.js';
|
|
14
|
+
|
|
15
|
+
// ─── Phase default tool sets ─────────────────────────────────────────────────
|
|
16
|
+
|
|
17
|
+
const PHASE_DEFAULT_TOOLS: Record<PhaseType, string[]> = {
|
|
18
|
+
[PhaseType.Research]: ['Read', 'Grep', 'Glob', 'Bash', 'WebSearch'],
|
|
19
|
+
[PhaseType.Execute]: ['Read', 'Write', 'Edit', 'Bash', 'Grep', 'Glob'],
|
|
20
|
+
[PhaseType.Verify]: ['Read', 'Bash', 'Grep', 'Glob'],
|
|
21
|
+
[PhaseType.Discuss]: ['Read', 'Bash', 'Grep', 'Glob'],
|
|
22
|
+
[PhaseType.Plan]: ['Read', 'Write', 'Bash', 'Glob', 'Grep', 'WebFetch'],
|
|
23
|
+
[PhaseType.Repair]: ['Read', 'Write', 'Edit', 'Bash', 'Grep', 'Glob'],
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
// ─── Phase → agent definition filename ──────────────────────────────────────
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Maps each phase type to its corresponding agent definition filename.
|
|
30
|
+
* Discuss has no dedicated agent — it runs in the main conversation.
|
|
31
|
+
*/
|
|
32
|
+
export const PHASE_AGENT_MAP: Record<PhaseType, string | null> = {
|
|
33
|
+
[PhaseType.Execute]: 'gsd-executor.md',
|
|
34
|
+
[PhaseType.Research]: 'gsd-phase-researcher.md',
|
|
35
|
+
[PhaseType.Plan]: 'gsd-planner.md',
|
|
36
|
+
[PhaseType.Verify]: 'gsd-verifier.md',
|
|
37
|
+
[PhaseType.Discuss]: null,
|
|
38
|
+
[PhaseType.Repair]: null,
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
// ─── Public API ──────────────────────────────────────────────────────────────
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Get the allowed tools for a phase type.
|
|
45
|
+
*
|
|
46
|
+
* If an agent definition string is provided, tools are parsed from its
|
|
47
|
+
* frontmatter (reusing parseAgentTools from prompt-builder). Otherwise,
|
|
48
|
+
* returns the hardcoded phase defaults per R015.
|
|
49
|
+
*
|
|
50
|
+
* @param phaseType - The phase being executed
|
|
51
|
+
* @param agentDef - Optional raw agent .md file content to parse tools from
|
|
52
|
+
* @returns Array of allowed tool names
|
|
53
|
+
*/
|
|
54
|
+
export function getToolsForPhase(phaseType: PhaseType, agentDef?: string): string[] {
|
|
55
|
+
if (agentDef) {
|
|
56
|
+
return parseAgentTools(agentDef);
|
|
57
|
+
}
|
|
58
|
+
return [...PHASE_DEFAULT_TOOLS[phaseType]];
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export { PHASE_DEFAULT_TOOLS };
|