prizmkit 1.1.57 → 1.1.60

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.
Files changed (188) hide show
  1. package/bin/create-prizmkit.js +8 -6
  2. package/bundled/VERSION.json +3 -3
  3. package/bundled/adapters/codex/agent-adapter.js +38 -0
  4. package/bundled/adapters/codex/paths.js +27 -0
  5. package/bundled/adapters/codex/rules-adapter.js +30 -0
  6. package/bundled/adapters/codex/settings-adapter.js +27 -0
  7. package/bundled/adapters/codex/skill-adapter.js +65 -0
  8. package/bundled/adapters/codex/team-adapter.js +37 -0
  9. package/bundled/dev-pipeline/.env.example +2 -1
  10. package/bundled/dev-pipeline/README.md +10 -7
  11. package/bundled/dev-pipeline/lib/common.sh +278 -37
  12. package/bundled/dev-pipeline/run-bugfix.sh +10 -61
  13. package/bundled/dev-pipeline/run-feature.sh +10 -78
  14. package/bundled/dev-pipeline/run-recovery.sh +10 -46
  15. package/bundled/dev-pipeline/run-refactor.sh +10 -61
  16. package/bundled/dev-pipeline/scripts/generate-bootstrap-prompt.py +17 -7
  17. package/bundled/dev-pipeline/scripts/generate-bugfix-prompt.py +9 -3
  18. package/bundled/dev-pipeline/scripts/generate-refactor-prompt.py +9 -3
  19. package/bundled/dev-pipeline/scripts/utils.py +6 -4
  20. package/bundled/dev-pipeline-windows/.env.example +28 -0
  21. package/bundled/dev-pipeline-windows/README.md +30 -0
  22. package/bundled/dev-pipeline-windows/SCHEMA_ANALYSIS.md +525 -0
  23. package/bundled/dev-pipeline-windows/assets/feature-list-example.json +146 -0
  24. package/bundled/dev-pipeline-windows/assets/prizm-dev-team-integration.md +138 -0
  25. package/bundled/dev-pipeline-windows/launch-bugfix-daemon.ps1 +9 -0
  26. package/bundled/dev-pipeline-windows/launch-feature-daemon.ps1 +9 -0
  27. package/bundled/dev-pipeline-windows/launch-refactor-daemon.ps1 +9 -0
  28. package/bundled/dev-pipeline-windows/lib/common.ps1 +432 -0
  29. package/bundled/dev-pipeline-windows/lib/daemon.ps1 +140 -0
  30. package/bundled/dev-pipeline-windows/lib/pipeline.ps1 +446 -0
  31. package/bundled/dev-pipeline-windows/lib/reset.ps1 +87 -0
  32. package/bundled/dev-pipeline-windows/reset-bug.ps1 +9 -0
  33. package/bundled/dev-pipeline-windows/reset-feature.ps1 +9 -0
  34. package/bundled/dev-pipeline-windows/reset-refactor.ps1 +9 -0
  35. package/bundled/dev-pipeline-windows/run-bugfix.ps1 +9 -0
  36. package/bundled/dev-pipeline-windows/run-feature.ps1 +9 -0
  37. package/bundled/dev-pipeline-windows/run-recovery.ps1 +76 -0
  38. package/bundled/dev-pipeline-windows/run-refactor.ps1 +9 -0
  39. package/bundled/dev-pipeline-windows/scripts/check-session-status.py +228 -0
  40. package/bundled/dev-pipeline-windows/scripts/cleanup-logs.py +192 -0
  41. package/bundled/dev-pipeline-windows/scripts/detect-stuck.py +530 -0
  42. package/bundled/dev-pipeline-windows/scripts/generate-bootstrap-prompt.py +1737 -0
  43. package/bundled/dev-pipeline-windows/scripts/generate-bugfix-prompt.py +685 -0
  44. package/bundled/dev-pipeline-windows/scripts/generate-recovery-prompt.py +805 -0
  45. package/bundled/dev-pipeline-windows/scripts/generate-refactor-prompt.py +763 -0
  46. package/bundled/dev-pipeline-windows/scripts/init-bugfix-pipeline.py +316 -0
  47. package/bundled/dev-pipeline-windows/scripts/init-dev-team.py +134 -0
  48. package/bundled/dev-pipeline-windows/scripts/init-pipeline.py +380 -0
  49. package/bundled/dev-pipeline-windows/scripts/init-refactor-pipeline.py +399 -0
  50. package/bundled/dev-pipeline-windows/scripts/parse-stream-progress.py +388 -0
  51. package/bundled/dev-pipeline-windows/scripts/patch-completion-notes.py +191 -0
  52. package/bundled/dev-pipeline-windows/scripts/update-bug-status.py +864 -0
  53. package/bundled/dev-pipeline-windows/scripts/update-checkpoint.py +173 -0
  54. package/bundled/dev-pipeline-windows/scripts/update-feature-status.py +1501 -0
  55. package/bundled/dev-pipeline-windows/scripts/update-refactor-status.py +1073 -0
  56. package/bundled/dev-pipeline-windows/scripts/utils.py +542 -0
  57. package/bundled/dev-pipeline-windows/templates/agent-prompts/critic-plan-challenge.md +7 -0
  58. package/bundled/dev-pipeline-windows/templates/agent-prompts/dev-fix.md +7 -0
  59. package/bundled/dev-pipeline-windows/templates/agent-prompts/dev-implement.md +30 -0
  60. package/bundled/dev-pipeline-windows/templates/agent-prompts/dev-resume.md +5 -0
  61. package/bundled/dev-pipeline-windows/templates/agent-prompts/reviewer-review.md +7 -0
  62. package/bundled/dev-pipeline-windows/templates/bootstrap-prompt.md +46 -0
  63. package/bundled/dev-pipeline-windows/templates/bootstrap-tier1.md +43 -0
  64. package/bundled/dev-pipeline-windows/templates/bootstrap-tier2.md +43 -0
  65. package/bundled/dev-pipeline-windows/templates/bootstrap-tier3.md +43 -0
  66. package/bundled/dev-pipeline-windows/templates/bug-fix-list-schema.json +263 -0
  67. package/bundled/dev-pipeline-windows/templates/bugfix-bootstrap-prompt.md +320 -0
  68. package/bundled/dev-pipeline-windows/templates/feature-list-schema.json +237 -0
  69. package/bundled/dev-pipeline-windows/templates/refactor-bootstrap-prompt.md +331 -0
  70. package/bundled/dev-pipeline-windows/templates/refactor-list-schema.json +270 -0
  71. package/bundled/dev-pipeline-windows/templates/sections/ac-verification-checklist.md +13 -0
  72. package/bundled/dev-pipeline-windows/templates/sections/checkpoint-system.md +91 -0
  73. package/bundled/dev-pipeline-windows/templates/sections/context-budget-rules.md +33 -0
  74. package/bundled/dev-pipeline-windows/templates/sections/critical-paths-agent.md +10 -0
  75. package/bundled/dev-pipeline-windows/templates/sections/critical-paths-full.md +12 -0
  76. package/bundled/dev-pipeline-windows/templates/sections/critical-paths-lite.md +7 -0
  77. package/bundled/dev-pipeline-windows/templates/sections/directory-convention-agent.md +8 -0
  78. package/bundled/dev-pipeline-windows/templates/sections/directory-convention-full.md +9 -0
  79. package/bundled/dev-pipeline-windows/templates/sections/directory-convention-lite.md +6 -0
  80. package/bundled/dev-pipeline-windows/templates/sections/failure-capture.md +21 -0
  81. package/bundled/dev-pipeline-windows/templates/sections/feature-context.md +31 -0
  82. package/bundled/dev-pipeline-windows/templates/sections/phase-browser-verification-auto.md +72 -0
  83. package/bundled/dev-pipeline-windows/templates/sections/phase-browser-verification-opencli.md +63 -0
  84. package/bundled/dev-pipeline-windows/templates/sections/phase-browser-verification.md +62 -0
  85. package/bundled/dev-pipeline-windows/templates/sections/phase-commit-full.md +71 -0
  86. package/bundled/dev-pipeline-windows/templates/sections/phase-commit.md +64 -0
  87. package/bundled/dev-pipeline-windows/templates/sections/phase-context-snapshot-agent-suffix.md +23 -0
  88. package/bundled/dev-pipeline-windows/templates/sections/phase-context-snapshot-base.md +24 -0
  89. package/bundled/dev-pipeline-windows/templates/sections/phase-context-snapshot-lite-suffix.md +12 -0
  90. package/bundled/dev-pipeline-windows/templates/sections/phase-critic-plan-full.md +53 -0
  91. package/bundled/dev-pipeline-windows/templates/sections/phase-critic-plan.md +32 -0
  92. package/bundled/dev-pipeline-windows/templates/sections/phase-implement-agent.md +37 -0
  93. package/bundled/dev-pipeline-windows/templates/sections/phase-implement-full.md +50 -0
  94. package/bundled/dev-pipeline-windows/templates/sections/phase-implement-lite.md +52 -0
  95. package/bundled/dev-pipeline-windows/templates/sections/phase-plan-agent.md +27 -0
  96. package/bundled/dev-pipeline-windows/templates/sections/phase-plan-lite.md +27 -0
  97. package/bundled/dev-pipeline-windows/templates/sections/phase-review-agent.md +27 -0
  98. package/bundled/dev-pipeline-windows/templates/sections/phase-review-full.md +29 -0
  99. package/bundled/dev-pipeline-windows/templates/sections/phase-specify-plan-full.md +77 -0
  100. package/bundled/dev-pipeline-windows/templates/sections/phase0-init.md +13 -0
  101. package/bundled/dev-pipeline-windows/templates/sections/phase0-test-baseline.md +23 -0
  102. package/bundled/dev-pipeline-windows/templates/sections/session-context.md +5 -0
  103. package/bundled/dev-pipeline-windows/templates/sections/subagent-timeout-recovery.md +6 -0
  104. package/bundled/dev-pipeline-windows/templates/sections/test-failure-recovery-agent.md +67 -0
  105. package/bundled/dev-pipeline-windows/templates/sections/test-failure-recovery-lite.md +58 -0
  106. package/bundled/dev-pipeline-windows/templates/session-status-schema.json +83 -0
  107. package/bundled/skills/_metadata.json +1 -1
  108. package/bundled/skills/app-planner/SKILL.md +26 -18
  109. package/bundled/skills/app-planner/references/architecture-decisions.md +9 -5
  110. package/bundled/skills/app-planner/references/frontend-design-guide.md +1 -1
  111. package/bundled/skills/feature-planner/SKILL.md +9 -2
  112. package/bundled/skills/prizmkit-init/SKILL.md +7 -6
  113. package/bundled/skills/recovery-workflow/scripts/detect-recovery-state.py +2 -0
  114. package/bundled/skills-windows/app-planner/SKILL.md +639 -0
  115. package/bundled/skills-windows/app-planner/assets/app-design-guide.md +101 -0
  116. package/bundled/skills-windows/app-planner/references/architecture-decisions.md +52 -0
  117. package/bundled/skills-windows/app-planner/references/brainstorm-guide.md +101 -0
  118. package/bundled/skills-windows/app-planner/references/frontend-design-guide.md +71 -0
  119. package/bundled/skills-windows/app-planner/references/project-brief-guide.md +82 -0
  120. package/bundled/skills-windows/app-planner/references/red-team-checklist.md +40 -0
  121. package/bundled/skills-windows/app-planner/references/rules/backend/derivation-rules.md +609 -0
  122. package/bundled/skills-windows/app-planner/references/rules/backend/fixed-rules.md +285 -0
  123. package/bundled/skills-windows/app-planner/references/rules/backend/question-bank.md +249 -0
  124. package/bundled/skills-windows/app-planner/references/rules/backend/template.md +173 -0
  125. package/bundled/skills-windows/app-planner/references/rules/database/derivation-rules.md +373 -0
  126. package/bundled/skills-windows/app-planner/references/rules/database/fixed-rules.md +211 -0
  127. package/bundled/skills-windows/app-planner/references/rules/database/question-bank.md +184 -0
  128. package/bundled/skills-windows/app-planner/references/rules/database/template.md +158 -0
  129. package/bundled/skills-windows/app-planner/references/rules/frontend/derivation-rules.md +810 -0
  130. package/bundled/skills-windows/app-planner/references/rules/frontend/fixed-rules.md +188 -0
  131. package/bundled/skills-windows/app-planner/references/rules/frontend/question-bank.md +302 -0
  132. package/bundled/skills-windows/app-planner/references/rules/frontend/template.md +320 -0
  133. package/bundled/skills-windows/app-planner/references/rules/mobile/derivation-rules.md +639 -0
  134. package/bundled/skills-windows/app-planner/references/rules/mobile/fixed-rules.md +290 -0
  135. package/bundled/skills-windows/app-planner/references/rules/mobile/question-bank.md +232 -0
  136. package/bundled/skills-windows/app-planner/references/rules/mobile/template.md +175 -0
  137. package/bundled/skills-windows/bug-fix-workflow/SKILL.md +415 -0
  138. package/bundled/skills-windows/bug-planner/SKILL.md +395 -0
  139. package/bundled/skills-windows/bug-planner/assets/bug-confirmation-template.md +43 -0
  140. package/bundled/skills-windows/bug-planner/references/critic-and-verification.md +44 -0
  141. package/bundled/skills-windows/bug-planner/references/error-recovery.md +73 -0
  142. package/bundled/skills-windows/bug-planner/references/input-formats.md +53 -0
  143. package/bundled/skills-windows/bug-planner/references/schema-validation.md +25 -0
  144. package/bundled/skills-windows/bug-planner/references/severity-rules.md +16 -0
  145. package/bundled/skills-windows/bug-planner/scripts/validate-bug-list.py +322 -0
  146. package/bundled/skills-windows/bugfix-pipeline-launcher/SKILL.md +380 -0
  147. package/bundled/skills-windows/feature-pipeline-launcher/SKILL.md +441 -0
  148. package/bundled/skills-windows/feature-pipeline-launcher/scripts/preflight-check.py +462 -0
  149. package/bundled/skills-windows/feature-planner/SKILL.md +401 -0
  150. package/bundled/skills-windows/feature-planner/assets/evaluation-guide.md +64 -0
  151. package/bundled/skills-windows/feature-planner/assets/planning-guide.md +214 -0
  152. package/bundled/skills-windows/feature-planner/references/browser-interaction.md +59 -0
  153. package/bundled/skills-windows/feature-planner/references/completeness-review.md +57 -0
  154. package/bundled/skills-windows/feature-planner/references/decomposition-patterns.md +75 -0
  155. package/bundled/skills-windows/feature-planner/references/error-recovery.md +90 -0
  156. package/bundled/skills-windows/feature-planner/references/incremental-feature-planning.md +112 -0
  157. package/bundled/skills-windows/feature-planner/references/new-project-planning.md +85 -0
  158. package/bundled/skills-windows/feature-planner/scripts/validate-and-generate.py +1029 -0
  159. package/bundled/skills-windows/feature-workflow/SKILL.md +531 -0
  160. package/bundled/skills-windows/prizmkit-init/SKILL.md +356 -0
  161. package/bundled/skills-windows/prizmkit-init/assets/project-brief-template.md +82 -0
  162. package/bundled/skills-windows/prizmkit-init/references/config-schema.md +68 -0
  163. package/bundled/skills-windows/prizmkit-init/references/rules/layer-detection.md +41 -0
  164. package/bundled/skills-windows/prizmkit-init/references/tech-stack-catalog.md +13 -0
  165. package/bundled/skills-windows/prizmkit-init/references/update-supplement.md +9 -0
  166. package/bundled/skills-windows/recovery-workflow/SKILL.md +456 -0
  167. package/bundled/skills-windows/recovery-workflow/evals/evals.json +46 -0
  168. package/bundled/skills-windows/recovery-workflow/scripts/detect-recovery-state.py +544 -0
  169. package/bundled/skills-windows/refactor-pipeline-launcher/SKILL.md +406 -0
  170. package/bundled/skills-windows/refactor-planner/SKILL.md +540 -0
  171. package/bundled/skills-windows/refactor-planner/assets/planning-guide.md +292 -0
  172. package/bundled/skills-windows/refactor-planner/references/behavior-preservation.md +301 -0
  173. package/bundled/skills-windows/refactor-planner/references/refactor-scoping-guide.md +221 -0
  174. package/bundled/skills-windows/refactor-planner/scripts/validate-and-generate-refactor.py +858 -0
  175. package/bundled/skills-windows/refactor-workflow/SKILL.md +503 -0
  176. package/package.json +3 -2
  177. package/src/clean.js +73 -2
  178. package/src/config.js +159 -50
  179. package/src/detect-platform.js +16 -8
  180. package/src/external-skills.js +26 -19
  181. package/src/index.js +31 -9
  182. package/src/manifest.js +6 -2
  183. package/src/metadata.js +43 -5
  184. package/src/platforms.js +36 -0
  185. package/src/prompts.js +31 -6
  186. package/src/runtimes.js +20 -0
  187. package/src/scaffold.js +314 -110
  188. package/src/upgrade.js +81 -41
