@1aboveio/skills 0.19.3 → 0.20.2

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 (206) hide show
  1. package/README.md +9 -4
  2. package/package.json +1 -1
  3. package/runtime/skills/distribution/generated/recipes.json +54 -48
  4. package/runtime/skills/distribution/scripts/bundles.mjs +113 -7
  5. package/runtime/skills/engineering/engineering-runtime/scripts/workflow-coherence.mjs +4 -6
  6. package/runtime/skills/engineering/engineering-runtime/scripts/workflow-policy.mjs +3 -36
  7. package/skills/cicd-pipeline/cloud-build/SKILL.md +6 -6
  8. package/skills/cicd-pipeline/mergify/SKILL.md +1 -1
  9. package/skills/engineering/engineering-runtime/coherence/workflow.json +15 -84
  10. package/skills/engineering/engineering-runtime/scripts/workflow-coherence.mjs +4 -6
  11. package/skills/engineering/engineering-runtime/scripts/workflow-policy.mjs +3 -36
  12. package/skills/engineering/rush-release/SKILL.md +46 -25
  13. package/skills/engineering/rush-release/evals/evals.json +22 -8
  14. package/skills/engineering/rush-release/references/cut.md +21 -4
  15. package/skills/engineering/rush-release/references/preflight.md +25 -6
  16. package/skills/engineering/rush-release/references/promotion.md +70 -0
  17. package/skills/engineering/rush-release/references/publish.md +49 -16
  18. package/skills/engineering/rush-release/scripts/plan.mjs +33 -7
  19. package/skills/engineering/smoke/SKILL.md +4 -4
  20. package/skills/engineering/smoke/references/manifest.md +3 -3
  21. package/skills/payment/payment-analysis/SKILL.md +5 -3
  22. package/skills/payment/tld-detection/SKILL.md +163 -0
  23. package/skills/payment/tld-detection/agents/openai.yaml +9 -0
  24. package/skills/payment/tld-detection/evals/evals.json +107 -0
  25. package/skills/payment/tld-detection/references/clean.md +51 -0
  26. package/skills/payment/tld-detection/references/clustering.md +219 -0
  27. package/skills/payment/tld-detection/references/decision.md +85 -0
  28. package/skills/payment/tld-detection/references/report-template.md +169 -0
  29. package/skills/payment/tld-detection/references/terminology.md +69 -0
  30. package/skills/payment/tld-detection/references/workflow.md +78 -0
  31. package/skills/payment/tld-detection/scripts/detect_ladders.py +390 -0
  32. package/skills/payment/tld-detection/tests/test_detect_ladders.py +132 -0
  33. package/skills/engineering/resolve-issues/SKILL.md +0 -168
  34. package/skills/engineering/resolve-issues/agents/openai.yaml +0 -9
  35. package/skills/engineering/resolve-issues/generated/workflow-repair-policy.json +0 -499
  36. package/skills/engineering/resolve-issues/references/breaker.md +0 -82
  37. package/skills/engineering/resolve-issues/references/deliverables.md +0 -27
  38. package/skills/engineering/resolve-issues/references/delivery.md +0 -108
  39. package/skills/engineering/resolve-issues/references/evidence-lane.md +0 -21
  40. package/skills/engineering/resolve-issues/references/exact-head-ci.md +0 -287
  41. package/skills/engineering/resolve-issues/references/fan-out.md +0 -33
  42. package/skills/engineering/resolve-issues/references/finalization.md +0 -68
  43. package/skills/engineering/resolve-issues/references/guarantees.md +0 -10
  44. package/skills/engineering/resolve-issues/references/high-risk.md +0 -29
  45. package/skills/engineering/resolve-issues/references/incidents/848/README.md +0 -156
  46. package/skills/engineering/resolve-issues/references/intake.md +0 -86
  47. package/skills/engineering/resolve-issues/references/integration-gate.md +0 -53
  48. package/skills/engineering/resolve-issues/references/interference.md +0 -87
  49. package/skills/engineering/resolve-issues/references/loop.md +0 -134
  50. package/skills/engineering/resolve-issues/references/model-catalog.md +0 -9
  51. package/skills/engineering/resolve-issues/references/postmortem.md +0 -27
  52. package/skills/engineering/resolve-issues/references/pre-flight-model-slots.md +0 -41
  53. package/skills/engineering/resolve-issues/references/pre-flight-recording-and-checkout.md +0 -48
  54. package/skills/engineering/resolve-issues/references/pre-flight.md +0 -41
  55. package/skills/engineering/resolve-issues/references/regression-checklist.md +0 -26
  56. package/skills/engineering/resolve-issues/references/run-state.md +0 -288
  57. package/skills/engineering/resolve-issues/references/sandboxed-testing.md +0 -48
  58. package/skills/engineering/resolve-issues/references/spawn-contract.md +0 -96
  59. package/skills/engineering/resolve-issues/references/terminal-evidence-journal.md +0 -40
  60. package/skills/engineering/resolve-issues/references/why.md +0 -653
  61. package/skills/engineering/resolve-issues/schemas/fix-round.schema.json +0 -49
  62. package/skills/engineering/resolve-issues/scripts/combine-and-verify.mjs +0 -721
  63. package/skills/engineering/resolve-issues/scripts/component-candidate.mjs +0 -962
  64. package/skills/engineering/resolve-issues/scripts/contract-revision.mjs +0 -220
  65. package/skills/engineering/resolve-issues/scripts/detect-delivery-mode.mjs +0 -420
  66. package/skills/engineering/resolve-issues/scripts/detect-target-branch.mjs +0 -256
  67. package/skills/engineering/resolve-issues/scripts/detect-workspace-mode.mjs +0 -168
  68. package/skills/engineering/resolve-issues/scripts/discover-models.mjs +0 -9
  69. package/skills/engineering/resolve-issues/scripts/doctrine.mjs +0 -62
  70. package/skills/engineering/resolve-issues/scripts/evidence-lifecycle-contract.mjs +0 -191
  71. package/skills/engineering/resolve-issues/scripts/exact-head-ci.mjs +0 -413
  72. package/skills/engineering/resolve-issues/scripts/exact-head-github-provider.mjs +0 -332
  73. package/skills/engineering/resolve-issues/scripts/finalize.mjs +0 -488
  74. package/skills/engineering/resolve-issues/scripts/fix-rounds.mjs +0 -3307
  75. package/skills/engineering/resolve-issues/scripts/fixtures/evidence-lifecycle-circular-1001.json +0 -16
  76. package/skills/engineering/resolve-issues/scripts/fixtures/evidence-lifecycle-valid-sequencing.json +0 -51
  77. package/skills/engineering/resolve-issues/scripts/fixtures/fmm-express-830-component-candidate.json +0 -17
  78. package/skills/engineering/resolve-issues/scripts/fixtures/head-check-set-1081.json +0 -166
  79. package/skills/engineering/resolve-issues/scripts/gate-value-series.mjs +0 -92
  80. package/skills/engineering/resolve-issues/scripts/guide-index.mjs +0 -73
  81. package/skills/engineering/resolve-issues/scripts/head-check-set.mjs +0 -159
  82. package/skills/engineering/resolve-issues/scripts/interference.mjs +0 -427
  83. package/skills/engineering/resolve-issues/scripts/model-catalog.mjs +0 -9
  84. package/skills/engineering/resolve-issues/scripts/next-operations.mjs +0 -419
  85. package/skills/engineering/resolve-issues/scripts/postmortem.mjs +0 -909
  86. package/skills/engineering/resolve-issues/scripts/preflight-questions.mjs +0 -345
  87. package/skills/engineering/resolve-issues/scripts/reconcile-contained-unit-prs.mjs +0 -415
  88. package/skills/engineering/resolve-issues/scripts/release-state-contract.mjs +0 -697
  89. package/skills/engineering/resolve-issues/scripts/report.mjs +0 -494
  90. package/skills/engineering/resolve-issues/scripts/required-check-plan.mjs +0 -172
  91. package/skills/engineering/resolve-issues/scripts/round-metadata.mjs +0 -79
  92. package/skills/engineering/resolve-issues/scripts/run-state-review6-cases.mjs +0 -334
  93. package/skills/engineering/resolve-issues/scripts/run-state.mjs +0 -4792
  94. package/skills/engineering/resolve-issues/scripts/sandbox-selftest.mjs +0 -395
  95. package/skills/engineering/resolve-issues/scripts/spawn-contract.mjs +0 -290
  96. package/skills/engineering/resolve-issues/scripts/terminal-dispositions.mjs +0 -170
  97. package/skills/engineering/resolve-issues/scripts/terminal-evidence-journal.mjs +0 -293
  98. package/skills/engineering/resolve-issues/scripts/unit-kind.mjs +0 -197
  99. package/skills/engineering/resolve-issues/scripts/unit-lifecycle.mjs +0 -127
  100. package/skills/engineering/resolve-issues/scripts/watch-delivery.mjs +0 -893
  101. package/skills/engineering/resolve-issues/scripts/workspaces.mjs +0 -829
  102. package/skills/engineering/resolve-issues/workflows/independent-review.workflow.js +0 -290
  103. package/skills/engineering/resolve-issues/workflows/prior-art-scan.workflow.js +0 -80
  104. package/skills/engineering/resolve-issues/workflows/workflow-smoke.mjs +0 -102
  105. package/skills/engineering/resolve-release/LICENSE +0 -3
  106. package/skills/engineering/resolve-release/SKILL.md +0 -113
  107. package/skills/engineering/resolve-release/agents/openai.yaml +0 -9
  108. package/skills/engineering/resolve-release/references/assembly.md +0 -137
  109. package/skills/engineering/resolve-release/references/auto-when-green.md +0 -56
  110. package/skills/engineering/resolve-release/references/candidate.md +0 -167
  111. package/skills/engineering/resolve-release/references/exposure.md +0 -178
  112. package/skills/engineering/resolve-release/references/handoff.md +0 -24
  113. package/skills/engineering/resolve-release/references/postmortem.md +0 -230
  114. package/skills/engineering/resolve-release/references/preflight.md +0 -208
  115. package/skills/engineering/resolve-release/references/principles.md +0 -94
  116. package/skills/engineering/resolve-release/references/regression-checklist.md +0 -36
  117. package/skills/engineering/resolve-release/references/related-skills.md +0 -13
  118. package/skills/engineering/resolve-release/references/routing.md +0 -149
  119. package/skills/engineering/resolve-release/references/verified-sha-github-flow.md +0 -285
  120. package/skills/engineering/resolve-release/references/versioning.md +0 -202
  121. package/skills/engineering/resolve-release/references/why.md +0 -53
  122. package/skills/engineering/resolve-release/scripts/adapter-completion-artifact.mjs +0 -389
  123. package/skills/engineering/resolve-release/scripts/build-changes.mjs +0 -209
  124. package/skills/engineering/resolve-release/scripts/candidate-hygiene.mjs +0 -407
  125. package/skills/engineering/resolve-release/scripts/candidate-identity.mjs +0 -904
  126. package/skills/engineering/resolve-release/scripts/candidate-traffic.mjs +0 -81
  127. package/skills/engineering/resolve-release/scripts/checked-adapter-loader.mjs +0 -612
  128. package/skills/engineering/resolve-release/scripts/close-attempt.mjs +0 -135
  129. package/skills/engineering/resolve-release/scripts/closeout-release.mjs +0 -161
  130. package/skills/engineering/resolve-release/scripts/doctrine.mjs +0 -106
  131. package/skills/engineering/resolve-release/scripts/durable-processing.mjs +0 -522
  132. package/skills/engineering/resolve-release/scripts/ensure-target-green.mjs +0 -659
  133. package/skills/engineering/resolve-release/scripts/evidence-bundle.mjs +0 -1014
  134. package/skills/engineering/resolve-release/scripts/finalize-release.mjs +0 -526
  135. package/skills/engineering/resolve-release/scripts/fixtures/durable-processing-adapter.mjs +0 -169
  136. package/skills/engineering/resolve-release/scripts/green-gate.mjs +0 -599
  137. package/skills/engineering/resolve-release/scripts/isolated-adapter-evaluator.mjs +0 -752
  138. package/skills/engineering/resolve-release/scripts/metadata-pr-status.mjs +0 -56
  139. package/skills/engineering/resolve-release/scripts/metadata-sync.mjs +0 -1538
  140. package/skills/engineering/resolve-release/scripts/postmortem.mjs +0 -381
  141. package/skills/engineering/resolve-release/scripts/preflight-probes.mjs +0 -510
  142. package/skills/engineering/resolve-release/scripts/production-endpoints.mjs +0 -326
  143. package/skills/engineering/resolve-release/scripts/rc-circuit-breaker.mjs +0 -272
  144. package/skills/engineering/resolve-release/scripts/report.mjs +0 -417
  145. package/skills/engineering/resolve-release/scripts/reprobe-credentials.mjs +0 -114
  146. package/skills/engineering/resolve-release/scripts/revalidate-candidate.mjs +0 -238
  147. package/skills/engineering/resolve-release/scripts/review-packet.mjs +0 -503
  148. package/skills/engineering/resolve-release/scripts/rollback-floor.mjs +0 -263
  149. package/skills/engineering/resolve-release/scripts/version-assert.mjs +0 -339
  150. package/skills/engineering/resolve-release/scripts/version-postmortem.mjs +0 -485
  151. package/skills/engineering/resolve-release/scripts/version.mjs +0 -1199
  152. package/skills/engineering/resolve-release/scripts/watch-candidate-delivery.mjs +0 -449
  153. package/skills/engineering/resolve-release/vendor/ACORN-LICENSE +0 -21
  154. package/skills/engineering/resolve-release/vendor/README.md +0 -60
  155. package/skills/engineering/resolve-release/vendor/acorn.mjs +0 -6233
  156. package/skills/engineering/resolve-release/vendor/quickjs/core/LICENSE +0 -21
  157. package/skills/engineering/resolve-release/vendor/quickjs/core/README.md +0 -341
  158. package/skills/engineering/resolve-release/vendor/quickjs/core/README.template.md +0 -70
  159. package/skills/engineering/resolve-release/vendor/quickjs/core/dist/chunk-TAV5CUKK.mjs +0 -2
  160. package/skills/engineering/resolve-release/vendor/quickjs/core/dist/chunk-TAV5CUKK.mjs.map +0 -1
  161. package/skills/engineering/resolve-release/vendor/quickjs/core/dist/chunk-V2S4ZYJR.mjs +0 -7
  162. package/skills/engineering/resolve-release/vendor/quickjs/core/dist/chunk-V2S4ZYJR.mjs.map +0 -1
  163. package/skills/engineering/resolve-release/vendor/quickjs/core/dist/index.d.mts +0 -2033
  164. package/skills/engineering/resolve-release/vendor/quickjs/core/dist/index.d.ts +0 -2033
  165. package/skills/engineering/resolve-release/vendor/quickjs/core/dist/index.js +0 -7
  166. package/skills/engineering/resolve-release/vendor/quickjs/core/dist/index.js.map +0 -1
  167. package/skills/engineering/resolve-release/vendor/quickjs/core/dist/index.mjs +0 -2
  168. package/skills/engineering/resolve-release/vendor/quickjs/core/dist/index.mjs.map +0 -1
  169. package/skills/engineering/resolve-release/vendor/quickjs/core/dist/module-ES6BEMUI.mjs +0 -2
  170. package/skills/engineering/resolve-release/vendor/quickjs/core/dist/module-ES6BEMUI.mjs.map +0 -1
  171. package/skills/engineering/resolve-release/vendor/quickjs/core/dist/module-asyncify-2EFITU5U.mjs +0 -2
  172. package/skills/engineering/resolve-release/vendor/quickjs/core/dist/module-asyncify-2EFITU5U.mjs.map +0 -1
  173. package/skills/engineering/resolve-release/vendor/quickjs/core/package.json +0 -49
  174. package/skills/engineering/resolve-release/vendor/quickjs/ffi-types/LICENSE +0 -21
  175. package/skills/engineering/resolve-release/vendor/quickjs/ffi-types/README.md +0 -5
  176. package/skills/engineering/resolve-release/vendor/quickjs/ffi-types/dist/index.d.mts +0 -549
  177. package/skills/engineering/resolve-release/vendor/quickjs/ffi-types/dist/index.d.ts +0 -549
  178. package/skills/engineering/resolve-release/vendor/quickjs/ffi-types/dist/index.js +0 -2
  179. package/skills/engineering/resolve-release/vendor/quickjs/ffi-types/dist/index.js.map +0 -1
  180. package/skills/engineering/resolve-release/vendor/quickjs/ffi-types/dist/index.mjs +0 -2
  181. package/skills/engineering/resolve-release/vendor/quickjs/ffi-types/dist/index.mjs.map +0 -1
  182. package/skills/engineering/resolve-release/vendor/quickjs/ffi-types/package.json +0 -36
  183. package/skills/engineering/resolve-release/vendor/quickjs/release-sync/LICENSE +0 -47
  184. package/skills/engineering/resolve-release/vendor/quickjs/release-sync/README.md +0 -82
  185. package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/emscripten-module.browser.d.ts +0 -11
  186. package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/emscripten-module.browser.mjs +0 -22
  187. package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/emscripten-module.cjs +0 -21
  188. package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/emscripten-module.cloudflare.cjs +0 -21
  189. package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/emscripten-module.cloudflare.d.ts +0 -11
  190. package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/emscripten-module.d.ts +0 -11
  191. package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/emscripten-module.mjs +0 -25
  192. package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/emscripten-module.wasm +0 -0
  193. package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/ffi.d.mts +0 -85
  194. package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/ffi.d.ts +0 -85
  195. package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/ffi.js +0 -2
  196. package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/ffi.js.map +0 -1
  197. package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/ffi.mjs +0 -2
  198. package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/ffi.mjs.map +0 -1
  199. package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/index.d.mts +0 -20
  200. package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/index.d.ts +0 -20
  201. package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/index.js +0 -2
  202. package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/index.js.map +0 -1
  203. package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/index.mjs +0 -2
  204. package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/index.mjs.map +0 -1
  205. package/skills/engineering/resolve-release/vendor/quickjs/release-sync/package.json +0 -61
  206. /package/skills/{engineering/resolve-issues → payment/tld-detection}/LICENSE +0 -0
