devlyn-cli 3.2.1 → 3.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (423) hide show
  1. package/AGENTS.md +2 -2
  2. package/CLAUDE.md +2 -2
  3. package/README.md +12 -102
  4. package/bin/devlyn.js +13 -225
  5. package/bin/instruction-templates.json +8 -0
  6. package/config/skills/_shared/adapters/grok.md +1 -2
  7. package/config/skills/_shared/archive_run.py +15 -3
  8. package/config/skills/_shared/judge-role-evidence.py +21 -1
  9. package/config/skills/_shared/runtime-principles.md +1 -1
  10. package/config/skills/_shared/spec-verify-check.py +0 -653
  11. package/config/skills/_shared/state-phase-write.py +351 -25
  12. package/config/skills/_shared/task-complete.py +660 -150
  13. package/config/skills/_shared/terminal-claim-check.py +229 -4
  14. package/config/skills/_shared/verify-merge-findings.py +93 -2
  15. package/config/skills/devlyn:ideate/SKILL.md +3 -4
  16. package/config/skills/devlyn:ideate/references/elicitation.md +2 -35
  17. package/config/skills/devlyn:ideate/references/from-spec-mode.md +3 -18
  18. package/config/skills/devlyn:ideate/references/project-mode.md +1 -16
  19. package/config/skills/devlyn:ideate/references/spec-template.md +0 -2
  20. package/config/skills/devlyn:queue/SKILL.md +6 -4
  21. package/config/skills/devlyn:resolve/SKILL.md +16 -25
  22. package/config/skills/devlyn:resolve/references/free-form-mode.md +0 -14
  23. package/config/skills/devlyn:resolve/references/outer-loop.md +1 -1
  24. package/config/skills/devlyn:resolve/references/phases/build-gate.md +1 -1
  25. package/config/skills/devlyn:resolve/references/phases/cleanup.md +3 -3
  26. package/config/skills/devlyn:resolve/references/phases/implement.md +1 -1
  27. package/config/skills/devlyn:resolve/references/phases/probe-derive.md +1 -16
  28. package/config/skills/devlyn:resolve/references/phases/verify.md +4 -9
  29. package/config/skills/devlyn:resolve/references/state-schema.md +9 -7
  30. package/config/skills/devlyn:resolve/references/task-completion.md +47 -38
  31. package/{config/skills → optional-skills}/code-health-standards/SKILL.md +4 -13
  32. package/{config/skills → optional-skills}/code-review-standards/SKILL.md +4 -12
  33. package/{config/skills → optional-skills}/root-cause-analysis/SKILL.md +4 -12
  34. package/{config/skills → optional-skills}/ui-implementation-standards/SKILL.md +4 -14
  35. package/package.json +1 -57
  36. package/benchmark/auto-resolve/BENCHMARK-DESIGN.md +0 -289
  37. package/benchmark/auto-resolve/BENCHMARK-RESULTS.md +0 -341
  38. package/benchmark/auto-resolve/README.md +0 -696
  39. package/benchmark/auto-resolve/RUBRIC.md +0 -177
  40. package/benchmark/auto-resolve/fixtures/F1-cli-trivial-flag/NOTES.md +0 -34
  41. package/benchmark/auto-resolve/fixtures/F1-cli-trivial-flag/expected.json +0 -68
  42. package/benchmark/auto-resolve/fixtures/F1-cli-trivial-flag/metadata.json +0 -10
  43. package/benchmark/auto-resolve/fixtures/F1-cli-trivial-flag/setup.sh +0 -4
  44. package/benchmark/auto-resolve/fixtures/F1-cli-trivial-flag/spec.md +0 -44
  45. package/benchmark/auto-resolve/fixtures/F1-cli-trivial-flag/task.ko.txt +0 -8
  46. package/benchmark/auto-resolve/fixtures/F1-cli-trivial-flag/task.txt +0 -8
  47. package/benchmark/auto-resolve/fixtures/F10-persist-write-collision/NOTES.md +0 -68
  48. package/benchmark/auto-resolve/fixtures/F10-persist-write-collision/expected.json +0 -60
  49. package/benchmark/auto-resolve/fixtures/F10-persist-write-collision/metadata.json +0 -10
  50. package/benchmark/auto-resolve/fixtures/F10-persist-write-collision/setup.sh +0 -17
  51. package/benchmark/auto-resolve/fixtures/F10-persist-write-collision/spec.md +0 -51
  52. package/benchmark/auto-resolve/fixtures/F10-persist-write-collision/task.txt +0 -9
  53. package/benchmark/auto-resolve/fixtures/F10-persist-write-collision/verifiers/invalid.js +0 -29
  54. package/benchmark/auto-resolve/fixtures/F10-persist-write-collision/verifiers/parallel.js +0 -50
  55. package/benchmark/auto-resolve/fixtures/F11-batch-import-all-or-nothing/NOTES.md +0 -75
  56. package/benchmark/auto-resolve/fixtures/F11-batch-import-all-or-nothing/expected.json +0 -52
  57. package/benchmark/auto-resolve/fixtures/F11-batch-import-all-or-nothing/metadata.json +0 -10
  58. package/benchmark/auto-resolve/fixtures/F11-batch-import-all-or-nothing/setup.sh +0 -171
  59. package/benchmark/auto-resolve/fixtures/F11-batch-import-all-or-nothing/spec.md +0 -50
  60. package/benchmark/auto-resolve/fixtures/F11-batch-import-all-or-nothing/task.txt +0 -9
  61. package/benchmark/auto-resolve/fixtures/F12-webhook-raw-body-signature/NOTES.md +0 -89
  62. package/benchmark/auto-resolve/fixtures/F12-webhook-raw-body-signature/expected.json +0 -74
  63. package/benchmark/auto-resolve/fixtures/F12-webhook-raw-body-signature/metadata.json +0 -10
  64. package/benchmark/auto-resolve/fixtures/F12-webhook-raw-body-signature/setup.sh +0 -251
  65. package/benchmark/auto-resolve/fixtures/F12-webhook-raw-body-signature/spec.md +0 -57
  66. package/benchmark/auto-resolve/fixtures/F12-webhook-raw-body-signature/task.txt +0 -13
  67. package/benchmark/auto-resolve/fixtures/F12-webhook-raw-body-signature/verifiers/replay-malformed-body.js +0 -64
  68. package/benchmark/auto-resolve/fixtures/F15-frozen-diff-race-review/NOTES.md +0 -104
  69. package/benchmark/auto-resolve/fixtures/F15-frozen-diff-race-review/expected.json +0 -46
  70. package/benchmark/auto-resolve/fixtures/F15-frozen-diff-race-review/metadata.json +0 -10
  71. package/benchmark/auto-resolve/fixtures/F15-frozen-diff-race-review/setup.sh +0 -336
  72. package/benchmark/auto-resolve/fixtures/F15-frozen-diff-race-review/spec.md +0 -51
  73. package/benchmark/auto-resolve/fixtures/F15-frozen-diff-race-review/task.txt +0 -9
  74. package/benchmark/auto-resolve/fixtures/F16-cli-quote-tax-rules/NOTES.md +0 -38
  75. package/benchmark/auto-resolve/fixtures/F16-cli-quote-tax-rules/expected.json +0 -64
  76. package/benchmark/auto-resolve/fixtures/F16-cli-quote-tax-rules/metadata.json +0 -10
  77. package/benchmark/auto-resolve/fixtures/F16-cli-quote-tax-rules/setup.sh +0 -32
  78. package/benchmark/auto-resolve/fixtures/F16-cli-quote-tax-rules/spec.md +0 -63
  79. package/benchmark/auto-resolve/fixtures/F16-cli-quote-tax-rules/task.txt +0 -7
  80. package/benchmark/auto-resolve/fixtures/F16-cli-quote-tax-rules/verifiers/exact-success.js +0 -54
  81. package/benchmark/auto-resolve/fixtures/F16-cli-quote-tax-rules/verifiers/no-hardcoded-pricing.js +0 -47
  82. package/benchmark/auto-resolve/fixtures/F16-cli-quote-tax-rules/verifiers/stock-error.js +0 -45
  83. package/benchmark/auto-resolve/fixtures/F2-cli-medium-subcommand/NOTES.md +0 -57
  84. package/benchmark/auto-resolve/fixtures/F2-cli-medium-subcommand/expected-pair-plan-registry.json +0 -170
  85. package/benchmark/auto-resolve/fixtures/F2-cli-medium-subcommand/expected.json +0 -84
  86. package/benchmark/auto-resolve/fixtures/F2-cli-medium-subcommand/metadata.json +0 -21
  87. package/benchmark/auto-resolve/fixtures/F2-cli-medium-subcommand/pair-plan.sample-fail.json +0 -214
  88. package/benchmark/auto-resolve/fixtures/F2-cli-medium-subcommand/pair-plan.sample-pass.json +0 -223
  89. package/benchmark/auto-resolve/fixtures/F2-cli-medium-subcommand/setup.sh +0 -5
  90. package/benchmark/auto-resolve/fixtures/F2-cli-medium-subcommand/spec.md +0 -55
  91. package/benchmark/auto-resolve/fixtures/F2-cli-medium-subcommand/task.txt +0 -14
  92. package/benchmark/auto-resolve/fixtures/F21-cli-scheduler-priority/NOTES.md +0 -39
  93. package/benchmark/auto-resolve/fixtures/F21-cli-scheduler-priority/expected.json +0 -62
  94. package/benchmark/auto-resolve/fixtures/F21-cli-scheduler-priority/metadata.json +0 -10
  95. package/benchmark/auto-resolve/fixtures/F21-cli-scheduler-priority/setup.sh +0 -2
  96. package/benchmark/auto-resolve/fixtures/F21-cli-scheduler-priority/spec.md +0 -67
  97. package/benchmark/auto-resolve/fixtures/F21-cli-scheduler-priority/task.txt +0 -7
  98. package/benchmark/auto-resolve/fixtures/F21-cli-scheduler-priority/verifiers/error-order.js +0 -55
  99. package/benchmark/auto-resolve/fixtures/F21-cli-scheduler-priority/verifiers/priority-blocked.js +0 -48
  100. package/benchmark/auto-resolve/fixtures/F22-cli-ledger-close/NOTES.md +0 -35
  101. package/benchmark/auto-resolve/fixtures/F22-cli-ledger-close/expected.json +0 -56
  102. package/benchmark/auto-resolve/fixtures/F22-cli-ledger-close/metadata.json +0 -10
  103. package/benchmark/auto-resolve/fixtures/F22-cli-ledger-close/setup.sh +0 -2
  104. package/benchmark/auto-resolve/fixtures/F22-cli-ledger-close/spec.md +0 -64
  105. package/benchmark/auto-resolve/fixtures/F22-cli-ledger-close/task.txt +0 -7
  106. package/benchmark/auto-resolve/fixtures/F22-cli-ledger-close/verifiers/conflicting-duplicate.js +0 -34
  107. package/benchmark/auto-resolve/fixtures/F22-cli-ledger-close/verifiers/idempotent-close.js +0 -41
  108. package/benchmark/auto-resolve/fixtures/F23-cli-fulfillment-wave/NOTES.md +0 -39
  109. package/benchmark/auto-resolve/fixtures/F23-cli-fulfillment-wave/expected.json +0 -56
  110. package/benchmark/auto-resolve/fixtures/F23-cli-fulfillment-wave/metadata.json +0 -10
  111. package/benchmark/auto-resolve/fixtures/F23-cli-fulfillment-wave/setup.sh +0 -2
  112. package/benchmark/auto-resolve/fixtures/F23-cli-fulfillment-wave/spec.md +0 -76
  113. package/benchmark/auto-resolve/fixtures/F23-cli-fulfillment-wave/task.txt +0 -7
  114. package/benchmark/auto-resolve/fixtures/F23-cli-fulfillment-wave/verifiers/priority-rollback.js +0 -64
  115. package/benchmark/auto-resolve/fixtures/F23-cli-fulfillment-wave/verifiers/single-warehouse-fefo.js +0 -66
  116. package/benchmark/auto-resolve/fixtures/F25-cli-cart-promotion-rules/NOTES.md +0 -40
  117. package/benchmark/auto-resolve/fixtures/F25-cli-cart-promotion-rules/expected.json +0 -66
  118. package/benchmark/auto-resolve/fixtures/F25-cli-cart-promotion-rules/metadata.json +0 -10
  119. package/benchmark/auto-resolve/fixtures/F25-cli-cart-promotion-rules/setup.sh +0 -36
  120. package/benchmark/auto-resolve/fixtures/F25-cli-cart-promotion-rules/spec.md +0 -71
  121. package/benchmark/auto-resolve/fixtures/F25-cli-cart-promotion-rules/task.txt +0 -7
  122. package/benchmark/auto-resolve/fixtures/F25-cli-cart-promotion-rules/verifiers/catalog-source.js +0 -57
  123. package/benchmark/auto-resolve/fixtures/F25-cli-cart-promotion-rules/verifiers/exact-success.js +0 -63
  124. package/benchmark/auto-resolve/fixtures/F25-cli-cart-promotion-rules/verifiers/stock-error.js +0 -34
  125. package/benchmark/auto-resolve/fixtures/F26-cli-payout-ledger-rules/NOTES.md +0 -31
  126. package/benchmark/auto-resolve/fixtures/F26-cli-payout-ledger-rules/expected.json +0 -68
  127. package/benchmark/auto-resolve/fixtures/F26-cli-payout-ledger-rules/metadata.json +0 -10
  128. package/benchmark/auto-resolve/fixtures/F26-cli-payout-ledger-rules/setup.sh +0 -17
  129. package/benchmark/auto-resolve/fixtures/F26-cli-payout-ledger-rules/spec.md +0 -68
  130. package/benchmark/auto-resolve/fixtures/F26-cli-payout-ledger-rules/task.txt +0 -7
  131. package/benchmark/auto-resolve/fixtures/F26-cli-payout-ledger-rules/verifiers/conflicting-duplicate.js +0 -29
  132. package/benchmark/auto-resolve/fixtures/F26-cli-payout-ledger-rules/verifiers/exact-payout.js +0 -58
  133. package/benchmark/auto-resolve/fixtures/F26-cli-payout-ledger-rules/verifiers/rules-source.js +0 -56
  134. package/benchmark/auto-resolve/fixtures/F3-backend-contract-risk/NOTES.md +0 -35
  135. package/benchmark/auto-resolve/fixtures/F3-backend-contract-risk/expected-pair-plan-registry.json +0 -162
  136. package/benchmark/auto-resolve/fixtures/F3-backend-contract-risk/expected.json +0 -67
  137. package/benchmark/auto-resolve/fixtures/F3-backend-contract-risk/metadata.json +0 -19
  138. package/benchmark/auto-resolve/fixtures/F3-backend-contract-risk/setup.sh +0 -4
  139. package/benchmark/auto-resolve/fixtures/F3-backend-contract-risk/spec.md +0 -55
  140. package/benchmark/auto-resolve/fixtures/F3-backend-contract-risk/task.txt +0 -9
  141. package/benchmark/auto-resolve/fixtures/F31-cli-seat-rebalance/NOTES.md +0 -34
  142. package/benchmark/auto-resolve/fixtures/F31-cli-seat-rebalance/expected.json +0 -57
  143. package/benchmark/auto-resolve/fixtures/F31-cli-seat-rebalance/metadata.json +0 -10
  144. package/benchmark/auto-resolve/fixtures/F31-cli-seat-rebalance/setup.sh +0 -2
  145. package/benchmark/auto-resolve/fixtures/F31-cli-seat-rebalance/spec.md +0 -67
  146. package/benchmark/auto-resolve/fixtures/F31-cli-seat-rebalance/task.txt +0 -7
  147. package/benchmark/auto-resolve/fixtures/F31-cli-seat-rebalance/verifiers/duplicate-event-error.js +0 -35
  148. package/benchmark/auto-resolve/fixtures/F31-cli-seat-rebalance/verifiers/priority-transfer-rollback.js +0 -53
  149. package/benchmark/auto-resolve/fixtures/F32-cli-subscription-renewal/NOTES.md +0 -38
  150. package/benchmark/auto-resolve/fixtures/F32-cli-subscription-renewal/expected.json +0 -57
  151. package/benchmark/auto-resolve/fixtures/F32-cli-subscription-renewal/metadata.json +0 -10
  152. package/benchmark/auto-resolve/fixtures/F32-cli-subscription-renewal/setup.sh +0 -2
  153. package/benchmark/auto-resolve/fixtures/F32-cli-subscription-renewal/spec.md +0 -70
  154. package/benchmark/auto-resolve/fixtures/F32-cli-subscription-renewal/task.txt +0 -3
  155. package/benchmark/auto-resolve/fixtures/F32-cli-subscription-renewal/verifiers/duplicate-renewal-error.js +0 -42
  156. package/benchmark/auto-resolve/fixtures/F32-cli-subscription-renewal/verifiers/priority-credit-rollback.js +0 -70
  157. package/benchmark/auto-resolve/fixtures/F4-web-browser-design/NOTES.md +0 -47
  158. package/benchmark/auto-resolve/fixtures/F4-web-browser-design/expected.json +0 -57
  159. package/benchmark/auto-resolve/fixtures/F4-web-browser-design/metadata.json +0 -10
  160. package/benchmark/auto-resolve/fixtures/F4-web-browser-design/setup.sh +0 -6
  161. package/benchmark/auto-resolve/fixtures/F4-web-browser-design/spec.md +0 -48
  162. package/benchmark/auto-resolve/fixtures/F4-web-browser-design/task.txt +0 -9
  163. package/benchmark/auto-resolve/fixtures/F5-fix-loop-red-green/NOTES.md +0 -45
  164. package/benchmark/auto-resolve/fixtures/F5-fix-loop-red-green/expected.json +0 -65
  165. package/benchmark/auto-resolve/fixtures/F5-fix-loop-red-green/metadata.json +0 -10
  166. package/benchmark/auto-resolve/fixtures/F5-fix-loop-red-green/setup.sh +0 -55
  167. package/benchmark/auto-resolve/fixtures/F5-fix-loop-red-green/spec.md +0 -48
  168. package/benchmark/auto-resolve/fixtures/F5-fix-loop-red-green/task.txt +0 -7
  169. package/benchmark/auto-resolve/fixtures/F6-dep-audit-native-module/NOTES.md +0 -43
  170. package/benchmark/auto-resolve/fixtures/F6-dep-audit-native-module/expected.json +0 -77
  171. package/benchmark/auto-resolve/fixtures/F6-dep-audit-native-module/metadata.json +0 -10
  172. package/benchmark/auto-resolve/fixtures/F6-dep-audit-native-module/setup.sh +0 -4
  173. package/benchmark/auto-resolve/fixtures/F6-dep-audit-native-module/spec.md +0 -48
  174. package/benchmark/auto-resolve/fixtures/F6-dep-audit-native-module/task.txt +0 -10
  175. package/benchmark/auto-resolve/fixtures/F7-out-of-scope-trap/NOTES.md +0 -57
  176. package/benchmark/auto-resolve/fixtures/F7-out-of-scope-trap/expected.json +0 -76
  177. package/benchmark/auto-resolve/fixtures/F7-out-of-scope-trap/metadata.json +0 -10
  178. package/benchmark/auto-resolve/fixtures/F7-out-of-scope-trap/setup.sh +0 -36
  179. package/benchmark/auto-resolve/fixtures/F7-out-of-scope-trap/spec.md +0 -45
  180. package/benchmark/auto-resolve/fixtures/F7-out-of-scope-trap/task.txt +0 -7
  181. package/benchmark/auto-resolve/fixtures/F8-known-limit-ambiguous/NOTES.md +0 -53
  182. package/benchmark/auto-resolve/fixtures/F8-known-limit-ambiguous/expected.json +0 -63
  183. package/benchmark/auto-resolve/fixtures/F8-known-limit-ambiguous/metadata.json +0 -10
  184. package/benchmark/auto-resolve/fixtures/F8-known-limit-ambiguous/setup.sh +0 -4
  185. package/benchmark/auto-resolve/fixtures/F8-known-limit-ambiguous/spec.md +0 -48
  186. package/benchmark/auto-resolve/fixtures/F8-known-limit-ambiguous/task.txt +0 -1
  187. package/benchmark/auto-resolve/fixtures/F9-e2e-ideate-to-resolve/NOTES.md +0 -105
  188. package/benchmark/auto-resolve/fixtures/F9-e2e-ideate-to-resolve/expected.json +0 -74
  189. package/benchmark/auto-resolve/fixtures/F9-e2e-ideate-to-resolve/metadata.json +0 -10
  190. package/benchmark/auto-resolve/fixtures/F9-e2e-ideate-to-resolve/setup.sh +0 -28
  191. package/benchmark/auto-resolve/fixtures/F9-e2e-ideate-to-resolve/spec.md +0 -59
  192. package/benchmark/auto-resolve/fixtures/F9-e2e-ideate-to-resolve/task.txt +0 -5
  193. package/benchmark/auto-resolve/fixtures/SCHEMA.md +0 -188
  194. package/benchmark/auto-resolve/fixtures/retired/F27-cli-subscription-proration/NOTES.md +0 -37
  195. package/benchmark/auto-resolve/fixtures/retired/F27-cli-subscription-proration/RETIRED.md +0 -13
  196. package/benchmark/auto-resolve/fixtures/retired/F27-cli-subscription-proration/expected.json +0 -56
  197. package/benchmark/auto-resolve/fixtures/retired/F27-cli-subscription-proration/metadata.json +0 -10
  198. package/benchmark/auto-resolve/fixtures/retired/F27-cli-subscription-proration/setup.sh +0 -18
  199. package/benchmark/auto-resolve/fixtures/retired/F27-cli-subscription-proration/spec.md +0 -69
  200. package/benchmark/auto-resolve/fixtures/retired/F27-cli-subscription-proration/task.txt +0 -7
  201. package/benchmark/auto-resolve/fixtures/retired/F27-cli-subscription-proration/verifiers/exact-proration.js +0 -48
  202. package/benchmark/auto-resolve/fixtures/retired/F27-cli-subscription-proration/verifiers/rules-source-and-conflict.js +0 -79
  203. package/benchmark/auto-resolve/fixtures/retired/F28-cli-return-authorization/NOTES.md +0 -54
  204. package/benchmark/auto-resolve/fixtures/retired/F28-cli-return-authorization/RETIRED.md +0 -7
  205. package/benchmark/auto-resolve/fixtures/retired/F28-cli-return-authorization/expected.json +0 -67
  206. package/benchmark/auto-resolve/fixtures/retired/F28-cli-return-authorization/metadata.json +0 -10
  207. package/benchmark/auto-resolve/fixtures/retired/F28-cli-return-authorization/setup.sh +0 -2
  208. package/benchmark/auto-resolve/fixtures/retired/F28-cli-return-authorization/spec.md +0 -67
  209. package/benchmark/auto-resolve/fixtures/retired/F28-cli-return-authorization/task.txt +0 -5
  210. package/benchmark/auto-resolve/fixtures/retired/F28-cli-return-authorization/verifiers/policy-precedence.js +0 -72
  211. package/benchmark/auto-resolve/fixtures/retired/F28-cli-return-authorization/verifiers/validation-and-immutability.js +0 -43
  212. package/benchmark/auto-resolve/fixtures/retired/F28-cli-return-authorization/verifiers/validation-boundary.js +0 -116
  213. package/benchmark/auto-resolve/fixtures/retired/F30-cli-credit-hold-settlement/NOTES.md +0 -35
  214. package/benchmark/auto-resolve/fixtures/retired/F30-cli-credit-hold-settlement/RETIRED.md +0 -12
  215. package/benchmark/auto-resolve/fixtures/retired/F30-cli-credit-hold-settlement/expected.json +0 -58
  216. package/benchmark/auto-resolve/fixtures/retired/F30-cli-credit-hold-settlement/metadata.json +0 -10
  217. package/benchmark/auto-resolve/fixtures/retired/F30-cli-credit-hold-settlement/setup.sh +0 -2
  218. package/benchmark/auto-resolve/fixtures/retired/F30-cli-credit-hold-settlement/spec.md +0 -73
  219. package/benchmark/auto-resolve/fixtures/retired/F30-cli-credit-hold-settlement/task.txt +0 -17
  220. package/benchmark/auto-resolve/fixtures/retired/F30-cli-credit-hold-settlement/verifiers/mixed-idempotent-settlement.js +0 -53
  221. package/benchmark/auto-resolve/fixtures/retired/F30-cli-credit-hold-settlement/verifiers/rejection-boundaries.js +0 -74
  222. package/benchmark/auto-resolve/fixtures/retired/F34-cli-settle-inflight/NOTES.md +0 -28
  223. package/benchmark/auto-resolve/fixtures/retired/F34-cli-settle-inflight/RETIRED.md +0 -15
  224. package/benchmark/auto-resolve/fixtures/retired/F34-cli-settle-inflight/expected.json +0 -57
  225. package/benchmark/auto-resolve/fixtures/retired/F34-cli-settle-inflight/metadata.json +0 -10
  226. package/benchmark/auto-resolve/fixtures/retired/F34-cli-settle-inflight/setup.sh +0 -50
  227. package/benchmark/auto-resolve/fixtures/retired/F34-cli-settle-inflight/spec.md +0 -59
  228. package/benchmark/auto-resolve/fixtures/retired/F34-cli-settle-inflight/task.txt +0 -9
  229. package/benchmark/auto-resolve/fixtures/retired/F34-cli-settle-inflight/verifiers/ordered-settlement.js +0 -88
  230. package/benchmark/auto-resolve/fixtures/retired/F34-cli-settle-inflight/verifiers/reject-invalid.js +0 -45
  231. package/benchmark/auto-resolve/fixtures/retired/F35-cli-apply-journal/NOTES.md +0 -30
  232. package/benchmark/auto-resolve/fixtures/retired/F35-cli-apply-journal/RETIRED.md +0 -16
  233. package/benchmark/auto-resolve/fixtures/retired/F35-cli-apply-journal/expected.json +0 -64
  234. package/benchmark/auto-resolve/fixtures/retired/F35-cli-apply-journal/metadata.json +0 -10
  235. package/benchmark/auto-resolve/fixtures/retired/F35-cli-apply-journal/setup.sh +0 -21
  236. package/benchmark/auto-resolve/fixtures/retired/F35-cli-apply-journal/spec.md +0 -58
  237. package/benchmark/auto-resolve/fixtures/retired/F35-cli-apply-journal/task.txt +0 -9
  238. package/benchmark/auto-resolve/fixtures/retired/F35-cli-apply-journal/verifiers/dup-op.js +0 -54
  239. package/benchmark/auto-resolve/fixtures/retired/F35-cli-apply-journal/verifiers/priority-apply.js +0 -82
  240. package/benchmark/auto-resolve/fixtures/retired/F35-cli-apply-journal/verifiers/rollback.js +0 -77
  241. package/benchmark/auto-resolve/fixtures/retired/F36-cli-session-admission/NOTES.md +0 -99
  242. package/benchmark/auto-resolve/fixtures/retired/F36-cli-session-admission/RETIRED.md +0 -18
  243. package/benchmark/auto-resolve/fixtures/retired/F36-cli-session-admission/expected.json +0 -64
  244. package/benchmark/auto-resolve/fixtures/retired/F36-cli-session-admission/metadata.json +0 -10
  245. package/benchmark/auto-resolve/fixtures/retired/F36-cli-session-admission/setup.sh +0 -4
  246. package/benchmark/auto-resolve/fixtures/retired/F36-cli-session-admission/spec.md +0 -61
  247. package/benchmark/auto-resolve/fixtures/retired/F36-cli-session-admission/task.txt +0 -9
  248. package/benchmark/auto-resolve/fixtures/retired/F36-cli-session-admission/verifiers/correctness-small.js +0 -135
  249. package/benchmark/auto-resolve/fixtures/retired/F36-cli-session-admission/verifiers/scale.js +0 -100
  250. package/benchmark/auto-resolve/fixtures/retired/F36-cli-session-admission/verifiers/validation.js +0 -75
  251. package/benchmark/auto-resolve/fixtures/retired/F37-cli-rule-lookup/NOTES.md +0 -93
  252. package/benchmark/auto-resolve/fixtures/retired/F37-cli-rule-lookup/RETIRED.md +0 -16
  253. package/benchmark/auto-resolve/fixtures/retired/F37-cli-rule-lookup/expected.json +0 -65
  254. package/benchmark/auto-resolve/fixtures/retired/F37-cli-rule-lookup/metadata.json +0 -10
  255. package/benchmark/auto-resolve/fixtures/retired/F37-cli-rule-lookup/setup.sh +0 -18
  256. package/benchmark/auto-resolve/fixtures/retired/F37-cli-rule-lookup/spec.md +0 -66
  257. package/benchmark/auto-resolve/fixtures/retired/F37-cli-rule-lookup/task.txt +0 -9
  258. package/benchmark/auto-resolve/fixtures/retired/F37-cli-rule-lookup/verifiers/correctness-small.js +0 -84
  259. package/benchmark/auto-resolve/fixtures/retired/F37-cli-rule-lookup/verifiers/scale.js +0 -184
  260. package/benchmark/auto-resolve/fixtures/retired/F37-cli-rule-lookup/verifiers/validation.js +0 -74
  261. package/benchmark/auto-resolve/fixtures/retired/F9-e2e-ideate-to-preflight/NOTES.md +0 -60
  262. package/benchmark/auto-resolve/fixtures/retired/F9-e2e-ideate-to-preflight/RETIRED.md +0 -29
  263. package/benchmark/auto-resolve/fixtures/retired/F9-e2e-ideate-to-preflight/expected.json +0 -73
  264. package/benchmark/auto-resolve/fixtures/retired/F9-e2e-ideate-to-preflight/metadata.json +0 -10
  265. package/benchmark/auto-resolve/fixtures/retired/F9-e2e-ideate-to-preflight/setup.sh +0 -28
  266. package/benchmark/auto-resolve/fixtures/retired/F9-e2e-ideate-to-preflight/spec.md +0 -58
  267. package/benchmark/auto-resolve/fixtures/retired/F9-e2e-ideate-to-preflight/task.txt +0 -5
  268. package/benchmark/auto-resolve/fixtures/test-repo/README.md +0 -12
  269. package/benchmark/auto-resolve/fixtures/test-repo/bin/cli.js +0 -63
  270. package/benchmark/auto-resolve/fixtures/test-repo/package-lock.json +0 -823
  271. package/benchmark/auto-resolve/fixtures/test-repo/package.json +0 -22
  272. package/benchmark/auto-resolve/fixtures/test-repo/playwright.config.js +0 -17
  273. package/benchmark/auto-resolve/fixtures/test-repo/server/index.js +0 -37
  274. package/benchmark/auto-resolve/fixtures/test-repo/tests/cli.test.js +0 -25
  275. package/benchmark/auto-resolve/fixtures/test-repo/tests/server.test.js +0 -58
  276. package/benchmark/auto-resolve/fixtures/test-repo/web/index.html +0 -37
  277. package/benchmark/auto-resolve/results/20260507-f10-f11-tier1-full-pipeline/headroom-gate.json +0 -25
  278. package/benchmark/auto-resolve/results/20260507-f10-f11-tier1-full-pipeline/headroom-gate.md +0 -10
  279. package/benchmark/auto-resolve/results/20260508-f22-exact-error-headroom/headroom-gate.json +0 -18
  280. package/benchmark/auto-resolve/results/20260508-f22-exact-error-headroom/headroom-gate.md +0 -9
  281. package/benchmark/auto-resolve/results/20260508-f26-headroom/headroom-gate.json +0 -18
  282. package/benchmark/auto-resolve/results/20260508-f26-headroom/headroom-gate.md +0 -9
  283. package/benchmark/auto-resolve/results/20260510-f16-f23-f25-combined-proof/F16-cli-quote-tax-rules/l2_risk_probes/result.json +0 -28
  284. package/benchmark/auto-resolve/results/20260510-f16-f23-f25-combined-proof/F23-cli-fulfillment-wave/l2_risk_probes/result.json +0 -28
  285. package/benchmark/auto-resolve/results/20260510-f16-f23-f25-combined-proof/F25-cli-cart-promotion-rules/l2_risk_probes/result.json +0 -30
  286. package/benchmark/auto-resolve/results/20260510-f16-f23-f25-combined-proof/full-pipeline-pair-gate.json +0 -82
  287. package/benchmark/auto-resolve/results/20260510-f16-f23-f25-combined-proof/full-pipeline-pair-gate.md +0 -18
  288. package/benchmark/auto-resolve/results/20260510-f16-f23-f25-combined-proof/headroom-gate.json +0 -46
  289. package/benchmark/auto-resolve/results/20260510-f16-f23-f25-combined-proof/headroom-gate.md +0 -17
  290. package/benchmark/auto-resolve/results/20260511-f12-webhook-headroom/headroom-gate.json +0 -28
  291. package/benchmark/auto-resolve/results/20260511-f12-webhook-headroom/headroom-gate.md +0 -15
  292. package/benchmark/auto-resolve/results/20260511-f15-concurrency-headroom/headroom-gate.json +0 -28
  293. package/benchmark/auto-resolve/results/20260511-f15-concurrency-headroom/headroom-gate.md +0 -15
  294. package/benchmark/auto-resolve/results/20260511-f21-current-riskprobes-v1/F21-cli-scheduler-priority/l2_risk_probes/result.json +0 -32
  295. package/benchmark/auto-resolve/results/20260511-f21-current-riskprobes-v1/full-pipeline-pair-gate.json +0 -44
  296. package/benchmark/auto-resolve/results/20260511-f21-current-riskprobes-v1/full-pipeline-pair-gate.md +0 -16
  297. package/benchmark/auto-resolve/results/20260511-f21-current-riskprobes-v1/headroom-gate.json +0 -18
  298. package/benchmark/auto-resolve/results/20260511-f21-current-riskprobes-v1/headroom-gate.md +0 -9
  299. package/benchmark/auto-resolve/results/20260511-f3-http-error-headroom/headroom-gate.json +0 -28
  300. package/benchmark/auto-resolve/results/20260511-f3-http-error-headroom/headroom-gate.md +0 -15
  301. package/benchmark/auto-resolve/results/20260512-f2-medium-headroom/headroom-gate.json +0 -28
  302. package/benchmark/auto-resolve/results/20260512-f2-medium-headroom/headroom-gate.md +0 -15
  303. package/benchmark/auto-resolve/results/20260512-f31-seat-rebalance-headroom/headroom-gate.json +0 -28
  304. package/benchmark/auto-resolve/results/20260512-f31-seat-rebalance-headroom/headroom-gate.md +0 -15
  305. package/benchmark/auto-resolve/results/20260512-f32-subscription-renewal-headroom/headroom-gate.json +0 -28
  306. package/benchmark/auto-resolve/results/20260512-f32-subscription-renewal-headroom/headroom-gate.md +0 -15
  307. package/benchmark/auto-resolve/results/20260512-f4-web-headroom/headroom-gate.json +0 -28
  308. package/benchmark/auto-resolve/results/20260512-f4-web-headroom/headroom-gate.md +0 -15
  309. package/benchmark/auto-resolve/results/20260512-f5-fixloop-headroom/headroom-gate.json +0 -28
  310. package/benchmark/auto-resolve/results/20260512-f5-fixloop-headroom/headroom-gate.md +0 -15
  311. package/benchmark/auto-resolve/results/20260512-f6-checksum-headroom/headroom-gate.json +0 -28
  312. package/benchmark/auto-resolve/results/20260512-f6-checksum-headroom/headroom-gate.md +0 -15
  313. package/benchmark/auto-resolve/results/20260512-f7-scope-headroom/headroom-gate.json +0 -28
  314. package/benchmark/auto-resolve/results/20260512-f7-scope-headroom/headroom-gate.md +0 -15
  315. package/benchmark/auto-resolve/results/20260512-f9-e2e-headroom/headroom-gate.json +0 -28
  316. package/benchmark/auto-resolve/results/20260512-f9-e2e-headroom/headroom-gate.md +0 -15
  317. package/benchmark/auto-resolve/run-real-benchmark.md +0 -303
  318. package/benchmark/auto-resolve/scripts/audit-headroom-rejections.py +0 -441
  319. package/benchmark/auto-resolve/scripts/audit-pair-evidence.py +0 -1256
  320. package/benchmark/auto-resolve/scripts/build-pair-eligible-manifest.py +0 -306
  321. package/benchmark/auto-resolve/scripts/check-f9-artifacts.py +0 -268
  322. package/benchmark/auto-resolve/scripts/collect-swebench-predictions.py +0 -108
  323. package/benchmark/auto-resolve/scripts/compile-report.py +0 -493
  324. package/benchmark/auto-resolve/scripts/fetch-swebench-instances.py +0 -129
  325. package/benchmark/auto-resolve/scripts/frozen-verify-gate.py +0 -434
  326. package/benchmark/auto-resolve/scripts/full-pipeline-pair-gate.py +0 -612
  327. package/benchmark/auto-resolve/scripts/headroom-gate.py +0 -378
  328. package/benchmark/auto-resolve/scripts/iter-0033c-compare.py +0 -683
  329. package/benchmark/auto-resolve/scripts/iter-0033c-l1-summary.py +0 -97
  330. package/benchmark/auto-resolve/scripts/judge-opus-pass.sh +0 -542
  331. package/benchmark/auto-resolve/scripts/judge.sh +0 -565
  332. package/benchmark/auto-resolve/scripts/oracle-scope-tier-a.py +0 -256
  333. package/benchmark/auto-resolve/scripts/oracle-scope-tier-b.py +0 -287
  334. package/benchmark/auto-resolve/scripts/oracle-test-fidelity.py +0 -328
  335. package/benchmark/auto-resolve/scripts/pair-candidate-frontier.py +0 -469
  336. package/benchmark/auto-resolve/scripts/pair-plan-idgen.py +0 -401
  337. package/benchmark/auto-resolve/scripts/pair-plan-lint.py +0 -475
  338. package/benchmark/auto-resolve/scripts/pair-rejected-fixtures.sh +0 -103
  339. package/benchmark/auto-resolve/scripts/pair_evidence_contract.py +0 -270
  340. package/benchmark/auto-resolve/scripts/prepare-swebench-frozen-case.py +0 -273
  341. package/benchmark/auto-resolve/scripts/prepare-swebench-frozen-corpus.py +0 -148
  342. package/benchmark/auto-resolve/scripts/prepare-swebench-solver-worktree.py +0 -210
  343. package/benchmark/auto-resolve/scripts/recent-benchmark-summary.py +0 -232
  344. package/benchmark/auto-resolve/scripts/run-fixture.sh +0 -1024
  345. package/benchmark/auto-resolve/scripts/run-frozen-verify-pair.sh +0 -683
  346. package/benchmark/auto-resolve/scripts/run-full-pipeline-pair-candidate.sh +0 -458
  347. package/benchmark/auto-resolve/scripts/run-headroom-candidate.sh +0 -336
  348. package/benchmark/auto-resolve/scripts/run-iter-0033c.sh +0 -208
  349. package/benchmark/auto-resolve/scripts/run-suite.sh +0 -251
  350. package/benchmark/auto-resolve/scripts/run-swebench-frozen-corpus.sh +0 -310
  351. package/benchmark/auto-resolve/scripts/run-swebench-solver-batch.sh +0 -257
  352. package/benchmark/auto-resolve/scripts/ship-gate.py +0 -391
  353. package/benchmark/auto-resolve/scripts/solo-ceiling-avoidance.py +0 -53
  354. package/benchmark/auto-resolve/scripts/solo-headroom-hypothesis.py +0 -77
  355. package/benchmark/auto-resolve/scripts/swebench-frozen-matrix.py +0 -478
  356. package/benchmark/auto-resolve/scripts/test-audit-headroom-rejections.sh +0 -288
  357. package/benchmark/auto-resolve/scripts/test-audit-pair-evidence.sh +0 -1672
  358. package/benchmark/auto-resolve/scripts/test-benchmark-arg-parsing.sh +0 -1015
  359. package/benchmark/auto-resolve/scripts/test-build-pair-eligible-manifest.sh +0 -491
  360. package/benchmark/auto-resolve/scripts/test-check-f9-artifacts.sh +0 -91
  361. package/benchmark/auto-resolve/scripts/test-frozen-verify-gate.sh +0 -517
  362. package/benchmark/auto-resolve/scripts/test-full-pipeline-pair-gate.sh +0 -610
  363. package/benchmark/auto-resolve/scripts/test-headroom-gate.sh +0 -401
  364. package/benchmark/auto-resolve/scripts/test-iter-0033c-compare.sh +0 -525
  365. package/benchmark/auto-resolve/scripts/test-iter-0033c-l1-summary.sh +0 -254
  366. package/benchmark/auto-resolve/scripts/test-lint-fixtures.sh +0 -580
  367. package/benchmark/auto-resolve/scripts/test-pair-candidate-frontier.sh +0 -591
  368. package/benchmark/auto-resolve/scripts/test-run-full-pipeline-pair-candidate.sh +0 -497
  369. package/benchmark/auto-resolve/scripts/test-run-headroom-candidate.sh +0 -401
  370. package/benchmark/auto-resolve/scripts/test-run-swebench-solver-batch.sh +0 -111
  371. package/benchmark/auto-resolve/scripts/test-ship-gate.sh +0 -1189
  372. package/benchmark/auto-resolve/scripts/test-swebench-frozen-case.sh +0 -1221
  373. package/benchmark/auto-resolve/shadow-fixtures/S1-cli-lang-flag/NOTES.md +0 -28
  374. package/benchmark/auto-resolve/shadow-fixtures/S1-cli-lang-flag/expected.json +0 -63
  375. package/benchmark/auto-resolve/shadow-fixtures/S1-cli-lang-flag/metadata.json +0 -10
  376. package/benchmark/auto-resolve/shadow-fixtures/S1-cli-lang-flag/setup.sh +0 -3
  377. package/benchmark/auto-resolve/shadow-fixtures/S1-cli-lang-flag/spec.md +0 -47
  378. package/benchmark/auto-resolve/shadow-fixtures/S1-cli-lang-flag/task.txt +0 -1
  379. package/benchmark/auto-resolve/shadow-fixtures/S2-cli-inventory-reservation/NOTES.md +0 -34
  380. package/benchmark/auto-resolve/shadow-fixtures/S2-cli-inventory-reservation/expected.json +0 -53
  381. package/benchmark/auto-resolve/shadow-fixtures/S2-cli-inventory-reservation/metadata.json +0 -10
  382. package/benchmark/auto-resolve/shadow-fixtures/S2-cli-inventory-reservation/setup.sh +0 -3
  383. package/benchmark/auto-resolve/shadow-fixtures/S2-cli-inventory-reservation/spec.md +0 -50
  384. package/benchmark/auto-resolve/shadow-fixtures/S2-cli-inventory-reservation/task.txt +0 -1
  385. package/benchmark/auto-resolve/shadow-fixtures/S2-cli-inventory-reservation/verifiers/duplicate-order-error.js +0 -27
  386. package/benchmark/auto-resolve/shadow-fixtures/S2-cli-inventory-reservation/verifiers/priority-stock-reservation.js +0 -44
  387. package/benchmark/auto-resolve/shadow-fixtures/S3-cli-ticket-assignment/NOTES.md +0 -34
  388. package/benchmark/auto-resolve/shadow-fixtures/S3-cli-ticket-assignment/expected.json +0 -55
  389. package/benchmark/auto-resolve/shadow-fixtures/S3-cli-ticket-assignment/metadata.json +0 -10
  390. package/benchmark/auto-resolve/shadow-fixtures/S3-cli-ticket-assignment/setup.sh +0 -3
  391. package/benchmark/auto-resolve/shadow-fixtures/S3-cli-ticket-assignment/spec.md +0 -52
  392. package/benchmark/auto-resolve/shadow-fixtures/S3-cli-ticket-assignment/task.txt +0 -1
  393. package/benchmark/auto-resolve/shadow-fixtures/S3-cli-ticket-assignment/verifiers/duplicate-ticket-error.js +0 -29
  394. package/benchmark/auto-resolve/shadow-fixtures/S3-cli-ticket-assignment/verifiers/priority-agent-assignment.js +0 -48
  395. package/benchmark/auto-resolve/shadow-fixtures/S4-cli-return-routing/NOTES.md +0 -34
  396. package/benchmark/auto-resolve/shadow-fixtures/S4-cli-return-routing/expected.json +0 -55
  397. package/benchmark/auto-resolve/shadow-fixtures/S4-cli-return-routing/metadata.json +0 -10
  398. package/benchmark/auto-resolve/shadow-fixtures/S4-cli-return-routing/setup.sh +0 -3
  399. package/benchmark/auto-resolve/shadow-fixtures/S4-cli-return-routing/spec.md +0 -55
  400. package/benchmark/auto-resolve/shadow-fixtures/S4-cli-return-routing/task.txt +0 -1
  401. package/benchmark/auto-resolve/shadow-fixtures/S4-cli-return-routing/verifiers/duplicate-return-error.js +0 -43
  402. package/benchmark/auto-resolve/shadow-fixtures/S4-cli-return-routing/verifiers/priority-return-routing.js +0 -70
  403. package/benchmark/auto-resolve/shadow-fixtures/S5-cli-credit-grant-ledger/NOTES.md +0 -37
  404. package/benchmark/auto-resolve/shadow-fixtures/S5-cli-credit-grant-ledger/expected.json +0 -54
  405. package/benchmark/auto-resolve/shadow-fixtures/S5-cli-credit-grant-ledger/metadata.json +0 -10
  406. package/benchmark/auto-resolve/shadow-fixtures/S5-cli-credit-grant-ledger/setup.sh +0 -3
  407. package/benchmark/auto-resolve/shadow-fixtures/S5-cli-credit-grant-ledger/spec.md +0 -59
  408. package/benchmark/auto-resolve/shadow-fixtures/S5-cli-credit-grant-ledger/task.txt +0 -1
  409. package/benchmark/auto-resolve/shadow-fixtures/S5-cli-credit-grant-ledger/verifiers/credit-ledger-priority.js +0 -98
  410. package/benchmark/auto-resolve/shadow-fixtures/S5-cli-credit-grant-ledger/verifiers/duplicate-charge-error.js +0 -38
  411. package/benchmark/auto-resolve/shadow-fixtures/S6-cli-refund-window-ledger/NOTES.md +0 -36
  412. package/benchmark/auto-resolve/shadow-fixtures/S6-cli-refund-window-ledger/expected.json +0 -56
  413. package/benchmark/auto-resolve/shadow-fixtures/S6-cli-refund-window-ledger/metadata.json +0 -10
  414. package/benchmark/auto-resolve/shadow-fixtures/S6-cli-refund-window-ledger/setup.sh +0 -3
  415. package/benchmark/auto-resolve/shadow-fixtures/S6-cli-refund-window-ledger/spec.md +0 -59
  416. package/benchmark/auto-resolve/shadow-fixtures/S6-cli-refund-window-ledger/task.txt +0 -1
  417. package/benchmark/auto-resolve/shadow-fixtures/S6-cli-refund-window-ledger/verifiers/duplicate-refund-error.js +0 -41
  418. package/benchmark/auto-resolve/shadow-fixtures/S6-cli-refund-window-ledger/verifiers/priority-refund-ledger.js +0 -65
  419. package/config/skills/_shared/pair-plan-schema.md +0 -298
  420. package/scripts/lint-fixtures.sh +0 -352
  421. package/scripts/lint-shadow-fixtures.sh +0 -58
  422. package/scripts/lint-skills.sh +0 -4265
  423. package/scripts/test-owner-phases.py +0 -238
