prizmkit 1.1.100 → 1.1.101

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 (309) hide show
  1. package/bin/create-prizmkit.js +4 -4
  2. package/bundled/VERSION.json +3 -3
  3. package/bundled/dev-pipeline/.env.example +3 -3
  4. package/bundled/dev-pipeline/README.md +110 -90
  5. package/bundled/dev-pipeline/assets/prizm-dev-team-integration.md +1 -1
  6. package/bundled/dev-pipeline/cli.py +27 -0
  7. package/bundled/dev-pipeline/prizmkit_runtime/__init__.py +13 -0
  8. package/bundled/dev-pipeline/prizmkit_runtime/__main__.py +9 -0
  9. package/bundled/dev-pipeline/prizmkit_runtime/cli.py +193 -0
  10. package/bundled/dev-pipeline/prizmkit_runtime/commands.py +313 -0
  11. package/bundled/dev-pipeline/prizmkit_runtime/compat.py +32 -0
  12. package/bundled/dev-pipeline/prizmkit_runtime/config.py +410 -0
  13. package/bundled/dev-pipeline/prizmkit_runtime/daemon.py +478 -0
  14. package/bundled/dev-pipeline/prizmkit_runtime/gitops.py +734 -0
  15. package/bundled/dev-pipeline/prizmkit_runtime/heartbeat.py +256 -0
  16. package/bundled/dev-pipeline/prizmkit_runtime/interoperability.py +109 -0
  17. package/bundled/dev-pipeline/prizmkit_runtime/paths.py +110 -0
  18. package/bundled/dev-pipeline/prizmkit_runtime/processes.py +373 -0
  19. package/bundled/dev-pipeline/prizmkit_runtime/reset.py +389 -0
  20. package/bundled/dev-pipeline/prizmkit_runtime/runner_bookkeeping.py +51 -0
  21. package/bundled/dev-pipeline/prizmkit_runtime/runner_classification.py +179 -0
  22. package/bundled/dev-pipeline/prizmkit_runtime/runner_models.py +345 -0
  23. package/bundled/dev-pipeline/prizmkit_runtime/runner_prompts.py +118 -0
  24. package/bundled/dev-pipeline/prizmkit_runtime/runner_recovery.py +187 -0
  25. package/bundled/dev-pipeline/prizmkit_runtime/runner_status.py +147 -0
  26. package/bundled/dev-pipeline/prizmkit_runtime/runners.py +422 -0
  27. package/bundled/dev-pipeline/prizmkit_runtime/sessions.py +552 -0
  28. package/bundled/dev-pipeline/prizmkit_runtime/status.py +71 -0
  29. package/bundled/dev-pipeline/scripts/generate-bootstrap-prompt.py +38 -23
  30. package/bundled/dev-pipeline/scripts/generate-bugfix-prompt.py +20 -5
  31. package/bundled/dev-pipeline/scripts/generate-recovery-prompt.py +2 -2
  32. package/bundled/dev-pipeline/scripts/parse-stream-progress.py +39 -0
  33. package/bundled/dev-pipeline/templates/agent-prompts/dev-implement.md +7 -1
  34. package/bundled/dev-pipeline/templates/bootstrap-prompt.md +4 -0
  35. package/bundled/dev-pipeline/templates/bootstrap-tier1.md +12 -3
  36. package/bundled/dev-pipeline/templates/bootstrap-tier2.md +13 -3
  37. package/bundled/dev-pipeline/templates/bootstrap-tier3.md +13 -3
  38. package/bundled/dev-pipeline/templates/sections/context-budget-rules.md +2 -0
  39. package/bundled/dev-pipeline/templates/sections/log-size-awareness.md +9 -30
  40. package/bundled/dev-pipeline/templates/sections/phase-context-snapshot-agent-suffix.md +15 -7
  41. package/bundled/dev-pipeline/templates/sections/phase-implement-agent.md +42 -29
  42. package/bundled/dev-pipeline/templates/sections/phase-implement-full.md +41 -39
  43. package/bundled/dev-pipeline/templates/sections/test-failure-recovery-agent.md +4 -0
  44. package/bundled/dev-pipeline/templates/sections/test-failure-recovery-lite.md +4 -0
  45. package/bundled/dev-pipeline/tests/test_auto_skip.py +436 -14
  46. package/bundled/dev-pipeline/tests/test_generate_bootstrap_prompt.py +104 -0
  47. package/bundled/dev-pipeline/tests/test_generate_bugfix_prompt.py +40 -0
  48. package/bundled/dev-pipeline/tests/test_python_runner_parity.py +1138 -0
  49. package/bundled/dev-pipeline/tests/test_unified_cli.py +1045 -0
  50. package/bundled/skills/_metadata.json +1 -1
  51. package/bundled/skills/bugfix-pipeline-launcher/SKILL.md +29 -34
  52. package/bundled/skills/bugfix-pipeline-launcher/references/configuration.md +6 -5
  53. package/bundled/skills/feature-pipeline-launcher/SKILL.md +29 -35
  54. package/bundled/skills/feature-pipeline-launcher/references/configuration.md +7 -6
  55. package/bundled/skills/feature-workflow/SKILL.md +3 -6
  56. package/bundled/skills/recovery-workflow/SKILL.md +23 -32
  57. package/bundled/skills/refactor-pipeline-launcher/SKILL.md +29 -35
  58. package/bundled/skills/refactor-pipeline-launcher/references/configuration.md +7 -6
  59. package/bundled/skills/refactor-workflow/SKILL.md +3 -6
  60. package/bundled/templates/hooks/commit-intent.json +2 -2
  61. package/bundled/templates/hooks/diff-prizm-docs.py +226 -0
  62. package/bundled/templates/hooks/prizm-pre-commit.py +45 -0
  63. package/bundled/templates/hooks/validate-prizm-docs.py +240 -0
  64. package/package.json +1 -1
  65. package/src/config.js +33 -12
  66. package/src/index.js +3 -6
  67. package/src/manifest.js +3 -2
  68. package/src/metadata.js +7 -18
  69. package/src/prompts.js +0 -12
  70. package/src/runtimes.js +18 -11
  71. package/src/scaffold.js +133 -116
  72. package/src/upgrade.js +1 -1
  73. package/bundled/dev-pipeline/launch-bugfix-daemon.sh +0 -500
  74. package/bundled/dev-pipeline/launch-feature-daemon.sh +0 -657
  75. package/bundled/dev-pipeline/launch-refactor-daemon.sh +0 -502
  76. package/bundled/dev-pipeline/lib/branch.sh +0 -326
  77. package/bundled/dev-pipeline/lib/common.sh +0 -1476
  78. package/bundled/dev-pipeline/lib/heartbeat.sh +0 -469
  79. package/bundled/dev-pipeline/reset-bug.sh +0 -425
  80. package/bundled/dev-pipeline/reset-feature.sh +0 -436
  81. package/bundled/dev-pipeline/reset-refactor.sh +0 -423
  82. package/bundled/dev-pipeline/run-bugfix.sh +0 -1430
  83. package/bundled/dev-pipeline/run-feature.sh +0 -1718
  84. package/bundled/dev-pipeline/run-recovery.sh +0 -648
  85. package/bundled/dev-pipeline/run-refactor.sh +0 -1463
  86. package/bundled/dev-pipeline/tests/test-path-resolution.sh +0 -100
  87. package/bundled/dev-pipeline-windows/.env.example +0 -36
  88. package/bundled/dev-pipeline-windows/README.md +0 -30
  89. package/bundled/dev-pipeline-windows/SCHEMA_ANALYSIS.md +0 -533
  90. package/bundled/dev-pipeline-windows/assets/feature-list-example.json +0 -146
  91. package/bundled/dev-pipeline-windows/assets/prizm-dev-team-integration.md +0 -137
  92. package/bundled/dev-pipeline-windows/launch-bugfix-daemon.ps1 +0 -9
  93. package/bundled/dev-pipeline-windows/launch-feature-daemon.ps1 +0 -9
  94. package/bundled/dev-pipeline-windows/launch-refactor-daemon.ps1 +0 -9
  95. package/bundled/dev-pipeline-windows/lib/branch.ps1 +0 -235
  96. package/bundled/dev-pipeline-windows/lib/common.ps1 +0 -991
  97. package/bundled/dev-pipeline-windows/lib/daemon.ps1 +0 -140
  98. package/bundled/dev-pipeline-windows/lib/pipeline.ps1 +0 -1051
  99. package/bundled/dev-pipeline-windows/lib/reset.ps1 +0 -121
  100. package/bundled/dev-pipeline-windows/reset-bug.ps1 +0 -10
  101. package/bundled/dev-pipeline-windows/reset-feature.ps1 +0 -10
  102. package/bundled/dev-pipeline-windows/reset-refactor.ps1 +0 -10
  103. package/bundled/dev-pipeline-windows/run-bugfix.ps1 +0 -9
  104. package/bundled/dev-pipeline-windows/run-feature.ps1 +0 -9
  105. package/bundled/dev-pipeline-windows/run-recovery.ps1 +0 -179
  106. package/bundled/dev-pipeline-windows/run-refactor.ps1 +0 -9
  107. package/bundled/dev-pipeline-windows/scripts/check-session-status.py +0 -301
  108. package/bundled/dev-pipeline-windows/scripts/continuation.py +0 -374
  109. package/bundled/dev-pipeline-windows/scripts/detect-stuck.py +0 -530
  110. package/bundled/dev-pipeline-windows/scripts/generate-bootstrap-prompt.py +0 -2279
  111. package/bundled/dev-pipeline-windows/scripts/generate-bugfix-prompt.py +0 -763
  112. package/bundled/dev-pipeline-windows/scripts/generate-recovery-prompt.py +0 -805
  113. package/bundled/dev-pipeline-windows/scripts/generate-refactor-prompt.py +0 -841
  114. package/bundled/dev-pipeline-windows/scripts/init-bugfix-pipeline.py +0 -316
  115. package/bundled/dev-pipeline-windows/scripts/init-dev-team.py +0 -134
  116. package/bundled/dev-pipeline-windows/scripts/init-pipeline.py +0 -382
  117. package/bundled/dev-pipeline-windows/scripts/init-refactor-pipeline.py +0 -399
  118. package/bundled/dev-pipeline-windows/scripts/parse-stream-progress.py +0 -1362
  119. package/bundled/dev-pipeline-windows/scripts/patch-completion-notes.py +0 -191
  120. package/bundled/dev-pipeline-windows/scripts/prizmkit-test-gate.py +0 -446
  121. package/bundled/dev-pipeline-windows/scripts/update-bug-status.py +0 -1121
  122. package/bundled/dev-pipeline-windows/scripts/update-checkpoint.py +0 -173
  123. package/bundled/dev-pipeline-windows/scripts/update-feature-status.py +0 -1789
  124. package/bundled/dev-pipeline-windows/scripts/update-refactor-status.py +0 -1327
  125. package/bundled/dev-pipeline-windows/scripts/utils.py +0 -542
  126. package/bundled/dev-pipeline-windows/templates/agent-prompts/critic-plan-challenge.md +0 -7
  127. package/bundled/dev-pipeline-windows/templates/agent-prompts/dev-fix.md +0 -7
  128. package/bundled/dev-pipeline-windows/templates/agent-prompts/dev-implement.md +0 -65
  129. package/bundled/dev-pipeline-windows/templates/agent-prompts/dev-resume.md +0 -5
  130. package/bundled/dev-pipeline-windows/templates/agent-prompts/reviewer-review.md +0 -7
  131. package/bundled/dev-pipeline-windows/templates/bootstrap-prompt.md +0 -73
  132. package/bundled/dev-pipeline-windows/templates/bootstrap-tier1.md +0 -589
  133. package/bundled/dev-pipeline-windows/templates/bootstrap-tier2.md +0 -710
  134. package/bundled/dev-pipeline-windows/templates/bootstrap-tier3.md +0 -791
  135. package/bundled/dev-pipeline-windows/templates/bug-fix-list-schema.json +0 -263
  136. package/bundled/dev-pipeline-windows/templates/bugfix-bootstrap-prompt.md +0 -326
  137. package/bundled/dev-pipeline-windows/templates/feature-list-schema.json +0 -237
  138. package/bundled/dev-pipeline-windows/templates/refactor-bootstrap-prompt.md +0 -340
  139. package/bundled/dev-pipeline-windows/templates/refactor-list-schema.json +0 -270
  140. package/bundled/dev-pipeline-windows/templates/sections/ac-verification-checklist.md +0 -7
  141. package/bundled/dev-pipeline-windows/templates/sections/checkpoint-system.md +0 -91
  142. package/bundled/dev-pipeline-windows/templates/sections/context-budget-rules.md +0 -34
  143. package/bundled/dev-pipeline-windows/templates/sections/critical-paths-agent.md +0 -10
  144. package/bundled/dev-pipeline-windows/templates/sections/critical-paths-full.md +0 -12
  145. package/bundled/dev-pipeline-windows/templates/sections/critical-paths-lite.md +0 -7
  146. package/bundled/dev-pipeline-windows/templates/sections/directory-convention-agent.md +0 -8
  147. package/bundled/dev-pipeline-windows/templates/sections/directory-convention-full.md +0 -9
  148. package/bundled/dev-pipeline-windows/templates/sections/directory-convention-lite.md +0 -6
  149. package/bundled/dev-pipeline-windows/templates/sections/failure-capture.md +0 -21
  150. package/bundled/dev-pipeline-windows/templates/sections/feature-context.md +0 -21
  151. package/bundled/dev-pipeline-windows/templates/sections/log-size-awareness.md +0 -41
  152. package/bundled/dev-pipeline-windows/templates/sections/phase-browser-verification-auto.md +0 -283
  153. package/bundled/dev-pipeline-windows/templates/sections/phase-browser-verification-opencli.md +0 -112
  154. package/bundled/dev-pipeline-windows/templates/sections/phase-browser-verification.md +0 -168
  155. package/bundled/dev-pipeline-windows/templates/sections/phase-commit-full.md +0 -82
  156. package/bundled/dev-pipeline-windows/templates/sections/phase-commit.md +0 -75
  157. package/bundled/dev-pipeline-windows/templates/sections/phase-context-snapshot-agent-suffix.md +0 -23
  158. package/bundled/dev-pipeline-windows/templates/sections/phase-context-snapshot-base.md +0 -14
  159. package/bundled/dev-pipeline-windows/templates/sections/phase-context-snapshot-lite-suffix.md +0 -19
  160. package/bundled/dev-pipeline-windows/templates/sections/phase-critic-plan-full.md +0 -63
  161. package/bundled/dev-pipeline-windows/templates/sections/phase-critic-plan.md +0 -42
  162. package/bundled/dev-pipeline-windows/templates/sections/phase-implement-agent.md +0 -44
  163. package/bundled/dev-pipeline-windows/templates/sections/phase-implement-full.md +0 -59
  164. package/bundled/dev-pipeline-windows/templates/sections/phase-implement-lite.md +0 -39
  165. package/bundled/dev-pipeline-windows/templates/sections/phase-plan-agent.md +0 -27
  166. package/bundled/dev-pipeline-windows/templates/sections/phase-plan-lite.md +0 -27
  167. package/bundled/dev-pipeline-windows/templates/sections/phase-prizmkit-test.md +0 -39
  168. package/bundled/dev-pipeline-windows/templates/sections/phase-review-agent.md +0 -35
  169. package/bundled/dev-pipeline-windows/templates/sections/phase-review-full.md +0 -35
  170. package/bundled/dev-pipeline-windows/templates/sections/phase-specify-plan-full.md +0 -73
  171. package/bundled/dev-pipeline-windows/templates/sections/phase0-init.md +0 -13
  172. package/bundled/dev-pipeline-windows/templates/sections/phase0-test-baseline.md +0 -21
  173. package/bundled/dev-pipeline-windows/templates/sections/session-context.md +0 -5
  174. package/bundled/dev-pipeline-windows/templates/sections/subagent-timeout-recovery.md +0 -6
  175. package/bundled/dev-pipeline-windows/templates/sections/task-contract.md +0 -34
  176. package/bundled/dev-pipeline-windows/templates/sections/test-failure-recovery-agent.md +0 -48
  177. package/bundled/dev-pipeline-windows/templates/sections/test-failure-recovery-lite.md +0 -48
  178. package/bundled/dev-pipeline-windows/templates/session-status-schema.json +0 -83
  179. package/bundled/skills-windows/app-planner/SKILL.md +0 -296
  180. package/bundled/skills-windows/app-planner/assets/app-design-guide.md +0 -101
  181. package/bundled/skills-windows/app-planner/references/architecture-decisions.md +0 -52
  182. package/bundled/skills-windows/app-planner/references/brainstorm-guide.md +0 -101
  183. package/bundled/skills-windows/app-planner/references/frontend-design-guide.md +0 -71
  184. package/bundled/skills-windows/app-planner/references/infrastructure-convention-discovery.md +0 -108
  185. package/bundled/skills-windows/app-planner/references/project-brief-guide.md +0 -82
  186. package/bundled/skills-windows/app-planner/references/project-conventions-discovery.md +0 -59
  187. package/bundled/skills-windows/app-planner/references/project-state-detection.md +0 -90
  188. package/bundled/skills-windows/app-planner/references/red-team-checklist.md +0 -40
  189. package/bundled/skills-windows/app-planner/references/rules/backend/derivation-rules.md +0 -619
  190. package/bundled/skills-windows/app-planner/references/rules/backend/fixed-rules.md +0 -285
  191. package/bundled/skills-windows/app-planner/references/rules/backend/question-bank.md +0 -249
  192. package/bundled/skills-windows/app-planner/references/rules/backend/question-manifest.json +0 -46
  193. package/bundled/skills-windows/app-planner/references/rules/backend/template.md +0 -173
  194. package/bundled/skills-windows/app-planner/references/rules/database/derivation-rules.md +0 -382
  195. package/bundled/skills-windows/app-planner/references/rules/database/fixed-rules.md +0 -211
  196. package/bundled/skills-windows/app-planner/references/rules/database/question-bank.md +0 -184
  197. package/bundled/skills-windows/app-planner/references/rules/database/question-manifest.json +0 -39
  198. package/bundled/skills-windows/app-planner/references/rules/database/template.md +0 -158
  199. package/bundled/skills-windows/app-planner/references/rules/frontend/derivation-rules.md +0 -820
  200. package/bundled/skills-windows/app-planner/references/rules/frontend/fixed-rules.md +0 -188
  201. package/bundled/skills-windows/app-planner/references/rules/frontend/question-bank.md +0 -319
  202. package/bundled/skills-windows/app-planner/references/rules/frontend/question-manifest.json +0 -51
  203. package/bundled/skills-windows/app-planner/references/rules/frontend/template.md +0 -339
  204. package/bundled/skills-windows/app-planner/references/rules/mobile/derivation-rules.md +0 -649
  205. package/bundled/skills-windows/app-planner/references/rules/mobile/fixed-rules.md +0 -290
  206. package/bundled/skills-windows/app-planner/references/rules/mobile/question-bank.md +0 -232
  207. package/bundled/skills-windows/app-planner/references/rules/mobile/question-manifest.json +0 -47
  208. package/bundled/skills-windows/app-planner/references/rules/mobile/template.md +0 -175
  209. package/bundled/skills-windows/app-planner/references/rules-configuration.md +0 -46
  210. package/bundled/skills-windows/bug-fix-workflow/SKILL.md +0 -379
  211. package/bundled/skills-windows/bug-fix-workflow/references/bug-diagnosis.md +0 -41
  212. package/bundled/skills-windows/bug-planner/SKILL.md +0 -402
  213. package/bundled/skills-windows/bug-planner/assets/bug-confirmation-template.md +0 -43
  214. package/bundled/skills-windows/bug-planner/references/critic-and-verification.md +0 -44
  215. package/bundled/skills-windows/bug-planner/references/error-recovery.md +0 -73
  216. package/bundled/skills-windows/bug-planner/references/input-formats.md +0 -53
  217. package/bundled/skills-windows/bug-planner/references/schema-validation.md +0 -25
  218. package/bundled/skills-windows/bug-planner/references/severity-rules.md +0 -16
  219. package/bundled/skills-windows/bug-planner/scripts/validate-bug-list.py +0 -322
  220. package/bundled/skills-windows/bugfix-pipeline-launcher/SKILL.md +0 -304
  221. package/bundled/skills-windows/bugfix-pipeline-launcher/references/configuration.md +0 -84
  222. package/bundled/skills-windows/feature-pipeline-launcher/SKILL.md +0 -381
  223. package/bundled/skills-windows/feature-pipeline-launcher/references/configuration.md +0 -67
  224. package/bundled/skills-windows/feature-pipeline-launcher/scripts/preflight-check.py +0 -462
  225. package/bundled/skills-windows/feature-planner/SKILL.md +0 -397
  226. package/bundled/skills-windows/feature-planner/assets/evaluation-guide.md +0 -64
  227. package/bundled/skills-windows/feature-planner/assets/planning-guide.md +0 -214
  228. package/bundled/skills-windows/feature-planner/references/browser-interaction.md +0 -59
  229. package/bundled/skills-windows/feature-planner/references/completeness-review.md +0 -57
  230. package/bundled/skills-windows/feature-planner/references/decomposition-patterns.md +0 -75
  231. package/bundled/skills-windows/feature-planner/references/error-recovery.md +0 -90
  232. package/bundled/skills-windows/feature-planner/references/incremental-feature-planning.md +0 -112
  233. package/bundled/skills-windows/feature-planner/references/new-project-planning.md +0 -85
  234. package/bundled/skills-windows/feature-planner/scripts/validate-and-generate.py +0 -1020
  235. package/bundled/skills-windows/feature-workflow/SKILL.md +0 -374
  236. package/bundled/skills-windows/feature-workflow/references/brainstorm-guide.md +0 -137
  237. package/bundled/skills-windows/prizm-kit/SKILL.md +0 -93
  238. package/bundled/skills-windows/prizmkit-code-review/SKILL.md +0 -161
  239. package/bundled/skills-windows/prizmkit-code-review/references/dev-agent-prompt.md +0 -30
  240. package/bundled/skills-windows/prizmkit-code-review/references/review-report-template.md +0 -31
  241. package/bundled/skills-windows/prizmkit-code-review/references/reviewer-agent-prompt.md +0 -66
  242. package/bundled/skills-windows/prizmkit-code-review/scripts/check_loop.py +0 -186
  243. package/bundled/skills-windows/prizmkit-committer/SKILL.md +0 -89
  244. package/bundled/skills-windows/prizmkit-deploy/SKILL.md +0 -444
  245. package/bundled/skills-windows/prizmkit-deploy/references/ci-cd-workflows.md +0 -115
  246. package/bundled/skills-windows/prizmkit-deploy/references/cloud-platform-deploy.md +0 -93
  247. package/bundled/skills-windows/prizmkit-deploy/references/data-safety-examples.md +0 -120
  248. package/bundled/skills-windows/prizmkit-deploy/references/database-setup.md +0 -46
  249. package/bundled/skills-windows/prizmkit-deploy/references/deploy-config-schema.md +0 -148
  250. package/bundled/skills-windows/prizmkit-deploy/references/deploy-history-schema.md +0 -62
  251. package/bundled/skills-windows/prizmkit-deploy/references/deployment-modes.md +0 -50
  252. package/bundled/skills-windows/prizmkit-deploy/references/direct-upload.md +0 -26
  253. package/bundled/skills-windows/prizmkit-deploy/references/dns-setup.md +0 -42
  254. package/bundled/skills-windows/prizmkit-deploy/references/docker-deploy.md +0 -31
  255. package/bundled/skills-windows/prizmkit-deploy/references/firewall-setup.md +0 -37
  256. package/bundled/skills-windows/prizmkit-deploy/references/live-validation-notes.md +0 -21
  257. package/bundled/skills-windows/prizmkit-deploy/references/nginx-blue-green.md +0 -59
  258. package/bundled/skills-windows/prizmkit-deploy/references/ssh-bootstrap-flow.md +0 -49
  259. package/bundled/skills-windows/prizmkit-deploy/references/ssh-execution-flow.md +0 -41
  260. package/bundled/skills-windows/prizmkit-deploy/references/ssh-takeover.md +0 -20
  261. package/bundled/skills-windows/prizmkit-deploy/references/ssl-setup.md +0 -56
  262. package/bundled/skills-windows/prizmkit-implement/SKILL.md +0 -71
  263. package/bundled/skills-windows/prizmkit-init/SKILL.md +0 -356
  264. package/bundled/skills-windows/prizmkit-init/assets/project-brief-template.md +0 -82
  265. package/bundled/skills-windows/prizmkit-init/references/config-schema.md +0 -70
  266. package/bundled/skills-windows/prizmkit-init/references/rules/layer-detection.md +0 -41
  267. package/bundled/skills-windows/prizmkit-init/references/tech-stack-catalog.md +0 -13
  268. package/bundled/skills-windows/prizmkit-init/references/update-supplement.md +0 -9
  269. package/bundled/skills-windows/prizmkit-plan/SKILL.md +0 -102
  270. package/bundled/skills-windows/prizmkit-plan/assets/plan-template.md +0 -115
  271. package/bundled/skills-windows/prizmkit-plan/assets/spec-template.md +0 -73
  272. package/bundled/skills-windows/prizmkit-plan/references/clarify-guide.md +0 -67
  273. package/bundled/skills-windows/prizmkit-plan/references/examples.md +0 -85
  274. package/bundled/skills-windows/prizmkit-plan/references/verification-checklist.md +0 -60
  275. package/bundled/skills-windows/prizmkit-prizm-docs/SKILL.md +0 -129
  276. package/bundled/skills-windows/prizmkit-prizm-docs/assets/prizm-docs-format.md +0 -613
  277. package/bundled/skills-windows/prizmkit-prizm-docs/references/op-init.md +0 -45
  278. package/bundled/skills-windows/prizmkit-prizm-docs/references/op-rebuild.md +0 -15
  279. package/bundled/skills-windows/prizmkit-prizm-docs/references/op-status.md +0 -14
  280. package/bundled/skills-windows/prizmkit-prizm-docs/references/op-update.md +0 -19
  281. package/bundled/skills-windows/prizmkit-prizm-docs/references/op-validate.md +0 -17
  282. package/bundled/skills-windows/prizmkit-retrospective/SKILL.md +0 -87
  283. package/bundled/skills-windows/prizmkit-retrospective/references/knowledge-injection-steps.md +0 -50
  284. package/bundled/skills-windows/prizmkit-retrospective/references/structural-sync-steps.md +0 -43
  285. package/bundled/skills-windows/prizmkit-test/SKILL.md +0 -227
  286. package/bundled/skills-windows/prizmkit-test/references/boundary-coverage-protocol.md +0 -220
  287. package/bundled/skills-windows/prizmkit-test/references/examples.md +0 -143
  288. package/bundled/skills-windows/prizmkit-test/references/service-boundary-test-catalog.md +0 -225
  289. package/bundled/skills-windows/prizmkit-test/references/test-generation-steps.md +0 -109
  290. package/bundled/skills-windows/prizmkit-test/references/test-report-template.md +0 -111
  291. package/bundled/skills-windows/prizmkit-test/scripts/validate_boundary_report.py +0 -347
  292. package/bundled/skills-windows/recovery-workflow/SKILL.md +0 -355
  293. package/bundled/skills-windows/recovery-workflow/evals/evals.json +0 -46
  294. package/bundled/skills-windows/recovery-workflow/references/detection.md +0 -58
  295. package/bundled/skills-windows/recovery-workflow/scripts/detect-recovery-state.py +0 -544
  296. package/bundled/skills-windows/refactor-pipeline-launcher/SKILL.md +0 -346
  297. package/bundled/skills-windows/refactor-pipeline-launcher/references/configuration.md +0 -72
  298. package/bundled/skills-windows/refactor-planner/SKILL.md +0 -398
  299. package/bundled/skills-windows/refactor-planner/assets/planning-guide.md +0 -292
  300. package/bundled/skills-windows/refactor-planner/references/behavior-preservation.md +0 -301
  301. package/bundled/skills-windows/refactor-planner/references/fast-path.md +0 -59
  302. package/bundled/skills-windows/refactor-planner/references/planning-phases.md +0 -135
  303. package/bundled/skills-windows/refactor-planner/references/refactor-scoping-guide.md +0 -221
  304. package/bundled/skills-windows/refactor-planner/scripts/validate-and-generate-refactor.py +0 -858
  305. package/bundled/skills-windows/refactor-workflow/SKILL.md +0 -343
  306. package/bundled/skills-windows/refactor-workflow/references/brainstorm-guide.md +0 -116
  307. package/bundled/templates/hooks/diff-prizm-docs.sh +0 -158
  308. package/bundled/templates/hooks/prizm-pre-commit.sh +0 -108
  309. package/bundled/templates/hooks/validate-prizm-docs.sh +0 -139
