@1aboveio/skills 0.19.3 → 0.20.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (197) 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/mergify/SKILL.md +1 -1
  8. package/skills/engineering/engineering-runtime/coherence/workflow.json +14 -83
  9. package/skills/engineering/engineering-runtime/scripts/workflow-coherence.mjs +4 -6
  10. package/skills/engineering/engineering-runtime/scripts/workflow-policy.mjs +3 -36
  11. package/skills/engineering/smoke/SKILL.md +1 -1
  12. package/skills/payment/payment-analysis/SKILL.md +5 -3
  13. package/skills/payment/tld-detection/SKILL.md +163 -0
  14. package/skills/payment/tld-detection/agents/openai.yaml +9 -0
  15. package/skills/payment/tld-detection/evals/evals.json +107 -0
  16. package/skills/payment/tld-detection/references/clean.md +51 -0
  17. package/skills/payment/tld-detection/references/clustering.md +219 -0
  18. package/skills/payment/tld-detection/references/decision.md +85 -0
  19. package/skills/payment/tld-detection/references/report-template.md +169 -0
  20. package/skills/payment/tld-detection/references/terminology.md +69 -0
  21. package/skills/payment/tld-detection/references/workflow.md +78 -0
  22. package/skills/payment/tld-detection/scripts/detect_ladders.py +390 -0
  23. package/skills/payment/tld-detection/tests/test_detect_ladders.py +132 -0
  24. package/skills/engineering/resolve-issues/SKILL.md +0 -168
  25. package/skills/engineering/resolve-issues/agents/openai.yaml +0 -9
  26. package/skills/engineering/resolve-issues/generated/workflow-repair-policy.json +0 -499
  27. package/skills/engineering/resolve-issues/references/breaker.md +0 -82
  28. package/skills/engineering/resolve-issues/references/deliverables.md +0 -27
  29. package/skills/engineering/resolve-issues/references/delivery.md +0 -108
  30. package/skills/engineering/resolve-issues/references/evidence-lane.md +0 -21
  31. package/skills/engineering/resolve-issues/references/exact-head-ci.md +0 -287
  32. package/skills/engineering/resolve-issues/references/fan-out.md +0 -33
  33. package/skills/engineering/resolve-issues/references/finalization.md +0 -68
  34. package/skills/engineering/resolve-issues/references/guarantees.md +0 -10
  35. package/skills/engineering/resolve-issues/references/high-risk.md +0 -29
  36. package/skills/engineering/resolve-issues/references/incidents/848/README.md +0 -156
  37. package/skills/engineering/resolve-issues/references/intake.md +0 -86
  38. package/skills/engineering/resolve-issues/references/integration-gate.md +0 -53
  39. package/skills/engineering/resolve-issues/references/interference.md +0 -87
  40. package/skills/engineering/resolve-issues/references/loop.md +0 -134
  41. package/skills/engineering/resolve-issues/references/model-catalog.md +0 -9
  42. package/skills/engineering/resolve-issues/references/postmortem.md +0 -27
  43. package/skills/engineering/resolve-issues/references/pre-flight-model-slots.md +0 -41
  44. package/skills/engineering/resolve-issues/references/pre-flight-recording-and-checkout.md +0 -48
  45. package/skills/engineering/resolve-issues/references/pre-flight.md +0 -41
  46. package/skills/engineering/resolve-issues/references/regression-checklist.md +0 -26
  47. package/skills/engineering/resolve-issues/references/run-state.md +0 -288
  48. package/skills/engineering/resolve-issues/references/sandboxed-testing.md +0 -48
  49. package/skills/engineering/resolve-issues/references/spawn-contract.md +0 -96
  50. package/skills/engineering/resolve-issues/references/terminal-evidence-journal.md +0 -40
  51. package/skills/engineering/resolve-issues/references/why.md +0 -653
  52. package/skills/engineering/resolve-issues/schemas/fix-round.schema.json +0 -49
  53. package/skills/engineering/resolve-issues/scripts/combine-and-verify.mjs +0 -721
  54. package/skills/engineering/resolve-issues/scripts/component-candidate.mjs +0 -962
  55. package/skills/engineering/resolve-issues/scripts/contract-revision.mjs +0 -220
  56. package/skills/engineering/resolve-issues/scripts/detect-delivery-mode.mjs +0 -420
  57. package/skills/engineering/resolve-issues/scripts/detect-target-branch.mjs +0 -256
  58. package/skills/engineering/resolve-issues/scripts/detect-workspace-mode.mjs +0 -168
  59. package/skills/engineering/resolve-issues/scripts/discover-models.mjs +0 -9
  60. package/skills/engineering/resolve-issues/scripts/doctrine.mjs +0 -62
  61. package/skills/engineering/resolve-issues/scripts/evidence-lifecycle-contract.mjs +0 -191
  62. package/skills/engineering/resolve-issues/scripts/exact-head-ci.mjs +0 -413
  63. package/skills/engineering/resolve-issues/scripts/exact-head-github-provider.mjs +0 -332
  64. package/skills/engineering/resolve-issues/scripts/finalize.mjs +0 -488
  65. package/skills/engineering/resolve-issues/scripts/fix-rounds.mjs +0 -3307
  66. package/skills/engineering/resolve-issues/scripts/fixtures/evidence-lifecycle-circular-1001.json +0 -16
  67. package/skills/engineering/resolve-issues/scripts/fixtures/evidence-lifecycle-valid-sequencing.json +0 -51
  68. package/skills/engineering/resolve-issues/scripts/fixtures/fmm-express-830-component-candidate.json +0 -17
  69. package/skills/engineering/resolve-issues/scripts/fixtures/head-check-set-1081.json +0 -166
  70. package/skills/engineering/resolve-issues/scripts/gate-value-series.mjs +0 -92
  71. package/skills/engineering/resolve-issues/scripts/guide-index.mjs +0 -73
  72. package/skills/engineering/resolve-issues/scripts/head-check-set.mjs +0 -159
  73. package/skills/engineering/resolve-issues/scripts/interference.mjs +0 -427
  74. package/skills/engineering/resolve-issues/scripts/model-catalog.mjs +0 -9
  75. package/skills/engineering/resolve-issues/scripts/next-operations.mjs +0 -419
  76. package/skills/engineering/resolve-issues/scripts/postmortem.mjs +0 -909
  77. package/skills/engineering/resolve-issues/scripts/preflight-questions.mjs +0 -345
  78. package/skills/engineering/resolve-issues/scripts/reconcile-contained-unit-prs.mjs +0 -415
  79. package/skills/engineering/resolve-issues/scripts/release-state-contract.mjs +0 -697
  80. package/skills/engineering/resolve-issues/scripts/report.mjs +0 -494
  81. package/skills/engineering/resolve-issues/scripts/required-check-plan.mjs +0 -172
  82. package/skills/engineering/resolve-issues/scripts/round-metadata.mjs +0 -79
  83. package/skills/engineering/resolve-issues/scripts/run-state-review6-cases.mjs +0 -334
  84. package/skills/engineering/resolve-issues/scripts/run-state.mjs +0 -4792
  85. package/skills/engineering/resolve-issues/scripts/sandbox-selftest.mjs +0 -395
  86. package/skills/engineering/resolve-issues/scripts/spawn-contract.mjs +0 -290
  87. package/skills/engineering/resolve-issues/scripts/terminal-dispositions.mjs +0 -170
  88. package/skills/engineering/resolve-issues/scripts/terminal-evidence-journal.mjs +0 -293
  89. package/skills/engineering/resolve-issues/scripts/unit-kind.mjs +0 -197
  90. package/skills/engineering/resolve-issues/scripts/unit-lifecycle.mjs +0 -127
  91. package/skills/engineering/resolve-issues/scripts/watch-delivery.mjs +0 -893
  92. package/skills/engineering/resolve-issues/scripts/workspaces.mjs +0 -829
  93. package/skills/engineering/resolve-issues/workflows/independent-review.workflow.js +0 -290
  94. package/skills/engineering/resolve-issues/workflows/prior-art-scan.workflow.js +0 -80
  95. package/skills/engineering/resolve-issues/workflows/workflow-smoke.mjs +0 -102
  96. package/skills/engineering/resolve-release/LICENSE +0 -3
  97. package/skills/engineering/resolve-release/SKILL.md +0 -113
  98. package/skills/engineering/resolve-release/agents/openai.yaml +0 -9
  99. package/skills/engineering/resolve-release/references/assembly.md +0 -137
  100. package/skills/engineering/resolve-release/references/auto-when-green.md +0 -56
  101. package/skills/engineering/resolve-release/references/candidate.md +0 -167
  102. package/skills/engineering/resolve-release/references/exposure.md +0 -178
  103. package/skills/engineering/resolve-release/references/handoff.md +0 -24
  104. package/skills/engineering/resolve-release/references/postmortem.md +0 -230
  105. package/skills/engineering/resolve-release/references/preflight.md +0 -208
  106. package/skills/engineering/resolve-release/references/principles.md +0 -94
  107. package/skills/engineering/resolve-release/references/regression-checklist.md +0 -36
  108. package/skills/engineering/resolve-release/references/related-skills.md +0 -13
  109. package/skills/engineering/resolve-release/references/routing.md +0 -149
  110. package/skills/engineering/resolve-release/references/verified-sha-github-flow.md +0 -285
  111. package/skills/engineering/resolve-release/references/versioning.md +0 -202
  112. package/skills/engineering/resolve-release/references/why.md +0 -53
  113. package/skills/engineering/resolve-release/scripts/adapter-completion-artifact.mjs +0 -389
  114. package/skills/engineering/resolve-release/scripts/build-changes.mjs +0 -209
  115. package/skills/engineering/resolve-release/scripts/candidate-hygiene.mjs +0 -407
  116. package/skills/engineering/resolve-release/scripts/candidate-identity.mjs +0 -904
  117. package/skills/engineering/resolve-release/scripts/candidate-traffic.mjs +0 -81
  118. package/skills/engineering/resolve-release/scripts/checked-adapter-loader.mjs +0 -612
  119. package/skills/engineering/resolve-release/scripts/close-attempt.mjs +0 -135
  120. package/skills/engineering/resolve-release/scripts/closeout-release.mjs +0 -161
  121. package/skills/engineering/resolve-release/scripts/doctrine.mjs +0 -106
  122. package/skills/engineering/resolve-release/scripts/durable-processing.mjs +0 -522
  123. package/skills/engineering/resolve-release/scripts/ensure-target-green.mjs +0 -659
  124. package/skills/engineering/resolve-release/scripts/evidence-bundle.mjs +0 -1014
  125. package/skills/engineering/resolve-release/scripts/finalize-release.mjs +0 -526
  126. package/skills/engineering/resolve-release/scripts/fixtures/durable-processing-adapter.mjs +0 -169
  127. package/skills/engineering/resolve-release/scripts/green-gate.mjs +0 -599
  128. package/skills/engineering/resolve-release/scripts/isolated-adapter-evaluator.mjs +0 -752
  129. package/skills/engineering/resolve-release/scripts/metadata-pr-status.mjs +0 -56
  130. package/skills/engineering/resolve-release/scripts/metadata-sync.mjs +0 -1538
  131. package/skills/engineering/resolve-release/scripts/postmortem.mjs +0 -381
  132. package/skills/engineering/resolve-release/scripts/preflight-probes.mjs +0 -510
  133. package/skills/engineering/resolve-release/scripts/production-endpoints.mjs +0 -326
  134. package/skills/engineering/resolve-release/scripts/rc-circuit-breaker.mjs +0 -272
  135. package/skills/engineering/resolve-release/scripts/report.mjs +0 -417
  136. package/skills/engineering/resolve-release/scripts/reprobe-credentials.mjs +0 -114
  137. package/skills/engineering/resolve-release/scripts/revalidate-candidate.mjs +0 -238
  138. package/skills/engineering/resolve-release/scripts/review-packet.mjs +0 -503
  139. package/skills/engineering/resolve-release/scripts/rollback-floor.mjs +0 -263
  140. package/skills/engineering/resolve-release/scripts/version-assert.mjs +0 -339
  141. package/skills/engineering/resolve-release/scripts/version-postmortem.mjs +0 -485
  142. package/skills/engineering/resolve-release/scripts/version.mjs +0 -1199
  143. package/skills/engineering/resolve-release/scripts/watch-candidate-delivery.mjs +0 -449
  144. package/skills/engineering/resolve-release/vendor/ACORN-LICENSE +0 -21
  145. package/skills/engineering/resolve-release/vendor/README.md +0 -60
  146. package/skills/engineering/resolve-release/vendor/acorn.mjs +0 -6233
  147. package/skills/engineering/resolve-release/vendor/quickjs/core/LICENSE +0 -21
  148. package/skills/engineering/resolve-release/vendor/quickjs/core/README.md +0 -341
  149. package/skills/engineering/resolve-release/vendor/quickjs/core/README.template.md +0 -70
  150. package/skills/engineering/resolve-release/vendor/quickjs/core/dist/chunk-TAV5CUKK.mjs +0 -2
  151. package/skills/engineering/resolve-release/vendor/quickjs/core/dist/chunk-TAV5CUKK.mjs.map +0 -1
  152. package/skills/engineering/resolve-release/vendor/quickjs/core/dist/chunk-V2S4ZYJR.mjs +0 -7
  153. package/skills/engineering/resolve-release/vendor/quickjs/core/dist/chunk-V2S4ZYJR.mjs.map +0 -1
  154. package/skills/engineering/resolve-release/vendor/quickjs/core/dist/index.d.mts +0 -2033
  155. package/skills/engineering/resolve-release/vendor/quickjs/core/dist/index.d.ts +0 -2033
  156. package/skills/engineering/resolve-release/vendor/quickjs/core/dist/index.js +0 -7
  157. package/skills/engineering/resolve-release/vendor/quickjs/core/dist/index.js.map +0 -1
  158. package/skills/engineering/resolve-release/vendor/quickjs/core/dist/index.mjs +0 -2
  159. package/skills/engineering/resolve-release/vendor/quickjs/core/dist/index.mjs.map +0 -1
  160. package/skills/engineering/resolve-release/vendor/quickjs/core/dist/module-ES6BEMUI.mjs +0 -2
  161. package/skills/engineering/resolve-release/vendor/quickjs/core/dist/module-ES6BEMUI.mjs.map +0 -1
  162. package/skills/engineering/resolve-release/vendor/quickjs/core/dist/module-asyncify-2EFITU5U.mjs +0 -2
  163. package/skills/engineering/resolve-release/vendor/quickjs/core/dist/module-asyncify-2EFITU5U.mjs.map +0 -1
  164. package/skills/engineering/resolve-release/vendor/quickjs/core/package.json +0 -49
  165. package/skills/engineering/resolve-release/vendor/quickjs/ffi-types/LICENSE +0 -21
  166. package/skills/engineering/resolve-release/vendor/quickjs/ffi-types/README.md +0 -5
  167. package/skills/engineering/resolve-release/vendor/quickjs/ffi-types/dist/index.d.mts +0 -549
  168. package/skills/engineering/resolve-release/vendor/quickjs/ffi-types/dist/index.d.ts +0 -549
  169. package/skills/engineering/resolve-release/vendor/quickjs/ffi-types/dist/index.js +0 -2
  170. package/skills/engineering/resolve-release/vendor/quickjs/ffi-types/dist/index.js.map +0 -1
  171. package/skills/engineering/resolve-release/vendor/quickjs/ffi-types/dist/index.mjs +0 -2
  172. package/skills/engineering/resolve-release/vendor/quickjs/ffi-types/dist/index.mjs.map +0 -1
  173. package/skills/engineering/resolve-release/vendor/quickjs/ffi-types/package.json +0 -36
  174. package/skills/engineering/resolve-release/vendor/quickjs/release-sync/LICENSE +0 -47
  175. package/skills/engineering/resolve-release/vendor/quickjs/release-sync/README.md +0 -82
  176. package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/emscripten-module.browser.d.ts +0 -11
  177. package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/emscripten-module.browser.mjs +0 -22
  178. package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/emscripten-module.cjs +0 -21
  179. package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/emscripten-module.cloudflare.cjs +0 -21
  180. package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/emscripten-module.cloudflare.d.ts +0 -11
  181. package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/emscripten-module.d.ts +0 -11
  182. package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/emscripten-module.mjs +0 -25
  183. package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/emscripten-module.wasm +0 -0
  184. package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/ffi.d.mts +0 -85
  185. package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/ffi.d.ts +0 -85
  186. package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/ffi.js +0 -2
  187. package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/ffi.js.map +0 -1
  188. package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/ffi.mjs +0 -2
  189. package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/ffi.mjs.map +0 -1
  190. package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/index.d.mts +0 -20
  191. package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/index.d.ts +0 -20
  192. package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/index.js +0 -2
  193. package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/index.js.map +0 -1
  194. package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/index.mjs +0 -2
  195. package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/index.mjs.map +0 -1
  196. package/skills/engineering/resolve-release/vendor/quickjs/release-sync/package.json +0 -61
  197. /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}`)