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,93 +0,0 @@
1
- # F37 Price events against the rule in effect at their own timestamp
2
-
3
- ## Failure mode
4
-
5
- Detects implementations that get the point-in-time rule lookup right at
6
- small, hand-written scale but reach for a data structure that stops
7
- scaling once the number of revisions per category grows large — most
8
- naturally, scanning a category's revisions linearly for every event to
9
- find the greatest `effectiveAt <= timestamp`. That shape is
10
- indistinguishable from the fully correct answer on any test an agent is
11
- likely to hand-write, and only fails once each category carries many
12
- thousands of revisions (Tier-2 axis: performance/scale — see
13
- F36-cli-session-admission's NOTES.md for the suite-wide grep evidence
14
- that no prior fixture measured wall-clock at all). Compounded with small-
15
- scale correctness sub-traps so a fast-but-wrong shortcut and a
16
- correct-but-slow shortcut both lose points independently: the inclusive
17
- `effectiveAt <= timestamp` boundary, the same-`effectiveAt` tie-break by
18
- greatest `id`, and the `unknown_category` vs. `no_effective_rule`
19
- distinction (whether the category has zero revisions at all versus
20
- revisions that just don't apply yet).
21
-
22
- This is a distinct algorithmic shape from F36 (online interval admission
23
- with expiry) — an offline/versioned point-in-time lookup, grouped by key
24
- and searched by time. It replaces an earlier F37 design (multi-hop category
25
- merge chains + dual-file rollback + idempotent rerun) that Codex R1 rejected
26
- outright as too structurally similar to the already-failed
27
- F35-cli-apply-journal / F26 / F32 rollback-and-idempotency family — see
28
- Rounds below.
29
-
30
- ## Fairness
31
-
32
- Every verifier assertion quotes a visible spec.md bullet via `contract_refs`
33
- (lint-fixtures enforced). The 200,000-event performance requirement is
34
- stated as a plain, numeric, visible spec bullet — no mechanism vocabulary
35
- ("group", "sort", "binary search", "index", "efficient") appears anywhere
36
- in `spec.md` or `task.txt`; only the observable behavior (must finish
37
- within the process timeout, must not change any event's outcome) is named.
38
- `data/rule-revisions.json` being unsorted is stated as a plain data-shape
39
- fact, not a hidden trap. The scale verifier's large revision set is
40
- generated only inside the hidden verifier at measurement time (never
41
- written to the persistent seed the arm develops against) specifically to
42
- avoid forcing the arm to read a multi-megabyte file into its own context
43
- during development — the setup.sh seed stays small and realistic.
44
-
45
- ## Pipeline phase(s) tested
46
-
47
- BUILD_GATE / VERIFY: an agent's own test suite is overwhelmingly likely to
48
- use a handful of hand-written revisions, so nothing in a normal iterative
49
- dev loop surfaces the scale defect; only the hidden, harness-side scale
50
- verifier (never visible to the arm) exercises it.
51
-
52
- ## Why another fixture can't cover this
53
-
54
- No active or retired fixture in this suite measures wall-clock or
55
- algorithmic complexity (see F36-cli-session-admission NOTES.md for the
56
- grep evidence). This fixture's specific shape — a versioned/point-in-time
57
- lookup keyed by category and searched by effective date — is also not
58
- covered by any prior pricing fixture (F16, F25, F26, F32), all of which
59
- price a single current state rather than resolving which historical rule
60
- revision applies.
61
-
62
- ## When to retire or replace
63
-
64
- If a headroom run shows solo_claude reliably recognizes and implements the
65
- required efficient per-category structure even without prompting, retire
66
- per the same honest-retirement contract used for F27/F28/F30/F34/F35 and
67
- add this id to `pair-rejected-fixtures.sh` with the observed scores.
68
-
69
- ## Rounds — Codex GPT-5.5 collaboration (read-only, `codex-monitored.sh`)
70
-
71
- **Round 1** (initial F37 design: multi-hop category-merge chain resolution,
72
- cycle detection, dual-file write-back to `products.json` +
73
- `migration-log.json`, idempotent-rerun requirement): Codex verdict
74
- **reject-and-replace** — "It reads like F35/F26/F32 with new nouns:
75
- rule-source pricing, idempotency/replay, validation-before-write,
76
- rollback/unchanged files. The rejected registry shows solo already scored
77
- 97-98 on these families... I would not spend another headroom run on this
78
- version." Codex proposed a concrete replacement direction instead of
79
- softening the objection: "dated category/rule snapshots where each product
80
- event must use the latest rule effective at or before its timestamp,
81
- across 200k events and 50k rule revisions. Naive scan-all-rules-per-product
82
- fails; correct solution groups by key and binary-searches or sweeps."
83
-
84
- **Round 2** (fully replaced design, as above, presented alongside the
85
- revised F36): Codex verdict **converge, no changes needed** — "F37 is
86
- distinct enough. It is a different access pattern: point-in-time lookup
87
- over versioned rules, not interval admission/capacity... I would not call
88
- it a freebie in the same way as 'meeting rooms'; agents still have to
89
- preserve input order, handle as-of boundaries, same-time tie-breaks, and
90
- distinguish missing-category cases." Confirmed the tie-break/boundary rules
91
- were unambiguous and the visible scale wording was fair (grounds
92
- `contract_refs` in observable behavior without leaking grouping, sorting,
93
- or binary search as required mechanisms).
@@ -1,16 +0,0 @@
1
- # F37 retired
2
-
3
- Retired from the active golden suite after headroom run
4
- `iter-0041-headroom-f36-f37`.
5
-
6
- Reason: bare scored 75, exceeding the headroom ceiling of 60, and
7
- `solo_claude` scored 96, exceeding the ceiling of 80 (judge: passed all four
8
- required verification commands including scale, via per-category sorted rule
9
- index + binary search with correct tie-breaks). The solo arm's invoke exited
10
- nonzero (`invoke_exit: 1` at 1247s) yet its working tree still verified
11
- clean — recorded by the gate as `solo_claude invoke failure` but the score
12
- stands on the verified artifacts. Neither ceiling held; no pair-lift headroom.
13
-
14
- Future use: the as-of lookup shape (Codex R1 replacement design) was still
15
- within one-shot reach of both arms. Same lesson as F36: the scale axis alone
16
- does not discriminate a full solo pipeline.
@@ -1,65 +0,0 @@
1
- {
2
- "verification_commands": [
3
- {
4
- "cmd": "node --test tests/cli.test.js",
5
- "exit_code": 0,
6
- "stdout_contains": [],
7
- "stdout_not_contains": ["not ok "]
8
- },
9
- {
10
- "cmd": "node \"$BENCH_FIXTURE_DIR/verifiers/correctness-small.js\"",
11
- "exit_code": 0,
12
- "stdout_contains": ["\"ok\":true"],
13
- "stdout_not_contains": [],
14
- "contract_refs": [
15
- "an exact match (`effectiveAt` equal to the event's `timestamp`) counts as eligible, not just strictly earlier ones",
16
- "If more than one eligible revision for that category shares the greatest `effectiveAt`, the one with the greatest `id` (plain string comparison) applies.",
17
- "If the event's `categoryId` has zero revisions anywhere in `data/rule-revisions.json`, the event is rejected with reason `unknown_category`.",
18
- "If the event's `categoryId` has at least one revision but none with `effectiveAt` less than or equal to the event's `timestamp`, the event is rejected with reason `no_effective_rule`."
19
- ]
20
- },
21
- {
22
- "cmd": "node \"$BENCH_FIXTURE_DIR/verifiers/validation.js\"",
23
- "exit_code": 0,
24
- "stdout_contains": ["\"ok\":true"],
25
- "stdout_not_contains": [],
26
- "contract_refs": [
27
- "Validation happens before any pricing.",
28
- "a duplicate event `id` uses shape `{ \"error\": \"duplicate_event_id\", \"id\": string }`"
29
- ]
30
- },
31
- {
32
- "cmd": "node \"$BENCH_FIXTURE_DIR/verifiers/scale.js\"",
33
- "exit_code": 0,
34
- "stdout_contains": ["\"ok\":true"],
35
- "stdout_not_contains": [],
36
- "contract_refs": [
37
- "`bench-cli price-events` must finish processing the 200,000-event verification input (see `## Verification`) against the seeded revision set within its process timeout, without changing the priced or rejected outcome for any event compared to a smaller input processed the same way."
38
- ]
39
- }
40
- ],
41
- "forbidden_patterns": [
42
- {
43
- "pattern": "catch\\s*\\([^)]*\\)\\s*\\{[^}]*return\\s+(null|undefined|''|\\{\\})",
44
- "description": "silent catch returning fallback in price-events path",
45
- "files": ["bin/cli.js"],
46
- "severity": "disqualifier"
47
- },
48
- {
49
- "pattern": "catch\\s*\\([^)]*\\)\\s*\\{\\s*\\}",
50
- "description": "empty catch block",
51
- "files": ["bin/cli.js"],
52
- "severity": "disqualifier"
53
- },
54
- {
55
- "pattern": "/\\*\\s*eslint-disable",
56
- "description": "eslint-disable without scoped justification",
57
- "files": ["bin/cli.js"],
58
- "severity": "disqualifier"
59
- }
60
- ],
61
- "required_files": ["bin/cli.js", "tests/cli.test.js", "data/rule-revisions.json"],
62
- "forbidden_files": [],
63
- "max_deps_added": 0,
64
- "spec_output_files": ["bin/cli.js", "tests/cli.test.js"]
65
- }
@@ -1,10 +0,0 @@
1
- {
2
- "id": "F37-cli-rule-lookup",
3
- "category": "high-risk",
4
- "difficulty": "high",
5
- "timeout_seconds": 1500,
6
- "required_tools": ["node"],
7
- "browser": false,
8
- "deps_change_expected": false,
9
- "intent": "Add a bench-cli price-events command that prices a batch of purchase events using the pricing rule revision that was in effect for that event's category at the event's own timestamp, drawn from a seeded, unsorted rule-revisions file, and that must finish processing a 200,000-event verification input against the seeded revision set within its process timeout."
10
- }
@@ -1,18 +0,0 @@
1
- #!/usr/bin/env bash
2
- # F37 setup — seed a small, deliberately unsorted rule-revisions file.
3
- set -e
4
-
5
- mkdir -p data
6
-
7
- cat > data/rule-revisions.json <<'JSON'
8
- [
9
- { "id": "rev-202", "categoryId": "cat-2", "effectiveAt": 2500, "discountPct": 25, "minPrice": 45 },
10
- { "id": "rev-101", "categoryId": "cat-1", "effectiveAt": 1000, "discountPct": 10, "minPrice": 50 },
11
- { "id": "rev-301", "categoryId": "cat-3", "effectiveAt": 500, "discountPct": 0, "minPrice": 100 },
12
- { "id": "rev-103", "categoryId": "cat-1", "effectiveAt": 3000, "discountPct": 15, "minPrice": 55 },
13
- { "id": "rev-201", "categoryId": "cat-2", "effectiveAt": 1500, "discountPct": 5, "minPrice": 40 },
14
- { "id": "rev-102", "categoryId": "cat-1", "effectiveAt": 2000, "discountPct": 20, "minPrice": 60 }
15
- ]
16
- JSON
17
-
18
- exit 0
@@ -1,66 +0,0 @@
1
- ---
2
- id: "F37-cli-rule-lookup"
3
- title: "Price events against the rule in effect at their own timestamp"
4
- status: planned
5
- complexity: high
6
- depends-on: []
7
- ---
8
-
9
- # F37 Price events against the rule in effect at their own timestamp
10
-
11
- ## Context
12
-
13
- `bench-cli` gets a `price-events` command that prices a batch of purchase
14
- events using the pricing rule revision that was actually in effect for that
15
- event's category at the event's own timestamp — not the newest rule, and
16
- not the same rule for every event in a category. Rule revisions arrive from
17
- a seeded, unsorted file with many revisions per category. Downstream
18
- billing tools parse stdout as JSON, and they replay very large event
19
- batches, so the lookup must stay exact and the command must finish in
20
- reasonable time.
21
-
22
- ## Requirements
23
-
24
- - [ ] `bench-cli price-events --input <path>` reads JSON shaped as `{ "events": [{ "id": string, "categoryId": string, "timestamp": number, "basePrice": number }] }`.
25
- - [ ] Pricing rule revisions come from `data/rule-revisions.json`, shaped as an array of `{ "id": string, "categoryId": string, "effectiveAt": number, "discountPct": number, "minPrice": number }`. Revisions in that file are not sorted by category or by time. The command must not modify `data/rule-revisions.json`.
26
- - [ ] For each event, consider every revision whose `categoryId` equals the event's `categoryId` and whose `effectiveAt` is less than or equal to the event's `timestamp`. Among those, the one with the greatest `effectiveAt` applies — an exact match (`effectiveAt` equal to the event's `timestamp`) counts as eligible, not just strictly earlier ones.
27
- - [ ] If more than one eligible revision for that category shares the greatest `effectiveAt`, the one with the greatest `id` (plain string comparison) applies.
28
- - [ ] If the event's `categoryId` has zero revisions anywhere in `data/rule-revisions.json`, the event is rejected with reason `unknown_category`.
29
- - [ ] If the event's `categoryId` has at least one revision but none with `effectiveAt` less than or equal to the event's `timestamp`, the event is rejected with reason `no_effective_rule`.
30
- - [ ] An accepted event's price is `Math.max(rule.minPrice, Math.round(event.basePrice * (100 - rule.discountPct) / 100))`.
31
- - [ ] `bench-cli price-events` must finish processing the 200,000-event verification input (see `## Verification`) against the seeded revision set within its process timeout, without changing the priced or rejected outcome for any event compared to a smaller input processed the same way.
32
- - [ ] Validation happens before any pricing. `events` must be an array; every event needs a non-empty string `id` and `categoryId`, an integer `timestamp`, and a non-negative integer `basePrice`; every event `id` must be unique. Invalid input exits `2` and writes exactly one JSON error object to stderr, printing nothing to stdout: a malformed field uses shape `{ "error": "invalid_input", "reason": string }`; a duplicate event `id` uses shape `{ "error": "duplicate_event_id", "id": string }`.
33
- - [ ] On success, write exactly one JSON object to stdout and no stderr. Keys: `priced` (array of `{ "id": string, "ruleId": string, "price": number }` rows) and `rejected` (array of `{ "id": string, "reason": string }` rows). Each event appears in exactly one of the two arrays; within each array, rows keep the original input event order.
34
- - [ ] `tests/cli.test.js` is updated. Existing tests still pass AND at least two new tests cover `price-events`: one where two revisions for the same category apply to different events depending on each event's own timestamp, and one rejection.
35
-
36
- ## Constraints
37
-
38
- - **No new npm dependencies.**
39
- - **No silent catches.** If parsing or file reading fails, emit a visible JSON error to stderr and exit `2`.
40
- - **No extra stdout/stderr text** on the success path; downstream tooling parses stdout as JSON.
41
- - `server` and `web` directories are unrelated to this command; do not add files there.
42
-
43
- ## Out of Scope
44
-
45
- - Persisting priced results between command invocations.
46
- - Adding, editing, or reordering rule revisions in `data/rule-revisions.json`.
47
- - Changing server routes, web UI, or any file outside `bin/cli.js` and `tests/cli.test.js`.
48
- - Touching `server/`, `web/`, or `tests/server.test.js`.
49
-
50
- ## Verification
51
-
52
- - `node --test tests/cli.test.js` exits 0.
53
- - Two revisions for the same category with different `effectiveAt` values each apply to the correct event depending on that event's own `timestamp`, including the exact-match boundary — `node "$BENCH_FIXTURE_DIR/verifiers/correctness-small.js"` exposes misses on this, the same-`effectiveAt` tie-break, and the `unknown_category`-versus-`no_effective_rule` distinction above.
54
- - Malformed input, non-unique event ids, and non-integer/negative fields are all rejected before any pricing decision, per the exact error shapes above — `node "$BENCH_FIXTURE_DIR/verifiers/validation.js"` exposes misses.
55
- - A 200,000-event input priced against a large seeded revision set completes within the process timeout and produces the exact priced/rejected outcome for every event — `node "$BENCH_FIXTURE_DIR/verifiers/scale.js"` exposes misses on both timing and correctness.
56
- - `git diff --stat` shows only `bin/cli.js` and `tests/cli.test.js` touched.
57
-
58
- ## Solo-headroom hypothesis
59
-
60
- A capable solo_claude baseline is expected to reach for a lookup approach
61
- that is correct on typical hand-written examples but does not stay fast as
62
- the number of revisions per category grows — for example, scanning a
63
- category's revisions linearly for every event instead of using a structure
64
- that stays fast as that list grows — which is correct at small scale but
65
- does not finish the 200,000-event input in time; observable command
66
- `node "$BENCH_FIXTURE_DIR/verifiers/scale.js"` exposes the miss.
@@ -1,9 +0,0 @@
1
- Add a `price-events` command to `bench-cli` so users can run `bench-cli price-events --input <path>` with a JSON file shaped as `{ "events": [{ "id": string, "categoryId": string, "timestamp": number, "basePrice": number }] }`. Pricing rules come from the seeded `data/rule-revisions.json` (an array of `{ "id", "categoryId", "effectiveAt", "discountPct", "minPrice" }` rows, not sorted by category or by time, and not to be modified by the command) — there can be many revisions for the same category over time, and each event must be priced using whichever revision was actually in effect for its category at its own timestamp, not just the newest one.
2
-
3
- For each event, find the revision for its category with the greatest `effectiveAt` that is less than or equal to the event's own `timestamp` (an exact match counts). If more than one revision ties on that `effectiveAt`, use the one with the greater `id`. If the category has no revisions at all, reject the event with reason `unknown_category`; if it has revisions but none apply yet at that timestamp, reject with reason `no_effective_rule`. An accepted event's price is the base price discounted by the rule's percentage and rounded, but never below the rule's minimum price.
4
-
5
- This command needs to stay fast: downstream billing tooling replays event batches well over a hundred thousand rows against revision sets with many entries per category, and it must still finish within a reasonable process timeout without changing any event's priced or rejected outcome versus a small input processed the same way.
6
-
7
- Validate the whole input before pricing anything: `events` must be an array, every event needs a non-empty string `id`/`categoryId`, an integer `timestamp`, and a non-negative integer `basePrice`, and every `id` must be unique. On any violation, exit 2, print exactly one JSON error object to stderr, and print nothing to stdout — use a distinct error for duplicate ids versus other malformed input. On success, print exactly one JSON object with `priced` (id/ruleId/price rows) and `rejected` (id/reason rows), each array keeping the original event order — nothing on stderr.
8
-
9
- Update `tests/cli.test.js`: existing tests still pass, plus at least two new tests for `price-events` (one exercising two revisions applying to different events by timestamp, one rejection). No new npm dependencies. Only touch `bin/cli.js` and `tests/cli.test.js`.
@@ -1,84 +0,0 @@
1
- 'use strict';
2
- // F37 hidden verifier — one bundled scenario exercising: (1) different
3
- // events in the same category resolving to different revisions by their
4
- // own timestamp, (2) the inclusive effectiveAt<=timestamp boundary (an
5
- // exact match is eligible), (3) the same-effectiveAt tie-break (greatest
6
- // id wins), (4) unknown_category vs no_effective_rule are distinct and
7
- // correctly assigned. Resets the seed so this verifier is order-independent
8
- // from other verifier commands (F35 pattern).
9
- //
10
- // Structural equality: object key order is not part of the visible
11
- // contract; array order is.
12
- function deepEqual(a, b) {
13
- if (a === b) return true;
14
- if (Array.isArray(a) && Array.isArray(b)) {
15
- return a.length === b.length && a.every((v, i) => deepEqual(v, b[i]));
16
- }
17
- if (a && b && typeof a === 'object' && typeof b === 'object' && !Array.isArray(a) && !Array.isArray(b)) {
18
- const ka = Object.keys(a).sort();
19
- const kb = Object.keys(b).sort();
20
- return deepEqual(ka, kb) && ka.every((k) => deepEqual(a[k], b[k]));
21
- }
22
- return false;
23
- }
24
-
25
- const fs = require('node:fs');
26
- const os = require('node:os');
27
- const path = require('node:path');
28
- const { spawnSync } = require('node:child_process');
29
-
30
- const work = process.env.BENCH_WORKDIR;
31
- const revPath = path.join(work, 'data', 'rule-revisions.json');
32
- const cli = path.join(work, 'bin', 'cli.js');
33
-
34
- const revisions = [
35
- { id: 'rev-a2', categoryId: 'cat-A', effectiveAt: 200, discountPct: 20, minPrice: 10 },
36
- { id: 'rev-a9', categoryId: 'cat-A', effectiveAt: 300, discountPct: 90, minPrice: 10 },
37
- { id: 'rev-a1', categoryId: 'cat-A', effectiveAt: 100, discountPct: 10, minPrice: 10 },
38
- { id: 'rev-b1', categoryId: 'cat-B', effectiveAt: 50, discountPct: 0, minPrice: 5 },
39
- { id: 'rev-a3', categoryId: 'cat-A', effectiveAt: 300, discountPct: 30, minPrice: 10 },
40
- ];
41
- fs.writeFileSync(revPath, JSON.stringify(revisions, null, 2) + '\n');
42
-
43
- const inputPath = path.join(os.tmpdir(), `price-events-small-${process.pid}.json`);
44
- fs.writeFileSync(inputPath, JSON.stringify({
45
- events: [
46
- { id: 'e1', categoryId: 'cat-A', timestamp: 150, basePrice: 100 },
47
- { id: 'e2', categoryId: 'cat-A', timestamp: 250, basePrice: 100 },
48
- { id: 'e3', categoryId: 'cat-A', timestamp: 200, basePrice: 50 },
49
- { id: 'e4', categoryId: 'cat-A', timestamp: 350, basePrice: 100 },
50
- { id: 'e5', categoryId: 'cat-B', timestamp: 10, basePrice: 100 },
51
- { id: 'e6', categoryId: 'cat-C', timestamp: 1000, basePrice: 100 },
52
- ],
53
- }));
54
-
55
- const result = spawnSync('node', [cli, 'price-events', '--input', inputPath], {
56
- cwd: work,
57
- encoding: 'utf8',
58
- maxBuffer: 16 * 1024 * 1024,
59
- });
60
-
61
- let out = null;
62
- try {
63
- out = JSON.parse(result.stdout);
64
- } catch {
65
- out = null;
66
- }
67
-
68
- const expected = {
69
- priced: [
70
- { id: 'e1', ruleId: 'rev-a1', price: 90 },
71
- { id: 'e2', ruleId: 'rev-a2', price: 80 },
72
- { id: 'e3', ruleId: 'rev-a2', price: 40 },
73
- { id: 'e4', ruleId: 'rev-a9', price: 10 },
74
- ],
75
- rejected: [
76
- { id: 'e5', reason: 'no_effective_rule' },
77
- { id: 'e6', reason: 'unknown_category' },
78
- ],
79
- };
80
-
81
- const ok = result.status === 0 && result.stderr === '' && deepEqual(out, expected);
82
-
83
- console.log(JSON.stringify({ ok, status: result.status, stderr: result.stderr, out, expected }));
84
- process.exit(ok ? 0 : 1);
@@ -1,184 +0,0 @@
1
- 'use strict';
2
- // F37 hidden verifier — the performance discriminator. 60,000 rule
3
- // revisions spread over 4 categories (15,000 revisions/category) and
4
- // 200,000 events. Every event resolves successfully (no rejections),
5
- // which keeps the expected output small and the correctness check a
6
- // direct array comparison; the discriminator is entirely in how the
7
- // lookup is done, not in exercising the reject paths (those are covered
8
- // by correctness-small.js).
9
- //
10
- // A per-event linear scan of a category's revisions costs on the order of
11
- // events * revisions-per-category =~ 200,000 * 15,000 = 3e9 comparisons —
12
- // tens of seconds or more in Node. Grouping by category (near-free) and
13
- // then binary-searching a sorted per-category list is a few million
14
- // log-steps — trivially fast. The reference below independently
15
- // implements the efficient shape (not shared code with the CLI) so it can
16
- // also serve as ground truth without becoming a second bottleneck. The
17
- // 15-second hard kill sits far above the efficient solution's expected
18
- // running time and correspondingly far below any realistic
19
- // linear-scan running time at these parameters.
20
- //
21
- // Revisions are written to `data/rule-revisions.json` in a shuffled
22
- // (non-category-grouped, non-time-sorted) order via a deterministic
23
- // permutation, matching the visible "not sorted by category or by time"
24
- // spec fact and closing a "trust file order" shortcut.
25
-
26
- const fs = require('node:fs');
27
- const os = require('node:os');
28
- const path = require('node:path');
29
- const { spawnSync } = require('node:child_process');
30
-
31
- const work = process.env.BENCH_WORKDIR;
32
- const revPath = path.join(work, 'data', 'rule-revisions.json');
33
- const cli = path.join(work, 'bin', 'cli.js');
34
-
35
- const CATS = 4;
36
- const REVS_PER_CAT = 15000;
37
- const TOTAL_REVS = CATS * REVS_PER_CAT;
38
- const EVENTS = 200000;
39
- const REV_PERMUTE_MULTIPLIER = 39989; // coprime with 60000 (2^5 * 3 * 5^4)
40
-
41
- const revisionsInOrder = new Array(TOTAL_REVS);
42
- let k = 0;
43
- for (let c = 0; c < CATS; c++) {
44
- for (let j = 0; j < REVS_PER_CAT; j++) {
45
- revisionsInOrder[k] = {
46
- id: `rev-${c}-${j}`,
47
- categoryId: `cat-${c}`,
48
- effectiveAt: j * 10,
49
- discountPct: (j * 7) % 50,
50
- minPrice: 100 + ((j * 13) % 900),
51
- };
52
- k += 1;
53
- }
54
- }
55
-
56
- const shuffled = new Array(TOTAL_REVS);
57
- for (let i = 0; i < TOTAL_REVS; i++) {
58
- const pos = (i * REV_PERMUTE_MULTIPLIER) % TOTAL_REVS;
59
- shuffled[pos] = revisionsInOrder[i];
60
- }
61
- fs.writeFileSync(revPath, JSON.stringify(shuffled));
62
-
63
- const events = new Array(EVENTS);
64
- for (let i = 0; i < EVENTS; i++) {
65
- const c = i % CATS;
66
- const base = (i * 131) % REVS_PER_CAT;
67
- events[i] = {
68
- id: `ev-${i}`,
69
- categoryId: `cat-${c}`,
70
- timestamp: base * 10 + 5,
71
- basePrice: 1000 + (i % 500),
72
- };
73
- }
74
-
75
- const inputPath = path.join(os.tmpdir(), `price-events-scale-${process.pid}.json`);
76
- fs.writeFileSync(inputPath, JSON.stringify({ events }));
77
-
78
- // Independent reference: group by category, sort each group by
79
- // (effectiveAt asc, id asc), binary-search the rightmost entry with
80
- // effectiveAt <= timestamp.
81
- const groups = new Map();
82
- for (const rev of revisionsInOrder) {
83
- if (!groups.has(rev.categoryId)) groups.set(rev.categoryId, []);
84
- groups.get(rev.categoryId).push(rev);
85
- }
86
- for (const list of groups.values()) {
87
- list.sort((a, b) => a.effectiveAt - b.effectiveAt || (a.id < b.id ? -1 : a.id > b.id ? 1 : 0));
88
- }
89
-
90
- function findRuleIndex(sorted, timestamp) {
91
- let lo = 0;
92
- let hi = sorted.length - 1;
93
- let ans = -1;
94
- while (lo <= hi) {
95
- const mid = (lo + hi) >> 1;
96
- if (sorted[mid].effectiveAt <= timestamp) {
97
- ans = mid;
98
- lo = mid + 1;
99
- } else {
100
- hi = mid - 1;
101
- }
102
- }
103
- return ans;
104
- }
105
-
106
- const expectedPriced = new Array(EVENTS);
107
- let expectedRejectedCount = 0;
108
- for (let i = 0; i < EVENTS; i++) {
109
- const ev = events[i];
110
- const group = groups.get(ev.categoryId);
111
- if (!group) {
112
- expectedRejectedCount += 1;
113
- expectedPriced[i] = null;
114
- continue;
115
- }
116
- const idx = findRuleIndex(group, ev.timestamp);
117
- if (idx < 0) {
118
- expectedRejectedCount += 1;
119
- expectedPriced[i] = null;
120
- continue;
121
- }
122
- const rule = group[idx];
123
- const price = Math.max(rule.minPrice, Math.round((ev.basePrice * (100 - rule.discountPct)) / 100));
124
- expectedPriced[i] = { id: ev.id, ruleId: rule.id, price };
125
- }
126
-
127
- const start = Date.now();
128
- const result = spawnSync('node', [cli, 'price-events', '--input', inputPath], {
129
- cwd: work,
130
- encoding: 'utf8',
131
- timeout: 15000,
132
- killSignal: 'SIGKILL',
133
- maxBuffer: 64 * 1024 * 1024,
134
- });
135
- const elapsedMs = Date.now() - start;
136
-
137
- const timedOut = result.status === null && result.signal !== null;
138
-
139
- let out = null;
140
- if (!timedOut) {
141
- try {
142
- out = JSON.parse(result.stdout);
143
- } catch {
144
- out = null;
145
- }
146
- }
147
-
148
- let correct = false;
149
- let mismatch = null;
150
- if (out && Array.isArray(out.priced) && Array.isArray(out.rejected)) {
151
- correct =
152
- out.rejected.length === expectedRejectedCount &&
153
- out.priced.length === EVENTS - expectedRejectedCount &&
154
- out.priced.every((row, i) => {
155
- const expected = expectedPriced[i];
156
- return expected && row.id === expected.id && row.ruleId === expected.ruleId && row.price === expected.price;
157
- });
158
- if (!correct) {
159
- const firstMismatchIndex = out.priced.findIndex((row, i) => {
160
- const expected = expectedPriced[i];
161
- return !expected || row.id !== expected.id || row.ruleId !== expected.ruleId || row.price !== expected.price;
162
- });
163
- mismatch = {
164
- pricedLength: out.priced.length,
165
- rejectedLength: out.rejected.length,
166
- expectedRejectedCount,
167
- firstMismatchIndex,
168
- };
169
- }
170
- }
171
-
172
- const ok = !timedOut && result.status === 0 && result.stderr === '' && correct;
173
-
174
- console.log(JSON.stringify({
175
- ok,
176
- timedOut,
177
- elapsedMs,
178
- status: result.status,
179
- signal: result.signal,
180
- stderrLength: result.stderr ? result.stderr.length : 0,
181
- correct,
182
- mismatch,
183
- }));
184
- process.exit(ok ? 0 : 1);
@@ -1,74 +0,0 @@
1
- 'use strict';
2
- // F37 hidden verifier — validation happens before any pricing decision:
3
- // malformed event fields use `invalid_input`, duplicate event ids use the
4
- // distinct `duplicate_event_id` shape, and nothing is priced or printed to
5
- // stdout in either case. Resets the seed so this verifier is
6
- // order-independent from other verifier commands.
7
-
8
- const fs = require('node:fs');
9
- const os = require('node:os');
10
- const path = require('node:path');
11
- const { spawnSync } = require('node:child_process');
12
-
13
- const work = process.env.BENCH_WORKDIR;
14
- const revPath = path.join(work, 'data', 'rule-revisions.json');
15
- const cli = path.join(work, 'bin', 'cli.js');
16
-
17
- const revisions = [
18
- { id: 'rev-a1', categoryId: 'cat-A', effectiveAt: 100, discountPct: 10, minPrice: 10 },
19
- ];
20
-
21
- let callCount = 0;
22
- function runPriceEvents(payload) {
23
- fs.writeFileSync(revPath, JSON.stringify(revisions, null, 2) + '\n');
24
- callCount += 1;
25
- const inputPath = path.join(os.tmpdir(), `price-events-validate-${process.pid}-${callCount}.json`);
26
- fs.writeFileSync(inputPath, JSON.stringify(payload));
27
- const result = spawnSync('node', [cli, 'price-events', '--input', inputPath], {
28
- cwd: work,
29
- encoding: 'utf8',
30
- maxBuffer: 16 * 1024 * 1024,
31
- });
32
- let err = null;
33
- try {
34
- err = JSON.parse(result.stderr);
35
- } catch {
36
- err = null;
37
- }
38
- return { result, err };
39
- }
40
-
41
- const failures = [];
42
-
43
- function expectInvalidInput(label, payload) {
44
- const { result, err } = runPriceEvents(payload);
45
- const ok = result.status === 2 && result.stdout === '' && err !== null && err.error === 'invalid_input' && typeof err.reason === 'string';
46
- if (!ok) {
47
- failures.push({ test: label, status: result.status, stdout: result.stdout, stderr: result.stderr, err });
48
- }
49
- }
50
-
51
- expectInvalidInput('events-not-array', { events: 'nope' });
52
- expectInvalidInput('missing-id', { events: [{ categoryId: 'cat-A', timestamp: 100, basePrice: 10 }] });
53
- expectInvalidInput('non-integer-timestamp', { events: [{ id: 'e1', categoryId: 'cat-A', timestamp: 1.5, basePrice: 10 }] });
54
- expectInvalidInput('negative-base-price', { events: [{ id: 'e1', categoryId: 'cat-A', timestamp: 100, basePrice: -1 }] });
55
- expectInvalidInput('non-string-category', { events: [{ id: 'e1', categoryId: 42, timestamp: 100, basePrice: 10 }] });
56
-
57
- // Duplicate event id — distinct error shape.
58
- {
59
- const payload = {
60
- events: [
61
- { id: 'dup', categoryId: 'cat-A', timestamp: 100, basePrice: 10 },
62
- { id: 'dup', categoryId: 'cat-A', timestamp: 200, basePrice: 20 },
63
- ],
64
- };
65
- const { result, err } = runPriceEvents(payload);
66
- const ok = result.status === 2 && result.stdout === '' && err !== null && err.error === 'duplicate_event_id' && err.id === 'dup';
67
- if (!ok) {
68
- failures.push({ test: 'duplicate-event-id', status: result.status, stdout: result.stdout, stderr: result.stderr, err });
69
- }
70
- }
71
-
72
- const ok = failures.length === 0;
73
- console.log(JSON.stringify({ ok, failures }));
74
- process.exit(ok ? 0 : 1);