@@ -1,172 +0,0 @@
1
- import fs from 'node:fs'
2
- import { execFileSync } from 'node:child_process'
3
- import { parseMergifyYaml } from '../../engineering-runtime/scripts/mergify-yaml.mjs'
4
- import { isMainModule } from '../../engineering-runtime/scripts/main-module.mjs'
5
- import { validateRequiredCheckPlan } from '../../engineering-runtime/scripts/required-check-plan.mjs'
6
-
7
- const nonEmpty = (value) => typeof value === 'string' && value.trim().length > 0
8
- const unique = (values) => [...new Set(values.filter(nonEmpty))]
9
-
10
- function structuralConditionTree(value, label) {
11
- if (typeof value === 'string' && value.trim()) return { condition: value.trim() }
12
- if (!value || typeof value !== 'object' || Array.isArray(value)) throw new Error(`${label} must be a condition string or and/or mapping`)
13
- const keys = Object.keys(value)
14
- if (keys.length !== 1 || !['and', 'or'].includes(keys[0])) throw new Error(`${label} has unsupported condition structure`)
15
- const children = value[keys[0]]
16
- if (!Array.isArray(children) || children.length === 0) throw new Error(`${label}.${keys[0]} must be a non-empty array`)
17
- return { [keys[0] === 'and' ? 'all' : 'any']: children.map((child, index) => structuralConditionTree(child, `${label}.${keys[0]}[${index}]`)) }
18
- }
19
-
20
- const MERGIFY_PHASES = {
21
- queue_conditions: { id: 'queue-entry', phase: 'pr-head', source: 'queue_conditions' },
22
- merge_conditions: { id: 'queue-merge', phase: 'queue-head', source: 'merge_conditions' },
23
- auto_merge_conditions: { id: 'auto-enqueue', phase: 'pr-head', source: 'auto_merge_conditions' },
24
- success_conditions: { id: 'merge-protection', phase: 'pr-head', source: 'success_conditions' },
25
- }
26
-
27
- export function mergifyDiscovery(yaml) {
28
- const document = parseMergifyYaml(yaml)
29
- const phases = []
30
- const phaseCounts = new Map()
31
- const collect = (value, label = 'root') => {
32
- if (!value || typeof value !== 'object') return
33
- if (Array.isArray(value)) return value.forEach((entry, index) => collect(entry, `${label}[${index}]`))
34
- for (const [key, child] of Object.entries(value)) {
35
- const at = `${label}.${key}`
36
- const shape = MERGIFY_PHASES[key]
37
- if (shape) {
38
- if (!Array.isArray(child) || child.length === 0) throw new Error(`${at} must be a non-empty condition array`)
39
- const trees = [{ all: child.map((entry, index) => structuralConditionTree(entry, `${at}[${index}]`)) }]
40
- const leaves = (tree) => tree.condition ? [tree.condition] : (tree.all || tree.any || []).flatMap(leaves)
41
- const count = (phaseCounts.get(shape.id) ?? 0) + 1
42
- phaseCounts.set(shape.id, count)
43
- phases.push({ ...shape, id: count === 1 ? shape.id : `${shape.id}:${count}`, source: `${shape.source}@${at}`, trees, conditions: unique(trees.flatMap(leaves)) })
44
- }
45
- collect(child, at)
46
- }
47
- }
48
- collect(document)
49
- if (!phases.length) throw new Error('Mergify YAML has no merge-admission condition sections')
50
- const leaves = (tree) => tree.condition ? [tree.condition] : (tree.all || tree.any || []).flatMap(leaves)
51
- const trees = phases.flatMap((phase) => phase.trees)
52
- return { phases, trees, conditions: unique(trees.flatMap(leaves)) }
53
- }
54
-
55
- export function mergifyConditions(yaml) { return mergifyDiscovery(yaml).conditions }
56
-
57
- function matchRefPattern(pattern, targetBranch, defaultBranch) {
58
- if (pattern === '~ALL') return true
59
- if (pattern === '~DEFAULT_BRANCH') {
60
- if (!nonEmpty(defaultBranch)) throw new Error('GitHub default branch is required to evaluate ~DEFAULT_BRANCH ruleset conditions')
61
- return targetBranch === defaultBranch
62
- }
63
- if (!nonEmpty(pattern)) throw new Error('ruleset ref_name include/exclude must contain non-empty strings')
64
- if (!/^[A-Za-z0-9._/*?/-]+$/.test(pattern)) throw new Error(`unsupported ruleset ref_name pattern ${JSON.stringify(pattern)}`)
65
- const expression = '^' + pattern.split('*').map((segment) => segment.split('?').map((part) => part.replace(/[.*+^${}()|[\]\\]/g, '\\$&')).join('[^/]')).join('.*') + '$'
66
- return new RegExp(expression).test(targetBranch)
67
- }
68
-
69
- function rulesetApplies(ruleset, { targetBranch, defaultBranch }) {
70
- if (ruleset?.enforcement && ruleset.enforcement !== 'active') return false
71
- if (ruleset?.target && ruleset.target !== 'branch') throw new Error(`unsupported ruleset target ${JSON.stringify(ruleset.target)}`)
72
- const conditions = ruleset?.conditions
73
- if (conditions == null) return true
74
- if (!conditions || typeof conditions !== 'object' || Array.isArray(conditions) || Object.keys(conditions).length !== 1 || !Object.hasOwn(conditions, 'ref_name')) throw new Error('unsupported or ambiguous GitHub ruleset condition structure')
75
- const ref = conditions.ref_name
76
- if (!ref || typeof ref !== 'object' || Array.isArray(ref) || Object.keys(ref).some((key) => !['include', 'exclude'].includes(key)) || !Array.isArray(ref.include) || !Array.isArray(ref.exclude)) throw new Error('unsupported or ambiguous GitHub ruleset ref_name condition shape')
77
- const included = ref.include.some((pattern) => matchRefPattern(pattern, targetBranch, defaultBranch))
78
- const excluded = ref.exclude.some((pattern) => matchRefPattern(pattern, targetBranch, defaultBranch))
79
- return included && !excluded
80
- }
81
-
82
- export function githubConditions(rulesets, { targetBranch, defaultBranch, withDiscovery = false } = {}) {
83
- const conditions = []
84
- const applicable = []
85
- for (const ruleset of Array.isArray(rulesets) ? rulesets : []) {
86
- if (!rulesetApplies(ruleset, { targetBranch, defaultBranch })) continue
87
- applicable.push({ id: ruleset?.id ?? null, target: ruleset?.target ?? 'branch', enforcement: ruleset?.enforcement ?? 'active', conditions: ruleset?.conditions ?? null })
88
- for (const rule of ruleset?.rules || []) {
89
- if (rule?.type !== 'required_status_checks') continue
90
- for (const check of rule.parameters?.required_status_checks || []) if (nonEmpty(check.context)) conditions.push('required_status_checks: ' + check.context)
91
- }
92
- }
93
- const result = { conditions: unique(conditions), rulesets: applicable }
94
- return withDiscovery ? result : result.conditions
95
- }
96
-
97
- const checksFrom = (conditions) => conditions.filter((condition) => /^required_status_checks:\s*|^check-success\s*=\s*/.test(condition)).map((condition) => condition.replace(/^required_status_checks:\s*|^check-success\s*=\s*/, '')).filter(nonEmpty)
98
-
99
- export function buildRequiredCheckPlan({ repository, targetBranch, defaultBranch, headSha, githubRulesets, mergifyYaml, mappings = {}, allowedSkippedJobs = [] }) {
100
- const githubResult = githubConditions(githubRulesets, { targetBranch, defaultBranch, withDiscovery: true })
101
- const github = githubResult.conditions
102
- const mergifyResult = mergifyDiscovery(mergifyYaml)
103
- const mergify = mergifyResult.conditions
104
- const requiredChecks = unique([...checksFrom(github), ...checksFrom(mergify)]).sort()
105
- const leaves = (tree) => tree.condition ? [tree.condition] : (tree.all || tree.any || []).flatMap(leaves)
106
- const checks = requiredChecks.map((name) => {
107
- const mapping = mappings[name]
108
- if (!mapping) throw new Error('live required check ' + name + ' has no classification/evidence mapping; classify it locally-reproduced or publish-only before freeze')
109
- const phases = unique([
110
- ...(github.includes('required_status_checks: ' + name) ? ['pr-head'] : []),
111
- ...mergifyResult.phases.filter((phase) => phase.trees.flatMap(leaves).includes('check-success = ' + name)).map((phase) => phase.phase),
112
- ])
113
- const sources = [...(github.includes('required_status_checks: ' + name) ? ['github-ruleset'] : []), ...mergifyResult.phases.filter((phase) => phase.trees.flatMap(leaves).includes('check-success = ' + name)).map((phase) => `mergify:${phase.id}`)]
114
- const queueEvidence = phases.includes('queue-head')
115
- ? mapping.queueEvidence ?? { provider: mapping.evidence?.provider ?? 'github', acquisition: 'github-check-runs' }
116
- : undefined
117
- return { name, admission: 'required', sources, phases, ...mapping, ...(queueEvidence ? { queueEvidence } : {}) }
118
- })
119
- const tree = (condition) => ({ condition })
120
- const plan = { version: 2, kind: 'required-check-plan', repository, targetBranch, headSha, discovery: { github: { conditions: github, trees: github.map(tree), rulesets: githubResult.rulesets }, mergify: { conditions: mergify, trees: mergifyResult.trees, phases: mergifyResult.phases }, requiredChecks }, checks, allowedSkippedJobs }
121
- const verdict = validateRequiredCheckPlan(plan, { expectedHeadSha: headSha })
122
- if (!verdict.ok) throw new Error('invalid discovered required-check plan: ' + verdict.errors.join('; '))
123
- return plan
124
- }
125
-
126
- function parseArgs(argv) {
127
- const options = {}
128
- for (let index = 0; index < argv.length; index += 1) {
129
- const arg = argv[index]
130
- if (arg === '--repository') options.repository = argv[++index]
131
- else if (arg === '--target') options.targetBranch = argv[++index]
132
- else if (arg === '--head') options.headSha = argv[++index]
133
- else if (arg === '--mappings') options.mappings = argv[++index]
134
- else if (arg === '--allowed-skipped-jobs') options.allowedSkippedJobs = argv[++index]
135
- else if (arg === '--out') options.out = argv[++index]
136
- else if (arg === '--help' || arg === '-h') options.help = true
137
- else throw new Error('unknown argument ' + arg)
138
- }
139
- return options
140
- }
141
-
142
- function ghJson(args) { return JSON.parse(execFileSync('gh', args, { encoding: 'utf8' })) }
143
-
144
- export function runCli(argv) {
145
- let options
146
- try { options = parseArgs(argv) } catch (error) { console.error('required-check-plan: ' + error.message); return 2 }
147
- if (options.help) {
148
- console.log('required-check-plan --repository owner/name --target main --head <40-sha> --mappings mappings.json [--allowed-skipped-jobs skips.json] --out required-check-plan.json')
149
- return 0
150
- }
151
- if (![options.repository, options.targetBranch, options.headSha, options.mappings, options.out].every(nonEmpty)) {
152
- console.error('required-check-plan requires --repository --target --head --mappings --out')
153
- return 2
154
- }
155
- try {
156
- const summary = ghJson(['api', 'repos/' + options.repository + '/rulesets'])
157
- const repository = ghJson(['api', 'repos/' + options.repository])
158
- const defaultBranch = repository.default_branch
159
- if (!nonEmpty(defaultBranch)) throw new Error('GitHub repository default_branch is unavailable; cannot evaluate ruleset conditions')
160
- const githubRulesets = summary.map((ruleset) => ghJson(['api', 'repos/' + options.repository + '/rulesets/' + ruleset.id]))
161
- const content = ghJson(['api', 'repos/' + options.repository + '/contents/.mergify.yml?ref=' + options.targetBranch])
162
- const mergifyYaml = Buffer.from(content.content.replace(/\s/g, ''), 'base64').toString('utf8')
163
- const mappings = JSON.parse(fs.readFileSync(options.mappings, 'utf8'))
164
- const allowedSkippedJobs = options.allowedSkippedJobs ? JSON.parse(fs.readFileSync(options.allowedSkippedJobs, 'utf8')) : []
165
- const plan = buildRequiredCheckPlan({ repository: options.repository, targetBranch: options.targetBranch, defaultBranch, headSha: options.headSha, githubRulesets, mergifyYaml, mappings, allowedSkippedJobs })
166
- fs.writeFileSync(options.out, JSON.stringify(plan, null, 2) + '\n')
167
- console.log('required-check-plan: discovered ' + plan.checks.length + ' live required checks at ' + plan.headSha)
168
- return 0
169
- } catch (error) { console.error('required-check-plan: ' + error.message); return 1 }
170
- }
171
-
172
- if (isMainModule(import.meta.url)) process.exit(runCli(process.argv.slice(2)))
@@ -1,79 +0,0 @@
1
- import { execFileSync } from 'node:child_process'
2
-
3
- export const CHANGED_SURFACES = [
4
- 'runtime',
5
- 'tests',
6
- 'verification-harness',
7
- 'evidence',
8
- 'docs',
9
- 'none',
10
- ]
11
-
12
- export const LEGACY_CHANGED_SURFACE = 'unknown'
13
-
14
- const SURFACE_ORDER = new Map(CHANGED_SURFACES.map((surface, index) => [surface, index]))
15
- const TEST_PATH = /(?:^|\/)(?:test|tests|__tests__|spec|specs)(?:\/|$)|\.(?:test|spec)\.[^/]+$/i
16
- const EVIDENCE_PATH = /(?:^|\/)(?:evidence|artifacts?|screenshots?|snapshots?|traces?)(?:\/|$)|(?:coverage-checklist|smoke-results|smoke-verdict|runtime-smoke)\.(?:json|md)$/i
17
- const DOC_PATH = /(?:^|\/)(?:docs?|documentation)(?:\/|$)|\.(?:md|mdx|rst|adoc|txt)$/i
18
- const HARNESS_PATH = /(?:^|\/)(?:e2e|harness|verification|validators?|sanitizers?|gates?|scripts)(?:\/|$)|(?:^|\/)(?:run-state|coverage-ledger|coverage-checklist|lint-tests|scan-diff)\.mjs$/i
19
-
20
- const normalizedPath = (value) => String(value).replaceAll('\\', '/').replace(/^\.\//, '')
21
-
22
- export function classifyChangedPath(file) {
23
- const value = normalizedPath(file)
24
- if (!value) return null
25
- if (TEST_PATH.test(value)) return 'tests'
26
- if (EVIDENCE_PATH.test(value)) return 'evidence'
27
- if (DOC_PATH.test(value)) return 'docs'
28
- if (HARNESS_PATH.test(value)) return 'verification-harness'
29
- return 'runtime'
30
- }
31
-
32
- export function normalizeChangedSurfaces(surfaces, { legacy = false } = {}) {
33
- const allowed = legacy ? [...CHANGED_SURFACES, LEGACY_CHANGED_SURFACE] : CHANGED_SURFACES
34
- if (!Array.isArray(surfaces) || !surfaces.length) {
35
- throw new Error(`changedSurfaces must be a non-empty array of ${allowed.join('|')}`)
36
- }
37
- const unique = [...new Set(surfaces)]
38
- const bad = unique.find((surface) => !allowed.includes(surface))
39
- if (bad) throw new Error(`changedSurfaces[] must each be one of ${allowed.join('|')} (got ${JSON.stringify(bad)})`)
40
- if (unique.includes('none') && unique.length !== 1) {
41
- throw new Error('changedSurfaces "none" is exclusive and cannot be combined with another surface')
42
- }
43
- if (unique.includes(LEGACY_CHANGED_SURFACE) && unique.length !== 1) {
44
- throw new Error('changedSurfaces "unknown" is a legacy-only exclusive classification')
45
- }
46
- return unique.sort((a, b) => (SURFACE_ORDER.get(a) ?? Number.MAX_SAFE_INTEGER) - (SURFACE_ORDER.get(b) ?? Number.MAX_SAFE_INTEGER))
47
- }
48
-
49
- export function classifyChangedPaths(paths) {
50
- const surfaces = [...new Set((Array.isArray(paths) ? paths : []).map(classifyChangedPath).filter(Boolean))]
51
- return normalizeChangedSurfaces(surfaces.length ? surfaces : ['none'])
52
- }
53
-
54
- export function deriveChangedSurfaces({ cwd = process.cwd(), fromRef, toRef = 'HEAD' } = {}) {
55
- if (typeof fromRef !== 'string' || !fromRef.trim()) throw new Error('fromRef is required to derive changedSurfaces')
56
- if (typeof toRef !== 'string' || !toRef.trim()) throw new Error('toRef is required to derive changedSurfaces')
57
- let output
58
- try {
59
- output = execFileSync(
60
- 'git',
61
- ['diff', '--name-only', '--no-renames', '-z', fromRef, toRef, '--'],
62
- { cwd, encoding: 'buffer', maxBuffer: 64 * 1024 * 1024, stdio: ['ignore', 'pipe', 'pipe'] },
63
- )
64
- } catch (error) {
65
- const detail = error.stderr?.toString().trim() || error.message
66
- throw new Error(`cannot derive changedSurfaces from ${fromRef}..${toRef}: ${detail}`)
67
- }
68
- const paths = output.toString('utf8').split('\0').filter(Boolean)
69
- return classifyChangedPaths(paths)
70
- }
71
-
72
- export function assertChangedSurfacesMatch(actual, expected) {
73
- const declared = normalizeChangedSurfaces(actual)
74
- const derived = normalizeChangedSurfaces(expected)
75
- if (JSON.stringify(declared) !== JSON.stringify(derived)) {
76
- throw new Error(`changedSurfaces override ${JSON.stringify(declared)} does not match diff-derived ${JSON.stringify(derived)}`)
77
- }
78
- return derived
79
- }
@@ -1,334 +0,0 @@
1
- // The sole round-7 source of truth for the contract-complete public matrix.
2
- // Keep the 42 case objects literal: the executor and durable evidence consume
3
- // these objects rather than maintaining a parallel declaration.
4
-
5
- export const MATRIX_THEME = {
6
- id: 'generic-writer-composability',
7
- kind: 'concurrency',
8
- contract: 'Generic writes preserve durable roster identity and dependency-bound history across every run-state state and task kind.',
9
- stateSpace: {
10
- states: [
11
- 'staged-manifest',
12
- 'new-versionless-unit',
13
- 'new-v2-unit',
14
- 'existing-versionless-unit',
15
- 'existing-v2-unit',
16
- 'existing-protected-unit',
17
- 'malformed-legacy-unit',
18
- ],
19
- taskKinds: ['set', 'merge', 'upsert-unit', 'validate', 'migrate-unit', 'round-transition'],
20
- },
21
- }
22
-
23
- const NOW = '2026-07-17T00:00:00.000Z'
24
- const unit = (id = '#809', extra = {}) => ({ id, status: 'in-progress', ...extra })
25
- const v2 = (id = '#809', extra = {}) => unit(id, { stateVersion: 2, ...extra })
26
- const protectedHistory = [
27
- { round: 1, verdict: 'PASS', themes: [] },
28
- ]
29
- const protectedUnit = (extra = {}) => v2('#protected', {
30
- status: 'in-progress',
31
- pr: '#334',
32
- branch: 'feat/809-contract-complete-fix-rounds',
33
- reviewHistory: structuredClone(protectedHistory),
34
- fixRounds: [],
35
- ...extra,
36
- })
37
- const malformedUnits = () => [unit('#malformed', { reviewHistory: { malformed: true }, fixRounds: ['malformed'] })]
38
-
39
- export function fixtureFor(arrange) {
40
- switch (arrange) {
41
- case 'staged-empty':
42
- return { models: { implementation: 'impl' } }
43
- case 'new-versionless-empty':
44
- return {}
45
- case 'new-versionless':
46
- return { units: [unit('#809')] }
47
- case 'new-v2-empty':
48
- return {}
49
- case 'new-v2':
50
- return { units: [v2('#809')] }
51
- case 'existing-versionless':
52
- return { units: [unit('#809')] }
53
- case 'existing-v2':
54
- return { units: [v2('#809')] }
55
- case 'existing-protected':
56
- return { units: [protectedUnit()] }
57
- case 'existing-protected-roster':
58
- return { units: [protectedUnit(), unit('#ordinary', { stateVersion: 2, status: 'queued' })] }
59
- case 'malformed-legacy':
60
- return { units: malformedUnits() }
61
- default:
62
- throw new Error(`unknown round-7 arrangement ${arrange}`)
63
- }
64
- }
65
-
66
- const json = (value) => JSON.stringify(value)
67
- const operation = (command, args, expectedExitStatus, stderrClass, mutation, assertion, expected = {}) => ({
68
- argv: [command, '<slug>', ...args, '--now', NOW],
69
- expectedExitStatus,
70
- stderrClass,
71
- mutation,
72
- assertion,
73
- expected,
74
- })
75
- const reject = (command, args, stderrClass, mutation = 'none/raw-byte-identical', assertion = 'rejection') => operation(command, args, 1, stderrClass, mutation, assertion)
76
- const accept = (command, args, mutation, assertion, expected = {}) => operation(command, args, 0, 'empty', mutation, assertion, expected)
77
- const readAccept = (args = []) => operation('validate', args, 0, 'validation-success', 'none/raw-byte-identical', 'read-only')
78
- const transition = (commands) => ({
79
- commands,
80
- expectedExitStatus: 0,
81
- stderrClass: 'empty',
82
- mutation: 'append-only-transition',
83
- assertion: 'transition',
84
- })
85
- const transitionCommand = (command, unitId, payload, expected) => ({ command, unitId, payload, expected })
86
- const transitionReject = (commands) => ({
87
- commands,
88
- expectedExitStatus: 1,
89
- stderrClass: 'transition-rejection',
90
- mutation: 'none/raw-byte-identical',
91
- assertion: 'rejection',
92
- })
93
- const markerRewrite = (command, args) => reject(command, args, 'generic-rejection', 'none/raw-byte-identical', 'rejection')
94
- const metadata = (command, args, expectedUnit) => accept(command, args, 'exact-delta', 'metadata', { unit: expectedUnit })
95
- export const MATRIX_CASES = [
96
- {
97
- caseId: 'staged-manifest--set', state: 'staged-manifest', taskKind: 'set', arrange: 'staged-empty',
98
- operation: accept('set', ['models.implementation', 'impl-next'], 'exact-delta', 'model-add', { models: { implementation: 'impl-next' } }),
99
- protectedState: [], testLocator: 'run-state-review6-cases.mjs:97', evidenceLocator: 'docs/evidence/809-runtime-smoke.json:199',
100
- },
101
- {
102
- caseId: 'staged-manifest--merge', state: 'staged-manifest', taskKind: 'merge', arrange: 'staged-empty',
103
- operation: accept('merge', [json({ models: { review: 'review' } })], 'exact-delta', 'model-add', { models: { review: 'review' } }),
104
- protectedState: [], testLocator: 'run-state-review6-cases.mjs:102', evidenceLocator: 'docs/evidence/809-runtime-smoke.json:237',
105
- },
106
- {
107
- caseId: 'staged-manifest--upsert-unit', state: 'staged-manifest', taskKind: 'upsert-unit', arrange: 'staged-empty',
108
- operation: accept('upsert-unit', [json(unit('#queued', { status: 'queued' }))], 'exact-delta', 'new-id', { unit: unit('#queued', { status: 'queued' }), order: ['#queued'] }),
109
- protectedState: [], testLocator: 'run-state-review6-cases.mjs:107', evidenceLocator: 'docs/evidence/809-runtime-smoke.json:274',
110
- },
111
- {
112
- caseId: 'staged-manifest--validate', state: 'staged-manifest', taskKind: 'validate', arrange: 'staged-empty',
113
- operation: reject('validate', [], 'validation-rejection'), protectedState: [], testLocator: 'run-state-review6-cases.mjs:112', evidenceLocator: 'docs/evidence/809-runtime-smoke.json:312',
114
- },
115
- {
116
- caseId: 'staged-manifest--migrate-unit', state: 'staged-manifest', taskKind: 'migrate-unit', arrange: 'staged-empty',
117
- operation: reject('migrate-unit', ['#missing', '--version', '1'], 'migration-rejection'), protectedState: [], testLocator: 'run-state-review6-cases.mjs:116', evidenceLocator: 'docs/evidence/809-runtime-smoke.json:347',
118
- },
119
- {
120
- caseId: 'staged-manifest--round-transition', state: 'staged-manifest', taskKind: 'round-transition', arrange: 'staged-empty',
121
- operation: transitionReject([
122
- transitionCommand('record-review-round', '#missing', { round: 1, verdict: 'PASS', findings: [] }, { type: 'reject' }),
123
- transitionCommand('record-fix-round', '#missing', { round: 1, reviewRound: 1, themeId: 'missing' }, { type: 'reject' }),
124
- ]), protectedState: [], testLocator: 'run-state-review6-cases.mjs:120', evidenceLocator: 'docs/evidence/809-runtime-smoke.json:385',
125
- },
126
-
127
- {
128
- caseId: 'new-versionless-unit--set', state: 'new-versionless-unit', taskKind: 'set', arrange: 'new-versionless-empty',
129
- operation: accept('set', ['units', json([unit('#809', { status: 'queued' })])], 'exact-delta', 'create-v1', { unit: unit('#809', { status: 'queued' }), order: ['#809'] }),
130
- protectedState: [], testLocator: 'run-state-review6-cases.mjs:128', evidenceLocator: 'docs/evidence/809-runtime-smoke.json:434',
131
- },
132
- {
133
- caseId: 'new-versionless-unit--merge', state: 'new-versionless-unit', taskKind: 'merge', arrange: 'new-versionless-empty',
134
- operation: accept('merge', [json({ units: [unit('#809', { status: 'queued' })] })], 'exact-delta', 'create-v1', { unit: unit('#809', { status: 'queued' }), order: ['#809'] }),
135
- protectedState: [], testLocator: 'run-state-review6-cases.mjs:133', evidenceLocator: 'docs/evidence/809-runtime-smoke.json:472',
136
- },
137
- {
138
- caseId: 'new-versionless-unit--upsert-unit', state: 'new-versionless-unit', taskKind: 'upsert-unit', arrange: 'new-versionless-empty',
139
- operation: accept('upsert-unit', [json(unit('#809', { status: 'queued' }))], 'exact-delta', 'create-v1', { unit: unit('#809', { status: 'queued' }), order: ['#809'] }),
140
- protectedState: [], testLocator: 'run-state-review6-cases.mjs:138', evidenceLocator: 'docs/evidence/809-runtime-smoke.json:509',
141
- },
142
- {
143
- caseId: 'new-versionless-unit--validate', state: 'new-versionless-unit', taskKind: 'validate', arrange: 'new-versionless',
144
- operation: readAccept(), protectedState: [], testLocator: 'run-state-review6-cases.mjs:143', evidenceLocator: 'docs/evidence/809-runtime-smoke.json:546',
145
- },
146
- {
147
- caseId: 'new-versionless-unit--migrate-unit', state: 'new-versionless-unit', taskKind: 'migrate-unit', arrange: 'new-versionless',
148
- operation: accept('migrate-unit', ['#809', '--version', '1'], 'migration', 'migration', { unit: v2('#809', { status: 'in-progress', reviewHistory: [] }) }),
149
- protectedState: [], testLocator: 'run-state-review6-cases.mjs:147', evidenceLocator: 'docs/evidence/809-runtime-smoke.json:581',
150
- },
151
- {
152
- caseId: 'new-versionless-unit--round-transition', state: 'new-versionless-unit', taskKind: 'round-transition', arrange: 'new-versionless',
153
- operation: transitionReject([
154
- transitionCommand('record-review-round', '#809', { round: 1, verdict: 'PASS', findings: [] }, { type: 'reject' }),
155
- transitionCommand('record-fix-round', '#809', { round: 1, reviewRound: 1, themeId: 'missing' }, { type: 'reject' }),
156
- ]), protectedState: [], testLocator: 'run-state-review6-cases.mjs:152', evidenceLocator: 'docs/evidence/809-runtime-smoke.json:620',
157
- },
158
-
159
- {
160
- caseId: 'new-v2-unit--set', state: 'new-v2-unit', taskKind: 'set', arrange: 'new-v2-empty',
161
- operation: accept('set', ['units', json([v2('#809', { status: 'queued' })])], 'exact-delta', 'create-v2', { unit: v2('#809', { status: 'queued' }), order: ['#809'] }),
162
- protectedState: [], testLocator: 'run-state-review6-cases.mjs:160', evidenceLocator: 'docs/evidence/809-runtime-smoke.json:669',
163
- },
164
- {
165
- caseId: 'new-v2-unit--merge', state: 'new-v2-unit', taskKind: 'merge', arrange: 'new-v2-empty',
166
- operation: accept('merge', [json({ units: [v2('#809', { status: 'queued' })] })], 'exact-delta', 'create-v2', { unit: v2('#809', { status: 'queued' }), order: ['#809'] }),
167
- protectedState: [], testLocator: 'run-state-review6-cases.mjs:165', evidenceLocator: 'docs/evidence/809-runtime-smoke.json:707',
168
- },
169
- {
170
- caseId: 'new-v2-unit--upsert-unit', state: 'new-v2-unit', taskKind: 'upsert-unit', arrange: 'new-v2-empty',
171
- operation: accept('upsert-unit', [json(v2('#809', { status: 'queued' }))], 'exact-delta', 'create-v2', { unit: v2('#809', { status: 'queued' }), order: ['#809'] }),
172
- protectedState: [], testLocator: 'run-state-review6-cases.mjs:170', evidenceLocator: 'docs/evidence/809-runtime-smoke.json:744',
173
- },
174
- {
175
- caseId: 'new-v2-unit--validate', state: 'new-v2-unit', taskKind: 'validate', arrange: 'new-v2',
176
- operation: readAccept(), protectedState: [], testLocator: 'run-state-review6-cases.mjs:175', evidenceLocator: 'docs/evidence/809-runtime-smoke.json:781',
177
- },
178
- {
179
- caseId: 'new-v2-unit--migrate-unit', state: 'new-v2-unit', taskKind: 'migrate-unit', arrange: 'new-v2',
180
- operation: reject('migrate-unit', ['#809', '--version', '1'], 'migration-rejection'), protectedState: [], testLocator: 'run-state-review6-cases.mjs:179', evidenceLocator: 'docs/evidence/809-runtime-smoke.json:816',
181
- },
182
- {
183
- caseId: 'new-v2-unit--round-transition', state: 'new-v2-unit', taskKind: 'round-transition', arrange: 'new-v2',
184
- operation: transition([
185
- transitionCommand('record-review-round', '#809', { round: 1, verdict: 'PASS', findings: [] }, {
186
- type: 'review-append',
187
- record: { round: 1, verdict: 'PASS', themes: [] },
188
- }),
189
- ]), protectedState: [], testLocator: 'run-state-review6-cases.mjs:183', evidenceLocator: 'docs/evidence/809-runtime-smoke.json:854',
190
- },
191
-
192
- {
193
- caseId: 'existing-versionless-unit--set', state: 'existing-versionless-unit', taskKind: 'set', arrange: 'existing-versionless',
194
- operation: markerRewrite('set', ['units', json([unit('#809', { status: 'queued', stateVersion: 2 })])]),
195
- variants: [{ name: 'ordinary metadata is allowed', arrange: 'existing-versionless', operation: metadata('set', ['units', json([unit('#809', { status: 'merge-ready', pr: '#809', lastVerdict: 'PASS' })])], unit('#809', { status: 'merge-ready', pr: '#809', lastVerdict: 'PASS' })) }],
196
- protectedState: [], testLocator: 'run-state-review6-cases.mjs:193', evidenceLocator: 'docs/evidence/809-runtime-smoke.json:892',
197
- },
198
- {
199
- caseId: 'existing-versionless-unit--merge', state: 'existing-versionless-unit', taskKind: 'merge', arrange: 'existing-versionless',
200
- operation: markerRewrite('merge', [json({ units: [unit('#809', { status: 'queued', stateVersion: 2 })] })]),
201
- variants: [{ name: 'ordinary metadata is allowed', arrange: 'existing-versionless', operation: metadata('merge', [json({ units: [unit('#809', { status: 'merge-ready', pr: '#809', lastVerdict: 'PASS' })] })], unit('#809', { status: 'merge-ready', pr: '#809', lastVerdict: 'PASS' })) }],
202
- protectedState: [], testLocator: 'run-state-review6-cases.mjs:199', evidenceLocator: 'docs/evidence/809-runtime-smoke.json:961',
203
- },
204
- {
205
- caseId: 'existing-versionless-unit--upsert-unit', state: 'existing-versionless-unit', taskKind: 'upsert-unit', arrange: 'existing-versionless',
206
- operation: markerRewrite('upsert-unit', [json(v2('#809', { status: 'queued' }))]),
207
- variants: [{ name: 'ordinary metadata is allowed', arrange: 'existing-versionless', operation: metadata('upsert-unit', [json(unit('#809', { status: 'merge-ready', pr: '#809', lastVerdict: 'PASS' }))], unit('#809', { status: 'merge-ready', pr: '#809', lastVerdict: 'PASS' })) }],
208
- protectedState: [], testLocator: 'run-state-review6-cases.mjs:205', evidenceLocator: 'docs/evidence/809-runtime-smoke.json:1028',
209
- },
210
- {
211
- caseId: 'existing-versionless-unit--validate', state: 'existing-versionless-unit', taskKind: 'validate', arrange: 'existing-versionless',
212
- operation: readAccept(), protectedState: [], testLocator: 'run-state-review6-cases.mjs:211', evidenceLocator: 'docs/evidence/809-runtime-smoke.json:1095',
213
- },
214
- {
215
- caseId: 'existing-versionless-unit--migrate-unit', state: 'existing-versionless-unit', taskKind: 'migrate-unit', arrange: 'existing-versionless',
216
- operation: accept('migrate-unit', ['#809', '--version', '1'], 'migration', 'migration', { unit: v2('#809', { status: 'in-progress', reviewHistory: [] }) }),
217
- protectedState: [], testLocator: 'run-state-review6-cases.mjs:215', evidenceLocator: 'docs/evidence/809-runtime-smoke.json:1130',
218
- },
219
- {
220
- caseId: 'existing-versionless-unit--round-transition', state: 'existing-versionless-unit', taskKind: 'round-transition', arrange: 'existing-versionless',
221
- operation: transitionReject([
222
- transitionCommand('record-review-round', '#809', { round: 1, verdict: 'PASS', findings: [] }, { type: 'reject' }),
223
- transitionCommand('record-fix-round', '#809', { round: 1, reviewRound: 1, themeId: 'missing' }, { type: 'reject' }),
224
- ]), protectedState: [], testLocator: 'run-state-review6-cases.mjs:220', evidenceLocator: 'docs/evidence/809-runtime-smoke.json:1169',
225
- },
226
-
227
- {
228
- caseId: 'existing-v2-unit--set', state: 'existing-v2-unit', taskKind: 'set', arrange: 'existing-v2',
229
- operation: metadata('set', ['units', json([v2('#809', { status: 'merge-ready', pr: '#334', branch: 'feat/809-contract-complete-fix-rounds', lastVerdict: 'PASS' })])], v2('#809', { status: 'merge-ready', pr: '#334', branch: 'feat/809-contract-complete-fix-rounds', lastVerdict: 'PASS' })),
230
- protectedState: [], testLocator: 'run-state-review6-cases.mjs:228', evidenceLocator: 'docs/evidence/809-runtime-smoke.json:1218',
231
- },
232
- {
233
- caseId: 'existing-v2-unit--merge', state: 'existing-v2-unit', taskKind: 'merge', arrange: 'existing-v2',
234
- operation: metadata('merge', [json({ units: [v2('#809', { status: 'merge-ready', pr: '#334', branch: 'feat/809-contract-complete-fix-rounds', lastVerdict: 'PASS' })] })], v2('#809', { status: 'merge-ready', pr: '#334', branch: 'feat/809-contract-complete-fix-rounds', lastVerdict: 'PASS' })),
235
- protectedState: [], testLocator: 'run-state-review6-cases.mjs:233', evidenceLocator: 'docs/evidence/809-runtime-smoke.json:1257',
236
- },
237
- {
238
- caseId: 'existing-v2-unit--upsert-unit', state: 'existing-v2-unit', taskKind: 'upsert-unit', arrange: 'existing-v2',
239
- operation: metadata('upsert-unit', [json({ id: '#809', status: 'merge-ready', pr: '#334', branch: 'feat/809-contract-complete-fix-rounds', lastVerdict: 'PASS' })], v2('#809', { status: 'merge-ready', pr: '#334', branch: 'feat/809-contract-complete-fix-rounds', lastVerdict: 'PASS' })),
240
- protectedState: [], testLocator: 'run-state-review6-cases.mjs:238', evidenceLocator: 'docs/evidence/809-runtime-smoke.json:1295',
241
- },
242
- {
243
- caseId: 'existing-v2-unit--validate', state: 'existing-v2-unit', taskKind: 'validate', arrange: 'existing-v2',
244
- operation: readAccept(), protectedState: [], testLocator: 'run-state-review6-cases.mjs:243', evidenceLocator: 'docs/evidence/809-runtime-smoke.json:1333',
245
- },
246
- {
247
- caseId: 'existing-v2-unit--migrate-unit', state: 'existing-v2-unit', taskKind: 'migrate-unit', arrange: 'existing-v2',
248
- operation: reject('migrate-unit', ['#809', '--version', '1'], 'migration-rejection'), protectedState: [], testLocator: 'run-state-review6-cases.mjs:247', evidenceLocator: 'docs/evidence/809-runtime-smoke.json:1368',
249
- },
250
- {
251
- caseId: 'existing-v2-unit--round-transition', state: 'existing-v2-unit', taskKind: 'round-transition', arrange: 'existing-v2',
252
- operation: transition([
253
- transitionCommand('record-review-round', '#809', { round: 1, verdict: 'PASS', findings: [] }, {
254
- type: 'review-append',
255
- record: { round: 1, verdict: 'PASS', themes: [] },
256
- }),
257
- ]), protectedState: [], testLocator: 'run-state-review6-cases.mjs:251', evidenceLocator: 'docs/evidence/809-runtime-smoke.json:1406',
258
- },
259
-
260
- {
261
- caseId: 'existing-protected-unit--set', state: 'existing-protected-unit', taskKind: 'set', arrange: 'existing-protected',
262
- operation: metadata('set', ['units', json([protectedUnit({ status: 'merge-ready', pr: '#334', branch: 'feat/809-contract-complete-fix-rounds', lastVerdict: 'PASS' })])], protectedUnit({ status: 'merge-ready', pr: '#334', branch: 'feat/809-contract-complete-fix-rounds', lastVerdict: 'PASS' })),
263
- variants: [
264
- { name: 'reorder complete protected roster', arrange: 'existing-protected-roster', operation: accept('set', ['units', json([unit('#ordinary', { stateVersion: 2, status: 'queued' }), protectedUnit()])], 'exact-delta', 'reorder', { order: ['#ordinary', '#protected'] }) },
265
- { name: 'add a new ID through set', arrange: 'existing-protected-roster', operation: accept('set', ['units', json([protectedUnit(), unit('#ordinary', { stateVersion: 2, status: 'queued' }), unit('#new', { status: 'queued' })])], 'exact-delta', 'new-id', { unit: unit('#new', { status: 'queued' }), order: ['#protected', '#ordinary', '#new'] }) },
266
- { name: 'protected history mutation rejects', arrange: 'existing-protected', operation: reject('set', ['units', json([protectedUnit({ reviewHistory: [...protectedHistory, { round: 2, verdict: 'PASS', themes: [] }] })])], 'generic-rejection') },
267
- ],
268
- protectedState: ['#protected'], testLocator: 'run-state-review6-cases.mjs:261', evidenceLocator: 'docs/evidence/809-runtime-smoke.json:1444',
269
- },
270
- {
271
- caseId: 'existing-protected-unit--merge', state: 'existing-protected-unit', taskKind: 'merge', arrange: 'existing-protected',
272
- operation: metadata('merge', [json({ units: [protectedUnit({ status: 'merge-ready', pr: '#334', branch: 'feat/809-contract-complete-fix-rounds', lastVerdict: 'PASS' })] })], protectedUnit({ status: 'merge-ready', pr: '#334', branch: 'feat/809-contract-complete-fix-rounds', lastVerdict: 'PASS' })),
273
- variants: [
274
- { name: 'add a new ID while retaining protected roster', arrange: 'existing-protected-roster', operation: accept('merge', [json({ units: [protectedUnit(), unit('#ordinary', { stateVersion: 2, status: 'queued' }), unit('#new', { status: 'queued' })] })], 'exact-delta', 'new-id', { unit: unit('#new', { status: 'queued' }), order: ['#protected', '#ordinary', '#new'] }) },
275
- { name: 'reorder complete roster through merge', arrange: 'existing-protected-roster', operation: accept('merge', [json({ units: [unit('#ordinary', { stateVersion: 2, status: 'queued' }), protectedUnit()] })], 'exact-delta', 'reorder', { order: ['#ordinary', '#protected'] }) },
276
- { name: 'protected history mutation rejects', arrange: 'existing-protected', operation: reject('merge', [json({ units: [protectedUnit({ fixRounds: [{ round: 1 }] })] })], 'generic-rejection') },
277
- ],
278
- protectedState: ['#protected'], testLocator: 'run-state-review6-cases.mjs:271', evidenceLocator: 'docs/evidence/809-runtime-smoke.json:1571',
279
- },
280
- {
281
- caseId: 'existing-protected-unit--upsert-unit', state: 'existing-protected-unit', taskKind: 'upsert-unit', arrange: 'existing-protected',
282
- operation: metadata('upsert-unit', [json({ id: '#protected', status: 'merge-ready', pr: '#334', branch: 'feat/809-contract-complete-fix-rounds', lastVerdict: 'PASS' })], protectedUnit({ status: 'merge-ready', pr: '#334', branch: 'feat/809-contract-complete-fix-rounds', lastVerdict: 'PASS' })),
283
- variants: [
284
- { name: 'protected history mutation rejects', arrange: 'existing-protected', operation: reject('upsert-unit', [json({ id: '#protected', reviewHistory: [...protectedHistory, { round: 2, verdict: 'PASS', themes: [] }] })], 'generic-rejection') },
285
- { name: 'add a new ID through upsert-unit', arrange: 'existing-protected-roster', operation: accept('upsert-unit', [json(unit('#new', { status: 'queued' }))], 'exact-delta', 'new-id', { unit: unit('#new', { status: 'queued' }), order: ['#protected', '#ordinary', '#new'] }) },
286
- ],
287
- protectedState: ['#protected'], testLocator: 'run-state-review6-cases.mjs:281', evidenceLocator: 'docs/evidence/809-runtime-smoke.json:1694',
288
- },
289
- {
290
- caseId: 'existing-protected-unit--validate', state: 'existing-protected-unit', taskKind: 'validate', arrange: 'existing-protected',
291
- operation: readAccept(), protectedState: ['#protected'], testLocator: 'run-state-review6-cases.mjs:290', evidenceLocator: 'docs/evidence/809-runtime-smoke.json:1789',
292
- },
293
- {
294
- caseId: 'existing-protected-unit--migrate-unit', state: 'existing-protected-unit', taskKind: 'migrate-unit', arrange: 'existing-protected',
295
- operation: reject('migrate-unit', ['#protected', '--version', '1'], 'migration-rejection'), protectedState: ['#protected'], testLocator: 'run-state-review6-cases.mjs:294', evidenceLocator: 'docs/evidence/809-runtime-smoke.json:1824',
296
- },
297
- {
298
- caseId: 'existing-protected-unit--round-transition', state: 'existing-protected-unit', taskKind: 'round-transition', arrange: 'existing-protected',
299
- operation: transitionReject([
300
- // Pre-#888 deep history is readable, but appending without universal typed rounds
301
- // would keep writing the old schema. Reconstruct unknown classifications first.
302
- transitionCommand('record-review-round', '#protected', { round: 2, verdict: 'PASS', findings: [] }, { type: 'reject' }),
303
- ]), protectedState: ['#protected'], testLocator: 'run-state-review6-cases.mjs:298', evidenceLocator: 'docs/evidence/809-runtime-smoke.json:1862',
304
- },
305
- {
306
- caseId: 'malformed-legacy-unit--set', state: 'malformed-legacy-unit', taskKind: 'set', arrange: 'malformed-legacy',
307
- operation: reject('set', ['units', json([unit('#malformed', { status: 'merge-ready', reviewHistory: { malformed: true }, fixRounds: ['malformed'] })])], 'generic-rejection'), protectedState: [], testLocator: 'run-state-review6-cases.mjs:306', evidenceLocator: 'docs/evidence/809-runtime-smoke.json:1899',
308
- },
309
- {
310
- caseId: 'malformed-legacy-unit--merge', state: 'malformed-legacy-unit', taskKind: 'merge', arrange: 'malformed-legacy',
311
- operation: reject('merge', [json({ units: [unit('#malformed', { status: 'merge-ready' })] })], 'generic-rejection'), protectedState: [], testLocator: 'run-state-review6-cases.mjs:310', evidenceLocator: 'docs/evidence/809-runtime-smoke.json:1936',
312
- },
313
- {
314
- caseId: 'malformed-legacy-unit--upsert-unit', state: 'malformed-legacy-unit', taskKind: 'upsert-unit', arrange: 'malformed-legacy',
315
- operation: reject('upsert-unit', [json({ id: '#malformed', status: 'merge-ready' })], 'generic-rejection'), protectedState: [], testLocator: 'run-state-review6-cases.mjs:314', evidenceLocator: 'docs/evidence/809-runtime-smoke.json:1972',
316
- },
317
- {
318
- caseId: 'malformed-legacy-unit--validate', state: 'malformed-legacy-unit', taskKind: 'validate', arrange: 'malformed-legacy',
319
- operation: reject('validate', [], 'validation-rejection'), protectedState: [], testLocator: 'run-state-review6-cases.mjs:318', evidenceLocator: 'docs/evidence/809-runtime-smoke.json:2008',
320
- },
321
- {
322
- caseId: 'malformed-legacy-unit--migrate-unit', state: 'malformed-legacy-unit', taskKind: 'migrate-unit', arrange: 'malformed-legacy',
323
- operation: reject('migrate-unit', ['#malformed', '--version', '1'], 'migration-rejection'), protectedState: [], testLocator: 'run-state-review6-cases.mjs:322', evidenceLocator: 'docs/evidence/809-runtime-smoke.json:2043',
324
- },
325
- {
326
- caseId: 'malformed-legacy-unit--round-transition', state: 'malformed-legacy-unit', taskKind: 'round-transition', arrange: 'malformed-legacy',
327
- operation: transitionReject([
328
- transitionCommand('record-review-round', '#malformed', { round: 1, verdict: 'PASS', findings: [] }, { type: 'reject' }),
329
- transitionCommand('record-fix-round', '#malformed', { round: 1, reviewRound: 1, themeId: 'missing' }, { type: 'reject' }),
330
- ]), protectedState: [], testLocator: 'run-state-review6-cases.mjs:326', evidenceLocator: 'docs/evidence/809-runtime-smoke.json:2081',
331
- },
332
- ]
333
-
334
- if (MATRIX_CASES.length !== 42) throw new Error(`round-6 matrix must contain exactly 42 literal cases; got ${MATRIX_CASES.length}`)