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,565 +0,0 @@
1
- #!/usr/bin/env bash
2
- # judge.sh — Codex (CLI's current flagship, inherited) blind judge for ONE fixture.
3
- #
4
- # Usage:
5
- # judge.sh --fixture <FID> --run-id <ID>
6
- #
7
- # Reads:
8
- # results/<run-id>/<fixture>/variant/diff.patch + verify.json
9
- # results/<run-id>/<fixture>/bare/diff.patch + verify.json
10
- # fixtures/<fixture>/spec.md + expected.json, or shadow-fixtures/<fixture>/...
11
- # RUBRIC.md (stable rubric)
12
- #
13
- # Writes:
14
- # results/<run-id>/<fixture>/judge.json
15
- #
16
- # Blind: arm-to-slot assignment randomized per fixture, seed stored in judge.json.
17
-
18
- set -euo pipefail
19
-
20
- usage() { echo "usage: $0 --fixture <FID> --run-id <ID>"; exit 1; }
21
- require_value() {
22
- local flag="$1"
23
- local value="${2:-}"
24
- if [ -z "$value" ] || [[ "$value" == --* ]]; then
25
- echo "$flag requires a value" >&2
26
- exit 1
27
- fi
28
- }
29
-
30
- FIXTURE=""; RUN_ID=""
31
- while [ $# -gt 0 ]; do
32
- case "$1" in
33
- --fixture) require_value "$1" "${2:-}"; FIXTURE="$2"; shift 2;;
34
- --run-id) require_value "$1" "${2:-}"; RUN_ID="$2"; shift 2;;
35
- *) usage;;
36
- esac
37
- done
38
- [ -n "$FIXTURE" ] && [ -n "$RUN_ID" ] || usage
39
-
40
- BENCH_ROOT="$(cd "$(dirname "$0")/.." && pwd)"
41
- RES_DIR="$BENCH_ROOT/results/$RUN_ID/$FIXTURE"
42
- FIX_DIR=""
43
- for candidate in "$BENCH_ROOT/fixtures/$FIXTURE" "$BENCH_ROOT/shadow-fixtures/$FIXTURE"; do
44
- if [ -d "$candidate" ]; then
45
- FIX_DIR="$candidate"
46
- break
47
- fi
48
- done
49
- [ -n "$FIX_DIR" ] || { echo "fixture not found in fixtures/ or shadow-fixtures/: $FIXTURE"; exit 1; }
50
-
51
- # iter-0019: 3 arms — variant (L2), solo_claude (L1), bare (L0). The judge
52
- # scores all three in a single pass with the same prompt + same model so
53
- # margin derivations (L2-vs-L0, L1-vs-L0, L2-vs-L1) are calibrated against
54
- # each other and not against separate judge calls. ARMS_PRESENT enumerates
55
- # whichever subset actually has artifacts (so a missing arm doesn't abort
56
- # the whole judge step). Two-arm judge mode is preserved for runs that pre-
57
- # date iter-0019.
58
- ARMS_PRESENT=()
59
- # iter-0033c: l2_gated/l2_forced added for NEW L2 vs NEW L1 measurement.
60
- # iter-0037: l2_risk_probes adds bounded visible-verification probes before
61
- # IMPLEMENT; judge treats it as another blind arm when artifacts exist.
62
- # Slot count is still A/B/C max 3. Current pair-candidate proof runs supply
63
- # {bare, solo_claude, selected pair arm} where the selected pair arm is usually
64
- # l2_risk_probes; older diagnostic runs may instead supply l2_gated/l2_forced.
65
- # The blind-shuffle slot mapping below already tolerates arbitrary
66
- # ARMS_PRESENT counts >=2.
67
- for arm in variant solo_claude bare l2_gated l2_risk_probes l2_forced; do
68
- if [ -f "$RES_DIR/$arm/diff.patch" ] && [ -f "$RES_DIR/$arm/verify.json" ]; then
69
- ARMS_PRESENT+=("$arm")
70
- fi
71
- done
72
- if [ ${#ARMS_PRESENT[@]} -lt 2 ]; then
73
- echo "judge needs at least 2 arms with diff.patch + verify.json; have: ${ARMS_PRESENT[*]:-(none)}"
74
- exit 1
75
- fi
76
- for f in "$FIX_DIR/spec.md" "$FIX_DIR/expected.json" "$BENCH_ROOT/RUBRIC.md"; do
77
- [ -f "$f" ] || { echo "missing required input: $f"; exit 1; }
78
- done
79
-
80
- # Blind randomization: shuffle ARMS_PRESENT into ABC order. Seed recorded
81
- # in judge.json so runs are reproducible if rejudged.
82
- SEED=$RANDOM
83
- # iter-0019.4: Bash 3.2 compatible (macOS /bin/bash). `mapfile` is Bash 4+
84
- # only; replaced with while-read loop. The `|| [ -n "$line" ]` guard
85
- # preserves exact `mapfile -t` behavior on a final unterminated line (Python
86
- # print() emits trailing \n so this guard is belt-and-suspenders here, but
87
- # matches mapfile semantics for future producers).
88
- SLOTS=()
89
- while IFS= read -r line || [ -n "$line" ]; do
90
- SLOTS+=("$line")
91
- done < <(python3 - "$SEED" "${ARMS_PRESENT[@]}" <<'PY'
92
- import sys, random
93
- seed = int(sys.argv[1]); arms = sys.argv[2:]
94
- random.seed(seed)
95
- random.shuffle(arms)
96
- print("\n".join(arms))
97
- PY
98
- )
99
- A_ARM="${SLOTS[0]:-}"
100
- B_ARM="${SLOTS[1]:-}"
101
- C_ARM="${SLOTS[2]:-}"
102
-
103
- PROMPT_FILE="$RES_DIR/judge-prompt.txt"
104
- A_DIFF="$RES_DIR/$A_ARM/diff.patch"
105
- A_VERIFY="$RES_DIR/$A_ARM/verify.json"
106
- B_DIFF="$RES_DIR/$B_ARM/diff.patch"
107
- B_VERIFY="$RES_DIR/$B_ARM/verify.json"
108
- if [ -n "$C_ARM" ]; then
109
- C_DIFF="$RES_DIR/$C_ARM/diff.patch"
110
- C_VERIFY="$RES_DIR/$C_ARM/verify.json"
111
- else
112
- C_DIFF=""
113
- C_VERIFY=""
114
- fi
115
-
116
- # Sanitize diffs so stylistic tells that correlate with variant (e.g.
117
- # pipeline-commit markers, .devlyn/ archive lines) don't leak to the judge.
118
- # Judge sees only file-content changes; the transcript, arm label, NOTES.md,
119
- # and all process artifacts stay out of the prompt.
120
- python3 - "$PROMPT_FILE" "$FIX_DIR/spec.md" "$FIX_DIR/expected.json" "$BENCH_ROOT/RUBRIC.md" "$A_DIFF" "$B_DIFF" "$A_VERIFY" "$B_VERIFY" "$C_DIFF" "$C_VERIFY" "$BENCH_ROOT/scripts" <<'PY'
121
- import sys, pathlib, re, json
122
- args = sys.argv[1:]
123
- out_p, spec_p, exp_p, rubric_p = map(pathlib.Path, args[:4])
124
- a_diff, b_diff, a_ver, b_ver = map(pathlib.Path, args[4:8])
125
- c_diff_arg, c_ver_arg = args[8], args[9]
126
- sys.path.insert(0, args[10])
127
- from pair_evidence_contract import loads_strict_json_object
128
-
129
- c_diff = pathlib.Path(c_diff_arg) if c_diff_arg else None
130
- c_ver = pathlib.Path(c_ver_arg) if c_ver_arg else None
131
- out = out_p
132
- spec = spec_p.read_text()
133
- expected = exp_p.read_text()
134
- rubric = rubric_p.read_text()
135
-
136
- # Strip pipeline-origin tells from the diff before the judge sees it.
137
- TELLS = [
138
- re.compile(r"^diff --git.*\.devlyn/.*$", re.M),
139
- re.compile(r"^chore\(pipeline\):.*$", re.M),
140
- re.compile(r"^\.devlyn/.*$", re.M),
141
- re.compile(r"^Co-Authored-By:.*$", re.M),
142
- ]
143
- def sanitize(diff: str) -> str:
144
- # Drop whole-file hunks under .devlyn/
145
- out_lines, skip = [], False
146
- for line in diff.splitlines(keepends=True):
147
- if line.startswith("diff --git ") and ".devlyn/" in line:
148
- skip = True
149
- continue
150
- if line.startswith("diff --git "):
151
- skip = False
152
- if skip:
153
- continue
154
- out_lines.append(line)
155
- text = "".join(out_lines)
156
- for pat in TELLS:
157
- text = pat.sub("", text)
158
- return text
159
-
160
- # Also strip arm-identifying fields from verify.json before passing to judge.
161
- def sanitize_verify(path: pathlib.Path) -> str:
162
- data = loads_strict_json_object(path.read_text())
163
- # Remove anything that could name the arm
164
- data.pop("arm", None)
165
- return json.dumps(data, indent=2)
166
-
167
- a_diff_text = sanitize(a_diff.read_text())
168
- b_diff_text = sanitize(b_diff.read_text())
169
- a_ver_text = sanitize_verify(a_ver)
170
- b_ver_text = sanitize_verify(b_ver)
171
- have_c = c_diff is not None
172
- if have_c:
173
- c_diff_text = sanitize(c_diff.read_text())
174
- c_ver_text = sanitize_verify(c_ver)
175
-
176
- n_arms = 3 if have_c else 2
177
- arms_phrase = "Three engineers" if have_c else "Two engineers"
178
- slot_keys = ["a_score", "b_score", "c_score"][:n_arms]
179
- slot_breakdowns = ["a_breakdown", "b_breakdown", "c_breakdown"][:n_arms]
180
- slot_letters = ["A", "B", "C"][:n_arms]
181
-
182
- # Build the JSON-format hint dynamically so the judge sees the right shape
183
- # for either 2 or 3 arms. Same scoring rules; same rubric.
184
- score_lines = ",\n ".join(f'"{k}": <int 0-100>' for k in slot_keys)
185
- breakdown_lines = ",\n ".join(
186
- f'"{b}": {{"spec": 0-25, "constraint": 0-25, "scope": 0-25, "quality": 0-25, "notes": "<3-5 bullets>"}}'
187
- for b in slot_breakdowns
188
- )
189
- findings_keys = ", ".join(f'"{l}": ["..."]' for l in slot_letters)
190
- dq_keys = ", ".join(f'"{l}": bool' for l in slot_letters)
191
- dq_reasons = ", ".join(f'"{l}_reason": "..."' for l in slot_letters)
192
- winner_choices = " | ".join(f'"{l}"' for l in slot_letters) + ' | "tie"'
193
-
194
- # Per-arm sections of the prompt
195
- def section(label: str, diff_text: str, verify_text: str) -> str:
196
- return (
197
- f"=== IMPLEMENTATION {label} ===\nDiff:\n"
198
- f"```diff\n{diff_text}\n```\n"
199
- f"Verification results:\n```json\n{verify_text}\n```\n"
200
- )
201
-
202
- impl_sections = section("A", a_diff_text, a_ver_text) + "\n" + section("B", b_diff_text, b_ver_text)
203
- if have_c:
204
- impl_sections += "\n" + section("C", c_diff_text, c_ver_text)
205
-
206
- prompt = f"""You are a blind code-review judge. {arms_phrase} implemented the same spec. You do NOT know which implementation came from which process — grade them only on the merits of the code and its behavior.
207
-
208
- Apply the 4-axis rubric from RUBRIC.md below. Each axis is 0-25, total 100. Score every implementation independently — do not let one arm's score anchor another's. The judge's job is to apply the rubric absolutely; relative ordering falls out from the absolute scores.
209
-
210
- Return STRICT JSON only — no prose outside the JSON. Format:
211
-
212
- {{
213
- {score_lines},
214
- "winner": {winner_choices},
215
- {breakdown_lines},
216
- "critical_findings": {{{findings_keys}}},
217
- "disqualifiers": {{{dq_keys}, {dq_reasons}}},
218
- "overall_reasoning": "<5-8 sentences>"
219
- }}
220
-
221
- === RUBRIC ===
222
- {rubric}
223
-
224
- === SPEC ===
225
- {spec}
226
-
227
- === EXPECTED (machine-readable acceptance) ===
228
- {expected}
229
-
230
- {impl_sections}
231
- Return the JSON and nothing else.
232
- """
233
- out.write_text(prompt)
234
- PY
235
-
236
- # Invoke Codex — no -m so CLI flagship is inherited. Model identity is
237
- # recorded from the codex config.toml so rejudging with a newer flagship is
238
- # traceable. Run from a clean temp CWD so the judge can't peek at project
239
- # files that would leak arm identity.
240
- command -v codex >/dev/null 2>&1 || { echo "codex CLI not on PATH; cannot judge"; exit 1; }
241
- CODEX_CLI_VER=$(python3 - <<'PY'
242
- import subprocess
243
-
244
- try:
245
- proc = subprocess.run(
246
- ["codex", "--version"],
247
- stdout=subprocess.PIPE,
248
- stderr=subprocess.PIPE,
249
- text=True,
250
- timeout=5,
251
- )
252
- out = (proc.stdout or proc.stderr).strip()
253
- if proc.returncode == 0 and out:
254
- print(out)
255
- else:
256
- print(f"codex-cli unknown (version-exit-{proc.returncode})")
257
- except subprocess.TimeoutExpired:
258
- print("codex-cli unknown (version-timeout)")
259
- except FileNotFoundError:
260
- print("codex-cli missing")
261
- except Exception as exc:
262
- print(f"codex-cli unknown ({type(exc).__name__})")
263
- PY
264
- )
265
- JUDGE_MODEL=$({ grep -E '^model[[:space:]]*=' "${HOME}/.codex/config.toml" 2>/dev/null || true; } \
266
- | head -1 \
267
- | sed -E 's/.*=[[:space:]]*"?([^"]*)"?[[:space:]]*$/\1/' \
268
- | xargs)
269
- [ -z "$JUDGE_MODEL" ] && JUDGE_MODEL="(unknown — codex config.toml not readable)"
270
-
271
- JUDGE_CWD="/tmp/judge-$RUN_ID-$FIXTURE"
272
- rm -rf "$JUDGE_CWD"
273
- mkdir -p "$JUDGE_CWD"
274
-
275
- JUDGE_OUT="$RES_DIR/judge-output.txt"
276
- JUDGE_LAST="$RES_DIR/judge-last-message.txt"
277
- JUDGE_SCHEMA="$RES_DIR/judge-output.schema.json"
278
- python3 - "$JUDGE_SCHEMA" "$C_ARM" <<'PY'
279
- import json
280
- import pathlib
281
- import sys
282
-
283
- out = pathlib.Path(sys.argv[1])
284
- have_c = bool(sys.argv[2])
285
- letters = ["A", "B"] + (["C"] if have_c else [])
286
-
287
- breakdown = {
288
- "type": "object",
289
- "required": ["spec", "constraint", "scope", "quality", "notes"],
290
- "properties": {
291
- "spec": {"type": "integer", "minimum": 0, "maximum": 25},
292
- "constraint": {"type": "integer", "minimum": 0, "maximum": 25},
293
- "scope": {"type": "integer", "minimum": 0, "maximum": 25},
294
- "quality": {"type": "integer", "minimum": 0, "maximum": 25},
295
- "notes": {"type": "string"},
296
- },
297
- "additionalProperties": False,
298
- }
299
- findings = {
300
- "type": "object",
301
- "required": letters,
302
- "properties": {letter: {"type": "array", "items": {"type": "string"}} for letter in letters},
303
- "additionalProperties": False,
304
- }
305
- disqualifier_props = {}
306
- for letter in letters:
307
- disqualifier_props[letter] = {"type": "boolean"}
308
- disqualifier_props[f"{letter}_reason"] = {"type": "string"}
309
- schema = {
310
- "type": "object",
311
- "required": [
312
- "a_score",
313
- "b_score",
314
- "winner",
315
- "a_breakdown",
316
- "b_breakdown",
317
- "critical_findings",
318
- "disqualifiers",
319
- "overall_reasoning",
320
- ] + (["c_score", "c_breakdown"] if have_c else []),
321
- "properties": {
322
- "a_score": {"type": "integer", "minimum": 0, "maximum": 100},
323
- "b_score": {"type": "integer", "minimum": 0, "maximum": 100},
324
- "winner": {"type": "string", "enum": letters + ["tie"]},
325
- "a_breakdown": breakdown,
326
- "b_breakdown": breakdown,
327
- "critical_findings": findings,
328
- "disqualifiers": {
329
- "type": "object",
330
- "required": list(disqualifier_props),
331
- "properties": disqualifier_props,
332
- "additionalProperties": False,
333
- },
334
- "overall_reasoning": {"type": "string"},
335
- },
336
- "additionalProperties": False,
337
- }
338
- if have_c:
339
- schema["properties"]["c_score"] = {"type": "integer", "minimum": 0, "maximum": 100}
340
- schema["properties"]["c_breakdown"] = breakdown
341
- out.write_text(json.dumps(schema, indent=2))
342
- PY
343
- set +e
344
- cat "$PROMPT_FILE" | (
345
- cd "$JUDGE_CWD" && codex exec \
346
- --ignore-user-config \
347
- --ignore-rules \
348
- --ephemeral \
349
- --disable codex_hooks \
350
- --disable hooks \
351
- -s read-only \
352
- --skip-git-repo-check \
353
- -c model_reasoning_effort=xhigh \
354
- --output-schema "$JUDGE_SCHEMA" \
355
- --output-last-message "$JUDGE_LAST" \
356
- -
357
- ) > "$JUDGE_OUT" 2>&1
358
- JUDGE_EXIT=$?
359
- set -e
360
- rm -rf "$JUDGE_CWD"
361
- if [ $JUDGE_EXIT -ne 0 ]; then
362
- echo "codex exec failed (exit $JUDGE_EXIT); see $JUDGE_OUT"
363
- exit 1
364
- fi
365
-
366
- # Extract JSON (codex wraps with banners; pick the last {...} block)
367
- python3 - "$JUDGE_OUT" "$JUDGE_LAST" "$RES_DIR/judge.json" "$A_ARM" "$B_ARM" "$C_ARM" "$SEED" "$CODEX_CLI_VER" "$JUDGE_MODEL" "$BENCH_ROOT/scripts" <<'PY'
368
- import math
369
- import sys, re, json, pathlib
370
- out_path = pathlib.Path(sys.argv[1])
371
- last_path = pathlib.Path(sys.argv[2])
372
- target = pathlib.Path(sys.argv[3])
373
- a_arm, b_arm, c_arm, seed, codex_ver, judge_model = sys.argv[4:10]
374
- sys.path.insert(0, sys.argv[10])
375
- from pair_evidence_contract import loads_strict_json_object, reject_json_constant
376
-
377
- out = last_path.read_text() if last_path.is_file() and last_path.stat().st_size else out_path.read_text()
378
-
379
- # Extract the last valid judgment JSON. A naive brace-counter breaks on
380
- # `{`/`}` that appear inside strings (e.g. JS source embedded in the arms'
381
- # diffs), so use json.JSONDecoder.raw_decode starting at each `{` position
382
- # and keep the last successful parse with the required keys.
383
- decoder = json.JSONDecoder(parse_constant=reject_json_constant)
384
- brace_positions = [i for i, c in enumerate(out) if c == '{']
385
- chosen = None
386
- for pos in reversed(brace_positions):
387
- try:
388
- obj, _ = decoder.raw_decode(out[pos:])
389
- except json.JSONDecodeError:
390
- continue
391
- if isinstance(obj, dict) and "a_score" in obj and "b_score" in obj:
392
- chosen = obj
393
- break
394
- if chosen is None:
395
- raise SystemExit(f"no valid JSON in judge output; see {out_path}")
396
-
397
- def is_score(value):
398
- return isinstance(value, int) and not isinstance(value, bool) and 0 <= value <= 100
399
-
400
- def is_bool(value):
401
- return isinstance(value, bool)
402
-
403
- def is_axis_score(value):
404
- return isinstance(value, int) and not isinstance(value, bool) and 0 <= value <= 25
405
-
406
- required_score_keys = ["a_score", "b_score"] + (["c_score"] if c_arm else [])
407
- invalid_scores = [key for key in required_score_keys if not is_score(chosen.get(key))]
408
- if invalid_scores:
409
- raise SystemExit(f"invalid judge score value(s): {', '.join(invalid_scores)}")
410
-
411
- # Decode blind labels — record full mapping so summary code can iterate
412
- mapping = {"A": a_arm, "B": b_arm}
413
- if c_arm:
414
- mapping["C"] = c_arm
415
- chosen["_blind_mapping"] = {**mapping, "seed": int(seed)}
416
- chosen["_judge_cli"] = codex_ver.strip()
417
- chosen["_judge_model"] = judge_model.strip()
418
-
419
- # iter-0023 — axis breakdown validation. Rubric axes are 0-25 (RUBRIC.md
420
- # "Scoring — 4 axes, 25 points each"). Past runs (iter-0020 F9) recorded
421
- # `quality: -1` because judge LLM occasionally emits sentinel/negative
422
- # values; ship-gate then averaged invalid cells. Detect, clamp to [0, 25],
423
- # and record the invalid cells under `_axis_validation` so downstream
424
- # consumers can refuse to trust that fixture's margin.
425
- AXIS_KEYS = ("spec", "constraint", "scope", "quality")
426
- BREAKDOWN_KEYS = ("a_breakdown", "b_breakdown", "c_breakdown")
427
- axis_invalid_cells = []
428
- for bk in BREAKDOWN_KEYS:
429
- if bk not in chosen or not isinstance(chosen[bk], dict):
430
- continue
431
- for axis in AXIS_KEYS:
432
- if axis not in chosen[bk]:
433
- continue
434
- v = chosen[bk][axis]
435
- if not is_axis_score(v):
436
- axis_invalid_cells.append({"breakdown": bk, "axis": axis, "value": v})
437
- chosen[bk][axis] = max(0, min(25, int(v) if not isinstance(v, bool) and isinstance(v, (int, float)) else 0))
438
- chosen["_axis_validation"] = {
439
- "out_of_range_count": len(axis_invalid_cells),
440
- "out_of_range_cells": axis_invalid_cells,
441
- "axis_range": [0, 25],
442
- }
443
- if axis_invalid_cells:
444
- sys.stderr.write(
445
- f"[judge.sh] WARNING: {len(axis_invalid_cells)} axis cell(s) out of [0,25] "
446
- f"clamped: {axis_invalid_cells}\n"
447
- )
448
-
449
- # Verification is the machine-readable acceptance contract. RUBRIC.md puts
450
- # verification behavior under Spec Compliance, but LLM judges can still grade
451
- # generous prose around failed commands. Cap score mechanically so an arm that
452
- # fails required verification cannot receive a ceiling score.
453
- def arm_verify_score(arm: str):
454
- path = target.parent / arm / "verify.json"
455
- if not path.is_file():
456
- return None
457
- data = loads_strict_json_object(path.read_text())
458
- value = data.get("verify_score")
459
- return float(value) if isinstance(value, (int, float)) else None
460
-
461
- verify_caps = []
462
- for letter, score_key, breakdown_key in (
463
- ("A", "a_score", "a_breakdown"),
464
- ("B", "b_score", "b_breakdown"),
465
- ("C", "c_score", "c_breakdown"),
466
- ):
467
- arm = mapping.get(letter)
468
- if not arm:
469
- continue
470
- verify_score = arm_verify_score(arm)
471
- if verify_score is None:
472
- continue
473
- verify_score = max(0.0, min(1.0, verify_score))
474
- score_cap = math.floor(100 * verify_score)
475
- spec_cap = math.floor(25 * verify_score)
476
- raw_score = chosen.get(score_key)
477
- raw_spec = (chosen.get(breakdown_key) or {}).get("spec")
478
- row = {
479
- "letter": letter,
480
- "arm": arm,
481
- "verify_score": verify_score,
482
- "score_cap": score_cap,
483
- "spec_cap": spec_cap,
484
- "raw_score": raw_score,
485
- "raw_spec": raw_spec,
486
- "score_capped": False,
487
- "spec_capped": False,
488
- }
489
- if is_score(raw_score) and raw_score > score_cap:
490
- chosen[score_key] = score_cap
491
- row["score_capped"] = True
492
- breakdown = chosen.get(breakdown_key)
493
- if isinstance(breakdown, dict) and isinstance(raw_spec, (int, float)) and raw_spec > spec_cap:
494
- breakdown["spec"] = spec_cap
495
- row["spec_capped"] = True
496
- verify_caps.append(row)
497
- chosen["_verify_score_caps"] = verify_caps
498
-
499
- # scores_by_arm: arm-name → score, computed from the blind A/B/C scores.
500
- # This is the canonical 3-arm-aware shape the report consumer reads. The
501
- # legacy variant_score / bare_score / margin fields below are derived from
502
- # scores_by_arm for backward compatibility with pre-iter-0019 callers.
503
- scores_by_arm = {}
504
- slot_keys = ["a_score", "b_score", "c_score"]
505
- slot_letters = ["A", "B", "C"]
506
- for letter, key in zip(slot_letters, slot_keys):
507
- arm = mapping.get(letter)
508
- if arm is not None and key in chosen and is_score(chosen[key]):
509
- scores_by_arm[arm] = chosen[key]
510
- chosen["scores_by_arm"] = scores_by_arm
511
-
512
- # Per-letter critical_findings / disqualifiers also rotated to per-arm.
513
- raw_findings_letters = chosen.get("critical_findings")
514
- findings_letters = raw_findings_letters if isinstance(raw_findings_letters, dict) else {}
515
- findings_by_arm = {mapping[l]: findings_letters.get(l, []) for l in slot_letters if l in mapping}
516
- chosen["findings_by_arm"] = findings_by_arm
517
-
518
- raw_dq_letters = chosen.get("disqualifiers")
519
- dq_letters = raw_dq_letters if isinstance(raw_dq_letters, dict) else {}
520
- invalid_dq_letters = [
521
- letter for letter in slot_letters
522
- if letter in dq_letters and not is_bool(dq_letters.get(letter))
523
- ]
524
- if invalid_dq_letters:
525
- raise SystemExit(f"invalid judge disqualifier value(s): {', '.join(invalid_dq_letters)}")
526
- dq_by_arm = {}
527
- for l in slot_letters:
528
- if l not in mapping:
529
- continue
530
- arm = mapping[l]
531
- dq_by_arm[arm] = {
532
- "disqualifier": dq_letters.get(l, False) is True,
533
- "reason": str(dq_letters.get(f"{l}_reason", "") or ""),
534
- }
535
- chosen["disqualifiers_by_arm"] = dq_by_arm
536
-
537
- # Pairwise margins (positive = first arm beat second).
538
- def margin(left: str, right: str):
539
- if left in scores_by_arm and right in scores_by_arm:
540
- return scores_by_arm[left] - scores_by_arm[right]
541
- return None
542
-
543
- chosen["margins"] = {
544
- "variant_over_bare": margin("variant", "bare"),
545
- "solo_over_bare": margin("solo_claude", "bare"),
546
- "variant_over_solo": margin("variant", "solo_claude"),
547
- }
548
-
549
- # Translate winner letter to arm
550
- w = chosen.get("winner")
551
- chosen["winner_arm"] = mapping.get(w, "tie") if w in mapping else "tie"
552
-
553
- # Legacy 2-arm fields preserved so older summary code still parses. When
554
- # solo_claude is present, variant/bare margin is derived from scores_by_arm.
555
- chosen["variant_score"] = scores_by_arm.get("variant")
556
- chosen["bare_score"] = scores_by_arm.get("bare")
557
- if chosen.get("variant_score") is not None and chosen.get("bare_score") is not None:
558
- chosen["margin"] = chosen["variant_score"] - chosen["bare_score"]
559
-
560
- target.write_text(json.dumps(chosen, indent=2))
561
- parts = [f"{arm}={s}" for arm, s in scores_by_arm.items()]
562
- mline = chosen.get("margins") or {}
563
- mparts = [f"{k}={v:+d}" for k, v in mline.items() if v is not None]
564
- print(f"[judge] " + " ".join(parts) + (" | " + " ".join(mparts) if mparts else ""))
565
- PY