copperhead 0.9.0 → 0.11.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 (142) hide show
  1. package/NOTICE +1 -1
  2. package/README.md +47 -8
  3. package/dist/agent/context.js +2 -0
  4. package/dist/agent/context.js.map +1 -0
  5. package/dist/agent/dock-renderer.js +2 -2
  6. package/dist/agent/dock-renderer.js.map +1 -1
  7. package/dist/agent/envelope.js +105 -0
  8. package/dist/agent/envelope.js.map +1 -0
  9. package/dist/agent/filetools.js +24 -1
  10. package/dist/agent/filetools.js.map +1 -1
  11. package/dist/agent/ledger.js +24 -0
  12. package/dist/agent/ledger.js.map +1 -1
  13. package/dist/agent/loop.js +63 -72
  14. package/dist/agent/loop.js.map +1 -1
  15. package/dist/agent/prompts.js +4 -3
  16. package/dist/agent/prompts.js.map +1 -1
  17. package/dist/agent/providers/claude-code.js +17 -1
  18. package/dist/agent/providers/claude-code.js.map +1 -1
  19. package/dist/agent/providers/codex.js +84 -39
  20. package/dist/agent/providers/codex.js.map +1 -1
  21. package/dist/agent/providers/tool-protocol.js +21 -0
  22. package/dist/agent/providers/tool-protocol.js.map +1 -1
  23. package/dist/agent/recovery.js +186 -15
  24. package/dist/agent/recovery.js.map +1 -1
  25. package/dist/agent/registry.js +49 -0
  26. package/dist/agent/registry.js.map +1 -0
  27. package/dist/agent/render.js +2 -2
  28. package/dist/agent/render.js.map +1 -1
  29. package/dist/agent/theme.js +10 -5
  30. package/dist/agent/theme.js.map +1 -1
  31. package/dist/agent/tools.js +100 -586
  32. package/dist/agent/tools.js.map +1 -1
  33. package/dist/agent/transcript.js +2 -0
  34. package/dist/agent/transcript.js.map +1 -1
  35. package/dist/capabilities/define.js +35 -0
  36. package/dist/capabilities/define.js.map +1 -0
  37. package/dist/capabilities/handlers.js +744 -0
  38. package/dist/capabilities/handlers.js.map +1 -0
  39. package/dist/capabilities/helpers.js +39 -0
  40. package/dist/capabilities/helpers.js.map +1 -0
  41. package/dist/capabilities/index.js +50 -0
  42. package/dist/capabilities/index.js.map +1 -0
  43. package/dist/capabilities/skills/generate-report.js +23 -0
  44. package/dist/capabilities/skills/generate-report.js.map +1 -0
  45. package/dist/cli.js +158 -0
  46. package/dist/cli.js.map +1 -1
  47. package/dist/commands/check.js +33 -1
  48. package/dist/commands/check.js.map +1 -1
  49. package/dist/commands/create.js +181 -26
  50. package/dist/commands/create.js.map +1 -1
  51. package/dist/commands/doctor.js +83 -6
  52. package/dist/commands/doctor.js.map +1 -1
  53. package/dist/commands/skill.js +109 -0
  54. package/dist/commands/skill.js.map +1 -0
  55. package/dist/commands/sync.js +3 -1
  56. package/dist/commands/sync.js.map +1 -1
  57. package/dist/config.js +19 -6
  58. package/dist/config.js.map +1 -1
  59. package/dist/kicad/bootstrap.js +24 -3
  60. package/dist/kicad/bootstrap.js.map +1 -1
  61. package/dist/kicad/cli.js +106 -18
  62. package/dist/kicad/cli.js.map +1 -1
  63. package/dist/kicad/dossier.js +207 -0
  64. package/dist/kicad/dossier.js.map +1 -0
  65. package/dist/kicad/draft/draft.js +135 -0
  66. package/dist/kicad/draft/draft.js.map +1 -0
  67. package/dist/kicad/draft/engine.js +5310 -0
  68. package/dist/kicad/draft/engine.js.map +1 -0
  69. package/dist/kicad/draft/ir.js +368 -0
  70. package/dist/kicad/draft/ir.js.map +1 -0
  71. package/dist/kicad/draft/symsource.js +504 -0
  72. package/dist/kicad/draft/symsource.js.map +1 -0
  73. package/dist/kicad/emit.js +220 -0
  74. package/dist/kicad/emit.js.map +1 -0
  75. package/dist/kicad/fab.js +13 -0
  76. package/dist/kicad/fab.js.map +1 -1
  77. package/dist/kicad/legibility.js +608 -0
  78. package/dist/kicad/legibility.js.map +1 -0
  79. package/dist/kicad/score.js +431 -0
  80. package/dist/kicad/score.js.map +1 -0
  81. package/dist/kicad/sexp.js +265 -6
  82. package/dist/kicad/sexp.js.map +1 -1
  83. package/dist/kicad/symlib.js +346 -16
  84. package/dist/kicad/symlib.js.map +1 -1
  85. package/dist/mcp/server.js +485 -0
  86. package/dist/mcp/server.js.map +1 -0
  87. package/dist/memory/bom-table.js +75 -39
  88. package/dist/memory/bom-table.js.map +1 -1
  89. package/dist/memory/scaffold.js +14 -1
  90. package/dist/memory/scaffold.js.map +1 -1
  91. package/dist/util/redact.js +6 -0
  92. package/dist/util/redact.js.map +1 -1
  93. package/package.json +13 -8
  94. package/src/agent/context.ts +35 -0
  95. package/src/agent/dock-renderer.ts +3 -2
  96. package/src/agent/envelope.ts +124 -0
  97. package/src/agent/filetools.ts +26 -1
  98. package/src/agent/ledger.ts +24 -0
  99. package/src/agent/loop.ts +73 -78
  100. package/src/agent/prompts.ts +4 -3
  101. package/src/agent/providers/claude-code.ts +22 -1
  102. package/src/agent/providers/codex.ts +91 -42
  103. package/src/agent/providers/tool-protocol.ts +22 -0
  104. package/src/agent/recovery.ts +183 -13
  105. package/src/agent/registry.ts +58 -0
  106. package/src/agent/render.ts +4 -3
  107. package/src/agent/theme.ts +15 -5
  108. package/src/agent/tools.ts +124 -628
  109. package/src/agent/transcript.ts +6 -0
  110. package/src/agent/types.ts +10 -5
  111. package/src/capabilities/define.ts +88 -0
  112. package/src/capabilities/handlers.ts +769 -0
  113. package/src/capabilities/helpers.ts +37 -0
  114. package/src/capabilities/index.ts +53 -0
  115. package/src/capabilities/skills/generate-report.ts +25 -0
  116. package/src/cli.ts +154 -0
  117. package/src/commands/check.ts +51 -1
  118. package/src/commands/create.ts +183 -21
  119. package/src/commands/doctor.ts +85 -6
  120. package/src/commands/skill.ts +127 -0
  121. package/src/commands/sync.ts +5 -3
  122. package/src/config.ts +56 -8
  123. package/src/kicad/bootstrap.ts +24 -3
  124. package/src/kicad/cli.ts +129 -18
  125. package/src/kicad/dossier.ts +217 -0
  126. package/src/kicad/draft/draft.ts +173 -0
  127. package/src/kicad/draft/engine.ts +5274 -0
  128. package/src/kicad/draft/ir.ts +416 -0
  129. package/src/kicad/draft/symsource.ts +549 -0
  130. package/src/kicad/emit.ts +300 -0
  131. package/src/kicad/fab.ts +15 -0
  132. package/src/kicad/legibility.ts +695 -0
  133. package/src/kicad/score.ts +502 -0
  134. package/src/kicad/sexp.ts +346 -6
  135. package/src/kicad/symlib.ts +364 -18
  136. package/src/mcp/server.ts +560 -0
  137. package/src/memory/bom-table.ts +85 -38
  138. package/src/memory/scaffold.ts +14 -1
  139. package/src/util/redact.ts +6 -0
  140. package/dist/memory/synap.js +0 -152
  141. package/dist/memory/synap.js.map +0 -1
  142. package/src/memory/synap.ts +0 -217