@@ -1,56 +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/priority-refund-ledger.js\"",
11
- "exit_code": 0,
12
- "stdout_contains": ["\"ok\":true"],
13
- "stdout_not_contains": [],
14
- "contract_refs": [
15
- "Process refund requests globally by `priority` descending, then `requested_on` ascending, then original input order ascending.",
16
- "A refund rejects with reason `window_expired` when `requested_on` is more than `refund_window_days` after `purchased_on`.",
17
- "A refund accepts only when the order's remaining refundable cents is at least the requested `cents`.",
18
- "A rejected refund with reason `over_refund` must not change that order's remaining refundable cents.",
19
- "For each accepted refund, decrement that order's remaining refundable cents by the requested `cents`.",
20
- "For each accepted refund, compute `fee_cents` as the category policy's `restocking_fee_cents` capped at the requested `cents`, and compute `net_cents = cents - fee_cents`.",
21
- "`approved` is ordered in processing order. Each row has keys `id`, `order`, `refund_cents`, `fee_cents`, and `net_cents`.",
22
- "`rejected` is ordered in the original input refund order. Each row has keys `id`, `reason`.",
23
- "`orders` is ordered by order id ascending. Each row has keys `id` and `remaining_refundable_cents`.",
24
- "On success, write exactly one JSON object to stdout and no stderr. Keys: `approved`, `rejected`, `orders`."
25
- ]
26
- },
27
- {
28
- "cmd": "node \"$BENCH_FIXTURE_DIR/verifiers/duplicate-refund-error.js\"",
29
- "exit_code": 0,
30
- "stdout_contains": ["\"ok\":true"],
31
- "stdout_not_contains": [],
32
- "contract_refs": [
33
- "Before settling any refund, duplicate refund ids are invalid input: exit `2`, write exactly one JSON error object `{ \"error\": \"duplicate_refund_id\", \"id\": string }` to stderr, and write no stdout."
34
- ]
35
- }
36
- ],
37
- "forbidden_patterns": [
38
- {
39
- "pattern": "catch\\s*\\([^)]*\\)\\s*\\{[^}]*return\\s+(null|undefined|''|\\{\\}|\\[\\])",
40
- "description": "silent catch returning fallback in settle-refunds path",
41
- "files": ["bin/cli.js", "tests/cli.test.js"],
42
- "severity": "disqualifier"
43
- },
44
- {
45
- "pattern": "catch\\s*\\([^)]*\\)\\s*\\{\\s*\\}",
46
- "description": "empty catch block",
47
- "files": ["bin/cli.js", "tests/cli.test.js"],
48
- "severity": "disqualifier"
49
- }
50
- ],
51
- "required_files": ["bin/cli.js", "tests/cli.test.js"],
52
- "forbidden_files": [],
53
- "tier_a_waivers": [],
54
- "spec_output_files": ["bin/cli.js", "tests/cli.test.js"],
55
- "max_deps_added": 0
56
- }
@@ -1,10 +0,0 @@
1
- {
2
- "id": "S6-cli-refund-window-ledger",
3
- "category": "high-risk",
4
- "difficulty": "high",
5
- "timeout_seconds": 900,
6
- "required_tools": ["node"],
7
- "browser": false,
8
- "deps_change_expected": false,
9
- "intent": "Add a refund ledger CLI command that applies category refund windows, priority-ordered refund requests, cumulative per-order refundable balances, duplicate refund rejection, and exact JSON output shape."
10
- }
@@ -1,3 +0,0 @@
1
- #!/usr/bin/env bash
2
- set -euo pipefail
3
- # S6 reuses the baseline test-repo state.
@@ -1,59 +0,0 @@
1
- ---
2
- id: "S6-cli-refund-window-ledger"
3
- title: "Add refund window ledger command"
4
- status: planned
5
- complexity: high
6
- depends-on: []
7
- ---
8
-
9
- # S6 Add Refund Window Ledger Command
10
-
11
- ## Context
12
-
13
- Finance operations needs a deterministic CLI command that settles refund
14
- requests against original orders. The command must combine category refund
15
- windows, priority ordering, cumulative per-order refundable balances, duplicate
16
- id rejection, and exact machine-readable output.
17
-
18
- ## Requirements
19
-
20
- - [ ] Add `settle-refunds` to `bin/cli.js`.
21
- - [ ] Accept `--policies <json>` as a JSON object whose keys are category names and whose values have keys `refund_window_days` and `restocking_fee_cents`.
22
- - [ ] Accept `--orders <json>` as a JSON array of order objects. Each order has keys `id`, `category`, `paid_cents`, `purchased_on`, and `fulfilled`.
23
- - [ ] Accept `--refunds <json>` as a JSON array of refund request objects. Each refund has keys `id`, `order`, `cents`, `priority`, and `requested_on`.
24
- - [ ] Before settling any refund, duplicate refund ids are invalid input: exit `2`, write exactly one JSON error object `{ "error": "duplicate_refund_id", "id": string }` to stderr, and write no stdout.
25
- - [ ] Process refund requests globally by `priority` descending, then `requested_on` ascending, then original input order ascending.
26
- - [ ] A refund rejects with reason `unknown_order` when the order does not exist.
27
- - [ ] A refund rejects with reason `unfulfilled_order` when the order exists but `fulfilled` is not `true`.
28
- - [ ] A refund rejects with reason `unknown_policy` when the order category has no policy.
29
- - [ ] A refund rejects with reason `window_expired` when `requested_on` is more than `refund_window_days` after `purchased_on`.
30
- - [ ] A refund accepts only when the order's remaining refundable cents is at least the requested `cents`.
31
- - [ ] A rejected refund with reason `over_refund` must not change that order's remaining refundable cents.
32
- - [ ] For each accepted refund, decrement that order's remaining refundable cents by the requested `cents`.
33
- - [ ] For each accepted refund, compute `fee_cents` as the category policy's `restocking_fee_cents` capped at the requested `cents`, and compute `net_cents = cents - fee_cents`.
34
- - [ ] `approved` is ordered in processing order. Each row has keys `id`, `order`, `refund_cents`, `fee_cents`, and `net_cents`.
35
- - [ ] `rejected` is ordered in the original input refund order. Each row has keys `id`, `reason`.
36
- - [ ] `orders` is ordered by order id ascending. Each row has keys `id` and `remaining_refundable_cents`.
37
- - [ ] On success, write exactly one JSON object to stdout and no stderr. Keys: `approved`, `rejected`, `orders`.
38
-
39
- ## Constraints
40
-
41
- - Use only Node.js built-ins; add no npm dependencies.
42
- - Touch only `bin/cli.js` and `tests/cli.test.js`.
43
- - Do not silently catch JSON parse or validation errors. Surface invalid input as a user-visible error with nonzero exit.
44
- - Do not persist refund balances between command invocations.
45
- - All public money amounts are integer cents.
46
-
47
- ## Out of Scope
48
-
49
- - Reading input from files.
50
- - Taxes, payment gateway calls, currency conversion, or store-credit issuance.
51
- - Partial approval of a single refund request.
52
- - Changing `hello`, `version`, server routes, or package metadata.
53
-
54
- ## Verification
55
-
56
- - `node --test tests/cli.test.js` passes.
57
- - `node "$BENCH_FIXTURE_DIR/verifiers/priority-refund-ledger.js"` prints `{"ok":true}`.
58
- - `node "$BENCH_FIXTURE_DIR/verifiers/duplicate-refund-error.js"` prints `{"ok":true}`.
59
- - Solo-headroom hypothesis: solo_claude is expected to miss cumulative remaining refundable cents or original-order rejected rows under priority-ordered refund settlement; observable command `node "$BENCH_FIXTURE_DIR/verifiers/priority-refund-ledger.js"` exposes the miss.
@@ -1 +0,0 @@
1
- Add a `settle-refunds` command to bench-cli. It must read policies, orders, and refund requests from JSON CLI arguments, process refund requests by priority, maintain per-order remaining refundable cents, reject duplicates before processing, and emit exact JSON output.
@@ -1,41 +0,0 @@
1
- 'use strict';
2
- const assert = require('node:assert');
3
- const { spawnSync } = require('node:child_process');
4
- const path = require('node:path');
5
-
6
- const work = process.env.BENCH_WORKDIR || process.cwd();
7
- const cli = path.join(work, 'bin', 'cli.js');
8
-
9
- const policies = JSON.stringify({
10
- apparel: { refund_window_days: 45, restocking_fee_cents: 25 }
11
- });
12
- const orders = JSON.stringify([
13
- { id: 'ord-a', category: 'apparel', paid_cents: 600, purchased_on: '2026-01-10', fulfilled: true }
14
- ]);
15
- const refunds = JSON.stringify([
16
- { id: 'dup', order: 'ord-a', cents: 100, priority: 2, requested_on: '2026-01-11' },
17
- { id: 'dup', order: 'ord-a', cents: 100, priority: 1, requested_on: '2026-01-12' }
18
- ]);
19
-
20
- const result = spawnSync('node', [
21
- cli,
22
- 'settle-refunds',
23
- '--policies',
24
- policies,
25
- '--orders',
26
- orders,
27
- '--refunds',
28
- refunds
29
- ], {
30
- cwd: work,
31
- encoding: 'utf8'
32
- });
33
-
34
- assert.strictEqual(result.status, 2, result.stdout || result.stderr);
35
- assert.strictEqual(result.stdout, '');
36
- assert.deepStrictEqual(JSON.parse(result.stderr), {
37
- error: 'duplicate_refund_id',
38
- id: 'dup'
39
- });
40
-
41
- console.log(JSON.stringify({ ok: true }));
@@ -1,65 +0,0 @@
1
- 'use strict';
2
- const assert = require('node:assert');
3
- const { spawnSync } = require('node:child_process');
4
- const path = require('node:path');
5
-
6
- const work = process.env.BENCH_WORKDIR || process.cwd();
7
- const cli = path.join(work, 'bin', 'cli.js');
8
-
9
- const policies = JSON.stringify({
10
- electronics: { refund_window_days: 30, restocking_fee_cents: 150 },
11
- apparel: { refund_window_days: 45, restocking_fee_cents: 25 }
12
- });
13
- const orders = JSON.stringify([
14
- { id: 'ord-a', category: 'electronics', paid_cents: 1000, purchased_on: '2026-01-01', fulfilled: true },
15
- { id: 'ord-b', category: 'apparel', paid_cents: 600, purchased_on: '2026-01-10', fulfilled: true },
16
- { id: 'ord-c', category: 'electronics', paid_cents: 400, purchased_on: '2025-12-01', fulfilled: true },
17
- { id: 'ord-d', category: 'apparel', paid_cents: 500, purchased_on: '2026-01-15', fulfilled: false }
18
- ]);
19
- const refunds = JSON.stringify([
20
- { id: 'low-a', order: 'ord-a', cents: 500, priority: 1, requested_on: '2026-01-08' },
21
- { id: 'expired-c', order: 'ord-c', cents: 100, priority: 9, requested_on: '2026-02-01' },
22
- { id: 'high-a', order: 'ord-a', cents: 800, priority: 10, requested_on: '2026-01-09' },
23
- { id: 'unknown', order: 'missing', cents: 50, priority: 8, requested_on: '2026-01-09' },
24
- { id: 'unfulfilled', order: 'ord-d', cents: 50, priority: 7, requested_on: '2026-01-20' },
25
- { id: 'apparel-ok', order: 'ord-b', cents: 300, priority: 6, requested_on: '2026-01-20' }
26
- ]);
27
-
28
- const result = spawnSync('node', [
29
- cli,
30
- 'settle-refunds',
31
- '--policies',
32
- policies,
33
- '--orders',
34
- orders,
35
- '--refunds',
36
- refunds
37
- ], {
38
- cwd: work,
39
- encoding: 'utf8'
40
- });
41
-
42
- assert.strictEqual(result.status, 0, result.stderr || result.stdout);
43
- assert.strictEqual(result.stderr, '');
44
- const parsed = JSON.parse(result.stdout);
45
-
46
- assert.deepStrictEqual(parsed, {
47
- approved: [
48
- { id: 'high-a', order: 'ord-a', refund_cents: 800, fee_cents: 150, net_cents: 650 },
49
- { id: 'apparel-ok', order: 'ord-b', refund_cents: 300, fee_cents: 25, net_cents: 275 }
50
- ],
51
- rejected: [
52
- { id: 'low-a', reason: 'over_refund' },
53
- { id: 'expired-c', reason: 'window_expired' },
54
- { id: 'unknown', reason: 'unknown_order' },
55
- { id: 'unfulfilled', reason: 'unfulfilled_order' }
56
- ],
57
- orders: [
58
- { id: 'ord-a', remaining_refundable_cents: 200 },
59
- { id: 'ord-b', remaining_refundable_cents: 300 },
60
- { id: 'ord-c', remaining_refundable_cents: 400 },
61
- { id: 'ord-d', remaining_refundable_cents: 500 }
62
- ]
63
- });
64
-
65
- console.log(JSON.stringify({ ok: true }));
@@ -1,298 +0,0 @@
1
- # Shared — `pair-plan.json` schema (iter-0022 archive)
2
-
3
- > **Archive header (iter-0034 Phase 4 cutover, 2026-05-04)** — this schema was iter-0022 infrastructure for the now-deleted `/devlyn:auto-resolve` PHASE 0 plan-pair contract. The `/devlyn:resolve` PHASE 1 PLAN at HEAD runs solo (per iter-0033 (C1) PASS evidence + iter-0033g § "CLOSURE"). The schema is preserved here as a design archive: the unblock conditions for re-instating PLAN-pair (per `iterations/0034-phase-4-cutover.md` § "L2 PLAN-pair research-only label") are A — container/sandbox isolation justified by another product need, OR B — production telemetry captures positive evidence of subagent introspection that a PLAN-pair measurement would need to isolate. When either condition fires, this schema (and the associated lint / idgen / preflight tooling under `benchmark/auto-resolve/scripts/`) is the starting point.
4
-
5
- Single source of truth for `pair-plan.json` and its companion `canonical_id_registry.json` when the architecture re-enters scope. Read this once before editing `pair-plan-idgen.py`, `pair-plan-lint.py`, `pair-plan-preflight.sh`, or any future plan-pair PHASE that consumes `state.plan`.
6
-
7
- ## Audience (when re-instated)
8
-
9
- - `benchmark/auto-resolve/scripts/pair-plan-idgen.py` — produces `canonical_id_registry.json` from `expected.json` + checked-in oracle scripts.
10
- - `benchmark/auto-resolve/scripts/pair-plan-lint.py` — validates a `pair-plan.json` against its registry.
11
- - `autoresearch/scripts/pair-plan-preflight.sh` — orchestrates solo + pair plan generation against blind-aliased fixtures.
12
- - A future `/devlyn:resolve` PHASE 1 plan-pair branch (currently solo; gated on unblock A or B above): would accept `--plan-path` / JSON payload, set `state.plan.{mode, path}`, and run lint before IMPLEMENT, mirroring the deleted `devlyn:auto-resolve` PHASE 0 contract.
13
-
14
- ## File locations and naming (canonical)
15
-
16
- - Registry per fixture: `benchmark/auto-resolve/fixtures/<F>/expected-pair-plan-registry.json` (committed snapshot for diff-against-baseline; iter-0023 verifies the live idgen output equals this snapshot).
17
- - Plan produced by preflight: `benchmark/auto-resolve/results/<run_id>/<blind_fixture>/plan-preflight/merged/pair-plan.json`.
18
- - Plan supplied to a re-instated plan-pair branch by an external caller: any path the user chooses, passed via `--plan-path <path>` (the contract surface is preserved as iter-0022 design archive).
19
- - The registry filename is `canonical_id_registry.json` for **runtime artifacts** — both inside the bundle dir and in the preflight output root. (HANDOFF.md:280 mentions `canonical-ids.json` for the preflight output dir; that name is deprecated — D4 emits `canonical_id_registry.json` to align with the rest of the toolchain.)
20
- - The **committed fixture snapshot** is named `expected-pair-plan-registry.json` (one per fixture, under `benchmark/auto-resolve/fixtures/<F>/`) — distinct file name to make snapshots greppable separately from runtime artifacts. iter-0023 verifies the live idgen output equals the committed snapshot for the same fixture.
21
-
22
- ## `canonical_id_registry.json` shape
23
-
24
- Top-level wrapper:
25
-
26
- ```jsonc
27
- {
28
- "schema_version": "1",
29
- "fixture_id": "F2-cli-medium-subcommand",
30
- "generated_at": "2026-04-29T18:30:00Z",
31
- "generated_from": {
32
- "expected_path": "benchmark/auto-resolve/fixtures/F2-cli-medium-subcommand/expected.json",
33
- "expected_sha256": "...", // raw file bytes sha256
34
- "metadata_path": "benchmark/auto-resolve/fixtures/F2-cli-medium-subcommand/metadata.json",
35
- "metadata_sha256": "...", // raw file bytes sha256
36
- "oracle_script_shas": {
37
- "test-fidelity": "...", // raw bytes sha256 of oracle-test-fidelity.py
38
- "scope-tier-a": "...",
39
- "scope-tier-b": "..."
40
- }
41
- },
42
- "required_invariants": [
43
- {
44
- "id": "...",
45
- "source_field": "expected.json/forbidden_patterns/0 | expected.json/verification_commands/3 | expected.json/required_files | expected.json/forbidden_files | expected.json/max_deps_added | expected.json/spec_output_files | oracle/<oracle-name>/<category-id>",
46
- "source_ref": "expected.json:60 | expected.json/verification_commands/0 | oracle-test-fidelity.py",
47
- "operational_check": "...natural-language description of what the variant must do or must not do...",
48
- "severity": "disqualifier | hard | flag | warn",
49
- "authority": "expected.json/forbidden_patterns | expected.json/verification_commands | expected.json/required_files | expected.json/forbidden_files | expected.json/max_deps_added | expected.json/spec_output_files | metadata/oracle-allowlist"
50
- }
51
- // ...sorted lexicographically by id
52
- ]
53
- }
54
- ```
55
-
56
- **Hard rules**:
57
- - `required_invariants` MUST be sorted lexicographically by `id`. idgen sorts before serializing; lint rejects an unsorted file.
58
- - All file shas (`expected_sha256`, `metadata_sha256`, `oracle_script_shas.*`) are **raw file bytes sha256** — `sha256(open(path, "rb").read())`. NOT canonical-JSON form. (Canonical form is reserved for the pair-plan pre-stamp hash; see below.)
59
- - `info`-severity oracle categories are NOT registry entries (e.g. scope-tier-b's `tier-b-reachable` is a positive signal, not an invariant violation).
60
- - The umbrella oracle category `scope-tier-a:tier-a-violation` is ONE registry entry; the 5 path-glob groups (planning-doc, ci-config, node-modules, test-results-or-coverage, env-secrets) are described inside `operational_check`, not split into 5 entries.
61
-
62
- **Determinism**: same `(expected.json, metadata.json, oracle scripts)` input → byte-identical `canonical_id_registry.json`. Achieved by:
63
- - `json.dumps(obj, sort_keys=True, indent=2, ensure_ascii=False)` for the on-disk file.
64
- - All lists pre-sorted before dumping (registry items by `id`).
65
- - No timestamps that change run-to-run except `generated_at` — see exemption below.
66
-
67
- `generated_at` is the ONE volatile field. Lint ignores it for sha-stability checks; lint's determinism check sets `generated_at` to a fixed value before comparing two consecutive idgen runs. (Implementation: idgen accepts `--generated-at <iso8601>` for testing.)
68
-
69
- ## `pair-plan.json` shape
70
-
71
- ```jsonc
72
- {
73
- "schema_version": "1",
74
- "plan_status": "final | blocked | draft",
75
- "planning_mode": "solo | pair",
76
- "fixture_id": "F2-cli-medium-subcommand", // human label; not authoritative
77
- "source": {
78
- "spec_path": "benchmark/auto-resolve/fixtures/F2-cli-medium-subcommand/spec.md",
79
- "spec_sha256": "...", // raw file bytes
80
- "expected_path": "benchmark/auto-resolve/fixtures/F2-cli-medium-subcommand/expected.json",
81
- "expected_sha256": "...", // raw file bytes (optional only when expected.json absent)
82
- "rubric_path": "benchmark/auto-resolve/RUBRIC.md",
83
- "rubric_sha256": "...", // raw file bytes
84
- "canonical_id_registry_path": "benchmark/auto-resolve/fixtures/F2-cli-medium-subcommand/expected-pair-plan-registry.json",
85
- "canonical_id_registry_sha256": "..." // raw file bytes of the registry file
86
- },
87
- "authority_order": [
88
- "spec.md",
89
- "expected.json/rubric",
90
- "phase prompt",
91
- "model preference"
92
- ],
93
- "rounds": [
94
- {
95
- "round": 1,
96
- "claude_draft_sha256": "...", // raw file bytes of the per-round draft artifact
97
- "codex_draft_sha256": "...",
98
- "merged_sha256": "...",
99
- "note": "..."
100
- }
101
- // up to 3 rounds; iter-0022 preflight stops at the first round where neither model has new substantive critique
102
- ],
103
- "accepted_invariants": [
104
- {
105
- "id": "no_silent_catch_return_fallback",
106
- "paraphrase": "...", // human-readable; informational only, NOT enforced
107
- "source_refs": ["spec.md:36", "expected.json/forbidden_patterns/0"],
108
- "operational_check": "BUILD output must not contain `catch[^{]*\\{[^}]*return [^}]*\\}` in bin/cli.js",
109
- "authority": "expected.json/forbidden_patterns"
110
- }
111
- ],
112
- "rejected_alternatives": [
113
- {
114
- "id": "alt_silent_catch_with_log",
115
- "rationale": "Authority order says expected.json/forbidden_patterns dominates; logging does not change visible-error contract.",
116
- "conflicts_with_ids": ["no_silent_catch_return_fallback"],
117
- "claude_stamp": "rejected",
118
- "codex_stamp": "rejected"
119
- }
120
- ],
121
- "unresolved": [], // MUST be empty in final plans
122
- "escalated_to_user": [], // populated only during draft / blocked status; final must have user_resolution per item if non-empty
123
- "model_stamps": {
124
- "claude": {
125
- "status": "sign | block",
126
- "blocked_ids": [],
127
- "signed_plan_sha256": "...", // canonical pre-stamp sha (see below)
128
- "model": "<exact claude model id>",
129
- "timestamp": "2026-04-29T..."
130
- },
131
- "codex": {
132
- "status": "sign | block",
133
- "blocked_ids": [],
134
- "signed_plan_sha256": "...",
135
- "model": "<exact codex model id>",
136
- "timestamp": "..."
137
- }
138
- }
139
- }
140
- ```
141
-
142
- ## Severity decoupling (registry vs findings)
143
-
144
- The registry's `required_invariants[].severity` taxonomy is **metadata for human review only**: `disqualifier | hard | flag | warn`. It is NOT mapped onto the `references/findings-schema.md` taxonomy used by EVAL / CRITIC findings (`CRITICAL | HIGH | MEDIUM | LOW`). When a phase emits a finding for a missed plan invariant, severity is assigned by that phase's own existing severity policy (per `findings-schema.md`), not by reading the registry severity directly. The two taxonomies serve different audiences (registry severity = "how the oracle classifies it"; findings severity = "what the orchestrator should do about it") and are intentionally not coupled in iter-0022.
145
-
146
- ## Hard rules (lint-enforced)
147
-
148
- 1. `unresolved.length > 0` → `plan_status` MUST be `blocked` or `draft`. Final accepted plan MUST have `unresolved == []`.
149
- 2. `escalated_to_user[]` non-empty → each item MUST carry a `user_resolution` field, OR `plan_status` MUST be `blocked` / `draft`.
150
- 3. Every `accepted_invariants[].id` MUST appear in the registry's `required_invariants[].id` exactly (string match — no paraphrase, no synonym, no new IDs at plan-time). `paraphrase` is informational only.
151
- 4. **Final-plan coverage**: when `plan_status == "final"`, every registry entry MUST be accounted for in the plan — each `required_invariants[].id` is in `accepted_invariants[].id` OR in some `rejected_alternatives[].conflicts_with_ids[]` OR in `escalated_to_user[].id` OR in `unresolved[].id`. (`draft` and `blocked` plans are NOT subject to full coverage; they may still carry un-decided ids in `unresolved[]` per Rule #1.)
152
- 5. `authority_order` MUST be the exact 4-string array `["spec.md", "expected.json/rubric", "phase prompt", "model preference"]` (snapshot at iter-0022 ship time; future iters can amend with explicit `schema_version` bump).
153
- 6. `model_stamps.{claude,codex}.status == "sign"` MUST hold for `plan_status: "final"`. A `block` from either model forces `plan_status` to `blocked` or `draft`.
154
- 7. `model_stamps.{claude,codex}.signed_plan_sha256` MUST be byte-identical AND MUST equal the canonical pre-stamp sha256 of the file (see "Two sha256 contracts" below).
155
- 8. `source.{spec_sha256, expected_sha256, rubric_sha256, canonical_id_registry_sha256}` MUST equal the actual raw-bytes sha256 of the referenced files at lint time (catches stale plans against changed sources).
156
- 9. `source.canonical_id_registry_path` MUST resolve to an existing registry file. lint reads it from this field; if `--registry <path>` is passed on the lint command line, the override wins.
157
- 10. `planning_mode: "pair"` requires `rounds.length >= 1`. `planning_mode: "solo"` requires `rounds.length == 0` (no merge artifacts).
158
-
159
- ## Two sha256 contracts (DO NOT CONFLATE)
160
-
161
- ### Contract A — raw file bytes
162
-
163
- Used for: every `source.*_sha256` field (spec, expected, rubric, registry), every `generated_from.*_sha256` field in the registry, every `rounds[].*_draft_sha256` and `merged_sha256`.
164
-
165
- ```python
166
- import hashlib
167
- with open(path, "rb") as f:
168
- sha = hashlib.sha256(f.read()).hexdigest()
169
- ```
170
-
171
- No canonicalization. The bytes on disk are what gets hashed. This catches "the plan claims spec.md is sha X but spec.md actually has bytes producing sha Y" drift.
172
-
173
- ### Contract B — canonical pre-stamp form (pair-plan stamps only)
174
-
175
- Used for: `model_stamps.claude.signed_plan_sha256` and `model_stamps.codex.signed_plan_sha256`. Both stamps sign **byte-identical** canonical bytes, so both sha values are byte-identical.
176
-
177
- Algorithm (writers and verifiers MUST implement exactly):
178
-
179
- ```python
180
- import json
181
- import hashlib
182
- import copy
183
-
184
- def canonical_pre_stamp_sha256(plan: dict) -> str:
185
- # Reject duplicate keys when LOADING the plan; this function assumes a clean dict.
186
- pre = copy.deepcopy(plan)
187
- pre["model_stamps"] = {} # replace value, keep key
188
- s = json.dumps(
189
- pre,
190
- sort_keys=True,
191
- separators=(",", ":"),
192
- ensure_ascii=False,
193
- allow_nan=False,
194
- )
195
- return hashlib.sha256(s.encode("utf-8")).hexdigest()
196
- ```
197
-
198
- When LOADING the plan, reject duplicate keys:
199
-
200
- ```python
201
- def _strict_pairs(pairs):
202
- keys = [k for k, _ in pairs]
203
- if len(keys) != len(set(keys)):
204
- raise ValueError("duplicate key in pair-plan.json")
205
- return dict(pairs)
206
-
207
- with open(path, "r", encoding="utf-8") as f:
208
- plan = json.load(f, object_pairs_hook=_strict_pairs)
209
- ```
210
-
211
- **Why no Unicode normalization**: the canonical form hashes input bytes as-is. Writers and verifiers must agree on input form (NFC recommended for any user-supplied free-text strings, but not enforced — the scheme survives because both sides derive from the same source bytes).
212
-
213
- **Why no floats**: integer + string serialize byte-stably across implementations. Floats vary (e.g. `1.0` vs `1`). Avoid floats in this schema until a future field absolutely requires one; if added, document the canonical float-printing rule in this file.
214
-
215
- ## Slug rules for registry IDs (idgen)
216
-
217
- When an `expected.json` item lacks an explicit `id` field, idgen synthesizes a deterministic slug.
218
-
219
- ### `forbidden_patterns[i]` slug
220
-
221
- ```
222
- forbidden_pattern__<sanitize(description, 60)>__<sanitize(files[0], 30)>
223
- ```
224
-
225
- `sanitize(s, max_len)`: lowercase; replace any non-`[a-z0-9]` run with a single `_`; strip leading/trailing `_`; truncate to `max_len` (right-truncate, no hash suffix at this level).
226
-
227
- If two items in the same `forbidden_patterns[]` array produce the same slug after sanitization, the FIRST one (by source-array index) keeps the bare slug; each subsequent collision appends `__i<index>`. idgen detects this deterministically by walking the array in order.
228
-
229
- Example F2:
230
- - `forbidden_patterns[0]` (description="silent catch returning a fallback value — violates no-silent-catches policy", files=["bin/cli.js"]) → `forbidden_pattern__silent_catch_returning_a_fallback_value_violate__bin_cli_js`
231
- - `forbidden_patterns[1]` (description="@ts-ignore escape hatch", files=["bin/cli.js"]) → `forbidden_pattern__ts_ignore_escape_hatch__bin_cli_js`
232
-
233
- ### `verification_commands[i]` slug
234
-
235
- ```
236
- verification__<sha8(canonical_json(verification_obj))>
237
- ```
238
-
239
- `canonical_json(obj)`: same compact form as Contract B (`json.dumps(obj, sort_keys=True, separators=(",", ":"), ensure_ascii=False, allow_nan=False)`).
240
- `sha8(s)`: first 8 hex chars of `sha256(s.encode("utf-8"))`.
241
-
242
- The full verification object is hashed (cmd + exit_code + stdout_contains + stdout_not_contains), so reordering the array does not change the slug. Array-index lives in `source_ref` (`expected.json/verification_commands/<i>`) for human navigation only.
243
-
244
- ### Other expected.json fields
245
-
246
- - `required_files`: one registry entry per file path: `required_file__<sanitize(path, 60)>`.
247
- - `forbidden_files`: same shape: `forbidden_file__<sanitize(path, 60)>`.
248
- - `max_deps_added`: one registry entry: `max_deps_added__<value>` (e.g. `max_deps_added__0`).
249
- - `spec_output_files`: one registry entry per path: `spec_output_file__<sanitize(path, 60)>`.
250
-
251
- ### Oracle category IDs (no slug — fixed strings)
252
-
253
- Oracle `--list-categories` returns category IDs in the form `<oracle-name>:<finding-type>`. These are stable strings that idgen passes through verbatim into `required_invariants[].id`. Each oracle script defines its own enum; iter-0022 ship snapshot:
254
-
255
- - `test-fidelity:test-file-deleted`
256
- - `test-fidelity:test-file-renamed`
257
- - `test-fidelity:mock-swap`
258
- - `test-fidelity:assertion-regression`
259
- - `scope-tier-a:lockfile-deletion`
260
- - `scope-tier-a:tier-a-violation`
261
- - `scope-tier-b:scope-unmatched`
262
-
263
- `scope-tier-b:tier-b-reachable` is `info`-severity and NOT a registry entry.
264
-
265
- ## metadata.json field for per-fixture oracle allowlist
266
-
267
- iter-0022 adds one new field to each fixture's `metadata.json`:
268
-
269
- ```json
270
- {
271
- "id": "F2-cli-medium-subcommand",
272
- // ... existing fields unchanged ...
273
- "pair_plan_oracle_categories": [
274
- "test-fidelity:test-file-deleted",
275
- "test-fidelity:test-file-renamed",
276
- "test-fidelity:mock-swap",
277
- "test-fidelity:assertion-regression",
278
- "scope-tier-a:lockfile-deletion",
279
- "scope-tier-a:tier-a-violation",
280
- "scope-tier-b:scope-unmatched"
281
- ]
282
- }
283
- ```
284
-
285
- Hard rule: idgen filters oracle categories to exactly this allowlist. If the field is missing, idgen treats it as the empty array (no oracle categories registered) — `expected.json`-derived invariants still appear. Schema-version bump if the allowlist semantics change.
286
-
287
- The runner `run-fixture.sh` reads `timeout_seconds` (line 54) and the report reads `category` (compile-report.py line 76); no other consumer reads metadata.json today, so adding a new field is a pure metadata enrichment with no scoring implication.
288
-
289
- ## Plan field minimum/maximum policy
290
-
291
- - A field listed in this schema with no "optional" annotation is REQUIRED.
292
- - Fields explicitly marked optional: `source.expected_path` / `source.expected_sha256` (only when `expected.json` is genuinely absent — not the case for any current fixture).
293
- - Unknown extra fields in `pair-plan.json` are NOT rejected by lint (forward-compat), but the canonical pre-stamp sha is computed over the whole object so unknown fields participate in the signature.
294
- - Unknown extra fields in `canonical_id_registry.json` ARE rejected by lint (idgen owns the registry shape; drift here is a bug).
295
-
296
- ## Versioning
297
-
298
- `schema_version` starts at `"1"`. A breaking change to any hard rule above bumps the version and the lint script gains a per-version dispatcher. iter-0022 ships version `1`. Future iters MUST update this file before bumping the version field anywhere else.