devlyn-cli 3.2.1 → 3.3.0

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 (423) hide show
  1. package/AGENTS.md +2 -2
  2. package/CLAUDE.md +2 -2
  3. package/README.md +12 -102
  4. package/bin/devlyn.js +13 -225
  5. package/bin/instruction-templates.json +6 -0
  6. package/config/skills/_shared/adapters/grok.md +1 -2
  7. package/config/skills/_shared/archive_run.py +15 -3
  8. package/config/skills/_shared/judge-role-evidence.py +21 -1
  9. package/config/skills/_shared/runtime-principles.md +1 -1
  10. package/config/skills/_shared/spec-verify-check.py +0 -653
  11. package/config/skills/_shared/state-phase-write.py +351 -25
  12. package/config/skills/_shared/task-complete.py +635 -143
  13. package/config/skills/_shared/terminal-claim-check.py +229 -4
  14. package/config/skills/_shared/verify-merge-findings.py +93 -2
  15. package/config/skills/devlyn:ideate/SKILL.md +3 -4
  16. package/config/skills/devlyn:ideate/references/elicitation.md +2 -35
  17. package/config/skills/devlyn:ideate/references/from-spec-mode.md +3 -18
  18. package/config/skills/devlyn:ideate/references/project-mode.md +1 -16
  19. package/config/skills/devlyn:ideate/references/spec-template.md +0 -2
  20. package/config/skills/devlyn:queue/SKILL.md +6 -4
  21. package/config/skills/devlyn:resolve/SKILL.md +16 -25
  22. package/config/skills/devlyn:resolve/references/free-form-mode.md +0 -14
  23. package/config/skills/devlyn:resolve/references/outer-loop.md +1 -1
  24. package/config/skills/devlyn:resolve/references/phases/build-gate.md +1 -1
  25. package/config/skills/devlyn:resolve/references/phases/cleanup.md +3 -3
  26. package/config/skills/devlyn:resolve/references/phases/implement.md +1 -1
  27. package/config/skills/devlyn:resolve/references/phases/probe-derive.md +1 -16
  28. package/config/skills/devlyn:resolve/references/phases/verify.md +4 -9
  29. package/config/skills/devlyn:resolve/references/state-schema.md +9 -7
  30. package/config/skills/devlyn:resolve/references/task-completion.md +46 -37
  31. package/{config/skills → optional-skills}/code-health-standards/SKILL.md +4 -13
  32. package/{config/skills → optional-skills}/code-review-standards/SKILL.md +4 -12
  33. package/{config/skills → optional-skills}/root-cause-analysis/SKILL.md +4 -12
  34. package/{config/skills → optional-skills}/ui-implementation-standards/SKILL.md +4 -14
  35. package/package.json +1 -57
  36. package/benchmark/auto-resolve/BENCHMARK-DESIGN.md +0 -289
  37. package/benchmark/auto-resolve/BENCHMARK-RESULTS.md +0 -341
  38. package/benchmark/auto-resolve/README.md +0 -696
  39. package/benchmark/auto-resolve/RUBRIC.md +0 -177
  40. package/benchmark/auto-resolve/fixtures/F1-cli-trivial-flag/NOTES.md +0 -34
  41. package/benchmark/auto-resolve/fixtures/F1-cli-trivial-flag/expected.json +0 -68
  42. package/benchmark/auto-resolve/fixtures/F1-cli-trivial-flag/metadata.json +0 -10
  43. package/benchmark/auto-resolve/fixtures/F1-cli-trivial-flag/setup.sh +0 -4
  44. package/benchmark/auto-resolve/fixtures/F1-cli-trivial-flag/spec.md +0 -44
  45. package/benchmark/auto-resolve/fixtures/F1-cli-trivial-flag/task.ko.txt +0 -8
  46. package/benchmark/auto-resolve/fixtures/F1-cli-trivial-flag/task.txt +0 -8
  47. package/benchmark/auto-resolve/fixtures/F10-persist-write-collision/NOTES.md +0 -68
  48. package/benchmark/auto-resolve/fixtures/F10-persist-write-collision/expected.json +0 -60
  49. package/benchmark/auto-resolve/fixtures/F10-persist-write-collision/metadata.json +0 -10
  50. package/benchmark/auto-resolve/fixtures/F10-persist-write-collision/setup.sh +0 -17
  51. package/benchmark/auto-resolve/fixtures/F10-persist-write-collision/spec.md +0 -51
  52. package/benchmark/auto-resolve/fixtures/F10-persist-write-collision/task.txt +0 -9
  53. package/benchmark/auto-resolve/fixtures/F10-persist-write-collision/verifiers/invalid.js +0 -29
  54. package/benchmark/auto-resolve/fixtures/F10-persist-write-collision/verifiers/parallel.js +0 -50
  55. package/benchmark/auto-resolve/fixtures/F11-batch-import-all-or-nothing/NOTES.md +0 -75
  56. package/benchmark/auto-resolve/fixtures/F11-batch-import-all-or-nothing/expected.json +0 -52
  57. package/benchmark/auto-resolve/fixtures/F11-batch-import-all-or-nothing/metadata.json +0 -10
  58. package/benchmark/auto-resolve/fixtures/F11-batch-import-all-or-nothing/setup.sh +0 -171
  59. package/benchmark/auto-resolve/fixtures/F11-batch-import-all-or-nothing/spec.md +0 -50
  60. package/benchmark/auto-resolve/fixtures/F11-batch-import-all-or-nothing/task.txt +0 -9
  61. package/benchmark/auto-resolve/fixtures/F12-webhook-raw-body-signature/NOTES.md +0 -89
  62. package/benchmark/auto-resolve/fixtures/F12-webhook-raw-body-signature/expected.json +0 -74
  63. package/benchmark/auto-resolve/fixtures/F12-webhook-raw-body-signature/metadata.json +0 -10
  64. package/benchmark/auto-resolve/fixtures/F12-webhook-raw-body-signature/setup.sh +0 -251
  65. package/benchmark/auto-resolve/fixtures/F12-webhook-raw-body-signature/spec.md +0 -57
  66. package/benchmark/auto-resolve/fixtures/F12-webhook-raw-body-signature/task.txt +0 -13
  67. package/benchmark/auto-resolve/fixtures/F12-webhook-raw-body-signature/verifiers/replay-malformed-body.js +0 -64
  68. package/benchmark/auto-resolve/fixtures/F15-frozen-diff-race-review/NOTES.md +0 -104
  69. package/benchmark/auto-resolve/fixtures/F15-frozen-diff-race-review/expected.json +0 -46
  70. package/benchmark/auto-resolve/fixtures/F15-frozen-diff-race-review/metadata.json +0 -10
  71. package/benchmark/auto-resolve/fixtures/F15-frozen-diff-race-review/setup.sh +0 -336
  72. package/benchmark/auto-resolve/fixtures/F15-frozen-diff-race-review/spec.md +0 -51
  73. package/benchmark/auto-resolve/fixtures/F15-frozen-diff-race-review/task.txt +0 -9
  74. package/benchmark/auto-resolve/fixtures/F16-cli-quote-tax-rules/NOTES.md +0 -38
  75. package/benchmark/auto-resolve/fixtures/F16-cli-quote-tax-rules/expected.json +0 -64
  76. package/benchmark/auto-resolve/fixtures/F16-cli-quote-tax-rules/metadata.json +0 -10
  77. package/benchmark/auto-resolve/fixtures/F16-cli-quote-tax-rules/setup.sh +0 -32
  78. package/benchmark/auto-resolve/fixtures/F16-cli-quote-tax-rules/spec.md +0 -63
  79. package/benchmark/auto-resolve/fixtures/F16-cli-quote-tax-rules/task.txt +0 -7
  80. package/benchmark/auto-resolve/fixtures/F16-cli-quote-tax-rules/verifiers/exact-success.js +0 -54
  81. package/benchmark/auto-resolve/fixtures/F16-cli-quote-tax-rules/verifiers/no-hardcoded-pricing.js +0 -47
  82. package/benchmark/auto-resolve/fixtures/F16-cli-quote-tax-rules/verifiers/stock-error.js +0 -45
  83. package/benchmark/auto-resolve/fixtures/F2-cli-medium-subcommand/NOTES.md +0 -57
  84. package/benchmark/auto-resolve/fixtures/F2-cli-medium-subcommand/expected-pair-plan-registry.json +0 -170
  85. package/benchmark/auto-resolve/fixtures/F2-cli-medium-subcommand/expected.json +0 -84
  86. package/benchmark/auto-resolve/fixtures/F2-cli-medium-subcommand/metadata.json +0 -21
  87. package/benchmark/auto-resolve/fixtures/F2-cli-medium-subcommand/pair-plan.sample-fail.json +0 -214
  88. package/benchmark/auto-resolve/fixtures/F2-cli-medium-subcommand/pair-plan.sample-pass.json +0 -223
  89. package/benchmark/auto-resolve/fixtures/F2-cli-medium-subcommand/setup.sh +0 -5
  90. package/benchmark/auto-resolve/fixtures/F2-cli-medium-subcommand/spec.md +0 -55
  91. package/benchmark/auto-resolve/fixtures/F2-cli-medium-subcommand/task.txt +0 -14
  92. package/benchmark/auto-resolve/fixtures/F21-cli-scheduler-priority/NOTES.md +0 -39
  93. package/benchmark/auto-resolve/fixtures/F21-cli-scheduler-priority/expected.json +0 -62
  94. package/benchmark/auto-resolve/fixtures/F21-cli-scheduler-priority/metadata.json +0 -10
  95. package/benchmark/auto-resolve/fixtures/F21-cli-scheduler-priority/setup.sh +0 -2
  96. package/benchmark/auto-resolve/fixtures/F21-cli-scheduler-priority/spec.md +0 -67
  97. package/benchmark/auto-resolve/fixtures/F21-cli-scheduler-priority/task.txt +0 -7
  98. package/benchmark/auto-resolve/fixtures/F21-cli-scheduler-priority/verifiers/error-order.js +0 -55
  99. package/benchmark/auto-resolve/fixtures/F21-cli-scheduler-priority/verifiers/priority-blocked.js +0 -48
  100. package/benchmark/auto-resolve/fixtures/F22-cli-ledger-close/NOTES.md +0 -35
  101. package/benchmark/auto-resolve/fixtures/F22-cli-ledger-close/expected.json +0 -56
  102. package/benchmark/auto-resolve/fixtures/F22-cli-ledger-close/metadata.json +0 -10
  103. package/benchmark/auto-resolve/fixtures/F22-cli-ledger-close/setup.sh +0 -2
  104. package/benchmark/auto-resolve/fixtures/F22-cli-ledger-close/spec.md +0 -64
  105. package/benchmark/auto-resolve/fixtures/F22-cli-ledger-close/task.txt +0 -7
  106. package/benchmark/auto-resolve/fixtures/F22-cli-ledger-close/verifiers/conflicting-duplicate.js +0 -34
  107. package/benchmark/auto-resolve/fixtures/F22-cli-ledger-close/verifiers/idempotent-close.js +0 -41
  108. package/benchmark/auto-resolve/fixtures/F23-cli-fulfillment-wave/NOTES.md +0 -39
  109. package/benchmark/auto-resolve/fixtures/F23-cli-fulfillment-wave/expected.json +0 -56
  110. package/benchmark/auto-resolve/fixtures/F23-cli-fulfillment-wave/metadata.json +0 -10
  111. package/benchmark/auto-resolve/fixtures/F23-cli-fulfillment-wave/setup.sh +0 -2
  112. package/benchmark/auto-resolve/fixtures/F23-cli-fulfillment-wave/spec.md +0 -76
  113. package/benchmark/auto-resolve/fixtures/F23-cli-fulfillment-wave/task.txt +0 -7
  114. package/benchmark/auto-resolve/fixtures/F23-cli-fulfillment-wave/verifiers/priority-rollback.js +0 -64
  115. package/benchmark/auto-resolve/fixtures/F23-cli-fulfillment-wave/verifiers/single-warehouse-fefo.js +0 -66
  116. package/benchmark/auto-resolve/fixtures/F25-cli-cart-promotion-rules/NOTES.md +0 -40
  117. package/benchmark/auto-resolve/fixtures/F25-cli-cart-promotion-rules/expected.json +0 -66
  118. package/benchmark/auto-resolve/fixtures/F25-cli-cart-promotion-rules/metadata.json +0 -10
  119. package/benchmark/auto-resolve/fixtures/F25-cli-cart-promotion-rules/setup.sh +0 -36
  120. package/benchmark/auto-resolve/fixtures/F25-cli-cart-promotion-rules/spec.md +0 -71
  121. package/benchmark/auto-resolve/fixtures/F25-cli-cart-promotion-rules/task.txt +0 -7
  122. package/benchmark/auto-resolve/fixtures/F25-cli-cart-promotion-rules/verifiers/catalog-source.js +0 -57
  123. package/benchmark/auto-resolve/fixtures/F25-cli-cart-promotion-rules/verifiers/exact-success.js +0 -63
  124. package/benchmark/auto-resolve/fixtures/F25-cli-cart-promotion-rules/verifiers/stock-error.js +0 -34
  125. package/benchmark/auto-resolve/fixtures/F26-cli-payout-ledger-rules/NOTES.md +0 -31
  126. package/benchmark/auto-resolve/fixtures/F26-cli-payout-ledger-rules/expected.json +0 -68
  127. package/benchmark/auto-resolve/fixtures/F26-cli-payout-ledger-rules/metadata.json +0 -10
  128. package/benchmark/auto-resolve/fixtures/F26-cli-payout-ledger-rules/setup.sh +0 -17
  129. package/benchmark/auto-resolve/fixtures/F26-cli-payout-ledger-rules/spec.md +0 -68
  130. package/benchmark/auto-resolve/fixtures/F26-cli-payout-ledger-rules/task.txt +0 -7
  131. package/benchmark/auto-resolve/fixtures/F26-cli-payout-ledger-rules/verifiers/conflicting-duplicate.js +0 -29
  132. package/benchmark/auto-resolve/fixtures/F26-cli-payout-ledger-rules/verifiers/exact-payout.js +0 -58
  133. package/benchmark/auto-resolve/fixtures/F26-cli-payout-ledger-rules/verifiers/rules-source.js +0 -56
  134. package/benchmark/auto-resolve/fixtures/F3-backend-contract-risk/NOTES.md +0 -35
  135. package/benchmark/auto-resolve/fixtures/F3-backend-contract-risk/expected-pair-plan-registry.json +0 -162
  136. package/benchmark/auto-resolve/fixtures/F3-backend-contract-risk/expected.json +0 -67
  137. package/benchmark/auto-resolve/fixtures/F3-backend-contract-risk/metadata.json +0 -19
  138. package/benchmark/auto-resolve/fixtures/F3-backend-contract-risk/setup.sh +0 -4
  139. package/benchmark/auto-resolve/fixtures/F3-backend-contract-risk/spec.md +0 -55
  140. package/benchmark/auto-resolve/fixtures/F3-backend-contract-risk/task.txt +0 -9
  141. package/benchmark/auto-resolve/fixtures/F31-cli-seat-rebalance/NOTES.md +0 -34
  142. package/benchmark/auto-resolve/fixtures/F31-cli-seat-rebalance/expected.json +0 -57
  143. package/benchmark/auto-resolve/fixtures/F31-cli-seat-rebalance/metadata.json +0 -10
  144. package/benchmark/auto-resolve/fixtures/F31-cli-seat-rebalance/setup.sh +0 -2
  145. package/benchmark/auto-resolve/fixtures/F31-cli-seat-rebalance/spec.md +0 -67
  146. package/benchmark/auto-resolve/fixtures/F31-cli-seat-rebalance/task.txt +0 -7
  147. package/benchmark/auto-resolve/fixtures/F31-cli-seat-rebalance/verifiers/duplicate-event-error.js +0 -35
  148. package/benchmark/auto-resolve/fixtures/F31-cli-seat-rebalance/verifiers/priority-transfer-rollback.js +0 -53
  149. package/benchmark/auto-resolve/fixtures/F32-cli-subscription-renewal/NOTES.md +0 -38
  150. package/benchmark/auto-resolve/fixtures/F32-cli-subscription-renewal/expected.json +0 -57
  151. package/benchmark/auto-resolve/fixtures/F32-cli-subscription-renewal/metadata.json +0 -10
  152. package/benchmark/auto-resolve/fixtures/F32-cli-subscription-renewal/setup.sh +0 -2
  153. package/benchmark/auto-resolve/fixtures/F32-cli-subscription-renewal/spec.md +0 -70
  154. package/benchmark/auto-resolve/fixtures/F32-cli-subscription-renewal/task.txt +0 -3
  155. package/benchmark/auto-resolve/fixtures/F32-cli-subscription-renewal/verifiers/duplicate-renewal-error.js +0 -42
  156. package/benchmark/auto-resolve/fixtures/F32-cli-subscription-renewal/verifiers/priority-credit-rollback.js +0 -70
  157. package/benchmark/auto-resolve/fixtures/F4-web-browser-design/NOTES.md +0 -47
  158. package/benchmark/auto-resolve/fixtures/F4-web-browser-design/expected.json +0 -57
  159. package/benchmark/auto-resolve/fixtures/F4-web-browser-design/metadata.json +0 -10
  160. package/benchmark/auto-resolve/fixtures/F4-web-browser-design/setup.sh +0 -6
  161. package/benchmark/auto-resolve/fixtures/F4-web-browser-design/spec.md +0 -48
  162. package/benchmark/auto-resolve/fixtures/F4-web-browser-design/task.txt +0 -9
  163. package/benchmark/auto-resolve/fixtures/F5-fix-loop-red-green/NOTES.md +0 -45
  164. package/benchmark/auto-resolve/fixtures/F5-fix-loop-red-green/expected.json +0 -65
  165. package/benchmark/auto-resolve/fixtures/F5-fix-loop-red-green/metadata.json +0 -10
  166. package/benchmark/auto-resolve/fixtures/F5-fix-loop-red-green/setup.sh +0 -55
  167. package/benchmark/auto-resolve/fixtures/F5-fix-loop-red-green/spec.md +0 -48
  168. package/benchmark/auto-resolve/fixtures/F5-fix-loop-red-green/task.txt +0 -7
  169. package/benchmark/auto-resolve/fixtures/F6-dep-audit-native-module/NOTES.md +0 -43
  170. package/benchmark/auto-resolve/fixtures/F6-dep-audit-native-module/expected.json +0 -77
  171. package/benchmark/auto-resolve/fixtures/F6-dep-audit-native-module/metadata.json +0 -10
  172. package/benchmark/auto-resolve/fixtures/F6-dep-audit-native-module/setup.sh +0 -4
  173. package/benchmark/auto-resolve/fixtures/F6-dep-audit-native-module/spec.md +0 -48
  174. package/benchmark/auto-resolve/fixtures/F6-dep-audit-native-module/task.txt +0 -10
  175. package/benchmark/auto-resolve/fixtures/F7-out-of-scope-trap/NOTES.md +0 -57
  176. package/benchmark/auto-resolve/fixtures/F7-out-of-scope-trap/expected.json +0 -76
  177. package/benchmark/auto-resolve/fixtures/F7-out-of-scope-trap/metadata.json +0 -10
  178. package/benchmark/auto-resolve/fixtures/F7-out-of-scope-trap/setup.sh +0 -36
  179. package/benchmark/auto-resolve/fixtures/F7-out-of-scope-trap/spec.md +0 -45
  180. package/benchmark/auto-resolve/fixtures/F7-out-of-scope-trap/task.txt +0 -7
  181. package/benchmark/auto-resolve/fixtures/F8-known-limit-ambiguous/NOTES.md +0 -53
  182. package/benchmark/auto-resolve/fixtures/F8-known-limit-ambiguous/expected.json +0 -63
  183. package/benchmark/auto-resolve/fixtures/F8-known-limit-ambiguous/metadata.json +0 -10
  184. package/benchmark/auto-resolve/fixtures/F8-known-limit-ambiguous/setup.sh +0 -4
  185. package/benchmark/auto-resolve/fixtures/F8-known-limit-ambiguous/spec.md +0 -48
  186. package/benchmark/auto-resolve/fixtures/F8-known-limit-ambiguous/task.txt +0 -1
  187. package/benchmark/auto-resolve/fixtures/F9-e2e-ideate-to-resolve/NOTES.md +0 -105
  188. package/benchmark/auto-resolve/fixtures/F9-e2e-ideate-to-resolve/expected.json +0 -74
  189. package/benchmark/auto-resolve/fixtures/F9-e2e-ideate-to-resolve/metadata.json +0 -10
  190. package/benchmark/auto-resolve/fixtures/F9-e2e-ideate-to-resolve/setup.sh +0 -28
  191. package/benchmark/auto-resolve/fixtures/F9-e2e-ideate-to-resolve/spec.md +0 -59
  192. package/benchmark/auto-resolve/fixtures/F9-e2e-ideate-to-resolve/task.txt +0 -5
  193. package/benchmark/auto-resolve/fixtures/SCHEMA.md +0 -188
  194. package/benchmark/auto-resolve/fixtures/retired/F27-cli-subscription-proration/NOTES.md +0 -37
  195. package/benchmark/auto-resolve/fixtures/retired/F27-cli-subscription-proration/RETIRED.md +0 -13
  196. package/benchmark/auto-resolve/fixtures/retired/F27-cli-subscription-proration/expected.json +0 -56
  197. package/benchmark/auto-resolve/fixtures/retired/F27-cli-subscription-proration/metadata.json +0 -10
  198. package/benchmark/auto-resolve/fixtures/retired/F27-cli-subscription-proration/setup.sh +0 -18
  199. package/benchmark/auto-resolve/fixtures/retired/F27-cli-subscription-proration/spec.md +0 -69
  200. package/benchmark/auto-resolve/fixtures/retired/F27-cli-subscription-proration/task.txt +0 -7
  201. package/benchmark/auto-resolve/fixtures/retired/F27-cli-subscription-proration/verifiers/exact-proration.js +0 -48
  202. package/benchmark/auto-resolve/fixtures/retired/F27-cli-subscription-proration/verifiers/rules-source-and-conflict.js +0 -79
  203. package/benchmark/auto-resolve/fixtures/retired/F28-cli-return-authorization/NOTES.md +0 -54
  204. package/benchmark/auto-resolve/fixtures/retired/F28-cli-return-authorization/RETIRED.md +0 -7
  205. package/benchmark/auto-resolve/fixtures/retired/F28-cli-return-authorization/expected.json +0 -67
  206. package/benchmark/auto-resolve/fixtures/retired/F28-cli-return-authorization/metadata.json +0 -10
  207. package/benchmark/auto-resolve/fixtures/retired/F28-cli-return-authorization/setup.sh +0 -2
  208. package/benchmark/auto-resolve/fixtures/retired/F28-cli-return-authorization/spec.md +0 -67
  209. package/benchmark/auto-resolve/fixtures/retired/F28-cli-return-authorization/task.txt +0 -5
  210. package/benchmark/auto-resolve/fixtures/retired/F28-cli-return-authorization/verifiers/policy-precedence.js +0 -72
  211. package/benchmark/auto-resolve/fixtures/retired/F28-cli-return-authorization/verifiers/validation-and-immutability.js +0 -43
  212. package/benchmark/auto-resolve/fixtures/retired/F28-cli-return-authorization/verifiers/validation-boundary.js +0 -116
  213. package/benchmark/auto-resolve/fixtures/retired/F30-cli-credit-hold-settlement/NOTES.md +0 -35
  214. package/benchmark/auto-resolve/fixtures/retired/F30-cli-credit-hold-settlement/RETIRED.md +0 -12
  215. package/benchmark/auto-resolve/fixtures/retired/F30-cli-credit-hold-settlement/expected.json +0 -58
  216. package/benchmark/auto-resolve/fixtures/retired/F30-cli-credit-hold-settlement/metadata.json +0 -10
  217. package/benchmark/auto-resolve/fixtures/retired/F30-cli-credit-hold-settlement/setup.sh +0 -2
  218. package/benchmark/auto-resolve/fixtures/retired/F30-cli-credit-hold-settlement/spec.md +0 -73
  219. package/benchmark/auto-resolve/fixtures/retired/F30-cli-credit-hold-settlement/task.txt +0 -17
  220. package/benchmark/auto-resolve/fixtures/retired/F30-cli-credit-hold-settlement/verifiers/mixed-idempotent-settlement.js +0 -53
  221. package/benchmark/auto-resolve/fixtures/retired/F30-cli-credit-hold-settlement/verifiers/rejection-boundaries.js +0 -74
  222. package/benchmark/auto-resolve/fixtures/retired/F34-cli-settle-inflight/NOTES.md +0 -28
  223. package/benchmark/auto-resolve/fixtures/retired/F34-cli-settle-inflight/RETIRED.md +0 -15
  224. package/benchmark/auto-resolve/fixtures/retired/F34-cli-settle-inflight/expected.json +0 -57
  225. package/benchmark/auto-resolve/fixtures/retired/F34-cli-settle-inflight/metadata.json +0 -10
  226. package/benchmark/auto-resolve/fixtures/retired/F34-cli-settle-inflight/setup.sh +0 -50
  227. package/benchmark/auto-resolve/fixtures/retired/F34-cli-settle-inflight/spec.md +0 -59
  228. package/benchmark/auto-resolve/fixtures/retired/F34-cli-settle-inflight/task.txt +0 -9
  229. package/benchmark/auto-resolve/fixtures/retired/F34-cli-settle-inflight/verifiers/ordered-settlement.js +0 -88
  230. package/benchmark/auto-resolve/fixtures/retired/F34-cli-settle-inflight/verifiers/reject-invalid.js +0 -45
  231. package/benchmark/auto-resolve/fixtures/retired/F35-cli-apply-journal/NOTES.md +0 -30
  232. package/benchmark/auto-resolve/fixtures/retired/F35-cli-apply-journal/RETIRED.md +0 -16
  233. package/benchmark/auto-resolve/fixtures/retired/F35-cli-apply-journal/expected.json +0 -64
  234. package/benchmark/auto-resolve/fixtures/retired/F35-cli-apply-journal/metadata.json +0 -10
  235. package/benchmark/auto-resolve/fixtures/retired/F35-cli-apply-journal/setup.sh +0 -21
  236. package/benchmark/auto-resolve/fixtures/retired/F35-cli-apply-journal/spec.md +0 -58
  237. package/benchmark/auto-resolve/fixtures/retired/F35-cli-apply-journal/task.txt +0 -9
  238. package/benchmark/auto-resolve/fixtures/retired/F35-cli-apply-journal/verifiers/dup-op.js +0 -54
  239. package/benchmark/auto-resolve/fixtures/retired/F35-cli-apply-journal/verifiers/priority-apply.js +0 -82
  240. package/benchmark/auto-resolve/fixtures/retired/F35-cli-apply-journal/verifiers/rollback.js +0 -77
  241. package/benchmark/auto-resolve/fixtures/retired/F36-cli-session-admission/NOTES.md +0 -99
  242. package/benchmark/auto-resolve/fixtures/retired/F36-cli-session-admission/RETIRED.md +0 -18
  243. package/benchmark/auto-resolve/fixtures/retired/F36-cli-session-admission/expected.json +0 -64
  244. package/benchmark/auto-resolve/fixtures/retired/F36-cli-session-admission/metadata.json +0 -10
  245. package/benchmark/auto-resolve/fixtures/retired/F36-cli-session-admission/setup.sh +0 -4
  246. package/benchmark/auto-resolve/fixtures/retired/F36-cli-session-admission/spec.md +0 -61
  247. package/benchmark/auto-resolve/fixtures/retired/F36-cli-session-admission/task.txt +0 -9
  248. package/benchmark/auto-resolve/fixtures/retired/F36-cli-session-admission/verifiers/correctness-small.js +0 -135
  249. package/benchmark/auto-resolve/fixtures/retired/F36-cli-session-admission/verifiers/scale.js +0 -100
  250. package/benchmark/auto-resolve/fixtures/retired/F36-cli-session-admission/verifiers/validation.js +0 -75
  251. package/benchmark/auto-resolve/fixtures/retired/F37-cli-rule-lookup/NOTES.md +0 -93
  252. package/benchmark/auto-resolve/fixtures/retired/F37-cli-rule-lookup/RETIRED.md +0 -16
  253. package/benchmark/auto-resolve/fixtures/retired/F37-cli-rule-lookup/expected.json +0 -65
  254. package/benchmark/auto-resolve/fixtures/retired/F37-cli-rule-lookup/metadata.json +0 -10
  255. package/benchmark/auto-resolve/fixtures/retired/F37-cli-rule-lookup/setup.sh +0 -18
  256. package/benchmark/auto-resolve/fixtures/retired/F37-cli-rule-lookup/spec.md +0 -66
  257. package/benchmark/auto-resolve/fixtures/retired/F37-cli-rule-lookup/task.txt +0 -9
  258. package/benchmark/auto-resolve/fixtures/retired/F37-cli-rule-lookup/verifiers/correctness-small.js +0 -84
  259. package/benchmark/auto-resolve/fixtures/retired/F37-cli-rule-lookup/verifiers/scale.js +0 -184
  260. package/benchmark/auto-resolve/fixtures/retired/F37-cli-rule-lookup/verifiers/validation.js +0 -74
  261. package/benchmark/auto-resolve/fixtures/retired/F9-e2e-ideate-to-preflight/NOTES.md +0 -60
  262. package/benchmark/auto-resolve/fixtures/retired/F9-e2e-ideate-to-preflight/RETIRED.md +0 -29
  263. package/benchmark/auto-resolve/fixtures/retired/F9-e2e-ideate-to-preflight/expected.json +0 -73
  264. package/benchmark/auto-resolve/fixtures/retired/F9-e2e-ideate-to-preflight/metadata.json +0 -10
  265. package/benchmark/auto-resolve/fixtures/retired/F9-e2e-ideate-to-preflight/setup.sh +0 -28
  266. package/benchmark/auto-resolve/fixtures/retired/F9-e2e-ideate-to-preflight/spec.md +0 -58
  267. package/benchmark/auto-resolve/fixtures/retired/F9-e2e-ideate-to-preflight/task.txt +0 -5
  268. package/benchmark/auto-resolve/fixtures/test-repo/README.md +0 -12
  269. package/benchmark/auto-resolve/fixtures/test-repo/bin/cli.js +0 -63
  270. package/benchmark/auto-resolve/fixtures/test-repo/package-lock.json +0 -823
  271. package/benchmark/auto-resolve/fixtures/test-repo/package.json +0 -22
  272. package/benchmark/auto-resolve/fixtures/test-repo/playwright.config.js +0 -17
  273. package/benchmark/auto-resolve/fixtures/test-repo/server/index.js +0 -37
  274. package/benchmark/auto-resolve/fixtures/test-repo/tests/cli.test.js +0 -25
  275. package/benchmark/auto-resolve/fixtures/test-repo/tests/server.test.js +0 -58
  276. package/benchmark/auto-resolve/fixtures/test-repo/web/index.html +0 -37
  277. package/benchmark/auto-resolve/results/20260507-f10-f11-tier1-full-pipeline/headroom-gate.json +0 -25
  278. package/benchmark/auto-resolve/results/20260507-f10-f11-tier1-full-pipeline/headroom-gate.md +0 -10
  279. package/benchmark/auto-resolve/results/20260508-f22-exact-error-headroom/headroom-gate.json +0 -18
  280. package/benchmark/auto-resolve/results/20260508-f22-exact-error-headroom/headroom-gate.md +0 -9
  281. package/benchmark/auto-resolve/results/20260508-f26-headroom/headroom-gate.json +0 -18
  282. package/benchmark/auto-resolve/results/20260508-f26-headroom/headroom-gate.md +0 -9
  283. package/benchmark/auto-resolve/results/20260510-f16-f23-f25-combined-proof/F16-cli-quote-tax-rules/l2_risk_probes/result.json +0 -28
  284. package/benchmark/auto-resolve/results/20260510-f16-f23-f25-combined-proof/F23-cli-fulfillment-wave/l2_risk_probes/result.json +0 -28
  285. package/benchmark/auto-resolve/results/20260510-f16-f23-f25-combined-proof/F25-cli-cart-promotion-rules/l2_risk_probes/result.json +0 -30
  286. package/benchmark/auto-resolve/results/20260510-f16-f23-f25-combined-proof/full-pipeline-pair-gate.json +0 -82
  287. package/benchmark/auto-resolve/results/20260510-f16-f23-f25-combined-proof/full-pipeline-pair-gate.md +0 -18
  288. package/benchmark/auto-resolve/results/20260510-f16-f23-f25-combined-proof/headroom-gate.json +0 -46
  289. package/benchmark/auto-resolve/results/20260510-f16-f23-f25-combined-proof/headroom-gate.md +0 -17
  290. package/benchmark/auto-resolve/results/20260511-f12-webhook-headroom/headroom-gate.json +0 -28
  291. package/benchmark/auto-resolve/results/20260511-f12-webhook-headroom/headroom-gate.md +0 -15
  292. package/benchmark/auto-resolve/results/20260511-f15-concurrency-headroom/headroom-gate.json +0 -28
  293. package/benchmark/auto-resolve/results/20260511-f15-concurrency-headroom/headroom-gate.md +0 -15
  294. package/benchmark/auto-resolve/results/20260511-f21-current-riskprobes-v1/F21-cli-scheduler-priority/l2_risk_probes/result.json +0 -32
  295. package/benchmark/auto-resolve/results/20260511-f21-current-riskprobes-v1/full-pipeline-pair-gate.json +0 -44
  296. package/benchmark/auto-resolve/results/20260511-f21-current-riskprobes-v1/full-pipeline-pair-gate.md +0 -16
  297. package/benchmark/auto-resolve/results/20260511-f21-current-riskprobes-v1/headroom-gate.json +0 -18
  298. package/benchmark/auto-resolve/results/20260511-f21-current-riskprobes-v1/headroom-gate.md +0 -9
  299. package/benchmark/auto-resolve/results/20260511-f3-http-error-headroom/headroom-gate.json +0 -28
  300. package/benchmark/auto-resolve/results/20260511-f3-http-error-headroom/headroom-gate.md +0 -15
  301. package/benchmark/auto-resolve/results/20260512-f2-medium-headroom/headroom-gate.json +0 -28
  302. package/benchmark/auto-resolve/results/20260512-f2-medium-headroom/headroom-gate.md +0 -15
  303. package/benchmark/auto-resolve/results/20260512-f31-seat-rebalance-headroom/headroom-gate.json +0 -28
  304. package/benchmark/auto-resolve/results/20260512-f31-seat-rebalance-headroom/headroom-gate.md +0 -15
  305. package/benchmark/auto-resolve/results/20260512-f32-subscription-renewal-headroom/headroom-gate.json +0 -28
  306. package/benchmark/auto-resolve/results/20260512-f32-subscription-renewal-headroom/headroom-gate.md +0 -15
  307. package/benchmark/auto-resolve/results/20260512-f4-web-headroom/headroom-gate.json +0 -28
  308. package/benchmark/auto-resolve/results/20260512-f4-web-headroom/headroom-gate.md +0 -15
  309. package/benchmark/auto-resolve/results/20260512-f5-fixloop-headroom/headroom-gate.json +0 -28
  310. package/benchmark/auto-resolve/results/20260512-f5-fixloop-headroom/headroom-gate.md +0 -15
  311. package/benchmark/auto-resolve/results/20260512-f6-checksum-headroom/headroom-gate.json +0 -28
  312. package/benchmark/auto-resolve/results/20260512-f6-checksum-headroom/headroom-gate.md +0 -15
  313. package/benchmark/auto-resolve/results/20260512-f7-scope-headroom/headroom-gate.json +0 -28
  314. package/benchmark/auto-resolve/results/20260512-f7-scope-headroom/headroom-gate.md +0 -15
  315. package/benchmark/auto-resolve/results/20260512-f9-e2e-headroom/headroom-gate.json +0 -28
  316. package/benchmark/auto-resolve/results/20260512-f9-e2e-headroom/headroom-gate.md +0 -15
  317. package/benchmark/auto-resolve/run-real-benchmark.md +0 -303
  318. package/benchmark/auto-resolve/scripts/audit-headroom-rejections.py +0 -441
  319. package/benchmark/auto-resolve/scripts/audit-pair-evidence.py +0 -1256
  320. package/benchmark/auto-resolve/scripts/build-pair-eligible-manifest.py +0 -306
  321. package/benchmark/auto-resolve/scripts/check-f9-artifacts.py +0 -268
  322. package/benchmark/auto-resolve/scripts/collect-swebench-predictions.py +0 -108
  323. package/benchmark/auto-resolve/scripts/compile-report.py +0 -493
  324. package/benchmark/auto-resolve/scripts/fetch-swebench-instances.py +0 -129
  325. package/benchmark/auto-resolve/scripts/frozen-verify-gate.py +0 -434
  326. package/benchmark/auto-resolve/scripts/full-pipeline-pair-gate.py +0 -612
  327. package/benchmark/auto-resolve/scripts/headroom-gate.py +0 -378
  328. package/benchmark/auto-resolve/scripts/iter-0033c-compare.py +0 -683
  329. package/benchmark/auto-resolve/scripts/iter-0033c-l1-summary.py +0 -97
  330. package/benchmark/auto-resolve/scripts/judge-opus-pass.sh +0 -542
  331. package/benchmark/auto-resolve/scripts/judge.sh +0 -565
  332. package/benchmark/auto-resolve/scripts/oracle-scope-tier-a.py +0 -256
  333. package/benchmark/auto-resolve/scripts/oracle-scope-tier-b.py +0 -287
  334. package/benchmark/auto-resolve/scripts/oracle-test-fidelity.py +0 -328
  335. package/benchmark/auto-resolve/scripts/pair-candidate-frontier.py +0 -469
  336. package/benchmark/auto-resolve/scripts/pair-plan-idgen.py +0 -401
  337. package/benchmark/auto-resolve/scripts/pair-plan-lint.py +0 -475
  338. package/benchmark/auto-resolve/scripts/pair-rejected-fixtures.sh +0 -103
  339. package/benchmark/auto-resolve/scripts/pair_evidence_contract.py +0 -270
  340. package/benchmark/auto-resolve/scripts/prepare-swebench-frozen-case.py +0 -273
  341. package/benchmark/auto-resolve/scripts/prepare-swebench-frozen-corpus.py +0 -148
  342. package/benchmark/auto-resolve/scripts/prepare-swebench-solver-worktree.py +0 -210
  343. package/benchmark/auto-resolve/scripts/recent-benchmark-summary.py +0 -232
  344. package/benchmark/auto-resolve/scripts/run-fixture.sh +0 -1024
  345. package/benchmark/auto-resolve/scripts/run-frozen-verify-pair.sh +0 -683
  346. package/benchmark/auto-resolve/scripts/run-full-pipeline-pair-candidate.sh +0 -458
  347. package/benchmark/auto-resolve/scripts/run-headroom-candidate.sh +0 -336
  348. package/benchmark/auto-resolve/scripts/run-iter-0033c.sh +0 -208
  349. package/benchmark/auto-resolve/scripts/run-suite.sh +0 -251
  350. package/benchmark/auto-resolve/scripts/run-swebench-frozen-corpus.sh +0 -310
  351. package/benchmark/auto-resolve/scripts/run-swebench-solver-batch.sh +0 -257
  352. package/benchmark/auto-resolve/scripts/ship-gate.py +0 -391
  353. package/benchmark/auto-resolve/scripts/solo-ceiling-avoidance.py +0 -53
  354. package/benchmark/auto-resolve/scripts/solo-headroom-hypothesis.py +0 -77
  355. package/benchmark/auto-resolve/scripts/swebench-frozen-matrix.py +0 -478
  356. package/benchmark/auto-resolve/scripts/test-audit-headroom-rejections.sh +0 -288
  357. package/benchmark/auto-resolve/scripts/test-audit-pair-evidence.sh +0 -1672
  358. package/benchmark/auto-resolve/scripts/test-benchmark-arg-parsing.sh +0 -1015
  359. package/benchmark/auto-resolve/scripts/test-build-pair-eligible-manifest.sh +0 -491
  360. package/benchmark/auto-resolve/scripts/test-check-f9-artifacts.sh +0 -91
  361. package/benchmark/auto-resolve/scripts/test-frozen-verify-gate.sh +0 -517
  362. package/benchmark/auto-resolve/scripts/test-full-pipeline-pair-gate.sh +0 -610
  363. package/benchmark/auto-resolve/scripts/test-headroom-gate.sh +0 -401
  364. package/benchmark/auto-resolve/scripts/test-iter-0033c-compare.sh +0 -525
  365. package/benchmark/auto-resolve/scripts/test-iter-0033c-l1-summary.sh +0 -254
  366. package/benchmark/auto-resolve/scripts/test-lint-fixtures.sh +0 -580
  367. package/benchmark/auto-resolve/scripts/test-pair-candidate-frontier.sh +0 -591
  368. package/benchmark/auto-resolve/scripts/test-run-full-pipeline-pair-candidate.sh +0 -497
  369. package/benchmark/auto-resolve/scripts/test-run-headroom-candidate.sh +0 -401
  370. package/benchmark/auto-resolve/scripts/test-run-swebench-solver-batch.sh +0 -111
  371. package/benchmark/auto-resolve/scripts/test-ship-gate.sh +0 -1189
  372. package/benchmark/auto-resolve/scripts/test-swebench-frozen-case.sh +0 -1221
  373. package/benchmark/auto-resolve/shadow-fixtures/S1-cli-lang-flag/NOTES.md +0 -28
  374. package/benchmark/auto-resolve/shadow-fixtures/S1-cli-lang-flag/expected.json +0 -63
  375. package/benchmark/auto-resolve/shadow-fixtures/S1-cli-lang-flag/metadata.json +0 -10
  376. package/benchmark/auto-resolve/shadow-fixtures/S1-cli-lang-flag/setup.sh +0 -3
  377. package/benchmark/auto-resolve/shadow-fixtures/S1-cli-lang-flag/spec.md +0 -47
  378. package/benchmark/auto-resolve/shadow-fixtures/S1-cli-lang-flag/task.txt +0 -1
  379. package/benchmark/auto-resolve/shadow-fixtures/S2-cli-inventory-reservation/NOTES.md +0 -34
  380. package/benchmark/auto-resolve/shadow-fixtures/S2-cli-inventory-reservation/expected.json +0 -53
  381. package/benchmark/auto-resolve/shadow-fixtures/S2-cli-inventory-reservation/metadata.json +0 -10
  382. package/benchmark/auto-resolve/shadow-fixtures/S2-cli-inventory-reservation/setup.sh +0 -3
  383. package/benchmark/auto-resolve/shadow-fixtures/S2-cli-inventory-reservation/spec.md +0 -50
  384. package/benchmark/auto-resolve/shadow-fixtures/S2-cli-inventory-reservation/task.txt +0 -1
  385. package/benchmark/auto-resolve/shadow-fixtures/S2-cli-inventory-reservation/verifiers/duplicate-order-error.js +0 -27
  386. package/benchmark/auto-resolve/shadow-fixtures/S2-cli-inventory-reservation/verifiers/priority-stock-reservation.js +0 -44
  387. package/benchmark/auto-resolve/shadow-fixtures/S3-cli-ticket-assignment/NOTES.md +0 -34
  388. package/benchmark/auto-resolve/shadow-fixtures/S3-cli-ticket-assignment/expected.json +0 -55
  389. package/benchmark/auto-resolve/shadow-fixtures/S3-cli-ticket-assignment/metadata.json +0 -10
  390. package/benchmark/auto-resolve/shadow-fixtures/S3-cli-ticket-assignment/setup.sh +0 -3
  391. package/benchmark/auto-resolve/shadow-fixtures/S3-cli-ticket-assignment/spec.md +0 -52
  392. package/benchmark/auto-resolve/shadow-fixtures/S3-cli-ticket-assignment/task.txt +0 -1
  393. package/benchmark/auto-resolve/shadow-fixtures/S3-cli-ticket-assignment/verifiers/duplicate-ticket-error.js +0 -29
  394. package/benchmark/auto-resolve/shadow-fixtures/S3-cli-ticket-assignment/verifiers/priority-agent-assignment.js +0 -48
  395. package/benchmark/auto-resolve/shadow-fixtures/S4-cli-return-routing/NOTES.md +0 -34
  396. package/benchmark/auto-resolve/shadow-fixtures/S4-cli-return-routing/expected.json +0 -55
  397. package/benchmark/auto-resolve/shadow-fixtures/S4-cli-return-routing/metadata.json +0 -10
  398. package/benchmark/auto-resolve/shadow-fixtures/S4-cli-return-routing/setup.sh +0 -3
  399. package/benchmark/auto-resolve/shadow-fixtures/S4-cli-return-routing/spec.md +0 -55
  400. package/benchmark/auto-resolve/shadow-fixtures/S4-cli-return-routing/task.txt +0 -1
  401. package/benchmark/auto-resolve/shadow-fixtures/S4-cli-return-routing/verifiers/duplicate-return-error.js +0 -43
  402. package/benchmark/auto-resolve/shadow-fixtures/S4-cli-return-routing/verifiers/priority-return-routing.js +0 -70
  403. package/benchmark/auto-resolve/shadow-fixtures/S5-cli-credit-grant-ledger/NOTES.md +0 -37
  404. package/benchmark/auto-resolve/shadow-fixtures/S5-cli-credit-grant-ledger/expected.json +0 -54
  405. package/benchmark/auto-resolve/shadow-fixtures/S5-cli-credit-grant-ledger/metadata.json +0 -10
  406. package/benchmark/auto-resolve/shadow-fixtures/S5-cli-credit-grant-ledger/setup.sh +0 -3
  407. package/benchmark/auto-resolve/shadow-fixtures/S5-cli-credit-grant-ledger/spec.md +0 -59
  408. package/benchmark/auto-resolve/shadow-fixtures/S5-cli-credit-grant-ledger/task.txt +0 -1
  409. package/benchmark/auto-resolve/shadow-fixtures/S5-cli-credit-grant-ledger/verifiers/credit-ledger-priority.js +0 -98
  410. package/benchmark/auto-resolve/shadow-fixtures/S5-cli-credit-grant-ledger/verifiers/duplicate-charge-error.js +0 -38
  411. package/benchmark/auto-resolve/shadow-fixtures/S6-cli-refund-window-ledger/NOTES.md +0 -36
  412. package/benchmark/auto-resolve/shadow-fixtures/S6-cli-refund-window-ledger/expected.json +0 -56
  413. package/benchmark/auto-resolve/shadow-fixtures/S6-cli-refund-window-ledger/metadata.json +0 -10
  414. package/benchmark/auto-resolve/shadow-fixtures/S6-cli-refund-window-ledger/setup.sh +0 -3
  415. package/benchmark/auto-resolve/shadow-fixtures/S6-cli-refund-window-ledger/spec.md +0 -59
  416. package/benchmark/auto-resolve/shadow-fixtures/S6-cli-refund-window-ledger/task.txt +0 -1
  417. package/benchmark/auto-resolve/shadow-fixtures/S6-cli-refund-window-ledger/verifiers/duplicate-refund-error.js +0 -41
  418. package/benchmark/auto-resolve/shadow-fixtures/S6-cli-refund-window-ledger/verifiers/priority-refund-ledger.js +0 -65
  419. package/config/skills/_shared/pair-plan-schema.md +0 -298
  420. package/scripts/lint-fixtures.sh +0 -352
  421. package/scripts/lint-shadow-fixtures.sh +0 -58
  422. package/scripts/lint-skills.sh +0 -4265
  423. package/scripts/test-owner-phases.py +0 -238
