prizmkit 1.1.100 → 1.1.102

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 (317) 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 +355 -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 +153 -0
  26. package/bundled/dev-pipeline/prizmkit_runtime/runners.py +425 -0
  27. package/bundled/dev-pipeline/prizmkit_runtime/sessions.py +560 -0
  28. package/bundled/dev-pipeline/prizmkit_runtime/status.py +71 -0
  29. package/bundled/dev-pipeline/scripts/generate-bootstrap-prompt.py +51 -36
  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 +8 -2
  34. package/bundled/dev-pipeline/templates/agent-prompts/reviewer-review.md +1 -1
  35. package/bundled/dev-pipeline/templates/bootstrap-prompt.md +6 -2
  36. package/bundled/dev-pipeline/templates/bootstrap-tier1.md +14 -6
  37. package/bundled/dev-pipeline/templates/bootstrap-tier2.md +14 -4
  38. package/bundled/dev-pipeline/templates/bootstrap-tier3.md +14 -4
  39. package/bundled/dev-pipeline/templates/sections/context-budget-rules.md +2 -0
  40. package/bundled/dev-pipeline/templates/sections/log-size-awareness.md +9 -30
  41. package/bundled/dev-pipeline/templates/sections/phase-context-snapshot-agent-suffix.md +15 -7
  42. package/bundled/dev-pipeline/templates/sections/phase-implement-agent.md +42 -29
  43. package/bundled/dev-pipeline/templates/sections/phase-implement-full.md +41 -39
  44. package/bundled/dev-pipeline/templates/sections/phase-implement-lite.md +8 -17
  45. package/bundled/dev-pipeline/templates/sections/phase-prizmkit-test.md +2 -2
  46. package/bundled/dev-pipeline/templates/sections/phase-review-agent.md +1 -3
  47. package/bundled/dev-pipeline/templates/sections/phase-review-full.md +1 -3
  48. package/bundled/dev-pipeline/templates/sections/phase0-test-baseline.md +3 -8
  49. package/bundled/dev-pipeline/templates/sections/test-failure-recovery-agent.md +6 -2
  50. package/bundled/dev-pipeline/templates/sections/test-failure-recovery-lite.md +5 -1
  51. package/bundled/dev-pipeline/tests/test_auto_skip.py +436 -14
  52. package/bundled/dev-pipeline/tests/test_generate_bootstrap_prompt.py +115 -7
  53. package/bundled/dev-pipeline/tests/test_generate_bugfix_prompt.py +40 -0
  54. package/bundled/dev-pipeline/tests/test_python_runner_parity.py +1226 -0
  55. package/bundled/dev-pipeline/tests/test_unified_cli.py +1045 -0
  56. package/bundled/skills/_metadata.json +1 -1
  57. package/bundled/skills/bugfix-pipeline-launcher/SKILL.md +29 -34
  58. package/bundled/skills/bugfix-pipeline-launcher/references/configuration.md +6 -5
  59. package/bundled/skills/feature-pipeline-launcher/SKILL.md +29 -35
  60. package/bundled/skills/feature-pipeline-launcher/references/configuration.md +7 -6
  61. package/bundled/skills/feature-workflow/SKILL.md +3 -6
  62. package/bundled/skills/recovery-workflow/SKILL.md +23 -32
  63. package/bundled/skills/refactor-pipeline-launcher/SKILL.md +29 -35
  64. package/bundled/skills/refactor-pipeline-launcher/references/configuration.md +7 -6
  65. package/bundled/skills/refactor-workflow/SKILL.md +3 -6
  66. package/bundled/templates/hooks/commit-intent.json +2 -2
  67. package/bundled/templates/hooks/diff-prizm-docs.py +226 -0
  68. package/bundled/templates/hooks/prizm-pre-commit.py +45 -0
  69. package/bundled/templates/hooks/validate-prizm-docs.py +240 -0
  70. package/package.json +1 -1
  71. package/src/config.js +42 -19
  72. package/src/external-skills.js +14 -14
  73. package/src/index.js +3 -6
  74. package/src/manifest.js +11 -5
  75. package/src/metadata.js +7 -18
  76. package/src/platforms.js +25 -0
  77. package/src/prompts.js +0 -12
  78. package/src/runtimes.js +18 -11
  79. package/src/scaffold.js +144 -122
  80. package/src/upgrade.js +12 -3
  81. package/bundled/dev-pipeline/launch-bugfix-daemon.sh +0 -500
  82. package/bundled/dev-pipeline/launch-feature-daemon.sh +0 -657
  83. package/bundled/dev-pipeline/launch-refactor-daemon.sh +0 -502
  84. package/bundled/dev-pipeline/lib/branch.sh +0 -326
  85. package/bundled/dev-pipeline/lib/common.sh +0 -1476
  86. package/bundled/dev-pipeline/lib/heartbeat.sh +0 -469
  87. package/bundled/dev-pipeline/reset-bug.sh +0 -425
  88. package/bundled/dev-pipeline/reset-feature.sh +0 -436
  89. package/bundled/dev-pipeline/reset-refactor.sh +0 -423
  90. package/bundled/dev-pipeline/run-bugfix.sh +0 -1430
  91. package/bundled/dev-pipeline/run-feature.sh +0 -1718
  92. package/bundled/dev-pipeline/run-recovery.sh +0 -648
  93. package/bundled/dev-pipeline/run-refactor.sh +0 -1463
  94. package/bundled/dev-pipeline/tests/test-path-resolution.sh +0 -100
  95. package/bundled/dev-pipeline-windows/.env.example +0 -36
  96. package/bundled/dev-pipeline-windows/README.md +0 -30
  97. package/bundled/dev-pipeline-windows/SCHEMA_ANALYSIS.md +0 -533
  98. package/bundled/dev-pipeline-windows/assets/feature-list-example.json +0 -146
  99. package/bundled/dev-pipeline-windows/assets/prizm-dev-team-integration.md +0 -137
  100. package/bundled/dev-pipeline-windows/launch-bugfix-daemon.ps1 +0 -9
  101. package/bundled/dev-pipeline-windows/launch-feature-daemon.ps1 +0 -9
  102. package/bundled/dev-pipeline-windows/launch-refactor-daemon.ps1 +0 -9
  103. package/bundled/dev-pipeline-windows/lib/branch.ps1 +0 -235
  104. package/bundled/dev-pipeline-windows/lib/common.ps1 +0 -991
  105. package/bundled/dev-pipeline-windows/lib/daemon.ps1 +0 -140
  106. package/bundled/dev-pipeline-windows/lib/pipeline.ps1 +0 -1051
  107. package/bundled/dev-pipeline-windows/lib/reset.ps1 +0 -121
  108. package/bundled/dev-pipeline-windows/reset-bug.ps1 +0 -10
  109. package/bundled/dev-pipeline-windows/reset-feature.ps1 +0 -10
  110. package/bundled/dev-pipeline-windows/reset-refactor.ps1 +0 -10
  111. package/bundled/dev-pipeline-windows/run-bugfix.ps1 +0 -9
  112. package/bundled/dev-pipeline-windows/run-feature.ps1 +0 -9
  113. package/bundled/dev-pipeline-windows/run-recovery.ps1 +0 -179
  114. package/bundled/dev-pipeline-windows/run-refactor.ps1 +0 -9
  115. package/bundled/dev-pipeline-windows/scripts/check-session-status.py +0 -301
  116. package/bundled/dev-pipeline-windows/scripts/continuation.py +0 -374
  117. package/bundled/dev-pipeline-windows/scripts/detect-stuck.py +0 -530
  118. package/bundled/dev-pipeline-windows/scripts/generate-bootstrap-prompt.py +0 -2279
  119. package/bundled/dev-pipeline-windows/scripts/generate-bugfix-prompt.py +0 -763
  120. package/bundled/dev-pipeline-windows/scripts/generate-recovery-prompt.py +0 -805
  121. package/bundled/dev-pipeline-windows/scripts/generate-refactor-prompt.py +0 -841
  122. package/bundled/dev-pipeline-windows/scripts/init-bugfix-pipeline.py +0 -316
  123. package/bundled/dev-pipeline-windows/scripts/init-dev-team.py +0 -134
  124. package/bundled/dev-pipeline-windows/scripts/init-pipeline.py +0 -382
  125. package/bundled/dev-pipeline-windows/scripts/init-refactor-pipeline.py +0 -399
  126. package/bundled/dev-pipeline-windows/scripts/parse-stream-progress.py +0 -1362
  127. package/bundled/dev-pipeline-windows/scripts/patch-completion-notes.py +0 -191
  128. package/bundled/dev-pipeline-windows/scripts/prizmkit-test-gate.py +0 -446
  129. package/bundled/dev-pipeline-windows/scripts/update-bug-status.py +0 -1121
  130. package/bundled/dev-pipeline-windows/scripts/update-checkpoint.py +0 -173
  131. package/bundled/dev-pipeline-windows/scripts/update-feature-status.py +0 -1789
  132. package/bundled/dev-pipeline-windows/scripts/update-refactor-status.py +0 -1327
  133. package/bundled/dev-pipeline-windows/scripts/utils.py +0 -542
  134. package/bundled/dev-pipeline-windows/templates/agent-prompts/critic-plan-challenge.md +0 -7
  135. package/bundled/dev-pipeline-windows/templates/agent-prompts/dev-fix.md +0 -7
  136. package/bundled/dev-pipeline-windows/templates/agent-prompts/dev-implement.md +0 -65
  137. package/bundled/dev-pipeline-windows/templates/agent-prompts/dev-resume.md +0 -5
  138. package/bundled/dev-pipeline-windows/templates/agent-prompts/reviewer-review.md +0 -7
  139. package/bundled/dev-pipeline-windows/templates/bootstrap-prompt.md +0 -73
  140. package/bundled/dev-pipeline-windows/templates/bootstrap-tier1.md +0 -589
  141. package/bundled/dev-pipeline-windows/templates/bootstrap-tier2.md +0 -710
  142. package/bundled/dev-pipeline-windows/templates/bootstrap-tier3.md +0 -791
  143. package/bundled/dev-pipeline-windows/templates/bug-fix-list-schema.json +0 -263
  144. package/bundled/dev-pipeline-windows/templates/bugfix-bootstrap-prompt.md +0 -326
  145. package/bundled/dev-pipeline-windows/templates/feature-list-schema.json +0 -237
  146. package/bundled/dev-pipeline-windows/templates/refactor-bootstrap-prompt.md +0 -340
  147. package/bundled/dev-pipeline-windows/templates/refactor-list-schema.json +0 -270
  148. package/bundled/dev-pipeline-windows/templates/sections/ac-verification-checklist.md +0 -7
  149. package/bundled/dev-pipeline-windows/templates/sections/checkpoint-system.md +0 -91
  150. package/bundled/dev-pipeline-windows/templates/sections/context-budget-rules.md +0 -34
  151. package/bundled/dev-pipeline-windows/templates/sections/critical-paths-agent.md +0 -10
  152. package/bundled/dev-pipeline-windows/templates/sections/critical-paths-full.md +0 -12
  153. package/bundled/dev-pipeline-windows/templates/sections/critical-paths-lite.md +0 -7
  154. package/bundled/dev-pipeline-windows/templates/sections/directory-convention-agent.md +0 -8
  155. package/bundled/dev-pipeline-windows/templates/sections/directory-convention-full.md +0 -9
  156. package/bundled/dev-pipeline-windows/templates/sections/directory-convention-lite.md +0 -6
  157. package/bundled/dev-pipeline-windows/templates/sections/failure-capture.md +0 -21
  158. package/bundled/dev-pipeline-windows/templates/sections/feature-context.md +0 -21
  159. package/bundled/dev-pipeline-windows/templates/sections/log-size-awareness.md +0 -41
  160. package/bundled/dev-pipeline-windows/templates/sections/phase-browser-verification-auto.md +0 -283
  161. package/bundled/dev-pipeline-windows/templates/sections/phase-browser-verification-opencli.md +0 -112
  162. package/bundled/dev-pipeline-windows/templates/sections/phase-browser-verification.md +0 -168
  163. package/bundled/dev-pipeline-windows/templates/sections/phase-commit-full.md +0 -82
  164. package/bundled/dev-pipeline-windows/templates/sections/phase-commit.md +0 -75
  165. package/bundled/dev-pipeline-windows/templates/sections/phase-context-snapshot-agent-suffix.md +0 -23
  166. package/bundled/dev-pipeline-windows/templates/sections/phase-context-snapshot-base.md +0 -14
  167. package/bundled/dev-pipeline-windows/templates/sections/phase-context-snapshot-lite-suffix.md +0 -19
  168. package/bundled/dev-pipeline-windows/templates/sections/phase-critic-plan-full.md +0 -63
  169. package/bundled/dev-pipeline-windows/templates/sections/phase-critic-plan.md +0 -42
  170. package/bundled/dev-pipeline-windows/templates/sections/phase-implement-agent.md +0 -44
  171. package/bundled/dev-pipeline-windows/templates/sections/phase-implement-full.md +0 -59
  172. package/bundled/dev-pipeline-windows/templates/sections/phase-implement-lite.md +0 -39
  173. package/bundled/dev-pipeline-windows/templates/sections/phase-plan-agent.md +0 -27
  174. package/bundled/dev-pipeline-windows/templates/sections/phase-plan-lite.md +0 -27
  175. package/bundled/dev-pipeline-windows/templates/sections/phase-prizmkit-test.md +0 -39
  176. package/bundled/dev-pipeline-windows/templates/sections/phase-review-agent.md +0 -35
  177. package/bundled/dev-pipeline-windows/templates/sections/phase-review-full.md +0 -35
  178. package/bundled/dev-pipeline-windows/templates/sections/phase-specify-plan-full.md +0 -73
  179. package/bundled/dev-pipeline-windows/templates/sections/phase0-init.md +0 -13
  180. package/bundled/dev-pipeline-windows/templates/sections/phase0-test-baseline.md +0 -21
  181. package/bundled/dev-pipeline-windows/templates/sections/session-context.md +0 -5
  182. package/bundled/dev-pipeline-windows/templates/sections/subagent-timeout-recovery.md +0 -6
  183. package/bundled/dev-pipeline-windows/templates/sections/task-contract.md +0 -34
  184. package/bundled/dev-pipeline-windows/templates/sections/test-failure-recovery-agent.md +0 -48
  185. package/bundled/dev-pipeline-windows/templates/sections/test-failure-recovery-lite.md +0 -48
  186. package/bundled/dev-pipeline-windows/templates/session-status-schema.json +0 -83
  187. package/bundled/skills-windows/app-planner/SKILL.md +0 -296
  188. package/bundled/skills-windows/app-planner/assets/app-design-guide.md +0 -101
  189. package/bundled/skills-windows/app-planner/references/architecture-decisions.md +0 -52
  190. package/bundled/skills-windows/app-planner/references/brainstorm-guide.md +0 -101
  191. package/bundled/skills-windows/app-planner/references/frontend-design-guide.md +0 -71
  192. package/bundled/skills-windows/app-planner/references/infrastructure-convention-discovery.md +0 -108
  193. package/bundled/skills-windows/app-planner/references/project-brief-guide.md +0 -82
  194. package/bundled/skills-windows/app-planner/references/project-conventions-discovery.md +0 -59
  195. package/bundled/skills-windows/app-planner/references/project-state-detection.md +0 -90
  196. package/bundled/skills-windows/app-planner/references/red-team-checklist.md +0 -40
  197. package/bundled/skills-windows/app-planner/references/rules/backend/derivation-rules.md +0 -619
  198. package/bundled/skills-windows/app-planner/references/rules/backend/fixed-rules.md +0 -285
  199. package/bundled/skills-windows/app-planner/references/rules/backend/question-bank.md +0 -249
  200. package/bundled/skills-windows/app-planner/references/rules/backend/question-manifest.json +0 -46
  201. package/bundled/skills-windows/app-planner/references/rules/backend/template.md +0 -173
  202. package/bundled/skills-windows/app-planner/references/rules/database/derivation-rules.md +0 -382
  203. package/bundled/skills-windows/app-planner/references/rules/database/fixed-rules.md +0 -211
  204. package/bundled/skills-windows/app-planner/references/rules/database/question-bank.md +0 -184
  205. package/bundled/skills-windows/app-planner/references/rules/database/question-manifest.json +0 -39
  206. package/bundled/skills-windows/app-planner/references/rules/database/template.md +0 -158
  207. package/bundled/skills-windows/app-planner/references/rules/frontend/derivation-rules.md +0 -820
  208. package/bundled/skills-windows/app-planner/references/rules/frontend/fixed-rules.md +0 -188
  209. package/bundled/skills-windows/app-planner/references/rules/frontend/question-bank.md +0 -319
  210. package/bundled/skills-windows/app-planner/references/rules/frontend/question-manifest.json +0 -51
  211. package/bundled/skills-windows/app-planner/references/rules/frontend/template.md +0 -339
  212. package/bundled/skills-windows/app-planner/references/rules/mobile/derivation-rules.md +0 -649
  213. package/bundled/skills-windows/app-planner/references/rules/mobile/fixed-rules.md +0 -290
  214. package/bundled/skills-windows/app-planner/references/rules/mobile/question-bank.md +0 -232
  215. package/bundled/skills-windows/app-planner/references/rules/mobile/question-manifest.json +0 -47
  216. package/bundled/skills-windows/app-planner/references/rules/mobile/template.md +0 -175
  217. package/bundled/skills-windows/app-planner/references/rules-configuration.md +0 -46
  218. package/bundled/skills-windows/bug-fix-workflow/SKILL.md +0 -379
  219. package/bundled/skills-windows/bug-fix-workflow/references/bug-diagnosis.md +0 -41
  220. package/bundled/skills-windows/bug-planner/SKILL.md +0 -402
  221. package/bundled/skills-windows/bug-planner/assets/bug-confirmation-template.md +0 -43
  222. package/bundled/skills-windows/bug-planner/references/critic-and-verification.md +0 -44
  223. package/bundled/skills-windows/bug-planner/references/error-recovery.md +0 -73
  224. package/bundled/skills-windows/bug-planner/references/input-formats.md +0 -53
  225. package/bundled/skills-windows/bug-planner/references/schema-validation.md +0 -25
  226. package/bundled/skills-windows/bug-planner/references/severity-rules.md +0 -16
  227. package/bundled/skills-windows/bug-planner/scripts/validate-bug-list.py +0 -322
  228. package/bundled/skills-windows/bugfix-pipeline-launcher/SKILL.md +0 -304
  229. package/bundled/skills-windows/bugfix-pipeline-launcher/references/configuration.md +0 -84
  230. package/bundled/skills-windows/feature-pipeline-launcher/SKILL.md +0 -381
  231. package/bundled/skills-windows/feature-pipeline-launcher/references/configuration.md +0 -67
  232. package/bundled/skills-windows/feature-pipeline-launcher/scripts/preflight-check.py +0 -462
  233. package/bundled/skills-windows/feature-planner/SKILL.md +0 -397
  234. package/bundled/skills-windows/feature-planner/assets/evaluation-guide.md +0 -64
  235. package/bundled/skills-windows/feature-planner/assets/planning-guide.md +0 -214
  236. package/bundled/skills-windows/feature-planner/references/browser-interaction.md +0 -59
  237. package/bundled/skills-windows/feature-planner/references/completeness-review.md +0 -57
  238. package/bundled/skills-windows/feature-planner/references/decomposition-patterns.md +0 -75
  239. package/bundled/skills-windows/feature-planner/references/error-recovery.md +0 -90
  240. package/bundled/skills-windows/feature-planner/references/incremental-feature-planning.md +0 -112
  241. package/bundled/skills-windows/feature-planner/references/new-project-planning.md +0 -85
  242. package/bundled/skills-windows/feature-planner/scripts/validate-and-generate.py +0 -1020
  243. package/bundled/skills-windows/feature-workflow/SKILL.md +0 -374
  244. package/bundled/skills-windows/feature-workflow/references/brainstorm-guide.md +0 -137
  245. package/bundled/skills-windows/prizm-kit/SKILL.md +0 -93
  246. package/bundled/skills-windows/prizmkit-code-review/SKILL.md +0 -161
  247. package/bundled/skills-windows/prizmkit-code-review/references/dev-agent-prompt.md +0 -30
  248. package/bundled/skills-windows/prizmkit-code-review/references/review-report-template.md +0 -31
  249. package/bundled/skills-windows/prizmkit-code-review/references/reviewer-agent-prompt.md +0 -66
  250. package/bundled/skills-windows/prizmkit-code-review/scripts/check_loop.py +0 -186
  251. package/bundled/skills-windows/prizmkit-committer/SKILL.md +0 -89
  252. package/bundled/skills-windows/prizmkit-deploy/SKILL.md +0 -444
  253. package/bundled/skills-windows/prizmkit-deploy/references/ci-cd-workflows.md +0 -115
  254. package/bundled/skills-windows/prizmkit-deploy/references/cloud-platform-deploy.md +0 -93
  255. package/bundled/skills-windows/prizmkit-deploy/references/data-safety-examples.md +0 -120
  256. package/bundled/skills-windows/prizmkit-deploy/references/database-setup.md +0 -46
  257. package/bundled/skills-windows/prizmkit-deploy/references/deploy-config-schema.md +0 -148
  258. package/bundled/skills-windows/prizmkit-deploy/references/deploy-history-schema.md +0 -62
  259. package/bundled/skills-windows/prizmkit-deploy/references/deployment-modes.md +0 -50
  260. package/bundled/skills-windows/prizmkit-deploy/references/direct-upload.md +0 -26
  261. package/bundled/skills-windows/prizmkit-deploy/references/dns-setup.md +0 -42
  262. package/bundled/skills-windows/prizmkit-deploy/references/docker-deploy.md +0 -31
  263. package/bundled/skills-windows/prizmkit-deploy/references/firewall-setup.md +0 -37
  264. package/bundled/skills-windows/prizmkit-deploy/references/live-validation-notes.md +0 -21
  265. package/bundled/skills-windows/prizmkit-deploy/references/nginx-blue-green.md +0 -59
  266. package/bundled/skills-windows/prizmkit-deploy/references/ssh-bootstrap-flow.md +0 -49
  267. package/bundled/skills-windows/prizmkit-deploy/references/ssh-execution-flow.md +0 -41
  268. package/bundled/skills-windows/prizmkit-deploy/references/ssh-takeover.md +0 -20
  269. package/bundled/skills-windows/prizmkit-deploy/references/ssl-setup.md +0 -56
  270. package/bundled/skills-windows/prizmkit-implement/SKILL.md +0 -71
  271. package/bundled/skills-windows/prizmkit-init/SKILL.md +0 -356
  272. package/bundled/skills-windows/prizmkit-init/assets/project-brief-template.md +0 -82
  273. package/bundled/skills-windows/prizmkit-init/references/config-schema.md +0 -70
  274. package/bundled/skills-windows/prizmkit-init/references/rules/layer-detection.md +0 -41
  275. package/bundled/skills-windows/prizmkit-init/references/tech-stack-catalog.md +0 -13
  276. package/bundled/skills-windows/prizmkit-init/references/update-supplement.md +0 -9
  277. package/bundled/skills-windows/prizmkit-plan/SKILL.md +0 -102
  278. package/bundled/skills-windows/prizmkit-plan/assets/plan-template.md +0 -115
  279. package/bundled/skills-windows/prizmkit-plan/assets/spec-template.md +0 -73
  280. package/bundled/skills-windows/prizmkit-plan/references/clarify-guide.md +0 -67
  281. package/bundled/skills-windows/prizmkit-plan/references/examples.md +0 -85
  282. package/bundled/skills-windows/prizmkit-plan/references/verification-checklist.md +0 -60
  283. package/bundled/skills-windows/prizmkit-prizm-docs/SKILL.md +0 -129
  284. package/bundled/skills-windows/prizmkit-prizm-docs/assets/prizm-docs-format.md +0 -613
  285. package/bundled/skills-windows/prizmkit-prizm-docs/references/op-init.md +0 -45
  286. package/bundled/skills-windows/prizmkit-prizm-docs/references/op-rebuild.md +0 -15
  287. package/bundled/skills-windows/prizmkit-prizm-docs/references/op-status.md +0 -14
  288. package/bundled/skills-windows/prizmkit-prizm-docs/references/op-update.md +0 -19
  289. package/bundled/skills-windows/prizmkit-prizm-docs/references/op-validate.md +0 -17
  290. package/bundled/skills-windows/prizmkit-retrospective/SKILL.md +0 -87
  291. package/bundled/skills-windows/prizmkit-retrospective/references/knowledge-injection-steps.md +0 -50
  292. package/bundled/skills-windows/prizmkit-retrospective/references/structural-sync-steps.md +0 -43
  293. package/bundled/skills-windows/prizmkit-test/SKILL.md +0 -227
  294. package/bundled/skills-windows/prizmkit-test/references/boundary-coverage-protocol.md +0 -220
  295. package/bundled/skills-windows/prizmkit-test/references/examples.md +0 -143
  296. package/bundled/skills-windows/prizmkit-test/references/service-boundary-test-catalog.md +0 -225
  297. package/bundled/skills-windows/prizmkit-test/references/test-generation-steps.md +0 -109
  298. package/bundled/skills-windows/prizmkit-test/references/test-report-template.md +0 -111
  299. package/bundled/skills-windows/prizmkit-test/scripts/validate_boundary_report.py +0 -347
  300. package/bundled/skills-windows/recovery-workflow/SKILL.md +0 -355
  301. package/bundled/skills-windows/recovery-workflow/evals/evals.json +0 -46
  302. package/bundled/skills-windows/recovery-workflow/references/detection.md +0 -58
  303. package/bundled/skills-windows/recovery-workflow/scripts/detect-recovery-state.py +0 -544
  304. package/bundled/skills-windows/refactor-pipeline-launcher/SKILL.md +0 -346
  305. package/bundled/skills-windows/refactor-pipeline-launcher/references/configuration.md +0 -72
  306. package/bundled/skills-windows/refactor-planner/SKILL.md +0 -398
  307. package/bundled/skills-windows/refactor-planner/assets/planning-guide.md +0 -292
  308. package/bundled/skills-windows/refactor-planner/references/behavior-preservation.md +0 -301
  309. package/bundled/skills-windows/refactor-planner/references/fast-path.md +0 -59
  310. package/bundled/skills-windows/refactor-planner/references/planning-phases.md +0 -135
  311. package/bundled/skills-windows/refactor-planner/references/refactor-scoping-guide.md +0 -221
  312. package/bundled/skills-windows/refactor-planner/scripts/validate-and-generate-refactor.py +0 -858
  313. package/bundled/skills-windows/refactor-workflow/SKILL.md +0 -343
  314. package/bundled/skills-windows/refactor-workflow/references/brainstorm-guide.md +0 -116
  315. package/bundled/templates/hooks/diff-prizm-docs.sh +0 -158
  316. package/bundled/templates/hooks/prizm-pre-commit.sh +0 -108
  317. package/bundled/templates/hooks/validate-prizm-docs.sh +0 -139
