prizmkit 1.1.99 → 1.1.101

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (321) hide show
  1. package/bin/create-prizmkit.js +4 -4
  2. package/bundled/VERSION.json +3 -3
  3. package/bundled/dev-pipeline/.env.example +3 -3
  4. package/bundled/dev-pipeline/README.md +110 -90
  5. package/bundled/dev-pipeline/assets/prizm-dev-team-integration.md +1 -1
  6. package/bundled/dev-pipeline/cli.py +27 -0
  7. package/bundled/dev-pipeline/prizmkit_runtime/__init__.py +13 -0
  8. package/bundled/dev-pipeline/prizmkit_runtime/__main__.py +9 -0
  9. package/bundled/dev-pipeline/prizmkit_runtime/cli.py +193 -0
  10. package/bundled/dev-pipeline/prizmkit_runtime/commands.py +313 -0
  11. package/bundled/dev-pipeline/prizmkit_runtime/compat.py +32 -0
  12. package/bundled/dev-pipeline/prizmkit_runtime/config.py +410 -0
  13. package/bundled/dev-pipeline/prizmkit_runtime/daemon.py +478 -0
  14. package/bundled/dev-pipeline/prizmkit_runtime/gitops.py +734 -0
  15. package/bundled/dev-pipeline/prizmkit_runtime/heartbeat.py +256 -0
  16. package/bundled/dev-pipeline/prizmkit_runtime/interoperability.py +109 -0
  17. package/bundled/dev-pipeline/prizmkit_runtime/paths.py +110 -0
  18. package/bundled/dev-pipeline/prizmkit_runtime/processes.py +373 -0
  19. package/bundled/dev-pipeline/prizmkit_runtime/reset.py +389 -0
  20. package/bundled/dev-pipeline/prizmkit_runtime/runner_bookkeeping.py +51 -0
  21. package/bundled/dev-pipeline/prizmkit_runtime/runner_classification.py +179 -0
  22. package/bundled/dev-pipeline/prizmkit_runtime/runner_models.py +345 -0
  23. package/bundled/dev-pipeline/prizmkit_runtime/runner_prompts.py +118 -0
  24. package/bundled/dev-pipeline/prizmkit_runtime/runner_recovery.py +187 -0
  25. package/bundled/dev-pipeline/prizmkit_runtime/runner_status.py +147 -0
  26. package/bundled/dev-pipeline/prizmkit_runtime/runners.py +422 -0
  27. package/bundled/dev-pipeline/prizmkit_runtime/sessions.py +552 -0
  28. package/bundled/dev-pipeline/prizmkit_runtime/status.py +71 -0
  29. package/bundled/dev-pipeline/scripts/check-session-status.py +74 -1
  30. package/bundled/dev-pipeline/scripts/continuation.py +374 -0
  31. package/bundled/dev-pipeline/scripts/generate-bootstrap-prompt.py +64 -52
  32. package/bundled/dev-pipeline/scripts/generate-bugfix-prompt.py +35 -25
  33. package/bundled/dev-pipeline/scripts/generate-recovery-prompt.py +2 -2
  34. package/bundled/dev-pipeline/scripts/generate-refactor-prompt.py +15 -20
  35. package/bundled/dev-pipeline/scripts/parse-stream-progress.py +185 -16
  36. package/bundled/dev-pipeline/scripts/update-bug-status.py +214 -6
  37. package/bundled/dev-pipeline/scripts/update-feature-status.py +237 -6
  38. package/bundled/dev-pipeline/scripts/update-refactor-status.py +214 -6
  39. package/bundled/dev-pipeline/templates/agent-prompts/dev-implement.md +8 -2
  40. package/bundled/dev-pipeline/templates/bootstrap-prompt.md +4 -0
  41. package/bundled/dev-pipeline/templates/bootstrap-tier1.md +14 -5
  42. package/bundled/dev-pipeline/templates/bootstrap-tier2.md +16 -6
  43. package/bundled/dev-pipeline/templates/bootstrap-tier3.md +16 -6
  44. package/bundled/dev-pipeline/templates/bugfix-bootstrap-prompt.md +1 -1
  45. package/bundled/dev-pipeline/templates/refactor-bootstrap-prompt.md +3 -3
  46. package/bundled/dev-pipeline/templates/sections/context-budget-rules.md +2 -0
  47. package/bundled/dev-pipeline/templates/sections/log-size-awareness.md +13 -69
  48. package/bundled/dev-pipeline/templates/sections/phase-context-snapshot-agent-suffix.md +15 -7
  49. package/bundled/dev-pipeline/templates/sections/phase-implement-agent.md +42 -29
  50. package/bundled/dev-pipeline/templates/sections/phase-implement-full.md +41 -39
  51. package/bundled/dev-pipeline/templates/sections/test-failure-recovery-agent.md +4 -0
  52. package/bundled/dev-pipeline/templates/sections/test-failure-recovery-lite.md +4 -0
  53. package/bundled/dev-pipeline/templates/session-status-schema.json +1 -1
  54. package/bundled/dev-pipeline/tests/conftest.py +1 -0
  55. package/bundled/dev-pipeline/tests/test_auto_skip.py +932 -0
  56. package/bundled/dev-pipeline/tests/test_generate_bootstrap_prompt.py +207 -0
  57. package/bundled/dev-pipeline/tests/test_generate_bugfix_prompt.py +100 -0
  58. package/bundled/dev-pipeline/tests/test_generate_refactor_prompt.py +43 -0
  59. package/bundled/dev-pipeline/tests/test_python_runner_parity.py +1138 -0
  60. package/bundled/dev-pipeline/tests/test_unified_cli.py +1045 -0
  61. package/bundled/skills/_metadata.json +1 -1
  62. package/bundled/skills/bugfix-pipeline-launcher/SKILL.md +29 -34
  63. package/bundled/skills/bugfix-pipeline-launcher/references/configuration.md +6 -5
  64. package/bundled/skills/feature-pipeline-launcher/SKILL.md +29 -35
  65. package/bundled/skills/feature-pipeline-launcher/references/configuration.md +7 -6
  66. package/bundled/skills/feature-workflow/SKILL.md +3 -6
  67. package/bundled/skills/recovery-workflow/SKILL.md +23 -32
  68. package/bundled/skills/refactor-pipeline-launcher/SKILL.md +29 -35
  69. package/bundled/skills/refactor-pipeline-launcher/references/configuration.md +7 -6
  70. package/bundled/skills/refactor-workflow/SKILL.md +3 -6
  71. package/bundled/templates/hooks/commit-intent.json +2 -2
  72. package/bundled/templates/hooks/diff-prizm-docs.py +226 -0
  73. package/bundled/templates/hooks/prizm-pre-commit.py +45 -0
  74. package/bundled/templates/hooks/validate-prizm-docs.py +240 -0
  75. package/package.json +1 -1
  76. package/src/config.js +33 -12
  77. package/src/index.js +3 -6
  78. package/src/manifest.js +3 -2
  79. package/src/metadata.js +7 -18
  80. package/src/prompts.js +0 -12
  81. package/src/runtimes.js +18 -11
  82. package/src/scaffold.js +133 -116
  83. package/src/upgrade.js +1 -1
  84. package/bundled/dev-pipeline/launch-bugfix-daemon.sh +0 -500
  85. package/bundled/dev-pipeline/launch-feature-daemon.sh +0 -657
  86. package/bundled/dev-pipeline/launch-refactor-daemon.sh +0 -502
  87. package/bundled/dev-pipeline/lib/branch.sh +0 -326
  88. package/bundled/dev-pipeline/lib/common.sh +0 -1257
  89. package/bundled/dev-pipeline/lib/heartbeat.sh +0 -469
  90. package/bundled/dev-pipeline/reset-bug.sh +0 -395
  91. package/bundled/dev-pipeline/reset-feature.sh +0 -406
  92. package/bundled/dev-pipeline/reset-refactor.sh +0 -393
  93. package/bundled/dev-pipeline/run-bugfix.sh +0 -1315
  94. package/bundled/dev-pipeline/run-feature.sh +0 -1602
  95. package/bundled/dev-pipeline/run-recovery.sh +0 -648
  96. package/bundled/dev-pipeline/run-refactor.sh +0 -1348
  97. package/bundled/dev-pipeline/scripts/monitor-log.sh +0 -104
  98. package/bundled/dev-pipeline/tests/test-path-resolution.sh +0 -100
  99. package/bundled/dev-pipeline-windows/.env.example +0 -36
  100. package/bundled/dev-pipeline-windows/README.md +0 -30
  101. package/bundled/dev-pipeline-windows/SCHEMA_ANALYSIS.md +0 -533
  102. package/bundled/dev-pipeline-windows/assets/feature-list-example.json +0 -146
  103. package/bundled/dev-pipeline-windows/assets/prizm-dev-team-integration.md +0 -137
  104. package/bundled/dev-pipeline-windows/launch-bugfix-daemon.ps1 +0 -9
  105. package/bundled/dev-pipeline-windows/launch-feature-daemon.ps1 +0 -9
  106. package/bundled/dev-pipeline-windows/launch-refactor-daemon.ps1 +0 -9
  107. package/bundled/dev-pipeline-windows/lib/branch.ps1 +0 -235
  108. package/bundled/dev-pipeline-windows/lib/common.ps1 +0 -829
  109. package/bundled/dev-pipeline-windows/lib/daemon.ps1 +0 -140
  110. package/bundled/dev-pipeline-windows/lib/pipeline.ps1 +0 -967
  111. package/bundled/dev-pipeline-windows/lib/reset.ps1 +0 -87
  112. package/bundled/dev-pipeline-windows/reset-bug.ps1 +0 -9
  113. package/bundled/dev-pipeline-windows/reset-feature.ps1 +0 -9
  114. package/bundled/dev-pipeline-windows/reset-refactor.ps1 +0 -9
  115. package/bundled/dev-pipeline-windows/run-bugfix.ps1 +0 -9
  116. package/bundled/dev-pipeline-windows/run-feature.ps1 +0 -9
  117. package/bundled/dev-pipeline-windows/run-recovery.ps1 +0 -179
  118. package/bundled/dev-pipeline-windows/run-refactor.ps1 +0 -9
  119. package/bundled/dev-pipeline-windows/scripts/check-session-status.py +0 -228
  120. package/bundled/dev-pipeline-windows/scripts/detect-stuck.py +0 -530
  121. package/bundled/dev-pipeline-windows/scripts/generate-bootstrap-prompt.py +0 -2282
  122. package/bundled/dev-pipeline-windows/scripts/generate-bugfix-prompt.py +0 -767
  123. package/bundled/dev-pipeline-windows/scripts/generate-recovery-prompt.py +0 -805
  124. package/bundled/dev-pipeline-windows/scripts/generate-refactor-prompt.py +0 -845
  125. package/bundled/dev-pipeline-windows/scripts/init-bugfix-pipeline.py +0 -316
  126. package/bundled/dev-pipeline-windows/scripts/init-dev-team.py +0 -134
  127. package/bundled/dev-pipeline-windows/scripts/init-pipeline.py +0 -382
  128. package/bundled/dev-pipeline-windows/scripts/init-refactor-pipeline.py +0 -399
  129. package/bundled/dev-pipeline-windows/scripts/monitor-log.ps1 +0 -102
  130. package/bundled/dev-pipeline-windows/scripts/parse-stream-progress.py +0 -1232
  131. package/bundled/dev-pipeline-windows/scripts/patch-completion-notes.py +0 -191
  132. package/bundled/dev-pipeline-windows/scripts/prizmkit-test-gate.py +0 -446
  133. package/bundled/dev-pipeline-windows/scripts/update-bug-status.py +0 -913
  134. package/bundled/dev-pipeline-windows/scripts/update-checkpoint.py +0 -173
  135. package/bundled/dev-pipeline-windows/scripts/update-feature-status.py +0 -1558
  136. package/bundled/dev-pipeline-windows/scripts/update-refactor-status.py +0 -1119
  137. package/bundled/dev-pipeline-windows/scripts/utils.py +0 -542
  138. package/bundled/dev-pipeline-windows/templates/agent-prompts/critic-plan-challenge.md +0 -7
  139. package/bundled/dev-pipeline-windows/templates/agent-prompts/dev-fix.md +0 -7
  140. package/bundled/dev-pipeline-windows/templates/agent-prompts/dev-implement.md +0 -65
  141. package/bundled/dev-pipeline-windows/templates/agent-prompts/dev-resume.md +0 -5
  142. package/bundled/dev-pipeline-windows/templates/agent-prompts/reviewer-review.md +0 -7
  143. package/bundled/dev-pipeline-windows/templates/bootstrap-prompt.md +0 -73
  144. package/bundled/dev-pipeline-windows/templates/bootstrap-tier1.md +0 -589
  145. package/bundled/dev-pipeline-windows/templates/bootstrap-tier2.md +0 -710
  146. package/bundled/dev-pipeline-windows/templates/bootstrap-tier3.md +0 -791
  147. package/bundled/dev-pipeline-windows/templates/bug-fix-list-schema.json +0 -263
  148. package/bundled/dev-pipeline-windows/templates/bugfix-bootstrap-prompt.md +0 -326
  149. package/bundled/dev-pipeline-windows/templates/feature-list-schema.json +0 -237
  150. package/bundled/dev-pipeline-windows/templates/refactor-bootstrap-prompt.md +0 -340
  151. package/bundled/dev-pipeline-windows/templates/refactor-list-schema.json +0 -270
  152. package/bundled/dev-pipeline-windows/templates/sections/ac-verification-checklist.md +0 -7
  153. package/bundled/dev-pipeline-windows/templates/sections/checkpoint-system.md +0 -91
  154. package/bundled/dev-pipeline-windows/templates/sections/context-budget-rules.md +0 -34
  155. package/bundled/dev-pipeline-windows/templates/sections/critical-paths-agent.md +0 -10
  156. package/bundled/dev-pipeline-windows/templates/sections/critical-paths-full.md +0 -12
  157. package/bundled/dev-pipeline-windows/templates/sections/critical-paths-lite.md +0 -7
  158. package/bundled/dev-pipeline-windows/templates/sections/directory-convention-agent.md +0 -8
  159. package/bundled/dev-pipeline-windows/templates/sections/directory-convention-full.md +0 -9
  160. package/bundled/dev-pipeline-windows/templates/sections/directory-convention-lite.md +0 -6
  161. package/bundled/dev-pipeline-windows/templates/sections/failure-capture.md +0 -21
  162. package/bundled/dev-pipeline-windows/templates/sections/feature-context.md +0 -21
  163. package/bundled/dev-pipeline-windows/templates/sections/log-size-awareness.md +0 -78
  164. package/bundled/dev-pipeline-windows/templates/sections/phase-browser-verification-auto.md +0 -283
  165. package/bundled/dev-pipeline-windows/templates/sections/phase-browser-verification-opencli.md +0 -112
  166. package/bundled/dev-pipeline-windows/templates/sections/phase-browser-verification.md +0 -168
  167. package/bundled/dev-pipeline-windows/templates/sections/phase-commit-full.md +0 -82
  168. package/bundled/dev-pipeline-windows/templates/sections/phase-commit.md +0 -75
  169. package/bundled/dev-pipeline-windows/templates/sections/phase-context-snapshot-agent-suffix.md +0 -23
  170. package/bundled/dev-pipeline-windows/templates/sections/phase-context-snapshot-base.md +0 -14
  171. package/bundled/dev-pipeline-windows/templates/sections/phase-context-snapshot-lite-suffix.md +0 -19
  172. package/bundled/dev-pipeline-windows/templates/sections/phase-critic-plan-full.md +0 -63
  173. package/bundled/dev-pipeline-windows/templates/sections/phase-critic-plan.md +0 -42
  174. package/bundled/dev-pipeline-windows/templates/sections/phase-implement-agent.md +0 -44
  175. package/bundled/dev-pipeline-windows/templates/sections/phase-implement-full.md +0 -59
  176. package/bundled/dev-pipeline-windows/templates/sections/phase-implement-lite.md +0 -39
  177. package/bundled/dev-pipeline-windows/templates/sections/phase-plan-agent.md +0 -27
  178. package/bundled/dev-pipeline-windows/templates/sections/phase-plan-lite.md +0 -27
  179. package/bundled/dev-pipeline-windows/templates/sections/phase-prizmkit-test.md +0 -39
  180. package/bundled/dev-pipeline-windows/templates/sections/phase-review-agent.md +0 -35
  181. package/bundled/dev-pipeline-windows/templates/sections/phase-review-full.md +0 -35
  182. package/bundled/dev-pipeline-windows/templates/sections/phase-specify-plan-full.md +0 -73
  183. package/bundled/dev-pipeline-windows/templates/sections/phase0-init.md +0 -13
  184. package/bundled/dev-pipeline-windows/templates/sections/phase0-test-baseline.md +0 -21
  185. package/bundled/dev-pipeline-windows/templates/sections/session-context.md +0 -5
  186. package/bundled/dev-pipeline-windows/templates/sections/subagent-timeout-recovery.md +0 -6
  187. package/bundled/dev-pipeline-windows/templates/sections/task-contract.md +0 -34
  188. package/bundled/dev-pipeline-windows/templates/sections/test-failure-recovery-agent.md +0 -48
  189. package/bundled/dev-pipeline-windows/templates/sections/test-failure-recovery-lite.md +0 -48
  190. package/bundled/dev-pipeline-windows/templates/session-status-schema.json +0 -83
  191. package/bundled/skills-windows/app-planner/SKILL.md +0 -296
  192. package/bundled/skills-windows/app-planner/assets/app-design-guide.md +0 -101
  193. package/bundled/skills-windows/app-planner/references/architecture-decisions.md +0 -52
  194. package/bundled/skills-windows/app-planner/references/brainstorm-guide.md +0 -101
  195. package/bundled/skills-windows/app-planner/references/frontend-design-guide.md +0 -71
  196. package/bundled/skills-windows/app-planner/references/infrastructure-convention-discovery.md +0 -108
  197. package/bundled/skills-windows/app-planner/references/project-brief-guide.md +0 -82
  198. package/bundled/skills-windows/app-planner/references/project-conventions-discovery.md +0 -59
  199. package/bundled/skills-windows/app-planner/references/project-state-detection.md +0 -90
  200. package/bundled/skills-windows/app-planner/references/red-team-checklist.md +0 -40
  201. package/bundled/skills-windows/app-planner/references/rules/backend/derivation-rules.md +0 -619
  202. package/bundled/skills-windows/app-planner/references/rules/backend/fixed-rules.md +0 -285
  203. package/bundled/skills-windows/app-planner/references/rules/backend/question-bank.md +0 -249
  204. package/bundled/skills-windows/app-planner/references/rules/backend/question-manifest.json +0 -46
  205. package/bundled/skills-windows/app-planner/references/rules/backend/template.md +0 -173
  206. package/bundled/skills-windows/app-planner/references/rules/database/derivation-rules.md +0 -382
  207. package/bundled/skills-windows/app-planner/references/rules/database/fixed-rules.md +0 -211
  208. package/bundled/skills-windows/app-planner/references/rules/database/question-bank.md +0 -184
  209. package/bundled/skills-windows/app-planner/references/rules/database/question-manifest.json +0 -39
  210. package/bundled/skills-windows/app-planner/references/rules/database/template.md +0 -158
  211. package/bundled/skills-windows/app-planner/references/rules/frontend/derivation-rules.md +0 -820
  212. package/bundled/skills-windows/app-planner/references/rules/frontend/fixed-rules.md +0 -188
  213. package/bundled/skills-windows/app-planner/references/rules/frontend/question-bank.md +0 -319
  214. package/bundled/skills-windows/app-planner/references/rules/frontend/question-manifest.json +0 -51
  215. package/bundled/skills-windows/app-planner/references/rules/frontend/template.md +0 -339
  216. package/bundled/skills-windows/app-planner/references/rules/mobile/derivation-rules.md +0 -649
  217. package/bundled/skills-windows/app-planner/references/rules/mobile/fixed-rules.md +0 -290
  218. package/bundled/skills-windows/app-planner/references/rules/mobile/question-bank.md +0 -232
  219. package/bundled/skills-windows/app-planner/references/rules/mobile/question-manifest.json +0 -47
  220. package/bundled/skills-windows/app-planner/references/rules/mobile/template.md +0 -175
  221. package/bundled/skills-windows/app-planner/references/rules-configuration.md +0 -46
  222. package/bundled/skills-windows/bug-fix-workflow/SKILL.md +0 -379
  223. package/bundled/skills-windows/bug-fix-workflow/references/bug-diagnosis.md +0 -41
  224. package/bundled/skills-windows/bug-planner/SKILL.md +0 -402
  225. package/bundled/skills-windows/bug-planner/assets/bug-confirmation-template.md +0 -43
  226. package/bundled/skills-windows/bug-planner/references/critic-and-verification.md +0 -44
  227. package/bundled/skills-windows/bug-planner/references/error-recovery.md +0 -73
  228. package/bundled/skills-windows/bug-planner/references/input-formats.md +0 -53
  229. package/bundled/skills-windows/bug-planner/references/schema-validation.md +0 -25
  230. package/bundled/skills-windows/bug-planner/references/severity-rules.md +0 -16
  231. package/bundled/skills-windows/bug-planner/scripts/validate-bug-list.py +0 -322
  232. package/bundled/skills-windows/bugfix-pipeline-launcher/SKILL.md +0 -304
  233. package/bundled/skills-windows/bugfix-pipeline-launcher/references/configuration.md +0 -84
  234. package/bundled/skills-windows/feature-pipeline-launcher/SKILL.md +0 -381
  235. package/bundled/skills-windows/feature-pipeline-launcher/references/configuration.md +0 -67
  236. package/bundled/skills-windows/feature-pipeline-launcher/scripts/preflight-check.py +0 -462
  237. package/bundled/skills-windows/feature-planner/SKILL.md +0 -397
  238. package/bundled/skills-windows/feature-planner/assets/evaluation-guide.md +0 -64
  239. package/bundled/skills-windows/feature-planner/assets/planning-guide.md +0 -214
  240. package/bundled/skills-windows/feature-planner/references/browser-interaction.md +0 -59
  241. package/bundled/skills-windows/feature-planner/references/completeness-review.md +0 -57
  242. package/bundled/skills-windows/feature-planner/references/decomposition-patterns.md +0 -75
  243. package/bundled/skills-windows/feature-planner/references/error-recovery.md +0 -90
  244. package/bundled/skills-windows/feature-planner/references/incremental-feature-planning.md +0 -112
  245. package/bundled/skills-windows/feature-planner/references/new-project-planning.md +0 -85
  246. package/bundled/skills-windows/feature-planner/scripts/validate-and-generate.py +0 -1020
  247. package/bundled/skills-windows/feature-workflow/SKILL.md +0 -374
  248. package/bundled/skills-windows/feature-workflow/references/brainstorm-guide.md +0 -137
  249. package/bundled/skills-windows/prizm-kit/SKILL.md +0 -93
  250. package/bundled/skills-windows/prizmkit-code-review/SKILL.md +0 -161
  251. package/bundled/skills-windows/prizmkit-code-review/references/dev-agent-prompt.md +0 -30
  252. package/bundled/skills-windows/prizmkit-code-review/references/review-report-template.md +0 -31
  253. package/bundled/skills-windows/prizmkit-code-review/references/reviewer-agent-prompt.md +0 -66
  254. package/bundled/skills-windows/prizmkit-code-review/scripts/check_loop.py +0 -186
  255. package/bundled/skills-windows/prizmkit-committer/SKILL.md +0 -89
  256. package/bundled/skills-windows/prizmkit-deploy/SKILL.md +0 -444
  257. package/bundled/skills-windows/prizmkit-deploy/references/ci-cd-workflows.md +0 -115
  258. package/bundled/skills-windows/prizmkit-deploy/references/cloud-platform-deploy.md +0 -93
  259. package/bundled/skills-windows/prizmkit-deploy/references/data-safety-examples.md +0 -120
  260. package/bundled/skills-windows/prizmkit-deploy/references/database-setup.md +0 -46
  261. package/bundled/skills-windows/prizmkit-deploy/references/deploy-config-schema.md +0 -148
  262. package/bundled/skills-windows/prizmkit-deploy/references/deploy-history-schema.md +0 -62
  263. package/bundled/skills-windows/prizmkit-deploy/references/deployment-modes.md +0 -50
  264. package/bundled/skills-windows/prizmkit-deploy/references/direct-upload.md +0 -26
  265. package/bundled/skills-windows/prizmkit-deploy/references/dns-setup.md +0 -42
  266. package/bundled/skills-windows/prizmkit-deploy/references/docker-deploy.md +0 -31
  267. package/bundled/skills-windows/prizmkit-deploy/references/firewall-setup.md +0 -37
  268. package/bundled/skills-windows/prizmkit-deploy/references/live-validation-notes.md +0 -21
  269. package/bundled/skills-windows/prizmkit-deploy/references/nginx-blue-green.md +0 -59
  270. package/bundled/skills-windows/prizmkit-deploy/references/ssh-bootstrap-flow.md +0 -49
  271. package/bundled/skills-windows/prizmkit-deploy/references/ssh-execution-flow.md +0 -41
  272. package/bundled/skills-windows/prizmkit-deploy/references/ssh-takeover.md +0 -20
  273. package/bundled/skills-windows/prizmkit-deploy/references/ssl-setup.md +0 -56
  274. package/bundled/skills-windows/prizmkit-implement/SKILL.md +0 -71
  275. package/bundled/skills-windows/prizmkit-init/SKILL.md +0 -356
  276. package/bundled/skills-windows/prizmkit-init/assets/project-brief-template.md +0 -82
  277. package/bundled/skills-windows/prizmkit-init/references/config-schema.md +0 -70
  278. package/bundled/skills-windows/prizmkit-init/references/rules/layer-detection.md +0 -41
  279. package/bundled/skills-windows/prizmkit-init/references/tech-stack-catalog.md +0 -13
  280. package/bundled/skills-windows/prizmkit-init/references/update-supplement.md +0 -9
  281. package/bundled/skills-windows/prizmkit-plan/SKILL.md +0 -102
  282. package/bundled/skills-windows/prizmkit-plan/assets/plan-template.md +0 -115
  283. package/bundled/skills-windows/prizmkit-plan/assets/spec-template.md +0 -73
  284. package/bundled/skills-windows/prizmkit-plan/references/clarify-guide.md +0 -67
  285. package/bundled/skills-windows/prizmkit-plan/references/examples.md +0 -85
  286. package/bundled/skills-windows/prizmkit-plan/references/verification-checklist.md +0 -60
  287. package/bundled/skills-windows/prizmkit-prizm-docs/SKILL.md +0 -129
  288. package/bundled/skills-windows/prizmkit-prizm-docs/assets/prizm-docs-format.md +0 -613
  289. package/bundled/skills-windows/prizmkit-prizm-docs/references/op-init.md +0 -45
  290. package/bundled/skills-windows/prizmkit-prizm-docs/references/op-rebuild.md +0 -15
  291. package/bundled/skills-windows/prizmkit-prizm-docs/references/op-status.md +0 -14
  292. package/bundled/skills-windows/prizmkit-prizm-docs/references/op-update.md +0 -19
  293. package/bundled/skills-windows/prizmkit-prizm-docs/references/op-validate.md +0 -17
  294. package/bundled/skills-windows/prizmkit-retrospective/SKILL.md +0 -87
  295. package/bundled/skills-windows/prizmkit-retrospective/references/knowledge-injection-steps.md +0 -50
  296. package/bundled/skills-windows/prizmkit-retrospective/references/structural-sync-steps.md +0 -43
  297. package/bundled/skills-windows/prizmkit-test/SKILL.md +0 -227
  298. package/bundled/skills-windows/prizmkit-test/references/boundary-coverage-protocol.md +0 -220
  299. package/bundled/skills-windows/prizmkit-test/references/examples.md +0 -143
  300. package/bundled/skills-windows/prizmkit-test/references/service-boundary-test-catalog.md +0 -225
  301. package/bundled/skills-windows/prizmkit-test/references/test-generation-steps.md +0 -109
  302. package/bundled/skills-windows/prizmkit-test/references/test-report-template.md +0 -111
  303. package/bundled/skills-windows/prizmkit-test/scripts/validate_boundary_report.py +0 -347
  304. package/bundled/skills-windows/recovery-workflow/SKILL.md +0 -355
  305. package/bundled/skills-windows/recovery-workflow/evals/evals.json +0 -46
  306. package/bundled/skills-windows/recovery-workflow/references/detection.md +0 -58
  307. package/bundled/skills-windows/recovery-workflow/scripts/detect-recovery-state.py +0 -544
  308. package/bundled/skills-windows/refactor-pipeline-launcher/SKILL.md +0 -346
  309. package/bundled/skills-windows/refactor-pipeline-launcher/references/configuration.md +0 -72
  310. package/bundled/skills-windows/refactor-planner/SKILL.md +0 -398
  311. package/bundled/skills-windows/refactor-planner/assets/planning-guide.md +0 -292
  312. package/bundled/skills-windows/refactor-planner/references/behavior-preservation.md +0 -301
  313. package/bundled/skills-windows/refactor-planner/references/fast-path.md +0 -59
  314. package/bundled/skills-windows/refactor-planner/references/planning-phases.md +0 -135
  315. package/bundled/skills-windows/refactor-planner/references/refactor-scoping-guide.md +0 -221
  316. package/bundled/skills-windows/refactor-planner/scripts/validate-and-generate-refactor.py +0 -858
  317. package/bundled/skills-windows/refactor-workflow/SKILL.md +0 -343
  318. package/bundled/skills-windows/refactor-workflow/references/brainstorm-guide.md +0 -116
  319. package/bundled/templates/hooks/diff-prizm-docs.sh +0 -158
  320. package/bundled/templates/hooks/prizm-pre-commit.sh +0 -108
  321. package/bundled/templates/hooks/validate-prizm-docs.sh +0 -139
@@ -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"