@tangle-network/browser-agent-driver 0.30.0 → 0.32.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 (252) hide show
  1. package/dist/brain/index.d.ts +12 -0
  2. package/dist/brain/index.d.ts.map +1 -1
  3. package/dist/brain/index.js +36 -8
  4. package/dist/brain/index.js.map +1 -1
  5. package/dist/cli-ack-patch.d.ts +39 -0
  6. package/dist/cli-ack-patch.d.ts.map +1 -0
  7. package/dist/cli-ack-patch.js +47 -0
  8. package/dist/cli-ack-patch.js.map +1 -0
  9. package/dist/cli-design-audit.d.ts +12 -0
  10. package/dist/cli-design-audit.d.ts.map +1 -1
  11. package/dist/cli-design-audit.js +78 -0
  12. package/dist/cli-design-audit.js.map +1 -1
  13. package/dist/cli-jobs.d.ts +13 -0
  14. package/dist/cli-jobs.d.ts.map +1 -0
  15. package/dist/cli-jobs.js +253 -0
  16. package/dist/cli-jobs.js.map +1 -0
  17. package/dist/cli-patterns.d.ts +26 -0
  18. package/dist/cli-patterns.d.ts.map +1 -0
  19. package/dist/cli-patterns.js +49 -0
  20. package/dist/cli-patterns.js.map +1 -0
  21. package/dist/cli-reports.d.ts +12 -0
  22. package/dist/cli-reports.d.ts.map +1 -0
  23. package/dist/cli-reports.js +97 -0
  24. package/dist/cli-reports.js.map +1 -0
  25. package/dist/cli.js +29 -1
  26. package/dist/cli.js.map +1 -1
  27. package/dist/design/audit/attribution/aggregate.d.ts +16 -0
  28. package/dist/design/audit/attribution/aggregate.d.ts.map +1 -0
  29. package/dist/design/audit/attribution/aggregate.js +81 -0
  30. package/dist/design/audit/attribution/aggregate.js.map +1 -0
  31. package/dist/design/audit/attribution/store.d.ts +36 -0
  32. package/dist/design/audit/attribution/store.d.ts.map +1 -0
  33. package/dist/design/audit/attribution/store.js +108 -0
  34. package/dist/design/audit/attribution/store.js.map +1 -0
  35. package/dist/design/audit/attribution/types.d.ts +13 -0
  36. package/dist/design/audit/attribution/types.d.ts.map +1 -0
  37. package/dist/design/audit/attribution/types.js +10 -0
  38. package/dist/design/audit/attribution/types.js.map +1 -0
  39. package/dist/design/audit/build-result.d.ts +68 -0
  40. package/dist/design/audit/build-result.d.ts.map +1 -0
  41. package/dist/design/audit/build-result.js +243 -0
  42. package/dist/design/audit/build-result.js.map +1 -0
  43. package/dist/design/audit/classify-ensemble.d.ts +46 -0
  44. package/dist/design/audit/classify-ensemble.d.ts.map +1 -0
  45. package/dist/design/audit/classify-ensemble.js +207 -0
  46. package/dist/design/audit/classify-ensemble.js.map +1 -0
  47. package/dist/design/audit/ethics/check.d.ts +59 -0
  48. package/dist/design/audit/ethics/check.d.ts.map +1 -0
  49. package/dist/design/audit/ethics/check.js +137 -0
  50. package/dist/design/audit/ethics/check.js.map +1 -0
  51. package/dist/design/audit/ethics/loader.d.ts +21 -0
  52. package/dist/design/audit/ethics/loader.d.ts.map +1 -0
  53. package/dist/design/audit/ethics/loader.js +207 -0
  54. package/dist/design/audit/ethics/loader.js.map +1 -0
  55. package/dist/design/audit/ethics/rules/finance.yaml +37 -0
  56. package/dist/design/audit/ethics/rules/kids.yaml +37 -0
  57. package/dist/design/audit/ethics/rules/legal.yaml +35 -0
  58. package/dist/design/audit/ethics/rules/medical.yaml +36 -0
  59. package/dist/design/audit/evaluate.d.ts.map +1 -1
  60. package/dist/design/audit/evaluate.js +4 -1
  61. package/dist/design/audit/evaluate.js.map +1 -1
  62. package/dist/design/audit/first-principles-mode.d.ts +42 -0
  63. package/dist/design/audit/first-principles-mode.d.ts.map +1 -0
  64. package/dist/design/audit/first-principles-mode.js +77 -0
  65. package/dist/design/audit/first-principles-mode.js.map +1 -0
  66. package/dist/design/audit/modality/android.d.ts +14 -0
  67. package/dist/design/audit/modality/android.d.ts.map +1 -0
  68. package/dist/design/audit/modality/android.js +18 -0
  69. package/dist/design/audit/modality/android.js.map +1 -0
  70. package/dist/design/audit/modality/html.d.ts +22 -0
  71. package/dist/design/audit/modality/html.d.ts.map +1 -0
  72. package/dist/design/audit/modality/html.js +51 -0
  73. package/dist/design/audit/modality/html.js.map +1 -0
  74. package/dist/design/audit/modality/index.d.ts +8 -0
  75. package/dist/design/audit/modality/index.d.ts.map +1 -0
  76. package/dist/design/audit/modality/index.js +15 -0
  77. package/dist/design/audit/modality/index.js.map +1 -0
  78. package/dist/design/audit/modality/ios.d.ts +16 -0
  79. package/dist/design/audit/modality/ios.d.ts.map +1 -0
  80. package/dist/design/audit/modality/ios.js +19 -0
  81. package/dist/design/audit/modality/ios.js.map +1 -0
  82. package/dist/design/audit/modality/types.d.ts +9 -0
  83. package/dist/design/audit/modality/types.d.ts.map +1 -0
  84. package/dist/design/audit/modality/types.js +9 -0
  85. package/dist/design/audit/modality/types.js.map +1 -0
  86. package/dist/design/audit/patches/generate.d.ts +45 -0
  87. package/dist/design/audit/patches/generate.d.ts.map +1 -0
  88. package/dist/design/audit/patches/generate.js +161 -0
  89. package/dist/design/audit/patches/generate.js.map +1 -0
  90. package/dist/design/audit/patches/index.d.ts +8 -0
  91. package/dist/design/audit/patches/index.d.ts.map +1 -0
  92. package/dist/design/audit/patches/index.js +5 -0
  93. package/dist/design/audit/patches/index.js.map +1 -0
  94. package/dist/design/audit/patches/parse.d.ts +29 -0
  95. package/dist/design/audit/patches/parse.d.ts.map +1 -0
  96. package/dist/design/audit/patches/parse.js +153 -0
  97. package/dist/design/audit/patches/parse.js.map +1 -0
  98. package/dist/design/audit/patches/render.d.ts +20 -0
  99. package/dist/design/audit/patches/render.d.ts.map +1 -0
  100. package/dist/design/audit/patches/render.js +55 -0
  101. package/dist/design/audit/patches/render.js.map +1 -0
  102. package/dist/design/audit/patches/severity-enforcement.d.ts +23 -0
  103. package/dist/design/audit/patches/severity-enforcement.d.ts.map +1 -0
  104. package/dist/design/audit/patches/severity-enforcement.js +42 -0
  105. package/dist/design/audit/patches/severity-enforcement.js.map +1 -0
  106. package/dist/design/audit/patches/validate.d.ts +40 -0
  107. package/dist/design/audit/patches/validate.d.ts.map +1 -0
  108. package/dist/design/audit/patches/validate.js +60 -0
  109. package/dist/design/audit/patches/validate.js.map +1 -0
  110. package/dist/design/audit/patterns/match.d.ts +24 -0
  111. package/dist/design/audit/patterns/match.d.ts.map +1 -0
  112. package/dist/design/audit/patterns/match.js +48 -0
  113. package/dist/design/audit/patterns/match.js.map +1 -0
  114. package/dist/design/audit/patterns/mine.d.ts +31 -0
  115. package/dist/design/audit/patterns/mine.d.ts.map +1 -0
  116. package/dist/design/audit/patterns/mine.js +35 -0
  117. package/dist/design/audit/patterns/mine.js.map +1 -0
  118. package/dist/design/audit/patterns/store.d.ts +14 -0
  119. package/dist/design/audit/patterns/store.d.ts.map +1 -0
  120. package/dist/design/audit/patterns/store.js +53 -0
  121. package/dist/design/audit/patterns/store.js.map +1 -0
  122. package/dist/design/audit/patterns/types.d.ts +53 -0
  123. package/dist/design/audit/patterns/types.d.ts.map +1 -0
  124. package/dist/design/audit/patterns/types.js +13 -0
  125. package/dist/design/audit/patterns/types.js.map +1 -0
  126. package/dist/design/audit/pipeline.d.ts +12 -0
  127. package/dist/design/audit/pipeline.d.ts.map +1 -1
  128. package/dist/design/audit/pipeline.js +81 -5
  129. package/dist/design/audit/pipeline.js.map +1 -1
  130. package/dist/design/audit/rubric/anchor-loader.d.ts +44 -0
  131. package/dist/design/audit/rubric/anchor-loader.d.ts.map +1 -0
  132. package/dist/design/audit/rubric/anchor-loader.js +210 -0
  133. package/dist/design/audit/rubric/anchor-loader.js.map +1 -0
  134. package/dist/design/audit/rubric/anchors/blog.yaml +33 -0
  135. package/dist/design/audit/rubric/anchors/dashboard.yaml +35 -0
  136. package/dist/design/audit/rubric/anchors/docs.yaml +35 -0
  137. package/dist/design/audit/rubric/anchors/ecommerce.yaml +33 -0
  138. package/dist/design/audit/rubric/anchors/marketing.yaml +34 -0
  139. package/dist/design/audit/rubric/anchors/saas-app.yaml +38 -0
  140. package/dist/design/audit/rubric/anchors/social.yaml +33 -0
  141. package/dist/design/audit/rubric/anchors/tool.yaml +33 -0
  142. package/dist/design/audit/rubric/anchors/utility.yaml +33 -0
  143. package/dist/design/audit/rubric/fragments/audience-clinician.md +42 -0
  144. package/dist/design/audit/rubric/fragments/audience-developer.md +40 -0
  145. package/dist/design/audit/rubric/fragments/audience-kids.md +35 -0
  146. package/dist/design/audit/rubric/fragments/audience-vulnerability-minor-facing.md +37 -0
  147. package/dist/design/audit/rubric/fragments/first-principles.md +65 -0
  148. package/dist/design/audit/rubric/fragments/modality-mobile.md +39 -0
  149. package/dist/design/audit/rubric/fragments/modality-tablet.md +35 -0
  150. package/dist/design/audit/rubric/fragments/regulatory-coppa.md +32 -0
  151. package/dist/design/audit/rubric/fragments/regulatory-gdpr.md +33 -0
  152. package/dist/design/audit/rubric/fragments/regulatory-hipaa.md +36 -0
  153. package/dist/design/audit/rubric/loader.d.ts +26 -6
  154. package/dist/design/audit/rubric/loader.d.ts.map +1 -1
  155. package/dist/design/audit/rubric/loader.js +45 -26
  156. package/dist/design/audit/rubric/loader.js.map +1 -1
  157. package/dist/design/audit/rubric/rollup-weights.d.ts +25 -0
  158. package/dist/design/audit/rubric/rollup-weights.d.ts.map +1 -0
  159. package/dist/design/audit/rubric/rollup-weights.js +51 -0
  160. package/dist/design/audit/rubric/rollup-weights.js.map +1 -0
  161. package/dist/design/audit/score-types.d.ts +431 -0
  162. package/dist/design/audit/score-types.d.ts.map +1 -0
  163. package/dist/design/audit/score-types.js +26 -0
  164. package/dist/design/audit/score-types.js.map +1 -0
  165. package/dist/design/audit/score.d.ts +49 -0
  166. package/dist/design/audit/score.d.ts.map +1 -0
  167. package/dist/design/audit/score.js +211 -0
  168. package/dist/design/audit/score.js.map +1 -0
  169. package/dist/design/audit/types.d.ts +28 -0
  170. package/dist/design/audit/types.d.ts.map +1 -1
  171. package/dist/discover/index.d.ts +16 -0
  172. package/dist/discover/index.d.ts.map +1 -0
  173. package/dist/discover/index.js +25 -0
  174. package/dist/discover/index.js.map +1 -0
  175. package/dist/discover/wayback.d.ts +49 -0
  176. package/dist/discover/wayback.d.ts.map +1 -0
  177. package/dist/discover/wayback.js +123 -0
  178. package/dist/discover/wayback.js.map +1 -0
  179. package/dist/jobs/anti-bot.d.ts +19 -0
  180. package/dist/jobs/anti-bot.d.ts.map +1 -0
  181. package/dist/jobs/anti-bot.js +64 -0
  182. package/dist/jobs/anti-bot.js.map +1 -0
  183. package/dist/jobs/cost-estimate.d.ts +12 -0
  184. package/dist/jobs/cost-estimate.d.ts.map +1 -0
  185. package/dist/jobs/cost-estimate.js +21 -0
  186. package/dist/jobs/cost-estimate.js.map +1 -0
  187. package/dist/jobs/cost-history.d.ts +19 -0
  188. package/dist/jobs/cost-history.d.ts.map +1 -0
  189. package/dist/jobs/cost-history.js +42 -0
  190. package/dist/jobs/cost-history.js.map +1 -0
  191. package/dist/jobs/index.d.ts +31 -0
  192. package/dist/jobs/index.d.ts.map +1 -0
  193. package/dist/jobs/index.js +37 -0
  194. package/dist/jobs/index.js.map +1 -0
  195. package/dist/jobs/orchestrator.d.ts +42 -0
  196. package/dist/jobs/orchestrator.d.ts.map +1 -0
  197. package/dist/jobs/orchestrator.js +282 -0
  198. package/dist/jobs/orchestrator.js.map +1 -0
  199. package/dist/jobs/queue.d.ts +45 -0
  200. package/dist/jobs/queue.d.ts.map +1 -0
  201. package/dist/jobs/queue.js +114 -0
  202. package/dist/jobs/queue.js.map +1 -0
  203. package/dist/jobs/retry.d.ts +36 -0
  204. package/dist/jobs/retry.d.ts.map +1 -0
  205. package/dist/jobs/retry.js +77 -0
  206. package/dist/jobs/retry.js.map +1 -0
  207. package/dist/jobs/store.d.ts +31 -0
  208. package/dist/jobs/store.d.ts.map +1 -0
  209. package/dist/jobs/store.js +92 -0
  210. package/dist/jobs/store.js.map +1 -0
  211. package/dist/jobs/types.d.ts +106 -0
  212. package/dist/jobs/types.d.ts.map +1 -0
  213. package/dist/jobs/types.js +13 -0
  214. package/dist/jobs/types.js.map +1 -0
  215. package/dist/reports/aggregate.d.ts +38 -0
  216. package/dist/reports/aggregate.d.ts.map +1 -0
  217. package/dist/reports/aggregate.js +145 -0
  218. package/dist/reports/aggregate.js.map +1 -0
  219. package/dist/reports/index.d.ts +21 -0
  220. package/dist/reports/index.d.ts.map +1 -0
  221. package/dist/reports/index.js +15 -0
  222. package/dist/reports/index.js.map +1 -0
  223. package/dist/reports/narrate.d.ts +19 -0
  224. package/dist/reports/narrate.d.ts.map +1 -0
  225. package/dist/reports/narrate.js +40 -0
  226. package/dist/reports/narrate.js.map +1 -0
  227. package/dist/reports/templates.d.ts +43 -0
  228. package/dist/reports/templates.d.ts.map +1 -0
  229. package/dist/reports/templates.js +200 -0
  230. package/dist/reports/templates.js.map +1 -0
  231. package/dist/reports/tokens.d.ts +69 -0
  232. package/dist/reports/tokens.d.ts.map +1 -0
  233. package/dist/reports/tokens.js +74 -0
  234. package/dist/reports/tokens.js.map +1 -0
  235. package/dist/reports/tools.d.ts +76 -0
  236. package/dist/reports/tools.d.ts.map +1 -0
  237. package/dist/reports/tools.js +205 -0
  238. package/dist/reports/tools.js.map +1 -0
  239. package/dist/reports/types.d.ts +51 -0
  240. package/dist/reports/types.d.ts.map +1 -0
  241. package/dist/reports/types.js +9 -0
  242. package/dist/reports/types.js.map +1 -0
  243. package/dist/run-state.d.ts +36 -1
  244. package/dist/run-state.d.ts.map +1 -1
  245. package/dist/run-state.js +36 -1
  246. package/dist/run-state.js.map +1 -1
  247. package/dist/runner/runner.d.ts.map +1 -1
  248. package/dist/runner/runner.js +73 -3
  249. package/dist/runner/runner.js.map +1 -1
  250. package/dist/types.d.ts +7 -0
  251. package/dist/types.d.ts.map +1 -1
  252. package/package.json +5 -1
