prizmkit 1.1.99 → 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 (321) 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/check-session-status.py +74 -1
  30. package/bundled/dev-pipeline/scripts/continuation.py +374 -0
  31. package/bundled/dev-pipeline/scripts/generate-bootstrap-prompt.py +64 -52
  32. package/bundled/dev-pipeline/scripts/generate-bugfix-prompt.py +35 -25
  33. package/bundled/dev-pipeline/scripts/generate-recovery-prompt.py +2 -2
  34. package/bundled/dev-pipeline/scripts/generate-refactor-prompt.py +15 -20
  35. package/bundled/dev-pipeline/scripts/parse-stream-progress.py +185 -16
  36. package/bundled/dev-pipeline/scripts/update-bug-status.py +214 -6
  37. package/bundled/dev-pipeline/scripts/update-feature-status.py +237 -6
  38. package/bundled/dev-pipeline/scripts/update-refactor-status.py +214 -6
  39. package/bundled/dev-pipeline/templates/agent-prompts/dev-implement.md +8 -2
  40. package/bundled/dev-pipeline/templates/bootstrap-prompt.md +4 -0
  41. package/bundled/dev-pipeline/templates/bootstrap-tier1.md +14 -5
  42. package/bundled/dev-pipeline/templates/bootstrap-tier2.md +16 -6
  43. package/bundled/dev-pipeline/templates/bootstrap-tier3.md +16 -6
  44. package/bundled/dev-pipeline/templates/bugfix-bootstrap-prompt.md +1 -1
  45. package/bundled/dev-pipeline/templates/refactor-bootstrap-prompt.md +3 -3
  46. package/bundled/dev-pipeline/templates/sections/context-budget-rules.md +2 -0
  47. package/bundled/dev-pipeline/templates/sections/log-size-awareness.md +13 -69
  48. package/bundled/dev-pipeline/templates/sections/phase-context-snapshot-agent-suffix.md +15 -7
  49. package/bundled/dev-pipeline/templates/sections/phase-implement-agent.md +42 -29
  50. package/bundled/dev-pipeline/templates/sections/phase-implement-full.md +41 -39
  51. package/bundled/dev-pipeline/templates/sections/test-failure-recovery-agent.md +4 -0
  52. package/bundled/dev-pipeline/templates/sections/test-failure-recovery-lite.md +4 -0
  53. package/bundled/dev-pipeline/templates/session-status-schema.json +1 -1
  54. package/bundled/dev-pipeline/tests/conftest.py +1 -0
  55. package/bundled/dev-pipeline/tests/test_auto_skip.py +932 -0
  56. package/bundled/dev-pipeline/tests/test_generate_bootstrap_prompt.py +207 -0
  57. package/bundled/dev-pipeline/tests/test_generate_bugfix_prompt.py +100 -0
  58. package/bundled/dev-pipeline/tests/test_generate_refactor_prompt.py +43 -0
  59. package/bundled/dev-pipeline/tests/test_python_runner_parity.py +1138 -0
  60. package/bundled/dev-pipeline/tests/test_unified_cli.py +1045 -0
  61. package/bundled/skills/_metadata.json +1 -1
  62. package/bundled/skills/bugfix-pipeline-launcher/SKILL.md +29 -34
  63. package/bundled/skills/bugfix-pipeline-launcher/references/configuration.md +6 -5
  64. package/bundled/skills/feature-pipeline-launcher/SKILL.md +29 -35
  65. package/bundled/skills/feature-pipeline-launcher/references/configuration.md +7 -6
  66. package/bundled/skills/feature-workflow/SKILL.md +3 -6
  67. package/bundled/skills/recovery-workflow/SKILL.md +23 -32
  68. package/bundled/skills/refactor-pipeline-launcher/SKILL.md +29 -35
  69. package/bundled/skills/refactor-pipeline-launcher/references/configuration.md +7 -6
  70. package/bundled/skills/refactor-workflow/SKILL.md +3 -6
  71. package/bundled/templates/hooks/commit-intent.json +2 -2
  72. package/bundled/templates/hooks/diff-prizm-docs.py +226 -0
  73. package/bundled/templates/hooks/prizm-pre-commit.py +45 -0
  74. package/bundled/templates/hooks/validate-prizm-docs.py +240 -0
  75. package/package.json +1 -1
  76. package/src/config.js +33 -12
  77. package/src/index.js +3 -6
  78. package/src/manifest.js +3 -2
  79. package/src/metadata.js +7 -18
  80. package/src/prompts.js +0 -12
  81. package/src/runtimes.js +18 -11
  82. package/src/scaffold.js +133 -116
  83. package/src/upgrade.js +1 -1
  84. package/bundled/dev-pipeline/launch-bugfix-daemon.sh +0 -500
  85. package/bundled/dev-pipeline/launch-feature-daemon.sh +0 -657
  86. package/bundled/dev-pipeline/launch-refactor-daemon.sh +0 -502
  87. package/bundled/dev-pipeline/lib/branch.sh +0 -326
  88. package/bundled/dev-pipeline/lib/common.sh +0 -1257
  89. package/bundled/dev-pipeline/lib/heartbeat.sh +0 -469
  90. package/bundled/dev-pipeline/reset-bug.sh +0 -395
  91. package/bundled/dev-pipeline/reset-feature.sh +0 -406
  92. package/bundled/dev-pipeline/reset-refactor.sh +0 -393
  93. package/bundled/dev-pipeline/run-bugfix.sh +0 -1315
  94. package/bundled/dev-pipeline/run-feature.sh +0 -1602
  95. package/bundled/dev-pipeline/run-recovery.sh +0 -648
  96. package/bundled/dev-pipeline/run-refactor.sh +0 -1348
  97. package/bundled/dev-pipeline/scripts/monitor-log.sh +0 -104
  98. package/bundled/dev-pipeline/tests/test-path-resolution.sh +0 -100
  99. package/bundled/dev-pipeline-windows/.env.example +0 -36
  100. package/bundled/dev-pipeline-windows/README.md +0 -30
  101. package/bundled/dev-pipeline-windows/SCHEMA_ANALYSIS.md +0 -533
  102. package/bundled/dev-pipeline-windows/assets/feature-list-example.json +0 -146
  103. package/bundled/dev-pipeline-windows/assets/prizm-dev-team-integration.md +0 -137
  104. package/bundled/dev-pipeline-windows/launch-bugfix-daemon.ps1 +0 -9
  105. package/bundled/dev-pipeline-windows/launch-feature-daemon.ps1 +0 -9
  106. package/bundled/dev-pipeline-windows/launch-refactor-daemon.ps1 +0 -9
  107. package/bundled/dev-pipeline-windows/lib/branch.ps1 +0 -235
  108. package/bundled/dev-pipeline-windows/lib/common.ps1 +0 -829
  109. package/bundled/dev-pipeline-windows/lib/daemon.ps1 +0 -140
  110. package/bundled/dev-pipeline-windows/lib/pipeline.ps1 +0 -967
  111. package/bundled/dev-pipeline-windows/lib/reset.ps1 +0 -87
  112. package/bundled/dev-pipeline-windows/reset-bug.ps1 +0 -9
  113. package/bundled/dev-pipeline-windows/reset-feature.ps1 +0 -9
  114. package/bundled/dev-pipeline-windows/reset-refactor.ps1 +0 -9
  115. package/bundled/dev-pipeline-windows/run-bugfix.ps1 +0 -9
  116. package/bundled/dev-pipeline-windows/run-feature.ps1 +0 -9
  117. package/bundled/dev-pipeline-windows/run-recovery.ps1 +0 -179
  118. package/bundled/dev-pipeline-windows/run-refactor.ps1 +0 -9
  119. package/bundled/dev-pipeline-windows/scripts/check-session-status.py +0 -228
  120. package/bundled/dev-pipeline-windows/scripts/detect-stuck.py +0 -530
  121. package/bundled/dev-pipeline-windows/scripts/generate-bootstrap-prompt.py +0 -2282
  122. package/bundled/dev-pipeline-windows/scripts/generate-bugfix-prompt.py +0 -767
  123. package/bundled/dev-pipeline-windows/scripts/generate-recovery-prompt.py +0 -805
  124. package/bundled/dev-pipeline-windows/scripts/generate-refactor-prompt.py +0 -845
  125. package/bundled/dev-pipeline-windows/scripts/init-bugfix-pipeline.py +0 -316
  126. package/bundled/dev-pipeline-windows/scripts/init-dev-team.py +0 -134
  127. package/bundled/dev-pipeline-windows/scripts/init-pipeline.py +0 -382
  128. package/bundled/dev-pipeline-windows/scripts/init-refactor-pipeline.py +0 -399
  129. package/bundled/dev-pipeline-windows/scripts/monitor-log.ps1 +0 -102
  130. package/bundled/dev-pipeline-windows/scripts/parse-stream-progress.py +0 -1232
  131. package/bundled/dev-pipeline-windows/scripts/patch-completion-notes.py +0 -191
  132. package/bundled/dev-pipeline-windows/scripts/prizmkit-test-gate.py +0 -446
  133. package/bundled/dev-pipeline-windows/scripts/update-bug-status.py +0 -913
  134. package/bundled/dev-pipeline-windows/scripts/update-checkpoint.py +0 -173
  135. package/bundled/dev-pipeline-windows/scripts/update-feature-status.py +0 -1558
  136. package/bundled/dev-pipeline-windows/scripts/update-refactor-status.py +0 -1119
  137. package/bundled/dev-pipeline-windows/scripts/utils.py +0 -542
  138. package/bundled/dev-pipeline-windows/templates/agent-prompts/critic-plan-challenge.md +0 -7
  139. package/bundled/dev-pipeline-windows/templates/agent-prompts/dev-fix.md +0 -7
  140. package/bundled/dev-pipeline-windows/templates/agent-prompts/dev-implement.md +0 -65
  141. package/bundled/dev-pipeline-windows/templates/agent-prompts/dev-resume.md +0 -5
  142. package/bundled/dev-pipeline-windows/templates/agent-prompts/reviewer-review.md +0 -7
  143. package/bundled/dev-pipeline-windows/templates/bootstrap-prompt.md +0 -73
  144. package/bundled/dev-pipeline-windows/templates/bootstrap-tier1.md +0 -589
  145. package/bundled/dev-pipeline-windows/templates/bootstrap-tier2.md +0 -710
  146. package/bundled/dev-pipeline-windows/templates/bootstrap-tier3.md +0 -791
  147. package/bundled/dev-pipeline-windows/templates/bug-fix-list-schema.json +0 -263
  148. package/bundled/dev-pipeline-windows/templates/bugfix-bootstrap-prompt.md +0 -326
  149. package/bundled/dev-pipeline-windows/templates/feature-list-schema.json +0 -237
  150. package/bundled/dev-pipeline-windows/templates/refactor-bootstrap-prompt.md +0 -340
  151. package/bundled/dev-pipeline-windows/templates/refactor-list-schema.json +0 -270
  152. package/bundled/dev-pipeline-windows/templates/sections/ac-verification-checklist.md +0 -7
  153. package/bundled/dev-pipeline-windows/templates/sections/checkpoint-system.md +0 -91
  154. package/bundled/dev-pipeline-windows/templates/sections/context-budget-rules.md +0 -34
  155. package/bundled/dev-pipeline-windows/templates/sections/critical-paths-agent.md +0 -10
  156. package/bundled/dev-pipeline-windows/templates/sections/critical-paths-full.md +0 -12
  157. package/bundled/dev-pipeline-windows/templates/sections/critical-paths-lite.md +0 -7
  158. package/bundled/dev-pipeline-windows/templates/sections/directory-convention-agent.md +0 -8
  159. package/bundled/dev-pipeline-windows/templates/sections/directory-convention-full.md +0 -9
  160. package/bundled/dev-pipeline-windows/templates/sections/directory-convention-lite.md +0 -6
  161. package/bundled/dev-pipeline-windows/templates/sections/failure-capture.md +0 -21
  162. package/bundled/dev-pipeline-windows/templates/sections/feature-context.md +0 -21
  163. package/bundled/dev-pipeline-windows/templates/sections/log-size-awareness.md +0 -78
  164. package/bundled/dev-pipeline-windows/templates/sections/phase-browser-verification-auto.md +0 -283
  165. package/bundled/dev-pipeline-windows/templates/sections/phase-browser-verification-opencli.md +0 -112
  166. package/bundled/dev-pipeline-windows/templates/sections/phase-browser-verification.md +0 -168
  167. package/bundled/dev-pipeline-windows/templates/sections/phase-commit-full.md +0 -82
  168. package/bundled/dev-pipeline-windows/templates/sections/phase-commit.md +0 -75
  169. package/bundled/dev-pipeline-windows/templates/sections/phase-context-snapshot-agent-suffix.md +0 -23
  170. package/bundled/dev-pipeline-windows/templates/sections/phase-context-snapshot-base.md +0 -14
  171. package/bundled/dev-pipeline-windows/templates/sections/phase-context-snapshot-lite-suffix.md +0 -19
  172. package/bundled/dev-pipeline-windows/templates/sections/phase-critic-plan-full.md +0 -63
  173. package/bundled/dev-pipeline-windows/templates/sections/phase-critic-plan.md +0 -42
  174. package/bundled/dev-pipeline-windows/templates/sections/phase-implement-agent.md +0 -44
  175. package/bundled/dev-pipeline-windows/templates/sections/phase-implement-full.md +0 -59
  176. package/bundled/dev-pipeline-windows/templates/sections/phase-implement-lite.md +0 -39
  177. package/bundled/dev-pipeline-windows/templates/sections/phase-plan-agent.md +0 -27
  178. package/bundled/dev-pipeline-windows/templates/sections/phase-plan-lite.md +0 -27
  179. package/bundled/dev-pipeline-windows/templates/sections/phase-prizmkit-test.md +0 -39
  180. package/bundled/dev-pipeline-windows/templates/sections/phase-review-agent.md +0 -35
  181. package/bundled/dev-pipeline-windows/templates/sections/phase-review-full.md +0 -35
  182. package/bundled/dev-pipeline-windows/templates/sections/phase-specify-plan-full.md +0 -73
  183. package/bundled/dev-pipeline-windows/templates/sections/phase0-init.md +0 -13
  184. package/bundled/dev-pipeline-windows/templates/sections/phase0-test-baseline.md +0 -21
  185. package/bundled/dev-pipeline-windows/templates/sections/session-context.md +0 -5
  186. package/bundled/dev-pipeline-windows/templates/sections/subagent-timeout-recovery.md +0 -6
  187. package/bundled/dev-pipeline-windows/templates/sections/task-contract.md +0 -34
  188. package/bundled/dev-pipeline-windows/templates/sections/test-failure-recovery-agent.md +0 -48
  189. package/bundled/dev-pipeline-windows/templates/sections/test-failure-recovery-lite.md +0 -48
  190. package/bundled/dev-pipeline-windows/templates/session-status-schema.json +0 -83
  191. package/bundled/skills-windows/app-planner/SKILL.md +0 -296
  192. package/bundled/skills-windows/app-planner/assets/app-design-guide.md +0 -101
  193. package/bundled/skills-windows/app-planner/references/architecture-decisions.md +0 -52
  194. package/bundled/skills-windows/app-planner/references/brainstorm-guide.md +0 -101
  195. package/bundled/skills-windows/app-planner/references/frontend-design-guide.md +0 -71
  196. package/bundled/skills-windows/app-planner/references/infrastructure-convention-discovery.md +0 -108
  197. package/bundled/skills-windows/app-planner/references/project-brief-guide.md +0 -82
  198. package/bundled/skills-windows/app-planner/references/project-conventions-discovery.md +0 -59
  199. package/bundled/skills-windows/app-planner/references/project-state-detection.md +0 -90
  200. package/bundled/skills-windows/app-planner/references/red-team-checklist.md +0 -40
  201. package/bundled/skills-windows/app-planner/references/rules/backend/derivation-rules.md +0 -619
  202. package/bundled/skills-windows/app-planner/references/rules/backend/fixed-rules.md +0 -285
  203. package/bundled/skills-windows/app-planner/references/rules/backend/question-bank.md +0 -249
  204. package/bundled/skills-windows/app-planner/references/rules/backend/question-manifest.json +0 -46
  205. package/bundled/skills-windows/app-planner/references/rules/backend/template.md +0 -173
  206. package/bundled/skills-windows/app-planner/references/rules/database/derivation-rules.md +0 -382
  207. package/bundled/skills-windows/app-planner/references/rules/database/fixed-rules.md +0 -211
  208. package/bundled/skills-windows/app-planner/references/rules/database/question-bank.md +0 -184
  209. package/bundled/skills-windows/app-planner/references/rules/database/question-manifest.json +0 -39
  210. package/bundled/skills-windows/app-planner/references/rules/database/template.md +0 -158
  211. package/bundled/skills-windows/app-planner/references/rules/frontend/derivation-rules.md +0 -820
  212. package/bundled/skills-windows/app-planner/references/rules/frontend/fixed-rules.md +0 -188
  213. package/bundled/skills-windows/app-planner/references/rules/frontend/question-bank.md +0 -319
  214. package/bundled/skills-windows/app-planner/references/rules/frontend/question-manifest.json +0 -51
  215. package/bundled/skills-windows/app-planner/references/rules/frontend/template.md +0 -339
  216. package/bundled/skills-windows/app-planner/references/rules/mobile/derivation-rules.md +0 -649
  217. package/bundled/skills-windows/app-planner/references/rules/mobile/fixed-rules.md +0 -290
  218. package/bundled/skills-windows/app-planner/references/rules/mobile/question-bank.md +0 -232
  219. package/bundled/skills-windows/app-planner/references/rules/mobile/question-manifest.json +0 -47
  220. package/bundled/skills-windows/app-planner/references/rules/mobile/template.md +0 -175
  221. package/bundled/skills-windows/app-planner/references/rules-configuration.md +0 -46
  222. package/bundled/skills-windows/bug-fix-workflow/SKILL.md +0 -379
  223. package/bundled/skills-windows/bug-fix-workflow/references/bug-diagnosis.md +0 -41
  224. package/bundled/skills-windows/bug-planner/SKILL.md +0 -402
  225. package/bundled/skills-windows/bug-planner/assets/bug-confirmation-template.md +0 -43
  226. package/bundled/skills-windows/bug-planner/references/critic-and-verification.md +0 -44
  227. package/bundled/skills-windows/bug-planner/references/error-recovery.md +0 -73
  228. package/bundled/skills-windows/bug-planner/references/input-formats.md +0 -53
  229. package/bundled/skills-windows/bug-planner/references/schema-validation.md +0 -25
  230. package/bundled/skills-windows/bug-planner/references/severity-rules.md +0 -16
  231. package/bundled/skills-windows/bug-planner/scripts/validate-bug-list.py +0 -322
  232. package/bundled/skills-windows/bugfix-pipeline-launcher/SKILL.md +0 -304
  233. package/bundled/skills-windows/bugfix-pipeline-launcher/references/configuration.md +0 -84
  234. package/bundled/skills-windows/feature-pipeline-launcher/SKILL.md +0 -381
  235. package/bundled/skills-windows/feature-pipeline-launcher/references/configuration.md +0 -67
  236. package/bundled/skills-windows/feature-pipeline-launcher/scripts/preflight-check.py +0 -462
  237. package/bundled/skills-windows/feature-planner/SKILL.md +0 -397
  238. package/bundled/skills-windows/feature-planner/assets/evaluation-guide.md +0 -64
  239. package/bundled/skills-windows/feature-planner/assets/planning-guide.md +0 -214
  240. package/bundled/skills-windows/feature-planner/references/browser-interaction.md +0 -59
  241. package/bundled/skills-windows/feature-planner/references/completeness-review.md +0 -57
  242. package/bundled/skills-windows/feature-planner/references/decomposition-patterns.md +0 -75
  243. package/bundled/skills-windows/feature-planner/references/error-recovery.md +0 -90
  244. package/bundled/skills-windows/feature-planner/references/incremental-feature-planning.md +0 -112
  245. package/bundled/skills-windows/feature-planner/references/new-project-planning.md +0 -85
  246. package/bundled/skills-windows/feature-planner/scripts/validate-and-generate.py +0 -1020
  247. package/bundled/skills-windows/feature-workflow/SKILL.md +0 -374
  248. package/bundled/skills-windows/feature-workflow/references/brainstorm-guide.md +0 -137
  249. package/bundled/skills-windows/prizm-kit/SKILL.md +0 -93
  250. package/bundled/skills-windows/prizmkit-code-review/SKILL.md +0 -161
  251. package/bundled/skills-windows/prizmkit-code-review/references/dev-agent-prompt.md +0 -30
  252. package/bundled/skills-windows/prizmkit-code-review/references/review-report-template.md +0 -31
  253. package/bundled/skills-windows/prizmkit-code-review/references/reviewer-agent-prompt.md +0 -66
  254. package/bundled/skills-windows/prizmkit-code-review/scripts/check_loop.py +0 -186
  255. package/bundled/skills-windows/prizmkit-committer/SKILL.md +0 -89
  256. package/bundled/skills-windows/prizmkit-deploy/SKILL.md +0 -444
  257. package/bundled/skills-windows/prizmkit-deploy/references/ci-cd-workflows.md +0 -115
  258. package/bundled/skills-windows/prizmkit-deploy/references/cloud-platform-deploy.md +0 -93
  259. package/bundled/skills-windows/prizmkit-deploy/references/data-safety-examples.md +0 -120
  260. package/bundled/skills-windows/prizmkit-deploy/references/database-setup.md +0 -46
  261. package/bundled/skills-windows/prizmkit-deploy/references/deploy-config-schema.md +0 -148
  262. package/bundled/skills-windows/prizmkit-deploy/references/deploy-history-schema.md +0 -62
  263. package/bundled/skills-windows/prizmkit-deploy/references/deployment-modes.md +0 -50
  264. package/bundled/skills-windows/prizmkit-deploy/references/direct-upload.md +0 -26
  265. package/bundled/skills-windows/prizmkit-deploy/references/dns-setup.md +0 -42
  266. package/bundled/skills-windows/prizmkit-deploy/references/docker-deploy.md +0 -31
  267. package/bundled/skills-windows/prizmkit-deploy/references/firewall-setup.md +0 -37
  268. package/bundled/skills-windows/prizmkit-deploy/references/live-validation-notes.md +0 -21
  269. package/bundled/skills-windows/prizmkit-deploy/references/nginx-blue-green.md +0 -59
  270. package/bundled/skills-windows/prizmkit-deploy/references/ssh-bootstrap-flow.md +0 -49
  271. package/bundled/skills-windows/prizmkit-deploy/references/ssh-execution-flow.md +0 -41
  272. package/bundled/skills-windows/prizmkit-deploy/references/ssh-takeover.md +0 -20
  273. package/bundled/skills-windows/prizmkit-deploy/references/ssl-setup.md +0 -56
  274. package/bundled/skills-windows/prizmkit-implement/SKILL.md +0 -71
  275. package/bundled/skills-windows/prizmkit-init/SKILL.md +0 -356
  276. package/bundled/skills-windows/prizmkit-init/assets/project-brief-template.md +0 -82
  277. package/bundled/skills-windows/prizmkit-init/references/config-schema.md +0 -70
  278. package/bundled/skills-windows/prizmkit-init/references/rules/layer-detection.md +0 -41
  279. package/bundled/skills-windows/prizmkit-init/references/tech-stack-catalog.md +0 -13
  280. package/bundled/skills-windows/prizmkit-init/references/update-supplement.md +0 -9
  281. package/bundled/skills-windows/prizmkit-plan/SKILL.md +0 -102
  282. package/bundled/skills-windows/prizmkit-plan/assets/plan-template.md +0 -115
  283. package/bundled/skills-windows/prizmkit-plan/assets/spec-template.md +0 -73
  284. package/bundled/skills-windows/prizmkit-plan/references/clarify-guide.md +0 -67
  285. package/bundled/skills-windows/prizmkit-plan/references/examples.md +0 -85
  286. package/bundled/skills-windows/prizmkit-plan/references/verification-checklist.md +0 -60
  287. package/bundled/skills-windows/prizmkit-prizm-docs/SKILL.md +0 -129
  288. package/bundled/skills-windows/prizmkit-prizm-docs/assets/prizm-docs-format.md +0 -613
  289. package/bundled/skills-windows/prizmkit-prizm-docs/references/op-init.md +0 -45
  290. package/bundled/skills-windows/prizmkit-prizm-docs/references/op-rebuild.md +0 -15
  291. package/bundled/skills-windows/prizmkit-prizm-docs/references/op-status.md +0 -14
  292. package/bundled/skills-windows/prizmkit-prizm-docs/references/op-update.md +0 -19
  293. package/bundled/skills-windows/prizmkit-prizm-docs/references/op-validate.md +0 -17
  294. package/bundled/skills-windows/prizmkit-retrospective/SKILL.md +0 -87
  295. package/bundled/skills-windows/prizmkit-retrospective/references/knowledge-injection-steps.md +0 -50
  296. package/bundled/skills-windows/prizmkit-retrospective/references/structural-sync-steps.md +0 -43
  297. package/bundled/skills-windows/prizmkit-test/SKILL.md +0 -227
  298. package/bundled/skills-windows/prizmkit-test/references/boundary-coverage-protocol.md +0 -220
  299. package/bundled/skills-windows/prizmkit-test/references/examples.md +0 -143
  300. package/bundled/skills-windows/prizmkit-test/references/service-boundary-test-catalog.md +0 -225
  301. package/bundled/skills-windows/prizmkit-test/references/test-generation-steps.md +0 -109
  302. package/bundled/skills-windows/prizmkit-test/references/test-report-template.md +0 -111
  303. package/bundled/skills-windows/prizmkit-test/scripts/validate_boundary_report.py +0 -347
  304. package/bundled/skills-windows/recovery-workflow/SKILL.md +0 -355
  305. package/bundled/skills-windows/recovery-workflow/evals/evals.json +0 -46
  306. package/bundled/skills-windows/recovery-workflow/references/detection.md +0 -58
  307. package/bundled/skills-windows/recovery-workflow/scripts/detect-recovery-state.py +0 -544
  308. package/bundled/skills-windows/refactor-pipeline-launcher/SKILL.md +0 -346
  309. package/bundled/skills-windows/refactor-pipeline-launcher/references/configuration.md +0 -72
  310. package/bundled/skills-windows/refactor-planner/SKILL.md +0 -398
  311. package/bundled/skills-windows/refactor-planner/assets/planning-guide.md +0 -292
  312. package/bundled/skills-windows/refactor-planner/references/behavior-preservation.md +0 -301
  313. package/bundled/skills-windows/refactor-planner/references/fast-path.md +0 -59
  314. package/bundled/skills-windows/refactor-planner/references/planning-phases.md +0 -135
  315. package/bundled/skills-windows/refactor-planner/references/refactor-scoping-guide.md +0 -221
  316. package/bundled/skills-windows/refactor-planner/scripts/validate-and-generate-refactor.py +0 -858
  317. package/bundled/skills-windows/refactor-workflow/SKILL.md +0 -343
  318. package/bundled/skills-windows/refactor-workflow/references/brainstorm-guide.md +0 -116
  319. package/bundled/templates/hooks/diff-prizm-docs.sh +0 -158
  320. package/bundled/templates/hooks/prizm-pre-commit.sh +0 -108
  321. package/bundled/templates/hooks/validate-prizm-docs.sh +0 -139