@@ -0,0 +1,734 @@
1
+ """Branch and worktree helper primitives."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import os
6
+ import re
7
+ import shutil
8
+ import subprocess
9
+ from collections.abc import Sequence
10
+ from dataclasses import dataclass
11
+ from pathlib import Path
12
+
13
+
14
+ HIDDEN_TOOL_WORKTREE_EXCLUDES = (
15
+ ":(top,exclude).prizmkit-worktree",
16
+ ":(top,exclude).skills-lock.json",
17
+ ":(top,exclude).AGENTS.md",
18
+ ":(top,exclude,glob).*/worktree",
19
+ ":(top,exclude,glob).*/worktree/**",
20
+ ":(top,exclude,glob).*/worktrees",
21
+ ":(top,exclude,glob).*/worktrees/**",
22
+ ":(top,exclude).claude",
23
+ ":(top,exclude,glob).claude/**",
24
+ ":(top,exclude).codebuddy",
25
+ ":(top,exclude,glob).codebuddy/**",
26
+ ":(top,exclude).codex",
27
+ ":(top,exclude,glob).codex/**",
28
+ ":(top,exclude).agents",
29
+ ":(top,exclude,glob).agents/**",
30
+ ":(top,exclude).prizmkit/prizm-docs",
31
+ ":(top,exclude,glob).prizmkit/prizm-docs/**",
32
+ ":(top,exclude).prizmkit/config.json",
33
+ ":(top,exclude).prizmkit/manifest.json",
34
+ ":(top,exclude).prizmkit/dev-pipeline/scripts",
35
+ ":(top,exclude,glob).prizmkit/dev-pipeline/scripts/**",
36
+ )
37
+
38
+ WORKTREE_PLATFORM_SUPPORT_DIRS = (".claude", ".codebuddy", ".codex", ".agents")
39
+ WORKTREE_ROOT_SUPPORT_FILES = ("skills-lock.json", "AGENTS.md")
40
+ WORKTREE_PRIZMKIT_SUPPORT_ENTRIES = ("prizm-docs", "config.json", "manifest.json")
41
+ WORKTREE_SUPPORT_IGNORE_NAMES = {"__pycache__", ".DS_Store", "settings.local.json"}
42
+
43
+
44
+ @dataclass(frozen=True)
45
+ class BranchContext:
46
+ """Branch state required by git/worktree helpers."""
47
+
48
+ base_branch: str
49
+ working_branch: str
50
+ project_root: Path
51
+ remote_name: str = "origin"
52
+
53
+
54
+ @dataclass(frozen=True)
55
+ class WorktreePolicy:
56
+ """Worktree creation and cleanup policy for later porting."""
57
+
58
+ use_worktree: bool
59
+ cleanup_on_success: bool
60
+ preserve_on_failure: bool
61
+ worktree_root: Path | None = None
62
+
63
+
64
+
65
+
66
+ @dataclass(frozen=True)
67
+ class WorktreeRuntimeContext:
68
+ """Resolved linked-worktree paths and safety metadata."""
69
+
70
+ context: BranchContext
71
+ policy: WorktreePolicy
72
+ worktree_root: Path
73
+ worktree_path: Path
74
+ sentinel_path: Path
75
+
76
+ def is_cleanup_path_safe(self) -> bool:
77
+ root = self.worktree_root.resolve()
78
+ target = self.worktree_path.resolve()
79
+ try:
80
+ return os.path.commonpath([str(root), str(target)]) == str(root) and target != root
81
+ except ValueError:
82
+ return False
83
+
84
+
85
+
86
+
87
+ @dataclass(frozen=True)
88
+ class WorktreeOperationResult:
89
+ """Executable linked-worktree operation result."""
90
+
91
+ ok: bool
92
+ reason: str = ""
93
+ runtime: WorktreeRuntimeContext | None = None
94
+ results: tuple[GitCommandResult, ...] = ()
95
+
96
+
97
+ @dataclass(frozen=True)
98
+ class WorktreeRemovalResult:
99
+ """Guarded worktree removal result."""
100
+
101
+ ok: bool
102
+ reason: str = ""
103
+ results: tuple[GitCommandResult, ...] = ()
104
+
105
+
106
+ @dataclass(frozen=True)
107
+ class WorktreeSupportAssetsResult:
108
+ """Support assets materialized into an AI-visible linked worktree."""
109
+
110
+ ok: bool
111
+ copied: tuple[Path, ...] = ()
112
+ existing: tuple[Path, ...] = ()
113
+ missing: tuple[str, ...] = ()
114
+ reason: str = ""
115
+
116
+
117
+ def _safe_worktree_name(branch_name: str) -> str:
118
+ safe = re.sub(r"[^A-Za-z0-9._-]+", "-", branch_name.strip())
119
+ safe = safe.strip(".-")
120
+ return safe or "worktree"
121
+
122
+
123
+ def worktree_runtime_context(context: BranchContext, policy: WorktreePolicy) -> WorktreeRuntimeContext:
124
+ """Resolve deterministic per-branch worktree paths under a runner-owned root."""
125
+ root = (policy.worktree_root or context.project_root / ".prizmkit" / "state" / "worktrees").resolve()
126
+ worktree_path = root / _safe_worktree_name(context.working_branch)
127
+ return WorktreeRuntimeContext(
128
+ context=context,
129
+ policy=policy,
130
+ worktree_root=root,
131
+ worktree_path=worktree_path,
132
+ sentinel_path=worktree_path / ".prizmkit-worktree",
133
+ )
134
+
135
+
136
+ def linked_worktree_setup_plan(runtime: WorktreeRuntimeContext) -> GitCommandPlan:
137
+ """Plan linked-worktree branch creation without main-worktree checkout."""
138
+ context = runtime.context
139
+ return GitCommandPlan(
140
+ name="linked_worktree_setup",
141
+ commands=(
142
+ _git("rev-parse", "--verify", context.working_branch, allow_failure=True, description="check existing branch"),
143
+ _git("branch", context.working_branch, context.base_branch, allow_failure=True, description="create branch without checkout"),
144
+ _git("worktree", "list", "--porcelain", allow_failure=True, description="inspect registered worktrees"),
145
+ _git("worktree", "add", "--checkout", str(runtime.worktree_path), context.working_branch, allow_failure=True, description="create or reuse linked worktree"),
146
+ ),
147
+ notes=(
148
+ "Creates the task branch without checking it out in the main working tree.",
149
+ "A deterministic path lets context-overflow continuations reuse the same worktree.",
150
+ ),
151
+ require_one_success=((0, 1),),
152
+ )
153
+
154
+
155
+ def worktree_merge_plan(runtime: WorktreeRuntimeContext, *, auto_push: bool = False) -> GitCommandPlan:
156
+ """Plan rebase-in-worktree then fast-forward merge in the main repository."""
157
+ context = runtime.context
158
+ commands = [
159
+ _git("rebase", context.base_branch, description="rebase worktree branch onto base"),
160
+ _git("merge", "--ff-only", context.working_branch, description="fast-forward base from worktree branch"),
161
+ ]
162
+ if auto_push:
163
+ commands.append(_git("push", allow_failure=True, description="optional auto-push after merge"))
164
+ return GitCommandPlan(
165
+ name="worktree_merge",
166
+ commands=tuple(commands),
167
+ notes=("Run rebase in the linked worktree and merge from the main checkout after checkout-free setup.",),
168
+ )
169
+
170
+
171
+ def worktree_remove_plan(runtime: WorktreeRuntimeContext, *, delete_branch: bool = True) -> GitCommandPlan:
172
+ """Plan guarded linked-worktree removal and optional branch deletion."""
173
+ commands = [
174
+ _git("worktree", "remove", "--force", str(runtime.worktree_path), description="remove linked worktree"),
175
+ ]
176
+ if delete_branch:
177
+ commands.append(_git("branch", "-d", runtime.context.working_branch, allow_failure=True, description="delete merged task branch"))
178
+ return GitCommandPlan(
179
+ name="worktree_remove",
180
+ commands=tuple(commands),
181
+ notes=("Caller must verify cleanup safety and registration before executing.",),
182
+ )
183
+
184
+
185
+ def worktree_registered(runtime: WorktreeRuntimeContext) -> bool:
186
+ """Return whether git worktree metadata contains the resolved path."""
187
+ result = run_git_command(runtime.context.project_root, ("worktree", "list", "--porcelain"))
188
+ if result.return_code != 0:
189
+ return False
190
+ target = str(runtime.worktree_path.resolve())
191
+ candidates: list[str] = []
192
+ for line in result.stdout.splitlines():
193
+ stripped = line.strip()
194
+ if stripped.startswith("worktree "):
195
+ candidates.append(stripped.removeprefix("worktree ").strip())
196
+ elif stripped:
197
+ candidates.append(stripped.split()[0])
198
+ return any(Path(candidate).resolve() == Path(target) for candidate in candidates if candidate)
199
+
200
+
201
+ def mark_worktree_sentinel(runtime: WorktreeRuntimeContext) -> None:
202
+ """Write a small runner-owned sentinel inside a linked worktree."""
203
+ runtime.sentinel_path.parent.mkdir(parents=True, exist_ok=True)
204
+ runtime.sentinel_path.write_text(runtime.context.working_branch + "\n", encoding="utf-8")
205
+
206
+
207
+
208
+ def materialize_worktree_support_assets(runtime: WorktreeRuntimeContext) -> WorktreeSupportAssetsResult:
209
+ """Copy ignored/untracked PrizmKit support assets into the linked worktree.
210
+
211
+ Git worktree checkout materializes only tracked files. Platform agent
212
+ definitions, Prizm docs/config, and installed runtime utility scripts are
213
+ commonly ignored support assets, yet generated prompts reference them from
214
+ the AI-visible project root. Copy only missing support files so continuation
215
+ worktrees keep any task-local artifact changes.
216
+ """
217
+ source_root = runtime.context.project_root
218
+ target_root = runtime.worktree_path
219
+ copied: list[Path] = []
220
+ existing: list[Path] = []
221
+ missing: list[str] = []
222
+
223
+ try:
224
+ for relative in WORKTREE_PLATFORM_SUPPORT_DIRS:
225
+ _materialize_optional_support_entry(source_root, target_root, relative, copied, existing, missing)
226
+ for relative in WORKTREE_ROOT_SUPPORT_FILES:
227
+ _materialize_optional_support_entry(source_root, target_root, relative, copied, existing, missing)
228
+ for relative in WORKTREE_PRIZMKIT_SUPPORT_ENTRIES:
229
+ _materialize_optional_support_entry(
230
+ source_root / ".prizmkit",
231
+ target_root / ".prizmkit",
232
+ relative,
233
+ copied,
234
+ existing,
235
+ missing,
236
+ )
237
+
238
+ runtime_scripts = _runtime_support_scripts_source(source_root)
239
+ if runtime_scripts is None:
240
+ missing.append(".prizmkit/dev-pipeline/scripts")
241
+ else:
242
+ target = target_root / ".prizmkit" / "dev-pipeline" / "scripts"
243
+ changed = _copy_support_entry(runtime_scripts, target)
244
+ (copied if changed else existing).append(target)
245
+ except OSError as exc:
246
+ return WorktreeSupportAssetsResult(False, tuple(copied), tuple(existing), tuple(missing), str(exc))
247
+
248
+ return WorktreeSupportAssetsResult(True, tuple(copied), tuple(existing), tuple(missing))
249
+
250
+
251
+ def _materialize_optional_support_entry(
252
+ source_root: Path,
253
+ target_root: Path,
254
+ relative: str,
255
+ copied: list[Path],
256
+ existing: list[Path],
257
+ missing: list[str],
258
+ ) -> None:
259
+ source = source_root / relative
260
+ target = target_root / relative
261
+ if not source.exists() and not source.is_symlink():
262
+ missing.append(relative)
263
+ return
264
+ changed = _copy_support_entry(source, target)
265
+ (copied if changed else existing).append(target)
266
+
267
+
268
+ def _runtime_support_scripts_source(project_root: Path) -> Path | None:
269
+ candidates = (
270
+ project_root / ".prizmkit" / "dev-pipeline" / "scripts",
271
+ project_root / "dev-pipeline" / "scripts",
272
+ )
273
+ for candidate in candidates:
274
+ if candidate.is_dir():
275
+ return candidate
276
+ return None
277
+
278
+
279
+ def _copy_support_entry(source: Path, target: Path) -> bool:
280
+ if source.is_symlink():
281
+ if target.exists() or target.is_symlink():
282
+ return False
283
+ target.parent.mkdir(parents=True, exist_ok=True)
284
+ os.symlink(os.readlink(source), target)
285
+ return True
286
+ if source.is_file():
287
+ if target.exists():
288
+ return False
289
+ target.parent.mkdir(parents=True, exist_ok=True)
290
+ shutil.copy2(source, target)
291
+ return True
292
+
293
+ changed = False
294
+ if not target.exists():
295
+ target.mkdir(parents=True, exist_ok=True)
296
+ changed = True
297
+ for current_root, dir_names, file_names in os.walk(source):
298
+ dir_names[:] = [name for name in dir_names if not _skip_support_asset_name(name)]
299
+ relative_root = Path(current_root).relative_to(source)
300
+ target_root = target / relative_root
301
+ if not target_root.exists():
302
+ target_root.mkdir(parents=True, exist_ok=True)
303
+ changed = True
304
+ for file_name in file_names:
305
+ if _skip_support_asset_name(file_name):
306
+ continue
307
+ source_file = Path(current_root) / file_name
308
+ target_file = target_root / file_name
309
+ if target_file.exists() or target_file.is_symlink():
310
+ continue
311
+ if source_file.is_symlink():
312
+ os.symlink(os.readlink(source_file), target_file)
313
+ else:
314
+ shutil.copy2(source_file, target_file)
315
+ changed = True
316
+ return changed
317
+
318
+
319
+ def _skip_support_asset_name(name: str) -> bool:
320
+ return name in WORKTREE_SUPPORT_IGNORE_NAMES or name.endswith(".pyc")
321
+
322
+
323
+ def ensure_linked_worktree(runtime: WorktreeRuntimeContext) -> WorktreeOperationResult:
324
+ """Create or reuse a linked worktree for the runtime context."""
325
+ if not runtime.policy.use_worktree:
326
+ return WorktreeOperationResult(False, "worktree_disabled", runtime)
327
+ if not runtime.is_cleanup_path_safe():
328
+ return WorktreeOperationResult(False, "unsafe_worktree_path", runtime)
329
+
330
+ runtime.worktree_root.mkdir(parents=True, exist_ok=True)
331
+ results: list[GitCommandResult] = []
332
+
333
+ branch_check = run_git_command(runtime.context.project_root, ("rev-parse", "--verify", runtime.context.working_branch))
334
+ results.append(branch_check)
335
+ if branch_check.return_code != 0:
336
+ branch_create = run_git_command(
337
+ runtime.context.project_root,
338
+ ("branch", runtime.context.working_branch, runtime.context.base_branch),
339
+ )
340
+ results.append(branch_create)
341
+ if branch_create.return_code != 0:
342
+ return WorktreeOperationResult(False, "branch_create_failed", runtime, tuple(results))
343
+
344
+ if worktree_registered(runtime):
345
+ mark_worktree_sentinel(runtime)
346
+ return WorktreeOperationResult(True, runtime=runtime, results=tuple(results))
347
+
348
+ if runtime.worktree_path.exists() and any(runtime.worktree_path.iterdir()):
349
+ return WorktreeOperationResult(False, "worktree_path_exists_unregistered", runtime, tuple(results))
350
+
351
+ add = run_git_command(
352
+ runtime.context.project_root,
353
+ ("worktree", "add", "--checkout", str(runtime.worktree_path), runtime.context.working_branch),
354
+ )
355
+ results.append(add)
356
+ if add.return_code != 0:
357
+ if worktree_registered(runtime):
358
+ mark_worktree_sentinel(runtime)
359
+ return WorktreeOperationResult(True, runtime=runtime, results=tuple(results))
360
+ return WorktreeOperationResult(False, "worktree_add_failed", runtime, tuple(results))
361
+
362
+ mark_worktree_sentinel(runtime)
363
+ return WorktreeOperationResult(True, runtime=runtime, results=tuple(results))
364
+
365
+
366
+ def merge_linked_worktree(runtime: WorktreeRuntimeContext, *, auto_push: bool = False) -> WorktreeOperationResult:
367
+ """Rebase the linked worktree branch and fast-forward merge it into base."""
368
+ results: list[GitCommandResult] = []
369
+ rebase = run_git_command(runtime.worktree_path, ("rebase", runtime.context.base_branch))
370
+ results.append(rebase)
371
+ if rebase.return_code != 0:
372
+ results.append(run_git_command(runtime.worktree_path, ("rebase", "--abort")))
373
+ return WorktreeOperationResult(False, "merge_conflict", runtime, tuple(results))
374
+
375
+ checkout = run_git_command(runtime.context.project_root, ("checkout", runtime.context.base_branch))
376
+ results.append(checkout)
377
+ if checkout.return_code != 0:
378
+ return WorktreeOperationResult(False, "base_checkout_failed", runtime, tuple(results))
379
+
380
+ merge = run_git_command(runtime.context.project_root, ("merge", "--ff-only", runtime.context.working_branch))
381
+ results.append(merge)
382
+ if merge.return_code != 0:
383
+ results.append(run_git_command(runtime.context.project_root, ("merge", "--abort")))
384
+ return WorktreeOperationResult(False, "merge_conflict", runtime, tuple(results))
385
+
386
+ if auto_push:
387
+ results.append(run_git_command(runtime.context.project_root, ("push",)))
388
+
389
+ return WorktreeOperationResult(True, runtime=runtime, results=tuple(results))
390
+
391
+ def guarded_worktree_remove(runtime: WorktreeRuntimeContext, *, delete_branch: bool = True) -> WorktreeRemovalResult:
392
+ """Remove a worktree only when path, sentinel, and git metadata are safe."""
393
+ if not runtime.is_cleanup_path_safe():
394
+ return WorktreeRemovalResult(False, "unsafe_worktree_path")
395
+ if not runtime.sentinel_path.is_file():
396
+ return WorktreeRemovalResult(False, "missing_worktree_sentinel")
397
+ if not worktree_registered(runtime):
398
+ return WorktreeRemovalResult(False, "worktree_not_registered")
399
+ results: list[GitCommandResult] = []
400
+ for command in worktree_remove_plan(runtime, delete_branch=delete_branch).commands:
401
+ result = run_git_command(runtime.context.project_root, command.args)
402
+ results.append(result)
403
+ if result.return_code != 0 and not command.allow_failure:
404
+ return WorktreeRemovalResult(False, command.description or "worktree_remove_failed", tuple(results))
405
+ return WorktreeRemovalResult(True, results=tuple(results))
406
+
407
+
408
+ @dataclass(frozen=True)
409
+ class GitCommand:
410
+ """One planned git command."""
411
+
412
+ args: tuple[str, ...]
413
+ allow_failure: bool = False
414
+ description: str = ""
415
+
416
+
417
+ @dataclass(frozen=True)
418
+ class GitCommandPlan:
419
+ """A deterministic branch/worktree command plan."""
420
+
421
+ name: str
422
+ commands: tuple[GitCommand, ...]
423
+ never_fails: bool = False
424
+ notes: tuple[str, ...] = ()
425
+ require_one_success: tuple[tuple[int, ...], ...] = ()
426
+
427
+
428
+ @dataclass(frozen=True)
429
+ class GitCommandResult:
430
+ """Result from running one git command."""
431
+
432
+ args: tuple[str, ...]
433
+ return_code: int
434
+ stdout: str
435
+ stderr: str
436
+
437
+
438
+ @dataclass(frozen=True)
439
+ class GitPlanResult:
440
+ """Result from running a command plan."""
441
+
442
+ plan: GitCommandPlan
443
+ results: tuple[GitCommandResult, ...]
444
+
445
+ @property
446
+ def ok(self) -> bool:
447
+ if self.plan.never_fails:
448
+ return True
449
+ for command, result in zip(self.plan.commands, self.results):
450
+ if result.return_code != 0 and not command.allow_failure:
451
+ return False
452
+ for success_group in self.plan.require_one_success:
453
+ if not any(
454
+ index < len(self.results) and self.results[index].return_code == 0
455
+ for index in success_group
456
+ ):
457
+ return False
458
+ return True
459
+
460
+
461
+ def _git(*args: str, allow_failure: bool = False, description: str = "") -> GitCommand:
462
+ return GitCommand(args=args, allow_failure=allow_failure, description=description)
463
+
464
+
465
+ def branch_create_plan(context: BranchContext) -> GitCommandPlan:
466
+ """Plan shell-equivalent branch_create intent."""
467
+ return GitCommandPlan(
468
+ name="branch_create",
469
+ commands=(
470
+ _git("rev-parse", "--verify", context.working_branch, allow_failure=True, description="check existing branch"),
471
+ _git("checkout", "-b", context.working_branch, context.base_branch, allow_failure=True, description="create branch if absent"),
472
+ _git("checkout", context.working_branch, allow_failure=True, description="checkout existing branch fallback"),
473
+ ),
474
+ notes=("Create and checkout branch from source, or checkout if it already exists.",),
475
+ require_one_success=((1, 2),),
476
+ )
477
+
478
+
479
+ def branch_return_plan(context: BranchContext) -> GitCommandPlan:
480
+ """Plan shell-equivalent branch_return intent."""
481
+ return GitCommandPlan(
482
+ name="branch_return",
483
+ commands=(
484
+ _git("rev-parse", "--abbrev-ref", "HEAD", description="detect current branch"),
485
+ _git("checkout", context.base_branch, allow_failure=True, description="checkout original branch if needed"),
486
+ ),
487
+ notes=("Safe when already on the original branch.",),
488
+ )
489
+
490
+
491
+ def branch_merge_plan(context: BranchContext, *, auto_push: bool = False) -> GitCommandPlan:
492
+ """Plan shell-equivalent branch_merge safety invariants."""
493
+ commands = [
494
+ _git("diff", "--name-only", allow_failure=True, description="detect tracked dirty files"),
495
+ _git("diff", "--cached", "--name-only", allow_failure=True, description="detect staged dirty files"),
496
+ _git("stash", "push", "-m", "pipeline-merge-stash", allow_failure=True, description="stash tracked dirty files only"),
497
+ _git("rebase", context.base_branch, context.working_branch, description="rebase dev onto original"),
498
+ _git("checkout", context.base_branch, description="checkout original for fast-forward"),
499
+ _git("merge", "--ff-only", context.working_branch, description="fast-forward original"),
500
+ ]
501
+ if auto_push:
502
+ commands.append(_git("push", allow_failure=True, description="optional auto-push"))
503
+ commands.extend(
504
+ [
505
+ _git("branch", "-d", context.working_branch, allow_failure=True, description="delete merged dev branch"),
506
+ _git("stash", "pop", allow_failure=True, description="restore stashed tracked files"),
507
+ ]
508
+ )
509
+ return GitCommandPlan(
510
+ name="branch_merge",
511
+ commands=tuple(commands),
512
+ notes=(
513
+ "Tracked-only stash avoids capturing ignored state artifacts.",
514
+ "Rebase then fast-forward preserves merge invariant.",
515
+ ),
516
+ )
517
+
518
+
519
+ def branch_save_wip_plan(context: BranchContext) -> GitCommandPlan:
520
+ """Plan shell-equivalent never-fail WIP preservation."""
521
+ return GitCommandPlan(
522
+ name="branch_save_wip",
523
+ commands=(
524
+ _git("rev-parse", "--abbrev-ref", "HEAD", allow_failure=True, description="verify current branch"),
525
+ _git("status", "--porcelain", allow_failure=True, description="detect uncommitted work"),
526
+ _git("add", "-A", "--", ".", *HIDDEN_TOOL_WORKTREE_EXCLUDES, allow_failure=True, description="stage non-ignored work excluding hidden tool worktrees"),
527
+ _git(
528
+ "commit",
529
+ "--no-verify",
530
+ "-m",
531
+ f"wip({context.working_branch}): interrupted — uncommitted work saved",
532
+ "-m",
533
+ "Pipeline was interrupted by signal. This commit preserves work-in-progress.",
534
+ "-m",
535
+ f"To resume: git checkout {context.working_branch}",
536
+ allow_failure=True,
537
+ description="create WIP commit",
538
+ ),
539
+ ),
540
+ never_fails=True,
541
+ notes=("Never-fail cleanup helper; errors are diagnostics only.",),
542
+ )
543
+
544
+
545
+ def branch_ensure_return_plan(context: BranchContext) -> GitCommandPlan:
546
+ """Plan shell-equivalent guaranteed return cleanup."""
547
+ return GitCommandPlan(
548
+ name="branch_ensure_return",
549
+ commands=(
550
+ _git("rebase", "--abort", allow_failure=True, description="abort in-progress rebase"),
551
+ _git("rev-parse", "--abbrev-ref", "HEAD", allow_failure=True, description="detect current branch"),
552
+ _git("status", "--porcelain", "--", ".", *HIDDEN_TOOL_WORKTREE_EXCLUDES, allow_failure=True, description="detect WIP before checkout"),
553
+ _git("add", "-A", "--", ".", *HIDDEN_TOOL_WORKTREE_EXCLUDES, allow_failure=True, description="stage WIP before checkout"),
554
+ _git(
555
+ "commit",
556
+ "--no-verify",
557
+ "-m",
558
+ f"wip({context.working_branch}): interrupted — uncommitted work saved",
559
+ "-m",
560
+ "Pipeline was interrupted by signal. This commit preserves work-in-progress.",
561
+ "-m",
562
+ f"To resume: git checkout {context.working_branch}",
563
+ allow_failure=True,
564
+ description="save WIP before return when on dev branch",
565
+ ),
566
+ _git("stash", "push", "-m", "pipeline-ensure-return-stash", allow_failure=True, description="stash checkout blockers"),
567
+ _git("checkout", context.base_branch, allow_failure=True, description="return to original branch"),
568
+ _git("stash", "pop", allow_failure=True, description="restore stashed checkout blockers"),
569
+ ),
570
+ never_fails=True,
571
+ notes=("Always returns success to support trap/finally cleanup paths.",),
572
+ )
573
+
574
+
575
+ def worktree_add_plan(context: BranchContext, policy: WorktreePolicy) -> GitCommandPlan:
576
+ """Plan worktree creation without recreating retired Windows runtime sources."""
577
+ root = policy.worktree_root or context.project_root.parent / f"{context.working_branch.replace('/', '-')}-worktree"
578
+ return GitCommandPlan(
579
+ name="worktree_add",
580
+ commands=(
581
+ _git("worktree", "add", str(root), context.working_branch, description="create git worktree"),
582
+ ),
583
+ notes=("Generic git worktree helper; no retired platform source trees are created.",),
584
+ )
585
+
586
+
587
+ def current_branch(project_root: Path) -> str:
588
+ """Return current git branch name, or an empty string outside git."""
589
+ result = run_git_command(project_root, ("rev-parse", "--abbrev-ref", "HEAD"))
590
+ return result.stdout.strip() if result.return_code == 0 else ""
591
+
592
+
593
+ def git_status_safe(project_root: Path) -> str:
594
+ """Return status while excluding hidden AI tool worktree directories."""
595
+ result = run_git_command(project_root, ("status", "--porcelain", "--", ".", *HIDDEN_TOOL_WORKTREE_EXCLUDES))
596
+ return result.stdout if result.return_code == 0 else ""
597
+
598
+
599
+ def branch_save_wip(project_root: Path, working_branch: str) -> GitPlanResult:
600
+ """Execute shell-compatible WIP save only when currently on working_branch."""
601
+ context = BranchContext(base_branch="", working_branch=working_branch, project_root=project_root)
602
+ plan = branch_save_wip_plan(context)
603
+ if not working_branch or current_branch(project_root) != working_branch or not git_status_safe(project_root).strip():
604
+ return GitPlanResult(plan=plan, results=())
605
+ return run_git_plan(project_root, plan)
606
+
607
+
608
+ def worktree_save_wip(runtime: WorktreeRuntimeContext) -> GitPlanResult:
609
+ """Preserve dirty linked-worktree changes on the task branch before removal."""
610
+ return branch_save_wip(runtime.worktree_path, runtime.context.working_branch)
611
+
612
+
613
+ def branch_ensure_return(project_root: Path, base_branch: str, working_branch: str = "") -> GitPlanResult:
614
+ """Best-effort shell-compatible ensure-return helper that never reports failure."""
615
+ active = current_branch(project_root)
616
+ if working_branch and active == working_branch:
617
+ branch_save_wip(project_root, working_branch)
618
+ context = BranchContext(base_branch=base_branch, working_branch=working_branch or active, project_root=project_root)
619
+ return run_git_plan(project_root, branch_ensure_return_plan(context))
620
+
621
+ def run_git_command(project_root: Path, args: Sequence[str]) -> GitCommandResult:
622
+ """Run one git command in a project root and capture output."""
623
+ completed = subprocess.run(
624
+ ["git", "-C", str(project_root), *map(str, args)],
625
+ stdout=subprocess.PIPE,
626
+ stderr=subprocess.PIPE,
627
+ text=True,
628
+ check=False,
629
+ )
630
+ return GitCommandResult(
631
+ args=tuple(map(str, args)),
632
+ return_code=completed.returncode,
633
+ stdout=completed.stdout,
634
+ stderr=completed.stderr,
635
+ )
636
+
637
+
638
+ def run_git_plan(project_root: Path, plan: GitCommandPlan) -> GitPlanResult:
639
+ """Run a plan sequentially, stopping on non-allowed failures."""
640
+ results: list[GitCommandResult] = []
641
+ for command in plan.commands:
642
+ result = run_git_command(project_root, command.args)
643
+ results.append(result)
644
+ if result.return_code != 0 and not (command.allow_failure or plan.never_fails):
645
+ break
646
+ return GitPlanResult(plan=plan, results=tuple(results))
647
+
648
+
649
+ @dataclass(frozen=True)
650
+ class ResetBranchCleanupResult:
651
+ """Observed result for reset-time branch cleanup."""
652
+
653
+ branch: str
654
+ cleaned: bool
655
+ deleted: bool
656
+ returned_to: str
657
+ warnings: tuple[str, ...] = ()
658
+
659
+
660
+ def default_branch(project_root: Path) -> str:
661
+ """Resolve the same main/master/default-branch fallback used by reset scripts."""
662
+ origin = run_git_command(project_root, ("symbolic-ref", "refs/remotes/origin/HEAD"))
663
+ if origin.return_code == 0 and origin.stdout.strip():
664
+ return origin.stdout.strip().removeprefix("refs/remotes/origin/")
665
+ if run_git_command(project_root, ("rev-parse", "--verify", "main")).return_code == 0:
666
+ return "main"
667
+ if run_git_command(project_root, ("rev-parse", "--verify", "master")).return_code == 0:
668
+ return "master"
669
+ return current_branch(project_root) or "main"
670
+
671
+
672
+ def reset_branch_pattern(prefix: str, item_id: str) -> str:
673
+ """Return the reset helper branch glob for one item."""
674
+ return f"{prefix}/{item_id}-*"
675
+
676
+
677
+ def list_reset_branches(project_root: Path, prefix: str, item_id: str) -> tuple[str, ...]:
678
+ """List dev branches that shell reset helpers would clean for an item."""
679
+ result = run_git_command(project_root, ("branch", "--list", reset_branch_pattern(prefix, item_id)))
680
+ if result.return_code != 0:
681
+ return ()
682
+ branches = []
683
+ for line in result.stdout.splitlines():
684
+ branch = line.strip().lstrip("* ").strip()
685
+ if branch:
686
+ branches.append(branch)
687
+ return tuple(branches)
688
+
689
+
690
+ def reset_cleanup_branch(project_root: Path, branch: str, *, return_branch: str, delete: bool) -> ResetBranchCleanupResult:
691
+ """Discard uncommitted branch changes and optionally delete the branch.
692
+
693
+ This is intentionally reset-specific: unlike interrupted runner cleanup, manual
694
+ reset abandons uncommitted work on matching dev branches to recreate the
695
+ shell helper contract.
696
+ """
697
+ warnings: list[str] = []
698
+ active = current_branch(project_root)
699
+ restored = active
700
+ stashed = False
701
+
702
+ if active == branch:
703
+ run_git_command(project_root, ("reset", "HEAD"))
704
+ run_git_command(project_root, ("checkout", "--", "."))
705
+ run_git_command(project_root, ("clean", "-fd"))
706
+ checkout = run_git_command(project_root, ("checkout", return_branch))
707
+ if checkout.return_code != 0:
708
+ warnings.append(f"failed to checkout {return_branch}")
709
+ restored = branch
710
+ else:
711
+ restored = return_branch
712
+ else:
713
+ dirty = run_git_command(project_root, ("status", "--porcelain"))
714
+ if dirty.stdout.strip():
715
+ stash = run_git_command(project_root, ("stash", "push", "--include-untracked", "-m", "reset-pipeline-temp"))
716
+ stashed = stash.return_code == 0
717
+ checkout = run_git_command(project_root, ("checkout", branch))
718
+ if checkout.return_code == 0:
719
+ run_git_command(project_root, ("reset", "HEAD"))
720
+ run_git_command(project_root, ("checkout", "--", "."))
721
+ run_git_command(project_root, ("clean", "-fd"))
722
+ run_git_command(project_root, ("checkout", active or return_branch))
723
+ restored = active or return_branch
724
+ else:
725
+ warnings.append(f"could not checkout {branch} to discard changes")
726
+ if stashed:
727
+ run_git_command(project_root, ("stash", "pop"))
728
+
729
+ deleted = False
730
+ if delete:
731
+ deleted = run_git_command(project_root, ("branch", "-D", branch)).return_code == 0
732
+ if not deleted:
733
+ warnings.append(f"failed to delete branch {branch}")
734
+ return ResetBranchCleanupResult(branch=branch, cleaned=True, deleted=deleted, returned_to=restored, warnings=tuple(warnings))