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,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.