@variance-authority/core 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (260) hide show
  1. package/CHANGELOG.md +79 -0
  2. package/LICENSE +21 -0
  3. package/README.md +169 -0
  4. package/dist/artifact.d.ts +47 -0
  5. package/dist/artifact.js +2 -0
  6. package/dist/artifact.js.map +1 -0
  7. package/dist/attribute/because.d.ts +43 -0
  8. package/dist/attribute/because.js +64 -0
  9. package/dist/attribute/because.js.map +1 -0
  10. package/dist/attribute/boundary.d.ts +191 -0
  11. package/dist/attribute/boundary.js +328 -0
  12. package/dist/attribute/boundary.js.map +1 -0
  13. package/dist/attribute/call-site.d.ts +96 -0
  14. package/dist/attribute/call-site.js +183 -0
  15. package/dist/attribute/call-site.js.map +1 -0
  16. package/dist/attribute/component-hash.d.ts +188 -0
  17. package/dist/attribute/component-hash.js +312 -0
  18. package/dist/attribute/component-hash.js.map +1 -0
  19. package/dist/attribute/composition-fixture.d.ts +18 -0
  20. package/dist/attribute/composition-fixture.js +53 -0
  21. package/dist/attribute/composition-fixture.js.map +1 -0
  22. package/dist/attribute/composition.d.ts +182 -0
  23. package/dist/attribute/composition.js +169 -0
  24. package/dist/attribute/composition.js.map +1 -0
  25. package/dist/attribute/control.d.ts +43 -0
  26. package/dist/attribute/control.js +54 -0
  27. package/dist/attribute/control.js.map +1 -0
  28. package/dist/attribute/coverage.d.ts +99 -0
  29. package/dist/attribute/coverage.js +86 -0
  30. package/dist/attribute/coverage.js.map +1 -0
  31. package/dist/attribute/divergence.d.ts +102 -0
  32. package/dist/attribute/divergence.js +152 -0
  33. package/dist/attribute/divergence.js.map +1 -0
  34. package/dist/attribute/index.d.ts +43 -0
  35. package/dist/attribute/index.js +29 -0
  36. package/dist/attribute/index.js.map +1 -0
  37. package/dist/attribute/instability.d.ts +89 -0
  38. package/dist/attribute/instability.js +183 -0
  39. package/dist/attribute/instability.js.map +1 -0
  40. package/dist/attribute/instances.d.ts +145 -0
  41. package/dist/attribute/instances.js +140 -0
  42. package/dist/attribute/instances.js.map +1 -0
  43. package/dist/attribute/locate.d.ts +22 -0
  44. package/dist/attribute/locate.js +100 -0
  45. package/dist/attribute/locate.js.map +1 -0
  46. package/dist/attribute/mask.d.ts +156 -0
  47. package/dist/attribute/mask.js +201 -0
  48. package/dist/attribute/mask.js.map +1 -0
  49. package/dist/attribute/movement.d.ts +211 -0
  50. package/dist/attribute/movement.js +181 -0
  51. package/dist/attribute/movement.js.map +1 -0
  52. package/dist/attribute/region.d.ts +188 -0
  53. package/dist/attribute/region.js +144 -0
  54. package/dist/attribute/region.js.map +1 -0
  55. package/dist/attribute/source-map.d.ts +98 -0
  56. package/dist/attribute/source-map.js +264 -0
  57. package/dist/attribute/source-map.js.map +1 -0
  58. package/dist/attribute/source.d.ts +77 -0
  59. package/dist/attribute/source.js +95 -0
  60. package/dist/attribute/source.js.map +1 -0
  61. package/dist/attribute/stack.d.ts +80 -0
  62. package/dist/attribute/stack.js +108 -0
  63. package/dist/attribute/stack.js.map +1 -0
  64. package/dist/compare/band.d.ts +85 -0
  65. package/dist/compare/band.js +70 -0
  66. package/dist/compare/band.js.map +1 -0
  67. package/dist/compare/cascade.d.ts +45 -0
  68. package/dist/compare/cascade.js +71 -0
  69. package/dist/compare/cascade.js.map +1 -0
  70. package/dist/compare/derive.d.ts +78 -0
  71. package/dist/compare/derive.js +39 -0
  72. package/dist/compare/derive.js.map +1 -0
  73. package/dist/compare/diff/attribution.d.ts +23 -0
  74. package/dist/compare/diff/attribution.js +244 -0
  75. package/dist/compare/diff/attribution.js.map +1 -0
  76. package/dist/compare/diff/compare-nodes.d.ts +15 -0
  77. package/dist/compare/diff/compare-nodes.js +227 -0
  78. package/dist/compare/diff/compare-nodes.js.map +1 -0
  79. package/dist/compare/diff/components.d.ts +20 -0
  80. package/dist/compare/diff/components.js +76 -0
  81. package/dist/compare/diff/components.js.map +1 -0
  82. package/dist/compare/diff/delta.d.ts +165 -0
  83. package/dist/compare/diff/delta.js +12 -0
  84. package/dist/compare/diff/delta.js.map +1 -0
  85. package/dist/compare/diff/index.d.ts +69 -0
  86. package/dist/compare/diff/index.js +101 -0
  87. package/dist/compare/diff/index.js.map +1 -0
  88. package/dist/compare/diff/match.d.ts +37 -0
  89. package/dist/compare/diff/match.js +167 -0
  90. package/dist/compare/diff/match.js.map +1 -0
  91. package/dist/compare/explain.d.ts +23 -0
  92. package/dist/compare/explain.js +190 -0
  93. package/dist/compare/explain.js.map +1 -0
  94. package/dist/compare/holding-diff.d.ts +25 -0
  95. package/dist/compare/holding-diff.js +74 -0
  96. package/dist/compare/holding-diff.js.map +1 -0
  97. package/dist/compare/impact.d.ts +56 -0
  98. package/dist/compare/impact.js +124 -0
  99. package/dist/compare/impact.js.map +1 -0
  100. package/dist/compare/index.d.ts +30 -0
  101. package/dist/compare/index.js +22 -0
  102. package/dist/compare/index.js.map +1 -0
  103. package/dist/compare/instance.d.ts +30 -0
  104. package/dist/compare/instance.js +145 -0
  105. package/dist/compare/instance.js.map +1 -0
  106. package/dist/compare/observability.d.ts +49 -0
  107. package/dist/compare/observability.js +57 -0
  108. package/dist/compare/observability.js.map +1 -0
  109. package/dist/compare/parting.d.ts +179 -0
  110. package/dist/compare/parting.js +244 -0
  111. package/dist/compare/parting.js.map +1 -0
  112. package/dist/compare/slice.d.ts +74 -0
  113. package/dist/compare/slice.js +79 -0
  114. package/dist/compare/slice.js.map +1 -0
  115. package/dist/compare/value.d.ts +60 -0
  116. package/dist/compare/value.js +111 -0
  117. package/dist/compare/value.js.map +1 -0
  118. package/dist/format/accessibility.d.ts +27 -0
  119. package/dist/format/accessibility.js +17 -0
  120. package/dist/format/accessibility.js.map +1 -0
  121. package/dist/format/canonical.d.ts +38 -0
  122. package/dist/format/canonical.js +65 -0
  123. package/dist/format/canonical.js.map +1 -0
  124. package/dist/format/capture.d.ts +212 -0
  125. package/dist/format/capture.js +2 -0
  126. package/dist/format/capture.js.map +1 -0
  127. package/dist/format/document.d.ts +279 -0
  128. package/dist/format/document.js +65 -0
  129. package/dist/format/document.js.map +1 -0
  130. package/dist/format/environment.d.ts +120 -0
  131. package/dist/format/environment.js +53 -0
  132. package/dist/format/environment.js.map +1 -0
  133. package/dist/format/hash.d.ts +45 -0
  134. package/dist/format/hash.js +41 -0
  135. package/dist/format/hash.js.map +1 -0
  136. package/dist/format/holding.d.ts +134 -0
  137. package/dist/format/holding.js +2 -0
  138. package/dist/format/holding.js.map +1 -0
  139. package/dist/format/index.d.ts +39 -0
  140. package/dist/format/index.js +25 -0
  141. package/dist/format/index.js.map +1 -0
  142. package/dist/format/intervention.d.ts +87 -0
  143. package/dist/format/intervention.js +11 -0
  144. package/dist/format/intervention.js.map +1 -0
  145. package/dist/format/profile.d.ts +59 -0
  146. package/dist/format/profile.js +66 -0
  147. package/dist/format/profile.js.map +1 -0
  148. package/dist/format/provenance.d.ts +179 -0
  149. package/dist/format/provenance.js +222 -0
  150. package/dist/format/provenance.js.map +1 -0
  151. package/dist/format/sha256.d.ts +34 -0
  152. package/dist/format/sha256.js +152 -0
  153. package/dist/format/sha256.js.map +1 -0
  154. package/dist/format/snapshot.d.ts +263 -0
  155. package/dist/format/snapshot.js +2 -0
  156. package/dist/format/snapshot.js.map +1 -0
  157. package/dist/format/stabilize.d.ts +190 -0
  158. package/dist/format/stabilize.js +333 -0
  159. package/dist/format/stabilize.js.map +1 -0
  160. package/dist/format/tier.d.ts +19 -0
  161. package/dist/format/tier.js +11 -0
  162. package/dist/format/tier.js.map +1 -0
  163. package/dist/format/value.d.ts +115 -0
  164. package/dist/format/value.js +182 -0
  165. package/dist/format/value.js.map +1 -0
  166. package/dist/format/wiring.d.ts +115 -0
  167. package/dist/format/wiring.js +60 -0
  168. package/dist/format/wiring.js.map +1 -0
  169. package/dist/index.d.ts +35 -0
  170. package/dist/index.js +35 -0
  171. package/dist/index.js.map +1 -0
  172. package/dist/judge/docket.d.ts +85 -0
  173. package/dist/judge/docket.js +162 -0
  174. package/dist/judge/docket.js.map +1 -0
  175. package/dist/judge/fingerprint.d.ts +53 -0
  176. package/dist/judge/fingerprint.js +144 -0
  177. package/dist/judge/fingerprint.js.map +1 -0
  178. package/dist/judge/ignore.d.ts +206 -0
  179. package/dist/judge/ignore.js +237 -0
  180. package/dist/judge/ignore.js.map +1 -0
  181. package/dist/judge/index.d.ts +44 -0
  182. package/dist/judge/index.js +34 -0
  183. package/dist/judge/index.js.map +1 -0
  184. package/dist/judge/inspect.d.ts +148 -0
  185. package/dist/judge/inspect.js +208 -0
  186. package/dist/judge/inspect.js.map +1 -0
  187. package/dist/judge/intent.d.ts +146 -0
  188. package/dist/judge/intent.js +150 -0
  189. package/dist/judge/intent.js.map +1 -0
  190. package/dist/judge/locale.d.ts +111 -0
  191. package/dist/judge/locale.js +247 -0
  192. package/dist/judge/locale.js.map +1 -0
  193. package/dist/judge/scope.d.ts +41 -0
  194. package/dist/judge/scope.js +47 -0
  195. package/dist/judge/scope.js.map +1 -0
  196. package/dist/judge/sensitivity.d.ts +202 -0
  197. package/dist/judge/sensitivity.js +152 -0
  198. package/dist/judge/sensitivity.js.map +1 -0
  199. package/dist/judge/trail.d.ts +122 -0
  200. package/dist/judge/trail.js +96 -0
  201. package/dist/judge/trail.js.map +1 -0
  202. package/dist/judge/verdict.d.ts +39 -0
  203. package/dist/judge/verdict.js +32 -0
  204. package/dist/judge/verdict.js.map +1 -0
  205. package/dist/plan/index.d.ts +12 -0
  206. package/dist/plan/index.js +11 -0
  207. package/dist/plan/index.js.map +1 -0
  208. package/dist/plan/tool.d.ts +85 -0
  209. package/dist/plan/tool.js +87 -0
  210. package/dist/plan/tool.js.map +1 -0
  211. package/dist/relate/graph.d.ts +190 -0
  212. package/dist/relate/graph.js +234 -0
  213. package/dist/relate/graph.js.map +1 -0
  214. package/dist/relate/index.d.ts +16 -0
  215. package/dist/relate/index.js +16 -0
  216. package/dist/relate/index.js.map +1 -0
  217. package/dist/relate/merkle.d.ts +110 -0
  218. package/dist/relate/merkle.js +246 -0
  219. package/dist/relate/merkle.js.map +1 -0
  220. package/dist/relate/reach.d.ts +65 -0
  221. package/dist/relate/reach.js +111 -0
  222. package/dist/relate/reach.js.map +1 -0
  223. package/dist/relate/records.d.ts +129 -0
  224. package/dist/relate/records.js +112 -0
  225. package/dist/relate/records.js.map +1 -0
  226. package/dist/rules/index.d.ts +19 -0
  227. package/dist/rules/index.js +17 -0
  228. package/dist/rules/index.js.map +1 -0
  229. package/dist/rules/normalize/alias.d.ts +50 -0
  230. package/dist/rules/normalize/alias.js +111 -0
  231. package/dist/rules/normalize/alias.js.map +1 -0
  232. package/dist/rules/normalize/cascade.d.ts +85 -0
  233. package/dist/rules/normalize/cascade.js +324 -0
  234. package/dist/rules/normalize/cascade.js.map +1 -0
  235. package/dist/rules/normalize/color.d.ts +30 -0
  236. package/dist/rules/normalize/color.js +185 -0
  237. package/dist/rules/normalize/color.js.map +1 -0
  238. package/dist/rules/normalize/fixture.d.ts +83 -0
  239. package/dist/rules/normalize/fixture.js +74 -0
  240. package/dist/rules/normalize/fixture.js.map +1 -0
  241. package/dist/rules/normalize/index.d.ts +39 -0
  242. package/dist/rules/normalize/index.js +268 -0
  243. package/dist/rules/normalize/index.js.map +1 -0
  244. package/dist/rules/normalize/project.d.ts +42 -0
  245. package/dist/rules/normalize/project.js +83 -0
  246. package/dist/rules/normalize/project.js.map +1 -0
  247. package/dist/rules/normalize/shorthand.d.ts +38 -0
  248. package/dist/rules/normalize/shorthand.js +388 -0
  249. package/dist/rules/normalize/shorthand.js.map +1 -0
  250. package/dist/rules/normalize/value.d.ts +23 -0
  251. package/dist/rules/normalize/value.js +162 -0
  252. package/dist/rules/normalize/value.js.map +1 -0
  253. package/dist/rules/normalize/wrapper.d.ts +16 -0
  254. package/dist/rules/normalize/wrapper.js +137 -0
  255. package/dist/rules/normalize/wrapper.js.map +1 -0
  256. package/dist/rules/ruleset.d.ts +93 -0
  257. package/dist/rules/ruleset.js +175 -0
  258. package/dist/rules/ruleset.js.map +1 -0
  259. package/mark.svg +30 -0
  260. package/package.json +69 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sha256.js","sourceRoot":"","sources":["../../src/format/sha256.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * SHA-256, in portable TypeScript.\n *\n * `core` originally used `node:crypto`, which was wrong — and the reason is not\n * ergonomic. `propsDigest` has to run *inside the page*: a React prop can be a\n * function or an element, and neither survives serialization out to a host\n * process, so the digest must be taken where the value still exists. A `core`\n * that imports `node:crypto` cannot run there, which quietly contradicted the\n * remote-sub-renderer story in ADR-0002 and the DOM-free boundary in ADR-0001.\n * (The `lib: [\"ES2022\"]` guard is one-directional: it stops `core` reaching into\n * a browser, not `core` depending on Node.)\n *\n * `crypto.subtle.digest` is the obvious replacement and is not usable: it is\n * async, and hashing is synchronous throughout by design — making it async would\n * colour the entire normalizer for no benefit.\n *\n * So the algorithm lives here. It is fully specified by FIPS 180-4, so this\n * produces byte-identical output to any other correct implementation on any\n * runtime, which is exactly the determinism Principle 2 requires. Performance is\n * not a consideration until a gate in ADR-0004 fires; none has.\n */\n\nconst K = new Uint32Array([\n 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,\n 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,\n 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,\n 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,\n 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,\n 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,\n 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,\n 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2,\n]);\n\nconst INITIAL = new Uint32Array([\n 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19,\n]);\n\n/** Hash a UTF-8 string, returning lowercase hex. */\nexport function sha256Hex(input: string): string {\n return sha256HexBytes(utf8Bytes(input));\n}\n\n/**\n * Hash raw bytes, returning lowercase hex.\n *\n * The string form is this with one encoding step in front of it, and not the\n * other way round: an image is bytes, and routing it through a string would mean\n * choosing an encoding that survives arbitrary octets — which is a second\n * decision, made in the wrong place, that changes the digest if it is ever\n * revisited.\n */\nexport function sha256HexBytes(bytes: Uint8Array): string {\n const state = new Uint32Array(INITIAL);\n\n // Padding: a single 1 bit, zeros, then the 64-bit big-endian bit length.\n const bitLength = bytes.length * 8;\n // Padding is minimal by definition: the smallest multiple of 64 that fits the\n // message, the 0x80 byte, and the 8-byte length. Rounding up unconditionally\n // would append a spare block whenever `length + 9` is already a multiple of\n // 64, which is a different message and therefore a different digest.\n const paddedLength = Math.ceil((bytes.length + 9) / 64) * 64;\n const padded = new Uint8Array(paddedLength);\n padded.set(bytes);\n padded[bytes.length] = 0x80;\n\n // Written as two 32-bit halves rather than a BigInt: inputs never approach\n // 2^32 bits (512 MiB), and the high word is always zero in practice, but\n // emitting it keeps the block format exactly as specified.\n const view = new DataView(padded.buffer);\n view.setUint32(paddedLength - 8, Math.floor(bitLength / 0x100000000), false);\n view.setUint32(paddedLength - 4, bitLength >>> 0, false);\n\n const w = new Uint32Array(64);\n\n for (let offset = 0; offset < paddedLength; offset += 64) {\n for (let i = 0; i < 16; i += 1) {\n w[i] = view.getUint32(offset + i * 4, false);\n }\n for (let i = 16; i < 64; i += 1) {\n const s0 = rotr(w[i - 15]!, 7) ^ rotr(w[i - 15]!, 18) ^ (w[i - 15]! >>> 3);\n const s1 = rotr(w[i - 2]!, 17) ^ rotr(w[i - 2]!, 19) ^ (w[i - 2]! >>> 10);\n w[i] = (w[i - 16]! + s0 + w[i - 7]! + s1) >>> 0;\n }\n\n let [a, b, c, d, e, f, g, h] = state as unknown as number[];\n\n for (let i = 0; i < 64; i += 1) {\n const S1 = rotr(e!, 6) ^ rotr(e!, 11) ^ rotr(e!, 25);\n const ch = (e! & f!) ^ (~e! & g!);\n const temp1 = (h! + S1 + ch + K[i]! + w[i]!) >>> 0;\n const S0 = rotr(a!, 2) ^ rotr(a!, 13) ^ rotr(a!, 22);\n const maj = (a! & b!) ^ (a! & c!) ^ (b! & c!);\n const temp2 = (S0 + maj) >>> 0;\n\n h = g;\n g = f;\n f = e;\n e = (d! + temp1) >>> 0;\n d = c;\n c = b;\n b = a;\n a = (temp1 + temp2) >>> 0;\n }\n\n state[0] = (state[0]! + a!) >>> 0;\n state[1] = (state[1]! + b!) >>> 0;\n state[2] = (state[2]! + c!) >>> 0;\n state[3] = (state[3]! + d!) >>> 0;\n state[4] = (state[4]! + e!) >>> 0;\n state[5] = (state[5]! + f!) >>> 0;\n state[6] = (state[6]! + g!) >>> 0;\n state[7] = (state[7]! + h!) >>> 0;\n }\n\n let hex = '';\n for (const word of state) {\n hex += word.toString(16).padStart(8, '0');\n }\n return hex;\n}\n\nfunction rotr(value: number, bits: number): number {\n return ((value >>> bits) | (value << (32 - bits))) >>> 0;\n}\n\n/**\n * Encode as UTF-8 without `TextEncoder`.\n *\n * `TextEncoder` is available everywhere this runs today, but hand-encoding keeps\n * `core` free of *every* host global, not merely the Node ones — which is the\n * property that just failed to hold. Lone surrogates are encoded as U+FFFD, the\n * same substitution `TextEncoder` makes, so a malformed string cannot produce\n * two different digests on two runtimes.\n */\nfunction utf8Bytes(input: string): Uint8Array {\n const bytes: number[] = [];\n\n for (let i = 0; i < input.length; i += 1) {\n let code = input.charCodeAt(i);\n\n if (code >= 0xd800 && code <= 0xdbff) {\n const next = input.charCodeAt(i + 1);\n if (next >= 0xdc00 && next <= 0xdfff) {\n code = 0x10000 + ((code - 0xd800) << 10) + (next - 0xdc00);\n i += 1;\n } else {\n code = 0xfffd;\n }\n } else if (code >= 0xdc00 && code <= 0xdfff) {\n code = 0xfffd;\n }\n\n if (code < 0x80) {\n bytes.push(code);\n } else if (code < 0x800) {\n bytes.push(0xc0 | (code >> 6), 0x80 | (code & 0x3f));\n } else if (code < 0x10000) {\n bytes.push(0xe0 | (code >> 12), 0x80 | ((code >> 6) & 0x3f), 0x80 | (code & 0x3f));\n } else {\n bytes.push(\n 0xf0 | (code >> 18),\n 0x80 | ((code >> 12) & 0x3f),\n 0x80 | ((code >> 6) & 0x3f),\n 0x80 | (code & 0x3f),\n );\n }\n }\n\n return Uint8Array.from(bytes);\n}\n"]}
@@ -0,0 +1,263 @@
1
+ import type { SubjectRef, Rect, Diagnostic } from './capture.js';
2
+ import type { EnvironmentKey } from './environment.js';
3
+ import type { Digest } from './hash.js';
4
+ import type { ObservationProfile } from './profile.js';
5
+ import type { Provenance } from './provenance.js';
6
+ import type { Wiring } from './wiring.js';
7
+ import type { Holding } from './holding.js';
8
+ /**
9
+ * The normalized semantic snapshot: the verdict's input, and the thing a render
10
+ * hash addresses.
11
+ *
12
+ * Everything volatile is gone by this point. Ids have become structural aliases,
13
+ * class attributes have been dropped entirely, inapplicable CSS has been pruned,
14
+ * and the cascade has been resolved to winning values (ADR-0003). What remains is
15
+ * meant to be *read*: a snapshot a reviewer refuses to open is a snapshot that
16
+ * gets rubber-stamped.
17
+ */
18
+ export interface SemanticSnapshot {
19
+ readonly formatVersion: 1;
20
+ readonly subject: SubjectRef;
21
+ readonly profile: ObservationProfile;
22
+ readonly environment: EnvironmentKey;
23
+ /** Content hash of `root` under `environment`. The identity of this state. */
24
+ readonly renderHash: Digest;
25
+ /**
26
+ * Structure and applicable style, hashed separately.
27
+ *
28
+ * These back the tier below full semantic comparison (ADR-0003): matching both
29
+ * settles a subject without resolving layout or taking a screenshot. Split
30
+ * rather than combined because the docket wants to say *which* held — "the DOM
31
+ * is identical, only styling moved" is the sentence that turns a diff into a
32
+ * token-band root.
33
+ */
34
+ readonly structureHash: Digest;
35
+ readonly styleHash: Digest;
36
+ readonly root: SemanticNode;
37
+ /**
38
+ * Where each winning declaration came from. Deliberately outside the hash.
39
+ *
40
+ * Pruning discards exactly what attribution needs — *which rule set this?* — so
41
+ * it is preserved here instead. Keeping it out of the hash is the point: moving
42
+ * a rule between files renames a source without changing a render, and must not
43
+ * invalidate a baseline.
44
+ */
45
+ readonly styleProvenance: readonly StyleProvenanceEntry[];
46
+ /**
47
+ * Subtrees the operator declared out of scope, resolved against *this* tree.
48
+ *
49
+ * Deliberately outside the hash, for the reason `styleProvenance` is: an ignore
50
+ * changes what a run says about a render, never the render. Folding it into the
51
+ * identity would invalidate every baseline in the repository the first time
52
+ * somebody masked a clock, which is the surest way to make a safety feature the
53
+ * thing people turn off.
54
+ *
55
+ * Present only when something was excluded, so a snapshot from a run with no
56
+ * ignores is byte-identical to one produced before this field existed.
57
+ */
58
+ readonly ignoreSites?: readonly IgnoreSite[];
59
+ /**
60
+ * What the collector or the normalizer could not do, carried forward.
61
+ *
62
+ * Outside the hash: a diagnostic describes the *observation*, not the render,
63
+ * and a snapshot that hashed its own warnings would invalidate whenever the
64
+ * warning text was reworded. But it must survive to the verdict — a subject
65
+ * whose capture half-failed is not a subject that legitimately `unchanged`,
66
+ * and silently discarding that fact is how a broken collector reads as a clean
67
+ * build.
68
+ */
69
+ readonly diagnostics: readonly Diagnostic[];
70
+ }
71
+ /**
72
+ * A node's stable address: child indices from the root, e.g. `0/2/1`.
73
+ *
74
+ * Positional because nothing else survives. Ids are volatile (that is why they
75
+ * were aliased away), and class names have been dropped. Position is honest about
76
+ * what it costs: inserting a sibling renumbers everything after it, so the differ
77
+ * matches nodes by shape and provenance before falling back to path (see
78
+ * `diff.ts`), and treats a path change alone as evidence of nothing.
79
+ */
80
+ export type NodePath = string;
81
+ export interface SemanticNode {
82
+ readonly path: NodePath;
83
+ readonly tag: string;
84
+ /** Structural alias, e.g. `#a0`. Absent when the node carried no id. */
85
+ readonly alias?: string;
86
+ readonly role?: string;
87
+ readonly name?: string;
88
+ /**
89
+ * Accessible description, resolved. See `RawAria.description` for why this is
90
+ * a field of its own rather than an attribute.
91
+ */
92
+ readonly description?: string;
93
+ readonly state?: Readonly<Record<string, string | boolean | number>>;
94
+ /** Semantic attributes surviving normalization. `class` is never among them. */
95
+ readonly attributes: Readonly<Record<string, string>>;
96
+ /** Winning values for allowlisted properties, canonicalized. */
97
+ readonly style: Readonly<Record<string, string>>;
98
+ /**
99
+ * Custom properties this node's winning declarations resolved through, as
100
+ * name → resolved value.
101
+ *
102
+ * Recording the name alongside the value is what lets a design-token change
103
+ * surface as one root with counted collateral instead of hundreds of unrelated
104
+ * colour diffs (spec §5, `token` band).
105
+ */
106
+ readonly tokens?: Readonly<Record<string, string>>;
107
+ /**
108
+ * Which token each styled property resolved through, including by inheritance.
109
+ *
110
+ * Outside the hash, like `styleProvenance` and for the same reason: swapping a
111
+ * literal for a token of the same value renames a source without changing a
112
+ * render. It exists so the differ can tell *which* property a token edit
113
+ * explains — `tokens` alone says a node uses tokens, not which of its values
114
+ * one drove.
115
+ */
116
+ readonly styleTokens?: Readonly<Record<string, string>>;
117
+ /** Present only under a profile with layout. Absent, never zeroed (ADR-0002). */
118
+ readonly rect?: Rect;
119
+ /** Text content, or its digest when policy declares the region volatile. */
120
+ readonly text?: string;
121
+ readonly provenance?: Provenance;
122
+ /**
123
+ * How the framework holds this node's component, when a framework adapter
124
+ * supplied it. See {@link Wiring}.
125
+ *
126
+ * On the node rather than on `Provenance`, though both come from the same
127
+ * adapter and the same fiber, because they answer to different readers.
128
+ * Provenance exists so a diff arrives carrying a name; wiring is a *dimension
129
+ * of the subject*, hashed into a band of its own, and a band's inputs belong
130
+ * beside the other bands' inputs — next to `style` and `attributes`, which is
131
+ * where `shapeOf` goes looking.
132
+ */
133
+ readonly wiring?: Wiring;
134
+ /**
135
+ * What that component was holding. **Outside every hash**, always.
136
+ *
137
+ * The field beside it is the contrast worth reading: `wiring` is a band and
138
+ * this is evidence. `Wiring` refuses state values because a hook's value is
139
+ * exactly what may legitimately differ between two readings of one page, and
140
+ * that refusal is right and is not softened here — a `holding` reaches the
141
+ * snapshot and reaches no digest, so a subject whose clock ticked has the same
142
+ * `renderHash` it had before this field existed.
143
+ *
144
+ * It rides outside on the same terms as `styleProvenance`, `styleTokens` and
145
+ * `ignoredBy`, by the same mechanism: `structureOf`, `styleOf` and `shapeOf`
146
+ * project the fields they hash **by name**, so a field none of them names
147
+ * cannot reach an identity. `holding.hash.test.ts` asserts that rather than
148
+ * trusting it, because the cost of being wrong is every baseline in a
149
+ * repository invalidating the first time a component held a timestamp.
150
+ */
151
+ readonly holding?: Holding;
152
+ /**
153
+ * `true` on the root of a subtree rendered through a portal.
154
+ *
155
+ * Recorded in the structure hash so that "the dialog moved from inline to
156
+ * portalled" is a change rather than a coincidence of identical content, and
157
+ * so the docket can say *where* something rendered, not only that it exists.
158
+ */
159
+ readonly portalled?: boolean;
160
+ /**
161
+ * Ignore rules this node was found under. Outside every hash, like its origin
162
+ * on `RawNode`. See {@link SemanticSnapshot.ignoreSites}.
163
+ */
164
+ readonly ignoredBy?: readonly string[];
165
+ readonly children: readonly SemanticNode[];
166
+ }
167
+ /**
168
+ * A subtree the operator excluded, resolved to a path and a box (spec 0024).
169
+ *
170
+ * Lives in `format` rather than beside the rules that consume it, because it is
171
+ * part of what a snapshot *is*: the collector produced it, it travels with the
172
+ * document over every wire this project has, and `core/judge` is only its first
173
+ * reader. A type the wire format needs cannot live in the policy layer.
174
+ */
175
+ export interface IgnoreSite {
176
+ /** Root of the excluded subtree, in this snapshot's own path space. */
177
+ readonly path: NodePath;
178
+ /** Which rule put it here, matched exactly against `IgnoreRule.id`. */
179
+ readonly rule: string;
180
+ /**
181
+ * The box it occupied, for the raster tier.
182
+ *
183
+ * Absent under a profile with no layout — which is ADR-0002 rather than a
184
+ * failure: a profile that cannot measure a box cannot decide pixels either, so
185
+ * there is nothing for the box to subtract from.
186
+ */
187
+ readonly rect?: Rect;
188
+ }
189
+ /**
190
+ * A component's own content, hashed per band (ADR-0018).
191
+ *
192
+ * In `format` rather than beside `hashComponents`, which computes it, because a
193
+ * baseline carries these: a stored image plus the component hashes of the
194
+ * document that painted it is what lets a later run tell the component that
195
+ * *caused* a change from the components the change merely moved. That makes this
196
+ * part of the wire format every store and every transport has to preserve, and a
197
+ * type the wire needs cannot live in the layer that derives it.
198
+ */
199
+ export interface ComponentHash {
200
+ readonly component: string;
201
+ /** Boundaries of this component in the subject, counted in document order. */
202
+ readonly instances: number;
203
+ /**
204
+ * Tree shape: tags, structural aliases, portalling, allowlisted attributes,
205
+ * and which child boundaries sit where. The `geometry` band's structural half.
206
+ *
207
+ * **Split out of a single `structure` digest on 2026-08-06.** It used to carry
208
+ * the accessible semantics and the text too, and the fusion was invisible
209
+ * until something needed to ask *which band moved* — at which point a baseline
210
+ * could say "this component changed" and never say whether a heading was
211
+ * renamed, a paragraph reworded, or a node inserted. Those are three different
212
+ * bands, three different readers, and one of them is the band a route-level
213
+ * test exists to ignore.
214
+ */
215
+ readonly structure: Digest;
216
+ /**
217
+ * Role, accessible name, and ARIA state. The `a11y` band.
218
+ *
219
+ * Its own digest because it is the band that must never be absorbed. Every
220
+ * sensitivity level asserts on it, including the ones that ignore everything
221
+ * else — and a level cannot assert on a band that is fused into another one.
222
+ */
223
+ readonly semantics: Digest;
224
+ /** Text runs, in document order. The `content` band. */
225
+ readonly text: Digest;
226
+ readonly style: Digest;
227
+ /**
228
+ * Absent under a profile without layout — absent, never empty (ADR-0002).
229
+ *
230
+ * An empty geometry digest would compare equal between a run that observed no
231
+ * movement and a run that could not observe movement at all, which is the
232
+ * false `unchanged` this system must never produce.
233
+ */
234
+ readonly geometry?: Digest;
235
+ /**
236
+ * The box each instance occupies, in document order. Never hashed.
237
+ *
238
+ * A digest can say a component is not what it was and can never say by how
239
+ * much. That is the gap a reviewer falls into: `Button — geometry, token` is
240
+ * true of a control that lost a shadow and of one that grew eight pixels and
241
+ * pushed the page down, and only the second explains why the subject is a
242
+ * different height. Four numbers per instance close it.
243
+ *
244
+ * Absent for a baseline written before this existed and for a profile with no
245
+ * layout — the same absence, and both mean *nobody measured*, never *it did
246
+ * not move*. A `null` entry is a boundary the browser laid out nothing for,
247
+ * kept in place so the list stays parallel to the instances it counts.
248
+ */
249
+ readonly boxes?: readonly (Rect | null)[];
250
+ }
251
+ export interface StyleProvenanceEntry {
252
+ readonly path: NodePath;
253
+ readonly property: string;
254
+ readonly sheet: string;
255
+ /** Generated segments replaced by placeholders, so it can name a root safely. */
256
+ readonly selector: string;
257
+ readonly tokenName?: string;
258
+ readonly source?: {
259
+ readonly file: string;
260
+ readonly line: number;
261
+ };
262
+ }
263
+ //# sourceMappingURL=snapshot.d.ts.map
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=snapshot.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"snapshot.js","sourceRoot":"","sources":["../../src/format/snapshot.ts"],"names":[],"mappings":"","sourcesContent":["import type { SubjectRef, Rect, Diagnostic } from './capture.js';\nimport type { EnvironmentKey } from './environment.js';\nimport type { Digest } from './hash.js';\nimport type { ObservationProfile } from './profile.js';\nimport type { Provenance } from './provenance.js';\nimport type { Wiring } from './wiring.js';\nimport type { Holding } from './holding.js';\n\n/**\n * The normalized semantic snapshot: the verdict's input, and the thing a render\n * hash addresses.\n *\n * Everything volatile is gone by this point. Ids have become structural aliases,\n * class attributes have been dropped entirely, inapplicable CSS has been pruned,\n * and the cascade has been resolved to winning values (ADR-0003). What remains is\n * meant to be *read*: a snapshot a reviewer refuses to open is a snapshot that\n * gets rubber-stamped.\n */\nexport interface SemanticSnapshot {\n readonly formatVersion: 1;\n readonly subject: SubjectRef;\n readonly profile: ObservationProfile;\n readonly environment: EnvironmentKey;\n\n /** Content hash of `root` under `environment`. The identity of this state. */\n readonly renderHash: Digest;\n\n /**\n * Structure and applicable style, hashed separately.\n *\n * These back the tier below full semantic comparison (ADR-0003): matching both\n * settles a subject without resolving layout or taking a screenshot. Split\n * rather than combined because the docket wants to say *which* held — \"the DOM\n * is identical, only styling moved\" is the sentence that turns a diff into a\n * token-band root.\n */\n readonly structureHash: Digest;\n readonly styleHash: Digest;\n\n readonly root: SemanticNode;\n\n /**\n * Where each winning declaration came from. Deliberately outside the hash.\n *\n * Pruning discards exactly what attribution needs — *which rule set this?* — so\n * it is preserved here instead. Keeping it out of the hash is the point: moving\n * a rule between files renames a source without changing a render, and must not\n * invalidate a baseline.\n */\n readonly styleProvenance: readonly StyleProvenanceEntry[];\n\n /**\n * Subtrees the operator declared out of scope, resolved against *this* tree.\n *\n * Deliberately outside the hash, for the reason `styleProvenance` is: an ignore\n * changes what a run says about a render, never the render. Folding it into the\n * identity would invalidate every baseline in the repository the first time\n * somebody masked a clock, which is the surest way to make a safety feature the\n * thing people turn off.\n *\n * Present only when something was excluded, so a snapshot from a run with no\n * ignores is byte-identical to one produced before this field existed.\n */\n readonly ignoreSites?: readonly IgnoreSite[];\n\n /**\n * What the collector or the normalizer could not do, carried forward.\n *\n * Outside the hash: a diagnostic describes the *observation*, not the render,\n * and a snapshot that hashed its own warnings would invalidate whenever the\n * warning text was reworded. But it must survive to the verdict — a subject\n * whose capture half-failed is not a subject that legitimately `unchanged`,\n * and silently discarding that fact is how a broken collector reads as a clean\n * build.\n */\n readonly diagnostics: readonly Diagnostic[];\n}\n\n/**\n * A node's stable address: child indices from the root, e.g. `0/2/1`.\n *\n * Positional because nothing else survives. Ids are volatile (that is why they\n * were aliased away), and class names have been dropped. Position is honest about\n * what it costs: inserting a sibling renumbers everything after it, so the differ\n * matches nodes by shape and provenance before falling back to path (see\n * `diff.ts`), and treats a path change alone as evidence of nothing.\n */\nexport type NodePath = string;\n\nexport interface SemanticNode {\n readonly path: NodePath;\n readonly tag: string;\n\n /** Structural alias, e.g. `#a0`. Absent when the node carried no id. */\n readonly alias?: string;\n\n readonly role?: string;\n readonly name?: string;\n\n /**\n * Accessible description, resolved. See `RawAria.description` for why this is\n * a field of its own rather than an attribute.\n */\n readonly description?: string;\n\n readonly state?: Readonly<Record<string, string | boolean | number>>;\n\n /** Semantic attributes surviving normalization. `class` is never among them. */\n readonly attributes: Readonly<Record<string, string>>;\n\n /** Winning values for allowlisted properties, canonicalized. */\n readonly style: Readonly<Record<string, string>>;\n\n /**\n * Custom properties this node's winning declarations resolved through, as\n * name → resolved value.\n *\n * Recording the name alongside the value is what lets a design-token change\n * surface as one root with counted collateral instead of hundreds of unrelated\n * colour diffs (spec §5, `token` band).\n */\n readonly tokens?: Readonly<Record<string, string>>;\n\n /**\n * Which token each styled property resolved through, including by inheritance.\n *\n * Outside the hash, like `styleProvenance` and for the same reason: swapping a\n * literal for a token of the same value renames a source without changing a\n * render. It exists so the differ can tell *which* property a token edit\n * explains — `tokens` alone says a node uses tokens, not which of its values\n * one drove.\n */\n readonly styleTokens?: Readonly<Record<string, string>>;\n\n /** Present only under a profile with layout. Absent, never zeroed (ADR-0002). */\n readonly rect?: Rect;\n\n /** Text content, or its digest when policy declares the region volatile. */\n readonly text?: string;\n\n readonly provenance?: Provenance;\n\n /**\n * How the framework holds this node's component, when a framework adapter\n * supplied it. See {@link Wiring}.\n *\n * On the node rather than on `Provenance`, though both come from the same\n * adapter and the same fiber, because they answer to different readers.\n * Provenance exists so a diff arrives carrying a name; wiring is a *dimension\n * of the subject*, hashed into a band of its own, and a band's inputs belong\n * beside the other bands' inputs — next to `style` and `attributes`, which is\n * where `shapeOf` goes looking.\n */\n readonly wiring?: Wiring;\n\n /**\n * What that component was holding. **Outside every hash**, always.\n *\n * The field beside it is the contrast worth reading: `wiring` is a band and\n * this is evidence. `Wiring` refuses state values because a hook's value is\n * exactly what may legitimately differ between two readings of one page, and\n * that refusal is right and is not softened here — a `holding` reaches the\n * snapshot and reaches no digest, so a subject whose clock ticked has the same\n * `renderHash` it had before this field existed.\n *\n * It rides outside on the same terms as `styleProvenance`, `styleTokens` and\n * `ignoredBy`, by the same mechanism: `structureOf`, `styleOf` and `shapeOf`\n * project the fields they hash **by name**, so a field none of them names\n * cannot reach an identity. `holding.hash.test.ts` asserts that rather than\n * trusting it, because the cost of being wrong is every baseline in a\n * repository invalidating the first time a component held a timestamp.\n */\n readonly holding?: Holding;\n\n /**\n * `true` on the root of a subtree rendered through a portal.\n *\n * Recorded in the structure hash so that \"the dialog moved from inline to\n * portalled\" is a change rather than a coincidence of identical content, and\n * so the docket can say *where* something rendered, not only that it exists.\n */\n readonly portalled?: boolean;\n\n /**\n * Ignore rules this node was found under. Outside every hash, like its origin\n * on `RawNode`. See {@link SemanticSnapshot.ignoreSites}.\n */\n readonly ignoredBy?: readonly string[];\n\n readonly children: readonly SemanticNode[];\n}\n\n/**\n * A subtree the operator excluded, resolved to a path and a box (spec 0024).\n *\n * Lives in `format` rather than beside the rules that consume it, because it is\n * part of what a snapshot *is*: the collector produced it, it travels with the\n * document over every wire this project has, and `core/judge` is only its first\n * reader. A type the wire format needs cannot live in the policy layer.\n */\nexport interface IgnoreSite {\n /** Root of the excluded subtree, in this snapshot's own path space. */\n readonly path: NodePath;\n\n /** Which rule put it here, matched exactly against `IgnoreRule.id`. */\n readonly rule: string;\n\n /**\n * The box it occupied, for the raster tier.\n *\n * Absent under a profile with no layout — which is ADR-0002 rather than a\n * failure: a profile that cannot measure a box cannot decide pixels either, so\n * there is nothing for the box to subtract from.\n */\n readonly rect?: Rect;\n}\n\n/**\n * A component's own content, hashed per band (ADR-0018).\n *\n * In `format` rather than beside `hashComponents`, which computes it, because a\n * baseline carries these: a stored image plus the component hashes of the\n * document that painted it is what lets a later run tell the component that\n * *caused* a change from the components the change merely moved. That makes this\n * part of the wire format every store and every transport has to preserve, and a\n * type the wire needs cannot live in the layer that derives it.\n */\nexport interface ComponentHash {\n readonly component: string;\n\n /** Boundaries of this component in the subject, counted in document order. */\n readonly instances: number;\n\n /**\n * Tree shape: tags, structural aliases, portalling, allowlisted attributes,\n * and which child boundaries sit where. The `geometry` band's structural half.\n *\n * **Split out of a single `structure` digest on 2026-08-06.** It used to carry\n * the accessible semantics and the text too, and the fusion was invisible\n * until something needed to ask *which band moved* — at which point a baseline\n * could say \"this component changed\" and never say whether a heading was\n * renamed, a paragraph reworded, or a node inserted. Those are three different\n * bands, three different readers, and one of them is the band a route-level\n * test exists to ignore.\n */\n readonly structure: Digest;\n\n /**\n * Role, accessible name, and ARIA state. The `a11y` band.\n *\n * Its own digest because it is the band that must never be absorbed. Every\n * sensitivity level asserts on it, including the ones that ignore everything\n * else — and a level cannot assert on a band that is fused into another one.\n */\n readonly semantics: Digest;\n\n /** Text runs, in document order. The `content` band. */\n readonly text: Digest;\n\n readonly style: Digest;\n\n /**\n * Absent under a profile without layout — absent, never empty (ADR-0002).\n *\n * An empty geometry digest would compare equal between a run that observed no\n * movement and a run that could not observe movement at all, which is the\n * false `unchanged` this system must never produce.\n */\n readonly geometry?: Digest;\n\n /**\n * The box each instance occupies, in document order. Never hashed.\n *\n * A digest can say a component is not what it was and can never say by how\n * much. That is the gap a reviewer falls into: `Button — geometry, token` is\n * true of a control that lost a shadow and of one that grew eight pixels and\n * pushed the page down, and only the second explains why the subject is a\n * different height. Four numbers per instance close it.\n *\n * Absent for a baseline written before this existed and for a profile with no\n * layout — the same absence, and both mean *nobody measured*, never *it did\n * not move*. A `null` entry is a boundary the browser laid out nothing for,\n * kept in place so the list stays parallel to the instances it counts.\n */\n readonly boxes?: readonly (Rect | null)[];\n}\n\nexport interface StyleProvenanceEntry {\n readonly path: NodePath;\n readonly property: string;\n readonly sheet: string;\n /** Generated segments replaced by placeholders, so it can name a root safely. */\n readonly selector: string;\n readonly tokenName?: string;\n readonly source?: { readonly file: string; readonly line: number };\n}\n"]}
@@ -0,0 +1,190 @@
1
+ import { type Digest } from './hash.js';
2
+ import { type Tier } from './tier.js';
3
+ import type { Intervention, ScreenshotOptions, SettleTarget } from './intervention.js';
4
+ /**
5
+ * Interventions as separate, nameable tricks — not a fixed set of switches.
6
+ *
7
+ * A subject that is still changing cannot be compared, so every system of this
8
+ * kind reaches into the page: it holds animations, waits for fonts, hides a
9
+ * caret, suppresses scrollbars. Written as one struct of booleans that becomes a
10
+ * closed vocabulary: adding a trick edits a type every caller depends on, and a
11
+ * project with a need nobody anticipated has to fork.
12
+ *
13
+ * So each is a value. It carries an id, the tier that can actually observe what
14
+ * it fixes, what it costs, and how it is applied — and a *recipe* is any list of
15
+ * them. Two tricks may express the same intent through different mechanisms and
16
+ * remain separate values, because they produce different images and choosing
17
+ * between them is the caller's business.
18
+ *
19
+ * ## What this buys
20
+ *
21
+ * A recipe can be filtered by tier, so the structure-and-style rung waits for
22
+ * nothing; composed from another project's tricks alongside these; digested, so
23
+ * a baseline made under one recipe is `incomparable` with a run made under
24
+ * another rather than `changed`; and checked for tricks that fight each other.
25
+ *
26
+ * ## Where the damage lands
27
+ *
28
+ * Ordered by increasing cost, earliest sufficient option first:
29
+ *
30
+ * - **Outside the subject** — injected CSS, browser screenshot options. Nothing
31
+ * in the product imports it and deleting the tool deletes the intervention.
32
+ * - **Runtime substitution** — wrapping `Promise`, replacing a suspense
33
+ * boundary. Buys the same knowledge without touching a component and is
34
+ * deliberately not shipped here: it moves the damage from design into
35
+ * semantics, where a difference caused by the patch cannot be told apart from
36
+ * a difference caused by the code. Expressible as a trick if a project decides
37
+ * the trade is worth it — that is the point of an open set.
38
+ * - **A contract the subject implements** — a readiness marker. Real design
39
+ * damage, and reserved for what the outside genuinely cannot know.
40
+ *
41
+ * ## Why this is in `format` and not in the raster package
42
+ *
43
+ * It was in `@variance-authority/raster` until 2026-08-06, on the reading that
44
+ * holding a page still is something you do before you photograph it. That
45
+ * reading was wrong in a way that cost correctness: an animation in flight is a
46
+ * *computed style value*, so it reaches the cheap representation too — and the
47
+ * allowlist excludes `animation-*` and `transition-*` precisely because it
48
+ * assumed a snapshot is taken with animation already disabled. Nothing disabled
49
+ * it. See {@link COLLECT_RECIPE} and ADR-0028.
50
+ *
51
+ * So a recipe is a render input on every tier, `EnvironmentInputs` carries its
52
+ * digest, and the vocabulary belongs beside the key it is part of.
53
+ */
54
+ export type { Intervention, ScreenshotOptions, SettleTarget, Trick } from './intervention.js';
55
+ /**
56
+ * Hand animations to the browser rather than emulating the hold in CSS.
57
+ *
58
+ * A browser disabling animations for a screenshot fast-forwards a finite
59
+ * animation to completion — the state a user comes to rest on — and cancels an
60
+ * infinite one to its initial frame, replaying it afterwards. That is the
61
+ * behaviour worth having, and CSS cannot express it.
62
+ */
63
+ export declare const holdAnimations: Intervention;
64
+ /**
65
+ * The same intent without a browser that can do it, and it is not equivalent.
66
+ *
67
+ * Pins every animation at its first frame, so a fade-in is captured at the
68
+ * moment it is invisible. `animation: none` is avoided deliberately — removing
69
+ * an animation drops whatever layout its keyframes contribute, which changes the
70
+ * page rather than stopping it.
71
+ */
72
+ export declare const pinAnimations: Intervention;
73
+ export declare const hideCaret: Intervention;
74
+ export declare const hideScrollbars: Intervention;
75
+ /**
76
+ * Drop the pixels of images the page itself called decorative, keeping their boxes.
77
+ *
78
+ * The other half of blanking, and it lives here because of what it needs to
79
+ * know. A driver rewriting responses (`@variance-authority/playwright`'s
80
+ * `blank` rules) can decide by URL and by intrinsic size, which answers "every
81
+ * illustration over 40,000 pixels" and answers it before the bytes are even
82
+ * fetched. It cannot answer `role="presentation"`, because a request carries no
83
+ * idea which element wanted it — that fact exists only in the document, so the
84
+ * trick that uses it is a stylesheet.
85
+ *
86
+ * `visibility:hidden` rather than `display:none`, and the distinction is the
87
+ * entire design: a hidden element still occupies exactly the box it would have,
88
+ * so a page whose column height comes from an image's intrinsic size is
89
+ * unchanged. `display:none` would collapse it and report a layout regression
90
+ * this tool caused.
91
+ *
92
+ * **Opt-in, and it belongs in no default recipe.** Every other trick here
93
+ * removes something that is not part of the assertion — a caret, a scrollbar, an
94
+ * animation mid-flight. This one removes page content, which is a judgement
95
+ * about what a suite is for, and a default that quietly stopped watching every
96
+ * `alt=""` image would hide real regressions under a green run.
97
+ */
98
+ export declare const hidePresentationalImages: Intervention;
99
+ export declare const waitForFonts: Intervention;
100
+ export declare const waitForImages: Intervention;
101
+ export declare const INTERVENTIONS: readonly Intervention[];
102
+ export type Recipe = readonly Intervention[];
103
+ /**
104
+ * Nothing at all, and correct for the tier that reads structure and declared style.
105
+ *
106
+ * A font that has not loaded cannot change which rules match or what they
107
+ * declare; an image that has not decoded cannot either. Waiting for both before
108
+ * a structure-and-style hash buys nothing and costs the wait per subject, on the
109
+ * rung the tier ladder exists to make cheap.
110
+ */
111
+ export declare const SEMANTIC_RECIPE: Recipe;
112
+ export declare const LAYOUT_RECIPE: Recipe;
113
+ export declare const RASTER_RECIPE: Recipe;
114
+ /**
115
+ * What is applied to a live page *before a subject is observed*, as opposed to
116
+ * before it is painted.
117
+ *
118
+ * The two are different recipes and it is not a preference. {@link
119
+ * holdAnimations} is a *screenshot option* — it asks the browser to settle
120
+ * animations for the image it is about to take — and there is no screenshot at
121
+ * collection time, so it would be a trick that silently does nothing. The CSS
122
+ * variant is the one that works where nobody is holding a camera, which is the
123
+ * whole reason both exist as separate values rather than as one switch.
124
+ *
125
+ * ## Why the cheap tier needs this at all
126
+ *
127
+ * The claim in [`ruleset.ts`](../rules/ruleset.ts) that `transition-*` and
128
+ * `animation-*` "describe a journey the snapshot does not contain" is only true
129
+ * if the snapshot is taken with the journey stopped. `transform`, `opacity`,
130
+ * `filter`, `color` and every geometric longhand *are* admitted, and an
131
+ * animation in flight moves all of them — so an unstabilized collection turns a
132
+ * 300ms fade into a component-attributed regression with a real file name on it,
133
+ * which is worse than an unexplained pixel diff because it is credible.
134
+ *
135
+ * Filtered by {@link forTier}, so jsdom applies none of it: with no layout
136
+ * engine and no animation clock there is nothing to hold still, and paying a
137
+ * `fonts.ready` wait per subject on the rung that exists to be cheap is exactly
138
+ * the trade {@link SEMANTIC_RECIPE} refuses.
139
+ */
140
+ export declare const COLLECT_RECIPE: Recipe;
141
+ /**
142
+ * Resolve a trick by the name a caller wrote down.
143
+ *
144
+ * The boundary a collection recipe crosses is a `page.evaluate`, and an
145
+ * `Intervention` does not survive it — `settle` is a function. Ids do survive,
146
+ * and the page holds this same registry, so a recipe travels as the list of
147
+ * names it is. A name nothing answers to is a caller error worth failing on
148
+ * rather than a trick to skip quietly: under-stabilizing is how a suite gets a
149
+ * flake it has already paid to prevent.
150
+ */
151
+ export declare function interventionById(id: string): Intervention | undefined;
152
+ /**
153
+ * A recipe from the names it travels as.
154
+ *
155
+ * Throws on a name nothing answers to, and names it. The quiet alternative —
156
+ * skip what cannot be resolved — turns a typo in a config into a suite that is
157
+ * one trick less stable than its operator believes, discovered later as a flake
158
+ * they have already paid to prevent. Failing here costs one run and one reading
159
+ * of the message.
160
+ */
161
+ export declare function recipeOf(ids: readonly string[]): Recipe;
162
+ /** Only the tricks a tier can observe the effect of. */
163
+ export declare function forTier(recipe: Recipe, tier: Tier): Recipe;
164
+ /**
165
+ * Tricks in a recipe that claim the same property.
166
+ *
167
+ * Returned rather than thrown, so a caller can decide — an override is a
168
+ * legitimate composition, and silently applying both is not. Two tricks over one
169
+ * property means one of them wins by accident of ordering, and which one is
170
+ * invisible in the result.
171
+ */
172
+ export declare function conflicts(recipe: Recipe): readonly {
173
+ governs: string;
174
+ ids: readonly string[];
175
+ }[];
176
+ export declare function recipeCss(recipe: Recipe): string;
177
+ export declare function recipeScreenshot(recipe: Recipe): ScreenshotOptions;
178
+ export declare function settleRecipe(recipe: Recipe, target: SettleTarget): Promise<void>;
179
+ /**
180
+ * The identity of a recipe.
181
+ *
182
+ * Sorted, so the order tricks were composed in does not change the identity —
183
+ * only which ones are present. Folded into `RenderIdentity`, which is what makes
184
+ * a cross-recipe comparison report `incomparable` instead of inventing a
185
+ * component to blame.
186
+ */
187
+ export declare function recipeDigest(recipe: Recipe): Digest;
188
+ /** The recipe as a sentence, so the gap between image and product stays visible. */
189
+ export declare function describeRecipe(recipe: Recipe): string;
190
+ //# sourceMappingURL=stabilize.d.ts.map