@@ -0,0 +1,161 @@
1
+ /**
2
+ * Patch generator — Layer 2's second LLM call.
3
+ *
4
+ * The findings prompt (evaluate.ts) stays slim and focused on scoring +
5
+ * findings. After findings exist, this module makes a SECOND LLM call given
6
+ * those major/critical findings and asks for one Patch per finding. The
7
+ * second-call shape is intentionally narrow: only the patch contract +
8
+ * ground-truth snapshot, nothing else. That keeps each call's cognitive load
9
+ * low and lets us measure them independently.
10
+ *
11
+ * Flow:
12
+ * 1. Filter findings to severity ∈ {major, critical}.
13
+ * 2. Build a focused prompt (snapshot + JSON of those findings).
14
+ * 3. Call the LLM, parse + validate the response, attach valid patches
15
+ * back to their findings by id.
16
+ *
17
+ * On any failure: return findings unchanged. Layer 2 enforcement (downgrade
18
+ * major/critical without a valid patch) runs after this in build-result.ts,
19
+ * so a failed generator → graceful degradation, not a broken pipeline.
20
+ */
21
+ import { parsePatches } from './parse.js';
22
+ const SYSTEM_OPENER = 'You are a code-mod author. For each finding below, emit ONE Patch the agent can apply literally. Patches that target HTML or page structure must reference verbatim text in the snapshot. Patches that target source files (CSS/TSX/Tailwind) reference selectors only — the agent verifies them at apply-time against the source.';
23
+ const DEFAULT_MAX = 8;
24
+ export async function generatePatches(opts) {
25
+ const max = opts.maxFindings ?? DEFAULT_MAX;
26
+ const eligible = opts.findings
27
+ .filter(f => f.severity === 'major' || f.severity === 'critical')
28
+ .slice(0, max);
29
+ if (eligible.length === 0) {
30
+ return { findings: opts.findings, tokensUsed: 0, notes: [] };
31
+ }
32
+ const prompt = buildPrompt(opts.snapshot, eligible);
33
+ let raw = '';
34
+ let tokensUsed = 0;
35
+ try {
36
+ const llm = await opts.brain.complete(SYSTEM_OPENER, prompt, { maxOutputTokens: 2000 });
37
+ raw = llm.text ?? '';
38
+ tokensUsed = llm.tokensUsed ?? 0;
39
+ }
40
+ catch (err) {
41
+ return {
42
+ findings: opts.findings,
43
+ tokensUsed: 0,
44
+ notes: [{ findingId: '*', reason: `LLM call failed: ${err.message}` }],
45
+ };
46
+ }
47
+ const parsed = parseGeneratorResponse(raw);
48
+ const byFinding = new Map();
49
+ for (const item of parsed.items) {
50
+ if (item.findingId)
51
+ byFinding.set(item.findingId, item.patch);
52
+ }
53
+ const notes = [];
54
+ const updated = opts.findings.map(f => {
55
+ const patchRaw = byFinding.get(f.id);
56
+ if (!patchRaw) {
57
+ if (f.severity === 'major' || f.severity === 'critical') {
58
+ notes.push({ findingId: f.id, reason: 'no patch in generator response' });
59
+ }
60
+ return f;
61
+ }
62
+ // Stamp the canonical findingId onto the patch (LLM may have used a placeholder).
63
+ const stamped = withFindingId(patchRaw, f.id);
64
+ // Quick parse check so the build-result stage sees a sane shape.
65
+ const parsedOne = parsePatches([stamped]);
66
+ if (parsedOne.patches.length === 0) {
67
+ notes.push({ findingId: f.id, reason: `parse failed: ${parsedOne.errors[0]?.reason ?? 'unknown'}` });
68
+ return f;
69
+ }
70
+ return { ...f, rawPatches: [stamped] };
71
+ });
72
+ return { findings: updated, tokensUsed, notes };
73
+ }
74
+ function buildPrompt(snapshot, findings) {
75
+ // Trim the snapshot to keep the prompt cheap. The findings reference visible
76
+ // elements; trimming should not cost meaningful context.
77
+ const trimmedSnapshot = snapshot.length > 8000 ? snapshot.slice(0, 8000) + '\n…[truncated]' : snapshot;
78
+ const findingsBlock = findings.map(f => ({
79
+ id: f.id,
80
+ severity: f.severity,
81
+ description: f.description,
82
+ location: f.location,
83
+ cssSelector: f.cssSelector,
84
+ suggestion: f.suggestion,
85
+ }));
86
+ return `PAGE SNAPSHOT (accessibility-tree text):
87
+ ${trimmedSnapshot}
88
+
89
+ FINDINGS THAT NEED A PATCH (one per id):
90
+ ${JSON.stringify(findingsBlock, null, 2)}
91
+
92
+ For each finding above, emit ONE Patch object. Required shape:
93
+ {
94
+ "patchId": "p-<short-stable-id>",
95
+ "findingId": "<copy verbatim from the finding>",
96
+ "scope": "page" | "section" | "component" | "system",
97
+ "target": {
98
+ "scope": "css" | "tsx" | "jsx" | "tailwind" | "module-css" | "styled-component" | "html" | "structural",
99
+ "cssSelector": "...", // OR
100
+ "filePath": "...", // OR
101
+ "componentName": "..." // at least ONE must be set
102
+ },
103
+ "diff": {
104
+ "before": "<verbatim text the agent will search-replace>",
105
+ "after": "<replacement text>"
106
+ },
107
+ "testThatProves": { "kind": "rerun-audit" | "visual-snapshot" | "a11y-rule" | "storybook" | "unit" | "manual", "description": "..." },
108
+ "rollback": { "kind": "css-disable" | "git-revert" | "manual" },
109
+ "estimatedDelta": { "dim": "product_intent" | "visual_craft" | "trust_clarity" | "workflow" | "content_ia", "delta": -3..3 },
110
+ "estimatedDeltaConfidence": "high" | "medium" | "low" | "untested"
111
+ }
112
+
113
+ Snapshot-anchoring rule (READ CAREFULLY — most patch failures fail this):
114
+ - target.scope MUST be "css" by default. Use "html" or "structural" ONLY when you are paste-copying a literal substring from the SNAPSHOT BLOCK above (not from your imagination, not from typical-site assumptions).
115
+ - Before setting target.scope to "html", verify diff.before is a verbatim substring of the snapshot block above. If it isn't, change target.scope to "css".
116
+ - For css / tsx / jsx / tailwind / module-css / styled-component scopes, diff.before is a source-file fragment the agent resolves at apply-time; the audit does not validate it. This is the safe default.
117
+
118
+ If a finding does not admit a clean patch, OMIT it (do not invent diffs).
119
+
120
+ RESPOND WITH ONLY a JSON object:
121
+ {
122
+ "patches": [
123
+ { "findingId": "<id>", "patch": <the Patch object above> }
124
+ ]
125
+ }`;
126
+ }
127
+ function parseGeneratorResponse(raw) {
128
+ let text = raw.trim();
129
+ if (text.startsWith('```')) {
130
+ text = text.replace(/^```(?:json)?\n?/, '').replace(/\n?```$/, '');
131
+ }
132
+ const start = text.indexOf('{');
133
+ const end = text.lastIndexOf('}');
134
+ if (start < 0 || end <= start)
135
+ return { items: [] };
136
+ try {
137
+ const obj = JSON.parse(text.slice(start, end + 1));
138
+ if (!Array.isArray(obj.patches))
139
+ return { items: [] };
140
+ const items = [];
141
+ for (const p of obj.patches) {
142
+ if (!p || typeof p !== 'object')
143
+ continue;
144
+ const rec = p;
145
+ if (typeof rec.findingId !== 'string')
146
+ continue;
147
+ items.push({ findingId: rec.findingId, patch: rec.patch ?? p });
148
+ }
149
+ return { items };
150
+ }
151
+ catch {
152
+ return { items: [] };
153
+ }
154
+ }
155
+ function withFindingId(raw, findingId) {
156
+ if (raw && typeof raw === 'object') {
157
+ return { ...raw, findingId };
158
+ }
159
+ return raw;
160
+ }
161
+ //# sourceMappingURL=generate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generate.js","sourceRoot":"","sources":["../../../../src/design/audit/patches/generate.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ export { parsePatch, parsePatches } from './parse.js';
2
+ export { validatePatch, validatePatches } from './validate.js';
3
+ export { renderUnifiedDiff, renderPatchSummary } from './render.js';
4
+ export { enforcePatchPolicy } from './severity-enforcement.js';
5
+ export type { ParseResult } from './parse.js';
6
+ export type { ValidationResult, ValidationReason } from './validate.js';
7
+ export type { EnforcementResult, EnforcementRecord } from './severity-enforcement.js';
8
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/design/audit/patches/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AACrD,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,eAAe,CAAA;AAC9D,OAAO,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAA;AACnE,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAA;AAC9D,YAAY,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;AAC7C,YAAY,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAA;AACvE,YAAY,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAA"}
@@ -0,0 +1,5 @@
1
+ export { parsePatch, parsePatches } from './parse.js';
2
+ export { validatePatch, validatePatches } from './validate.js';
3
+ export { renderUnifiedDiff, renderPatchSummary } from './render.js';
4
+ export { enforcePatchPolicy } from './severity-enforcement.js';
5
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/design/audit/patches/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AACrD,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,eAAe,CAAA;AAC9D,OAAO,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAA;AACnE,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAA"}
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Patch parser — converts raw LLM JSON output into typed `Patch` objects.
3
+ *
4
+ * Strict shape validation. On schema mismatch returns `{ patch: null, reason }`
5
+ * rather than throwing — the calling pipeline batches many candidate patches
6
+ * per audit and a single malformed entry must not abort the whole run.
7
+ */
8
+ import type { Patch } from '../score-types.js';
9
+ export interface ParseResult {
10
+ patch: Patch | null;
11
+ reason?: string;
12
+ }
13
+ /**
14
+ * Parse a single raw LLM-produced object into a `Patch`. Returns
15
+ * `{ patch: null, reason }` on any schema violation.
16
+ */
17
+ export declare function parsePatch(raw: unknown): ParseResult;
18
+ /**
19
+ * Parse an array of raw patch objects. Invalid entries are dropped from the
20
+ * returned `patches` and reported in `errors` with their original index.
21
+ */
22
+ export declare function parsePatches(raw: unknown): {
23
+ patches: Patch[];
24
+ errors: Array<{
25
+ index: number;
26
+ reason: string;
27
+ }>;
28
+ };
29
+ //# sourceMappingURL=parse.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parse.d.ts","sourceRoot":"","sources":["../../../../src/design/audit/patches/parse.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EACV,KAAK,EAQN,MAAM,mBAAmB,CAAA;AAgB1B,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,KAAK,GAAG,IAAI,CAAA;IACnB,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB;AAwDD;;;GAGG;AACH,wBAAgB,UAAU,CAAC,GAAG,EAAE,OAAO,GAAG,WAAW,CA+CpD;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,OAAO,GAAG;IAC1C,OAAO,EAAE,KAAK,EAAE,CAAA;IAChB,MAAM,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CACjD,CAYA"}
@@ -0,0 +1,153 @@
1
+ /**
2
+ * Patch parser — converts raw LLM JSON output into typed `Patch` objects.
3
+ *
4
+ * Strict shape validation. On schema mismatch returns `{ patch: null, reason }`
5
+ * rather than throwing — the calling pipeline batches many candidate patches
6
+ * per audit and a single malformed entry must not abort the whole run.
7
+ */
8
+ const VALID_SCOPES = ['page', 'section', 'component', 'system'];
9
+ const VALID_TARGET_SCOPES = [
10
+ 'tsx', 'jsx', 'css', 'tailwind', 'module-css', 'styled-component', 'structural', 'html',
11
+ ];
12
+ const VALID_TEST_KINDS = [
13
+ 'storybook', 'a11y-rule', 'visual-snapshot', 'unit', 'rerun-audit', 'manual',
14
+ ];
15
+ const VALID_ROLLBACK_KINDS = ['git-revert', 'css-disable', 'manual'];
16
+ const VALID_CONFIDENCES = ['high', 'medium', 'low', 'untested'];
17
+ function isObject(value) {
18
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
19
+ }
20
+ function isString(value) {
21
+ return typeof value === 'string' && value.length > 0;
22
+ }
23
+ function oneOf(value, allowed) {
24
+ return typeof value === 'string' && allowed.includes(value);
25
+ }
26
+ function parseTarget(raw) {
27
+ if (!isObject(raw))
28
+ return 'target: not an object';
29
+ if (!oneOf(raw.scope, VALID_TARGET_SCOPES))
30
+ return `target.scope: invalid (got ${String(raw.scope)})`;
31
+ const target = { scope: raw.scope };
32
+ if (raw.filePath !== undefined) {
33
+ if (!isString(raw.filePath))
34
+ return 'target.filePath: must be non-empty string';
35
+ target.filePath = raw.filePath;
36
+ }
37
+ if (raw.componentName !== undefined) {
38
+ if (!isString(raw.componentName))
39
+ return 'target.componentName: must be non-empty string';
40
+ target.componentName = raw.componentName;
41
+ }
42
+ if (raw.cssSelector !== undefined) {
43
+ if (!isString(raw.cssSelector))
44
+ return 'target.cssSelector: must be non-empty string';
45
+ target.cssSelector = raw.cssSelector;
46
+ }
47
+ return target;
48
+ }
49
+ function parseTest(raw) {
50
+ if (!isObject(raw))
51
+ return 'testThatProves: not an object';
52
+ if (!oneOf(raw.kind, VALID_TEST_KINDS))
53
+ return `testThatProves.kind: invalid (got ${String(raw.kind)})`;
54
+ if (!isString(raw.description))
55
+ return 'testThatProves.description: must be non-empty string';
56
+ const test = { kind: raw.kind, description: raw.description };
57
+ if (raw.command !== undefined) {
58
+ if (typeof raw.command !== 'string')
59
+ return 'testThatProves.command: must be string when present';
60
+ test.command = raw.command;
61
+ }
62
+ return test;
63
+ }
64
+ function parseRollback(raw) {
65
+ if (!isObject(raw))
66
+ return 'rollback: not an object';
67
+ if (!oneOf(raw.kind, VALID_ROLLBACK_KINDS))
68
+ return `rollback.kind: invalid (got ${String(raw.kind)})`;
69
+ const rollback = { kind: raw.kind };
70
+ if (raw.instruction !== undefined) {
71
+ if (typeof raw.instruction !== 'string')
72
+ return 'rollback.instruction: must be string when present';
73
+ rollback.instruction = raw.instruction;
74
+ }
75
+ return rollback;
76
+ }
77
+ /**
78
+ * Parse a single raw LLM-produced object into a `Patch`. Returns
79
+ * `{ patch: null, reason }` on any schema violation.
80
+ */
81
+ export function parsePatch(raw) {
82
+ if (!isObject(raw))
83
+ return { patch: null, reason: 'patch: not an object' };
84
+ if (!isString(raw.patchId))
85
+ return { patch: null, reason: 'patchId: required non-empty string' };
86
+ if (!isString(raw.findingId))
87
+ return { patch: null, reason: 'findingId: required non-empty string' };
88
+ if (!oneOf(raw.scope, VALID_SCOPES))
89
+ return { patch: null, reason: `scope: invalid (got ${String(raw.scope)})` };
90
+ const target = parseTarget(raw.target);
91
+ if (typeof target === 'string')
92
+ return { patch: null, reason: target };
93
+ if (!isObject(raw.diff))
94
+ return { patch: null, reason: 'diff: not an object' };
95
+ if (!isString(raw.diff.before))
96
+ return { patch: null, reason: 'diff.before: required non-empty string' };
97
+ if (typeof raw.diff.after !== 'string')
98
+ return { patch: null, reason: 'diff.after: required string' };
99
+ const diff = {
100
+ before: raw.diff.before,
101
+ after: raw.diff.after,
102
+ ...(typeof raw.diff.unifiedDiff === 'string' ? { unifiedDiff: raw.diff.unifiedDiff } : {}),
103
+ };
104
+ const test = parseTest(raw.testThatProves);
105
+ if (typeof test === 'string')
106
+ return { patch: null, reason: test };
107
+ const rollback = parseRollback(raw.rollback);
108
+ if (typeof rollback === 'string')
109
+ return { patch: null, reason: rollback };
110
+ if (!isObject(raw.estimatedDelta))
111
+ return { patch: null, reason: 'estimatedDelta: not an object' };
112
+ if (!isString(raw.estimatedDelta.dim))
113
+ return { patch: null, reason: 'estimatedDelta.dim: required' };
114
+ if (typeof raw.estimatedDelta.delta !== 'number' || !Number.isFinite(raw.estimatedDelta.delta)) {
115
+ return { patch: null, reason: 'estimatedDelta.delta: must be finite number' };
116
+ }
117
+ if (!oneOf(raw.estimatedDeltaConfidence, VALID_CONFIDENCES)) {
118
+ return { patch: null, reason: `estimatedDeltaConfidence: invalid (got ${String(raw.estimatedDeltaConfidence)})` };
119
+ }
120
+ const patch = {
121
+ patchId: raw.patchId,
122
+ findingId: raw.findingId,
123
+ scope: raw.scope,
124
+ target,
125
+ diff,
126
+ testThatProves: test,
127
+ rollback,
128
+ estimatedDelta: { dim: raw.estimatedDelta.dim, delta: raw.estimatedDelta.delta },
129
+ estimatedDeltaConfidence: raw.estimatedDeltaConfidence,
130
+ ...(typeof raw.matchedPatternId === 'string' ? { matchedPatternId: raw.matchedPatternId } : {}),
131
+ };
132
+ return { patch };
133
+ }
134
+ /**
135
+ * Parse an array of raw patch objects. Invalid entries are dropped from the
136
+ * returned `patches` and reported in `errors` with their original index.
137
+ */
138
+ export function parsePatches(raw) {
139
+ if (!Array.isArray(raw)) {
140
+ return { patches: [], errors: [{ index: -1, reason: 'patches: not an array' }] };
141
+ }
142
+ const patches = [];
143
+ const errors = [];
144
+ for (let i = 0; i < raw.length; i++) {
145
+ const result = parsePatch(raw[i]);
146
+ if (result.patch)
147
+ patches.push(result.patch);
148
+ else
149
+ errors.push({ index: i, reason: result.reason ?? 'unknown' });
150
+ }
151
+ return { patches, errors };
152
+ }
153
+ //# sourceMappingURL=parse.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parse.js","sourceRoot":"","sources":["../../../../src/design/audit/patches/parse.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Patch renderer — produces a unified diff from a Patch when filePath is known.
3
+ *
4
+ * Agents can pipe the result to `git apply --check` then `git apply`.
5
+ * When filePath is unknown, returns null — the agent must use before/after for
6
+ * search-replace instead.
7
+ */
8
+ import type { Patch } from '../score-types.js';
9
+ /**
10
+ * Render a minimal unified diff (1-hunk, 3 lines context) from a patch.
11
+ * Returns null when:
12
+ * - `target.filePath` is not set (no file to diff against)
13
+ * - `unifiedDiff` is already set on the patch (prefer the LLM's version)
14
+ */
15
+ export declare function renderUnifiedDiff(patch: Patch): string | null;
16
+ /**
17
+ * Render a human-readable patch summary for display in report.md.
18
+ */
19
+ export declare function renderPatchSummary(patch: Patch): string;
20
+ //# sourceMappingURL=render.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"render.d.ts","sourceRoot":"","sources":["../../../../src/design/audit/patches/render.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAA;AAE9C;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,KAAK,GAAG,MAAM,GAAG,IAAI,CAuB7D;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,KAAK,GAAG,MAAM,CAYvD"}
@@ -0,0 +1,55 @@
1
+ /**
2
+ * Patch renderer — produces a unified diff from a Patch when filePath is known.
3
+ *
4
+ * Agents can pipe the result to `git apply --check` then `git apply`.
5
+ * When filePath is unknown, returns null — the agent must use before/after for
6
+ * search-replace instead.
7
+ */
8
+ /**
9
+ * Render a minimal unified diff (1-hunk, 3 lines context) from a patch.
10
+ * Returns null when:
11
+ * - `target.filePath` is not set (no file to diff against)
12
+ * - `unifiedDiff` is already set on the patch (prefer the LLM's version)
13
+ */
14
+ export function renderUnifiedDiff(patch) {
15
+ if (patch.diff.unifiedDiff)
16
+ return patch.diff.unifiedDiff;
17
+ if (!patch.target.filePath)
18
+ return null;
19
+ const { before, after } = patch.diff;
20
+ const filePath = patch.target.filePath;
21
+ const beforeLines = before.split('\n');
22
+ const afterLines = after.split('\n');
23
+ const removals = beforeLines.map(l => `- ${l}`);
24
+ const additions = afterLines.map(l => `+ ${l}`);
25
+ const hunkOldLen = beforeLines.length;
26
+ const hunkNewLen = afterLines.length;
27
+ return [
28
+ `--- a/${filePath}`,
29
+ `+++ b/${filePath}`,
30
+ `@@ -1,${hunkOldLen} +1,${hunkNewLen} @@`,
31
+ ...removals,
32
+ ...additions,
33
+ ].join('\n');
34
+ }
35
+ /**
36
+ * Render a human-readable patch summary for display in report.md.
37
+ */
38
+ export function renderPatchSummary(patch) {
39
+ const parts = [];
40
+ parts.push(`**Patch ${patch.patchId}** (${patch.scope})`);
41
+ if (patch.target.filePath)
42
+ parts.push(`File: \`${patch.target.filePath}\``);
43
+ else if (patch.target.cssSelector)
44
+ parts.push(`Selector: \`${patch.target.cssSelector}\``);
45
+ else if (patch.target.componentName)
46
+ parts.push(`Component: \`${patch.target.componentName}\``);
47
+ parts.push(`\`\`\`diff\n${renderUnifiedDiff(patch) ?? `- ${patch.diff.before}\n+ ${patch.diff.after}`}\n\`\`\``);
48
+ parts.push(`Test: ${patch.testThatProves.description}`);
49
+ if (patch.testThatProves.command)
50
+ parts.push(`Command: \`${patch.testThatProves.command}\``);
51
+ parts.push(`Rollback: ${patch.rollback.kind}${patch.rollback.instruction ? ` — ${patch.rollback.instruction}` : ''}`);
52
+ parts.push(`Estimated Δ: ${patch.estimatedDelta.dim} ${patch.estimatedDelta.delta > 0 ? '+' : ''}${patch.estimatedDelta.delta} (confidence: ${patch.estimatedDeltaConfidence})`);
53
+ return parts.join('\n');
54
+ }
55
+ //# sourceMappingURL=render.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"render.js","sourceRoot":"","sources":["../../../../src/design/audit/patches/render.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Severity enforcement — every major/critical finding MUST have ≥1 valid patch.
3
+ *
4
+ * Findings without patches are downgraded to `minor` with an explanatory note.
5
+ * This runs as a post-processing step after patch validation.
6
+ */
7
+ import type { DesignFinding } from '../score-types.js';
8
+ export interface EnforcementRecord {
9
+ findingId: string;
10
+ fromSeverity: string;
11
+ toSeverity: 'minor';
12
+ reason: string;
13
+ }
14
+ export interface EnforcementResult {
15
+ findings: DesignFinding[];
16
+ downgraded: EnforcementRecord[];
17
+ }
18
+ /**
19
+ * Given a list of findings and the set of valid patches (post-validation),
20
+ * downgrade any major/critical finding that has no valid patch to `minor`.
21
+ */
22
+ export declare function enforcePatchPolicy(findings: DesignFinding[], validPatchIds: Set<string>): EnforcementResult;
23
+ //# sourceMappingURL=severity-enforcement.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"severity-enforcement.d.ts","sourceRoot":"","sources":["../../../../src/design/audit/patches/severity-enforcement.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAS,aAAa,EAAE,MAAM,mBAAmB,CAAA;AAE7D,MAAM,WAAW,iBAAiB;IAChC,SAAS,EAAE,MAAM,CAAA;IACjB,YAAY,EAAE,MAAM,CAAA;IACpB,UAAU,EAAE,OAAO,CAAA;IACnB,MAAM,EAAE,MAAM,CAAA;CACf;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,aAAa,EAAE,CAAA;IACzB,UAAU,EAAE,iBAAiB,EAAE,CAAA;CAChC;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAChC,QAAQ,EAAE,aAAa,EAAE,EACzB,aAAa,EAAE,GAAG,CAAC,MAAM,CAAC,GACzB,iBAAiB,CAkCnB"}
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Severity enforcement — every major/critical finding MUST have ≥1 valid patch.
3
+ *
4
+ * Findings without patches are downgraded to `minor` with an explanatory note.
5
+ * This runs as a post-processing step after patch validation.
6
+ */
7
+ /**
8
+ * Given a list of findings and the set of valid patches (post-validation),
9
+ * downgrade any major/critical finding that has no valid patch to `minor`.
10
+ */
11
+ export function enforcePatchPolicy(findings, validPatchIds) {
12
+ const downgraded = [];
13
+ const updated = findings.map(f => {
14
+ if (f.severity !== 'major' && f.severity !== 'critical')
15
+ return f;
16
+ const v2Finding = f;
17
+ const patches = v2Finding.patches ?? [];
18
+ const hasValidPatch = patches.some(p => validPatchIds.has(p.patchId));
19
+ if (hasValidPatch)
20
+ return f;
21
+ downgraded.push({
22
+ findingId: f.id,
23
+ fromSeverity: f.severity,
24
+ toSeverity: 'minor',
25
+ reason: patches.length === 0
26
+ ? 'no patches proposed'
27
+ : 'all proposed patches failed validation (before not in snapshot, missing locator, or delta out of range)',
28
+ });
29
+ return {
30
+ ...f,
31
+ severity: 'minor',
32
+ suggestion: [
33
+ f.suggestion,
34
+ '[auto-downgraded: patch required for major/critical severity]',
35
+ ]
36
+ .filter(Boolean)
37
+ .join(' '),
38
+ };
39
+ });
40
+ return { findings: updated, downgraded };
41
+ }
42
+ //# sourceMappingURL=severity-enforcement.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"severity-enforcement.js","sourceRoot":"","sources":["../../../../src/design/audit/patches/severity-enforcement.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAgBH;;;GAGG;AACH,MAAM,UAAU,kBAAkB,CAChC,QAAyB,EACzB,aAA0B;IAE1B,MAAM,UAAU,GAAwB,EAAE,CAAA;IAE1C,MAAM,OAAO,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE;QAC/B,IAAI,CAAC,CAAC,QAAQ,KAAK,OAAO,IAAI,CAAC,CAAC,QAAQ,KAAK,UAAU;YAAE,OAAO,CAAC,CAAA;QAEjE,MAAM,SAAS,GAAG,CAA0C,CAAA;QAC5D,MAAM,OAAO,GAAG,SAAS,CAAC,OAAO,IAAI,EAAE,CAAA;QACvC,MAAM,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAA;QAErE,IAAI,aAAa;YAAE,OAAO,CAAC,CAAA;QAE3B,UAAU,CAAC,IAAI,CAAC;YACd,SAAS,EAAE,CAAC,CAAC,EAAE;YACf,YAAY,EAAE,CAAC,CAAC,QAAQ;YACxB,UAAU,EAAE,OAAO;YACnB,MAAM,EAAE,OAAO,CAAC,MAAM,KAAK,CAAC;gBAC1B,CAAC,CAAC,qBAAqB;gBACvB,CAAC,CAAC,yGAAyG;SAC9G,CAAC,CAAA;QAEF,OAAO;YACL,GAAG,CAAC;YACJ,QAAQ,EAAE,OAAgB;YAC1B,UAAU,EAAE;gBACV,CAAC,CAAC,UAAU;gBACZ,+DAA+D;aAChE;iBACE,MAAM,CAAC,OAAO,CAAC;iBACf,IAAI,CAAC,GAAG,CAAC;SACb,CAAA;IACH,CAAC,CAAC,CAAA;IAEF,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,UAAU,EAAE,CAAA;AAC1C,CAAC"}
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Patch validator — given a parsed patch and the page snapshot text, verify
3
+ * that the patch is grounded and applyable.
4
+ *
5
+ * Rules:
6
+ * - `diff.before` must appear as a case-sensitive substring of the snapshot.
7
+ * Agents apply patches literally; a hallucinated `before` is unfixable.
8
+ * - `target` must carry at least one locator (cssSelector | filePath |
9
+ * componentName). Without one the agent has nowhere to apply.
10
+ * - `estimatedDelta.delta` must be in [-3, 3]. Larger claims are almost
11
+ * always over-confident on a 1–10 scale.
12
+ */
13
+ import type { Patch } from '../score-types.js';
14
+ export type ValidationReason = 'before-not-in-snapshot' | 'target-missing-locator' | 'estimated-delta-out-of-range' | 'before-empty';
15
+ export interface ValidationResult {
16
+ valid: boolean;
17
+ reasons: ValidationReason[];
18
+ }
19
+ /**
20
+ * Validate a single patch against a page snapshot. Reports all issues in one
21
+ * pass so callers can surface every problem to the agent at once.
22
+ *
23
+ * Snapshot-anchoring rule: `diff.before` must appear verbatim in the page
24
+ * snapshot ONLY when the patch targets the snapshot itself — i.e. `target.scope`
25
+ * is `html` or `structural`. CSS / TSX / Tailwind patches modify source files
26
+ * the audit can't see, so the snapshot check would always fail for them. The
27
+ * agent verifies those patches at apply-time against the actual source file.
28
+ */
29
+ export declare function validatePatch(patch: Patch, snapshot: string): ValidationResult;
30
+ /**
31
+ * Validate a list of patches and partition into valid / invalid.
32
+ */
33
+ export declare function validatePatches(patches: Patch[], snapshot: string): {
34
+ valid: Patch[];
35
+ invalid: Array<{
36
+ patch: Patch;
37
+ reasons: ValidationReason[];
38
+ }>;
39
+ };
40
+ //# sourceMappingURL=validate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../../../../src/design/audit/patches/validate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAA;AAE9C,MAAM,MAAM,gBAAgB,GACxB,wBAAwB,GACxB,wBAAwB,GACxB,8BAA8B,GAC9B,cAAc,CAAA;AAElB,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,OAAO,CAAA;IACd,OAAO,EAAE,gBAAgB,EAAE,CAAA;CAC5B;AAKD;;;;;;;;;GASG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,GAAG,gBAAgB,CAyB9E;AAED;;GAEG;AACH,wBAAgB,eAAe,CAC7B,OAAO,EAAE,KAAK,EAAE,EAChB,QAAQ,EAAE,MAAM,GACf;IAAE,KAAK,EAAE,KAAK,EAAE,CAAC;IAAC,OAAO,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE,KAAK,CAAC;QAAC,OAAO,EAAE,gBAAgB,EAAE,CAAA;KAAE,CAAC,CAAA;CAAE,CASnF"}