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,389 @@
1
+ """Manual reset commands for the unified Python runtime."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import json
6
+ import re
7
+ import subprocess
8
+ import sys
9
+ from collections.abc import Sequence
10
+ from dataclasses import dataclass
11
+ from pathlib import Path
12
+
13
+ from .commands import CommandResult # type: ignore # runtime boundary import
14
+ from .gitops import default_branch, list_reset_branches, reset_cleanup_branch
15
+ from .runner_models import RunnerFamily, family_for
16
+
17
+
18
+ @dataclass(frozen=True)
19
+ class ResetOptions:
20
+ """Parsed legacy reset arguments for one family."""
21
+
22
+ list_path: Path
23
+ item_id: str = ""
24
+ item_range: tuple[str, str] | None = None
25
+ filter_mode: str = ""
26
+ clean: bool = False
27
+ run_after: bool = False
28
+ help_requested: bool = False
29
+ unknown_args: tuple[str, ...] = ()
30
+
31
+
32
+ @dataclass(frozen=True)
33
+ class ResetItem:
34
+ """Resolved reset target from the plan list."""
35
+
36
+ item_id: str
37
+ title: str
38
+ slug: str
39
+ status: str
40
+
41
+
42
+ FAMILY_LABELS = {
43
+ "feature": "feature",
44
+ "bugfix": "bug",
45
+ "refactor": "refactor",
46
+ }
47
+
48
+ FILTER_FLAGS = {
49
+ "--auto-skipped": "auto_skipped",
50
+ "--failed": "failed",
51
+ "--stalled": "stalled",
52
+ }
53
+
54
+
55
+ ID_FIELD_BY_KIND = {
56
+ "feature": "id",
57
+ "bugfix": "id",
58
+ "refactor": "id",
59
+ }
60
+
61
+
62
+ TITLE_FIELD_BY_KIND = {
63
+ "feature": "title",
64
+ "bugfix": "title",
65
+ "refactor": "title",
66
+ }
67
+
68
+
69
+ BRANCH_PREFIX_BY_KIND = {
70
+ "feature": "dev",
71
+ "bugfix": "bugfix",
72
+ "refactor": "refactor",
73
+ }
74
+
75
+ STALLED_FILTER_STATUSES = {
76
+ "failed",
77
+ "auto_skipped",
78
+ "needs_info",
79
+ "stalled",
80
+ "stalled_context_continuation",
81
+ }
82
+
83
+
84
+ def run_reset_command(kind: str, legacy_args: tuple[str, ...], paths) -> CommandResult:
85
+ """Run a manual reset command for feature, bugfix, or refactor."""
86
+ family = family_for(kind, paths)
87
+ options = _parse_reset_args(family, legacy_args)
88
+ if options.help_requested:
89
+ return CommandResult(0, f"Python {kind} reset", _help_text(family), stdout=_help_text(family))
90
+
91
+ list_path = _resolve_list_path(options.list_path, paths.project_root)
92
+ if not list_path.is_file():
93
+ return CommandResult(1, f"Python {kind} reset", f"{kind} list not found: {list_path}")
94
+ if not (family.state_dir / "pipeline.json").is_file():
95
+ return CommandResult(1, f"Python {kind} reset", f"No pipeline state found. Run the {kind} pipeline first to initialize.")
96
+
97
+ options = ResetOptions(
98
+ list_path=list_path,
99
+ item_id=options.item_id,
100
+ item_range=options.item_range,
101
+ filter_mode=options.filter_mode,
102
+ clean=options.clean,
103
+ run_after=options.run_after,
104
+ help_requested=options.help_requested,
105
+ unknown_args=options.unknown_args,
106
+ )
107
+ try:
108
+ items = _resolve_items(family, options)
109
+ except ValueError as exc:
110
+ return CommandResult(1, f"Python {kind} reset", str(exc))
111
+ if not items:
112
+ return CommandResult(0, f"Python {kind} reset", f"No {FAMILY_LABELS[kind]}s found with status: {options.filter_mode}")
113
+
114
+ if options.run_after and len(items) > 1:
115
+ options = ResetOptions(
116
+ list_path=options.list_path,
117
+ item_id=options.item_id,
118
+ item_range=options.item_range,
119
+ filter_mode=options.filter_mode,
120
+ clean=options.clean,
121
+ run_after=False,
122
+ help_requested=False,
123
+ unknown_args=options.unknown_args,
124
+ )
125
+
126
+ lines: list[str] = []
127
+ success = 0
128
+ failed = 0
129
+ return_branch = default_branch(paths.project_root)
130
+ for item in items:
131
+ ok = _reset_one(family, item, options, paths.project_root, return_branch, lines)
132
+ if ok:
133
+ success += 1
134
+ else:
135
+ failed += 1
136
+
137
+ lines.append(f"Reset complete: {success} succeeded, {failed} failed")
138
+ if options.run_after and len(items) == 1 and failed == 0:
139
+ from .runners import run_pipeline_command
140
+
141
+ lines.append(f"Auto-retrying {items[0].item_id} via Python foreground runner...")
142
+ retry_result = run_pipeline_command(kind, "run", (items[0].item_id, str(options.list_path)), paths)
143
+ lines.append(retry_result.render())
144
+ return CommandResult(retry_result.exit_code, f"Python {kind} reset", "\n".join(lines), stdout="\n".join(lines))
145
+
146
+ return CommandResult(0 if failed == 0 else 1, f"Python {kind} reset", "\n".join(lines), stdout="\n".join(lines))
147
+
148
+
149
+ def _parse_reset_args(family: RunnerFamily, legacy_args: Sequence[str]) -> ResetOptions:
150
+ args = tuple(str(arg) for arg in legacy_args)
151
+ list_path = family.plan_path
152
+ item_id = ""
153
+ item_range: tuple[str, str] | None = None
154
+ filter_mode = ""
155
+ clean = False
156
+ run_after = False
157
+ help_requested = False
158
+ unknown: list[str] = []
159
+ positional: list[str] = []
160
+
161
+ index = 0
162
+ while index < len(args):
163
+ arg = args[index]
164
+ if arg in {"--help", "-h", "help"}:
165
+ help_requested = True
166
+ elif arg == "--clean":
167
+ clean = True
168
+ elif arg == "--run":
169
+ run_after = True
170
+ elif arg in FILTER_FLAGS:
171
+ filter_mode = FILTER_FLAGS[arg]
172
+ elif arg.startswith("-"):
173
+ unknown.append(arg)
174
+ else:
175
+ positional.append(arg)
176
+ index += 1
177
+
178
+ for value in positional:
179
+ if _looks_like_range(value, family.id_prefix):
180
+ item_range = _normalize_range(value, family.id_prefix)
181
+ elif _looks_like_item_id(value, family.id_prefix) and not item_id:
182
+ item_id = _normalize_item_id(value, family.id_prefix)
183
+ elif list_path == family.plan_path:
184
+ list_path = Path(value).expanduser()
185
+ else:
186
+ unknown.append(value)
187
+
188
+ return ResetOptions(
189
+ list_path=list_path,
190
+ item_id=item_id,
191
+ item_range=item_range,
192
+ filter_mode=filter_mode,
193
+ clean=clean,
194
+ run_after=run_after,
195
+ help_requested=help_requested,
196
+ unknown_args=tuple(unknown),
197
+ )
198
+
199
+
200
+ def _resolve_list_path(path: Path, project_root: Path) -> Path:
201
+ return path.resolve() if path.is_absolute() else (project_root / path).resolve()
202
+
203
+
204
+ def _resolve_items(family: RunnerFamily, options: ResetOptions) -> tuple[ResetItem, ...]:
205
+ data = json.loads(options.list_path.read_text(encoding="utf-8"))
206
+ raw_items = data.get(family.list_key, [])
207
+ if not isinstance(raw_items, list):
208
+ raw_items = []
209
+ by_id = {_item_id(family, item): item for item in raw_items if isinstance(item, dict) and _item_id(family, item)}
210
+
211
+ ids: list[str]
212
+ if options.filter_mode:
213
+ ids = []
214
+ for item in raw_items:
215
+ if not isinstance(item, dict):
216
+ continue
217
+ status = str(item.get("status") or "")
218
+ if options.filter_mode == "auto_skipped" and status == "auto_skipped":
219
+ ids.append(_item_id(family, item))
220
+ elif options.filter_mode == "failed" and status == "failed":
221
+ ids.append(_item_id(family, item))
222
+ elif options.filter_mode == "stalled" and status in STALLED_FILTER_STATUSES:
223
+ ids.append(_item_id(family, item))
224
+ elif options.item_range:
225
+ start, end = options.item_range
226
+ start_num = _numeric_suffix(start, family.id_prefix)
227
+ end_num = _numeric_suffix(end, family.id_prefix)
228
+ if start_num <= 0 or end_num <= 0 or start_num > end_num:
229
+ raise ValueError(f"Invalid range: {start}:{end} (start must be <= end)")
230
+ ids = [f"{family.id_prefix}{number:03d}" for number in range(start_num, end_num + 1)]
231
+ elif options.item_id:
232
+ ids = [options.item_id]
233
+ else:
234
+ raise ValueError(_help_text(family))
235
+
236
+ resolved: list[ResetItem] = []
237
+ for item_id in ids:
238
+ item = by_id.get(item_id)
239
+ if not isinstance(item, dict):
240
+ continue
241
+ title = str(item.get(TITLE_FIELD_BY_KIND[family.kind]) or "")
242
+ resolved.append(ResetItem(item_id=item_id, title=title, slug=_slug_for_item(family, item_id, title), status=str(item.get("status") or "unknown")))
243
+ return tuple(resolved)
244
+
245
+
246
+ def _reset_one(family: RunnerFamily, item: ResetItem, options: ResetOptions, project_root: Path, return_branch: str, lines: list[str]) -> bool:
247
+ label = FAMILY_LABELS[family.kind]
248
+ status_file = family.state_dir / item.item_id / "status.json"
249
+ lines.append(f"Reset: {item.item_id} — {item.title}")
250
+ status_data = _load_status(status_file)
251
+ if status_data:
252
+ lines.append(f"Current status: {item.status} (retry {status_data.get('retry_count', 0)}, {len(status_data.get('sessions') or [])} sessions)")
253
+ _append_continuation_warning(lines, status_data, item.item_id, label)
254
+ else:
255
+ lines.append(f"Current status: {item.status} (no runtime state file)")
256
+
257
+ for branch in list_reset_branches(project_root, BRANCH_PREFIX_BY_KIND[family.kind], item.item_id):
258
+ cleanup = reset_cleanup_branch(project_root, branch, return_branch=return_branch, delete=options.clean)
259
+ lines.append(f"Discarded uncommitted changes on dev branch: {cleanup.branch}")
260
+ if cleanup.deleted:
261
+ lines.append(f"Deleted dev branch: {cleanup.branch}")
262
+ elif not options.clean:
263
+ lines.append(f"Dev branch preserved for debugging: {cleanup.branch}")
264
+ lines.extend(f"WARN: {warning}" for warning in cleanup.warnings)
265
+
266
+ action = "clean" if options.clean else "reset"
267
+ lines.append(f"{'Cleaning' if options.clean else 'Resetting'} {item.item_id} status...")
268
+ result = _run_updater(family, action, options, item, project_root)
269
+ if result.returncode == 0 and _json_without_error(result.stdout):
270
+ lines.append(f"{item.item_id} {action} complete: status -> pending, retry count -> 0")
271
+ return True
272
+ error = _error_text(result.stdout) or result.stderr.strip() or "unknown"
273
+ lines.append(f"ERROR: Reset {item.item_id} failed: {error}")
274
+ return False
275
+
276
+
277
+ def _run_updater(family: RunnerFamily, action: str, options: ResetOptions, item: ResetItem, project_root: Path) -> subprocess.CompletedProcess[str]:
278
+ command = [
279
+ sys.executable,
280
+ str(family.updater_script),
281
+ family.list_arg,
282
+ str(options.list_path),
283
+ "--state-dir",
284
+ str(family.state_dir),
285
+ family.item_id_arg,
286
+ item.item_id,
287
+ "--action",
288
+ action,
289
+ "--max-retries",
290
+ "3",
291
+ "--max-infra-retries",
292
+ "3",
293
+ ]
294
+ if action == "clean":
295
+ command.extend(["--project-root", str(project_root)])
296
+ if family.kind == "feature":
297
+ command.extend(["--feature-slug", item.slug])
298
+ return subprocess.run(command, cwd=str(project_root), stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True, check=False)
299
+
300
+
301
+ def _append_continuation_warning(lines: list[str], status_data: dict[str, object], item_id: str, item_label: str) -> None:
302
+ if status_data.get("continuation_pending") is True:
303
+ reason = str(status_data.get("continuation_reason") or "context_overflow")
304
+ lines.append(
305
+ f"WARN: Continuation pending for {item_label} {item_id} ({reason}). Manual reset will abandon automatic continuation progress."
306
+ )
307
+ branch = str(status_data.get("active_dev_branch") or "")
308
+ if branch:
309
+ lines.append(f"WARN: Pending continuation branch: {branch}")
310
+
311
+
312
+ def _load_status(path: Path) -> dict[str, object]:
313
+ if not path.is_file():
314
+ return {}
315
+ try:
316
+ data = json.loads(path.read_text(encoding="utf-8"))
317
+ except (OSError, json.JSONDecodeError):
318
+ return {}
319
+ return data if isinstance(data, dict) else {}
320
+
321
+
322
+ def _json_without_error(text: str) -> bool:
323
+ try:
324
+ data = json.loads(text or "{}")
325
+ except json.JSONDecodeError:
326
+ return False
327
+ return isinstance(data, dict) and "error" not in data
328
+
329
+
330
+ def _error_text(text: str) -> str:
331
+ try:
332
+ data = json.loads(text or "{}")
333
+ except json.JSONDecodeError:
334
+ return text.strip()
335
+ return str(data.get("error") or "") if isinstance(data, dict) else ""
336
+
337
+
338
+ def _item_id(family: RunnerFamily, item: dict[str, object]) -> str:
339
+ return _normalize_item_id(str(item.get(ID_FIELD_BY_KIND[family.kind]) or ""), family.id_prefix)
340
+
341
+
342
+ def _slug_for_item(family: RunnerFamily, item_id: str, title: str) -> str:
343
+ if family.kind != "feature":
344
+ return item_id
345
+ numeric = item_id.replace("F-", "").replace("f-", "").zfill(3)
346
+ slug = re.sub(r"[^a-z0-9\s-]", "", title.lower())
347
+ slug = re.sub(r"[\s]+", "-", slug.strip())
348
+ slug = re.sub(r"-+", "-", slug).strip("-") or "feature"
349
+ return f"{numeric}-{slug}"
350
+
351
+
352
+ def _looks_like_item_id(value: str, prefix: str) -> bool:
353
+ return value.upper().startswith(prefix.upper())
354
+
355
+
356
+ def _looks_like_range(value: str, prefix: str) -> bool:
357
+ if ":" not in value:
358
+ return False
359
+ left, right = value.split(":", 1)
360
+ return _looks_like_item_id(left, prefix) and _looks_like_item_id(right, prefix)
361
+
362
+
363
+ def _normalize_range(value: str, prefix: str) -> tuple[str, str]:
364
+ left, right = value.split(":", 1)
365
+ return _normalize_item_id(left, prefix), _normalize_item_id(right, prefix)
366
+
367
+
368
+ def _normalize_item_id(value: str, prefix: str) -> str:
369
+ upper = value.upper()
370
+ if upper.startswith(prefix.upper()):
371
+ suffix = upper[len(prefix) :]
372
+ if suffix.isdigit():
373
+ return f"{prefix}{int(suffix):03d}"
374
+ return upper
375
+
376
+
377
+ def _numeric_suffix(value: str, prefix: str) -> int:
378
+ normalized = _normalize_item_id(value, prefix)
379
+ suffix = normalized[len(prefix) :]
380
+ return int(suffix) if suffix.isdigit() else 0
381
+
382
+
383
+ def _help_text(family: RunnerFamily) -> str:
384
+ label = FAMILY_LABELS[family.kind]
385
+ return (
386
+ f"Usage: prizmkit-runtime reset {family.kind} <{label}-id|range> [--clean] [--run] "
387
+ "[--auto-skipped|--failed|--stalled] [list-path]\n"
388
+ "Reset is a destructive manual operation and is not used for automatic context continuation."
389
+ )
@@ -0,0 +1,51 @@
1
+ """Bookkeeping git helpers for Python foreground runners.
2
+
3
+ These helpers model the shell runner bookkeeping boundaries without hiding git
4
+ failures. They are intentionally small wrappers so task runners can preserve the
5
+ legacy ordering around branch creation and final status updates.
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ from dataclasses import dataclass
11
+ from pathlib import Path
12
+
13
+ from .gitops import GitCommandResult, git_status_safe, run_git_command
14
+ from .runner_models import RunnerFamily
15
+
16
+
17
+ @dataclass(frozen=True)
18
+ class BookkeepingResult:
19
+ """Result from an optional bookkeeping commit boundary."""
20
+
21
+ attempted: bool
22
+ committed: bool
23
+ result: GitCommandResult | None = None
24
+
25
+ @property
26
+ def ok(self) -> bool:
27
+ return self.result is None or self.result.return_code == 0
28
+
29
+
30
+ def has_workspace_changes(project_root: Path) -> bool:
31
+ """Return true when git status has non-hidden-tool worktree changes."""
32
+ return bool(git_status_safe(project_root).strip())
33
+
34
+
35
+ def commit_all_changes(project_root: Path, message: str) -> BookkeepingResult:
36
+ """Stage and commit current workspace changes when present."""
37
+ if not has_workspace_changes(project_root):
38
+ return BookkeepingResult(attempted=False, committed=False)
39
+ run_git_command(project_root, ("add", "-A", "--", "."))
40
+ result = run_git_command(project_root, ("commit", "--no-verify", "-m", message))
41
+ return BookkeepingResult(attempted=True, committed=result.return_code == 0, result=result)
42
+
43
+
44
+ def commit_pre_branch_bookkeeping(project_root: Path, family: RunnerFamily, item_id: str) -> BookkeepingResult:
45
+ """Commit status/list changes before creating the item dev branch."""
46
+ return commit_all_changes(project_root, f"chore({item_id}): mark in_progress")
47
+
48
+
49
+ def commit_final_bookkeeping(project_root: Path, family: RunnerFamily, item_id: str, status: str) -> BookkeepingResult:
50
+ """Commit final list/state changes after returning to the base branch."""
51
+ return commit_all_changes(project_root, f"chore({item_id}): update {family.kind} status {status}")
@@ -0,0 +1,179 @@
1
+ """Session classification and continuation helpers for Python runners."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import hashlib
6
+ import json
7
+ import subprocess
8
+ from pathlib import Path
9
+
10
+ from .gitops import HIDDEN_TOOL_WORKTREE_EXCLUDES, git_status_safe, run_git_command
11
+ from .runner_models import PromptGenerationResult, SessionClassification
12
+ from .sessions import AISessionResult
13
+
14
+ CONTEXT_OVERFLOW = "context_overflow"
15
+ STALL_REASON = "context_overflow_without_git_checkpoint_or_artifact_progress"
16
+ CONTEXT_MARKERS = (
17
+ "context_overflow",
18
+ "input exceeds the context window",
19
+ "context_length_exceeded",
20
+ "maximum context length exceeded",
21
+ "prompt is too long",
22
+ "too many tokens",
23
+ "input token count exceeds",
24
+ )
25
+ INFRA_MARKERS = (
26
+ "rate limit",
27
+ "overloaded",
28
+ "gateway",
29
+ "authentication",
30
+ "unauthorized",
31
+ "api error",
32
+ )
33
+
34
+
35
+ def classify_session(
36
+ result: AISessionResult,
37
+ *,
38
+ project_root: Path,
39
+ base_head: str,
40
+ prompt: PromptGenerationResult | None = None,
41
+ previous_fingerprint: object | None = None,
42
+ previous_no_progress_count: int = 0,
43
+ ) -> SessionClassification:
44
+ """Classify raw AI session signals with durable success precedence."""
45
+ fingerprint = progress_fingerprint(project_root, prompt)
46
+ if _has_commit_since(project_root, base_head):
47
+ return SessionClassification("success", reason="commit_since_base", progress_fingerprint=fingerprint)
48
+
49
+ if _is_context_overflow(result):
50
+ no_progress_count = _next_no_progress_count(previous_fingerprint, fingerprint, previous_no_progress_count)
51
+ if no_progress_count >= 2:
52
+ return SessionClassification(
53
+ "stalled_context_continuation",
54
+ reason=STALL_REASON,
55
+ fatal_error_code=result.fatal_error_code or CONTEXT_OVERFLOW,
56
+ progress_fingerprint=fingerprint,
57
+ no_progress_count=no_progress_count,
58
+ )
59
+ return SessionClassification(
60
+ CONTEXT_OVERFLOW,
61
+ reason=CONTEXT_OVERFLOW,
62
+ fatal_error_code=result.fatal_error_code or CONTEXT_OVERFLOW,
63
+ progress_fingerprint=fingerprint,
64
+ no_progress_count=no_progress_count,
65
+ )
66
+
67
+ if _is_infra_error(result):
68
+ return SessionClassification("infra_error", reason="ai_runtime_or_provider_error", progress_fingerprint=fingerprint)
69
+ if result.termination_reason == "stale_session":
70
+ return SessionClassification("crashed", reason="stale_session", progress_fingerprint=fingerprint)
71
+ if result.timed_out or result.termination_reason == "timeout":
72
+ return SessionClassification("timed_out", reason="timeout", progress_fingerprint=fingerprint)
73
+ if result.exit_code not in (0, None):
74
+ return SessionClassification("crashed", reason=f"exit_code={result.exit_code}", progress_fingerprint=fingerprint)
75
+ if _has_workspace_changes(project_root):
76
+ _auto_commit_workspace(project_root)
77
+ return SessionClassification("success", reason="auto_commit_uncommitted_changes", progress_fingerprint=fingerprint)
78
+ return SessionClassification("crashed", reason="no_durable_success", progress_fingerprint=fingerprint)
79
+
80
+
81
+ def progress_fingerprint(project_root: Path, prompt: PromptGenerationResult | None = None) -> dict[str, object]:
82
+ """Build the no-progress continuation fingerprint used by runner status metadata."""
83
+ status_text = git_status_safe(project_root)
84
+ head = run_git_command(project_root, ("rev-parse", "HEAD")).stdout.strip()
85
+ artifact_hash = ""
86
+ checkpoint_cursor = ""
87
+ if prompt and prompt.artifact_path and prompt.artifact_path.exists():
88
+ artifact_hash = _hash_tree(prompt.artifact_path)
89
+ if prompt and prompt.checkpoint_path and prompt.checkpoint_path.is_file():
90
+ try:
91
+ data = json.loads(prompt.checkpoint_path.read_text(encoding="utf-8"))
92
+ checkpoint_cursor = _checkpoint_cursor(data)
93
+ except (OSError, json.JSONDecodeError):
94
+ checkpoint_cursor = "unreadable"
95
+ return {
96
+ "git_diff_fingerprint": hashlib.sha256(status_text.encode()).hexdigest(),
97
+ "checkpoint_cursor": checkpoint_cursor,
98
+ "artifact_fingerprint": artifact_hash,
99
+ "head_commit": head,
100
+ }
101
+
102
+
103
+ def _next_no_progress_count(previous: object | None, current: object, count: int) -> int:
104
+ if previous and previous == current:
105
+ return max(0, count) + 1
106
+ return 0
107
+
108
+
109
+ def _is_context_overflow(result: AISessionResult) -> bool:
110
+ if (result.fatal_error_code or "").lower() == CONTEXT_OVERFLOW:
111
+ return True
112
+ text = "\n".join(
113
+ [
114
+ result.progress_summary.fatal_error_code,
115
+ result.progress_summary.terminal_result_text,
116
+ *result.progress_summary.errors,
117
+ _tail(result.session_log),
118
+ ]
119
+ ).lower()
120
+ return any(marker in text for marker in CONTEXT_MARKERS)
121
+
122
+
123
+ def _is_infra_error(result: AISessionResult) -> bool:
124
+ text = "\n".join([result.progress_summary.terminal_result_text, *result.progress_summary.errors, _tail(result.session_log)]).lower()
125
+ return bool(result.fatal_error_code and result.fatal_error_code != CONTEXT_OVERFLOW) or any(marker in text for marker in INFRA_MARKERS)
126
+
127
+
128
+ def _has_commit_since(project_root: Path, base_head: str) -> bool:
129
+ if not base_head:
130
+ return False
131
+ current = run_git_command(project_root, ("rev-parse", "HEAD")).stdout.strip()
132
+ return bool(current and current != base_head)
133
+
134
+
135
+ def _has_workspace_changes(project_root: Path) -> bool:
136
+ return bool(git_status_safe(project_root).strip())
137
+
138
+
139
+ def _auto_commit_workspace(project_root: Path) -> None:
140
+ run_git_command(project_root, ("add", "-A", "--", ".", *HIDDEN_TOOL_WORKTREE_EXCLUDES))
141
+ run_git_command(project_root, ("commit", "--no-verify", "-m", "chore: save runner session changes"))
142
+
143
+
144
+ def _tail(path: Path, max_bytes: int = 8192) -> str:
145
+ try:
146
+ data = path.read_bytes()
147
+ except OSError:
148
+ return ""
149
+ return data[-max_bytes:].decode("utf-8", errors="ignore")
150
+
151
+
152
+ def _hash_tree(path: Path) -> str:
153
+ digest = hashlib.sha256()
154
+ if path.is_file():
155
+ digest.update(path.name.encode())
156
+ digest.update(path.read_bytes())
157
+ return digest.hexdigest()
158
+ for child in sorted(path.rglob("*")):
159
+ if child.is_file():
160
+ try:
161
+ rel = child.relative_to(path).as_posix()
162
+ digest.update(rel.encode())
163
+ digest.update(child.read_bytes())
164
+ except OSError:
165
+ continue
166
+ return digest.hexdigest()
167
+
168
+
169
+ def _checkpoint_cursor(data: dict[str, object]) -> str:
170
+ steps = data.get("steps")
171
+ if not isinstance(steps, list):
172
+ return ""
173
+ for step in steps:
174
+ if not isinstance(step, dict):
175
+ continue
176
+ status = step.get("status", "pending")
177
+ if status not in {"completed", "skipped"}:
178
+ return f"{step.get('id', '?')}:{step.get('skill', 'unknown')}:{status}"
179
+ return "complete"