@@ -0,0 +1,138 @@
1
+ # prizm-dev-team Integration Guide
2
+
3
+ ## Overview
4
+
5
+ dev-pipeline drives the prizm-dev-team multi-agent team through an outer shell loop. Each iteration spawns a new AI CLI session with a bootstrap prompt that instructs the agent to create and orchestrate the team for one feature.
6
+
7
+ ## Architecture
8
+
9
+ ```
10
+ dev-pipeline (outer loop)
11
+
12
+ ├── run-feature.ps1 PowerShell runner — picks next feature, spawns CLI
13
+ ├── scripts/ Python state management scripts
14
+ ├── templates/bootstrap-prompt.md Session prompt template
15
+
16
+ └── [per session] AI CLI
17
+
18
+ ├── Phase 0: Init (Orchestrator)
19
+ ├── Phase 1-2: Context snapshot + Specify + Plan (Orchestrator)
20
+ ├── Phase 3: Analyze (Reviewer agent) [tier2] / Phase 4: Analyze [tier3]
21
+ ├── Phase 4: Implement (Dev agent) [tier2] / Phase 5: Implement [tier3]
22
+ ├── Phase 4.5/6: Review (Reviewer agent)
23
+ └── Phase 5/7: Retrospective & Commit (Orchestrator)
24
+
25
+ └── Write session-status.json → exit
26
+ ```
27
+
28
+ ## Agent Definitions (Source of Truth)
29
+
30
+ | Agent | Definition Path | Type |
31
+ |-------|----------------|------|
32
+ | Dev | `.claude/agents/prizm-dev-team-dev.md` (or `.codebuddy/agents/`) | prizm-dev-team-dev |
33
+ | Reviewer | `.claude/agents/prizm-dev-team-reviewer.md` (or `.codebuddy/agents/`) | prizm-dev-team-reviewer |
34
+ | Critic | `.claude/agents/prizm-dev-team-critic.md` (or `.codebuddy/agents/`) | prizm-dev-team-critic |
35
+
36
+ Note: The Orchestrator role is handled by the main agent (session orchestrator) directly — no separate agent definition needed.
37
+
38
+ ## Pipeline Scripts
39
+
40
+ Located at `.prizmkit/dev-pipeline/scripts/`:
41
+
42
+ | Script | Purpose |
43
+ |--------|---------|
44
+ | `init-dev-team.py` | Initialize `.dev-team/` + `.prizmkit/` directories |
45
+ | `init-pipeline.py` | Initialize pipeline state directories and config |
46
+ | `init-bugfix-pipeline.py` | Initialize bugfix pipeline state |
47
+ | `generate-bootstrap-prompt.py` | Render tier-specific bootstrap prompt with feature context |
48
+ | `generate-bugfix-prompt.py` | Render bugfix bootstrap prompt with bug context |
49
+ | `update-feature-status.py` | Update feature status in feature-list.json after session |
50
+ | `update-bug-status.py` | Update bug status in bug-fix-list.json after session |
51
+ | `check-session-status.py` | Read and validate session-status.json output |
52
+ | `detect-stuck.py` | Detect stuck/hung pipeline sessions via heartbeat |
53
+ | `parse-stream-progress.py` | Parse AI CLI output stream for progress tracking |
54
+ | `cleanup-logs.py` | Clean up old pipeline logs and state files |
55
+ | `utils.py` | Shared utility functions for pipeline scripts |
56
+
57
+ ## Artifact Mapping
58
+
59
+ ### PrizmKit Artifacts (.prizmkit/)
60
+
61
+ | Phase | File | Content |
62
+ |-------|------|---------|
63
+ | 1 | `specs/spec.md` | Feature specification (WHAT/WHY) |
64
+ | 2 | `plans/plan.md` | Technical plan (architecture, API, tests) |
65
+ | 3 | `tasks/tasks.md` | Executable task list with `[ ]` / `[x]` (legacy — now part of plan.md Tasks section) |
66
+ | 4 | `analysis/analyze-report.md` | Consistency analysis |
67
+
68
+ ### Dev-Team Artifacts (.dev-team/)
69
+
70
+ | Phase | File | Content |
71
+ |-------|------|---------|
72
+ | 1 | `specs/requirements.md` | Requirements with REQ-NNN IDs |
73
+ | 2 | `contracts/*.contract.json` | Interface contracts |
74
+ | 2 | `contracts/data-models.json` | Data entity definitions |
75
+ | 3 | `tasks/task-manifest.json` | Structured tasks with T-NNN IDs |
76
+ | 3 | `tasks/dependency-graph.json` | Task DAG |
77
+ | 6 | `reports/dev/self-test-*.md` | Dev self-test reports |
78
+ | 7 | `reports/qa/integration-test.md` | QA integration test report |
79
+ | 7 | `reports/review/code-review.md` | Review report |
80
+
81
+ ## Session Lifecycle
82
+
83
+ ### 1. Session Start
84
+
85
+ The bootstrap prompt instructs the agent to:
86
+ - Execute phases directly as the session orchestrator
87
+ - Spawn Dev and Reviewer agents as subagents for implementation and review phases
88
+ - The orchestrator handles context building, planning, retrospective, and commit phases directly
89
+
90
+ ### 2. Pipeline Execution
91
+
92
+ The Orchestrator drives the pipeline phases with checkpoints (CP-0 through CP-3). Each checkpoint validates artifacts.
93
+
94
+ ### 3. Session End
95
+
96
+ The agent MUST write `session-status.json` before exiting:
97
+
98
+ ```json
99
+ {
100
+ "session_id": "F-001-20260304100000",
101
+ "feature_id": "F-001",
102
+ "status": "success",
103
+ "completed_phases": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
104
+ "current_phase": 9,
105
+ "checkpoint_reached": "CP-7",
106
+ "tasks_completed": 12,
107
+ "tasks_total": 12,
108
+ "errors": [],
109
+ "can_resume": false,
110
+ "resume_from_phase": null,
111
+ "artifacts": {
112
+ "spec_path": ".prizmkit/specs/spec.md",
113
+ "plan_path": ".prizmkit/plans/plan.md"
114
+ },
115
+ "timestamp": "2026-03-04T11:30:00Z"
116
+ }
117
+ ```
118
+
119
+ ## Failure Recovery
120
+
121
+ | Session Outcome | Pipeline Action |
122
+ |-----------------|-----------------|
123
+ | `status: "success"` | Mark feature completed, pick next |
124
+ | `status: "partial"`, `can_resume: true` | Resume from `resume_from_phase` |
125
+ | `status: "partial"`, `can_resume: false` | Retry from scratch |
126
+ | `status: "failed"` | Retry (up to MAX_RETRIES) |
127
+ | No status file (crash) | Treat as failed, retry |
128
+ | Timeout (exit 124) | Treat as timed_out, retry |
129
+
130
+ ## Team Naming Convention
131
+
132
+ Each feature gets its own team instance: `prizm-dev-team-{FEATURE_ID}`
133
+
134
+ Examples:
135
+ - `prizm-dev-team-F-001` — User Authentication
136
+ - `prizm-dev-team-F-002` — Dashboard
137
+
138
+ This ensures clean isolation between features and allows multiple features to have separate artifact histories.
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env pwsh
2
+ . "$PSScriptRoot\lib\daemon.ps1"
3
+ try {
4
+ Invoke-PrizmDaemon -Kind bugfix -ScriptRoot $PSScriptRoot -RunScript (Join-Path $PSScriptRoot 'run-bugfix.ps1') -Args $args
5
+ exit $global:PRIZM_DAEMON_EXIT_CODE
6
+ } catch {
7
+ Write-PrizmError $_.Exception.Message
8
+ exit 1
9
+ }
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env pwsh
2
+ . "$PSScriptRoot\lib\daemon.ps1"
3
+ try {
4
+ Invoke-PrizmDaemon -Kind feature -ScriptRoot $PSScriptRoot -RunScript (Join-Path $PSScriptRoot 'run-feature.ps1') -Args $args
5
+ exit $global:PRIZM_DAEMON_EXIT_CODE
6
+ } catch {
7
+ Write-PrizmError $_.Exception.Message
8
+ exit 1
9
+ }
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env pwsh
2
+ . "$PSScriptRoot\lib\daemon.ps1"
3
+ try {
4
+ Invoke-PrizmDaemon -Kind refactor -ScriptRoot $PSScriptRoot -RunScript (Join-Path $PSScriptRoot 'run-refactor.ps1') -Args $args
5
+ exit $global:PRIZM_DAEMON_EXIT_CODE
6
+ } catch {
7
+ Write-PrizmError $_.Exception.Message
8
+ exit 1
9
+ }
@@ -0,0 +1,432 @@
1
+ Set-StrictMode -Version 2.0
2
+ $ErrorActionPreference = 'Stop'
3
+
4
+ $script:PrizmAiProcess = $null
5
+
6
+ function Write-PrizmInfo { param([string]$Message) Write-Host "[INFO] $(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') $Message" -ForegroundColor Blue }
7
+ function Write-PrizmWarn { param([string]$Message) Write-Host "[WARN] $(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') $Message" -ForegroundColor Yellow }
8
+ function Write-PrizmError { param([string]$Message) Write-Host "[ERROR] $(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') $Message" -ForegroundColor Red }
9
+ function Write-PrizmSuccess { param([string]$Message) Write-Host "[SUCCESS] $(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') $Message" -ForegroundColor Green }
10
+
11
+ function Initialize-PrizmPaths {
12
+ param([string]$ScriptRoot)
13
+ $pipelineDir = Resolve-Path $ScriptRoot
14
+ $pipelineParent = Split-Path $pipelineDir -Parent
15
+ if ((Split-Path $pipelineParent -Leaf) -eq '.prizmkit') {
16
+ $prizmkitDir = $pipelineParent
17
+ $projectRoot = Split-Path $pipelineParent -Parent
18
+ } else {
19
+ $projectRoot = Split-Path $pipelineDir -Parent
20
+ $prizmkitDir = Join-Path $projectRoot '.prizmkit'
21
+ }
22
+ [pscustomobject]@{
23
+ PipelineDir = $pipelineDir.Path
24
+ PrizmkitDir = $prizmkitDir
25
+ ProjectRoot = $projectRoot
26
+ ScriptsDir = Join-Path $pipelineDir.Path 'scripts'
27
+ TemplatesDir = Join-Path $pipelineDir.Path 'templates'
28
+ }
29
+ }
30
+
31
+ function Import-PrizmEnv {
32
+ param([string]$EnvPath)
33
+ if (-not (Test-Path $EnvPath)) { return }
34
+ foreach ($line in Get-Content $EnvPath) {
35
+ $trimmed = $line.Trim()
36
+ if (-not $trimmed -or $trimmed.StartsWith('#')) { continue }
37
+ $idx = $trimmed.IndexOf('=')
38
+ if ($idx -lt 1) { continue }
39
+ $key = $trimmed.Substring(0, $idx).Trim()
40
+ $rawValue = $trimmed.Substring($idx + 1).Trim()
41
+ $valueBuilder = [System.Text.StringBuilder]::new()
42
+ $inSingleQuote = $false
43
+ $inDoubleQuote = $false
44
+ for ($i = 0; $i -lt $rawValue.Length; $i++) {
45
+ $char = $rawValue[$i]
46
+ if ($char -eq "'" -and -not $inDoubleQuote) { $inSingleQuote = -not $inSingleQuote }
47
+ if ($char -eq '"' -and -not $inSingleQuote) { $inDoubleQuote = -not $inDoubleQuote }
48
+ if ($char -eq '#' -and -not $inSingleQuote -and -not $inDoubleQuote) { break }
49
+ [void]$valueBuilder.Append($char)
50
+ }
51
+ $value = $valueBuilder.ToString().Trim().Trim('"').Trim("'")
52
+ if (-not [Environment]::GetEnvironmentVariable($key, 'Process')) {
53
+ [Environment]::SetEnvironmentVariable($key, $value, 'Process')
54
+ }
55
+ }
56
+ }
57
+
58
+ function Resolve-PrizmPython {
59
+ $python = Get-Command python -ErrorAction SilentlyContinue
60
+ if ($python) {
61
+ & $python.Source -c 'import sys; raise SystemExit(0 if sys.version_info[0] == 3 else 1)' *> $null
62
+ if ($LASTEXITCODE -eq 0) { return @($python.Source) }
63
+ }
64
+ $py = Get-Command py -ErrorAction SilentlyContinue
65
+ if ($py) {
66
+ & $py.Source -3 -c 'import sys; raise SystemExit(0 if sys.version_info[0] == 3 else 1)' *> $null
67
+ if ($LASTEXITCODE -eq 0) { return @($py.Source, '-3') }
68
+ }
69
+ throw 'Python 3 is required. Install Python and ensure python or py is in PATH.'
70
+ }
71
+
72
+ function Resolve-PrizmPowerShellHost {
73
+ $pwsh = Get-Command pwsh -ErrorAction SilentlyContinue
74
+ if ($pwsh) { return $pwsh.Source }
75
+ $powershell = Get-Command powershell -ErrorAction SilentlyContinue
76
+ if ($powershell) { return $powershell.Source }
77
+ throw 'PowerShell host not found. Install PowerShell or ensure powershell.exe is in PATH.'
78
+ }
79
+
80
+ function Invoke-PrizmPythonOutput {
81
+ param([string[]]$PythonCommand, [string[]]$Arguments)
82
+ $cmd = $PythonCommand[0]
83
+ $prefix = @()
84
+ if ($PythonCommand.Count -gt 1) { $prefix = $PythonCommand[1..($PythonCommand.Count - 1)] }
85
+ $output = & $cmd @prefix @Arguments
86
+ if ($LASTEXITCODE -ne 0) { throw "Python command failed: $($Arguments -join ' ')" }
87
+ if (-not $output) { return '' }
88
+ return ($output -join "`n")
89
+ }
90
+
91
+ function Invoke-PrizmPythonJson {
92
+ param([string[]]$PythonCommand, [string[]]$Arguments)
93
+ $text = Invoke-PrizmPythonOutput $PythonCommand $Arguments
94
+ if (-not $text) { return $null }
95
+ return $text | ConvertFrom-Json
96
+ }
97
+
98
+ function Invoke-PrizmPythonText {
99
+ param([string[]]$PythonCommand, [string[]]$Arguments)
100
+ $cmd = $PythonCommand[0]
101
+ $prefix = @()
102
+ if ($PythonCommand.Count -gt 1) { $prefix = $PythonCommand[1..($PythonCommand.Count - 1)] }
103
+ & $cmd @prefix @Arguments
104
+ if ($LASTEXITCODE -ne 0) { throw "Python command failed: $($Arguments -join ' ')" }
105
+ }
106
+
107
+ function Get-PrizmConfigValue {
108
+ param([string]$ConfigPath, [string]$Key)
109
+ if (-not (Test-Path $ConfigPath)) { return $null }
110
+ try {
111
+ $json = Get-Content $ConfigPath -Raw | ConvertFrom-Json
112
+ return $json.$Key
113
+ } catch { return $null }
114
+ }
115
+
116
+ function Split-PrizmCommandLine {
117
+ param([string]$CommandLine)
118
+ $trimmed = if ($CommandLine) { $CommandLine.Trim() } else { '' }
119
+ if (-not $trimmed) { throw 'AI CLI command is empty.' }
120
+ if (Test-Path $trimmed) {
121
+ return [pscustomobject]@{ Command = $trimmed; Arguments = '' }
122
+ }
123
+ if ($trimmed -match '^"([^"]+)"\s*(.*)$') {
124
+ return [pscustomobject]@{ Command = $matches[1]; Arguments = $matches[2].Trim() }
125
+ }
126
+ if ($trimmed -match "^'([^']+)'\s*(.*)$") {
127
+ return [pscustomobject]@{ Command = $matches[1]; Arguments = $matches[2].Trim() }
128
+ }
129
+ if ($trimmed -match '^(\S+)\s*(.*)$') {
130
+ return [pscustomobject]@{ Command = $matches[1]; Arguments = $matches[2].Trim() }
131
+ }
132
+ throw "Unable to parse AI CLI command: $CommandLine"
133
+ }
134
+
135
+ function Resolve-PrizmExecutableShim {
136
+ param([string]$Source)
137
+ if (-not $Source) { return $Source }
138
+
139
+ $extension = [System.IO.Path]::GetExtension($Source).ToLowerInvariant()
140
+ if ($extension -ne '.ps1') { return $Source }
141
+
142
+ $directory = [System.IO.Path]::GetDirectoryName($Source)
143
+ $baseName = [System.IO.Path]::GetFileNameWithoutExtension($Source)
144
+ if (-not $directory -or -not $baseName) { return $Source }
145
+
146
+ foreach ($candidateExtension in @('.cmd', '.bat', '.exe')) {
147
+ $candidate = Join-Path $directory ($baseName + $candidateExtension)
148
+ if (Test-Path $candidate) { return $candidate }
149
+ }
150
+
151
+ return $Source
152
+ }
153
+
154
+ function Resolve-PrizmCommandLine {
155
+ param([string]$CommandLine)
156
+ $parsed = Split-PrizmCommandLine $CommandLine
157
+ $command = @(Get-Command $parsed.Command -ErrorAction SilentlyContinue)[0]
158
+ if (-not $command) { return $CommandLine }
159
+ $source = if ($command.Source) { $command.Source } else { $command.Definition }
160
+ if (-not $source) { return $CommandLine }
161
+ $source = Resolve-PrizmExecutableShim $source
162
+ if ($source -match '\s') { $source = '"' + $source + '"' }
163
+ if ($parsed.Arguments) {
164
+ return "$source $($parsed.Arguments)"
165
+ }
166
+ return $source
167
+ }
168
+
169
+ function Get-PrizmCliNamesForPlatform {
170
+ param([string]$Platform)
171
+ $normalized = if ($Platform) { $Platform.ToLowerInvariant() } else { '' }
172
+ switch ($normalized) {
173
+ 'codex' { return @('codex') }
174
+ 'claude' { return @('claude') }
175
+ 'codebuddy' { return @('cbc') }
176
+ 'both' { return @('claude', 'cbc') }
177
+ 'all' { return @('codex', 'claude', 'cbc') }
178
+ default { return @() }
179
+ }
180
+ }
181
+
182
+ function Resolve-PrizmCliName {
183
+ param([string]$CliName)
184
+ if ($CliName -eq 'cbc' -and $env:CODEBUDDY_CLI) {
185
+ return Resolve-PrizmCommandLine $env:CODEBUDDY_CLI
186
+ }
187
+ if (Get-Command $CliName -ErrorAction SilentlyContinue) {
188
+ return Resolve-PrizmCommandLine $CliName
189
+ }
190
+ return ''
191
+ }
192
+
193
+ function Resolve-PrizmCliForPlatform {
194
+ param([string]$Platform)
195
+ foreach ($candidate in (Get-PrizmCliNamesForPlatform $Platform)) {
196
+ $cli = Resolve-PrizmCliName $candidate
197
+ if ($cli) { return $cli }
198
+ }
199
+ return ''
200
+ }
201
+
202
+ function Resolve-PrizmCliForPlatformRequirement {
203
+ param([string]$Platform, [string]$Source)
204
+ $expectedCliNames = @(Get-PrizmCliNamesForPlatform $Platform)
205
+ if ($expectedCliNames.Count -eq 0) { return '' }
206
+ $cli = Resolve-PrizmCliForPlatform $Platform
207
+ if ($cli) { return $cli }
208
+ $expectedCliText = $expectedCliNames -join ', '
209
+ throw "$Source PrizmKit platform '$Platform' requires one of: $expectedCliText. Install it or set AI_CLI."
210
+ }
211
+
212
+ function Resolve-PrizmAiCli {
213
+ param([string]$ProjectRoot, [string]$PrizmkitDir)
214
+ Import-PrizmEnv (Join-Path $PrizmkitDir '.env')
215
+ if ($env:AI_CLI) { return Resolve-PrizmCommandLine $env:AI_CLI }
216
+ $configured = Get-PrizmConfigValue (Join-Path $PrizmkitDir 'config.json') 'ai_cli'
217
+ if ($configured) { return Resolve-PrizmCommandLine $configured }
218
+
219
+ $manifestPlatform = Get-PrizmConfigValue (Join-Path $PrizmkitDir 'manifest.json') 'platform'
220
+ if ($manifestPlatform) {
221
+ $manifestCli = Resolve-PrizmCliForPlatformRequirement ([string]$manifestPlatform) 'Installed'
222
+ if ($manifestCli) { return $manifestCli }
223
+ }
224
+
225
+ $configuredPlatform = Get-PrizmConfigValue (Join-Path $PrizmkitDir 'config.json') 'platform'
226
+ if ($configuredPlatform) {
227
+ $configuredPlatformCli = Resolve-PrizmCliForPlatformRequirement ([string]$configuredPlatform) 'Configured'
228
+ if ($configuredPlatformCli) { return $configuredPlatformCli }
229
+ }
230
+
231
+ if ($env:CODEBUDDY_CLI) { return Resolve-PrizmCommandLine $env:CODEBUDDY_CLI }
232
+
233
+ if (((Test-Path (Join-Path $ProjectRoot '.codex\agents\prizm-dev-team-dev.toml')) -or (Test-Path (Join-Path $ProjectRoot '.agents\skills\prizm-kit\SKILL.md'))) -and (Get-Command codex -ErrorAction SilentlyContinue)) { return Resolve-PrizmCommandLine 'codex' }
234
+ if ((Test-Path (Join-Path $ProjectRoot '.claude\commands\prizm-kit.md')) -and (Get-Command claude -ErrorAction SilentlyContinue)) { return Resolve-PrizmCommandLine 'claude' }
235
+ if (((Test-Path (Join-Path $ProjectRoot '.codebuddy\agents\prizm-dev-team-dev.md')) -or (Test-Path (Join-Path $ProjectRoot '.codebuddy\skills\prizm-kit\SKILL.md'))) -and (Resolve-PrizmCliName 'cbc')) { return Resolve-PrizmCliName 'cbc' }
236
+ foreach ($candidate in @('codex', 'claude', 'cbc')) {
237
+ $cli = Resolve-PrizmCliName $candidate
238
+ if ($cli) { return $cli }
239
+ }
240
+ throw 'No AI CLI found. Install Codex (codex), Claude Code (claude), or CodeBuddy (cbc), or set AI_CLI.'
241
+ }
242
+
243
+ function Get-PrizmConcretePlatform {
244
+ param([string]$Platform)
245
+ $normalized = if ($Platform) { $Platform.ToLowerInvariant() } else { '' }
246
+ if (@('codex', 'claude', 'codebuddy') -contains $normalized) { return $normalized }
247
+ return ''
248
+ }
249
+
250
+ function Get-PrizmKnownPlatformFromCli {
251
+ param([string]$CliCommand)
252
+ $parsed = Split-PrizmCommandLine $CliCommand
253
+ $cliName = [System.IO.Path]::GetFileNameWithoutExtension($parsed.Command).ToLowerInvariant()
254
+ if ($cliName -match 'claude') { return 'claude' }
255
+ if ($cliName -match 'codex') { return 'codex' }
256
+ if ($cliName -match 'cbc|codebuddy') { return 'codebuddy' }
257
+ return ''
258
+ }
259
+
260
+ function ConvertTo-PrizmProcessArgument {
261
+ param([string]$Argument)
262
+ if ($Argument -eq $null) { return '""' }
263
+ if ($Argument -notmatch '[\s"]') { return $Argument }
264
+ return '"' + ($Argument -replace '"', '\"') + '"'
265
+ }
266
+
267
+ function Join-PrizmProcessArguments {
268
+ param([string[]]$Arguments)
269
+ return (($Arguments | ForEach-Object { ConvertTo-PrizmProcessArgument $_ }) -join ' ')
270
+ }
271
+
272
+ function Get-PrizmPlatformFromCli {
273
+ param([string]$CliCommand)
274
+ $platform = Get-PrizmKnownPlatformFromCli $CliCommand
275
+ if ($platform) { return $platform }
276
+ return 'codebuddy'
277
+ }
278
+
279
+ function Get-PrizmPlatformFromProject {
280
+ param([string]$ProjectRoot, [string]$PrizmkitDir, [string]$CliCommand)
281
+ $cliPlatform = Get-PrizmKnownPlatformFromCli $CliCommand
282
+ if ($cliPlatform) { return $cliPlatform }
283
+ $envPlatform = Get-PrizmConcretePlatform $env:PRIZMKIT_PLATFORM
284
+ if ($envPlatform) { return $envPlatform }
285
+ $manifestPlatform = Get-PrizmConcretePlatform (Get-PrizmConfigValue (Join-Path $PrizmkitDir 'manifest.json') 'platform')
286
+ if ($manifestPlatform) { return $manifestPlatform }
287
+ $configuredPlatform = Get-PrizmConcretePlatform (Get-PrizmConfigValue (Join-Path $PrizmkitDir 'config.json') 'platform')
288
+ if ($configuredPlatform) { return $configuredPlatform }
289
+ return Get-PrizmPlatformFromCli $CliCommand
290
+ }
291
+
292
+ function Get-PrizmSessionPlatform {
293
+ param([string]$CliCommand)
294
+ $cliPlatform = Get-PrizmKnownPlatformFromCli $CliCommand
295
+ if ($cliPlatform) { return $cliPlatform }
296
+ $platform = Get-PrizmConcretePlatform $env:PRIZMKIT_PLATFORM
297
+ if ($platform) { return $platform }
298
+ return Get-PrizmPlatformFromCli $CliCommand
299
+ }
300
+
301
+ function Stop-PrizmProcessTreeById {
302
+ param([int]$ProcessId)
303
+ if ($ProcessId -le 0) { return }
304
+
305
+ $process = Get-Process -Id $ProcessId -ErrorAction SilentlyContinue
306
+ if (-not $process) { return }
307
+
308
+ try {
309
+ $process.Kill($true)
310
+ return
311
+ } catch {
312
+ try {
313
+ $children = Get-CimInstance Win32_Process -Filter "ParentProcessId=$ProcessId" -ErrorAction SilentlyContinue
314
+ foreach ($child in $children) {
315
+ Stop-PrizmProcessTreeById -ProcessId ([int]$child.ProcessId)
316
+ }
317
+ } catch {
318
+ try {
319
+ $children = Get-WmiObject Win32_Process -Filter "ParentProcessId=$ProcessId" -ErrorAction SilentlyContinue
320
+ foreach ($child in $children) {
321
+ Stop-PrizmProcessTreeById -ProcessId ([int]$child.ProcessId)
322
+ }
323
+ } catch {}
324
+ }
325
+ try {
326
+ Stop-Process -Id $ProcessId -Force -ErrorAction SilentlyContinue
327
+ } catch {}
328
+ }
329
+ }
330
+
331
+ function Invoke-PrizmAiSession {
332
+ param(
333
+ [string]$CliCommand,
334
+ [string]$PromptPath,
335
+ [string]$LogPath,
336
+ [string]$ProjectRoot,
337
+ [string]$Model = '',
338
+ [string]$PidPath = ''
339
+ )
340
+ $prompt = Get-Content $PromptPath -Raw
341
+ $logDir = Split-Path $LogPath -Parent
342
+ New-Item -ItemType Directory -Force -Path $logDir | Out-Null
343
+
344
+ $psi = [System.Diagnostics.ProcessStartInfo]::new()
345
+ $psi.UseShellExecute = $false
346
+ $psi.RedirectStandardInput = $true
347
+ $psi.RedirectStandardOutput = $true
348
+ $psi.RedirectStandardError = $true
349
+ $psi.WorkingDirectory = $ProjectRoot
350
+ [void]$psi.Environment.Remove('CLAUDECODE')
351
+ $cliArgs = @()
352
+ $parsedCli = Split-PrizmCommandLine $CliCommand
353
+ $cliExecutable = $parsedCli.Command
354
+ $sessionPlatform = Get-PrizmSessionPlatform $CliCommand
355
+
356
+ if ($sessionPlatform -eq 'claude') {
357
+ $cliArgs += @('-p', '--dangerously-skip-permissions')
358
+ if ($Model) { $cliArgs += @('--model', $Model) }
359
+ } elseif ($sessionPlatform -eq 'codex') {
360
+ $cliArgs += @('--ask-for-approval', 'never', '--sandbox', 'danger-full-access', 'exec', '--cd', $ProjectRoot, '--skip-git-repo-check')
361
+ if ($Model) { $cliArgs += @('--model', $Model) }
362
+ $cliArgs += '-'
363
+ } else {
364
+ $cliArgs += @('--print', '-y')
365
+ if ($Model) { $cliArgs += @('--model', $Model) }
366
+ }
367
+ $generatedArgs = (($cliArgs | ForEach-Object { ConvertTo-PrizmProcessArgument $_ }) -join ' ')
368
+ $fullArgs = @()
369
+ if ($parsedCli.Arguments) { $fullArgs += $parsedCli.Arguments }
370
+ if ($generatedArgs) { $fullArgs += $generatedArgs }
371
+ $argumentString = ($fullArgs -join ' ')
372
+
373
+ $cliExtension = [System.IO.Path]::GetExtension($cliExecutable).ToLowerInvariant()
374
+
375
+ if ($cliExtension -in @('.cmd', '.bat')) {
376
+ $psi.FileName = if ($env:ComSpec) { $env:ComSpec } else { 'cmd.exe' }
377
+ $childCommand = (ConvertTo-PrizmProcessArgument $cliExecutable)
378
+ if ($argumentString) { $childCommand = "$childCommand $argumentString" }
379
+ $psi.Arguments = '/d /s /c "' + $childCommand + '"'
380
+ } elseif ($cliExtension -eq '.ps1') {
381
+ $psi.FileName = Resolve-PrizmPowerShellHost
382
+ $scriptArgs = @('-NoProfile', '-ExecutionPolicy', 'Bypass', '-File', $cliExecutable)
383
+ $scriptArgumentString = Join-PrizmProcessArguments $scriptArgs
384
+ if ($argumentString) { $scriptArgumentString = "$scriptArgumentString $argumentString" }
385
+ $psi.Arguments = $scriptArgumentString
386
+ } else {
387
+ $psi.FileName = $cliExecutable
388
+ $psi.Arguments = $argumentString
389
+ }
390
+
391
+ $process = [System.Diagnostics.Process]::Start($psi)
392
+ $script:PrizmAiProcess = $process
393
+ if ($PidPath) {
394
+ $pidDir = Split-Path $PidPath -Parent
395
+ if ($pidDir) { New-Item -ItemType Directory -Force -Path $pidDir | Out-Null }
396
+ Set-Content -Path $PidPath -Value ([string]$process.Id) -Encoding UTF8
397
+ }
398
+ $process.StandardInput.Write($prompt)
399
+ $process.StandardInput.Close()
400
+ $stdoutTask = $process.StandardOutput.ReadToEndAsync()
401
+ $stderrTask = $process.StandardError.ReadToEndAsync()
402
+ $process.WaitForExit()
403
+ $stdout = $stdoutTask.Result
404
+ $stderr = $stderrTask.Result
405
+ Set-Content -Path $LogPath -Value ($stdout + $stderr) -Encoding UTF8
406
+ return $process.ExitCode
407
+ }
408
+
409
+ function New-PrizmSessionId {
410
+ param([string]$Prefix)
411
+ return "$Prefix-$(Get-Date -Format 'yyyyMMdd-HHmmss')-$([guid]::NewGuid().ToString('N').Substring(0, 8))"
412
+ }
413
+
414
+ function Get-PrizmListDefault {
415
+ param([string]$Kind, [string]$ProjectRoot)
416
+ switch ($Kind) {
417
+ 'feature' { return Join-Path $ProjectRoot '.prizmkit\plans\feature-list.json' }
418
+ 'bugfix' { return Join-Path $ProjectRoot '.prizmkit\plans\bug-fix-list.json' }
419
+ 'refactor' { return Join-Path $ProjectRoot '.prizmkit\plans\refactor-list.json' }
420
+ default { throw "Unknown pipeline kind: $Kind" }
421
+ }
422
+ }
423
+
424
+ function Get-PrizmStateDir {
425
+ param([string]$Kind, [string]$ProjectRoot)
426
+ switch ($Kind) {
427
+ 'feature' { return Join-Path $ProjectRoot '.prizmkit\state\features' }
428
+ 'bugfix' { return Join-Path $ProjectRoot '.prizmkit\state\bugfix' }
429
+ 'refactor' { return Join-Path $ProjectRoot '.prizmkit\state\refactor' }
430
+ default { throw "Unknown pipeline kind: $Kind" }
431
+ }
432
+ }