devlyn-cli 3.2.0 → 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 (424) hide show
  1. package/AGENTS.md +2 -2
  2. package/CLAUDE.md +2 -2
  3. package/README.md +22 -113
  4. package/bin/devlyn.js +13 -225
  5. package/bin/instruction-templates.json +752 -1
  6. package/bin/instructions.js +101 -17
  7. package/config/skills/_shared/adapters/grok.md +1 -2
  8. package/config/skills/_shared/archive_run.py +15 -3
  9. package/config/skills/_shared/judge-role-evidence.py +21 -1
  10. package/config/skills/_shared/runtime-principles.md +1 -1
  11. package/config/skills/_shared/spec-verify-check.py +0 -653
  12. package/config/skills/_shared/state-phase-write.py +371 -30
  13. package/config/skills/_shared/task-complete.py +635 -143
  14. package/config/skills/_shared/terminal-claim-check.py +229 -4
  15. package/config/skills/_shared/verify-merge-findings.py +93 -2
  16. package/config/skills/devlyn:ideate/SKILL.md +3 -4
  17. package/config/skills/devlyn:ideate/references/elicitation.md +2 -35
  18. package/config/skills/devlyn:ideate/references/from-spec-mode.md +3 -18
  19. package/config/skills/devlyn:ideate/references/project-mode.md +1 -16
  20. package/config/skills/devlyn:ideate/references/spec-template.md +0 -2
  21. package/config/skills/devlyn:queue/SKILL.md +6 -4
  22. package/config/skills/devlyn:resolve/SKILL.md +16 -25
  23. package/config/skills/devlyn:resolve/references/free-form-mode.md +0 -14
  24. package/config/skills/devlyn:resolve/references/outer-loop.md +1 -1
  25. package/config/skills/devlyn:resolve/references/phases/build-gate.md +1 -1
  26. package/config/skills/devlyn:resolve/references/phases/cleanup.md +3 -3
  27. package/config/skills/devlyn:resolve/references/phases/implement.md +1 -1
  28. package/config/skills/devlyn:resolve/references/phases/probe-derive.md +1 -16
  29. package/config/skills/devlyn:resolve/references/phases/verify.md +4 -9
  30. package/config/skills/devlyn:resolve/references/state-schema.md +9 -7
  31. package/config/skills/devlyn:resolve/references/task-completion.md +46 -37
  32. package/{config/skills → optional-skills}/code-health-standards/SKILL.md +4 -13
  33. package/{config/skills → optional-skills}/code-review-standards/SKILL.md +4 -12
  34. package/{config/skills → optional-skills}/root-cause-analysis/SKILL.md +4 -12
  35. package/{config/skills → optional-skills}/ui-implementation-standards/SKILL.md +4 -14
  36. package/package.json +1 -57
  37. package/benchmark/auto-resolve/BENCHMARK-DESIGN.md +0 -289
  38. package/benchmark/auto-resolve/BENCHMARK-RESULTS.md +0 -341
  39. package/benchmark/auto-resolve/README.md +0 -696
  40. package/benchmark/auto-resolve/RUBRIC.md +0 -177
  41. package/benchmark/auto-resolve/fixtures/F1-cli-trivial-flag/NOTES.md +0 -34
  42. package/benchmark/auto-resolve/fixtures/F1-cli-trivial-flag/expected.json +0 -68
  43. package/benchmark/auto-resolve/fixtures/F1-cli-trivial-flag/metadata.json +0 -10
  44. package/benchmark/auto-resolve/fixtures/F1-cli-trivial-flag/setup.sh +0 -4
  45. package/benchmark/auto-resolve/fixtures/F1-cli-trivial-flag/spec.md +0 -44
  46. package/benchmark/auto-resolve/fixtures/F1-cli-trivial-flag/task.ko.txt +0 -8
  47. package/benchmark/auto-resolve/fixtures/F1-cli-trivial-flag/task.txt +0 -8
  48. package/benchmark/auto-resolve/fixtures/F10-persist-write-collision/NOTES.md +0 -68
  49. package/benchmark/auto-resolve/fixtures/F10-persist-write-collision/expected.json +0 -60
  50. package/benchmark/auto-resolve/fixtures/F10-persist-write-collision/metadata.json +0 -10
  51. package/benchmark/auto-resolve/fixtures/F10-persist-write-collision/setup.sh +0 -17
  52. package/benchmark/auto-resolve/fixtures/F10-persist-write-collision/spec.md +0 -51
  53. package/benchmark/auto-resolve/fixtures/F10-persist-write-collision/task.txt +0 -9
  54. package/benchmark/auto-resolve/fixtures/F10-persist-write-collision/verifiers/invalid.js +0 -29
  55. package/benchmark/auto-resolve/fixtures/F10-persist-write-collision/verifiers/parallel.js +0 -50
  56. package/benchmark/auto-resolve/fixtures/F11-batch-import-all-or-nothing/NOTES.md +0 -75
  57. package/benchmark/auto-resolve/fixtures/F11-batch-import-all-or-nothing/expected.json +0 -52
  58. package/benchmark/auto-resolve/fixtures/F11-batch-import-all-or-nothing/metadata.json +0 -10
  59. package/benchmark/auto-resolve/fixtures/F11-batch-import-all-or-nothing/setup.sh +0 -171
  60. package/benchmark/auto-resolve/fixtures/F11-batch-import-all-or-nothing/spec.md +0 -50
  61. package/benchmark/auto-resolve/fixtures/F11-batch-import-all-or-nothing/task.txt +0 -9
  62. package/benchmark/auto-resolve/fixtures/F12-webhook-raw-body-signature/NOTES.md +0 -89
  63. package/benchmark/auto-resolve/fixtures/F12-webhook-raw-body-signature/expected.json +0 -74
  64. package/benchmark/auto-resolve/fixtures/F12-webhook-raw-body-signature/metadata.json +0 -10
  65. package/benchmark/auto-resolve/fixtures/F12-webhook-raw-body-signature/setup.sh +0 -251
  66. package/benchmark/auto-resolve/fixtures/F12-webhook-raw-body-signature/spec.md +0 -57
  67. package/benchmark/auto-resolve/fixtures/F12-webhook-raw-body-signature/task.txt +0 -13
  68. package/benchmark/auto-resolve/fixtures/F12-webhook-raw-body-signature/verifiers/replay-malformed-body.js +0 -64
  69. package/benchmark/auto-resolve/fixtures/F15-frozen-diff-race-review/NOTES.md +0 -104
  70. package/benchmark/auto-resolve/fixtures/F15-frozen-diff-race-review/expected.json +0 -46
  71. package/benchmark/auto-resolve/fixtures/F15-frozen-diff-race-review/metadata.json +0 -10
  72. package/benchmark/auto-resolve/fixtures/F15-frozen-diff-race-review/setup.sh +0 -336
  73. package/benchmark/auto-resolve/fixtures/F15-frozen-diff-race-review/spec.md +0 -51
  74. package/benchmark/auto-resolve/fixtures/F15-frozen-diff-race-review/task.txt +0 -9
  75. package/benchmark/auto-resolve/fixtures/F16-cli-quote-tax-rules/NOTES.md +0 -38
  76. package/benchmark/auto-resolve/fixtures/F16-cli-quote-tax-rules/expected.json +0 -64
  77. package/benchmark/auto-resolve/fixtures/F16-cli-quote-tax-rules/metadata.json +0 -10
  78. package/benchmark/auto-resolve/fixtures/F16-cli-quote-tax-rules/setup.sh +0 -32
  79. package/benchmark/auto-resolve/fixtures/F16-cli-quote-tax-rules/spec.md +0 -63
  80. package/benchmark/auto-resolve/fixtures/F16-cli-quote-tax-rules/task.txt +0 -7
  81. package/benchmark/auto-resolve/fixtures/F16-cli-quote-tax-rules/verifiers/exact-success.js +0 -54
  82. package/benchmark/auto-resolve/fixtures/F16-cli-quote-tax-rules/verifiers/no-hardcoded-pricing.js +0 -47
  83. package/benchmark/auto-resolve/fixtures/F16-cli-quote-tax-rules/verifiers/stock-error.js +0 -45
  84. package/benchmark/auto-resolve/fixtures/F2-cli-medium-subcommand/NOTES.md +0 -57
  85. package/benchmark/auto-resolve/fixtures/F2-cli-medium-subcommand/expected-pair-plan-registry.json +0 -170
  86. package/benchmark/auto-resolve/fixtures/F2-cli-medium-subcommand/expected.json +0 -84
  87. package/benchmark/auto-resolve/fixtures/F2-cli-medium-subcommand/metadata.json +0 -21
  88. package/benchmark/auto-resolve/fixtures/F2-cli-medium-subcommand/pair-plan.sample-fail.json +0 -214
  89. package/benchmark/auto-resolve/fixtures/F2-cli-medium-subcommand/pair-plan.sample-pass.json +0 -223
  90. package/benchmark/auto-resolve/fixtures/F2-cli-medium-subcommand/setup.sh +0 -5
  91. package/benchmark/auto-resolve/fixtures/F2-cli-medium-subcommand/spec.md +0 -55
  92. package/benchmark/auto-resolve/fixtures/F2-cli-medium-subcommand/task.txt +0 -14
  93. package/benchmark/auto-resolve/fixtures/F21-cli-scheduler-priority/NOTES.md +0 -39
  94. package/benchmark/auto-resolve/fixtures/F21-cli-scheduler-priority/expected.json +0 -62
  95. package/benchmark/auto-resolve/fixtures/F21-cli-scheduler-priority/metadata.json +0 -10
  96. package/benchmark/auto-resolve/fixtures/F21-cli-scheduler-priority/setup.sh +0 -2
  97. package/benchmark/auto-resolve/fixtures/F21-cli-scheduler-priority/spec.md +0 -67
  98. package/benchmark/auto-resolve/fixtures/F21-cli-scheduler-priority/task.txt +0 -7
  99. package/benchmark/auto-resolve/fixtures/F21-cli-scheduler-priority/verifiers/error-order.js +0 -55
  100. package/benchmark/auto-resolve/fixtures/F21-cli-scheduler-priority/verifiers/priority-blocked.js +0 -48
  101. package/benchmark/auto-resolve/fixtures/F22-cli-ledger-close/NOTES.md +0 -35
  102. package/benchmark/auto-resolve/fixtures/F22-cli-ledger-close/expected.json +0 -56
  103. package/benchmark/auto-resolve/fixtures/F22-cli-ledger-close/metadata.json +0 -10
  104. package/benchmark/auto-resolve/fixtures/F22-cli-ledger-close/setup.sh +0 -2
  105. package/benchmark/auto-resolve/fixtures/F22-cli-ledger-close/spec.md +0 -64
  106. package/benchmark/auto-resolve/fixtures/F22-cli-ledger-close/task.txt +0 -7
  107. package/benchmark/auto-resolve/fixtures/F22-cli-ledger-close/verifiers/conflicting-duplicate.js +0 -34
  108. package/benchmark/auto-resolve/fixtures/F22-cli-ledger-close/verifiers/idempotent-close.js +0 -41
  109. package/benchmark/auto-resolve/fixtures/F23-cli-fulfillment-wave/NOTES.md +0 -39
  110. package/benchmark/auto-resolve/fixtures/F23-cli-fulfillment-wave/expected.json +0 -56
  111. package/benchmark/auto-resolve/fixtures/F23-cli-fulfillment-wave/metadata.json +0 -10
  112. package/benchmark/auto-resolve/fixtures/F23-cli-fulfillment-wave/setup.sh +0 -2
  113. package/benchmark/auto-resolve/fixtures/F23-cli-fulfillment-wave/spec.md +0 -76
  114. package/benchmark/auto-resolve/fixtures/F23-cli-fulfillment-wave/task.txt +0 -7
  115. package/benchmark/auto-resolve/fixtures/F23-cli-fulfillment-wave/verifiers/priority-rollback.js +0 -64
  116. package/benchmark/auto-resolve/fixtures/F23-cli-fulfillment-wave/verifiers/single-warehouse-fefo.js +0 -66
  117. package/benchmark/auto-resolve/fixtures/F25-cli-cart-promotion-rules/NOTES.md +0 -40
  118. package/benchmark/auto-resolve/fixtures/F25-cli-cart-promotion-rules/expected.json +0 -66
  119. package/benchmark/auto-resolve/fixtures/F25-cli-cart-promotion-rules/metadata.json +0 -10
  120. package/benchmark/auto-resolve/fixtures/F25-cli-cart-promotion-rules/setup.sh +0 -36
  121. package/benchmark/auto-resolve/fixtures/F25-cli-cart-promotion-rules/spec.md +0 -71
  122. package/benchmark/auto-resolve/fixtures/F25-cli-cart-promotion-rules/task.txt +0 -7
  123. package/benchmark/auto-resolve/fixtures/F25-cli-cart-promotion-rules/verifiers/catalog-source.js +0 -57
  124. package/benchmark/auto-resolve/fixtures/F25-cli-cart-promotion-rules/verifiers/exact-success.js +0 -63
  125. package/benchmark/auto-resolve/fixtures/F25-cli-cart-promotion-rules/verifiers/stock-error.js +0 -34
  126. package/benchmark/auto-resolve/fixtures/F26-cli-payout-ledger-rules/NOTES.md +0 -31
  127. package/benchmark/auto-resolve/fixtures/F26-cli-payout-ledger-rules/expected.json +0 -68
  128. package/benchmark/auto-resolve/fixtures/F26-cli-payout-ledger-rules/metadata.json +0 -10
  129. package/benchmark/auto-resolve/fixtures/F26-cli-payout-ledger-rules/setup.sh +0 -17
  130. package/benchmark/auto-resolve/fixtures/F26-cli-payout-ledger-rules/spec.md +0 -68
  131. package/benchmark/auto-resolve/fixtures/F26-cli-payout-ledger-rules/task.txt +0 -7
  132. package/benchmark/auto-resolve/fixtures/F26-cli-payout-ledger-rules/verifiers/conflicting-duplicate.js +0 -29
  133. package/benchmark/auto-resolve/fixtures/F26-cli-payout-ledger-rules/verifiers/exact-payout.js +0 -58
  134. package/benchmark/auto-resolve/fixtures/F26-cli-payout-ledger-rules/verifiers/rules-source.js +0 -56
  135. package/benchmark/auto-resolve/fixtures/F3-backend-contract-risk/NOTES.md +0 -35
  136. package/benchmark/auto-resolve/fixtures/F3-backend-contract-risk/expected-pair-plan-registry.json +0 -162
  137. package/benchmark/auto-resolve/fixtures/F3-backend-contract-risk/expected.json +0 -67
  138. package/benchmark/auto-resolve/fixtures/F3-backend-contract-risk/metadata.json +0 -19
  139. package/benchmark/auto-resolve/fixtures/F3-backend-contract-risk/setup.sh +0 -4
  140. package/benchmark/auto-resolve/fixtures/F3-backend-contract-risk/spec.md +0 -55
  141. package/benchmark/auto-resolve/fixtures/F3-backend-contract-risk/task.txt +0 -9
  142. package/benchmark/auto-resolve/fixtures/F31-cli-seat-rebalance/NOTES.md +0 -34
  143. package/benchmark/auto-resolve/fixtures/F31-cli-seat-rebalance/expected.json +0 -57
  144. package/benchmark/auto-resolve/fixtures/F31-cli-seat-rebalance/metadata.json +0 -10
  145. package/benchmark/auto-resolve/fixtures/F31-cli-seat-rebalance/setup.sh +0 -2
  146. package/benchmark/auto-resolve/fixtures/F31-cli-seat-rebalance/spec.md +0 -67
  147. package/benchmark/auto-resolve/fixtures/F31-cli-seat-rebalance/task.txt +0 -7
  148. package/benchmark/auto-resolve/fixtures/F31-cli-seat-rebalance/verifiers/duplicate-event-error.js +0 -35
  149. package/benchmark/auto-resolve/fixtures/F31-cli-seat-rebalance/verifiers/priority-transfer-rollback.js +0 -53
  150. package/benchmark/auto-resolve/fixtures/F32-cli-subscription-renewal/NOTES.md +0 -38
  151. package/benchmark/auto-resolve/fixtures/F32-cli-subscription-renewal/expected.json +0 -57
  152. package/benchmark/auto-resolve/fixtures/F32-cli-subscription-renewal/metadata.json +0 -10
  153. package/benchmark/auto-resolve/fixtures/F32-cli-subscription-renewal/setup.sh +0 -2
  154. package/benchmark/auto-resolve/fixtures/F32-cli-subscription-renewal/spec.md +0 -70
  155. package/benchmark/auto-resolve/fixtures/F32-cli-subscription-renewal/task.txt +0 -3
  156. package/benchmark/auto-resolve/fixtures/F32-cli-subscription-renewal/verifiers/duplicate-renewal-error.js +0 -42
  157. package/benchmark/auto-resolve/fixtures/F32-cli-subscription-renewal/verifiers/priority-credit-rollback.js +0 -70
  158. package/benchmark/auto-resolve/fixtures/F4-web-browser-design/NOTES.md +0 -47
  159. package/benchmark/auto-resolve/fixtures/F4-web-browser-design/expected.json +0 -57
  160. package/benchmark/auto-resolve/fixtures/F4-web-browser-design/metadata.json +0 -10
  161. package/benchmark/auto-resolve/fixtures/F4-web-browser-design/setup.sh +0 -6
  162. package/benchmark/auto-resolve/fixtures/F4-web-browser-design/spec.md +0 -48
  163. package/benchmark/auto-resolve/fixtures/F4-web-browser-design/task.txt +0 -9
  164. package/benchmark/auto-resolve/fixtures/F5-fix-loop-red-green/NOTES.md +0 -45
  165. package/benchmark/auto-resolve/fixtures/F5-fix-loop-red-green/expected.json +0 -65
  166. package/benchmark/auto-resolve/fixtures/F5-fix-loop-red-green/metadata.json +0 -10
  167. package/benchmark/auto-resolve/fixtures/F5-fix-loop-red-green/setup.sh +0 -55
  168. package/benchmark/auto-resolve/fixtures/F5-fix-loop-red-green/spec.md +0 -48
  169. package/benchmark/auto-resolve/fixtures/F5-fix-loop-red-green/task.txt +0 -7
  170. package/benchmark/auto-resolve/fixtures/F6-dep-audit-native-module/NOTES.md +0 -43
  171. package/benchmark/auto-resolve/fixtures/F6-dep-audit-native-module/expected.json +0 -77
  172. package/benchmark/auto-resolve/fixtures/F6-dep-audit-native-module/metadata.json +0 -10
  173. package/benchmark/auto-resolve/fixtures/F6-dep-audit-native-module/setup.sh +0 -4
  174. package/benchmark/auto-resolve/fixtures/F6-dep-audit-native-module/spec.md +0 -48
  175. package/benchmark/auto-resolve/fixtures/F6-dep-audit-native-module/task.txt +0 -10
  176. package/benchmark/auto-resolve/fixtures/F7-out-of-scope-trap/NOTES.md +0 -57
  177. package/benchmark/auto-resolve/fixtures/F7-out-of-scope-trap/expected.json +0 -76
  178. package/benchmark/auto-resolve/fixtures/F7-out-of-scope-trap/metadata.json +0 -10
  179. package/benchmark/auto-resolve/fixtures/F7-out-of-scope-trap/setup.sh +0 -36
  180. package/benchmark/auto-resolve/fixtures/F7-out-of-scope-trap/spec.md +0 -45
  181. package/benchmark/auto-resolve/fixtures/F7-out-of-scope-trap/task.txt +0 -7
  182. package/benchmark/auto-resolve/fixtures/F8-known-limit-ambiguous/NOTES.md +0 -53
  183. package/benchmark/auto-resolve/fixtures/F8-known-limit-ambiguous/expected.json +0 -63
  184. package/benchmark/auto-resolve/fixtures/F8-known-limit-ambiguous/metadata.json +0 -10
  185. package/benchmark/auto-resolve/fixtures/F8-known-limit-ambiguous/setup.sh +0 -4
  186. package/benchmark/auto-resolve/fixtures/F8-known-limit-ambiguous/spec.md +0 -48
  187. package/benchmark/auto-resolve/fixtures/F8-known-limit-ambiguous/task.txt +0 -1
  188. package/benchmark/auto-resolve/fixtures/F9-e2e-ideate-to-resolve/NOTES.md +0 -105
  189. package/benchmark/auto-resolve/fixtures/F9-e2e-ideate-to-resolve/expected.json +0 -74
  190. package/benchmark/auto-resolve/fixtures/F9-e2e-ideate-to-resolve/metadata.json +0 -10
  191. package/benchmark/auto-resolve/fixtures/F9-e2e-ideate-to-resolve/setup.sh +0 -28
  192. package/benchmark/auto-resolve/fixtures/F9-e2e-ideate-to-resolve/spec.md +0 -59
  193. package/benchmark/auto-resolve/fixtures/F9-e2e-ideate-to-resolve/task.txt +0 -5
  194. package/benchmark/auto-resolve/fixtures/SCHEMA.md +0 -188
  195. package/benchmark/auto-resolve/fixtures/retired/F27-cli-subscription-proration/NOTES.md +0 -37
  196. package/benchmark/auto-resolve/fixtures/retired/F27-cli-subscription-proration/RETIRED.md +0 -13
  197. package/benchmark/auto-resolve/fixtures/retired/F27-cli-subscription-proration/expected.json +0 -56
  198. package/benchmark/auto-resolve/fixtures/retired/F27-cli-subscription-proration/metadata.json +0 -10
  199. package/benchmark/auto-resolve/fixtures/retired/F27-cli-subscription-proration/setup.sh +0 -18
  200. package/benchmark/auto-resolve/fixtures/retired/F27-cli-subscription-proration/spec.md +0 -69
  201. package/benchmark/auto-resolve/fixtures/retired/F27-cli-subscription-proration/task.txt +0 -7
  202. package/benchmark/auto-resolve/fixtures/retired/F27-cli-subscription-proration/verifiers/exact-proration.js +0 -48
  203. package/benchmark/auto-resolve/fixtures/retired/F27-cli-subscription-proration/verifiers/rules-source-and-conflict.js +0 -79
  204. package/benchmark/auto-resolve/fixtures/retired/F28-cli-return-authorization/NOTES.md +0 -54
  205. package/benchmark/auto-resolve/fixtures/retired/F28-cli-return-authorization/RETIRED.md +0 -7
  206. package/benchmark/auto-resolve/fixtures/retired/F28-cli-return-authorization/expected.json +0 -67
  207. package/benchmark/auto-resolve/fixtures/retired/F28-cli-return-authorization/metadata.json +0 -10
  208. package/benchmark/auto-resolve/fixtures/retired/F28-cli-return-authorization/setup.sh +0 -2
  209. package/benchmark/auto-resolve/fixtures/retired/F28-cli-return-authorization/spec.md +0 -67
  210. package/benchmark/auto-resolve/fixtures/retired/F28-cli-return-authorization/task.txt +0 -5
  211. package/benchmark/auto-resolve/fixtures/retired/F28-cli-return-authorization/verifiers/policy-precedence.js +0 -72
  212. package/benchmark/auto-resolve/fixtures/retired/F28-cli-return-authorization/verifiers/validation-and-immutability.js +0 -43
  213. package/benchmark/auto-resolve/fixtures/retired/F28-cli-return-authorization/verifiers/validation-boundary.js +0 -116
  214. package/benchmark/auto-resolve/fixtures/retired/F30-cli-credit-hold-settlement/NOTES.md +0 -35
  215. package/benchmark/auto-resolve/fixtures/retired/F30-cli-credit-hold-settlement/RETIRED.md +0 -12
  216. package/benchmark/auto-resolve/fixtures/retired/F30-cli-credit-hold-settlement/expected.json +0 -58
  217. package/benchmark/auto-resolve/fixtures/retired/F30-cli-credit-hold-settlement/metadata.json +0 -10
  218. package/benchmark/auto-resolve/fixtures/retired/F30-cli-credit-hold-settlement/setup.sh +0 -2
  219. package/benchmark/auto-resolve/fixtures/retired/F30-cli-credit-hold-settlement/spec.md +0 -73
  220. package/benchmark/auto-resolve/fixtures/retired/F30-cli-credit-hold-settlement/task.txt +0 -17
  221. package/benchmark/auto-resolve/fixtures/retired/F30-cli-credit-hold-settlement/verifiers/mixed-idempotent-settlement.js +0 -53
  222. package/benchmark/auto-resolve/fixtures/retired/F30-cli-credit-hold-settlement/verifiers/rejection-boundaries.js +0 -74
  223. package/benchmark/auto-resolve/fixtures/retired/F34-cli-settle-inflight/NOTES.md +0 -28
  224. package/benchmark/auto-resolve/fixtures/retired/F34-cli-settle-inflight/RETIRED.md +0 -15
  225. package/benchmark/auto-resolve/fixtures/retired/F34-cli-settle-inflight/expected.json +0 -57
  226. package/benchmark/auto-resolve/fixtures/retired/F34-cli-settle-inflight/metadata.json +0 -10
  227. package/benchmark/auto-resolve/fixtures/retired/F34-cli-settle-inflight/setup.sh +0 -50
  228. package/benchmark/auto-resolve/fixtures/retired/F34-cli-settle-inflight/spec.md +0 -59
  229. package/benchmark/auto-resolve/fixtures/retired/F34-cli-settle-inflight/task.txt +0 -9
  230. package/benchmark/auto-resolve/fixtures/retired/F34-cli-settle-inflight/verifiers/ordered-settlement.js +0 -88
  231. package/benchmark/auto-resolve/fixtures/retired/F34-cli-settle-inflight/verifiers/reject-invalid.js +0 -45
  232. package/benchmark/auto-resolve/fixtures/retired/F35-cli-apply-journal/NOTES.md +0 -30
  233. package/benchmark/auto-resolve/fixtures/retired/F35-cli-apply-journal/RETIRED.md +0 -16
  234. package/benchmark/auto-resolve/fixtures/retired/F35-cli-apply-journal/expected.json +0 -64
  235. package/benchmark/auto-resolve/fixtures/retired/F35-cli-apply-journal/metadata.json +0 -10
  236. package/benchmark/auto-resolve/fixtures/retired/F35-cli-apply-journal/setup.sh +0 -21
  237. package/benchmark/auto-resolve/fixtures/retired/F35-cli-apply-journal/spec.md +0 -58
  238. package/benchmark/auto-resolve/fixtures/retired/F35-cli-apply-journal/task.txt +0 -9
  239. package/benchmark/auto-resolve/fixtures/retired/F35-cli-apply-journal/verifiers/dup-op.js +0 -54
  240. package/benchmark/auto-resolve/fixtures/retired/F35-cli-apply-journal/verifiers/priority-apply.js +0 -82
  241. package/benchmark/auto-resolve/fixtures/retired/F35-cli-apply-journal/verifiers/rollback.js +0 -77
  242. package/benchmark/auto-resolve/fixtures/retired/F36-cli-session-admission/NOTES.md +0 -99
  243. package/benchmark/auto-resolve/fixtures/retired/F36-cli-session-admission/RETIRED.md +0 -18
  244. package/benchmark/auto-resolve/fixtures/retired/F36-cli-session-admission/expected.json +0 -64
  245. package/benchmark/auto-resolve/fixtures/retired/F36-cli-session-admission/metadata.json +0 -10
  246. package/benchmark/auto-resolve/fixtures/retired/F36-cli-session-admission/setup.sh +0 -4
  247. package/benchmark/auto-resolve/fixtures/retired/F36-cli-session-admission/spec.md +0 -61
  248. package/benchmark/auto-resolve/fixtures/retired/F36-cli-session-admission/task.txt +0 -9
  249. package/benchmark/auto-resolve/fixtures/retired/F36-cli-session-admission/verifiers/correctness-small.js +0 -135
  250. package/benchmark/auto-resolve/fixtures/retired/F36-cli-session-admission/verifiers/scale.js +0 -100
  251. package/benchmark/auto-resolve/fixtures/retired/F36-cli-session-admission/verifiers/validation.js +0 -75
  252. package/benchmark/auto-resolve/fixtures/retired/F37-cli-rule-lookup/NOTES.md +0 -93
  253. package/benchmark/auto-resolve/fixtures/retired/F37-cli-rule-lookup/RETIRED.md +0 -16
  254. package/benchmark/auto-resolve/fixtures/retired/F37-cli-rule-lookup/expected.json +0 -65
  255. package/benchmark/auto-resolve/fixtures/retired/F37-cli-rule-lookup/metadata.json +0 -10
  256. package/benchmark/auto-resolve/fixtures/retired/F37-cli-rule-lookup/setup.sh +0 -18
  257. package/benchmark/auto-resolve/fixtures/retired/F37-cli-rule-lookup/spec.md +0 -66
  258. package/benchmark/auto-resolve/fixtures/retired/F37-cli-rule-lookup/task.txt +0 -9
  259. package/benchmark/auto-resolve/fixtures/retired/F37-cli-rule-lookup/verifiers/correctness-small.js +0 -84
  260. package/benchmark/auto-resolve/fixtures/retired/F37-cli-rule-lookup/verifiers/scale.js +0 -184
  261. package/benchmark/auto-resolve/fixtures/retired/F37-cli-rule-lookup/verifiers/validation.js +0 -74
  262. package/benchmark/auto-resolve/fixtures/retired/F9-e2e-ideate-to-preflight/NOTES.md +0 -60
  263. package/benchmark/auto-resolve/fixtures/retired/F9-e2e-ideate-to-preflight/RETIRED.md +0 -29
  264. package/benchmark/auto-resolve/fixtures/retired/F9-e2e-ideate-to-preflight/expected.json +0 -73
  265. package/benchmark/auto-resolve/fixtures/retired/F9-e2e-ideate-to-preflight/metadata.json +0 -10
  266. package/benchmark/auto-resolve/fixtures/retired/F9-e2e-ideate-to-preflight/setup.sh +0 -28
  267. package/benchmark/auto-resolve/fixtures/retired/F9-e2e-ideate-to-preflight/spec.md +0 -58
  268. package/benchmark/auto-resolve/fixtures/retired/F9-e2e-ideate-to-preflight/task.txt +0 -5
  269. package/benchmark/auto-resolve/fixtures/test-repo/README.md +0 -12
  270. package/benchmark/auto-resolve/fixtures/test-repo/bin/cli.js +0 -63
  271. package/benchmark/auto-resolve/fixtures/test-repo/package-lock.json +0 -823
  272. package/benchmark/auto-resolve/fixtures/test-repo/package.json +0 -22
  273. package/benchmark/auto-resolve/fixtures/test-repo/playwright.config.js +0 -17
  274. package/benchmark/auto-resolve/fixtures/test-repo/server/index.js +0 -37
  275. package/benchmark/auto-resolve/fixtures/test-repo/tests/cli.test.js +0 -25
  276. package/benchmark/auto-resolve/fixtures/test-repo/tests/server.test.js +0 -58
  277. package/benchmark/auto-resolve/fixtures/test-repo/web/index.html +0 -37
  278. package/benchmark/auto-resolve/results/20260507-f10-f11-tier1-full-pipeline/headroom-gate.json +0 -25
  279. package/benchmark/auto-resolve/results/20260507-f10-f11-tier1-full-pipeline/headroom-gate.md +0 -10
  280. package/benchmark/auto-resolve/results/20260508-f22-exact-error-headroom/headroom-gate.json +0 -18
  281. package/benchmark/auto-resolve/results/20260508-f22-exact-error-headroom/headroom-gate.md +0 -9
  282. package/benchmark/auto-resolve/results/20260508-f26-headroom/headroom-gate.json +0 -18
  283. package/benchmark/auto-resolve/results/20260508-f26-headroom/headroom-gate.md +0 -9
  284. package/benchmark/auto-resolve/results/20260510-f16-f23-f25-combined-proof/F16-cli-quote-tax-rules/l2_risk_probes/result.json +0 -28
  285. package/benchmark/auto-resolve/results/20260510-f16-f23-f25-combined-proof/F23-cli-fulfillment-wave/l2_risk_probes/result.json +0 -28
  286. package/benchmark/auto-resolve/results/20260510-f16-f23-f25-combined-proof/F25-cli-cart-promotion-rules/l2_risk_probes/result.json +0 -30
  287. package/benchmark/auto-resolve/results/20260510-f16-f23-f25-combined-proof/full-pipeline-pair-gate.json +0 -82
  288. package/benchmark/auto-resolve/results/20260510-f16-f23-f25-combined-proof/full-pipeline-pair-gate.md +0 -18
  289. package/benchmark/auto-resolve/results/20260510-f16-f23-f25-combined-proof/headroom-gate.json +0 -46
  290. package/benchmark/auto-resolve/results/20260510-f16-f23-f25-combined-proof/headroom-gate.md +0 -17
  291. package/benchmark/auto-resolve/results/20260511-f12-webhook-headroom/headroom-gate.json +0 -28
  292. package/benchmark/auto-resolve/results/20260511-f12-webhook-headroom/headroom-gate.md +0 -15
  293. package/benchmark/auto-resolve/results/20260511-f15-concurrency-headroom/headroom-gate.json +0 -28
  294. package/benchmark/auto-resolve/results/20260511-f15-concurrency-headroom/headroom-gate.md +0 -15
  295. package/benchmark/auto-resolve/results/20260511-f21-current-riskprobes-v1/F21-cli-scheduler-priority/l2_risk_probes/result.json +0 -32
  296. package/benchmark/auto-resolve/results/20260511-f21-current-riskprobes-v1/full-pipeline-pair-gate.json +0 -44
  297. package/benchmark/auto-resolve/results/20260511-f21-current-riskprobes-v1/full-pipeline-pair-gate.md +0 -16
  298. package/benchmark/auto-resolve/results/20260511-f21-current-riskprobes-v1/headroom-gate.json +0 -18
  299. package/benchmark/auto-resolve/results/20260511-f21-current-riskprobes-v1/headroom-gate.md +0 -9
  300. package/benchmark/auto-resolve/results/20260511-f3-http-error-headroom/headroom-gate.json +0 -28
  301. package/benchmark/auto-resolve/results/20260511-f3-http-error-headroom/headroom-gate.md +0 -15
  302. package/benchmark/auto-resolve/results/20260512-f2-medium-headroom/headroom-gate.json +0 -28
  303. package/benchmark/auto-resolve/results/20260512-f2-medium-headroom/headroom-gate.md +0 -15
  304. package/benchmark/auto-resolve/results/20260512-f31-seat-rebalance-headroom/headroom-gate.json +0 -28
  305. package/benchmark/auto-resolve/results/20260512-f31-seat-rebalance-headroom/headroom-gate.md +0 -15
  306. package/benchmark/auto-resolve/results/20260512-f32-subscription-renewal-headroom/headroom-gate.json +0 -28
  307. package/benchmark/auto-resolve/results/20260512-f32-subscription-renewal-headroom/headroom-gate.md +0 -15
  308. package/benchmark/auto-resolve/results/20260512-f4-web-headroom/headroom-gate.json +0 -28
  309. package/benchmark/auto-resolve/results/20260512-f4-web-headroom/headroom-gate.md +0 -15
  310. package/benchmark/auto-resolve/results/20260512-f5-fixloop-headroom/headroom-gate.json +0 -28
  311. package/benchmark/auto-resolve/results/20260512-f5-fixloop-headroom/headroom-gate.md +0 -15
  312. package/benchmark/auto-resolve/results/20260512-f6-checksum-headroom/headroom-gate.json +0 -28
  313. package/benchmark/auto-resolve/results/20260512-f6-checksum-headroom/headroom-gate.md +0 -15
  314. package/benchmark/auto-resolve/results/20260512-f7-scope-headroom/headroom-gate.json +0 -28
  315. package/benchmark/auto-resolve/results/20260512-f7-scope-headroom/headroom-gate.md +0 -15
  316. package/benchmark/auto-resolve/results/20260512-f9-e2e-headroom/headroom-gate.json +0 -28
  317. package/benchmark/auto-resolve/results/20260512-f9-e2e-headroom/headroom-gate.md +0 -15
  318. package/benchmark/auto-resolve/run-real-benchmark.md +0 -303
  319. package/benchmark/auto-resolve/scripts/audit-headroom-rejections.py +0 -441
  320. package/benchmark/auto-resolve/scripts/audit-pair-evidence.py +0 -1256
  321. package/benchmark/auto-resolve/scripts/build-pair-eligible-manifest.py +0 -306
  322. package/benchmark/auto-resolve/scripts/check-f9-artifacts.py +0 -268
  323. package/benchmark/auto-resolve/scripts/collect-swebench-predictions.py +0 -108
  324. package/benchmark/auto-resolve/scripts/compile-report.py +0 -493
  325. package/benchmark/auto-resolve/scripts/fetch-swebench-instances.py +0 -129
  326. package/benchmark/auto-resolve/scripts/frozen-verify-gate.py +0 -434
  327. package/benchmark/auto-resolve/scripts/full-pipeline-pair-gate.py +0 -612
  328. package/benchmark/auto-resolve/scripts/headroom-gate.py +0 -378
  329. package/benchmark/auto-resolve/scripts/iter-0033c-compare.py +0 -683
  330. package/benchmark/auto-resolve/scripts/iter-0033c-l1-summary.py +0 -97
  331. package/benchmark/auto-resolve/scripts/judge-opus-pass.sh +0 -542
  332. package/benchmark/auto-resolve/scripts/judge.sh +0 -565
  333. package/benchmark/auto-resolve/scripts/oracle-scope-tier-a.py +0 -256
  334. package/benchmark/auto-resolve/scripts/oracle-scope-tier-b.py +0 -287
  335. package/benchmark/auto-resolve/scripts/oracle-test-fidelity.py +0 -328
  336. package/benchmark/auto-resolve/scripts/pair-candidate-frontier.py +0 -469
  337. package/benchmark/auto-resolve/scripts/pair-plan-idgen.py +0 -401
  338. package/benchmark/auto-resolve/scripts/pair-plan-lint.py +0 -475
  339. package/benchmark/auto-resolve/scripts/pair-rejected-fixtures.sh +0 -103
  340. package/benchmark/auto-resolve/scripts/pair_evidence_contract.py +0 -270
  341. package/benchmark/auto-resolve/scripts/prepare-swebench-frozen-case.py +0 -273
  342. package/benchmark/auto-resolve/scripts/prepare-swebench-frozen-corpus.py +0 -148
  343. package/benchmark/auto-resolve/scripts/prepare-swebench-solver-worktree.py +0 -210
  344. package/benchmark/auto-resolve/scripts/recent-benchmark-summary.py +0 -232
  345. package/benchmark/auto-resolve/scripts/run-fixture.sh +0 -1024
  346. package/benchmark/auto-resolve/scripts/run-frozen-verify-pair.sh +0 -683
  347. package/benchmark/auto-resolve/scripts/run-full-pipeline-pair-candidate.sh +0 -458
  348. package/benchmark/auto-resolve/scripts/run-headroom-candidate.sh +0 -336
  349. package/benchmark/auto-resolve/scripts/run-iter-0033c.sh +0 -208
  350. package/benchmark/auto-resolve/scripts/run-suite.sh +0 -251
  351. package/benchmark/auto-resolve/scripts/run-swebench-frozen-corpus.sh +0 -310
  352. package/benchmark/auto-resolve/scripts/run-swebench-solver-batch.sh +0 -257
  353. package/benchmark/auto-resolve/scripts/ship-gate.py +0 -391
  354. package/benchmark/auto-resolve/scripts/solo-ceiling-avoidance.py +0 -53
  355. package/benchmark/auto-resolve/scripts/solo-headroom-hypothesis.py +0 -77
  356. package/benchmark/auto-resolve/scripts/swebench-frozen-matrix.py +0 -478
  357. package/benchmark/auto-resolve/scripts/test-audit-headroom-rejections.sh +0 -288
  358. package/benchmark/auto-resolve/scripts/test-audit-pair-evidence.sh +0 -1672
  359. package/benchmark/auto-resolve/scripts/test-benchmark-arg-parsing.sh +0 -1015
  360. package/benchmark/auto-resolve/scripts/test-build-pair-eligible-manifest.sh +0 -491
  361. package/benchmark/auto-resolve/scripts/test-check-f9-artifacts.sh +0 -91
  362. package/benchmark/auto-resolve/scripts/test-frozen-verify-gate.sh +0 -517
  363. package/benchmark/auto-resolve/scripts/test-full-pipeline-pair-gate.sh +0 -610
  364. package/benchmark/auto-resolve/scripts/test-headroom-gate.sh +0 -401
  365. package/benchmark/auto-resolve/scripts/test-iter-0033c-compare.sh +0 -525
  366. package/benchmark/auto-resolve/scripts/test-iter-0033c-l1-summary.sh +0 -254
  367. package/benchmark/auto-resolve/scripts/test-lint-fixtures.sh +0 -580
  368. package/benchmark/auto-resolve/scripts/test-pair-candidate-frontier.sh +0 -591
  369. package/benchmark/auto-resolve/scripts/test-run-full-pipeline-pair-candidate.sh +0 -497
  370. package/benchmark/auto-resolve/scripts/test-run-headroom-candidate.sh +0 -401
  371. package/benchmark/auto-resolve/scripts/test-run-swebench-solver-batch.sh +0 -111
  372. package/benchmark/auto-resolve/scripts/test-ship-gate.sh +0 -1189
  373. package/benchmark/auto-resolve/scripts/test-swebench-frozen-case.sh +0 -1221
  374. package/benchmark/auto-resolve/shadow-fixtures/S1-cli-lang-flag/NOTES.md +0 -28
  375. package/benchmark/auto-resolve/shadow-fixtures/S1-cli-lang-flag/expected.json +0 -63
  376. package/benchmark/auto-resolve/shadow-fixtures/S1-cli-lang-flag/metadata.json +0 -10
  377. package/benchmark/auto-resolve/shadow-fixtures/S1-cli-lang-flag/setup.sh +0 -3
  378. package/benchmark/auto-resolve/shadow-fixtures/S1-cli-lang-flag/spec.md +0 -47
  379. package/benchmark/auto-resolve/shadow-fixtures/S1-cli-lang-flag/task.txt +0 -1
  380. package/benchmark/auto-resolve/shadow-fixtures/S2-cli-inventory-reservation/NOTES.md +0 -34
  381. package/benchmark/auto-resolve/shadow-fixtures/S2-cli-inventory-reservation/expected.json +0 -53
  382. package/benchmark/auto-resolve/shadow-fixtures/S2-cli-inventory-reservation/metadata.json +0 -10
  383. package/benchmark/auto-resolve/shadow-fixtures/S2-cli-inventory-reservation/setup.sh +0 -3
  384. package/benchmark/auto-resolve/shadow-fixtures/S2-cli-inventory-reservation/spec.md +0 -50
  385. package/benchmark/auto-resolve/shadow-fixtures/S2-cli-inventory-reservation/task.txt +0 -1
  386. package/benchmark/auto-resolve/shadow-fixtures/S2-cli-inventory-reservation/verifiers/duplicate-order-error.js +0 -27
  387. package/benchmark/auto-resolve/shadow-fixtures/S2-cli-inventory-reservation/verifiers/priority-stock-reservation.js +0 -44
  388. package/benchmark/auto-resolve/shadow-fixtures/S3-cli-ticket-assignment/NOTES.md +0 -34
  389. package/benchmark/auto-resolve/shadow-fixtures/S3-cli-ticket-assignment/expected.json +0 -55
  390. package/benchmark/auto-resolve/shadow-fixtures/S3-cli-ticket-assignment/metadata.json +0 -10
  391. package/benchmark/auto-resolve/shadow-fixtures/S3-cli-ticket-assignment/setup.sh +0 -3
  392. package/benchmark/auto-resolve/shadow-fixtures/S3-cli-ticket-assignment/spec.md +0 -52
  393. package/benchmark/auto-resolve/shadow-fixtures/S3-cli-ticket-assignment/task.txt +0 -1
  394. package/benchmark/auto-resolve/shadow-fixtures/S3-cli-ticket-assignment/verifiers/duplicate-ticket-error.js +0 -29
  395. package/benchmark/auto-resolve/shadow-fixtures/S3-cli-ticket-assignment/verifiers/priority-agent-assignment.js +0 -48
  396. package/benchmark/auto-resolve/shadow-fixtures/S4-cli-return-routing/NOTES.md +0 -34
  397. package/benchmark/auto-resolve/shadow-fixtures/S4-cli-return-routing/expected.json +0 -55
  398. package/benchmark/auto-resolve/shadow-fixtures/S4-cli-return-routing/metadata.json +0 -10
  399. package/benchmark/auto-resolve/shadow-fixtures/S4-cli-return-routing/setup.sh +0 -3
  400. package/benchmark/auto-resolve/shadow-fixtures/S4-cli-return-routing/spec.md +0 -55
  401. package/benchmark/auto-resolve/shadow-fixtures/S4-cli-return-routing/task.txt +0 -1
  402. package/benchmark/auto-resolve/shadow-fixtures/S4-cli-return-routing/verifiers/duplicate-return-error.js +0 -43
  403. package/benchmark/auto-resolve/shadow-fixtures/S4-cli-return-routing/verifiers/priority-return-routing.js +0 -70
  404. package/benchmark/auto-resolve/shadow-fixtures/S5-cli-credit-grant-ledger/NOTES.md +0 -37
  405. package/benchmark/auto-resolve/shadow-fixtures/S5-cli-credit-grant-ledger/expected.json +0 -54
  406. package/benchmark/auto-resolve/shadow-fixtures/S5-cli-credit-grant-ledger/metadata.json +0 -10
  407. package/benchmark/auto-resolve/shadow-fixtures/S5-cli-credit-grant-ledger/setup.sh +0 -3
  408. package/benchmark/auto-resolve/shadow-fixtures/S5-cli-credit-grant-ledger/spec.md +0 -59
  409. package/benchmark/auto-resolve/shadow-fixtures/S5-cli-credit-grant-ledger/task.txt +0 -1
  410. package/benchmark/auto-resolve/shadow-fixtures/S5-cli-credit-grant-ledger/verifiers/credit-ledger-priority.js +0 -98
  411. package/benchmark/auto-resolve/shadow-fixtures/S5-cli-credit-grant-ledger/verifiers/duplicate-charge-error.js +0 -38
  412. package/benchmark/auto-resolve/shadow-fixtures/S6-cli-refund-window-ledger/NOTES.md +0 -36
  413. package/benchmark/auto-resolve/shadow-fixtures/S6-cli-refund-window-ledger/expected.json +0 -56
  414. package/benchmark/auto-resolve/shadow-fixtures/S6-cli-refund-window-ledger/metadata.json +0 -10
  415. package/benchmark/auto-resolve/shadow-fixtures/S6-cli-refund-window-ledger/setup.sh +0 -3
  416. package/benchmark/auto-resolve/shadow-fixtures/S6-cli-refund-window-ledger/spec.md +0 -59
  417. package/benchmark/auto-resolve/shadow-fixtures/S6-cli-refund-window-ledger/task.txt +0 -1
  418. package/benchmark/auto-resolve/shadow-fixtures/S6-cli-refund-window-ledger/verifiers/duplicate-refund-error.js +0 -41
  419. package/benchmark/auto-resolve/shadow-fixtures/S6-cli-refund-window-ledger/verifiers/priority-refund-ledger.js +0 -65
  420. package/config/skills/_shared/pair-plan-schema.md +0 -298
  421. package/scripts/lint-fixtures.sh +0 -352
  422. package/scripts/lint-shadow-fixtures.sh +0 -58
  423. package/scripts/lint-skills.sh +0 -4265
  424. package/scripts/test-owner-phases.py +0 -193