@@ -1,1051 +0,0 @@
1
- . "$PSScriptRoot\common.ps1"
2
- . "$PSScriptRoot\branch.ps1"
3
- $global:PRIZM_EXIT_CODE = 0
4
-
5
- function Invoke-PrizmPipeline {
6
- param(
7
- [ValidateSet('feature','bugfix','refactor')][string]$Kind,
8
- [string]$ScriptRoot,
9
- [string[]]$Args
10
- )
11
-
12
- $paths = Initialize-PrizmPaths $ScriptRoot
13
- Import-PrizmEnv (Join-Path $paths.PrizmkitDir '.env')
14
- Set-Location $paths.ProjectRoot
15
- $python = Resolve-PrizmPython
16
-
17
- $command = if ($Args.Count -gt 0) { $Args[0] } else { 'help' }
18
- $remaining = if ($Args.Count -gt 1) { $Args[1..($Args.Count - 1)] } else { @() }
19
-
20
- $idName = @{ feature = 'feature'; bugfix = 'bug'; refactor = 'refactor' }[$Kind]
21
- $idOption = @{ feature = '--feature-id'; bugfix = '--bug-id'; refactor = '--refactor-id' }[$Kind]
22
- $listOption = @{ feature = '--feature-list'; bugfix = '--bug-list'; refactor = '--refactor-list' }[$Kind]
23
- $initScript = @{ feature = 'init-pipeline.py'; bugfix = 'init-bugfix-pipeline.py'; refactor = 'init-refactor-pipeline.py' }[$Kind]
24
- $updateScript = @{ feature = 'update-feature-status.py'; bugfix = 'update-bug-status.py'; refactor = 'update-refactor-status.py' }[$Kind]
25
- $promptScript = @{ feature = 'generate-bootstrap-prompt.py'; bugfix = 'generate-bugfix-prompt.py'; refactor = 'generate-refactor-prompt.py' }[$Kind]
26
- $defaultList = Get-PrizmListDefault $Kind $paths.ProjectRoot
27
- $stateDir = Get-PrizmStateDir $Kind $paths.ProjectRoot
28
- $envMaxRetryArgs = @()
29
- if ($env:MAX_RETRIES) {
30
- $parsedEnvMaxRetries = 0
31
- if (-not [int]::TryParse($env:MAX_RETRIES, [ref]$parsedEnvMaxRetries) -or $parsedEnvMaxRetries -lt 1) {
32
- throw "MAX_RETRIES must be a positive integer: $($env:MAX_RETRIES)"
33
- }
34
- $envMaxRetryArgs = @('--max-retries', [string]$parsedEnvMaxRetries)
35
- }
36
-
37
- $envMaxInfraRetryArgs = @()
38
- if ($env:MAX_INFRA_RETRIES) {
39
- $parsedEnvMaxInfraRetries = 0
40
- if (-not [int]::TryParse($env:MAX_INFRA_RETRIES, [ref]$parsedEnvMaxInfraRetries) -or $parsedEnvMaxInfraRetries -lt 1) {
41
- throw "MAX_INFRA_RETRIES must be a positive integer: $($env:MAX_INFRA_RETRIES)"
42
- }
43
- $envMaxInfraRetryArgs = @('--max-infra-retries', [string]$parsedEnvMaxInfraRetries)
44
- }
45
-
46
- if ($command -in @('help','--help','-h')) {
47
- Write-Host "Usage: .\run-$Kind.ps1 run [item-id] [list-path] [--dry-run] [--mode lite|standard|full] [--critic] [--max-retries N] [--max-infra-retries N]"
48
- Write-Host " .\run-$Kind.ps1 status [list-path]"
49
- Write-Host " .\run-$Kind.ps1 reset"
50
- Write-Host ""
51
- Write-Host "Environment Variables:"
52
- Write-Host " PRIZMKIT_EFFORT AI reasoning effort (low|medium|high|xhigh|max; max is Claude Code only)"
53
- Write-Host " MAX_LOG_SIZE Include passive log-size checkpoint guidance above this threshold (default: 2097152 = 2MB, set 0 to disable)"
54
- $global:PRIZM_EXIT_CODE = 0
55
- return
56
- }
57
-
58
- if ($command -eq 'reset') {
59
- if (Test-Path $stateDir) { Remove-Item -Recurse -Force $stateDir }
60
- New-Item -ItemType Directory -Force -Path $stateDir | Out-Null
61
- Write-PrizmSuccess "State reset: $stateDir"
62
- $global:PRIZM_EXIT_CODE = 0
63
- return
64
- }
65
-
66
- if ($command -eq 'status') {
67
- $listPath = if ($remaining.Count -gt 0) { $remaining[0] } else { $defaultList }
68
- Invoke-PrizmPythonText $python (@((Join-Path $paths.ScriptsDir $updateScript), $listOption, $listPath, '--state-dir', $stateDir, '--action', 'status') + $envMaxRetryArgs + $envMaxInfraRetryArgs)
69
- $global:PRIZM_EXIT_CODE = $LASTEXITCODE
70
- return
71
- }
72
-
73
- if ($command -ne 'run') { throw "Unknown command: $command" }
74
-
75
- $itemId = $null
76
- $listPath = $defaultList
77
- $dryRun = $false
78
- $mode = $null
79
- if ($env:PIPELINE_MODE) { $mode = $env:PIPELINE_MODE.Trim() }
80
- $critic = $null
81
- $criticEnv = if ($env:ENABLE_CRITIC) { $env:ENABLE_CRITIC.Trim().ToLowerInvariant() } else { '' }
82
- if ($criticEnv -in @('true','1','yes','on')) {
83
- $critic = 'true'
84
- } elseif ($criticEnv -in @('false','0','no','off')) {
85
- $critic = 'false'
86
- } elseif ($criticEnv) {
87
- Write-PrizmWarn "Ignoring unsupported ENABLE_CRITIC value: $($env:ENABLE_CRITIC)"
88
- }
89
- $maxRetries = $null
90
- if ($envMaxRetryArgs.Count -gt 0) { $maxRetries = [int]$envMaxRetryArgs[1] }
91
- $maxInfraRetries = $null
92
- if ($envMaxInfraRetryArgs.Count -gt 0) { $maxInfraRetries = [int]$envMaxInfraRetryArgs[1] }
93
- $verboseEnabled = $env:VERBOSE -in @('1','true','yes','on')
94
- $heartbeatInterval = 30
95
- if ($env:HEARTBEAT_INTERVAL) {
96
- $parsedHeartbeatInterval = 0
97
- if (-not [int]::TryParse($env:HEARTBEAT_INTERVAL, [ref]$parsedHeartbeatInterval) -or $parsedHeartbeatInterval -lt 1) {
98
- throw "HEARTBEAT_INTERVAL must be a positive integer: $($env:HEARTBEAT_INTERVAL)"
99
- }
100
- $heartbeatInterval = $parsedHeartbeatInterval
101
- }
102
- $staleKillThreshold = 900
103
- if ($env:STALE_KILL_THRESHOLD) {
104
- $parsedStaleKillThreshold = 0
105
- if (-not [int]::TryParse($env:STALE_KILL_THRESHOLD, [ref]$parsedStaleKillThreshold) -or $parsedStaleKillThreshold -lt 0) {
106
- throw "STALE_KILL_THRESHOLD must be a non-negative integer: $($env:STALE_KILL_THRESHOLD)"
107
- }
108
- $staleKillThreshold = $parsedStaleKillThreshold
109
- }
110
- $staleKillGraceSeconds = 10
111
- if ($env:STALE_KILL_GRACE_SECONDS) {
112
- $parsedStaleKillGraceSeconds = 0
113
- if (-not [int]::TryParse($env:STALE_KILL_GRACE_SECONDS, [ref]$parsedStaleKillGraceSeconds) -or $parsedStaleKillGraceSeconds -lt 0) {
114
- throw "STALE_KILL_GRACE_SECONDS must be a non-negative integer: $($env:STALE_KILL_GRACE_SECONDS)"
115
- }
116
- $staleKillGraceSeconds = $parsedStaleKillGraceSeconds
117
- }
118
- $autoPush = $env:AUTO_PUSH -in @('1','true','yes','on')
119
- $enableDeploy = $env:ENABLE_DEPLOY -in @('1','true','yes','on')
120
- $stopOnFailure = $env:STOP_ON_FAILURE -in @('1','true','yes','on')
121
- $devBranchOverride = if ($env:DEV_BRANCH) { $env:DEV_BRANCH.Trim() } else { '' }
122
- $featuresFilter = $null
123
-
124
- for ($i = 0; $i -lt $remaining.Count; $i++) {
125
- $arg = $remaining[$i]
126
- switch -Regex ($arg) {
127
- '^--dry-run$' { $dryRun = $true; continue }
128
- '^--critic$' { $critic = 'true'; continue }
129
- '^--no-critic$' { $critic = 'false'; continue }
130
- '^--mode$' { $i++; $mode = $remaining[$i]; continue }
131
- '^--max-retries$' {
132
- $i++
133
- $parsedMaxRetries = 0
134
- if (-not [int]::TryParse($remaining[$i], [ref]$parsedMaxRetries) -or $parsedMaxRetries -lt 1) {
135
- throw "--max-retries must be a positive integer: $($remaining[$i])"
136
- }
137
- $maxRetries = $parsedMaxRetries
138
- continue
139
- }
140
- '^--max-infra-retries$' {
141
- $i++
142
- $parsedMaxInfraRetries = 0
143
- if (-not [int]::TryParse($remaining[$i], [ref]$parsedMaxInfraRetries) -or $parsedMaxInfraRetries -lt 1) {
144
- throw "--max-infra-retries must be a positive integer: $($remaining[$i])"
145
- }
146
- $maxInfraRetries = $parsedMaxInfraRetries
147
- continue
148
- }
149
- '^--features$' { $i++; $featuresFilter = $remaining[$i]; continue }
150
- '^-' { Write-PrizmWarn "Ignoring unsupported option: $arg"; continue }
151
- default {
152
- if (-not $itemId -and $arg -match '^[FBR]-\d+') { $itemId = $arg; continue }
153
- $listPath = $arg
154
- }
155
- }
156
- }
157
-
158
- if ($mode -and $mode -notin @('lite','standard','full')) {
159
- throw "PIPELINE_MODE/--mode must be one of: lite, standard, full. Got: $mode"
160
- }
161
- $maxRetryArgs = @()
162
- if ($maxRetries -ne $null) { $maxRetryArgs = @('--max-retries', [string]$maxRetries) }
163
- $maxInfraRetryArgs = @()
164
- if ($maxInfraRetries -ne $null) { $maxInfraRetryArgs = @('--max-infra-retries', [string]$maxInfraRetries) }
165
- if ($verboseEnabled) {
166
- $modeLabel = if ($mode) { $mode } else { 'auto' }
167
- $criticLabel = if ($critic) { $critic } else { 'plan-default' }
168
- $retryLabel = if ($maxRetries -ne $null) { [string]$maxRetries } else { 'default' }
169
- $infraRetryLabel = if ($maxInfraRetries -ne $null) { [string]$maxInfraRetries } else { 'default' }
170
- Write-PrizmInfo "Verbose mode enabled."
171
- Write-PrizmInfo "Effective options: mode=$modeLabel critic=$criticLabel maxRetries=$retryLabel maxInfraRetries=$infraRetryLabel staleKillThreshold=$staleKillThreshold dryRun=$dryRun"
172
- }
173
-
174
- # Validate PRIZMKIT_EFFORT early (fail-fast before any sessions are spawned)
175
- $cli = Resolve-PrizmAiCli $paths.ProjectRoot $paths.PrizmkitDir
176
- Test-PrizmEffort $cli
177
-
178
- if (-not (Test-Path $listPath)) { throw "List file not found: $listPath" }
179
- $pipelineStatePath = Join-Path $stateDir 'pipeline.json'
180
- if (-not $dryRun) {
181
- New-Item -ItemType Directory -Force -Path $stateDir | Out-Null
182
- if (-not (Test-Path $pipelineStatePath)) {
183
- Invoke-PrizmPythonText $python @((Join-Path $paths.ScriptsDir $initScript), $listOption, $listPath, '--state-dir', $stateDir)
184
- } else {
185
- Write-PrizmInfo "Using existing pipeline state: $pipelineStatePath"
186
- }
187
- } elseif (-not (Test-Path $pipelineStatePath)) {
188
- Write-PrizmInfo "Dry-run mode: not initializing pipeline state."
189
- }
190
-
191
- function Test-PrizmGitRepository {
192
- param([string]$ProjectRoot)
193
- & git -C $ProjectRoot rev-parse --is-inside-work-tree *> $null
194
- return $LASTEXITCODE -eq 0
195
- }
196
-
197
- function Get-PrizmGitHead {
198
- param([string]$ProjectRoot)
199
- $head = & git -C $ProjectRoot rev-parse HEAD 2>$null
200
- if ($LASTEXITCODE -eq 0 -and $head) { return ($head | Select-Object -First 1) }
201
- return ''
202
- }
203
-
204
- function Test-PrizmGitCommitsSince {
205
- param([string]$ProjectRoot, [string]$BaseCommit)
206
- if (-not $BaseCommit) {
207
- return -not [string]::IsNullOrWhiteSpace([string](Get-PrizmGitHead $ProjectRoot))
208
- }
209
- $commit = & git -C $ProjectRoot log "$BaseCommit..HEAD" --oneline 2>$null | Select-Object -First 1
210
- return -not [string]::IsNullOrWhiteSpace([string]$commit)
211
- }
212
-
213
- function ConvertTo-PrizmGitRelativePath {
214
- param([string]$ProjectRoot, [string]$Path)
215
- if (-not $Path) { return '' }
216
- try {
217
- $rootFull = [System.IO.Path]::GetFullPath($ProjectRoot).TrimEnd([char[]]@('\', '/')) + [System.IO.Path]::DirectorySeparatorChar
218
- $pathInput = if ([System.IO.Path]::IsPathRooted($Path)) { $Path } else { Join-Path $ProjectRoot $Path }
219
- $pathFull = [System.IO.Path]::GetFullPath($pathInput)
220
- $rootUri = [System.Uri]::new($rootFull)
221
- $pathUri = [System.Uri]::new($pathFull)
222
- return ([System.Uri]::UnescapeDataString($rootUri.MakeRelativeUri($pathUri).ToString()) -replace '\\', '/').TrimStart([char[]]@('.', '/'))
223
- } catch {
224
- return ($Path -replace '\\', '/').TrimStart([char[]]@('.', '/'))
225
- }
226
- }
227
-
228
- function Get-PrizmGitDirtyPaths {
229
- param([string]$ProjectRoot)
230
- $hiddenToolWorktreeExcludes = Get-PrizmHiddenToolWorktreeExcludes
231
- $lines = & git -C $ProjectRoot status --porcelain -- . @hiddenToolWorktreeExcludes 2>$null
232
- $paths = @()
233
- foreach ($line in $lines) {
234
- if ([string]::IsNullOrWhiteSpace($line) -or $line.Length -lt 4) { continue }
235
- $path = $line.Substring(3).Trim()
236
- if ($path -match ' -> ') { $path = ($path -split ' -> ')[-1].Trim() }
237
- $paths += (($path -replace '\\', '/').Trim('"').TrimStart([char[]]@('/')))
238
- }
239
- return @($paths)
240
- }
241
-
242
- function Test-PrizmPipelineIgnoredPath {
243
- param([string]$Path)
244
- $normalizedPath = (($Path -replace '\\', '/').Trim('"').TrimStart([char[]]@('/')))
245
- $segments = @($normalizedPath -split '/' | Where-Object { -not [string]::IsNullOrWhiteSpace($_) })
246
- if ($segments.Count -lt 2) { return $false }
247
- if (-not $segments[0].StartsWith('.')) { return $false }
248
- return $segments[1] -in @('worktree', 'worktrees')
249
- }
250
-
251
- function Test-PrizmPipelineBookkeepingPath {
252
- param(
253
- [string]$ProjectRoot,
254
- [string]$Path,
255
- [string]$StateDir,
256
- [string]$ListPath
257
- )
258
- $normalizedPath = (($Path -replace '\\', '/').Trim('"').TrimStart([char[]]@('.', '/')))
259
- $stateRel = ConvertTo-PrizmGitRelativePath $ProjectRoot $StateDir
260
- $listRel = ConvertTo-PrizmGitRelativePath $ProjectRoot $ListPath
261
- if ($stateRel -and ($normalizedPath -eq $stateRel -or $normalizedPath.StartsWith("$stateRel/"))) { return $true }
262
- if ($listRel -and $normalizedPath -eq $listRel) { return $true }
263
- return $false
264
- }
265
-
266
- function Test-PrizmGitWorkDirty {
267
- param([string]$ProjectRoot, [string]$StateDir, [string]$ListPath)
268
- foreach ($path in (Get-PrizmGitDirtyPaths $ProjectRoot)) {
269
- if (Test-PrizmPipelineIgnoredPath $path) { continue }
270
- if (-not (Test-PrizmPipelineBookkeepingPath $ProjectRoot $path $StateDir $ListPath)) {
271
- return $true
272
- }
273
- }
274
- return $false
275
- }
276
-
277
- function Test-PrizmGitDirty {
278
- param([string]$ProjectRoot)
279
- $hiddenToolWorktreeExcludes = Get-PrizmHiddenToolWorktreeExcludes
280
- $dirty = & git -C $ProjectRoot status --porcelain -- . @hiddenToolWorktreeExcludes 2>$null | Select-Object -First 1
281
- return -not [string]::IsNullOrWhiteSpace([string]$dirty)
282
- }
283
-
284
- function Stop-PrizmSessionProcess {
285
- param([string]$PidPath)
286
- if (-not (Test-Path $PidPath)) { return }
287
- $rawPid = Get-Content $PidPath -ErrorAction SilentlyContinue | Select-Object -First 1
288
- $aiPid = 0
289
- if ([int]::TryParse($rawPid, [ref]$aiPid)) {
290
- Stop-PrizmProcessTreeById -ProcessId $aiPid
291
- }
292
- }
293
-
294
- function Write-PrizmStaleKillMarker {
295
- param([string]$MarkerPath, [int]$StaleSeconds, [int]$Threshold)
296
- $markerDir = Split-Path $MarkerPath -Parent
297
- if ($markerDir) { New-Item -ItemType Directory -Force -Path $markerDir | Out-Null }
298
- [ordered]@{
299
- killed_at = (Get-Date).ToUniversalTime().ToString('yyyy-MM-ddTHH:mm:ssZ')
300
- reason = 'stale_session'
301
- stale_seconds = $StaleSeconds
302
- threshold = $Threshold
303
- } | ConvertTo-Json -Compress | Set-Content -Path $MarkerPath -Encoding UTF8
304
- }
305
-
306
- function Invoke-PrizmGitAutoCommit {
307
- param([string]$ProjectRoot, [string]$Message)
308
- $hiddenToolWorktreeExcludes = Get-PrizmHiddenToolWorktreeExcludes
309
- & git -C $ProjectRoot add -A -- . @hiddenToolWorktreeExcludes *> $null
310
- & git -C $ProjectRoot commit --no-verify -m $Message *> $null
311
- return $LASTEXITCODE -eq 0
312
- }
313
-
314
- function Invoke-PrizmGitIncludeRemainingArtifacts {
315
- param([string]$ProjectRoot, [string]$ItemId)
316
- $hiddenToolWorktreeExcludes = Get-PrizmHiddenToolWorktreeExcludes
317
- & git -C $ProjectRoot add -A -- . @hiddenToolWorktreeExcludes *> $null
318
- & git -C $ProjectRoot commit --no-verify --amend --no-edit *> $null
319
- if ($LASTEXITCODE -eq 0) { return }
320
- & git -C $ProjectRoot commit --no-verify -m "chore($ItemId): include remaining session artifacts" *> $null
321
- }
322
-
323
- function Invoke-PrizmGitIncludeBookkeepingArtifacts {
324
- param([string]$ProjectRoot, [string]$StateDir, [string]$ListPath)
325
- $listRel = ConvertTo-PrizmGitRelativePath $ProjectRoot $ListPath
326
- if (-not $listRel) { return }
327
- & git -C $ProjectRoot ls-files --error-unmatch -- $listRel *> $null
328
- if ($LASTEXITCODE -ne 0) { return }
329
- & git -C $ProjectRoot commit --no-verify --amend --no-edit --only -- $listRel *> $null
330
- }
331
-
332
- function Invoke-PrizmGitCommitPath {
333
- param([string]$ProjectRoot, [string]$Path, [string]$Message)
334
- if (-not $Path) { return $false }
335
- $relPath = ConvertTo-PrizmGitRelativePath $ProjectRoot $Path
336
- if (-not $relPath) { return $false }
337
- & git -C $ProjectRoot diff --quiet -- $relPath 2>$null
338
- if ($LASTEXITCODE -eq 0) { return $false }
339
- & git -C $ProjectRoot add -- $relPath *> $null
340
- if ($LASTEXITCODE -ne 0) { return $false }
341
- & git -C $ProjectRoot commit --no-verify -m $Message *> $null
342
- return $LASTEXITCODE -eq 0
343
- }
344
-
345
- function Get-PrizmFeatureSlugFromList {
346
- param([string]$ListPath, [string]$FeatureId)
347
- if (-not (Test-Path $ListPath)) { return '' }
348
- try { $data = Get-Content $ListPath -Raw | ConvertFrom-Json } catch { return '' }
349
- foreach ($feature in @($data.features)) {
350
- if ($feature.id -eq $FeatureId) {
351
- $number = ([string]$feature.id).Replace('F-', '').Replace('f-', '').PadLeft(3, '0')
352
- $title = ([string]$feature.title).ToLowerInvariant()
353
- $title = [regex]::Replace($title, '[^a-z0-9\s-]', '')
354
- $title = [regex]::Replace($title.Trim(), '[\s]+', '-')
355
- $title = [regex]::Replace($title, '-+', '-').Trim('-')
356
- if ($title) { return "$number-$title" }
357
- return $number
358
- }
359
- }
360
- return ''
361
- }
362
-
363
- function Test-PrizmCheckpointComplete {
364
- param([string]$CheckpointPath)
365
- if (-not (Test-Path $CheckpointPath)) { return $false }
366
- try { $checkpoint = Get-Content $CheckpointPath -Raw | ConvertFrom-Json } catch { return $false }
367
- if (-not $checkpoint.steps) { return $false }
368
- foreach ($step in @($checkpoint.steps)) {
369
- if ($step.status -notin @('completed', 'skipped')) { return $false }
370
- }
371
- return $true
372
- }
373
-
374
- function Get-PrizmFeatureTitleFromList {
375
- param([string]$ListPath, [string]$FeatureId)
376
- if (-not (Test-Path $ListPath)) { return '' }
377
- try { $data = Get-Content $ListPath -Raw | ConvertFrom-Json } catch { return '' }
378
- foreach ($feature in @($data.features)) {
379
- if ($feature.id -eq $FeatureId) { return [string]$feature.title }
380
- }
381
- return ''
382
- }
383
-
384
- function Get-PrizmTitleWords {
385
- param([string]$Text)
386
- $matches = [regex]::Matches(([string]$Text).ToLowerInvariant(), '[a-z0-9]{3,}')
387
- $words = @()
388
- foreach ($match in $matches) { $words += [string]$match.Value }
389
- return @($words)
390
- }
391
-
392
- function Test-PrizmCommitMatchesFeatureTitle {
393
- param([string]$Subject, [string]$FeatureTitle)
394
- $titleWords = @(Get-PrizmTitleWords $FeatureTitle)
395
- if ($titleWords.Count -eq 0) { return $false }
396
- $subjectWords = @(Get-PrizmTitleWords $Subject)
397
- $subjectSet = @{}
398
- foreach ($word in $subjectWords) { $subjectSet[$word] = $true }
399
- $required = if ($titleWords.Count -le 3) { $titleWords.Count } else { [Math]::Max(3, [int][Math]::Ceiling($titleWords.Count * 0.75)) }
400
- $matched = 0
401
- foreach ($word in $titleWords) {
402
- if ($subjectSet.ContainsKey($word)) { $matched++ }
403
- }
404
- return $matched -ge $required
405
- }
406
-
407
- function Get-PrizmFeatureCommit {
408
- param([string]$ProjectRoot, [string]$BaseCommit, [string]$FeatureId, [bool]$AllowFallback = $false, [string]$FeatureTitle = '')
409
- $range = if ($BaseCommit) { "$BaseCommit..HEAD" } else { 'HEAD' }
410
- $lines = & git -C $ProjectRoot log $range '--format=%H%x09%s' 2>$null
411
- if ($LASTEXITCODE -ne 0) { return '' }
412
- foreach ($line in @($lines)) {
413
- $parts = ([string]$line).Split("`t", 2)
414
- if ($parts.Count -lt 2) { continue }
415
- $subject = $parts[1]
416
- if ($subject.Contains($FeatureId) -and $subject -notmatch '^wip(\(|:)') { return $parts[0] }
417
- }
418
- if ($AllowFallback -and $FeatureTitle) {
419
- foreach ($line in @($lines)) {
420
- $parts = ([string]$line).Split("`t", 2)
421
- if ($parts.Count -lt 2) { continue }
422
- $subject = $parts[1]
423
- if ($subject -notmatch '^wip(\(|:)' -and (Test-PrizmCommitMatchesFeatureTitle $subject $FeatureTitle)) { return $parts[0] }
424
- }
425
- }
426
- return ''
427
- }
428
-
429
- function Get-PrizmFeatureSemanticCompletion {
430
- param([string]$ProjectRoot, [string]$ListPath, [string]$FeatureId, [string]$BaseCommit, [string]$PrizmkitDir)
431
- $slug = Get-PrizmFeatureSlugFromList $ListPath $FeatureId
432
- if (-not $slug) { return $null }
433
- $checkpointPath = Join-Path $PrizmkitDir "specs\$slug\workflow-checkpoint.json"
434
- if (-not (Test-PrizmCheckpointComplete $checkpointPath)) { return $null }
435
- $featureTitle = Get-PrizmFeatureTitleFromList $ListPath $FeatureId
436
- $commitSha = Get-PrizmFeatureCommit $ProjectRoot $BaseCommit $FeatureId $true $featureTitle
437
- if (-not $commitSha) { return $null }
438
- return [pscustomobject]@{ Slug = $slug; CommitSha = $commitSha; CheckpointPath = $checkpointPath }
439
- }
440
-
441
- function Write-PrizmRuntimeFailureLog {
442
- param(
443
- [string]$FailureLog,
444
- [string]$FeatureId,
445
- [string]$SessionId,
446
- [string]$SessionStatus,
447
- [int]$ExitCode,
448
- [string]$StaleKillMarker,
449
- [string]$ProgressJson,
450
- [string]$CheckpointPath,
451
- [string]$ProjectRoot,
452
- [string]$BaseCommit
453
- )
454
- if (-not $FailureLog -or (Test-Path $FailureLog)) { return }
455
- $dir = Split-Path $FailureLog -Parent
456
- if ($dir) { New-Item -ItemType Directory -Force -Path $dir | Out-Null }
457
- $stale = if (Test-Path $StaleKillMarker) { Get-Content $StaleKillMarker -Raw } else { 'No stale-kill marker.' }
458
- $progressLines = @('Progress data unavailable.')
459
- if (Test-Path $ProgressJson) {
460
- try {
461
- $progress = Get-Content $ProgressJson -Raw | ConvertFrom-Json
462
- $progressLines = @()
463
- foreach ($key in @('fatal_error_code','api_error_status','api_error_code','current_phase','current_tool','last_text_snippet','terminal_result_text')) {
464
- if ($progress.PSObject.Properties[$key] -and $progress.$key) { $progressLines += "- ${key}: $($progress.$key)" }
465
- }
466
- if ($progressLines.Count -eq 0) { $progressLines = @('Progress data contained no terminal fields.') }
467
- } catch { $progressLines = @("Progress parse error: $($_.Exception.Message)") }
468
- }
469
- $checkpointLines = @('No checkpoint file found.')
470
- if (Test-Path $CheckpointPath) {
471
- try {
472
- $checkpoint = Get-Content $CheckpointPath -Raw | ConvertFrom-Json
473
- $steps = @($checkpoint.steps)
474
- $complete = @($steps | Where-Object { $_.status -in @('completed','skipped') }).Count
475
- $checkpointLines = @("$complete/$($steps.Count) steps completed_or_skipped")
476
- foreach ($step in $steps) {
477
- if ($step.status -notin @('completed','skipped')) { $checkpointLines += "- incomplete: $($step.id) $($step.skill) = $($step.status)" }
478
- }
479
- } catch { $checkpointLines = @("Checkpoint parse error: $($_.Exception.Message)") }
480
- }
481
- $latestCommit = (& git -C $ProjectRoot rev-parse --short HEAD 2>$null | Select-Object -First 1)
482
- if (-not $latestCommit) { $latestCommit = 'unavailable' }
483
- $featureCommit = if (Get-PrizmFeatureCommit $ProjectRoot $BaseCommit $FeatureId $false) { 'yes' } else { 'no' }
484
- $dirty = & git -C $ProjectRoot status --short 2>$null
485
- if ([string]::IsNullOrWhiteSpace(($dirty -join "`n"))) { $dirty = @('clean') }
486
- @(
487
- '# Runtime-synthesized failure log',
488
- '',
489
- '## Session',
490
- '',
491
- "- feature_id: $FeatureId",
492
- "- session_id: $SessionId",
493
- "- session_status: $SessionStatus",
494
- "- exit_code: $ExitCode",
495
- '',
496
- '## Stale kill marker',
497
- '',
498
- '```json',
499
- $stale,
500
- '```',
501
- '',
502
- '## Progress',
503
- '',
504
- $progressLines,
505
- '',
506
- '## Checkpoint',
507
- '',
508
- $checkpointLines,
509
- '',
510
- '## Git state',
511
- '',
512
- "- feature_commit_exists: $featureCommit",
513
- "- latest_commit: $latestCommit",
514
- '',
515
- '```text',
516
- $dirty,
517
- '```',
518
- '',
519
- '## Recommended recovery action',
520
- '',
521
- '- If this is an AI runtime/provider error before checkpoint completion, retry the session with a fresh context.',
522
- '- If the working tree is dirty, preserve or review those changes before any reset or merge.'
523
- ) | Set-Content -Path $FailureLog -Encoding UTF8
524
- }
525
-
526
- function New-PrizmDefaultDevBranchName {
527
- param([string]$Kind, [string]$CurrentItemId)
528
- $timestamp = Get-Date -Format 'yyyyMMddHHmm'
529
- switch ($Kind) {
530
- 'feature' { return "dev/$CurrentItemId-$timestamp" }
531
- 'bugfix' { return "bugfix/$CurrentItemId-$timestamp" }
532
- 'refactor' { return "refactor/$CurrentItemId-$timestamp" }
533
- default { return "dev/$CurrentItemId-$timestamp" }
534
- }
535
- }
536
-
537
- function Get-PrizmDeployIncompleteItems {
538
- param([string]$Kind, [string]$ListPath)
539
-
540
- if (-not (Test-Path $ListPath)) { return @("List file not found: $ListPath") }
541
- try {
542
- $data = Get-Content -Raw $ListPath | ConvertFrom-Json
543
- } catch {
544
- return @("List file is not valid JSON: $ListPath")
545
- }
546
-
547
- $collectionName = @{ feature = 'features'; bugfix = 'bugs'; refactor = 'refactors' }[$Kind]
548
- $allowedStatuses = @{
549
- feature = @('completed', 'skipped')
550
- bugfix = @('completed', 'skipped', 'needs_info')
551
- refactor = @('completed', 'skipped')
552
- }[$Kind]
553
-
554
- $items = @()
555
- $property = $data.PSObject.Properties[$collectionName]
556
- if ($property -and $property.Value) { $items = @($property.Value) }
557
-
558
- $bad = @()
559
- foreach ($item in $items) {
560
- $status = if ($item.PSObject.Properties['status']) { [string]$item.status } else { 'unknown' }
561
- if ($status -notin $allowedStatuses) {
562
- $itemIdText = if ($item.PSObject.Properties['id']) { [string]$item.id } else { 'unknown' }
563
- $titleText = if ($item.PSObject.Properties['title']) { [string]$item.title } else { '' }
564
- $bad += " ${itemIdText}: $status - $titleText"
565
- }
566
- }
567
- return @($bad)
568
- }
569
-
570
- function Invoke-PrizmDeploySession {
571
- param([string]$Kind, [string]$ListPath)
572
-
573
- if (-not $enableDeploy) { return 0 }
574
-
575
- $incomplete = @(Get-PrizmDeployIncompleteItems $Kind $ListPath)
576
- if ($incomplete.Count -gt 0) {
577
- Write-PrizmWarn "DEPLOY BLOCKED: $($incomplete.Count) task(s) not completed successfully."
578
- foreach ($line in $incomplete) { Write-PrizmWarn $line }
579
- Write-PrizmWarn "Fix failed tasks and re-run, or manually run /prizmkit-deploy."
580
- return 1
581
- }
582
-
583
- Write-PrizmInfo "All tasks completed - starting deploy session..."
584
- Write-PrizmInfo "ENABLE_DEPLOY=1"
585
-
586
- $deploySessionId = "deploy-$(Get-Date -Format 'yyyyMMddHHmmss')"
587
- $deploySessionDir = Join-Path $stateDir "deploy\$deploySessionId"
588
- $deployLogsDir = Join-Path $deploySessionDir 'logs'
589
- New-Item -ItemType Directory -Force -Path $deployLogsDir | Out-Null
590
-
591
- $deployPrompt = Join-Path $deploySessionDir 'bootstrap-prompt.md'
592
- $deployLog = Join-Path $deployLogsDir 'session.log'
593
- $deployPidPath = Join-Path $deployLogsDir 'ai.pid'
594
- $deployBranch = Get-PrizmCurrentBranch $paths.ProjectRoot
595
- if (-not $deployBranch) { $deployBranch = 'unknown' }
596
- $deployCommit = & git -C $paths.ProjectRoot rev-parse --short HEAD 2>$null
597
- if ($LASTEXITCODE -ne 0 -or -not $deployCommit) { $deployCommit = 'unknown' }
598
- $deployCommit = [string]($deployCommit | Select-Object -First 1)
599
-
600
- @(
601
- '## Deploy',
602
- '',
603
- "All $Kind tasks in the pipeline completed successfully.",
604
- '',
605
- "- Branch: $deployBranch",
606
- "- Commit: $deployCommit",
607
- '',
608
- 'Run /prizmkit-deploy to deploy the project. Read .prizmkit/deploy/deploy.config.json',
609
- 'for deployment configuration. If no deploy config exists, guide the user through',
610
- 'setting one up before deploying.'
611
- ) | Set-Content -Path $deployPrompt -Encoding UTF8
612
-
613
- Write-PrizmInfo "Deploy prompt: $deployPrompt"
614
- Write-PrizmInfo "Deploy log: $deployLog"
615
-
616
- $cli = Resolve-PrizmAiCli $paths.ProjectRoot $paths.PrizmkitDir
617
- $env:PRIZMKIT_PLATFORM = Get-PrizmPlatformFromProject $paths.ProjectRoot $paths.PrizmkitDir $cli
618
- $exitCode = Invoke-PrizmAiSession -CliCommand $cli -PromptPath $deployPrompt -LogPath $deployLog -ProjectRoot $paths.ProjectRoot -Model $env:MODEL -PidPath $deployPidPath
619
- if ($exitCode -eq 0) {
620
- Write-PrizmSuccess "Deploy session completed"
621
- } else {
622
- Write-PrizmWarn "Deploy session failed with exit code $exitCode"
623
- }
624
- return $exitCode
625
- }
626
-
627
- function Invoke-PrizmPipelineItem {
628
- param(
629
- [string]$CurrentItemId,
630
- [object]$ContinuationState = $null
631
- )
632
- $script:PRIZM_ITEM_EXIT_CODE = 0
633
-
634
- $sessionId = New-PrizmSessionId $Kind
635
- $runId = "run-$(Get-Date -Format 'yyyyMMdd-HHmmss')"
636
- $retryCount = '0'
637
- $resumePhase = 'null'
638
- $isGitRepository = if (-not $dryRun) { Test-PrizmGitRepository $paths.ProjectRoot } else { $false }
639
- $originalBranch = if ($isGitRepository) { Get-PrizmCurrentBranch $paths.ProjectRoot } else { '' }
640
- $devBranchName = ''
641
- $activeDevBranch = ''
642
- $continuationPending = $false
643
- $continuationReason = ''
644
- $contextOverflowCount = 0
645
- $continuationCount = 0
646
- $previousSessionId = ''
647
- $noProgressCount = 0
648
- if ($ContinuationState) {
649
- if ($ContinuationState.PSObject.Properties['active_dev_branch'] -and $ContinuationState.active_dev_branch) { $activeDevBranch = [string]$ContinuationState.active_dev_branch }
650
- if ($ContinuationState.PSObject.Properties['base_branch'] -and $ContinuationState.base_branch) { $originalBranch = [string]$ContinuationState.base_branch }
651
- if ($ContinuationState.PSObject.Properties['continuation_pending']) { $continuationPending = [bool]$ContinuationState.continuation_pending }
652
- if ($ContinuationState.PSObject.Properties['continuation_reason'] -and $ContinuationState.continuation_reason) { $continuationReason = [string]$ContinuationState.continuation_reason }
653
- if ($ContinuationState.PSObject.Properties['context_overflow_count'] -and $ContinuationState.context_overflow_count -ne $null) { $contextOverflowCount = [int]$ContinuationState.context_overflow_count }
654
- if ($ContinuationState.PSObject.Properties['continuation_count'] -and $ContinuationState.continuation_count -ne $null) { $continuationCount = [int]$ContinuationState.continuation_count }
655
- if ($ContinuationState.PSObject.Properties['last_context_overflow_session_id'] -and $ContinuationState.last_context_overflow_session_id) { $previousSessionId = [string]$ContinuationState.last_context_overflow_session_id }
656
- if ($ContinuationState.PSObject.Properties['no_progress_count'] -and $ContinuationState.no_progress_count -ne $null) { $noProgressCount = [int]$ContinuationState.no_progress_count }
657
- }
658
- if ($continuationPending -and $activeDevBranch) {
659
- Write-PrizmInfo "Continuation pending ($continuationReason); reusing dev branch: $activeDevBranch"
660
- Write-PrizmInfo "Continuation count: $continuationCount (context overflows: $contextOverflowCount)"
661
- }
662
- $hadDirtyBaseline = if ($isGitRepository) { Test-PrizmGitWorkDirty $paths.ProjectRoot $stateDir $listPath } else { $false }
663
- if ($hadDirtyBaseline) {
664
- if ($dryRun) {
665
- Write-PrizmWarn "Dirty working tree detected before $CurrentItemId; would auto-commit snapshot in real run."
666
- } else {
667
- Write-PrizmInfo "Dirty working tree detected before $CurrentItemId; auto-committing snapshot."
668
- Invoke-PrizmGitAutoCommit $paths.ProjectRoot "chore: workspace snapshot ready for run $CurrentItemId" | Out-Null
669
- }
670
- }
671
-
672
- if ($dryRun) {
673
- $statusPath = Join-Path $stateDir "$CurrentItemId\status.json"
674
- if (Test-Path $statusPath) {
675
- try {
676
- $itemStatus = Get-Content -Raw $statusPath | ConvertFrom-Json
677
- if ($itemStatus.retry_count -ne $null) { $retryCount = [string]$itemStatus.retry_count }
678
- if ($itemStatus.resume_from_phase -ne $null) { $resumePhase = [string]$itemStatus.resume_from_phase }
679
- } catch {
680
- Write-PrizmWarn "Could not read dry-run status file: $statusPath"
681
- }
682
- }
683
- } else {
684
- $start = Invoke-PrizmPythonJson $python (@((Join-Path $paths.ScriptsDir $updateScript), $listOption, $listPath, '--state-dir', $stateDir, '--action', 'start', $idOption, $CurrentItemId, '--session-id', $sessionId) + $maxRetryArgs + $maxInfraRetryArgs)
685
- if ($start.retry_count -ne $null) { $retryCount = [string]$start.retry_count }
686
- if ($start.resume_from_phase -ne $null) { $resumePhase = [string]$start.resume_from_phase }
687
-
688
- if ($isGitRepository -and $originalBranch) {
689
- Invoke-PrizmGitCommitPath $paths.ProjectRoot $listPath "chore($CurrentItemId): mark in_progress" | Out-Null
690
- $candidateBranch = if ($devBranchOverride) { $devBranchOverride } elseif ($continuationPending -and $activeDevBranch) { $activeDevBranch } else { New-PrizmDefaultDevBranchName $Kind $CurrentItemId }
691
- if (New-PrizmDevBranch $paths.ProjectRoot $candidateBranch $originalBranch) {
692
- $devBranchName = $candidateBranch
693
- Write-PrizmInfo "Dev branch: $devBranchName"
694
- } else {
695
- Write-PrizmError "Failed to create dev branch: $candidateBranch from $originalBranch - aborting to avoid running on $originalBranch"
696
- $script:PRIZM_ITEM_LIST_STATUS = ''
697
- $script:PRIZM_ITEM_EXIT_CODE = 1
698
- return
699
- }
700
- }
701
- }
702
-
703
- $baseCommit = if ($isGitRepository) { Get-PrizmGitHead $paths.ProjectRoot } else { '' }
704
-
705
- while ($true) {
706
- $sessionDir = if ($dryRun) {
707
- Join-Path ([System.IO.Path]::GetTempPath()) "prizmkit-dry-run\$sessionId"
708
- } else {
709
- Join-Path $stateDir "$CurrentItemId\sessions\$sessionId"
710
- }
711
- $logsDir = Join-Path $sessionDir 'logs'
712
- New-Item -ItemType Directory -Force -Path $logsDir | Out-Null
713
- $promptPath = Join-Path $sessionDir 'bootstrap-prompt.md'
714
- $sessionLog = Join-Path $logsDir 'session.log'
715
- $pidPath = Join-Path $logsDir 'ai.pid'
716
-
717
- $cli = $null
718
- if (-not $dryRun) {
719
- $cli = Resolve-PrizmAiCli $paths.ProjectRoot $paths.PrizmkitDir
720
- $env:PRIZMKIT_PLATFORM = Get-PrizmPlatformFromProject $paths.ProjectRoot $paths.PrizmkitDir $cli
721
- }
722
-
723
- $promptArgs = @((Join-Path $paths.ScriptsDir $promptScript), $listOption, $listPath, $idOption, $CurrentItemId, '--session-id', $sessionId, '--run-id', $runId, '--retry-count', $retryCount, '--resume-phase', $resumePhase, '--state-dir', $stateDir, '--output', $promptPath)
724
- $continuationSummaryPath = ".prizmkit/$Kind/$CurrentItemId/continuation-summary.md"
725
- if ($Kind -eq 'feature') {
726
- $featureSlug = Get-PrizmFeatureSlugFromList $listPath $CurrentItemId
727
- if ($featureSlug) { $continuationSummaryPath = ".prizmkit/specs/$featureSlug/continuation-summary.md" }
728
- }
729
- if ($continuationPending) {
730
- $modeForContinuation = if ($continuationReason) { $continuationReason } else { 'context_overflow' }
731
- $promptArgs += @('--continuation-mode', $modeForContinuation, '--previous-session-id', $previousSessionId, '--continuation-count', [string]$continuationCount, '--context-overflow-count', [string]$contextOverflowCount, '--task-type', $Kind, '--active-dev-branch', $activeDevBranch, '--base-branch', $originalBranch, '--continuation-summary-path', $continuationSummaryPath)
732
- }
733
- if ($mode) { $promptArgs += @('--mode', $mode) }
734
- if ($critic) { $promptArgs += @('--critic', $critic) }
735
- if ($dryRun) { $promptArgs += '--no-checkpoint' }
736
- if ($verboseEnabled) { Write-PrizmInfo "Prompt args: $($promptArgs -join ' ')" }
737
- $promptResult = Invoke-PrizmPythonJson $python $promptArgs
738
- $itemModel = ''
739
- if ($promptResult -and $promptResult.PSObject.Properties['model'] -and $promptResult.model) {
740
- $itemModel = [string]$promptResult.model
741
- }
742
- $effectiveModel = if ($itemModel) { $itemModel } else { $env:MODEL }
743
- Write-PrizmSuccess "Generated prompt: $promptPath"
744
-
745
- if ($dryRun) {
746
- Get-Content $promptPath
747
- $script:PRIZM_ITEM_EXIT_CODE = 0
748
- return
749
- }
750
-
751
- Write-PrizmInfo "Starting $cli session for $CurrentItemId ($sessionId)"
752
-
753
- $artifactDirForFingerprint = if ($Kind -eq 'feature') { Split-Path $continuationSummaryPath -Parent } else { ".prizmkit/$Kind/$CurrentItemId" }
754
- $checkpointForFingerprint = Join-Path $artifactDirForFingerprint 'workflow-checkpoint.json'
755
- $progressBefore = Get-PrizmContextProgressFingerprint -ProjectRoot $paths.ProjectRoot -TaskType $Kind -TaskId $CurrentItemId -ArtifactDir $artifactDirForFingerprint -CheckpointFile $checkpointForFingerprint
756
-
757
- $progressJson = Join-Path $logsDir 'progress.json'
758
- $parserProcess = Start-PrizmProgressParser -PythonCommand $python -ScriptsDir $paths.ScriptsDir -SessionLog $sessionLog -ProgressFile $progressJson -CliCommand $cli
759
-
760
- $job = Start-Job -ScriptBlock {
761
- param($commonPath, $cli, $promptPath, $sessionLog, $projectRoot, $model, $pidPath)
762
- . $commonPath
763
- Invoke-PrizmAiSession -CliCommand $cli -PromptPath $promptPath -LogPath $sessionLog -ProjectRoot $projectRoot -Model $model -PidPath $pidPath
764
- } -ArgumentList (Join-Path $paths.PipelineDir 'lib\common.ps1'), $cli, $promptPath, $sessionLog, $paths.ProjectRoot, $effectiveModel, $pidPath
765
-
766
- $elapsedSeconds = 0
767
- $staleSeconds = 0
768
- $previousLogSize = 0
769
- $previousProgressSignature = ''
770
- $previousChildActivitySignature = ''
771
- $staleKillMarker = Join-Path $logsDir 'stale-kill.json'
772
- $wasStaleKilled = $false
773
- while ($true) {
774
- $completed = Wait-Job $job -Timeout $heartbeatInterval
775
- if ($completed) { break }
776
-
777
- $elapsedSeconds += $heartbeatInterval
778
- $currentLogSize = 0
779
- if (Test-Path $sessionLog) {
780
- $currentLogSize = [int64](Get-Item $sessionLog).Length
781
- }
782
- $growth = $currentLogSize - $previousLogSize
783
- $previousLogSize = $currentLogSize
784
-
785
- $progressActivity = Get-PrizmProgressActivity -ProgressFile $progressJson
786
- $progressSignature = [string]$progressActivity.ProgressSignature
787
- $progressAdvanced = ($progressSignature -and $progressSignature -ne $previousProgressSignature)
788
- $previousProgressSignature = $progressSignature
789
- $childSignature = [string]$progressActivity.ChildSignature
790
- $childAdvanced = ($childSignature -and $childSignature -ne $previousChildActivitySignature)
791
- $previousChildActivitySignature = $childSignature
792
-
793
- $effectiveStaleKillThreshold = Get-PrizmEffectiveStaleKillThreshold -ProgressFile $progressJson -BaseThreshold $staleKillThreshold
794
-
795
- if ($growth -gt 0 -or $childAdvanced -or $progressAdvanced) {
796
- $staleSeconds = 0
797
- } else {
798
- $staleSeconds += $heartbeatInterval
799
- }
800
-
801
- $fatalErrorCode = Get-PrizmProgressFatalErrorCode -ProgressFile $progressJson
802
- if ($fatalErrorCode) {
803
- $wasStaleKilled = $true
804
- Write-PrizmWarn "Session hit fatal AI runtime error: $fatalErrorCode"
805
- $fatalErrorMarker = Join-Path $logsDir 'fatal-error.json'
806
- Write-PrizmFatalErrorMarker $fatalErrorMarker $fatalErrorCode $staleSeconds $effectiveStaleKillThreshold
807
- Write-PrizmFatalErrorMarker $staleKillMarker $fatalErrorCode $staleSeconds $effectiveStaleKillThreshold
808
- Stop-PrizmSessionProcess $pidPath
809
- if ($staleKillGraceSeconds -gt 0) { Start-Sleep -Seconds $staleKillGraceSeconds }
810
- break
811
- }
812
- if ($effectiveStaleKillThreshold -gt 0 -and $staleSeconds -ge $effectiveStaleKillThreshold) {
813
- $wasStaleKilled = $true
814
- Write-PrizmWarn "Session stale-killed (no progress for ${effectiveStaleKillThreshold}s)"
815
- Write-PrizmStaleKillMarker $staleKillMarker $staleSeconds $effectiveStaleKillThreshold
816
- Stop-PrizmSessionProcess $pidPath
817
- if ($staleKillGraceSeconds -gt 0) { Start-Sleep -Seconds $staleKillGraceSeconds }
818
- break
819
- }
820
- }
821
-
822
- $exitCode = 0
823
- if ($wasStaleKilled) {
824
- Stop-Job $job
825
- Remove-Job $job
826
- $exitCode = 143
827
- } else {
828
- try {
829
- $exitCode = [int](Receive-Job $job)
830
- } catch {
831
- Write-PrizmWarn "AI session job failed: $($_.Exception.Message)"
832
- $exitCode = 1
833
- }
834
- Remove-Job $job
835
- }
836
- Stop-PrizmProgressParser $parserProcess
837
-
838
- $wasContextOverflow = Test-PrizmContextOverflowError -SessionLog $sessionLog -ProgressJson $progressJson
839
- $wasInfraError = ($exitCode -ne 0 -and (Test-PrizmInfraError -SessionLog $sessionLog -ProgressJson $progressJson))
840
- $wasAiRuntimeError = Test-PrizmAiRuntimeError -SessionLog $sessionLog -ProgressJson $progressJson
841
- $semanticCompletion = if ($Kind -eq 'feature' -and $isGitRepository) {
842
- Get-PrizmFeatureSemanticCompletion $paths.ProjectRoot $listPath $CurrentItemId $baseCommit $paths.PrizmkitDir
843
- } else { $null }
844
-
845
- $hasSuccessfulCommit = $false
846
- if ($Kind -ne 'feature' -and $isGitRepository) {
847
- $hasSuccessfulCommit = Test-PrizmGitCommitsSince $paths.ProjectRoot $baseCommit
848
- }
849
-
850
- $status = 'crashed'
851
- if ($semanticCompletion) {
852
- $status = 'success'
853
- if ($exitCode -ne 0 -or $wasStaleKilled -or $wasContextOverflow -or $wasAiRuntimeError) {
854
- Write-PrizmWarn "Session ended with a failure signal after semantic completion; treating as finalized success"
855
- Write-PrizmWarn "Semantic completion commit: $($semanticCompletion.CommitSha)"
856
- }
857
- } elseif ($hasSuccessfulCommit) {
858
- $status = 'success'
859
- } elseif ($wasContextOverflow) {
860
- $status = 'context_overflow'
861
- Write-PrizmWarn "AI session failed because the AI CLI exceeded the model context window"
862
- Write-PrizmWarn "Context overflow is retried without consuming code retry budget"
863
- } elseif ($wasAiRuntimeError) {
864
- $status = 'infra_error'
865
- Write-PrizmWarn "AI session failed due to structured AI runtime error"
866
- Write-PrizmWarn "AI runtime errors are retried without consuming code retry budget"
867
- } elseif ($wasInfraError) {
868
- $status = 'infra_error'
869
- Write-PrizmWarn "AI session failed due to AI CLI/provider infrastructure error"
870
- Write-PrizmWarn "Infrastructure errors are retried without consuming code retry budget"
871
- } elseif ($wasStaleKilled -or (Test-Path $staleKillMarker)) {
872
- Write-PrizmWarn "Session was stale-killed by heartbeat monitor (no progress for too long)"
873
- Write-PrizmWarn "Heartbeat-killed sessions are treated as failed; dev branch is preserved for inspection"
874
- } elseif ($exitCode -ne 0) {
875
- Write-PrizmWarn "AI session exited with code $exitCode"
876
- } elseif (-not $isGitRepository) {
877
- Write-PrizmWarn "AI session exited cleanly, but project is not a git repository; cannot verify work was committed."
878
- } elseif (Test-PrizmGitCommitsSince $paths.ProjectRoot $baseCommit) {
879
- $status = 'success'
880
- } elseif (Test-PrizmGitWorkDirty $paths.ProjectRoot $stateDir $listPath) {
881
- Write-PrizmWarn "AI session exited cleanly but produced no commits; auto-committing dirty work tree."
882
- if (Invoke-PrizmGitAutoCommit $paths.ProjectRoot "chore($CurrentItemId): auto-commit session work") {
883
- $status = 'success'
884
- } else {
885
- Write-PrizmWarn "Auto-commit failed; treating session as crashed."
886
- }
887
- } else {
888
- Write-PrizmWarn "AI session exited cleanly but produced no commits and no changes."
889
- }
890
-
891
- $mergeSucceeded = $true
892
- $itemListStatus = ''
893
- $activeDevBranchForStatus = $devBranchName
894
- $progressAfter = ''
895
- $statusContinuationArgs = @('--active-dev-branch', $activeDevBranchForStatus, '--base-branch', $originalBranch, '--last-fatal-error-code', 'context_overflow', '--continuation-summary-path', $continuationSummaryPath)
896
- if ($status -eq 'context_overflow') {
897
- $progressAfter = Get-PrizmContextProgressFingerprint -ProjectRoot $paths.ProjectRoot -TaskType $Kind -TaskId $CurrentItemId -ArtifactDir $artifactDirForFingerprint -CheckpointFile $checkpointForFingerprint
898
- if (Test-PrizmContextProgressChanged -BeforeJson $progressBefore -AfterJson $progressAfter) {
899
- $noProgressCount = 0
900
- Write-PrizmInfo "Context-overflow session made observable progress; continuing on $devBranchName"
901
- } else {
902
- $noProgressCount++
903
- Write-PrizmWarn "Context-overflow session made no observable progress ($noProgressCount consecutive)"
904
- }
905
- $statusContinuationArgs = @('--active-dev-branch', $activeDevBranchForStatus, '--base-branch', $originalBranch, '--last-fatal-error-code', 'context_overflow', '--continuation-summary-path', $continuationSummaryPath, '--no-progress-count', [string]$noProgressCount, '--progress-fingerprint', $progressAfter)
906
- if ($noProgressCount -ge 2) {
907
- Write-PrizmWarn 'Pausing automatic continuation: context_overflow_without_git_checkpoint_or_artifact_progress'
908
- $status = 'stalled_context_continuation'
909
- } else {
910
- $updateResult = Invoke-PrizmPythonJson $python (@((Join-Path $paths.ScriptsDir $updateScript), $listOption, $listPath, '--state-dir', $stateDir, '--action', 'update', $idOption, $CurrentItemId, '--session-id', $sessionId, '--session-status', 'context_overflow') + $maxRetryArgs + $maxInfraRetryArgs + $statusContinuationArgs)
911
- if ($updateResult -and $updateResult.PSObject.Properties['new_status']) { $itemListStatus = [string]$updateResult.new_status }
912
- $continuationPending = $true
913
- $continuationReason = 'context_overflow'
914
- $previousSessionId = $sessionId
915
- $activeDevBranch = $devBranchName
916
- $contextOverflowCount++
917
- $continuationCount++
918
- $sessionId = New-PrizmSessionId $Kind
919
- $runId = "run-$(Get-Date -Format 'yyyyMMdd-HHmmss')"
920
- Write-PrizmInfo "Launching automatic continuation for $CurrentItemId on same branch/worktree"
921
- continue
922
- }
923
- }
924
-
925
- if ($status -eq 'success') {
926
- if (Test-PrizmGitDirty $paths.ProjectRoot) {
927
- Write-PrizmInfo "Auto-committing remaining session artifacts."
928
- Invoke-PrizmGitIncludeRemainingArtifacts $paths.ProjectRoot $CurrentItemId
929
- }
930
-
931
- if ($status -eq 'success') {
932
- $updateResult = Invoke-PrizmPythonJson $python (@((Join-Path $paths.ScriptsDir $updateScript), $listOption, $listPath, '--state-dir', $stateDir, '--action', 'update', $idOption, $CurrentItemId, '--session-id', $sessionId, '--session-status', $status) + $maxRetryArgs + $maxInfraRetryArgs + $statusContinuationArgs)
933
- if ($updateResult -and $updateResult.PSObject.Properties['new_status']) {
934
- $itemListStatus = [string]$updateResult.new_status
935
- }
936
-
937
- if ($isGitRepository -and $devBranchName) {
938
- if (Merge-PrizmDevBranch $paths.ProjectRoot $devBranchName $originalBranch $autoPush) {
939
- $devBranchName = ''
940
- } else {
941
- $mergeSucceeded = $false
942
- $status = 'merge_conflict'
943
- Write-PrizmWarn "Auto-merge failed - dev branch preserved for inspection"
944
- }
945
- }
946
- }
947
- } elseif ($isGitRepository -and $devBranchName) {
948
- Write-PrizmWarn "Session failed - dev branch preserved for inspection: $devBranchName"
949
- }
950
-
951
- if ($isGitRepository -and $originalBranch) {
952
- Restore-PrizmOriginalBranch $paths.ProjectRoot $originalBranch $devBranchName | Out-Null
953
- }
954
-
955
- if ($status -eq 'success' -and $mergeSucceeded -and $isGitRepository) {
956
- Invoke-PrizmGitCommitPath $paths.ProjectRoot $listPath "chore($CurrentItemId): update $idName status" | Out-Null
957
- }
958
-
959
- if ($status -ne 'success') {
960
- if ($Kind -eq 'feature') {
961
- $failureSlug = if ($semanticCompletion) { [string]$semanticCompletion.Slug } else { Get-PrizmFeatureSlugFromList $listPath $CurrentItemId }
962
- if ($failureSlug) {
963
- $featureArtifactDir = Join-Path $paths.PrizmkitDir "specs\$failureSlug"
964
- $failureLog = Join-Path $featureArtifactDir 'failure-log.md'
965
- $checkpointPath = Join-Path $featureArtifactDir 'workflow-checkpoint.json'
966
- Write-PrizmRuntimeFailureLog $failureLog $CurrentItemId $sessionId $status $exitCode $staleKillMarker $progressJson $checkpointPath $paths.ProjectRoot $baseCommit
967
- }
968
- }
969
- $updateResult = Invoke-PrizmPythonJson $python (@((Join-Path $paths.ScriptsDir $updateScript), $listOption, $listPath, '--state-dir', $stateDir, '--action', 'update', $idOption, $CurrentItemId, '--session-id', $sessionId, '--session-status', $status) + $maxRetryArgs + $maxInfraRetryArgs + $statusContinuationArgs)
970
- if ($updateResult -and $updateResult.PSObject.Properties['new_status']) {
971
- $itemListStatus = [string]$updateResult.new_status
972
- }
973
- if ($isGitRepository) {
974
- Invoke-PrizmGitCommitPath $paths.ProjectRoot $listPath "chore($CurrentItemId): update $idName status" | Out-Null
975
- }
976
- }
977
-
978
- break
979
- }
980
-
981
- if ($status -eq 'success' -and $mergeSucceeded) {
982
- Write-PrizmSuccess "$Kind item completed: $CurrentItemId"
983
- } else {
984
- Write-PrizmError "$Kind item failed: $CurrentItemId. Log: $sessionLog"
985
- }
986
- $script:PRIZM_ITEM_LIST_STATUS = $itemListStatus
987
- $script:PRIZM_ITEM_EXIT_CODE = if ($status -eq 'success' -and $mergeSucceeded) { 0 } else { 1 }
988
- return
989
- }
990
-
991
- if ($itemId) {
992
- Invoke-PrizmPipelineItem $itemId
993
- $global:PRIZM_EXIT_CODE = $script:PRIZM_ITEM_EXIT_CODE
994
- return
995
- }
996
-
997
- $processedCount = 0
998
- $lastExitCode = 0
999
- while ($true) {
1000
- $getNextArgs = @((Join-Path $paths.ScriptsDir $updateScript), $listOption, $listPath, '--state-dir', $stateDir, '--action', 'get_next')
1001
- if ($featuresFilter -and $Kind -eq 'feature') { $getNextArgs += @('--features', $featuresFilter) }
1002
- $getNextOutput = (Invoke-PrizmPythonOutput $python $getNextArgs).Trim()
1003
- if (-not $getNextOutput -or $getNextOutput -eq 'PIPELINE_COMPLETE') {
1004
- if ($processedCount -eq 0) {
1005
- Write-PrizmSuccess "No pending $Kind items."
1006
- } else {
1007
- Write-PrizmSuccess "Processed $processedCount $Kind item(s)."
1008
- }
1009
- if (-not $dryRun) {
1010
- $deployExit = Invoke-PrizmDeploySession $Kind $listPath
1011
- if ($deployExit -ne 0 -and $lastExitCode -eq 0) { $lastExitCode = $deployExit }
1012
- }
1013
- $global:PRIZM_EXIT_CODE = $lastExitCode
1014
- return
1015
- }
1016
- if ($getNextOutput -eq 'PIPELINE_BLOCKED') {
1017
- Write-PrizmWarn "All remaining $Kind items are blocked."
1018
- Write-PrizmWarn "Run .\run-$Kind.ps1 status to see details."
1019
- $global:PRIZM_EXIT_CODE = $lastExitCode
1020
- return
1021
- }
1022
- if ($getNextOutput -notmatch '^\s*[\{\[]') {
1023
- throw "Unexpected get_next output: $getNextOutput"
1024
- }
1025
- $next = $getNextOutput | ConvertFrom-Json
1026
- $nextItemId = $next.PSObject.Properties["${idName}_id"].Value
1027
- if (-not $nextItemId) {
1028
- if ($processedCount -eq 0) {
1029
- Write-PrizmSuccess "No pending $Kind items."
1030
- } else {
1031
- Write-PrizmSuccess "Processed $processedCount $Kind item(s)."
1032
- }
1033
- $global:PRIZM_EXIT_CODE = $lastExitCode
1034
- return
1035
- }
1036
-
1037
- $processedCount++
1038
- Invoke-PrizmPipelineItem $nextItemId $next
1039
- $lastExitCode = $script:PRIZM_ITEM_EXIT_CODE
1040
- if ($dryRun) {
1041
- $global:PRIZM_EXIT_CODE = $lastExitCode
1042
- return
1043
- }
1044
- if ($lastExitCode -ne 0 -and $stopOnFailure -and $script:PRIZM_ITEM_LIST_STATUS -eq 'failed') {
1045
- $global:PRIZM_EXIT_CODE = $lastExitCode
1046
- return
1047
- } elseif ($lastExitCode -ne 0 -and $stopOnFailure) {
1048
- Write-PrizmInfo "STOP_ON_FAILURE: $nextItemId is $($script:PRIZM_ITEM_LIST_STATUS); code/infra retry budget not exhausted, continuing."
1049
- }
1050
- }
1051
- }