@@ -0,0 +1,368 @@
1
+ import { readFile } from 'node:fs/promises';
2
+ import { existsSync } from 'node:fs';
3
+ import path from 'node:path';
4
+ import { SymbolResolutionError, powerNetToken } from './symsource.js';
5
+ import { parseBomTable, normalizeValue } from '../../memory/bom-table.js';
6
+ /**
7
+ * The netlist-intent IR (`schematic.intent.json`): the compact declarative
8
+ * input the model authors instead of geometry (design D5/D6). No coordinates,
9
+ * ever — the engine computes every position. Re-drafting the same IR fully
10
+ * regenerates the sheet.
11
+ */
12
+ export const INTENT_VERSION = 1;
13
+ export const INTENT_FILENAME = 'schematic.intent.json';
14
+ /** `## Heading` names from a markdown file, in order. */
15
+ async function headingsOf(file) {
16
+ if (!existsSync(file))
17
+ return null;
18
+ const text = await readFile(file, 'utf8');
19
+ const names = [...text.matchAll(/^#{2,6}\s+(.+?)\s*$/gm)].map((m) => m[1].trim()).filter(Boolean);
20
+ return names.length ? names : null;
21
+ }
22
+ /**
23
+ * BOM.md rows as { ref, value }, or null when the file/table is absent.
24
+ *
25
+ * Goes through the shared canonical reader (`parseBomTable`) rather than
26
+ * scanning every pipe-line in the file: the old inline scan read a supporting
27
+ * table's rows (a quiescent-current roll-up, a cost summary) as parts.
28
+ * `parseBomTable` reads only the Refdes-headed canonical table(s) and resolves
29
+ * Value by header *name*, the same discipline `checkDrift` and `export bom`
30
+ * already use.
31
+ *
32
+ * One row per refdes: a cell naming several parts (`R1, R2`, `C5-C8`) is read
33
+ * verbatim and simply matches nothing, because the BOM contract is one row per
34
+ * part — the row's single Rationale cell is where that part's purpose lives.
35
+ */
36
+ async function bomRowsOf(file) {
37
+ if (!existsSync(file))
38
+ return null;
39
+ const rows = parseBomTable(await readFile(file, 'utf8')).map((r) => ({ ref: r.refdes, value: r.value ?? '' }));
40
+ return rows.length ? rows : null;
41
+ }
42
+ /**
43
+ * Is this BOM Value cell a component *value*, or a description?
44
+ *
45
+ * The Value cell is drawn on the sheet as the symbol's Value field, so its
46
+ * length is a layout input, not just documentation. A cell like
47
+ * `1S Li-Po cell, 500 mAh, bare leads` renders as 34 characters beside a
48
+ * battery symbol and collides with its neighbours — an error-severity
49
+ * legibility finding that `create`'s stage-4 contract refuses to pass.
50
+ *
51
+ * That is unrecoverable without this check. The IR is the agent's only lever
52
+ * on the drawn sheet (`edit_file` is refused on a drafted schematic), and the
53
+ * BOM cross-check below pins the IR value to this cell — so shortening the
54
+ * value in the IR fails validation, and leaving it fails legibility. The run
55
+ * that found this burned all three stage-4 attempts and 2h49m discovering the
56
+ * loop, twice, because the legibility findings never named BOM.md as the thing
57
+ * to change (see the deadlock issue).
58
+ *
59
+ * Heuristic, deliberately loose — it fires only on cells that are clearly
60
+ * prose, so a legitimately long value (`STM32F103C8T6`,
61
+ * `JST_PH_S2B-PH-K_1x02_P2.00mm`) is left alone:
62
+ * - a comma-separated clause list where a later clause contains a space
63
+ * (`4.7uF, X5R, 10V, 0603` is a value; `P-MOSFET, divider gate` is prose), or
64
+ * - a cell too long to draw (> MAX_DRAWN_VALUE chars) that contains a space.
65
+ * A single unbroken token over the cap (`JST_PH_S2B-PH-K_1x02_P2.00mm`,
66
+ * 28 chars) is a real part identifier with no prose to move into Rationale,
67
+ * so length alone never refuses it — a wide Value field costs legibility
68
+ * score, but a hard refusal with no escape hatch would wedge the pipeline.
69
+ */
70
+ const MAX_DRAWN_VALUE = 24;
71
+ export function looksLikeDescription(value) {
72
+ const v = value.replace(/`/g, '').trim();
73
+ if (!v)
74
+ return false;
75
+ if (v.length > MAX_DRAWN_VALUE && v.includes(' '))
76
+ return true;
77
+ const clauses = v.split(',').map((c) => c.trim());
78
+ return clauses.length > 1 && clauses.slice(1).some((c) => c.includes(' ') && /[a-z]{3}/i.test(c));
79
+ }
80
+ export function parseIntent(json) {
81
+ let raw;
82
+ try {
83
+ raw = JSON.parse(json);
84
+ }
85
+ catch (e) {
86
+ return { intent: null, findings: [{ detail: `intent is not valid JSON: ${e.message}` }] };
87
+ }
88
+ if (raw === null || typeof raw !== 'object') {
89
+ return { intent: null, findings: [{ detail: 'intent must be a JSON object' }] };
90
+ }
91
+ const o = raw;
92
+ if (o.version !== INTENT_VERSION) {
93
+ return {
94
+ intent: null,
95
+ findings: [{ detail: `unsupported intent version ${JSON.stringify(o.version)}; this engine supports version ${INTENT_VERSION}` }],
96
+ };
97
+ }
98
+ if (!Array.isArray(o.parts) || !Array.isArray(o.nets)) {
99
+ return { intent: null, findings: [{ detail: 'intent needs "parts" and "nets" arrays' }] };
100
+ }
101
+ return { intent: raw, findings: [] };
102
+ }
103
+ /**
104
+ * Validate the IR before any placement (design D6): structural checks, lib
105
+ * resolution, pin existence, group membership against SUBSYSTEMS.md, no-connect
106
+ * consistency, and the BOM.md cross-check. A failed validation means nothing is
107
+ * written; findings come back numbered in the verify_symbols shape.
108
+ */
109
+ export async function validateIntent(intent, symsource, docsDir) {
110
+ const findings = [];
111
+ const add = (detail) => {
112
+ findings.push({ detail });
113
+ };
114
+ // parts: shape, duplicates, lib resolution. Field TYPES are checked here so a
115
+ // type-confused-but-valid JSON part ("group": 5) comes back as a numbered
116
+ // finding the model can act on, not a TypeError surfaced as an opaque tool
117
+ // error — the repair contract matters most exactly when the input is wrong.
118
+ const symbols = new Map();
119
+ const partByRef = new Map();
120
+ for (const p of intent.parts) {
121
+ if (typeof p?.ref !== 'string' || !p.ref || typeof p.libId !== 'string' || !p.libId || typeof p.value !== 'string') {
122
+ add(`part ${JSON.stringify(p?.ref ?? '(missing ref)')} needs string ref, libId, and value fields`);
123
+ continue;
124
+ }
125
+ if (p.group !== undefined && typeof p.group !== 'string') {
126
+ add(`${p.ref}: "group" must be a string (a SUBSYSTEMS.md heading), got ${JSON.stringify(p.group)}`);
127
+ continue;
128
+ }
129
+ if (p.footprint !== undefined && typeof p.footprint !== 'string') {
130
+ add(`${p.ref}: "footprint" must be a string, got ${JSON.stringify(p.footprint)}`);
131
+ continue;
132
+ }
133
+ if (partByRef.has(p.ref)) {
134
+ add(`duplicate refdes ${p.ref}`);
135
+ continue;
136
+ }
137
+ partByRef.set(p.ref, p);
138
+ try {
139
+ const sym = await symsource.resolve(p.libId);
140
+ // A multi-unit symbol (an opamp, a gate pack) is placed one unit at a
141
+ // time: units share symbol-space pin coordinates, so a single placed
142
+ // instance would overlay unrelated pins on one point and silently merge
143
+ // their nets (an LM358 drafted that way fused its two outputs). Common
144
+ // (unit-0) pins are fine — KiCad draws them on every placed unit and
145
+ // the engine wires each appearance to the pin's one net. What is
146
+ // refused is a pin number repeated across NUMBERED units (an ambiguous
147
+ // endpoint), and a pin living only in a de Morgan alternate (it would
148
+ // vanish from the drawn sheet).
149
+ if (sym.multiUnit) {
150
+ const common = new Set(sym.commonUnitPins ?? []);
151
+ const owner = new Map();
152
+ const shared = new Set();
153
+ for (const u of sym.units ?? []) {
154
+ for (const pin of u.pins) {
155
+ if (common.has(pin.number))
156
+ continue;
157
+ const prev = owner.get(pin.number);
158
+ if (prev !== undefined && prev !== u.unit)
159
+ shared.add(pin.number);
160
+ owner.set(pin.number, u.unit);
161
+ }
162
+ }
163
+ if (shared.size) {
164
+ add(`${p.ref}: "${p.libId}" repeats pin(s) ${[...shared].sort().join(', ')} in more than one unit, so a ` +
165
+ `net endpoint cannot be mapped to a single placed unit; the drafting engine cannot place this symbol`);
166
+ continue;
167
+ }
168
+ const unmapped = [...new Set(sym.pins.map((pin) => pin.number))].filter((n) => !owner.has(n) && !common.has(n));
169
+ if (unmapped.length) {
170
+ add(`${p.ref}: "${p.libId}" defines pin(s) ${unmapped.sort().join(', ')} outside its default-style units, ` +
171
+ `so the drafting engine cannot place them; use a variant with conventional unit structure`);
172
+ continue;
173
+ }
174
+ }
175
+ symbols.set(p.ref, sym);
176
+ }
177
+ catch (e) {
178
+ if (e instanceof SymbolResolutionError)
179
+ add(`${p.ref}: ${e.message}`);
180
+ else
181
+ throw e;
182
+ }
183
+ }
184
+ // groups: exactly one per non-power part, validated against SUBSYSTEMS.md when present
185
+ const docGroups = docsDir ? await headingsOf(path.join(docsDir, 'SUBSYSTEMS.md')) : null;
186
+ for (const p of partByRef.values()) {
187
+ const sym = symbols.get(p.ref);
188
+ if (sym?.isPower)
189
+ continue;
190
+ if (!p.group) {
191
+ add(`${p.ref} has no group assignment; available groups: ${docGroups?.join(', ') ?? '(SUBSYSTEMS.md absent)'}`);
192
+ }
193
+ else if (docGroups && !docGroups.some((g) => g.toLowerCase() === p.group.toLowerCase())) {
194
+ add(`${p.ref} names group "${p.group}", which is not a SUBSYSTEMS.md heading; available: ${docGroups.join(', ')}`);
195
+ }
196
+ }
197
+ // nets: endpoints exist, at least two of them
198
+ const pinKey = (ref, pin) => `${ref}.${pin}`;
199
+ const usedPins = new Set();
200
+ const netNames = new Set();
201
+ for (const net of intent.nets) {
202
+ if (typeof net?.name !== 'string' || !net.name || !Array.isArray(net.pins)) {
203
+ add(`net ${JSON.stringify(net?.name ?? '(unnamed)')} needs a string name and a pins array`);
204
+ continue;
205
+ }
206
+ // The name is drawn as label text and embedded verbatim in the generated
207
+ // power-symbol source; a quote, backslash, or control character would emit
208
+ // a structurally corrupt schematic, so it dies here as a finding instead.
209
+ if ([...net.name].some((c) => c === '"' || c === '\\' || c.charCodeAt(0) < 32 || c.charCodeAt(0) === 127)) {
210
+ add(`net name ${JSON.stringify(net.name)} contains characters that cannot be drawn (quotes, backslashes, or control characters); rename the net`);
211
+ continue;
212
+ }
213
+ if (net.kind !== undefined && net.kind !== 'power' && net.kind !== 'ground' && net.kind !== 'signal') {
214
+ add(`net ${net.name}: "kind" must be "power", "ground", or "signal", got ${JSON.stringify(net.kind)}`);
215
+ }
216
+ if (netNames.has(net.name))
217
+ add(`duplicate net name ${net.name}`);
218
+ netNames.add(net.name);
219
+ if (net.pins.length < 2)
220
+ add(`net ${net.name} has ${net.pins.length} endpoint(s); a net needs at least two`);
221
+ for (const ep of net.pins) {
222
+ if (typeof ep !== 'string') {
223
+ add(`net ${net.name}: endpoint ${JSON.stringify(ep)} must be a "REF.PIN" string`);
224
+ continue;
225
+ }
226
+ const m = /^([^.]+)\.(.+)$/.exec(ep);
227
+ if (!m) {
228
+ add(`net ${net.name}: endpoint "${ep}" is not of the form REF.PIN`);
229
+ continue;
230
+ }
231
+ const [, ref, pin] = m;
232
+ const sym = symbols.get(ref);
233
+ if (!partByRef.has(ref)) {
234
+ add(`net ${net.name}: endpoint "${ep}" references unknown part ${ref}`);
235
+ continue;
236
+ }
237
+ if (sym && !sym.pins.some((p) => p.number === pin)) {
238
+ add(`net ${net.name}: ${ref} has no pin ${pin}; its pins are [${sym.pins.map((p) => p.number).join(', ')}]`);
239
+ }
240
+ if (usedPins.has(pinKey(ref, pin)))
241
+ add(`pin ${ep} appears in more than one net`);
242
+ usedPins.add(pinKey(ref, pin));
243
+ }
244
+ }
245
+ // Two power-class nets whose names sanitize to one symbol token would share
246
+ // one generated `copperhead_power:` lib_id and one embedded pin name, so
247
+ // KiCad's netlist can quietly merge the rails (last write wins in the
248
+ // lib_symbols map). Refused here as a finding, before any placement.
249
+ const isPowerClass = (net) => {
250
+ if (net.kind === 'power' || net.kind === 'ground')
251
+ return true;
252
+ if (net.kind === 'signal')
253
+ return false;
254
+ return net.pins.some((ep) => {
255
+ const m = typeof ep === 'string' ? /^([^.]+)\.(.+)$/.exec(ep) : null;
256
+ if (!m)
257
+ return false;
258
+ const pin = symbols.get(m[1])?.pins.find((pn) => pn.number === m[2]);
259
+ return pin !== undefined && (pin.etype === 'power_in' || pin.etype === 'power_out');
260
+ });
261
+ };
262
+ const byToken = new Map();
263
+ for (const net of intent.nets) {
264
+ if (typeof net?.name !== 'string' || !Array.isArray(net.pins))
265
+ continue;
266
+ if (!isPowerClass(net))
267
+ continue;
268
+ const token = powerNetToken(net.name);
269
+ const names = byToken.get(token) ?? new Set();
270
+ names.add(net.name);
271
+ byToken.set(token, names);
272
+ }
273
+ for (const [token, names] of byToken) {
274
+ if (names.size > 1) {
275
+ add(`power nets ${[...names].sort().join(' and ')} both sanitize to the symbol token "${token}", ` +
276
+ `which would give them one shared power symbol and merge the rails; rename one so the tokens differ`);
277
+ }
278
+ }
279
+ // no-connects: an array of REF.PIN strings; each pin exists and is not in any net
280
+ const noConnect = intent.noConnect ?? [];
281
+ if (!Array.isArray(noConnect) || noConnect.some((e) => typeof e !== 'string')) {
282
+ add(`"noConnect" must be an array of "REF.PIN" strings, got ${JSON.stringify(intent.noConnect)}`);
283
+ }
284
+ else {
285
+ for (const ep of noConnect) {
286
+ const m = /^([^.]+)\.(.+)$/.exec(ep);
287
+ if (!m) {
288
+ add(`noConnect entry "${ep}" is not of the form REF.PIN`);
289
+ continue;
290
+ }
291
+ const [, ref, pin] = m;
292
+ const sym = symbols.get(ref);
293
+ if (!partByRef.has(ref))
294
+ add(`noConnect "${ep}" references unknown part ${ref}`);
295
+ else if (sym && !sym.pins.some((p) => p.number === pin))
296
+ add(`noConnect "${ep}": ${ref} has no pin ${pin}`);
297
+ if (usedPins.has(`${ref}.${pin}`))
298
+ add(`pin ${ep} is declared no-connect but appears in a net`);
299
+ }
300
+ }
301
+ // hints: every field the engine or emitter dereferences is type-checked here,
302
+ // so "hints": {"groupOrder": "Power"} steers back as a finding instead of a
303
+ // TypeError inside the placement pass
304
+ const hints = intent.hints;
305
+ if (hints !== undefined) {
306
+ if (hints === null || typeof hints !== 'object' || Array.isArray(hints)) {
307
+ add(`"hints" must be an object, got ${JSON.stringify(hints)}`);
308
+ }
309
+ else {
310
+ if (hints.groupOrder !== undefined && (!Array.isArray(hints.groupOrder) || hints.groupOrder.some((g) => typeof g !== 'string'))) {
311
+ add(`"hints.groupOrder" must be an array of group-name strings, got ${JSON.stringify(hints.groupOrder)}`);
312
+ }
313
+ if (hints.paper !== undefined && typeof hints.paper !== 'string') {
314
+ add(`"hints.paper" must be a string (a standard sheet name like "A3"), got ${JSON.stringify(hints.paper)}`);
315
+ }
316
+ if (hints.date !== undefined && typeof hints.date !== 'string') {
317
+ add(`"hints.date" must be a string, got ${JSON.stringify(hints.date)}`);
318
+ }
319
+ }
320
+ }
321
+ // BOM cross-check: a transcription slip dies here, not at the drift gate (D6)
322
+ const bomRows = docsDir ? await bomRowsOf(path.join(docsDir, 'BOM.md')) : null;
323
+ if (bomRows) {
324
+ const bomByRef = new Map(bomRows.map((r) => [r.ref, r.value]));
325
+ for (const p of partByRef.values()) {
326
+ if (symbols.get(p.ref)?.isPower)
327
+ continue;
328
+ const bomValue = bomByRef.get(p.ref);
329
+ if (bomValue === undefined) {
330
+ add(`${p.ref} is not a BOM.md row; add it to the BOM or drop it from the intent`);
331
+ continue;
332
+ }
333
+ // Drawability first, and independently of whether the two agree. Whether
334
+ // the cell can be drawn is a property of BOM.md alone, and the agent's
335
+ // first instinct on an unreadable sheet is to shorten the value in the
336
+ // intent — which makes the two differ. Reporting this only on a match
337
+ // answers that instinct with "differs from BOM.md's …" and never names the
338
+ // real problem, which is the loop this check exists to break: the fix is in
339
+ // the doc, not the intent.
340
+ if (looksLikeDescription(bomValue)) {
341
+ add(`${p.ref}: BOM.md's Value is a description, not a component value ("${bomValue}"). ` +
342
+ `It is drawn on the sheet as ${p.ref}'s Value field, where it collides with neighbouring symbols ` +
343
+ `and fails the legibility gate — and you cannot shorten it in the intent alone, because this ` +
344
+ `cross-check requires the two to agree. Fix docs/BOM.md: put the component value in the Value column ` +
345
+ `(e.g. "500mAh Li-Po", "4.7uF", "1M") and move the prose to the Rationale column, then update the intent to match.`);
346
+ continue; // the value mismatch below would be noise next to this
347
+ }
348
+ // Compared through the shared value key, not raw bytes: `1 MΩ` vs `1 Mohm`
349
+ // and `4.7uF` vs `4.7 µF` are encoding differences with no electrical
350
+ // meaning. `checkDrift` has always folded them (normalizeValue); this gate
351
+ // running stricter than the gate downstream of it meant an IR that would
352
+ // pass drift could still be refused here, with no way to satisfy both.
353
+ if (normalizeValue(bomValue) !== normalizeValue(p.value)) {
354
+ add(`${p.ref} value "${p.value}" differs from BOM.md's "${bomValue}"`);
355
+ }
356
+ }
357
+ }
358
+ if (findings.length)
359
+ return { ok: false, findings, validated: null };
360
+ return { ok: true, findings: [], validated: { intent, symbols, docGroups } };
361
+ }
362
+ export function formatIrFindings(findings) {
363
+ return [
364
+ `intent validation: ${findings.length} finding(s) to reconcile:`,
365
+ ...findings.map((f, i) => ` ${i + 1}. ${f.detail}`),
366
+ ].join('\n');
367
+ }
368
+ //# sourceMappingURL=ir.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ir.js","sourceRoot":"","sources":["../../../src/kicad/draft/ir.ts"],"names":[],"mappings":"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"}