@@ -1,257 +0,0 @@
1
- #!/usr/bin/env bash
2
- # Prepare SWE-bench solver worktrees, run a direct solver, and collect patches.
3
- set -euo pipefail
4
-
5
- usage() {
6
- cat >&2 <<EOF
7
- usage: $0 --instances-jsonl <path> --predictions-out <path>
8
- [--instance-id ID ...] [--limit N] [--model-name NAME]
9
- [--repos-root <path>] [--worktrees-root <path>]
10
- [--timeout-seconds N] [--copy-devlyn-context] [--resume]
11
-
12
- Runs Claude Code directly against each selected SWE-bench instance without
13
- reading gold patch/test_patch fields. Each worktree receives patch.diff plus
14
- direct-transcript.txt and claude-direct-debug.log. At the end, patch.diff files
15
- are collected into a SWE-bench predictions JSONL.
16
- EOF
17
- exit "${1:-1}"
18
- }
19
-
20
- INSTANCES_JSONL=""
21
- PREDICTIONS_OUT=""
22
- MODEL_NAME="claude-direct"
23
- REPOS_ROOT="benchmark/auto-resolve/external/swebench/repos-solver"
24
- WORKTREES_ROOT="benchmark/auto-resolve/external/swebench/worktrees"
25
- TIMEOUT_SECONDS=2400
26
- COPY_DEVLYN_CONTEXT=0
27
- RESUME=0
28
- LIMIT=""
29
- INSTANCE_IDS=()
30
-
31
- require_value() {
32
- local flag="$1"
33
- local value="${2:-}"
34
- if [ -z "$value" ] || [[ "$value" == --* ]]; then
35
- echo "$flag requires a value" >&2
36
- exit 1
37
- fi
38
- }
39
-
40
- while [ $# -gt 0 ]; do
41
- case "$1" in
42
- --instances-jsonl) require_value "$1" "${2:-}"; INSTANCES_JSONL="$2"; shift 2;;
43
- --predictions-out) require_value "$1" "${2:-}"; PREDICTIONS_OUT="$2"; shift 2;;
44
- --model-name) require_value "$1" "${2:-}"; MODEL_NAME="$2"; shift 2;;
45
- --repos-root) require_value "$1" "${2:-}"; REPOS_ROOT="$2"; shift 2;;
46
- --worktrees-root) require_value "$1" "${2:-}"; WORKTREES_ROOT="$2"; shift 2;;
47
- --timeout-seconds) require_value "$1" "${2:-}"; TIMEOUT_SECONDS="$2"; shift 2;;
48
- --copy-devlyn-context) COPY_DEVLYN_CONTEXT=1; shift;;
49
- --resume) RESUME=1; shift;;
50
- --limit) require_value "$1" "${2:-}"; LIMIT="$2"; shift 2;;
51
- --instance-id) require_value "$1" "${2:-}"; INSTANCE_IDS+=("$2"); shift 2;;
52
- -h|--help) usage 0;;
53
- *) echo "unknown arg: $1" >&2; usage 1;;
54
- esac
55
- done
56
-
57
- [ -n "$INSTANCES_JSONL" ] || usage 1
58
- [ -n "$PREDICTIONS_OUT" ] || usage 1
59
- [ -f "$INSTANCES_JSONL" ] || { echo "instances JSONL not found: $INSTANCES_JSONL" >&2; exit 1; }
60
- case "$TIMEOUT_SECONDS" in ''|*[!0-9]*) echo "--timeout-seconds must be an integer" >&2; exit 1;; esac
61
- [ "$TIMEOUT_SECONDS" -gt 0 ] || { echo "--timeout-seconds must be > 0" >&2; exit 1; }
62
- if [ -n "$LIMIT" ]; then
63
- case "$LIMIT" in ''|*[!0-9]*) echo "--limit must be an integer" >&2; exit 1;; esac
64
- [ "$LIMIT" -gt 0 ] || { echo "--limit must be > 0" >&2; exit 1; }
65
- fi
66
- command -v claude >/dev/null 2>&1 || { echo "claude command not found" >&2; exit 1; }
67
- mkdir -p "$REPOS_ROOT" "$WORKTREES_ROOT" "$(dirname "$PREDICTIONS_OUT")"
68
-
69
- SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
70
- TMP_IDS="$(mktemp)"
71
- TMP_SELECTED_INSTANCES="$(mktemp)"
72
- trap 'rm -f "$TMP_IDS" "$TMP_SELECTED_INSTANCES"' EXIT
73
-
74
- selection_args=("$INSTANCES_JSONL" "$TMP_SELECTED_INSTANCES" "$LIMIT")
75
- if [ "${#INSTANCE_IDS[@]}" -gt 0 ]; then
76
- selection_args+=("${INSTANCE_IDS[@]}")
77
- fi
78
-
79
- python3 - "$SCRIPT_DIR" "${selection_args[@]}" > "$TMP_IDS" <<'PY'
80
- import json
81
- import sys
82
- from pathlib import Path
83
- sys.path.insert(0, sys.argv[1])
84
- from pair_evidence_contract import reject_json_constant
85
-
86
- instances_path = Path(sys.argv[2])
87
- selected_path = Path(sys.argv[3])
88
- limit = int(sys.argv[4]) if sys.argv[4] else None
89
- requested = sys.argv[5:]
90
- requested_set = set(requested)
91
- rows = []
92
- with instances_path.open(encoding="utf8") as f:
93
- for line_no, line in enumerate(f, start=1):
94
- if not line.strip():
95
- continue
96
- row = json.loads(line, parse_constant=reject_json_constant)
97
- if not isinstance(row, dict):
98
- raise SystemExit(f"{instances_path}:{line_no}: expected JSON object")
99
- instance_id = row.get("instance_id")
100
- if not isinstance(instance_id, str) or not instance_id:
101
- raise SystemExit(f"{instances_path}:{line_no}: missing instance_id")
102
- if requested_set and instance_id not in requested_set:
103
- continue
104
- rows.append(row)
105
- if limit is not None and len(rows) >= limit:
106
- break
107
- if requested_set:
108
- missing = sorted(requested_set - {row["instance_id"] for row in rows})
109
- if missing:
110
- raise SystemExit(f"requested instance ids not found: {', '.join(missing)}")
111
- for instance_id in rows:
112
- print(instance_id["instance_id"])
113
- with selected_path.open("w", encoding="utf8") as f:
114
- for row in rows:
115
- f.write(json.dumps(row) + "\n")
116
- PY
117
-
118
- run_solver() {
119
- local worktree
120
- worktree="$(cd "$1" && pwd -P)"
121
- local timeout_seconds="$2"
122
- local prompt_file="$worktree/solve-prompt.txt"
123
- local transcript="$worktree/direct-transcript.txt"
124
- local debug_log="$worktree/claude-direct-debug.log"
125
- local timeout_flag="$worktree/.solver-timed-out"
126
-
127
- rm -f "$transcript" "$debug_log" "$timeout_flag"
128
- set +e
129
- set -m
130
- (
131
- cd "$worktree"
132
- exec claude \
133
- -p "$(cat "$prompt_file")" \
134
- --dangerously-skip-permissions \
135
- --effort xhigh \
136
- --strict-mcp-config \
137
- --mcp-config '{"mcpServers":{}}' \
138
- --debug-file "$debug_log" \
139
- </dev/null
140
- ) > "$transcript" 2>&1 &
141
- local child_pid=$!
142
- set +m
143
-
144
- (
145
- sleep "$timeout_seconds"
146
- if kill -0 "$child_pid" 2>/dev/null; then
147
- : > "$timeout_flag"
148
- kill -TERM -- "-$child_pid" 2>/dev/null
149
- sleep 5
150
- kill -KILL -- "-$child_pid" 2>/dev/null
151
- fi
152
- ) &
153
- local watchdog_pid=$!
154
-
155
- wait "$child_pid"
156
- local invoke_exit=$?
157
- kill -TERM "$watchdog_pid" 2>/dev/null || true
158
- wait "$watchdog_pid" 2>/dev/null || true
159
-
160
- if [ -f "$timeout_flag" ]; then
161
- rm -f "$timeout_flag"
162
- invoke_exit=124
163
- fi
164
- set -e
165
- return "$invoke_exit"
166
- }
167
-
168
- write_patch() {
169
- local worktree
170
- worktree="$(cd "$1" && pwd -P)"
171
- (
172
- cd "$worktree"
173
- git add -N -- . \
174
- ':(exclude).claude/**' \
175
- ':(exclude)CLAUDE.md' \
176
- ':(exclude)benchmark/**' \
177
- ':(exclude)docs/roadmap/phase-1/*.md' \
178
- ':(exclude)solve-prompt.txt' \
179
- ':(exclude)direct-transcript.txt' \
180
- ':(exclude)claude-direct-debug.log' \
181
- ':(exclude)latest' \
182
- ':(exclude).solver-timed-out' >/dev/null 2>&1 || true
183
- git diff --binary -- . \
184
- ':(exclude).claude/**' \
185
- ':(exclude)CLAUDE.md' \
186
- ':(exclude)benchmark/**' \
187
- ':(exclude)docs/roadmap/phase-1/*.md' \
188
- ':(exclude)solve-prompt.txt' \
189
- ':(exclude)direct-transcript.txt' \
190
- ':(exclude)claude-direct-debug.log' \
191
- ':(exclude)latest' \
192
- ':(exclude).solver-timed-out' > patch.diff
193
- )
194
- }
195
-
196
- while IFS= read -r instance_id; do
197
- [ -n "$instance_id" ] || continue
198
- worktree="$WORKTREES_ROOT/$instance_id"
199
- if [ "$RESUME" -eq 1 ] && [ -s "$worktree/patch.diff" ]; then
200
- echo "[swebench-solver] skip existing patch: $instance_id"
201
- continue
202
- fi
203
-
204
- echo "[swebench-solver] prepare: $instance_id"
205
- prepare_cmd=(
206
- python3 "$SCRIPT_DIR/prepare-swebench-solver-worktree.py"
207
- --instances-jsonl "$INSTANCES_JSONL"
208
- --instance-id "$instance_id"
209
- --repos-root "$REPOS_ROOT"
210
- --worktrees-root "$WORKTREES_ROOT"
211
- )
212
- if [ "$COPY_DEVLYN_CONTEXT" -eq 1 ]; then
213
- prepare_cmd+=(--copy-devlyn-context)
214
- fi
215
- "${prepare_cmd[@]}" > "$worktree.prepare.json"
216
-
217
- echo "[swebench-solver] solve: $instance_id"
218
- if run_solver "$worktree" "$TIMEOUT_SECONDS"; then
219
- invoke_exit=0
220
- else
221
- invoke_exit=$?
222
- fi
223
- write_patch "$worktree"
224
- python3 - "$worktree" "$instance_id" "$invoke_exit" <<'PY'
225
- import json
226
- import subprocess
227
- import sys
228
- from pathlib import Path
229
-
230
- worktree = Path(sys.argv[1])
231
- instance_id = sys.argv[2]
232
- invoke_exit = int(sys.argv[3])
233
- patch = worktree / "patch.diff"
234
- stat = subprocess.run(
235
- ["git", "-C", str(worktree), "diff", "--stat", "--", "."],
236
- text=True,
237
- capture_output=True,
238
- check=False,
239
- )
240
- report = {
241
- "instance_id": instance_id,
242
- "invoke_exit": invoke_exit,
243
- "patch_path": str(patch),
244
- "patch_bytes": patch.stat().st_size if patch.exists() else 0,
245
- "diff_stat": stat.stdout.strip(),
246
- }
247
- (worktree / "solver-result.json").write_text(json.dumps(report, indent=2) + "\n", encoding="utf8")
248
- print(json.dumps(report, indent=2))
249
- PY
250
- done < "$TMP_IDS"
251
-
252
- python3 "$SCRIPT_DIR/collect-swebench-predictions.py" \
253
- --patch-root "$WORKTREES_ROOT" \
254
- --instances-jsonl "$TMP_SELECTED_INSTANCES" \
255
- --model-name "$MODEL_NAME" \
256
- --out "$PREDICTIONS_OUT" \
257
- --allow-empty
@@ -1,391 +0,0 @@
1
- #!/usr/bin/env python3
2
- """
3
- ship-gate.py — apply RUBRIC.md ship thresholds to a suite run's summary.json.
4
-
5
- Usage:
6
- ship-gate.py --run-id <ID> # check gates, return 0/1 via exit code
7
- ship-gate.py --run-id <ID> --bless # if PASS, promote summary to baselines/shipped.json
8
-
9
- Exits 0 on PASS, 1 on FAIL.
10
- """
11
- from __future__ import annotations
12
- import argparse, json, pathlib, sys, shutil, datetime
13
-
14
- SCRIPT_DIR = pathlib.Path(__file__).resolve().parent
15
- if str(SCRIPT_DIR) not in sys.path:
16
- sys.path.insert(0, str(SCRIPT_DIR))
17
-
18
- from pair_evidence_contract import reject_json_constant
19
-
20
-
21
- def load_dict_json(path: pathlib.Path) -> tuple[dict | None, str | None]:
22
- try:
23
- data = json.loads(path.read_text(), parse_constant=reject_json_constant)
24
- except (ValueError, json.JSONDecodeError):
25
- return None, "invalid JSON"
26
- if not isinstance(data, dict):
27
- return None, "expected object"
28
- return data, None
29
-
30
-
31
- def object_or_empty(value) -> dict:
32
- return value if isinstance(value, dict) else {}
33
-
34
-
35
- def rows_from_summary(summary: dict, failures: list[str]) -> list[dict]:
36
- raw_rows = summary.get("rows")
37
- if not isinstance(raw_rows, list):
38
- failures.append("summary rows missing or malformed — measurement invalid")
39
- return []
40
- rows = [row for row in raw_rows if isinstance(row, dict)]
41
- if len(rows) != len(raw_rows):
42
- failures.append("summary rows contain non-object entries — measurement invalid")
43
- return rows
44
-
45
-
46
- def int_or_none(value) -> int | None:
47
- return value if isinstance(value, int) and not isinstance(value, bool) else None
48
-
49
-
50
- def number_or_none(value) -> int | float | None:
51
- if isinstance(value, bool):
52
- return None
53
- return value if isinstance(value, (int, float)) else None
54
-
55
-
56
- def bool_or_none(value) -> bool | None:
57
- return value if isinstance(value, bool) else None
58
-
59
-
60
- def axis_invalid_count(rows: list[dict], arm: str, failures: list[str]) -> int:
61
- total = 0
62
- for row in rows:
63
- arms = object_or_empty(row.get("arms"))
64
- payload = object_or_empty(arms.get(arm))
65
- raw_count = payload.get("_axis_validation_out_of_range_count", 0)
66
- count = number_or_none(raw_count)
67
- if count is None:
68
- failures.append(f"{arm} axis count malformed — measurement invalid")
69
- elif count > 0:
70
- total += 1
71
- return total
72
-
73
-
74
- def unmapped_axis_invalid_count(rows: list[dict], failures: list[str]) -> int:
75
- total = 0
76
- for row in rows:
77
- raw_count = row.get("_axis_validation_unmapped_out_of_range_count", 0)
78
- count = number_or_none(raw_count)
79
- if count is None:
80
- failures.append("unmapped axis count malformed — measurement invalid")
81
- elif count > 0:
82
- total += 1
83
- return total
84
-
85
-
86
- def is_known_limit(row: dict) -> bool:
87
- raw_category = row.get("category")
88
- category = raw_category.lower() if isinstance(raw_category, str) else ""
89
- return category in {"edge", "known-limit"}
90
-
91
-
92
- def main() -> int:
93
- p = argparse.ArgumentParser()
94
- p.add_argument("--run-id", required=True)
95
- p.add_argument("--bless", action="store_true")
96
- p.add_argument("--accept-missing", action="store_true",
97
- help="skip hard-floor gates that require fixtures not yet implemented "
98
- "(F9 and the 7-of-9 count) — only for suites in bootstrap")
99
- args = p.parse_args()
100
-
101
- root = pathlib.Path(__file__).resolve().parent.parent
102
- summary_p = root / "results" / args.run_id / "summary.json"
103
- if not summary_p.exists():
104
- print(f"no summary at {summary_p}", file=sys.stderr); return 1
105
- summary, summary_error = load_dict_json(summary_p)
106
- if summary is None:
107
- print(f"measurement invalid: malformed summary.json ({summary_error})", file=sys.stderr)
108
- return 1
109
-
110
- baseline_p = root / "history" / "baselines" / "shipped.json"
111
- baseline = None
112
- if baseline_p.exists():
113
- baseline, _ = load_dict_json(baseline_p)
114
- if baseline is None:
115
- baseline = None
116
-
117
- failures: list[str] = []
118
- warnings: list[str] = []
119
- rows = rows_from_summary(summary, failures)
120
-
121
- # Hard floor 1: no disqualifier in variant
122
- hard_floor_violations = int_or_none(summary.get("hard_floor_violations"))
123
- if hard_floor_violations is None:
124
- failures.append("summary hard_floor_violations missing or malformed — measurement invalid")
125
- elif hard_floor_violations > 0:
126
- failures.append(f"{hard_floor_violations} variant disqualifier(s) — see report")
127
- variant_axis_invalid = axis_invalid_count(rows, "variant", failures)
128
- if variant_axis_invalid > 0:
129
- failures.append(
130
- f"variant axis-invalid: {variant_axis_invalid} fixture(s) have out-of-range axis cells — "
131
- "re-judge before trusting L2 margins"
132
- )
133
- bare_axis_invalid = axis_invalid_count(rows, "bare", failures)
134
- if bare_axis_invalid > 0:
135
- failures.append(
136
- f"bare axis-invalid: {bare_axis_invalid} fixture(s) have out-of-range axis cells — "
137
- "re-judge before trusting margins"
138
- )
139
- unmapped_axis_invalid = unmapped_axis_invalid_count(rows, failures)
140
- if unmapped_axis_invalid > 0:
141
- failures.append(
142
- f"judge axis-invalid unmapped: {unmapped_axis_invalid} fixture(s) have out-of-range axis cells "
143
- "that could not be mapped to an arm — re-judge before trusting margins"
144
- )
145
-
146
- # Hard floor 2: F9 must pass (skipped during bootstrap via --accept-missing)
147
- # Variant arm legacy gate kept for L2 baseline comparability.
148
- # iter-0033a (2026-04-30): renamed F9 dir from -to-preflight to -to-resolve to
149
- # match the shipped 2-skill contract (no preflight). The OLD pre-rename id
150
- # is preserved in fixtures/retired/ for replay.
151
- f9_row = next((r for r in rows if r.get("fixture") == "F9-e2e-ideate-to-resolve"), None)
152
- if f9_row is None:
153
- if not args.accept_missing:
154
- failures.append("F9 (E2E novice flow) missing — add fixture or run with --accept-missing")
155
- else:
156
- f9_margin = number_or_none(f9_row.get("margin"))
157
- if f9_margin is None:
158
- failures.append("F9 (E2E novice flow) margin missing or malformed — measurement invalid")
159
- elif f9_margin < 5:
160
- failures.append("F9 (E2E novice flow) must have variant margin ≥ +5")
161
-
162
- for row in rows:
163
- if not is_known_limit(row):
164
- continue
165
- margin = number_or_none(row.get("margin"))
166
- if margin is not None and (margin < -3 or margin > 3):
167
- warnings.append(
168
- f"{row.get('fixture')} known-limit margin {margin:+g} outside expected [-3,+3] range"
169
- )
170
-
171
- # Hard floor 3: at least 7 gated fixtures with margin ≥ +5
172
- # (skipped during bootstrap via --accept-missing)
173
- gated_fixtures = int_or_none(summary.get("gated_fixtures"))
174
- margin_ge_5_count = int_or_none(summary.get("margin_ge_5_count"))
175
- if gated_fixtures is None or margin_ge_5_count is None:
176
- failures.append("summary gated fixture counts missing or malformed — measurement invalid")
177
- elif gated_fixtures > 0 and margin_ge_5_count < 7:
178
- if not args.accept_missing:
179
- failures.append(
180
- f"only {margin_ge_5_count} of {gated_fixtures} "
181
- f"gated fixtures have variant margin ≥ +5 (need ≥ 7)"
182
- )
183
-
184
- # iter-0023 — L1 (solo_claude) gates per NORTH-STAR.md ops test #1.
185
- # Codex R1 (this iter) caught that ship-gate enforced only legacy L2
186
- # `variant` margin and never read `solo_over_bare`. Now NORTH-STAR's
187
- # documented L1 floor (≥ +5 on at least 7 gated fixtures, F9 ≥ +5, no L1
188
- # disqualifier) is mechanically enforced.
189
- raw_arms_present = summary.get("arms_present")
190
- if raw_arms_present is not None and not isinstance(raw_arms_present, dict):
191
- failures.append("summary arms_present malformed — measurement invalid")
192
- arms_present = object_or_empty(raw_arms_present)
193
- raw_margins_avg = summary.get("margins_avg")
194
- margins_avg = object_or_empty(raw_margins_avg)
195
- raw_solo_present = arms_present.get("solo_claude")
196
- solo_present = bool_or_none(raw_solo_present)
197
- if raw_solo_present is not None and solo_present is None:
198
- failures.append("summary arms_present.solo_claude malformed — measurement invalid")
199
- if solo_present is True:
200
- if raw_margins_avg is not None and not isinstance(raw_margins_avg, dict):
201
- failures.append("summary margins_avg malformed — measurement invalid")
202
- l1_dq_by_fixture: dict[str, bool] = {}
203
- for r in rows:
204
- fixture = str(r.get("fixture"))
205
- l1 = object_or_empty(object_or_empty(r.get("arms")).get("solo_claude"))
206
- raw_l1_dq = l1.get("disqualifier")
207
- parsed_l1_dq = bool_or_none(raw_l1_dq)
208
- if raw_l1_dq is not None and parsed_l1_dq is None:
209
- failures.append(f"{fixture} L1 disqualifier malformed — measurement invalid")
210
- l1_dq_by_fixture[fixture] = True
211
- else:
212
- l1_dq_by_fixture[fixture] = parsed_l1_dq is True
213
-
214
- l1_avg = margins_avg.get("solo_over_bare")
215
- if l1_avg is not None and number_or_none(l1_avg) is None:
216
- failures.append("L1 (solo_over_bare) suite avg malformed — measurement invalid")
217
- elif l1_avg is not None and l1_avg < 5:
218
- warnings.append(
219
- f"L1 (solo_over_bare) suite avg {l1_avg:+.1f} below NORTH-STAR floor +5 "
220
- "(reporting only — per-fixture L1 gates below are decisive)"
221
- )
222
- # F9 L1 floor
223
- if f9_row is not None:
224
- f9_l1 = object_or_empty(f9_row.get("margins")).get("solo_over_bare")
225
- if f9_l1 is None:
226
- if not args.accept_missing:
227
- failures.append("F9 L1 (solo_over_bare) margin missing — measurement invalid")
228
- elif number_or_none(f9_l1) is None:
229
- failures.append("F9 L1 (solo_over_bare) margin malformed — measurement invalid")
230
- elif f9_l1 < 5:
231
- failures.append(f"F9 L1 (solo_over_bare) margin {f9_l1:+g} < +5 floor")
232
- # 7-fixture L1 floor — headroom-aware (added 2026-05-02 per iter-0033 R4
233
- # Codex collab + NORTH-STAR amendment + RUBRIC hard-floor 3 update).
234
- # A fixture is excluded from the denominator when 100 - L0_score < 5
235
- # AND L1_score >= 95 AND the L1 arm has no disqualifier / CRITICAL-HIGH
236
- # finding / watchdog timeout / regression worse than gate #4. Excluded
237
- # fixtures become fixture-rotation candidates if RUBRIC's
238
- # two-shipped-version saturation rule fires.
239
- l1_ge_5 = 0
240
- l1_gated = 0
241
- l1_excluded_headroom = []
242
- for r in rows:
243
- if is_known_limit(r):
244
- continue
245
- arms = object_or_empty(r.get("arms"))
246
- l0 = object_or_empty(arms.get("bare"))
247
- l1 = object_or_empty(arms.get("solo_claude"))
248
- l0_score = number_or_none(l0.get("score"))
249
- l1_score = number_or_none(l1.get("score"))
250
- m = number_or_none(object_or_empty(r.get("margins")).get("solo_over_bare"))
251
- if m is None:
252
- continue
253
- # Headroom carve-out — must satisfy ALL conditions:
254
- # (a) bare ceiling-near (100 - L0 < 5)
255
- # (b) L1 also ceiling-near (>=95)
256
- # (c) L1 arm clean (no disqualifier, no axis-invalid, fix-loop didn't fail)
257
- l1_dq_here = l1_dq_by_fixture.get(str(r.get("fixture")), False)
258
- l1_axis_count = number_or_none(l1.get("_axis_validation_out_of_range_count", 0))
259
- l1_axis_inv = bool(l1_axis_count is not None and l1_axis_count > 0)
260
- if (
261
- l0_score is not None and l1_score is not None
262
- and (100 - l0_score) < 5 and l1_score >= 95
263
- and not l1_dq_here and not l1_axis_inv
264
- ):
265
- l1_excluded_headroom.append({
266
- "fixture": r.get("fixture"),
267
- "l0_score": l0_score,
268
- "l1_score": l1_score,
269
- "margin": m,
270
- })
271
- continue
272
- l1_gated += 1
273
- if m >= 5:
274
- l1_ge_5 += 1
275
- if l1_gated > 0 and l1_ge_5 < 7 and not args.accept_missing:
276
- failures.append(
277
- f"L1: only {l1_ge_5} of {l1_gated} headroom-available fixtures have solo_over_bare ≥ +5 (need ≥ 7)"
278
- )
279
- if l1_excluded_headroom:
280
- warnings.append(
281
- "L1 headroom-excluded (saturation candidates per RUBRIC two-shipped-version rule): "
282
- + ", ".join(
283
- f"{x['fixture']} (L0={x['l0_score']} L1={x['l1_score']} margin={x['margin']:+g})"
284
- for x in l1_excluded_headroom
285
- )
286
- )
287
- # L1 disqualifier floor
288
- l1_dq = sum(
289
- 1 for r in rows
290
- if l1_dq_by_fixture.get(str(r.get("fixture")), False)
291
- )
292
- if l1_dq > 0:
293
- failures.append(f"L1 disqualifier(s): {l1_dq} solo_claude arm(s) hit a disqualifier")
294
- # L1 axis-validity gate (judge.sh records out-of-range axis cells under
295
- # `_axis_validation` per fixture). If any L1 row has invalid axis data,
296
- # the L1 score for that row is not trustworthy.
297
- l1_axis_invalid = 0
298
- for r in rows:
299
- av = object_or_empty(object_or_empty(r.get("arms")).get("solo_claude"))
300
- inv = av.get("_axis_validation_out_of_range_count")
301
- count = number_or_none(inv)
302
- if inv is not None and count is None:
303
- failures.append("L1 axis count malformed — measurement invalid")
304
- elif count is not None and count > 0:
305
- l1_axis_invalid += 1
306
- if l1_axis_invalid > 0:
307
- failures.append(
308
- f"L1 axis-invalid: {l1_axis_invalid} fixture(s) have out-of-range axis cells — "
309
- "re-judge before trusting L1 margins"
310
- )
311
-
312
- # Hard floor 4: no per-fixture regression worse than −5 vs shipped baseline
313
- if baseline:
314
- prev_rows = {
315
- r["fixture"]: r for r in baseline.get("rows", [])
316
- if isinstance(r, dict) and isinstance(r.get("fixture"), str)
317
- }
318
- for r in rows:
319
- if is_known_limit(r):
320
- continue
321
- fid = r.get("fixture")
322
- prev = prev_rows.get(fid)
323
- current_score = number_or_none(r.get("variant_score"))
324
- previous_score = number_or_none(prev.get("variant_score")) if prev else None
325
- if prev and current_score is not None and previous_score is not None:
326
- delta = current_score - previous_score
327
- if delta < -5:
328
- failures.append(f"{fid} regressed {delta:+g} vs shipped (floor: −5)")
329
-
330
- # Soft gate: suite average margin drop > 3
331
- if baseline:
332
- current_margin_avg = number_or_none(summary.get("margin_avg"))
333
- baseline_margin_avg = number_or_none(baseline.get("margin_avg"))
334
- if current_margin_avg is None:
335
- failures.append("suite margin missing — measurement invalid")
336
- elif baseline_margin_avg is None:
337
- warnings.append("shipped baseline margin malformed; skipping suite margin delta")
338
- else:
339
- margin_delta = current_margin_avg - baseline_margin_avg
340
- if margin_delta < -3:
341
- warnings.append(f"suite margin dropped {margin_delta:+.1f} vs shipped (soft gate: > −3)")
342
-
343
- # Soft gate: any fixture that was > +5 before is now ≤ 0
344
- if baseline:
345
- prev_rows = {
346
- r["fixture"]: r for r in baseline.get("rows", [])
347
- if isinstance(r, dict) and isinstance(r.get("fixture"), str)
348
- }
349
- for r in rows:
350
- fid = r.get("fixture")
351
- prev = prev_rows.get(fid)
352
- prev_margin = number_or_none(prev.get("margin")) if prev else None
353
- current_margin = number_or_none(r.get("margin"))
354
- if prev and prev_margin is not None and prev_margin > 5:
355
- if current_margin is None:
356
- warnings.append(f"{fid} margin missing; was {prev_margin:+g}")
357
- elif current_margin <= 0:
358
- warnings.append(
359
- f"{fid} lost its margin: was {prev_margin:+g}, now {current_margin:+g}"
360
- )
361
-
362
- verdict = "PASS" if not failures else "FAIL"
363
- print(f"\n═══ SHIP-GATE VERDICT: {verdict} ═══\n")
364
- if failures:
365
- print("Hard-floor failures:")
366
- for f in failures:
367
- print(f" ✗ {f}")
368
- print()
369
- if warnings:
370
- print("Soft-gate warnings:")
371
- for w in warnings:
372
- print(f" ⚠ {w}")
373
- print()
374
- if not failures and not warnings:
375
- print("No gate violations. Suite is ship-ready.")
376
-
377
- # Bless if PASS + --bless — opt-in promotion to shipped baseline.
378
- # Per BENCHMARK-DESIGN.md Karpathy Check, automatic history mutation is
379
- # deferred until after the suite format stabilizes; `--bless` stays as
380
- # the explicit promotion path, and `summary.json` inside the run dir
381
- # is the durable record for ad-hoc inspection.
382
- if verdict == "PASS" and args.bless:
383
- baseline_p.parent.mkdir(parents=True, exist_ok=True)
384
- shutil.copyfile(summary_p, baseline_p)
385
- print(f"\nBlessed: {baseline_p}")
386
-
387
- return 0 if verdict == "PASS" else 1
388
-
389
-
390
- if __name__ == "__main__":
391
- sys.exit(main())