@@ -1,306 +0,0 @@
1
- #!/usr/bin/env python3
2
- """Build the iter-0033c pair-eligible manifest (Codex R0/R0.5 + R0-infra/R0.5-infra).
3
-
4
- Manifest captures the immutable Gate-3 input to iter-0033c-compare.py:
5
- - which fixtures are pair-eligible (high-value ∪ L1≤L0 ∪ F9-if-iter-0033a-passed)
6
- - what the Gate-3 threshold count is
7
- - sha256 over the canonical document so any post-write tampering is detectable
8
-
9
- Hashing pattern is the pre-stamp form lifted from
10
- benchmark/auto-resolve/scripts/pair-plan-lint.py:81-91 — deep-copy the manifest,
11
- zero out `manifest_sha256`, serialize with `sort_keys=True, separators=(",",":"),
12
- ensure_ascii=False, allow_nan=False`, then sha256 the bytes.
13
-
14
- Inputs (all required):
15
- --c1-summary <path> iter-0033 (C1) summary.json (selection grounds; never a comparison baseline)
16
- --f9-judge <path> iter-0033a F9 judge.json (F9 inclusion proof)
17
- --l1-rerun-summary <path> L1 rerun summary archived for provenance, not selection
18
- --output <path> destination .devlyn/manifests/iter-0033c-pair-eligible.json
19
-
20
- Selection rule (frozen pre-registration, iter-0033c §"Pair-eligible fixture set"):
21
- high_value = {F2, F3, F4, F6, F7}
22
- promoted_by_l1_le_l0 = {f ∈ C1 summary | solo_claude.score ≤ bare.score}
23
- conditional_excluded = {F1, F5} # promoted only if L1≤L0
24
- reporting_only = {F8} # excluded from Gate 3
25
- pair_eligible = high_value ∪ promoted_by_l1_le_l0 ∪ {F9 if iter-0033a passed}
26
- − reporting_only
27
- − conditional_excluded that did not get promoted
28
- − current rejected/ceiling registry
29
- """
30
- import argparse
31
- import copy
32
- import hashlib
33
- import json
34
- import re
35
- import subprocess
36
- import sys
37
- from pathlib import Path
38
-
39
- SCRIPT_DIR = Path(__file__).resolve().parent
40
- if str(SCRIPT_DIR) not in sys.path:
41
- sys.path.insert(0, str(SCRIPT_DIR))
42
-
43
- from pair_evidence_contract import is_score, reject_json_constant
44
-
45
- HIGH_VALUE = ["F2", "F3", "F4", "F6", "F7"]
46
- CONDITIONAL = ["F1", "F5"]
47
- REPORTING_ONLY = ["F8"]
48
- REJECTED_REGISTRY = Path(__file__).with_name("pair-rejected-fixtures.sh")
49
-
50
-
51
- def exact_bool(value: object) -> bool | None:
52
- return value if isinstance(value, bool) else None
53
-
54
-
55
- def disqualifier_flag(value: object, *, default: bool = False) -> bool:
56
- if value is None:
57
- return default
58
- parsed = exact_bool(value)
59
- return parsed if parsed is not None else True
60
-
61
-
62
- def file_sha256(path: Path) -> str:
63
- return hashlib.sha256(path.read_bytes()).hexdigest()
64
-
65
-
66
- def canonical_manifest_sha256(manifest: dict) -> str:
67
- """Pre-stamp hash per pair-plan-lint.py:81-91 — zero out the stamp, then sha256."""
68
- pre = copy.deepcopy(manifest)
69
- pre["manifest_sha256"] = ""
70
- s = json.dumps(
71
- pre,
72
- sort_keys=True,
73
- separators=(",", ":"),
74
- ensure_ascii=False,
75
- allow_nan=False,
76
- )
77
- return hashlib.sha256(s.encode("utf-8")).hexdigest()
78
-
79
-
80
- def fixture_short_id(full: str) -> str:
81
- """'F3-backend-contract-risk' -> 'F3'. Pure prefix; matches existing convention."""
82
- return full.split("-", 1)[0] if "-" in full else full
83
-
84
-
85
- def load_rejected_fixture_reasons(path: Path) -> dict[str, str]:
86
- if not path.is_file():
87
- raise ValueError(f"rejected fixture registry not found: {path}")
88
- rejected: dict[str, str] = {}
89
- current: str | None = None
90
- for line in path.read_text().splitlines():
91
- match = re.match(r"\s*([FS]\d+)-\*\|([FS]\d+)\)", line)
92
- if match and match.group(1) == match.group(2):
93
- current = match.group(1)
94
- continue
95
- reason = re.match(r'\s*echo "([^"]+)"', line)
96
- if current and reason:
97
- rejected[current] = reason.group(1)
98
- current = None
99
- return dict(sorted(rejected.items(), key=lambda item: (item[0][0], int(item[0][1:]))))
100
-
101
-
102
- def load_rejected_short_ids(path: Path) -> list[str]:
103
- return list(load_rejected_fixture_reasons(path))
104
-
105
-
106
- def load_json_object(path: Path, label: str) -> dict:
107
- try:
108
- data = json.loads(path.read_text(), parse_constant=reject_json_constant)
109
- except (ValueError, json.JSONDecodeError) as exc:
110
- raise ValueError(f"{label} malformed: invalid JSON") from exc
111
- if not isinstance(data, dict):
112
- raise ValueError(f"{label} malformed: expected object")
113
- return data
114
-
115
-
116
- def compute_promoted_l1_le_l0(c1_rows: list) -> list:
117
- """Return short fixture IDs (e.g. 'F3') where solo_claude.score ≤ bare.score in C1."""
118
- promoted = []
119
- for row in c1_rows:
120
- if not isinstance(row, dict):
121
- continue
122
- raw_arms = row.get("arms")
123
- arms = raw_arms if isinstance(raw_arms, dict) else {}
124
- raw_solo = arms.get("solo_claude")
125
- raw_bare = arms.get("bare")
126
- solo_arm = raw_solo if isinstance(raw_solo, dict) else {}
127
- bare_arm = raw_bare if isinstance(raw_bare, dict) else {}
128
- if (
129
- disqualifier_flag(solo_arm.get("disqualifier"))
130
- or disqualifier_flag(bare_arm.get("disqualifier"))
131
- ):
132
- continue
133
- solo = solo_arm.get("score")
134
- bare = bare_arm.get("score")
135
- if not is_score(solo) or not is_score(bare):
136
- continue
137
- if solo <= bare:
138
- fixture = row.get("fixture")
139
- if isinstance(fixture, str):
140
- promoted.append(fixture_short_id(fixture))
141
- return promoted
142
-
143
-
144
- def mapped_score(judge: dict, arm: str) -> int | None:
145
- mapping = judge.get("_blind_mapping")
146
- if not isinstance(mapping, dict):
147
- return None
148
- letter = next((slot for slot, mapped in mapping.items() if mapped == arm), None)
149
- if letter is None:
150
- return None
151
- raw_scores = judge.get("scores_by_arm")
152
- scores = raw_scores if isinstance(raw_scores, dict) else {}
153
- score = scores.get(arm)
154
- if is_score(score):
155
- return score
156
- legacy = judge.get(f"{letter.lower()}_score")
157
- return legacy if is_score(legacy) else None
158
-
159
-
160
- def mapped_disqualifier(judge: dict, arm: str) -> bool:
161
- mapping = judge.get("_blind_mapping")
162
- if not isinstance(mapping, dict):
163
- return True
164
- letter = next((slot for slot, mapped in mapping.items() if mapped == arm), None)
165
- if letter is None:
166
- return True
167
- raw_by_arm = judge.get("disqualifiers_by_arm")
168
- if raw_by_arm is not None and not isinstance(raw_by_arm, dict):
169
- return True
170
- by_arm = raw_by_arm if isinstance(raw_by_arm, dict) else {}
171
- if arm in by_arm:
172
- entry = by_arm.get(arm)
173
- return disqualifier_flag(
174
- entry.get("disqualifier") if isinstance(entry, dict) else entry
175
- )
176
- raw_legacy = judge.get("disqualifiers")
177
- if raw_legacy is not None and not isinstance(raw_legacy, dict):
178
- return True
179
- legacy = raw_legacy if isinstance(raw_legacy, dict) else {}
180
- return disqualifier_flag(legacy.get(letter))
181
-
182
-
183
- def f9_passed(f9_judge: dict) -> bool:
184
- """iter-0033a passed iff solo_claude beats bare and solo is not disqualified."""
185
- solo = mapped_score(f9_judge, "solo_claude")
186
- bare = mapped_score(f9_judge, "bare")
187
- if solo is None or bare is None:
188
- return False
189
- return solo > bare and not mapped_disqualifier(f9_judge, "solo_claude")
190
-
191
-
192
- def head_sha() -> str:
193
- try:
194
- out = subprocess.check_output(
195
- ["git", "rev-parse", "HEAD"], stderr=subprocess.DEVNULL
196
- )
197
- return out.decode().strip()
198
- except Exception:
199
- return ""
200
-
201
-
202
- def main() -> int:
203
- ap = argparse.ArgumentParser()
204
- ap.add_argument("--c1-summary", required=True)
205
- ap.add_argument("--f9-judge", required=True)
206
- ap.add_argument("--l1-rerun-summary", required=True)
207
- ap.add_argument("--output", required=True)
208
- args = ap.parse_args()
209
-
210
- c1_path = Path(args.c1_summary)
211
- f9_path = Path(args.f9_judge)
212
- l1_path = Path(args.l1_rerun_summary)
213
- out_path = Path(args.output)
214
-
215
- for p, label in [(c1_path, "c1-summary"), (f9_path, "f9-judge"), (l1_path, "l1-rerun-summary")]:
216
- if not p.is_file():
217
- print(f"error: {label} not found: {p}", file=sys.stderr)
218
- return 2
219
-
220
- try:
221
- c1 = load_json_object(c1_path, "c1-summary")
222
- f9 = load_json_object(f9_path, "f9-judge")
223
- rejected_reasons = load_rejected_fixture_reasons(REJECTED_REGISTRY)
224
- rejected_short_ids = list(rejected_reasons)
225
- except ValueError as exc:
226
- print(f"error: {exc}", file=sys.stderr)
227
- return 2
228
-
229
- c1_rows = c1.get("rows")
230
- if not isinstance(c1_rows, list):
231
- print("error: c1-summary malformed: rows must be an array", file=sys.stderr)
232
- return 2
233
-
234
- promoted = compute_promoted_l1_le_l0(c1_rows)
235
- f9_in = f9_passed(f9)
236
-
237
- pair_eligible = list(HIGH_VALUE) # frozen high-value list, ordered
238
- for fx in promoted:
239
- if fx not in pair_eligible and fx not in REPORTING_ONLY:
240
- pair_eligible.append(fx)
241
- if f9_in and "F9" not in pair_eligible:
242
- pair_eligible.append("F9")
243
- pair_eligible = [fx for fx in pair_eligible if fx not in REPORTING_ONLY]
244
- rejected_excluded = sorted(
245
- {fx for fx in pair_eligible if fx in rejected_short_ids},
246
- key=lambda s: (s[0], int(s[1:])),
247
- )
248
- pair_eligible = [fx for fx in pair_eligible if fx not in rejected_short_ids]
249
-
250
- conditional_promoted = [fx for fx in CONDITIONAL if fx in promoted]
251
- conditional_excluded = [fx for fx in CONDITIONAL if fx not in promoted]
252
- pair_eligible_sorted = sorted(pair_eligible, key=lambda s: (s[0], int(s[1:])))
253
- if not pair_eligible_sorted:
254
- rejected_text = ", ".join(rejected_excluded) if rejected_excluded else "none"
255
- print(
256
- "error: no pair-eligible fixtures remain after rejected-registry filtering "
257
- f"(rejected_excluded={rejected_text})",
258
- file=sys.stderr,
259
- )
260
- return 1
261
-
262
- gate3_total = len(pair_eligible_sorted)
263
- gate3_threshold = (gate3_total + 1) // 2 # ≥50% — ceil(gate3_total / 2)
264
-
265
- manifest = {
266
- "schema_version": "1.0",
267
- "iter": "0033c",
268
- "head": head_sha(),
269
- "sources": {
270
- "c1_summary": {"path": str(c1_path), "sha256": file_sha256(c1_path)},
271
- "f9_judge": {"path": str(f9_path), "sha256": file_sha256(f9_path)},
272
- "l1_rerun_summary": {"path": str(l1_path), "sha256": file_sha256(l1_path)},
273
- },
274
- "selection_rule": {
275
- "high_value": HIGH_VALUE,
276
- "promoted_by_l1_le_l0": sorted(set(promoted)),
277
- "f9_included": f9_in,
278
- "f9_passed_iter_0033a": f9_in,
279
- "reporting_only": REPORTING_ONLY,
280
- "conditional_excluded": conditional_excluded,
281
- "conditional_promoted": conditional_promoted,
282
- "rejected_registry": str(REJECTED_REGISTRY),
283
- "rejected_excluded": rejected_excluded,
284
- "rejected_excluded_reasons": {
285
- fixture: rejected_reasons[fixture] for fixture in rejected_excluded
286
- },
287
- },
288
- "fixtures_pair_eligible": pair_eligible_sorted,
289
- "gate3_threshold_count": gate3_threshold,
290
- "gate3_total": gate3_total,
291
- "manifest_sha256": "",
292
- }
293
- manifest["manifest_sha256"] = canonical_manifest_sha256(manifest)
294
-
295
- out_path.parent.mkdir(parents=True, exist_ok=True)
296
- out_path.write_text(json.dumps(manifest, indent=2) + "\n")
297
-
298
- print(f"[manifest] wrote {out_path}")
299
- print(f"[manifest] pair-eligible: {pair_eligible_sorted} "
300
- f"(gate3 ≥ {gate3_threshold} / {gate3_total})")
301
- print(f"[manifest] sha256: {manifest['manifest_sha256']}")
302
- return 0
303
-
304
-
305
- if __name__ == "__main__":
306
- sys.exit(main())
@@ -1,268 +0,0 @@
1
- #!/usr/bin/env python3
2
- """F9 skill-driven arm artifact + transcript fingerprint check.
3
-
4
- Out-of-band per Codex R0.5 §B (iter-0033a): expected.json.verification_commands
5
- apply to ALL arms (run-fixture.sh:472), so a `docs/specs/**` check there would
6
- punish bare. This script runs AFTER run-fixture.sh and asserts skill-driven
7
- arms produced the artifacts the 2-skill ideate→resolve chain should emit.
8
-
9
- Bare arm is exempt by construction.
10
-
11
- Usage:
12
- check-f9-artifacts.py --result-dir <results/<run_id>/F9-e2e-ideate-to-resolve/<arm>>
13
-
14
- Exits:
15
- 0 — all checks pass (or bare arm — exempt).
16
- 1 — skill-driven arm but artifact contract violated.
17
- 2 — invalid invocation (missing args, missing dir).
18
-
19
- Emits a small JSON report at <result-dir>/check-f9-artifacts.json.
20
- """
21
- import argparse
22
- import json
23
- import os
24
- import re
25
- import sys
26
- from pathlib import Path
27
-
28
- from pair_evidence_contract import loads_strict_json_object
29
-
30
-
31
- SKILL_DRIVEN_ARMS = {"variant", "solo_claude", "l2_gated", "l2_risk_probes", "l2_forced"}
32
- EXEMPT_ARMS = {"bare"}
33
-
34
- SPEC_DIR_GLOB = "docs/specs/*/spec.md"
35
- SPEC_EXPECTED_GLOB = "docs/specs/*/spec.expected.json"
36
-
37
- # Transcript fingerprint regexes (negative checks only — `claude -p`
38
- # transcript captures only the agent's final reply, not intermediate
39
- # tool calls; positive resolve invocation evidence lives in state).
40
- RE_AUTO_RESOLVE = re.compile(r"/devlyn:auto-resolve\b")
41
- RE_PREFLIGHT = re.compile(r"/devlyn:preflight\b")
42
-
43
-
44
- def _load_json_object(path: Path) -> tuple[dict | None, str | None]:
45
- try:
46
- data = loads_strict_json_object(path.read_text())
47
- except json.JSONDecodeError as exc:
48
- return None, f"{exc.__class__.__name__}: {exc}"
49
- except ValueError as exc:
50
- if str(exc) == "top-level JSON value must be an object":
51
- return None, "expected JSON object"
52
- return None, f"{exc.__class__.__name__}: {exc}"
53
- return data, None
54
-
55
-
56
- def main() -> int:
57
- p = argparse.ArgumentParser(description=__doc__.split("\n", 1)[0])
58
- p.add_argument("--result-dir", required=True,
59
- help="Path to results/<run_id>/<fixture>/<arm>/")
60
- args = p.parse_args()
61
-
62
- result_dir = Path(args.result_dir)
63
- if not result_dir.is_dir():
64
- print(f"error: result dir not found: {result_dir}", file=sys.stderr)
65
- return 2
66
-
67
- arm = result_dir.name
68
- fixture = result_dir.parent.name
69
-
70
- if fixture != "F9-e2e-ideate-to-resolve":
71
- print(f"error: this script is F9-only (got fixture={fixture})", file=sys.stderr)
72
- return 2
73
-
74
- report = {
75
- "fixture": fixture,
76
- "arm": arm,
77
- "checks": [],
78
- "exempt": False,
79
- "pass": True,
80
- }
81
-
82
- if arm in EXEMPT_ARMS:
83
- report["exempt"] = True
84
- report["checks"].append({"name": "arm-is-bare-exempt", "pass": True})
85
- _write_report(result_dir, report)
86
- return 0
87
-
88
- if arm not in SKILL_DRIVEN_ARMS:
89
- print(f"error: unknown arm '{arm}' (expected one of {SKILL_DRIVEN_ARMS | EXEMPT_ARMS})",
90
- file=sys.stderr)
91
- return 2
92
-
93
- # The fixture's work-dir is referenced from result_dir/timing.json. The
94
- # arm produced files inside that work-dir; we glob from there.
95
- timing_path = result_dir / "timing.json"
96
- work_dir: Path
97
- if timing_path.is_file():
98
- timing, _timing_error = _load_json_object(timing_path)
99
- if timing is not None:
100
- work_dir = Path(timing.get("work_dir", ""))
101
- else:
102
- work_dir = Path("__invalid_timing_work_dir__")
103
- else:
104
- work_dir = Path("__missing_timing_work_dir__")
105
-
106
- if not work_dir.is_dir():
107
- report["checks"].append({
108
- "name": "work-dir-resolvable",
109
- "pass": False,
110
- "reason": f"work_dir from timing.json not usable: {work_dir!r}",
111
- })
112
- report["pass"] = False
113
- _write_report(result_dir, report)
114
- return 1
115
-
116
- # Check 1: docs/specs/<id>-<slug>/spec.md exists.
117
- specs_root = work_dir / "docs" / "specs"
118
- spec_md_files = list(specs_root.glob("*/spec.md")) if specs_root.is_dir() else []
119
- spec_md_present = bool(spec_md_files)
120
- report["checks"].append({
121
- "name": "spec.md-exists-under-docs/specs",
122
- "pass": spec_md_present,
123
- "matched": [str(p.relative_to(work_dir)) for p in spec_md_files],
124
- })
125
- if not spec_md_present:
126
- report["pass"] = False
127
-
128
- # Check 2: spec.expected.json exists at the same dir.
129
- spec_exp_files = list(specs_root.glob("*/spec.expected.json")) if specs_root.is_dir() else []
130
- spec_exp_present = bool(spec_exp_files)
131
- report["checks"].append({
132
- "name": "spec.expected.json-exists-under-docs/specs",
133
- "pass": spec_exp_present,
134
- "matched": [str(p.relative_to(work_dir)) for p in spec_exp_files],
135
- })
136
- if not spec_exp_present:
137
- report["pass"] = False
138
-
139
- # Path-shape regression: the parent dir name should be `<id>-<slug>` shape.
140
- # Both id and slug are kebab-case, so the dir must contain at least one
141
- # hyphen. Bare `<id>/spec.md` (no hyphen) is the legacy shape we reject.
142
- if spec_md_files:
143
- bad_shapes = [p for p in spec_md_files if "-" not in p.parent.name]
144
- report["checks"].append({
145
- "name": "path-shape-id-slug",
146
- "pass": not bad_shapes,
147
- "non_conforming": [str(p.relative_to(work_dir)) for p in bad_shapes],
148
- })
149
- if bad_shapes:
150
- report["pass"] = False
151
-
152
- # Resolve invocation evidence — primary source is pipeline.state.json,
153
- # NOT transcript.txt. `claude -p` only emits the agent's final reply to
154
- # stdout; intermediate Skill / Agent / Bash tool calls do not appear in
155
- # transcript.txt. Therefore "regex /devlyn:resolve --spec in transcript"
156
- # is the wrong source. The authoritative evidence resolve actually ran
157
- # in --spec mode is `state.mode == "spec"` plus `state.source.type ==
158
- # "spec"` plus a populated `state.source.spec_path` pointing under
159
- # `docs/specs/`. Per state-schema.md this is single-source-of-truth.
160
- # Look for the archive first (preferred), then fall back to the live
161
- # in-flight location. NEW resolve currently lands artifacts directly in
162
- # `.devlyn/` and may skip the move-to-runs/ archive step (TODO: separate
163
- # iter to fix archive); both locations carry the same authoritative
164
- # state shape.
165
- archived_paths = list(work_dir.glob(".devlyn/runs/*/pipeline.state.json"))
166
- live_path = work_dir / ".devlyn" / "pipeline.state.json"
167
- state_paths = archived_paths if archived_paths else (
168
- [live_path] if live_path.is_file() else []
169
- )
170
- if not state_paths:
171
- report["checks"].append({
172
- "name": "pipeline.state.json-present",
173
- "pass": False,
174
- "reason": "neither .devlyn/runs/*/pipeline.state.json nor .devlyn/pipeline.state.json found in work_dir",
175
- })
176
- report["pass"] = False
177
- else:
178
- # Read the most recent run.
179
- state_path = sorted(state_paths)[-1]
180
- state, state_error = _load_json_object(state_path)
181
- if state is None:
182
- report["checks"].append({
183
- "name": "pipeline.state.json-parses",
184
- "pass": False,
185
- "reason": state_error,
186
- })
187
- report["pass"] = False
188
-
189
- if state is not None:
190
- archived = "/runs/" in str(state_path)
191
- report["checks"].append({
192
- "name": "pipeline.state.json-present",
193
- "pass": True,
194
- "path": str(state_path.relative_to(work_dir)),
195
- "archived_to_runs_dir": archived,
196
- })
197
- if not archived:
198
- # Not a fail — note for harness developer that NEW resolve
199
- # is skipping the archive step in this run.
200
- report["checks"].append({
201
- "name": "archive-step-completed",
202
- "pass": True,
203
- "warning": "NEW resolve left artifacts in .devlyn/ instead of .devlyn/runs/<id>/ — archive step skipped (separate iter for harness fix)",
204
- })
205
- mode = state.get("mode")
206
- src_type = (state.get("source") or {}).get("type")
207
- spec_path = (state.get("source") or {}).get("spec_path") or ""
208
- spec_under_specs = spec_path.startswith("docs/specs/") and spec_path.endswith("spec.md")
209
- mode_ok = mode == "spec"
210
- src_ok = src_type == "spec"
211
- report["checks"].append({
212
- "name": "state.mode-and-source-spec",
213
- "pass": mode_ok and src_ok and spec_under_specs,
214
- "mode": mode,
215
- "source.type": src_type,
216
- "source.spec_path": spec_path,
217
- })
218
- if not (mode_ok and src_ok and spec_under_specs):
219
- report["pass"] = False
220
-
221
- # Transcript fingerprint — negative checks only. transcript.txt records
222
- # the agent's final reply; if the agent (or any subagent) had invoked
223
- # /devlyn:auto-resolve or /devlyn:preflight, the prompt-following gate
224
- # should still surface the name in the summary. Positive resolve
225
- # evidence lives in state above; here we just rule out the deprecated
226
- # 3-skill chain names.
227
- transcript_path = result_dir / "transcript.txt"
228
- if not transcript_path.is_file():
229
- report["checks"].append({
230
- "name": "transcript-readable",
231
- "pass": False,
232
- "reason": f"transcript.txt missing at {transcript_path}",
233
- })
234
- report["pass"] = False
235
- _write_report(result_dir, report)
236
- return 1
237
-
238
- transcript = transcript_path.read_text(errors="replace")
239
-
240
- auto_resolve_hits = RE_AUTO_RESOLVE.findall(transcript)
241
- report["checks"].append({
242
- "name": "transcript-no-auto-resolve",
243
- "pass": len(auto_resolve_hits) == 0,
244
- "count": len(auto_resolve_hits),
245
- })
246
- if auto_resolve_hits:
247
- report["pass"] = False
248
-
249
- preflight_hits = RE_PREFLIGHT.findall(transcript)
250
- report["checks"].append({
251
- "name": "transcript-no-preflight",
252
- "pass": len(preflight_hits) == 0,
253
- "count": len(preflight_hits),
254
- })
255
- if preflight_hits:
256
- report["pass"] = False
257
-
258
- _write_report(result_dir, report)
259
- return 0 if report["pass"] else 1
260
-
261
-
262
- def _write_report(result_dir: Path, report: dict) -> None:
263
- out_path = result_dir / "check-f9-artifacts.json"
264
- out_path.write_text(json.dumps(report, indent=2) + "\n")
265
-
266
-
267
- if __name__ == "__main__":
268
- sys.exit(main())
@@ -1,108 +0,0 @@
1
- #!/usr/bin/env python3
2
- """Collect patch.diff files into SWE-bench prediction JSONL."""
3
-
4
- from __future__ import annotations
5
-
6
- import argparse
7
- import json
8
- from pathlib import Path
9
- from typing import Any
10
-
11
- from pair_evidence_contract import reject_json_constant
12
-
13
-
14
- def read_jsonl(path: Path) -> list[dict[str, Any]]:
15
- rows: list[dict[str, Any]] = []
16
- with path.open(encoding="utf8") as f:
17
- for line_no, line in enumerate(f, start=1):
18
- if not line.strip():
19
- continue
20
- value = json.loads(line, parse_constant=reject_json_constant)
21
- if not isinstance(value, dict):
22
- raise ValueError(f"{path}:{line_no}: expected JSON object")
23
- rows.append(value)
24
- return rows
25
-
26
-
27
- def instance_ids_from_jsonl(path: Path | None) -> set[str] | None:
28
- if path is None:
29
- return None
30
- ids: set[str] = set()
31
- for row in read_jsonl(path):
32
- instance_id = row.get("instance_id")
33
- if not isinstance(instance_id, str) or not instance_id:
34
- raise ValueError(f"{path}: row missing non-empty instance_id")
35
- ids.add(instance_id)
36
- return ids
37
-
38
-
39
- def collect_from_root(root: Path, patch_name: str, keep: set[str] | None) -> list[tuple[str, Path]]:
40
- patches: list[tuple[str, Path]] = []
41
- seen: set[str] = set()
42
- for patch_path in sorted(root.glob(f"*/{patch_name}")):
43
- instance_id = patch_path.parent.name
44
- if keep is not None and instance_id not in keep:
45
- continue
46
- seen.add(instance_id)
47
- patches.append((instance_id, patch_path))
48
- if keep is not None:
49
- missing = sorted(keep - seen)
50
- if missing:
51
- raise ValueError(f"missing {patch_name} for instance ids: {', '.join(missing)}")
52
- return patches
53
-
54
-
55
- def main() -> int:
56
- parser = argparse.ArgumentParser()
57
- parser.add_argument("--patch-root", required=True, type=Path)
58
- parser.add_argument("--patch-name", default="patch.diff")
59
- parser.add_argument("--instances-jsonl", type=Path, help="Optional filter/validation set.")
60
- parser.add_argument("--model-name", required=True)
61
- parser.add_argument("--out", required=True, type=Path)
62
- parser.add_argument("--allow-empty", action="store_true")
63
- args = parser.parse_args()
64
-
65
- keep = instance_ids_from_jsonl(args.instances_jsonl)
66
- patches = collect_from_root(args.patch_root, args.patch_name, keep)
67
- if not patches:
68
- raise ValueError(f"no {args.patch_name} files found under {args.patch_root}")
69
-
70
- args.out.parent.mkdir(parents=True, exist_ok=True)
71
- written = 0
72
- skipped_empty: list[str] = []
73
- with args.out.open("w", encoding="utf8") as f:
74
- for instance_id, patch_path in patches:
75
- patch = patch_path.read_text(encoding="utf8")
76
- if not patch.strip():
77
- if args.allow_empty:
78
- skipped_empty.append(instance_id)
79
- continue
80
- raise ValueError(f"empty patch for {instance_id}: {patch_path}")
81
- f.write(
82
- json.dumps(
83
- {
84
- "instance_id": instance_id,
85
- "model_name_or_path": args.model_name,
86
- "model_patch": patch,
87
- }
88
- )
89
- + "\n"
90
- )
91
- written += 1
92
- if written == 0:
93
- raise ValueError("no non-empty patches collected")
94
-
95
- report = {
96
- "patch_root": str(args.patch_root),
97
- "patch_name": args.patch_name,
98
- "model_name_or_path": args.model_name,
99
- "out": str(args.out),
100
- "predictions_written": written,
101
- "empty_skipped": skipped_empty,
102
- }
103
- print(json.dumps(report, indent=2))
104
- return 0
105
-
106
-
107
- if __name__ == "__main__":
108
- raise SystemExit(main())