@@ -1,1257 +0,0 @@
1
- #!/usr/bin/env bash
2
- # ============================================================
3
- # dev-pipeline/lib/common.sh - Shared shell helpers
4
- #
5
- # Shared by feature and bugfix pipeline runners.
6
- # Provides:
7
- # - CLI/platform detection
8
- # - Common color + log helpers
9
- # - Common dependency checks
10
- # ============================================================
11
-
12
- # Colors
13
- RED='\033[0;31m'
14
- GREEN='\033[0;32m'
15
- YELLOW='\033[1;33m'
16
- BLUE='\033[0;34m'
17
- MAGENTA='\033[0;35m'
18
- BOLD='\033[1m'
19
- NC='\033[0m'
20
-
21
- log_info() { echo -e "${BLUE}[INFO]${NC} $(date '+%Y-%m-%d %H:%M:%S') $*"; }
22
- log_warn() { echo -e "${YELLOW}[WARN]${NC} $(date '+%Y-%m-%d %H:%M:%S') $*"; }
23
- log_error() { echo -e "${RED}[ERROR]${NC} $(date '+%Y-%m-%d %H:%M:%S') $*"; }
24
- log_success() { echo -e "${GREEN}[SUCCESS]${NC} $(date '+%Y-%m-%d %H:%M:%S') $*"; }
25
-
26
- prizm_require_positive_int() {
27
- local option_name="$1"
28
- local option_value="$2"
29
- if [[ ! "$option_value" =~ ^[1-9][0-9]*$ ]]; then
30
- log_error "$option_name must be a positive integer: $option_value"
31
- exit 1
32
- fi
33
- }
34
-
35
- # Ignore temporary git worktrees created under root-level hidden AI tool dirs
36
- # matching .<tool>/worktree(s), without hiding normal source directories.
37
- PRIZM_GIT_HIDDEN_TOOL_WORKTREE_EXCLUDES=(
38
- ':(top,exclude,glob).*/worktree'
39
- ':(top,exclude,glob).*/worktree/**'
40
- ':(top,exclude,glob).*/worktrees'
41
- ':(top,exclude,glob).*/worktrees/**'
42
- )
43
-
44
- prizm_git_status_safe() {
45
- local project_root="$1"
46
- git -C "$project_root" status --porcelain -- . \
47
- "${PRIZM_GIT_HIDDEN_TOOL_WORKTREE_EXCLUDES[@]}" 2>/dev/null
48
- }
49
-
50
- prizm_git_add_all_safe() {
51
- local project_root="$1"
52
- git -C "$project_root" add -A -- . \
53
- "${PRIZM_GIT_HIDDEN_TOOL_WORKTREE_EXCLUDES[@]}" 2>/dev/null
54
- }
55
-
56
- prizm_git_relative_path() {
57
- local project_root="$1"
58
- local target_path="$2"
59
- python3 - "$project_root" "$target_path" <<'PY' 2>/dev/null || true
60
- import os
61
- import sys
62
- root = os.path.abspath(sys.argv[1])
63
- target = os.path.abspath(sys.argv[2])
64
- print(os.path.relpath(target, root).replace(os.sep, "/"))
65
- PY
66
- }
67
-
68
- prizm_git_status_non_bookkeeping() {
69
- local project_root="$1"
70
- local state_dir="$2"
71
- local list_path="$3"
72
-
73
- local state_rel list_rel
74
- state_rel="$(prizm_git_relative_path "$project_root" "$state_dir")"
75
- list_rel="$(prizm_git_relative_path "$project_root" "$list_path")"
76
-
77
- local line path
78
- while IFS= read -r line; do
79
- [[ -n "$line" ]] || continue
80
- path="${line:3}"
81
- if [[ "$path" == *" -> "* ]]; then
82
- path="${path##* -> }"
83
- fi
84
- path="${path%\"}"
85
- path="${path#\"}"
86
- path="${path#./}"
87
- if [[ -n "$list_rel" && "$path" == "$list_rel" ]]; then
88
- continue
89
- fi
90
- if [[ -n "$state_rel" && ( "$path" == "$state_rel" || "$path" == "$state_rel/"* ) ]]; then
91
- continue
92
- fi
93
- printf '%s\n' "$line"
94
- done < <(prizm_git_status_safe "$project_root")
95
- }
96
-
97
- prizm_git_status_bookkeeping() {
98
- local project_root="$1"
99
- local state_dir="$2"
100
- local list_path="$3"
101
-
102
- local state_rel list_rel
103
- state_rel="$(prizm_git_relative_path "$project_root" "$state_dir")"
104
- list_rel="$(prizm_git_relative_path "$project_root" "$list_path")"
105
-
106
- local line path
107
- while IFS= read -r line; do
108
- [[ -n "$line" ]] || continue
109
- path="${line:3}"
110
- if [[ "$path" == *" -> "* ]]; then
111
- path="${path##* -> }"
112
- fi
113
- path="${path%\"}"
114
- path="${path#\"}"
115
- path="${path#./}"
116
- if [[ -n "$list_rel" && "$path" == "$list_rel" ]]; then
117
- printf '%s\n' "$line"
118
- continue
119
- fi
120
- if [[ -n "$state_rel" && ( "$path" == "$state_rel" || "$path" == "$state_rel/"* ) ]]; then
121
- printf '%s\n' "$line"
122
- fi
123
- done < <(prizm_git_status_safe "$project_root")
124
- }
125
-
126
- prizm_git_commit_paths() {
127
- local project_root="$1"
128
- local message="$2"
129
- shift 2
130
-
131
- local paths=()
132
- local path rel_path
133
- for path in "$@"; do
134
- [[ -n "$path" && -e "$path" ]] || continue
135
- rel_path="$(prizm_git_relative_path "$project_root" "$path")"
136
- [[ -n "$rel_path" ]] || continue
137
- paths+=("$rel_path")
138
- done
139
- [[ ${#paths[@]} -gt 0 ]] || return 0
140
-
141
- git -C "$project_root" add -- "${paths[@]}" 2>/dev/null || true
142
- if ! git -C "$project_root" diff --cached --quiet -- "${paths[@]}" 2>/dev/null; then
143
- git -C "$project_root" commit --no-verify -m "$message" -- "${paths[@]}" 2>/dev/null || true
144
- fi
145
- }
146
-
147
-
148
- # ============================================================
149
- # Path resolution (single source of truth)
150
- # ============================================================
151
- # Exports three directories used throughout dev-pipeline scripts:
152
- # PIPELINE_DIR — directory containing the dev-pipeline scripts
153
- # PRIZMKIT_DIR — the .prizmkit/ runtime directory
154
- # PROJECT_ROOT — the user's project root
155
- #
156
- # Layout detection (no override case):
157
- # - If PIPELINE_DIR's parent is named ".prizmkit" → user-install layout
158
- # (.prizmkit/dev-pipeline/). PRIZMKIT_DIR = parent.
159
- # - Otherwise → framework repo source (<repo>/dev-pipeline/).
160
- # PROJECT_ROOT = parent, PRIZMKIT_DIR = <repo>/.prizmkit.
161
- #
162
- # Callers (tests) may pre-set any of these env vars to override detection.
163
- if [[ -z "${PIPELINE_DIR:-}" ]]; then
164
- PIPELINE_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
165
- fi
166
- if [[ -z "${PRIZMKIT_DIR:-}" || -z "${PROJECT_ROOT:-}" ]]; then
167
- _pipeline_parent="$(dirname "$PIPELINE_DIR")"
168
- if [[ "$(basename "$_pipeline_parent")" == ".prizmkit" ]]; then
169
- : "${PRIZMKIT_DIR:=$_pipeline_parent}"
170
- : "${PROJECT_ROOT:=$(dirname "$_pipeline_parent")}"
171
- else
172
- : "${PROJECT_ROOT:=$_pipeline_parent}"
173
- : "${PRIZMKIT_DIR:=$PROJECT_ROOT/.prizmkit}"
174
- fi
175
- unset _pipeline_parent
176
- fi
177
- export PIPELINE_DIR PRIZMKIT_DIR PROJECT_ROOT
178
-
179
- # ============================================================
180
- # .env file loading
181
- # ============================================================
182
-
183
- # Load .env file if it exists. Does NOT override already-set env vars.
184
- # Supports: KEY=VALUE, KEY="VALUE", KEY='VALUE', comments (#), empty lines.
185
- # If the file does not exist, silently continues (no error).
186
- prizm_load_env() {
187
- local env_file="${1:-.env}"
188
- [[ -f "$env_file" ]] || return 0
189
-
190
- while IFS= read -r line || [[ -n "$line" ]]; do
191
- # Skip empty lines and comments
192
- [[ -z "$line" || "$line" =~ ^[[:space:]]*# ]] && continue
193
- # Remove inline comments (not inside quotes)
194
- line="${line%%#*}"
195
- # Trim whitespace
196
- line="$(echo "$line" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')"
197
- [[ -z "$line" ]] && continue
198
- # Parse KEY=VALUE
199
- if [[ "$line" =~ ^([A-Za-z_][A-Za-z0-9_]*)=(.*)$ ]]; then
200
- local key="${BASH_REMATCH[1]}"
201
- local val="${BASH_REMATCH[2]}"
202
- # Strip surrounding quotes
203
- val="${val#\"}" ; val="${val%\"}"
204
- val="${val#\'}" ; val="${val%\'}"
205
- # Only set if not already defined in environment
206
- if [[ -z "${!key+x}" ]]; then
207
- export "$key=$val"
208
- fi
209
- fi
210
- done < "$env_file"
211
- }
212
-
213
- # ============================================================
214
- # Test mode: bootstrap prompt logging
215
- # ============================================================
216
-
217
- # Log bootstrap prompt content when PRIZMKIT_ENV=test.
218
- # Called after prompt generation, before AI CLI session spawn.
219
- # Usage: prizm_log_bootstrap_prompt <prompt_path> <item_id>
220
- prizm_log_bootstrap_prompt() {
221
- local prompt_path="$1"
222
- local item_id="$2"
223
-
224
- [[ "${PRIZMKIT_ENV:-}" == "test" ]] || return 0
225
- [[ -f "$prompt_path" ]] || return 0
226
-
227
- local lines size
228
- lines=$(wc -l < "$prompt_path" 2>/dev/null | tr -d ' ')
229
- size=$(wc -c < "$prompt_path" 2>/dev/null | tr -d ' ')
230
-
231
- echo ""
232
- echo -e "${MAGENTA}[TEST]${NC} ════════════════════════════════════════════════════"
233
- echo -e "${MAGENTA}[TEST]${NC} Bootstrap Prompt for $item_id"
234
- echo -e "${MAGENTA}[TEST]${NC} Lines: $lines | Size: $((size / 1024))KB"
235
- echo -e "${MAGENTA}[TEST]${NC} Path: $prompt_path"
236
- echo -e "${MAGENTA}[TEST]${NC} ════════════════════════════════════════════════════"
237
- cat "$prompt_path"
238
- echo ""
239
- echo -e "${MAGENTA}[TEST]${NC} ════════════════════════ END ═══════════════════════"
240
- echo ""
241
- }
242
-
243
- # Detect AI CLI + platform.
244
- # Priority:
245
- # AI_CLI env > .prizmkit/config.json ai_cli > manifest/config platform > CODEBUDDY_CLI
246
- # > installed PrizmKit platform artifacts > PATH auto-detect > error
247
- #
248
- # Exports:
249
- # CLI_CMD
250
- # PLATFORM
251
- # PRIZMKIT_PLATFORM
252
- _prizm_json_value() {
253
- local json_file="$1"
254
- local key="$2"
255
- [[ -f "$json_file" ]] || return 0
256
- JSON_FILE="$json_file" JSON_KEY="$key" python3 - <<'PY' 2>/dev/null || true
257
- import json
258
- import os
259
-
260
- try:
261
- with open(os.environ["JSON_FILE"], encoding="utf-8") as fh:
262
- data = json.load(fh)
263
- value = data.get(os.environ["JSON_KEY"], "")
264
- if value is not None and value != "":
265
- print(value)
266
- except Exception:
267
- pass
268
- PY
269
- }
270
-
271
- _prizm_normalize_platform() {
272
- printf '%s' "$1" | tr '[:upper:]' '[:lower:]'
273
- }
274
-
275
- _prizm_concrete_platform() {
276
- case "$(_prizm_normalize_platform "$1")" in
277
- codex|claude|codebuddy) printf '%s\n' "$(_prizm_normalize_platform "$1")" ;;
278
- esac
279
- }
280
-
281
- _prizm_cli_names_for_platform() {
282
- case "$(_prizm_normalize_platform "$1")" in
283
- codex) printf '%s\n' codex ;;
284
- claude) printf '%s\n' claude ;;
285
- codebuddy) printf '%s\n' cbc ;;
286
- both) printf '%s\n' claude cbc ;;
287
- all) printf '%s\n' codex claude cbc ;;
288
- esac
289
- }
290
-
291
- _prizm_expected_cli_text() {
292
- _prizm_cli_names_for_platform "$1" | awk 'BEGIN { sep="" } { printf "%s%s", sep, $0; sep=", " } END { if (sep != "") print "" }'
293
- }
294
-
295
- _prizm_resolve_cli_name() {
296
- local cli_name="$1"
297
- if [[ "$cli_name" == "cbc" && -n "${CODEBUDDY_CLI:-}" ]]; then
298
- printf '%s\n' "$CODEBUDDY_CLI"
299
- return 0
300
- fi
301
- if command -v "$cli_name" &>/dev/null; then
302
- printf '%s\n' "$cli_name"
303
- return 0
304
- fi
305
- return 1
306
- }
307
-
308
- _prizm_cli_for_platform() {
309
- local platform="$1"
310
- local cli_name cli_cmd
311
- while IFS= read -r cli_name; do
312
- [[ -n "$cli_name" ]] || continue
313
- cli_cmd="$(_prizm_resolve_cli_name "$cli_name" || true)"
314
- if [[ -n "$cli_cmd" ]]; then
315
- printf '%s\n' "$cli_cmd"
316
- return 0
317
- fi
318
- done < <(_prizm_cli_names_for_platform "$platform")
319
- return 1
320
- }
321
-
322
- _prizm_known_platform_from_cli() {
323
- local cli_cmd="$1"
324
- local cli_token="${cli_cmd%%[[:space:]]*}"
325
- cli_token="${cli_token#\"}" ; cli_token="${cli_token%\"}"
326
- cli_token="${cli_token#\'}" ; cli_token="${cli_token%\'}"
327
- local cli_name="${cli_token##*/}"
328
- if [[ "$cli_name" == *"claude"* ]]; then
329
- printf '%s\n' claude
330
- elif [[ "$cli_name" == *"codex"* ]]; then
331
- printf '%s\n' codex
332
- elif [[ "$cli_name" == *"cbc"* || "$cli_name" == *"codebuddy"* ]]; then
333
- printf '%s\n' codebuddy
334
- else
335
- return 1
336
- fi
337
- }
338
-
339
- _prizm_platform_from_cli() {
340
- local cli_cmd="$1"
341
- if ! _prizm_known_platform_from_cli "$cli_cmd"; then
342
- printf '%s\n' codebuddy
343
- fi
344
- }
345
-
346
- _prizm_session_platform() {
347
- local cli_platform
348
- cli_platform="$(_prizm_known_platform_from_cli "$CLI_CMD" || true)"
349
- if [[ -n "$cli_platform" ]]; then
350
- printf '%s\n' "$cli_platform"
351
- return 0
352
- fi
353
-
354
- local platform="${PRIZMKIT_PLATFORM:-${PLATFORM:-}}"
355
- case "$(_prizm_normalize_platform "$platform")" in
356
- codex|claude|codebuddy) printf '%s\n' "$(_prizm_normalize_platform "$platform")" ;;
357
- *) _prizm_platform_from_cli "$CLI_CMD" ;;
358
- esac
359
- }
360
-
361
- _prizm_project_platform_for_cli() {
362
- local cli_cmd="$1"
363
- local manifest_platform="$2"
364
- local config_platform="$3"
365
- local cli_platform
366
- cli_platform="$(_prizm_known_platform_from_cli "$cli_cmd" || true)"
367
- if [[ -n "$cli_platform" ]]; then
368
- printf '%s\n' "$cli_platform"
369
- elif [[ -n "${PRIZMKIT_PLATFORM:-}" ]]; then
370
- printf '%s\n' "$PRIZMKIT_PLATFORM"
371
- elif [[ -n "$(_prizm_concrete_platform "$manifest_platform")" ]]; then
372
- _prizm_concrete_platform "$manifest_platform"
373
- elif [[ -n "$(_prizm_concrete_platform "$config_platform")" ]]; then
374
- _prizm_concrete_platform "$config_platform"
375
- else
376
- printf '%s\n' codebuddy
377
- fi
378
- }
379
-
380
- prizm_detect_cli_and_platform() {
381
- # Load .env from .prizmkit/.env if it exists (does not override existing env vars)
382
- if [[ -n "${PRIZMKIT_DIR:-}" ]]; then
383
- prizm_load_env "$PRIZMKIT_DIR/.env"
384
- fi
385
-
386
- local _raw_cli=""
387
- local _config_ai_cli=""
388
- local _config_platform=""
389
- local _manifest_platform=""
390
- local _installed_cli=""
391
- local _platform_cli=""
392
- local _platform_cli_names=""
393
-
394
- if [[ -n "${PRIZMKIT_DIR:-}" ]]; then
395
- _config_ai_cli="$(_prizm_json_value "$PRIZMKIT_DIR/config.json" ai_cli)"
396
- _config_platform="$(_prizm_json_value "$PRIZMKIT_DIR/config.json" platform)"
397
- _manifest_platform="$(_prizm_json_value "$PRIZMKIT_DIR/manifest.json" platform)"
398
- fi
399
-
400
- _detect_installed_platform_cli() {
401
- if [[ -f "$PROJECT_ROOT/.codex/agents/prizm-dev-team-dev.toml" || -f "$PROJECT_ROOT/.agents/skills/prizm-kit/SKILL.md" ]] && command -v codex &>/dev/null; then
402
- echo "codex"
403
- elif [[ -f "$PROJECT_ROOT/.claude/commands/prizm-kit.md" ]] && command -v claude &>/dev/null; then
404
- echo "claude"
405
- elif [[ -f "$PROJECT_ROOT/.codebuddy/agents/prizm-dev-team-dev.md" || -f "$PROJECT_ROOT/.codebuddy/skills/prizm-kit/SKILL.md" ]]; then
406
- _prizm_resolve_cli_name cbc || true
407
- fi
408
- }
409
-
410
- if [[ -n "${AI_CLI:-}" ]]; then
411
- _raw_cli="$AI_CLI"
412
- elif [[ -n "$_config_ai_cli" ]]; then
413
- _raw_cli="$_config_ai_cli"
414
- elif [[ -n "$_manifest_platform" ]]; then
415
- _platform_cli="$(_prizm_cli_for_platform "$_manifest_platform" || true)"
416
- _platform_cli_names="$(_prizm_cli_names_for_platform "$_manifest_platform")"
417
- if [[ -n "$_platform_cli" ]]; then
418
- _raw_cli="$_platform_cli"
419
- elif [[ -n "$_platform_cli_names" ]]; then
420
- echo "ERROR: Installed PrizmKit platform '$_manifest_platform' requires one of: $(_prizm_expected_cli_text "$_manifest_platform"). Install it or set AI_CLI." >&2
421
- exit 1
422
- fi
423
- elif [[ -n "$_config_platform" ]]; then
424
- _platform_cli="$(_prizm_cli_for_platform "$_config_platform" || true)"
425
- _platform_cli_names="$(_prizm_cli_names_for_platform "$_config_platform")"
426
- if [[ -n "$_platform_cli" ]]; then
427
- _raw_cli="$_platform_cli"
428
- elif [[ -n "$_platform_cli_names" ]]; then
429
- echo "ERROR: Configured PrizmKit platform '$_config_platform' requires one of: $(_prizm_expected_cli_text "$_config_platform"). Install it or set AI_CLI." >&2
430
- exit 1
431
- fi
432
- fi
433
-
434
- if [[ -z "$_raw_cli" && -n "${CODEBUDDY_CLI:-}" ]]; then
435
- _raw_cli="$CODEBUDDY_CLI"
436
- fi
437
- if [[ -z "$_raw_cli" ]]; then
438
- _installed_cli="$(_detect_installed_platform_cli || true)"
439
- if [[ -n "$_installed_cli" ]]; then
440
- _raw_cli="$_installed_cli"
441
- fi
442
- fi
443
- if [[ -z "$_raw_cli" ]] && command -v claude &>/dev/null; then
444
- _raw_cli="claude"
445
- elif [[ -z "$_raw_cli" ]] && command -v cbc &>/dev/null; then
446
- _raw_cli="cbc"
447
- elif [[ -z "$_raw_cli" ]] && command -v codex &>/dev/null; then
448
- _raw_cli="codex"
449
- elif [[ -z "$_raw_cli" ]]; then
450
- echo "ERROR: No AI CLI found. Install CodeBuddy (cbc), Claude Code (claude), or Codex (codex)." >&2
451
- exit 1
452
- fi
453
-
454
- CLI_CMD="$_raw_cli"
455
-
456
- PLATFORM="$(_prizm_project_platform_for_cli "$_raw_cli" "$_manifest_platform" "$_config_platform")"
457
-
458
- export CLI_CMD
459
- export PLATFORM
460
- export PRIZMKIT_PLATFORM="$PLATFORM"
461
- }
462
-
463
- # Validate PRIZMKIT_EFFORT against the detected platform's supported values.
464
- # Exits with a friendly error if the value is unsupported.
465
- prizm_validate_effort() {
466
- [[ -n "${PRIZMKIT_EFFORT:-}" ]] || return 0
467
-
468
- local session_platform
469
- session_platform="$(_prizm_session_platform)"
470
-
471
- local allowed_values
472
- case "$session_platform" in
473
- claude) allowed_values="low, medium, high, xhigh, max" ;;
474
- codex) allowed_values="low, medium, high, xhigh" ;;
475
- *) allowed_values="low, medium, high, xhigh" ;;
476
- esac
477
-
478
- local valid=0
479
- local val
480
- for val in $allowed_values; do
481
- val="${val%,}"
482
- [[ "$val" == "$PRIZMKIT_EFFORT" ]] && valid=1 && break
483
- done
484
-
485
- if [[ "$valid" -ne 1 ]]; then
486
- local platform_label="$session_platform"
487
- [[ "$session_platform" == "claude" ]] && platform_label="Claude Code"
488
- [[ "$session_platform" == "codebuddy" ]] && platform_label="CodeBuddy"
489
- [[ "$session_platform" == "codex" ]] && platform_label="Codex"
490
-
491
- log_error "PRIZMKIT_EFFORT='$PRIZMKIT_EFFORT' is not supported by the detected CLI ($platform_label)."
492
- log_error " Supported values for $platform_label: $allowed_values"
493
- log_error " Set PRIZMKIT_EFFORT to one of the above, or unset it to use the CLI default."
494
- exit 1
495
- fi
496
- }
497
-
498
- # Start an AI CLI session in the background.
499
- # Usage: prizm_start_ai_session <prompt_path> <log_path> <model>
500
- # Sets PRIZM_AI_PID to the spawned process PID. Do not call this function via
501
- # command substitution; the background process must remain a child of the
502
- # runner shell so wait/heartbeat/trap handling works correctly.
503
- PRIZM_AI_PID=""
504
-
505
- _prizm_codex_subagent_timeout_seconds() {
506
- local configured="${CODEX_SUBAGENT_TIMEOUT_SECONDS:-}"
507
- if [[ "$configured" =~ ^[0-9]+$ && "$configured" -gt 0 ]]; then
508
- printf '%s\n' "$configured"
509
- return 0
510
- fi
511
-
512
- local wait_threshold="${CODEX_WAIT_STALE_KILL_THRESHOLD:-3600}"
513
- if [[ "$wait_threshold" =~ ^[0-9]+$ && "$wait_threshold" -gt 600 ]]; then
514
- printf '%s\n' "$((wait_threshold - 300))"
515
- return 0
516
- fi
517
-
518
- printf '%s\n' 3300
519
- }
520
-
521
- prizm_start_ai_session() {
522
- local prompt_path="$1"
523
- local log_path="$2"
524
- local model="${3:-}"
525
-
526
- unset CLAUDECODE 2>/dev/null || true
527
-
528
- # Create backup outside project tree. Claude Code subagents can unlink
529
- # session.log inside the project, but cannot reach $HOME/.prizmkit/.
530
- # tee writes to the backup file while >> redirects to the main log.
531
- # If the main log gets severed (unlinked+recreated by subagent),
532
- # prizm_recover_session_log copies the backup back when the session ends.
533
- local backup_dir="$HOME/.prizmkit/session-backups"
534
- mkdir -p "$backup_dir"
535
- local session_dir
536
- session_dir="$(dirname "$(dirname "$log_path")")"
537
- local session_id
538
- session_id="$(basename "$session_dir")"
539
- local backup_log="$backup_dir/${session_id}.log"
540
- PRIZM_BACKUP_LOG="$backup_log"
541
-
542
- # Write preamble to both files
543
- {
544
- echo "=== PRIZMKIT SESSION START ==="
545
- echo "Prompt: $prompt_path"
546
- echo "Model: ${model:-default}"
547
- echo "Started at: $(date -u +%Y-%m-%dT%H:%M:%SZ)"
548
- echo "--- OUTPUT BELOW ---"
549
- } > "$log_path"
550
- cp "$log_path" "$backup_log"
551
-
552
- local session_platform
553
- session_platform="$(_prizm_session_platform)"
554
-
555
- case "$session_platform" in
556
- claude)
557
- local claude_args=(-p "$(cat "$prompt_path")" --dangerously-skip-permissions)
558
- if [[ "$VERBOSE" == "1" || "$USE_STREAM_JSON" == "true" ]]; then
559
- claude_args+=(--verbose)
560
- fi
561
- if [[ "$USE_STREAM_JSON" == "true" ]]; then
562
- claude_args+=(--output-format stream-json)
563
- fi
564
- if [[ -n "${PRIZMKIT_EFFORT:-}" ]]; then
565
- claude_args+=(--effort "$PRIZMKIT_EFFORT")
566
- fi
567
- if [[ -n "$model" ]]; then
568
- claude_args+=(--model "$model")
569
- fi
570
- "$CLI_CMD" "${claude_args[@]}" 2>&1 | tee -a "$backup_log" >> "$log_path" &
571
- ;;
572
- codex)
573
- local codex_args=(--ask-for-approval never --sandbox danger-full-access)
574
- local codex_subagent_timeout
575
- codex_subagent_timeout="$(_prizm_codex_subagent_timeout_seconds)"
576
- if [[ "$codex_subagent_timeout" =~ ^[0-9]+$ && "$codex_subagent_timeout" -gt 0 ]]; then
577
- codex_args+=(--config "agents.job_max_runtime_seconds=$codex_subagent_timeout")
578
- fi
579
- codex_args+=(exec --cd "$PROJECT_ROOT" --skip-git-repo-check)
580
- if [[ "$USE_STREAM_JSON" == "true" ]]; then
581
- codex_args+=(--json)
582
- fi
583
- if [[ -n "$model" ]]; then
584
- codex_args+=(--model "$model")
585
- fi
586
- if [[ -n "${PRIZMKIT_EFFORT:-}" ]]; then
587
- codex_args+=(--config "model_reasoning_effort=$PRIZMKIT_EFFORT")
588
- fi
589
- "$CLI_CMD" "${codex_args[@]}" - < "$prompt_path" 2>&1 | tee -a "$backup_log" >> "$log_path" &
590
- ;;
591
- *)
592
- local cb_args=(--print -y)
593
- if [[ "$VERBOSE" == "1" ]]; then
594
- cb_args+=(--verbose)
595
- fi
596
- if [[ "$USE_STREAM_JSON" == "true" ]]; then
597
- cb_args+=(--output-format stream-json)
598
- fi
599
- if [[ -n "${PRIZMKIT_EFFORT:-}" ]]; then
600
- cb_args+=(--effort "$PRIZMKIT_EFFORT")
601
- fi
602
- if [[ -n "$model" ]]; then
603
- cb_args+=(--model "$model")
604
- fi
605
- "$CLI_CMD" "${cb_args[@]}" < "$prompt_path" 2>&1 | tee -a "$backup_log" >> "$log_path" &
606
- ;;
607
- esac
608
- PRIZM_AI_PID=$!
609
- }
610
-
611
- # Detect AI CLI/provider infrastructure failures that are outside the
612
- # generated code's control. These should be retried without consuming the
613
- # item's code retry budget.
614
- prizm_detect_infra_error() {
615
- local session_log="${1:-}"
616
- local progress_json="${2:-}"
617
-
618
- local haystack=""
619
- if [[ -n "$session_log" && -f "$session_log" ]]; then
620
- haystack="$(tail -c 65536 "$session_log" 2>/dev/null || true)"
621
- fi
622
- if [[ -n "$progress_json" && -f "$progress_json" ]]; then
623
- haystack+=$'\n'
624
- haystack+="$(cat "$progress_json" 2>/dev/null || true)"
625
- fi
626
-
627
- [[ -n "$haystack" ]] || return 1
628
-
629
- if printf '%s' "$haystack" | grep -Eiq \
630
- 'auth_unavailable|no auth available|502 Bad Gateway|503 Service Unavailable|504 Gateway Timeout|gateway timeout|upstream (connect )?error|connection reset|ECONNRESET|ETIMEDOUT|ENOTFOUND|EAI_AGAIN|rate limit|rate_limit|temporarily unavailable|overloaded'; then
631
- return 0
632
- fi
633
-
634
- return 1
635
- }
636
-
637
- # Detect AI runtime/provider request failures that are not caused by generated
638
- # project code. Unlike generic infra errors, these can be deterministic for the
639
- # current transcript (for example context_too_large), so the runner must first
640
- # check semantic completion before deciding whether to retry.
641
- prizm_detect_ai_runtime_error() {
642
- local session_log="${1:-}"
643
- local progress_json="${2:-}"
644
-
645
- if [[ -n "$progress_json" && -f "$progress_json" ]]; then
646
- local fatal_error_code
647
- fatal_error_code=$(python3 - "$progress_json" <<'PY' 2>/dev/null || true
648
- import json
649
- import sys
650
-
651
- try:
652
- with open(sys.argv[1], encoding="utf-8") as fh:
653
- progress = json.load(fh)
654
- except Exception:
655
- raise SystemExit(0)
656
-
657
- code = progress.get("fatal_error_code")
658
- if code:
659
- print(str(code))
660
- PY
661
- )
662
- if [[ -n "$fatal_error_code" ]]; then
663
- return 0
664
- fi
665
- fi
666
-
667
- local haystack=""
668
- if [[ -n "$session_log" && -f "$session_log" ]]; then
669
- haystack="$(tail -c 65536 "$session_log" 2>/dev/null || true)"
670
- fi
671
- if [[ -n "$progress_json" && -f "$progress_json" ]]; then
672
- haystack+=$'\n'
673
- haystack+="$(cat "$progress_json" 2>/dev/null || true)"
674
- fi
675
-
676
- [[ -n "$haystack" ]] || return 1
677
-
678
- if printf '%s' "$haystack" | grep -Eiq \
679
- 'context_too_large|model_context_window_exceeded|input exceeds the context window|context window of this model|context window (was )?exceeded|exceeded (the )?context window|invalid_request_error.*context window|context window.*invalid_request_error'; then
680
- if printf '%s' "$haystack" | grep -Eiq \
681
- 'api error|invalid_request_error|api_error_status|api_error_code|status[[:space:]]*[:=]?[[:space:]]*(400|413)|last_result_is_error[[:space:]"'\'':=]+true|is_error[[:space:]"'\'':=]+true'; then
682
- return 0
683
- fi
684
- fi
685
-
686
- return 1
687
- }
688
-
689
- prizm_feature_slug_from_list() {
690
- local feature_list="$1"
691
- local feature_id="$2"
692
- python3 - "$feature_list" "$feature_id" <<'PY'
693
- import json
694
- import re
695
- import sys
696
-
697
- feature_list, feature_id = sys.argv[1], sys.argv[2]
698
- with open(feature_list, encoding="utf-8") as fh:
699
- data = json.load(fh)
700
- for feature in data.get("features", []):
701
- if feature.get("id") == feature_id:
702
- number = feature.get("id", "").replace("F-", "").replace("f-", "").zfill(3)
703
- title = str(feature.get("title", "")).lower()
704
- title = re.sub(r"[^a-z0-9\s-]", "", title)
705
- title = re.sub(r"[\s]+", "-", title.strip())
706
- title = re.sub(r"-+", "-", title).strip("-")
707
- print(f"{number}-{title}" if title else number)
708
- raise SystemExit(0)
709
- raise SystemExit(1)
710
- PY
711
- }
712
-
713
- prizm_checkpoint_all_complete() {
714
- local checkpoint_file="$1"
715
- [[ -f "$checkpoint_file" ]] || return 1
716
- python3 - "$checkpoint_file" <<'PY'
717
- import json
718
- import sys
719
-
720
- try:
721
- with open(sys.argv[1], encoding="utf-8") as fh:
722
- data = json.load(fh)
723
- except Exception:
724
- raise SystemExit(2)
725
- steps = data.get("steps")
726
- if not isinstance(steps, list) or not steps:
727
- raise SystemExit(1)
728
- for step in steps:
729
- if not isinstance(step, dict) or step.get("status") not in ("completed", "skipped"):
730
- raise SystemExit(1)
731
- raise SystemExit(0)
732
- PY
733
- }
734
-
735
- # Return the successful feature commit SHA if one exists in base_ref..HEAD.
736
- # Prefer messages containing the feature ID. If checkpoint is complete, allow an
737
- # older prompt variant only when the non-WIP commit identifies the feature title.
738
- prizm_find_feature_commit() {
739
- local project_root="$1"
740
- local base_ref="$2"
741
- local feature_id="$3"
742
- local allow_title_fallback="${4:-false}"
743
- local feature_title="${5:-}"
744
-
745
- git -C "$project_root" rev-parse --is-inside-work-tree >/dev/null 2>&1 || return 1
746
-
747
- local range="${base_ref}..HEAD"
748
- if [[ -z "$base_ref" ]] || ! git -C "$project_root" rev-parse --verify "$base_ref" >/dev/null 2>&1; then
749
- range="HEAD"
750
- fi
751
-
752
- local feature_commit
753
- feature_commit=$(git -C "$project_root" log "$range" --format='%H%x09%s' 2>/dev/null \
754
- | awk -F '\t' -v fid="$feature_id" 'index($2, fid) > 0 && $2 !~ /^wip(\(|:)/ { print $1; exit }')
755
- if [[ -n "$feature_commit" ]]; then
756
- printf '%s\n' "$feature_commit"
757
- return 0
758
- fi
759
-
760
- if [[ "$allow_title_fallback" == "true" && -n "$feature_title" ]]; then
761
- feature_commit=$(git -C "$project_root" log "$range" --format='%H%x09%s' 2>/dev/null \
762
- | python3 -c '
763
- import re
764
- import sys
765
-
766
- title = sys.argv[1]
767
-
768
- def words(text):
769
- return [w for w in re.split(r"[^a-z0-9]+", text.lower()) if len(w) >= 3]
770
-
771
- title_words = words(title)
772
- if not title_words:
773
- raise SystemExit(1)
774
- # Require all title words for short titles, or a strong majority for longer
775
- # titles so punctuation/articles do not make older commits unmatchable.
776
- required = len(title_words) if len(title_words) <= 3 else max(3, int(len(title_words) * 0.75 + 0.999))
777
- for line in sys.stdin:
778
- commit, sep, subject = line.rstrip("\n").partition("\t")
779
- if not sep or re.match(r"^wip(\(|:)", subject):
780
- continue
781
- subject_words = set(words(subject))
782
- if sum(1 for word in title_words if word in subject_words) >= required:
783
- print(commit)
784
- raise SystemExit(0)
785
- raise SystemExit(1)
786
- ' "$feature_title")
787
- if [[ -n "$feature_commit" ]]; then
788
- printf '%s\n' "$feature_commit"
789
- return 0
790
- fi
791
- fi
792
-
793
- return 1
794
- }
795
-
796
- # Semantic completion means the durable workflow checkpoint is complete and a
797
- # non-WIP feature commit exists. This intentionally runs before exit-code based
798
- # failure classification so delayed post-commit model errors cannot strand a
799
- # completed feature on its dev branch.
800
- PRIZM_SEMANTIC_FEATURE_SLUG=""
801
- PRIZM_SEMANTIC_COMMIT_SHA=""
802
- prizm_feature_semantically_complete() {
803
- local feature_list="$1"
804
- local feature_id="$2"
805
- local project_root="$3"
806
- local base_ref="$4"
807
- local prizmkit_dir="$5"
808
-
809
- PRIZM_SEMANTIC_FEATURE_SLUG=""
810
- PRIZM_SEMANTIC_COMMIT_SHA=""
811
-
812
- local feature_slug
813
- feature_slug=$(prizm_feature_slug_from_list "$feature_list" "$feature_id" 2>/dev/null) || return 1
814
- local checkpoint_file="$prizmkit_dir/specs/${feature_slug}/workflow-checkpoint.json"
815
- prizm_checkpoint_all_complete "$checkpoint_file" || return 1
816
-
817
- local feature_title
818
- feature_title=$(python3 - "$feature_list" "$feature_id" <<'PY' 2>/dev/null || true
819
- import json
820
- import sys
821
- with open(sys.argv[1], encoding="utf-8") as fh:
822
- data = json.load(fh)
823
- for feature in data.get("features", []):
824
- if feature.get("id") == sys.argv[2]:
825
- print(feature.get("title", ""))
826
- break
827
- PY
828
- )
829
-
830
- local commit_sha
831
- commit_sha=$(prizm_find_feature_commit "$project_root" "$base_ref" "$feature_id" true "$feature_title" 2>/dev/null) || return 1
832
-
833
- PRIZM_SEMANTIC_FEATURE_SLUG="$feature_slug"
834
- PRIZM_SEMANTIC_COMMIT_SHA="$commit_sha"
835
- return 0
836
- }
837
-
838
- prizm_synthesize_failure_log() {
839
- local failure_log="$1"
840
- local feature_id="$2"
841
- local session_id="$3"
842
- local session_status="$4"
843
- local exit_code="$5"
844
- local stale_kill_marker="$6"
845
- local progress_json="$7"
846
- local checkpoint_file="$8"
847
- local project_root="$9"
848
- local base_ref="${10:-}"
849
-
850
- [[ -n "$failure_log" ]] || return 0
851
- [[ -f "$failure_log" ]] && return 0
852
- mkdir -p "$(dirname "$failure_log")" || return 0
853
-
854
- local progress_summary="Progress data unavailable."
855
- if [[ -f "$progress_json" ]]; then
856
- progress_summary=$(python3 - "$progress_json" <<'PY' 2>/dev/null || true
857
- import json
858
- import sys
859
- try:
860
- with open(sys.argv[1], encoding="utf-8") as fh:
861
- data = json.load(fh)
862
- except Exception as exc:
863
- print(f"Progress parse error: {exc}")
864
- raise SystemExit(0)
865
- fields = [
866
- ("fatal_error_code", data.get("fatal_error_code")),
867
- ("api_error_status", data.get("api_error_status")),
868
- ("api_error_code", data.get("api_error_code")),
869
- ("current_phase", data.get("current_phase")),
870
- ("current_tool", data.get("current_tool")),
871
- ("last_text_snippet", data.get("last_text_snippet")),
872
- ("terminal_result_text", data.get("terminal_result_text")),
873
- ]
874
- for key, value in fields:
875
- if value not in (None, "", []):
876
- text = str(value).replace("\n", " ")
877
- print(f"- {key}: {text[:500]}")
878
- PY
879
- )
880
- [[ -n "$progress_summary" ]] || progress_summary="Progress data contained no terminal fields."
881
- fi
882
-
883
- local stale_summary="No stale-kill marker."
884
- if [[ -f "$stale_kill_marker" ]]; then
885
- stale_summary="$(cat "$stale_kill_marker" 2>/dev/null || true)"
886
- fi
887
-
888
- local checkpoint_summary="No checkpoint file found."
889
- if [[ -f "$checkpoint_file" ]]; then
890
- checkpoint_summary=$(python3 - "$checkpoint_file" <<'PY' 2>/dev/null || true
891
- import json
892
- import sys
893
- try:
894
- with open(sys.argv[1], encoding="utf-8") as fh:
895
- data = json.load(fh)
896
- except Exception as exc:
897
- print(f"Checkpoint parse error: {exc}")
898
- raise SystemExit(0)
899
- steps = data.get("steps") or []
900
- complete = sum(1 for step in steps if isinstance(step, dict) and step.get("status") in ("completed", "skipped"))
901
- print(f"{complete}/{len(steps)} steps completed_or_skipped")
902
- for step in steps:
903
- if isinstance(step, dict) and step.get("status") not in ("completed", "skipped"):
904
- print(f"- incomplete: {step.get('id')} {step.get('skill')} = {step.get('status')}")
905
- PY
906
- )
907
- fi
908
-
909
- local latest_commit="unavailable"
910
- local feature_commit="no"
911
- if git -C "$project_root" rev-parse --is-inside-work-tree >/dev/null 2>&1; then
912
- latest_commit=$(git -C "$project_root" rev-parse --short HEAD 2>/dev/null || echo unavailable)
913
- if prizm_find_feature_commit "$project_root" "$base_ref" "$feature_id" false >/dev/null 2>&1; then
914
- feature_commit="yes"
915
- fi
916
- fi
917
-
918
- local dirty_summary="unavailable"
919
- dirty_summary=$(git -C "$project_root" status --short 2>/dev/null || true)
920
- [[ -n "$dirty_summary" ]] || dirty_summary="clean"
921
-
922
- cat > "$failure_log" <<EOF
923
- # Runtime-synthesized failure log
924
-
925
- ## Session
926
-
927
- - feature_id: $feature_id
928
- - session_id: ${session_id:-unknown}
929
- - session_status: $session_status
930
- - exit_code: $exit_code
931
-
932
- ## Stale kill marker
933
-
934
- \`\`\`json
935
- $stale_summary
936
- \`\`\`
937
-
938
- ## Progress
939
-
940
- $progress_summary
941
-
942
- ## Checkpoint
943
-
944
- $checkpoint_summary
945
-
946
- ## Git state
947
-
948
- - feature_commit_exists: $feature_commit
949
- - latest_commit: $latest_commit
950
-
951
- \`\`\`text
952
- $dirty_summary
953
- \`\`\`
954
-
955
- ## Recommended recovery action
956
-
957
- - If this is an AI runtime/provider error before checkpoint completion, retry the session with a fresh context.
958
- - If the working tree is dirty, preserve or review those changes before any reset or merge.
959
- EOF
960
- }
961
-
962
- prizm_extract_update_new_status() {
963
- python3 -c "
964
- import json, sys
965
- raw = sys.stdin.read()
966
- try:
967
- data = json.loads(raw)
968
- except Exception:
969
- sys.exit(0)
970
- value = data.get('new_status')
971
- if value:
972
- print(value)
973
- "
974
- }
975
-
976
- # Run an AI CLI session synchronously.
977
- # Usage: prizm_run_ai_session <prompt_path> <log_path> <model>
978
- prizm_run_ai_session() {
979
- local prompt_path="$1"
980
- local log_path="$2"
981
- local model="${3:-}"
982
-
983
- unset CLAUDECODE 2>/dev/null || true
984
-
985
- # Create backup outside project tree (same rationale as prizm_start_ai_session)
986
- local backup_dir="$HOME/.prizmkit/session-backups"
987
- mkdir -p "$backup_dir"
988
- local session_dir
989
- session_dir="$(dirname "$(dirname "$log_path")")"
990
- local session_id
991
- session_id="$(basename "$session_dir")"
992
- local backup_log="$backup_dir/${session_id}.log"
993
- PRIZM_BACKUP_LOG="$backup_log"
994
-
995
- # Write preamble to both files
996
- {
997
- echo "=== PRIZMKIT SESSION START ==="
998
- echo "Prompt: $prompt_path"
999
- echo "Model: ${model:-default}"
1000
- echo "Started at: $(date -u +%Y-%m-%dT%H:%M:%SZ)"
1001
- echo "--- OUTPUT BELOW ---"
1002
- } > "$log_path"
1003
- cp "$log_path" "$backup_log"
1004
-
1005
- local session_platform
1006
- session_platform="$(_prizm_session_platform)"
1007
-
1008
- case "$session_platform" in
1009
- claude)
1010
- local claude_args=(-p "$(cat "$prompt_path")" --dangerously-skip-permissions)
1011
- if [[ -n "${PRIZMKIT_EFFORT:-}" ]]; then
1012
- claude_args+=(--effort "$PRIZMKIT_EFFORT")
1013
- fi
1014
- if [[ -n "$model" ]]; then
1015
- claude_args+=(--model "$model")
1016
- fi
1017
- "$CLI_CMD" "${claude_args[@]}" 2>&1 | tee -a "$backup_log" >> "$log_path"
1018
- ;;
1019
- codex)
1020
- local codex_args=(--ask-for-approval never --sandbox danger-full-access)
1021
- local codex_subagent_timeout
1022
- codex_subagent_timeout="$(_prizm_codex_subagent_timeout_seconds)"
1023
- if [[ "$codex_subagent_timeout" =~ ^[0-9]+$ && "$codex_subagent_timeout" -gt 0 ]]; then
1024
- codex_args+=(--config "agents.job_max_runtime_seconds=$codex_subagent_timeout")
1025
- fi
1026
- codex_args+=(exec --cd "$PROJECT_ROOT" --skip-git-repo-check)
1027
- if [[ "$USE_STREAM_JSON" == "true" ]]; then
1028
- codex_args+=(--json)
1029
- fi
1030
- if [[ -n "$model" ]]; then
1031
- codex_args+=(--model "$model")
1032
- fi
1033
- if [[ -n "${PRIZMKIT_EFFORT:-}" ]]; then
1034
- codex_args+=(--config "model_reasoning_effort=$PRIZMKIT_EFFORT")
1035
- fi
1036
- "$CLI_CMD" "${codex_args[@]}" - < "$prompt_path" 2>&1 | tee -a "$backup_log" >> "$log_path"
1037
- ;;
1038
- *)
1039
- local cb_args=(--print -y)
1040
- if [[ -n "${PRIZMKIT_EFFORT:-}" ]]; then
1041
- cb_args+=(--effort "$PRIZMKIT_EFFORT")
1042
- fi
1043
- if [[ -n "$model" ]]; then
1044
- cb_args+=(--model "$model")
1045
- fi
1046
- "$CLI_CMD" "${cb_args[@]}" < "$prompt_path" 2>&1 | tee -a "$backup_log" >> "$log_path"
1047
- ;;
1048
- esac
1049
- }
1050
-
1051
- # Recover session log from backup if the main log was truncated during execution.
1052
- # Claude Code subagents can unlink session.log at the filesystem level. The backup
1053
- # lives in $HOME/.prizmkit/ — outside the project tree — so it survives.
1054
- #
1055
- # Must be called AFTER the AI CLI process exits and BEFORE the session summary
1056
- # reads session.log. Uses PRIZM_BACKUP_LOG set by prizm_start_ai_session /
1057
- # prizm_run_ai_session.
1058
- prizm_recover_session_log() {
1059
- local session_log="${1:-}"
1060
- local backup_log="${PRIZM_BACKUP_LOG:-}"
1061
-
1062
- if [[ -z "$backup_log" || ! -f "$backup_log" ]]; then
1063
- return 0
1064
- fi
1065
-
1066
- local main_size=0
1067
- if [[ -f "$session_log" ]]; then
1068
- main_size=$(wc -c < "$session_log" 2>/dev/null | tr -d ' ') || true
1069
- fi
1070
-
1071
- local backup_size=0
1072
- backup_size=$(wc -c < "$backup_log" 2>/dev/null | tr -d ' ') || true
1073
-
1074
- if [[ "$main_size" -lt 1024 && "$backup_size" -gt "$main_size" ]]; then
1075
- # Ensure parent directory exists before copying (subagent may have
1076
- # deleted it along with session.log).
1077
- local log_dir
1078
- log_dir="$(dirname "$session_log")"
1079
- mkdir -p "$log_dir" 2>/dev/null || true
1080
- if cp "$backup_log" "$session_log" 2>/dev/null; then
1081
- log_info "Session log recovered from backup (${backup_size}B → $session_log)"
1082
- else
1083
- log_warn "Session log recovery failed: could not copy backup to $session_log"
1084
- fi
1085
- fi
1086
-
1087
- # Clean up backup either way (rm is safe even with set -e)
1088
- rm -f "$backup_log" 2>/dev/null || true
1089
- return 0
1090
- }
1091
-
1092
- # prizm_detect_subagents <session_log>
1093
- #
1094
- # Scan session log for subagent spawns, count them, and log the result.
1095
- # Sets _SUBAGENT_COUNT to the number of Agent tool calls detected.
1096
- # Requires: USE_STREAM_JSON (from detect_stream_json_support)
1097
- _SUBAGENT_COUNT=0
1098
- prizm_detect_subagents() {
1099
- local session_log="$1"
1100
- _SUBAGENT_COUNT=0
1101
- [[ -f "$session_log" ]] || return 0
1102
-
1103
- local count=0
1104
- if [[ "$USE_STREAM_JSON" == "true" && "${STREAM_JSON_FORMAT:-}" == "codex-json" ]]; then
1105
- count=$(grep -c '"tool"[[:space:]]*:[[:space:]]*"spawn_agent"' "$session_log" 2>/dev/null) || true
1106
- elif [[ "$USE_STREAM_JSON" == "true" ]]; then
1107
- count=$(grep -c '"name"[[:space:]]*:[[:space:]]*"Agent"' "$session_log" 2>/dev/null) || true
1108
- else
1109
- count=$(grep -cE '(Tool: Agent|"tool":\s*"Agent"|"tool":\s*"spawn_agent"|tool_use.*Agent|subagent_type|collab: SpawnAgent)' "$session_log" 2>/dev/null) || true
1110
- fi
1111
-
1112
- count=${count:-0}
1113
- _SUBAGENT_COUNT=$count
1114
- if [[ "$count" -gt 0 ]]; then
1115
- log_info "Subagent calls detected in session: $count"
1116
- else
1117
- log_info "Subagent calls detected in session: 0 (single-agent mode)"
1118
- fi
1119
- }
1120
-
1121
- # Common dependency check (jq + python3 + optional CLI in PATH)
1122
- # Args:
1123
- # $1 - cli command (optional)
1124
- prizm_check_common_dependencies() {
1125
- local cli_cmd="${1:-}"
1126
-
1127
- if ! command -v jq &>/dev/null; then
1128
- log_error "jq is required but not installed. Install with: brew install jq"
1129
- exit 1
1130
- fi
1131
-
1132
- if ! command -v python3 &>/dev/null; then
1133
- log_error "python3 is required but not installed."
1134
- exit 1
1135
- fi
1136
-
1137
- if [[ -n "$cli_cmd" ]] && ! command -v "$cli_cmd" &>/dev/null; then
1138
- log_warn "AI CLI '$cli_cmd' not found in PATH."
1139
- log_warn "Set AI_CLI environment variable to the correct command."
1140
- log_warn "Continuing anyway (will fail when spawning sessions)..."
1141
- fi
1142
- }
1143
-
1144
- # Ensure git is installed and a given directory is a git repository.
1145
- # If git is missing, attempt auto-install; on failure print instructions and exit.
1146
- # If not inside a git repo, run git init + initial commit automatically.
1147
- #
1148
- # Usage: prizm_ensure_git_repo [directory]
1149
- # directory — path to check/initialize (defaults to current working directory)
1150
- prizm_ensure_git_repo() {
1151
- local target_dir="${1:-.}"
1152
-
1153
- # --- helper: run a command with a timeout (macOS-compatible) ---
1154
- # Uses GNU timeout / gtimeout if available, otherwise a background+kill fallback.
1155
- _run_with_timeout() {
1156
- local secs="$1"; shift
1157
- if command -v timeout &>/dev/null; then
1158
- timeout "$secs" "$@"
1159
- elif command -v gtimeout &>/dev/null; then
1160
- gtimeout "$secs" "$@"
1161
- else
1162
- # background + kill fallback
1163
- "$@" &
1164
- local pid=$!
1165
- ( sleep "$secs" && kill "$pid" 2>/dev/null ) &
1166
- local watchdog=$!
1167
- if wait "$pid" 2>/dev/null; then
1168
- kill "$watchdog" 2>/dev/null; wait "$watchdog" 2>/dev/null
1169
- return 0
1170
- else
1171
- kill "$watchdog" 2>/dev/null; wait "$watchdog" 2>/dev/null
1172
- return 1
1173
- fi
1174
- fi
1175
- }
1176
-
1177
- if ! command -v git &>/dev/null; then
1178
- log_warn "git is not installed. Attempting automatic installation..."
1179
- local _install_ok=false
1180
- case "$(uname -s)" in
1181
- Darwin)
1182
- if command -v brew &>/dev/null; then
1183
- log_info "Installing git via Homebrew..."
1184
- if _run_with_timeout 120 brew install git &>/dev/null; then
1185
- _install_ok=true
1186
- fi
1187
- else
1188
- # xcode-select --install opens a GUI dialog that cannot be automated;
1189
- # skip auto-install and fall through to manual instructions.
1190
- log_info "Homebrew not found; cannot auto-install git on macOS."
1191
- fi
1192
- ;;
1193
- Linux)
1194
- # Verify passwordless sudo is available (daemon/CI safety)
1195
- if ! sudo -n true 2>/dev/null; then
1196
- log_info "sudo requires a password; cannot auto-install git."
1197
- elif command -v apt-get &>/dev/null; then
1198
- log_info "Installing git via apt-get..."
1199
- _run_with_timeout 120 sudo apt-get update -y &>/dev/null
1200
- if _run_with_timeout 120 sudo apt-get install -y git &>/dev/null; then
1201
- _install_ok=true
1202
- fi
1203
- elif command -v yum &>/dev/null; then
1204
- log_info "Installing git via yum..."
1205
- if _run_with_timeout 120 sudo yum install -y git &>/dev/null; then
1206
- _install_ok=true
1207
- fi
1208
- elif command -v dnf &>/dev/null; then
1209
- log_info "Installing git via dnf..."
1210
- if _run_with_timeout 120 sudo dnf install -y git &>/dev/null; then
1211
- _install_ok=true
1212
- fi
1213
- elif command -v pacman &>/dev/null; then
1214
- log_info "Installing git via pacman..."
1215
- if _run_with_timeout 120 sudo pacman -S --noconfirm git &>/dev/null; then
1216
- _install_ok=true
1217
- fi
1218
- fi
1219
- ;;
1220
- esac
1221
-
1222
- if $_install_ok && command -v git &>/dev/null; then
1223
- log_success "git installed successfully ($(git --version))."
1224
- else
1225
- log_error "Automatic git installation failed or timed out."
1226
- log_error "Please install git manually:"
1227
- log_error " macOS: brew install git or xcode-select --install"
1228
- log_error " Ubuntu: sudo apt-get install git"
1229
- log_error " CentOS: sudo yum install git"
1230
- log_error " Windows: https://git-scm.com/download/win"
1231
- exit 1
1232
- fi
1233
- fi
1234
-
1235
- # Validate target directory exists
1236
- if [[ ! -d "$target_dir" ]]; then
1237
- log_error "Target directory does not exist: $target_dir"
1238
- exit 1
1239
- fi
1240
-
1241
- if ! git -C "$target_dir" rev-parse --is-inside-work-tree &>/dev/null 2>&1; then
1242
- log_warn "Directory is not a git repository: $target_dir"
1243
- log_info "Initializing git repository..."
1244
- git -C "$target_dir" init -b main
1245
- log_info "Git repository initialized at: $target_dir"
1246
- # Create initial commit so branches and diffs work
1247
- if ! git -C "$target_dir" add -A; then
1248
- log_error "Failed to stage files in: $target_dir"
1249
- exit 1
1250
- fi
1251
- git -C "$target_dir" commit --no-verify -m "chore: initial commit (auto-created by dev-pipeline)" || {
1252
- # If nothing to commit (empty project), create an empty initial commit
1253
- git -C "$target_dir" commit --no-verify --allow-empty -m "chore: initial commit (auto-created by dev-pipeline)"
1254
- }
1255
- log_success "Initial commit created — workspace content committed."
1256
- fi
1257
- }