copperhead 0.8.1 → 0.10.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.
- package/NOTICE +1 -1
- package/README.md +13 -5
- package/dist/agent/filetools.js +24 -1
- package/dist/agent/filetools.js.map +1 -1
- package/dist/agent/ledger.js +24 -0
- package/dist/agent/ledger.js.map +1 -1
- package/dist/agent/loop.js +67 -62
- package/dist/agent/loop.js.map +1 -1
- package/dist/agent/prompts.js +4 -3
- package/dist/agent/prompts.js.map +1 -1
- package/dist/agent/providers/openai.js +28 -6
- package/dist/agent/providers/openai.js.map +1 -1
- package/dist/agent/providers/tool-protocol.js +21 -0
- package/dist/agent/providers/tool-protocol.js.map +1 -1
- package/dist/agent/recovery.js +95 -1
- package/dist/agent/recovery.js.map +1 -1
- package/dist/agent/response-cache.js +18 -2
- package/dist/agent/response-cache.js.map +1 -1
- package/dist/agent/tools.js +185 -1
- package/dist/agent/tools.js.map +1 -1
- package/dist/agent/transcript.js +2 -0
- package/dist/agent/transcript.js.map +1 -1
- package/dist/cli.js +77 -2
- package/dist/cli.js.map +1 -1
- package/dist/commands/check.js +33 -1
- package/dist/commands/check.js.map +1 -1
- package/dist/commands/create.js +282 -26
- package/dist/commands/create.js.map +1 -1
- package/dist/commands/doctor.js +211 -11
- package/dist/commands/doctor.js.map +1 -1
- package/dist/config.js +61 -4
- package/dist/config.js.map +1 -1
- package/dist/kicad/bootstrap.js +24 -3
- package/dist/kicad/bootstrap.js.map +1 -1
- package/dist/kicad/cli.js +7 -26
- package/dist/kicad/cli.js.map +1 -1
- package/dist/kicad/dossier.js +207 -0
- package/dist/kicad/dossier.js.map +1 -0
- package/dist/kicad/draft/draft.js +132 -0
- package/dist/kicad/draft/draft.js.map +1 -0
- package/dist/kicad/draft/engine.js +2389 -0
- package/dist/kicad/draft/engine.js.map +1 -0
- package/dist/kicad/draft/ir.js +368 -0
- package/dist/kicad/draft/ir.js.map +1 -0
- package/dist/kicad/draft/symsource.js +490 -0
- package/dist/kicad/draft/symsource.js.map +1 -0
- package/dist/kicad/emit.js +181 -0
- package/dist/kicad/emit.js.map +1 -0
- package/dist/kicad/fab.js +13 -0
- package/dist/kicad/fab.js.map +1 -1
- package/dist/kicad/legibility.js +561 -0
- package/dist/kicad/legibility.js.map +1 -0
- package/dist/kicad/score.js +261 -0
- package/dist/kicad/score.js.map +1 -0
- package/dist/kicad/sexp.js +262 -10
- package/dist/kicad/sexp.js.map +1 -1
- package/dist/kicad/symlib.js +346 -16
- package/dist/kicad/symlib.js.map +1 -1
- package/dist/memory/bom-table.js +108 -34
- package/dist/memory/bom-table.js.map +1 -1
- package/dist/memory/scaffold.js +6 -0
- package/dist/memory/scaffold.js.map +1 -1
- package/dist/openspec/cli.js +2 -1
- package/dist/openspec/cli.js.map +1 -1
- package/dist/util/preflight.js +17 -0
- package/dist/util/preflight.js.map +1 -1
- package/dist/util/redact.js +12 -2
- package/dist/util/redact.js.map +1 -1
- package/package.json +9 -7
- package/src/agent/filetools.ts +26 -1
- package/src/agent/ledger.ts +24 -0
- package/src/agent/loop.ts +88 -65
- package/src/agent/prompts.ts +4 -3
- package/src/agent/providers/openai.ts +38 -4
- package/src/agent/providers/tool-protocol.ts +22 -0
- package/src/agent/recovery.ts +94 -1
- package/src/agent/response-cache.ts +17 -1
- package/src/agent/tools.ts +189 -1
- package/src/agent/transcript.ts +6 -0
- package/src/cli.ts +73 -2
- package/src/commands/check.ts +51 -1
- package/src/commands/create.ts +278 -22
- package/src/commands/doctor.ts +219 -12
- package/src/config.ts +107 -2
- package/src/kicad/bootstrap.ts +24 -3
- package/src/kicad/cli.ts +6 -19
- package/src/kicad/dossier.ts +217 -0
- package/src/kicad/draft/draft.ts +171 -0
- package/src/kicad/draft/engine.ts +2466 -0
- package/src/kicad/draft/ir.ts +416 -0
- package/src/kicad/draft/symsource.ts +535 -0
- package/src/kicad/emit.ts +236 -0
- package/src/kicad/fab.ts +15 -0
- package/src/kicad/legibility.ts +646 -0
- package/src/kicad/score.ts +323 -0
- package/src/kicad/sexp.ts +339 -10
- package/src/kicad/symlib.ts +364 -18
- package/src/memory/bom-table.ts +119 -31
- package/src/memory/scaffold.ts +6 -0
- package/src/openspec/cli.ts +3 -2
- package/src/util/preflight.ts +18 -0
- package/src/util/redact.ts +12 -2
- package/dist/memory/synap.js +0 -152
- package/dist/memory/synap.js.map +0 -1
- package/src/memory/synap.ts +0 -217
|
@@ -0,0 +1,261 @@
|
|
|
1
|
+
import { readSheetGeometry } from './sexp.js';
|
|
2
|
+
import { checkLegibility } from './legibility.js';
|
|
3
|
+
const DEFAULT_WEIGHTS = {
|
|
4
|
+
'wire-crossings': 10,
|
|
5
|
+
'wire-bends': 5,
|
|
6
|
+
'wire-length': 5,
|
|
7
|
+
'label-to-wire-ratio': 5,
|
|
8
|
+
'group-cohesion': 10,
|
|
9
|
+
'flow-direction': 10,
|
|
10
|
+
utilization: 10,
|
|
11
|
+
'axis-alignment': 10,
|
|
12
|
+
'spacing-uniformity': 10,
|
|
13
|
+
'straight-wire-ratio': 5,
|
|
14
|
+
'label-alignment': 5,
|
|
15
|
+
'whitespace-balance': 10,
|
|
16
|
+
'pair-symmetry': 5,
|
|
17
|
+
};
|
|
18
|
+
/** Composite is capped this far below the Tier A floor when errors exist. */
|
|
19
|
+
const DEFAULT_FLOOR = 85;
|
|
20
|
+
const ERROR_CAP = 40;
|
|
21
|
+
/** Top-edge spread (mm) within which two group boxes count as the same row. */
|
|
22
|
+
const ROW_BAND = 12;
|
|
23
|
+
const PAPER = {
|
|
24
|
+
A5: { w: 210, h: 148 },
|
|
25
|
+
A4: { w: 297, h: 210 },
|
|
26
|
+
A3: { w: 420, h: 297 },
|
|
27
|
+
A2: { w: 594, h: 420 },
|
|
28
|
+
A1: { w: 841, h: 594 },
|
|
29
|
+
A0: { w: 1189, h: 841 },
|
|
30
|
+
};
|
|
31
|
+
const segLen = (s) => Math.hypot(s.x2 - s.x1, s.y2 - s.y1);
|
|
32
|
+
const isVert = (s) => s.x1 === s.x2;
|
|
33
|
+
function properCrossing(a, b) {
|
|
34
|
+
// orthogonal proper crossing (interiors intersect); shared endpoints are joins
|
|
35
|
+
const [v, h] = isVert(a) && !isVert(b) ? [a, b] : !isVert(a) && isVert(b) ? [b, a] : [null, null];
|
|
36
|
+
if (!v || !h)
|
|
37
|
+
return false;
|
|
38
|
+
const [hy, vx] = [h.y1, v.x1];
|
|
39
|
+
const [hx1, hx2] = [Math.min(h.x1, h.x2), Math.max(h.x1, h.x2)];
|
|
40
|
+
const [vy1, vy2] = [Math.min(v.y1, v.y2), Math.max(v.y1, v.y2)];
|
|
41
|
+
return vx > hx1 + 0.01 && vx < hx2 - 0.01 && hy > vy1 + 0.01 && hy < vy2 - 0.01;
|
|
42
|
+
}
|
|
43
|
+
export async function scoreSchematic(rootSch, opts = {}) {
|
|
44
|
+
const sheets = await readSheetGeometry(rootSch);
|
|
45
|
+
const legibility = await checkLegibility(rootSch, {
|
|
46
|
+
docsDir: opts.docsDir ?? null,
|
|
47
|
+
...(opts.config ? { config: opts.config } : {}),
|
|
48
|
+
});
|
|
49
|
+
return scoreFromGeometry(sheets, legibility, opts.config);
|
|
50
|
+
}
|
|
51
|
+
export function scoreFromGeometry(sheets, legibility, config) {
|
|
52
|
+
const weights = { ...DEFAULT_WEIGHTS };
|
|
53
|
+
for (const [k, v] of Object.entries(config?.score?.weights ?? {})) {
|
|
54
|
+
if (k in weights && typeof v === 'number' && Number.isFinite(v) && v >= 0)
|
|
55
|
+
weights[k] = v;
|
|
56
|
+
}
|
|
57
|
+
// Sanitized like the weights above: a floor of 0 (or a non-number) would
|
|
58
|
+
// push the error cap `min(ERROR_CAP, floor - 1)` negative or NaN.
|
|
59
|
+
const rawFloor = config?.score?.floor;
|
|
60
|
+
const floor = typeof rawFloor === 'number' && Number.isFinite(rawFloor) && rawFloor >= 1 ? rawFloor : DEFAULT_FLOOR;
|
|
61
|
+
// ---- collect geometry across sheets ----
|
|
62
|
+
const segs = sheets.flatMap((s) => s.wires);
|
|
63
|
+
const labels = sheets.flatMap((s) => s.labels);
|
|
64
|
+
const realSyms = sheets.flatMap((s) => s.symbols.filter((y) => !y.isPower).map((y) => ({ ...y, sheet: s.sheetName })));
|
|
65
|
+
// wire crossings
|
|
66
|
+
let crossings = 0;
|
|
67
|
+
for (let i = 0; i < segs.length; i++) {
|
|
68
|
+
for (let j = i + 1; j < segs.length; j++)
|
|
69
|
+
if (properCrossing(segs[i], segs[j]))
|
|
70
|
+
crossings++;
|
|
71
|
+
}
|
|
72
|
+
// bends: points where exactly two segments of different orientation meet
|
|
73
|
+
const ends = new Map();
|
|
74
|
+
for (const s of segs) {
|
|
75
|
+
for (const [x, y] of [[s.x1, s.y1], [s.x2, s.y2]]) {
|
|
76
|
+
const k = `${x},${y}`;
|
|
77
|
+
ends.set(k, [...(ends.get(k) ?? []), s]);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
let bends = 0;
|
|
81
|
+
for (const list of ends.values()) {
|
|
82
|
+
if (list.length === 2 && isVert(list[0]) !== isVert(list[1]))
|
|
83
|
+
bends++;
|
|
84
|
+
}
|
|
85
|
+
const totalLen = segs.reduce((s, w) => s + segLen(w), 0);
|
|
86
|
+
// group cohesion: same-name label pairs, mean anchor distance vs sheet diagonal
|
|
87
|
+
const byName = new Map();
|
|
88
|
+
for (const l of labels)
|
|
89
|
+
byName.set(l.name, [...(byName.get(l.name) ?? []), { x: l.x, y: l.y }]);
|
|
90
|
+
const paper = PAPER[sheets[0]?.paper.name ?? 'A4'] ?? PAPER.A4;
|
|
91
|
+
const diag = Math.hypot(paper.w, paper.h);
|
|
92
|
+
const pairDists = [];
|
|
93
|
+
for (const pts of byName.values()) {
|
|
94
|
+
for (let i = 0; i < pts.length; i++) {
|
|
95
|
+
for (let j = i + 1; j < pts.length; j++)
|
|
96
|
+
pairDists.push(Math.hypot(pts[i].x - pts[j].x, pts[i].y - pts[j].y));
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
const meanPair = pairDists.length ? pairDists.reduce((a, b) => a + b, 0) / pairDists.length : 0;
|
|
100
|
+
// flow-direction: cross-group label nets should connect adjacent groups in
|
|
101
|
+
// reading order; a hop across intervening groups reads as against-the-flow
|
|
102
|
+
// wiring
|
|
103
|
+
const rects = sheets.flatMap((s) => s.rectangles.map((r) => ({
|
|
104
|
+
minX: Math.min(r.x1, r.x2),
|
|
105
|
+
maxX: Math.max(r.x1, r.x2),
|
|
106
|
+
minY: Math.min(r.y1, r.y2),
|
|
107
|
+
maxY: Math.max(r.y1, r.y2),
|
|
108
|
+
})));
|
|
109
|
+
// Reading order is rows first, then left-to-right within a row. Ordering by
|
|
110
|
+
// minX alone was correct only while every group sat in one band; on a sheet
|
|
111
|
+
// whose groups wrap onto several rows it interleaves row 2 back into row 1
|
|
112
|
+
// and reports flow violations for a drawing that reads perfectly.
|
|
113
|
+
const byRow = [...rects].sort((a, b) => a.minY - b.minY || a.minX - b.minX);
|
|
114
|
+
const rows = [];
|
|
115
|
+
for (const r of byRow) {
|
|
116
|
+
const row = rows[rows.length - 1];
|
|
117
|
+
// Rows are separated by a group box height; members of one row share a top
|
|
118
|
+
// edge to within a symbol cell, so a generous band still cannot merge two.
|
|
119
|
+
if (row && r.minY - row[0].minY <= ROW_BAND)
|
|
120
|
+
row.push(r);
|
|
121
|
+
else
|
|
122
|
+
rows.push([r]);
|
|
123
|
+
}
|
|
124
|
+
const ordered = rows.flatMap((row) => [...row].sort((a, b) => a.minX - b.minX));
|
|
125
|
+
const groupIdx = (x, y) => ordered.findIndex((r) => x > r.minX && x < r.maxX && y > r.minY && y < r.maxY);
|
|
126
|
+
/** Which wrapped row a point falls in; -1 when it is in no group box. */
|
|
127
|
+
const rowIdx = (x, y) => rows.findIndex((row) => row.some((r) => x > r.minX && x < r.maxX && y > r.minY && y < r.maxY));
|
|
128
|
+
let crossNets = 0;
|
|
129
|
+
let flowViolations = 0;
|
|
130
|
+
for (const pts of byName.values()) {
|
|
131
|
+
const gs = [...new Set(pts.map((p) => groupIdx(p.x, p.y)).filter((g) => g >= 0))];
|
|
132
|
+
if (gs.length > 1) {
|
|
133
|
+
crossNets++;
|
|
134
|
+
if (Math.max(...gs) - Math.min(...gs) > 1)
|
|
135
|
+
flowViolations++;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
// utilization + whitespace balance over the first sheet's usable frame
|
|
139
|
+
const items = [
|
|
140
|
+
...realSyms.map((s) => ({ minX: s.at.x - 2, minY: s.at.y - 2, maxX: s.at.x + 2, maxY: s.at.y + 2 })),
|
|
141
|
+
...rects,
|
|
142
|
+
];
|
|
143
|
+
const content = items.length
|
|
144
|
+
? items.reduce((a, b) => ({
|
|
145
|
+
minX: Math.min(a.minX, b.minX),
|
|
146
|
+
minY: Math.min(a.minY, b.minY),
|
|
147
|
+
maxX: Math.max(a.maxX, b.maxX),
|
|
148
|
+
maxY: Math.max(a.maxY, b.maxY),
|
|
149
|
+
}))
|
|
150
|
+
: null;
|
|
151
|
+
const usable = { minX: 10, minY: 10, maxX: paper.w - 10, maxY: paper.h - 10 - 30 };
|
|
152
|
+
const usableArea = (usable.maxX - usable.minX) * (usable.maxY - usable.minY);
|
|
153
|
+
const utilization = content
|
|
154
|
+
? Math.min(1, ((content.maxX - content.minX) * (content.maxY - content.minY)) / usableArea)
|
|
155
|
+
: 0;
|
|
156
|
+
const centroidOff = content
|
|
157
|
+
? Math.hypot((content.minX + content.maxX) / 2 - (usable.minX + usable.maxX) / 2, (content.minY + content.maxY) / 2 - (usable.minY + usable.maxY) / 2) / (diag / 2)
|
|
158
|
+
: 1;
|
|
159
|
+
// axis alignment: symbols sharing an origin axis with at least one other
|
|
160
|
+
const sharesAxis = (i) => realSyms.some((o, j) => j !== i && (Math.abs(o.at.x - realSyms[i].at.x) < 0.01 || Math.abs(o.at.y - realSyms[i].at.y) < 0.01));
|
|
161
|
+
const axisAligned = realSyms.length > 1 ? realSyms.filter((_, i) => sharesAxis(i)).length / realSyms.length : 1;
|
|
162
|
+
// spacing uniformity: variance of consecutive gaps within shared-x columns
|
|
163
|
+
const cols = new Map();
|
|
164
|
+
for (const s of realSyms) {
|
|
165
|
+
// Keyed by row as well as x: a column is a vertical run the eye reads as
|
|
166
|
+
// one stack. Once groups wrap, two symbols in different rows can share an x
|
|
167
|
+
// while sitting a whole row apart, and treating that jump as a "gap" pushes
|
|
168
|
+
// the coefficient of variation — and the score — off a cliff.
|
|
169
|
+
const k = `${s.sheet}:${Math.round(s.at.x * 100)}:${rowIdx(s.at.x, s.at.y)}`;
|
|
170
|
+
cols.set(k, [...(cols.get(k) ?? []), s.at.y]);
|
|
171
|
+
}
|
|
172
|
+
const gapCVs = [];
|
|
173
|
+
for (const ys of cols.values()) {
|
|
174
|
+
if (ys.length < 3)
|
|
175
|
+
continue;
|
|
176
|
+
ys.sort((a, b) => a - b);
|
|
177
|
+
const gaps = ys.slice(1).map((y, i) => y - ys[i]);
|
|
178
|
+
const mean = gaps.reduce((a, b) => a + b, 0) / gaps.length;
|
|
179
|
+
const sd = Math.sqrt(gaps.reduce((a, g) => a + (g - mean) ** 2, 0) / gaps.length);
|
|
180
|
+
gapCVs.push(mean > 0 ? sd / mean : 0);
|
|
181
|
+
}
|
|
182
|
+
const spacingUniformity = gapCVs.length ? Math.max(0, 1 - gapCVs.reduce((a, b) => a + b, 0) / gapCVs.length) : 1;
|
|
183
|
+
// pair symmetry: same-libId+value symbols in one group aligned on a shared axis
|
|
184
|
+
const pairKeys = new Map();
|
|
185
|
+
for (const s of realSyms) {
|
|
186
|
+
const g = groupIdx(s.at.x, s.at.y);
|
|
187
|
+
const k = `${g}:${s.libId}:${s.value}`;
|
|
188
|
+
pairKeys.set(k, [...(pairKeys.get(k) ?? []), { x: s.at.x, y: s.at.y }]);
|
|
189
|
+
}
|
|
190
|
+
let pairs = 0;
|
|
191
|
+
let symmetric = 0;
|
|
192
|
+
for (const pts of pairKeys.values()) {
|
|
193
|
+
if (pts.length < 2)
|
|
194
|
+
continue;
|
|
195
|
+
for (let i = 0; i < pts.length; i++) {
|
|
196
|
+
for (let j = i + 1; j < pts.length; j++) {
|
|
197
|
+
pairs++;
|
|
198
|
+
if (Math.abs(pts[i].x - pts[j].x) < 0.01 || Math.abs(pts[i].y - pts[j].y) < 0.01)
|
|
199
|
+
symmetric++;
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
const pairSymmetry = pairs ? symmetric / pairs : 1;
|
|
204
|
+
const horizLabels = labels.length
|
|
205
|
+
? labels.filter((l) => Math.abs(l.rot % 180) !== 90).length / labels.length
|
|
206
|
+
: 1;
|
|
207
|
+
const straightRatio = segs.length ? Math.max(0, 1 - bends / segs.length) : 1;
|
|
208
|
+
const labelRatio = segs.length ? labels.length / segs.length : labels.length ? 1 : 0;
|
|
209
|
+
// ---- normalize to [0,1] goodness and compose ----
|
|
210
|
+
const raw = {
|
|
211
|
+
'wire-crossings': { raw: crossings, score: 1 / (1 + crossings) },
|
|
212
|
+
'wire-bends': { raw: bends, score: 1 / (1 + bends / 8) },
|
|
213
|
+
'wire-length': { raw: totalLen, score: 1 / (1 + totalLen / (4 * diag)) },
|
|
214
|
+
'label-to-wire-ratio': { raw: labelRatio, score: labelRatio <= 1.5 ? 1 : 1.5 / labelRatio },
|
|
215
|
+
'group-cohesion': { raw: meanPair, score: pairDists.length ? Math.max(0, 1 - meanPair / diag) : 1 },
|
|
216
|
+
'flow-direction': { raw: flowViolations, score: crossNets ? 1 - flowViolations / crossNets : 1 },
|
|
217
|
+
utilization: { raw: utilization, score: Math.min(1, utilization / 0.5) },
|
|
218
|
+
'axis-alignment': { raw: axisAligned, score: axisAligned },
|
|
219
|
+
'spacing-uniformity': { raw: spacingUniformity, score: spacingUniformity },
|
|
220
|
+
'straight-wire-ratio': { raw: straightRatio, score: straightRatio },
|
|
221
|
+
'label-alignment': { raw: horizLabels, score: horizLabels },
|
|
222
|
+
'whitespace-balance': { raw: centroidOff, score: Math.max(0, 1 - centroidOff) },
|
|
223
|
+
'pair-symmetry': { raw: pairSymmetry, score: pairSymmetry },
|
|
224
|
+
};
|
|
225
|
+
const totalWeight = Object.values(weights).reduce((a, b) => a + b, 0) || 1;
|
|
226
|
+
const metrics = Object.entries(raw).map(([name, m]) => ({
|
|
227
|
+
name,
|
|
228
|
+
raw: m.raw,
|
|
229
|
+
score: m.score,
|
|
230
|
+
weight: weights[name],
|
|
231
|
+
contribution: (100 * weights[name] * m.score) / totalWeight,
|
|
232
|
+
}));
|
|
233
|
+
let composite = metrics.reduce((a, m) => a + m.contribution, 0);
|
|
234
|
+
let cap = null;
|
|
235
|
+
if (legibility.counts.error > 0) {
|
|
236
|
+
const capValue = Math.min(ERROR_CAP, floor - 1);
|
|
237
|
+
if (composite > capValue) {
|
|
238
|
+
cap = {
|
|
239
|
+
appliedAt: capValue,
|
|
240
|
+
reason: `${legibility.counts.error} error-severity legibility finding(s) cap the composite below the known-good floor (${floor})`,
|
|
241
|
+
};
|
|
242
|
+
composite = capValue;
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
return {
|
|
246
|
+
composite: Math.round(composite * 100) / 100,
|
|
247
|
+
metrics,
|
|
248
|
+
cap,
|
|
249
|
+
legibility: legibility.counts,
|
|
250
|
+
};
|
|
251
|
+
}
|
|
252
|
+
export function formatScore(report) {
|
|
253
|
+
const lines = [`score: ${report.composite}/100`];
|
|
254
|
+
if (report.cap)
|
|
255
|
+
lines.push(` cap: ${report.cap.appliedAt} — ${report.cap.reason}`);
|
|
256
|
+
for (const m of report.metrics) {
|
|
257
|
+
lines.push(` ${m.name}: raw ${Math.round(m.raw * 10000) / 10000}, score ${Math.round(m.score * 1000) / 1000}, weight ${m.weight}, contributes ${Math.round(m.contribution * 100) / 100}`);
|
|
258
|
+
}
|
|
259
|
+
return lines.join('\n');
|
|
260
|
+
}
|
|
261
|
+
//# sourceMappingURL=score.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"score.js","sourceRoot":"","sources":["../../src/kicad/score.ts"],"names":[],"mappings":"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"}
|
package/dist/kicad/sexp.js
CHANGED
|
@@ -14,7 +14,11 @@ export function parseSexp(text) {
|
|
|
14
14
|
let s = '';
|
|
15
15
|
while (j < text.length && text[j] !== '"') {
|
|
16
16
|
if (text[j] === '\\' && j + 1 < text.length) {
|
|
17
|
-
|
|
17
|
+
// KiCad writes multi-line text as `\n` (and tabs as `\t`) inside the
|
|
18
|
+
// quoted atom; mapping the escape to the literal letter would give
|
|
19
|
+
// the legibility width model a one-line `line1nline2` string.
|
|
20
|
+
const e = text[j + 1];
|
|
21
|
+
s += e === 'n' ? '\n' : e === 't' ? '\t' : e;
|
|
18
22
|
j += 2;
|
|
19
23
|
}
|
|
20
24
|
else {
|
|
@@ -98,7 +102,10 @@ async function loadSheets(rootSch) {
|
|
|
98
102
|
await load(rootSch, '/');
|
|
99
103
|
return out;
|
|
100
104
|
}
|
|
101
|
-
/** Pin definitions per lib symbol name, in symbol coordinates.
|
|
105
|
+
/** Pin definitions per lib symbol name, in symbol coordinates. Each pin
|
|
106
|
+
* carries the unit of the `_<unit>_<style>` child it was defined in (0 for
|
|
107
|
+
* the common unit); de Morgan alternates (style ≥ 2) are skipped so a pin is
|
|
108
|
+
* recorded once. */
|
|
102
109
|
function libPinDefs(root) {
|
|
103
110
|
const map = new Map();
|
|
104
111
|
const libs = child(root, 'lib_symbols');
|
|
@@ -109,9 +116,17 @@ function libPinDefs(root) {
|
|
|
109
116
|
if (!name)
|
|
110
117
|
continue;
|
|
111
118
|
const pins = [];
|
|
112
|
-
const walk = (n) => {
|
|
119
|
+
const walk = (n, unit) => {
|
|
113
120
|
if (!isList(n))
|
|
114
121
|
return;
|
|
122
|
+
if (tag(n) === 'symbol') {
|
|
123
|
+
const m = /_(\d+)_(\d+)$/.exec(atomAt(n, 1) ?? '');
|
|
124
|
+
if (m) {
|
|
125
|
+
if (Number(m[2]) >= 2)
|
|
126
|
+
return; // de Morgan alternate body style
|
|
127
|
+
unit = Number(m[1]);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
115
130
|
if (tag(n) === 'pin') {
|
|
116
131
|
const at = child(n, 'at');
|
|
117
132
|
const num = atomAt(child(n, 'number'), 1);
|
|
@@ -122,17 +137,26 @@ function libPinDefs(root) {
|
|
|
122
137
|
name: pinName ?? '~',
|
|
123
138
|
x: parseFloat(atomAt(at, 1) ?? '0'),
|
|
124
139
|
y: parseFloat(atomAt(at, 2) ?? '0'),
|
|
140
|
+
unit,
|
|
125
141
|
});
|
|
126
142
|
}
|
|
127
143
|
}
|
|
128
144
|
for (const c of n)
|
|
129
|
-
walk(c);
|
|
145
|
+
walk(c, unit);
|
|
130
146
|
};
|
|
131
|
-
walk(sym);
|
|
147
|
+
walk(sym, 0);
|
|
132
148
|
map.set(name, pins);
|
|
133
149
|
}
|
|
134
150
|
return map;
|
|
135
151
|
}
|
|
152
|
+
/** The pins a PLACED instance actually shows: its own unit's plus the common
|
|
153
|
+
* unit's. A single-unit symbol keeps every pin (they are all unit ≤ 1). */
|
|
154
|
+
export function pinsOfUnit(defs, unit) {
|
|
155
|
+
const multi = defs.some((p) => p.unit >= 2);
|
|
156
|
+
if (!multi)
|
|
157
|
+
return defs;
|
|
158
|
+
return defs.filter((p) => p.unit === 0 || p.unit === unit);
|
|
159
|
+
}
|
|
136
160
|
/** Symbol-space → schematic-space transform (schematic Y grows downward). */
|
|
137
161
|
export function pinAbsolute(symAt, mirror, pin) {
|
|
138
162
|
let px = pin.x;
|
|
@@ -189,19 +213,37 @@ function symbolsOf(sheet) {
|
|
|
189
213
|
rot: parseFloat(atomAt(at, 3) ?? '0'),
|
|
190
214
|
},
|
|
191
215
|
uuid: atomAt(child(s, 'uuid'), 1) ?? '',
|
|
216
|
+
unit: parseInt(atomAt(child(s, 'unit'), 1) ?? '1', 10) || 1,
|
|
192
217
|
},
|
|
193
218
|
});
|
|
194
219
|
}
|
|
195
220
|
return out;
|
|
196
221
|
}
|
|
197
|
-
|
|
222
|
+
function collectPowerSymbols(sheets) {
|
|
223
|
+
const set = new Set();
|
|
224
|
+
for (const sheet of sheets) {
|
|
225
|
+
const libs = child(sheet.root, 'lib_symbols');
|
|
226
|
+
if (!libs)
|
|
227
|
+
continue;
|
|
228
|
+
for (const sym of children(libs, 'symbol')) {
|
|
229
|
+
const name = atomAt(sym, 1);
|
|
230
|
+
const p = child(sym, 'power');
|
|
231
|
+
if (name && p !== undefined && atomAt(p, 1) !== 'no') {
|
|
232
|
+
set.add(name);
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
return set;
|
|
237
|
+
}
|
|
238
|
+
const isPowerSymbol = (libId, powerSyms) => libId.startsWith('power:') || powerSyms.has(libId);
|
|
198
239
|
/** One row per real component (power symbols excluded), across all sheets. */
|
|
199
240
|
export async function listSymbols(rootSch) {
|
|
200
241
|
const sheets = await loadSheets(rootSch);
|
|
242
|
+
const powerSyms = collectPowerSymbols(sheets);
|
|
201
243
|
const out = [];
|
|
202
244
|
for (const sheet of sheets) {
|
|
203
245
|
for (const { sym } of symbolsOf(sheet)) {
|
|
204
|
-
if (!isPowerSymbol(sym.libId))
|
|
246
|
+
if (!isPowerSymbol(sym.libId, powerSyms))
|
|
205
247
|
out.push(sym);
|
|
206
248
|
}
|
|
207
249
|
}
|
|
@@ -210,6 +252,7 @@ export async function listSymbols(rootSch) {
|
|
|
210
252
|
/** All net names visible via labels and power symbols, across all sheets. */
|
|
211
253
|
export async function listNets(rootSch) {
|
|
212
254
|
const sheets = await loadSheets(rootSch);
|
|
255
|
+
const powerSyms = collectPowerSymbols(sheets);
|
|
213
256
|
const names = new Set();
|
|
214
257
|
for (const sheet of sheets) {
|
|
215
258
|
for (const kind of ['label', 'global_label', 'hierarchical_label']) {
|
|
@@ -220,12 +263,217 @@ export async function listNets(rootSch) {
|
|
|
220
263
|
}
|
|
221
264
|
}
|
|
222
265
|
for (const { sym } of symbolsOf(sheet)) {
|
|
223
|
-
if (isPowerSymbol(sym.libId))
|
|
266
|
+
if (isPowerSymbol(sym.libId, powerSyms))
|
|
224
267
|
names.add(sym.value);
|
|
225
268
|
}
|
|
226
269
|
}
|
|
227
270
|
return [...names].sort();
|
|
228
271
|
}
|
|
272
|
+
const num = (n, idx, fallback = 0) => {
|
|
273
|
+
const v = atomAt(n, idx);
|
|
274
|
+
return v === undefined ? fallback : parseFloat(v);
|
|
275
|
+
};
|
|
276
|
+
function effectsOf(node) {
|
|
277
|
+
const effects = child(node, 'effects');
|
|
278
|
+
const font = effects ? child(effects, 'font') : undefined;
|
|
279
|
+
const size = font ? child(font, 'size') : undefined;
|
|
280
|
+
// hidden: legacy bare `hide` atom, or v9 `(hide yes)`
|
|
281
|
+
const hideNode = effects ? child(effects, 'hide') : undefined;
|
|
282
|
+
const hidden = (effects?.some((c) => c === 'hide') ?? false) || (hideNode !== undefined && atomAt(hideNode, 1) !== 'no');
|
|
283
|
+
return { height: size ? num(size, 1, 1.27) : 1.27, hidden };
|
|
284
|
+
}
|
|
285
|
+
function libBodyBounds(root) {
|
|
286
|
+
const map = new Map();
|
|
287
|
+
const libs = child(root, 'lib_symbols');
|
|
288
|
+
if (!libs)
|
|
289
|
+
return map;
|
|
290
|
+
for (const sym of children(libs, 'symbol')) {
|
|
291
|
+
const name = atomAt(sym, 1);
|
|
292
|
+
if (!name)
|
|
293
|
+
continue;
|
|
294
|
+
/** Union across the whole symbol under `name`, per-unit union (common
|
|
295
|
+
* graphics included) under `name#<unit>` — a placed unit of a multi-unit
|
|
296
|
+
* symbol draws only its own unit's graphics, so measuring it with the
|
|
297
|
+
* package union would size every instance like the whole gate pack. */
|
|
298
|
+
const perUnit = new Map();
|
|
299
|
+
let b = null;
|
|
300
|
+
const grow = (prev, x, y) => {
|
|
301
|
+
if (!prev)
|
|
302
|
+
return { minX: x, minY: y, maxX: x, maxY: y };
|
|
303
|
+
prev.minX = Math.min(prev.minX, x);
|
|
304
|
+
prev.minY = Math.min(prev.minY, y);
|
|
305
|
+
prev.maxX = Math.max(prev.maxX, x);
|
|
306
|
+
prev.maxY = Math.max(prev.maxY, y);
|
|
307
|
+
return prev;
|
|
308
|
+
};
|
|
309
|
+
const walk = (n, unit) => {
|
|
310
|
+
if (!isList(n))
|
|
311
|
+
return;
|
|
312
|
+
const t = tag(n);
|
|
313
|
+
if (t === 'symbol') {
|
|
314
|
+
const m = /_(\d+)_(\d+)$/.exec(atomAt(n, 1) ?? '');
|
|
315
|
+
if (m) {
|
|
316
|
+
if (Number(m[2]) >= 2)
|
|
317
|
+
return; // de Morgan alternate body style
|
|
318
|
+
unit = Number(m[1]);
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
const extend = (x, y) => {
|
|
322
|
+
b = grow(b, x, y);
|
|
323
|
+
if (unit !== null)
|
|
324
|
+
perUnit.set(unit, grow(perUnit.get(unit) ?? null, x, y));
|
|
325
|
+
};
|
|
326
|
+
if (t === 'rectangle') {
|
|
327
|
+
const s = child(n, 'start');
|
|
328
|
+
const e = child(n, 'end');
|
|
329
|
+
extend(num(s, 1), num(s, 2));
|
|
330
|
+
extend(num(e, 1), num(e, 2));
|
|
331
|
+
}
|
|
332
|
+
else if (t === 'circle') {
|
|
333
|
+
const c = child(n, 'center');
|
|
334
|
+
const r = num(child(n, 'radius'), 1);
|
|
335
|
+
extend(num(c, 1) - r, num(c, 2) - r);
|
|
336
|
+
extend(num(c, 1) + r, num(c, 2) + r);
|
|
337
|
+
}
|
|
338
|
+
else if (t === 'arc') {
|
|
339
|
+
for (const part of ['start', 'mid', 'end']) {
|
|
340
|
+
const p = child(n, part);
|
|
341
|
+
if (p)
|
|
342
|
+
extend(num(p, 1), num(p, 2));
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
else if (t === 'polyline') {
|
|
346
|
+
for (const xy of children(child(n, 'pts') ?? [], 'xy'))
|
|
347
|
+
extend(num(xy, 1), num(xy, 2));
|
|
348
|
+
}
|
|
349
|
+
// pin/text graphics are deliberately excluded from the body box (design C2)
|
|
350
|
+
if (t !== 'pin' && t !== 'text')
|
|
351
|
+
for (const c of n)
|
|
352
|
+
walk(c, unit);
|
|
353
|
+
};
|
|
354
|
+
walk(sym, null);
|
|
355
|
+
map.set(name, b);
|
|
356
|
+
const common = perUnit.get(0) ?? null;
|
|
357
|
+
for (const [unit, ub] of perUnit) {
|
|
358
|
+
if (unit === 0)
|
|
359
|
+
continue;
|
|
360
|
+
const merged = ub && common
|
|
361
|
+
? {
|
|
362
|
+
minX: Math.min(ub.minX, common.minX),
|
|
363
|
+
minY: Math.min(ub.minY, common.minY),
|
|
364
|
+
maxX: Math.max(ub.maxX, common.maxX),
|
|
365
|
+
maxY: Math.max(ub.maxY, common.maxY),
|
|
366
|
+
}
|
|
367
|
+
: (ub ?? (common ? { ...common } : null));
|
|
368
|
+
map.set(`${name}#${unit}`, merged);
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
return map;
|
|
372
|
+
}
|
|
373
|
+
function textItemsOf(sym) {
|
|
374
|
+
const out = [];
|
|
375
|
+
for (const p of children(sym, 'property')) {
|
|
376
|
+
const key = atomAt(p, 1);
|
|
377
|
+
if (key !== 'Reference' && key !== 'Value')
|
|
378
|
+
continue;
|
|
379
|
+
const at = child(p, 'at');
|
|
380
|
+
const fx = effectsOf(p);
|
|
381
|
+
out.push({
|
|
382
|
+
text: atomAt(p, 2) ?? '',
|
|
383
|
+
x: num(at, 1),
|
|
384
|
+
y: num(at, 2),
|
|
385
|
+
rot: num(at, 3),
|
|
386
|
+
height: fx.height,
|
|
387
|
+
hidden: fx.hidden,
|
|
388
|
+
});
|
|
389
|
+
}
|
|
390
|
+
return out;
|
|
391
|
+
}
|
|
392
|
+
/**
|
|
393
|
+
* Everything the legibility checker needs to see per sheet, extracted read-only.
|
|
394
|
+
* Never serializes and never mutates the file.
|
|
395
|
+
*/
|
|
396
|
+
export async function readSheetGeometry(rootSch) {
|
|
397
|
+
const sheets = await loadSheets(rootSch);
|
|
398
|
+
const powerSyms = collectPowerSymbols(sheets);
|
|
399
|
+
return sheets.map((sheet) => {
|
|
400
|
+
const paperNode = child(sheet.root, 'paper');
|
|
401
|
+
const paperName = atomAt(paperNode, 1) ?? null;
|
|
402
|
+
const portrait = paperNode?.includes('portrait') ?? false;
|
|
403
|
+
const explicitW = num(paperNode, 2, NaN);
|
|
404
|
+
const explicitH = num(paperNode, 3, NaN);
|
|
405
|
+
const tb = child(sheet.root, 'title_block');
|
|
406
|
+
const tbField = (name) => (tb ? (atomAt(child(tb, name), 1) ?? '') : '');
|
|
407
|
+
const wires = [];
|
|
408
|
+
for (const w of children(sheet.root, 'wire')) {
|
|
409
|
+
const pts = children(child(w, 'pts') ?? [], 'xy');
|
|
410
|
+
for (let i = 1; i < pts.length; i++) {
|
|
411
|
+
wires.push({ x1: num(pts[i - 1], 1), y1: num(pts[i - 1], 2), x2: num(pts[i], 1), y2: num(pts[i], 2) });
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
const labels = [];
|
|
415
|
+
for (const kind of ['label', 'global_label', 'hierarchical_label']) {
|
|
416
|
+
for (const l of children(sheet.root, kind)) {
|
|
417
|
+
const at = child(l, 'at');
|
|
418
|
+
const effects = child(l, 'effects');
|
|
419
|
+
const justify = effects ? child(effects, 'justify') : undefined;
|
|
420
|
+
labels.push({
|
|
421
|
+
name: atomAt(l, 1) ?? '',
|
|
422
|
+
kind,
|
|
423
|
+
x: num(at, 1),
|
|
424
|
+
y: num(at, 2),
|
|
425
|
+
rot: num(at, 3),
|
|
426
|
+
height: effectsOf(l).height,
|
|
427
|
+
justify: justify?.some((c) => c === 'right') ? 'right' : justify?.some((c) => c === 'left') ? 'left' : null,
|
|
428
|
+
});
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
const texts = children(sheet.root, 'text').map((t) => {
|
|
432
|
+
const at = child(t, 'at');
|
|
433
|
+
const fx = effectsOf(t);
|
|
434
|
+
return { text: atomAt(t, 1) ?? '', x: num(at, 1), y: num(at, 2), rot: num(at, 3), height: fx.height, hidden: fx.hidden };
|
|
435
|
+
});
|
|
436
|
+
const rectangles = children(sheet.root, 'rectangle').map((r) => {
|
|
437
|
+
const s = child(r, 'start');
|
|
438
|
+
const e = child(r, 'end');
|
|
439
|
+
const stroke = child(r, 'stroke');
|
|
440
|
+
return {
|
|
441
|
+
x1: num(s, 1),
|
|
442
|
+
y1: num(s, 2),
|
|
443
|
+
x2: num(e, 1),
|
|
444
|
+
y2: num(e, 2),
|
|
445
|
+
strokeType: atomAt(child(stroke ?? [], 'type'), 1) ?? 'default',
|
|
446
|
+
};
|
|
447
|
+
});
|
|
448
|
+
return {
|
|
449
|
+
filePath: sheet.filePath,
|
|
450
|
+
sheetName: sheet.sheetName,
|
|
451
|
+
paper: {
|
|
452
|
+
name: paperName,
|
|
453
|
+
width: Number.isNaN(explicitW) ? null : explicitW,
|
|
454
|
+
height: Number.isNaN(explicitH) ? null : explicitH,
|
|
455
|
+
portrait,
|
|
456
|
+
},
|
|
457
|
+
titleBlock: tb ? { title: tbField('title'), date: tbField('date'), rev: tbField('rev') } : null,
|
|
458
|
+
symbols: symbolsOf(sheet).map(({ sym, mirror, node }) => ({
|
|
459
|
+
ref: sym.ref,
|
|
460
|
+
libId: sym.libId,
|
|
461
|
+
value: sym.value,
|
|
462
|
+
at: sym.at,
|
|
463
|
+
mirror,
|
|
464
|
+
isPower: isPowerSymbol(sym.libId, powerSyms),
|
|
465
|
+
unit: sym.unit,
|
|
466
|
+
props: textItemsOf(node),
|
|
467
|
+
})),
|
|
468
|
+
wires,
|
|
469
|
+
labels,
|
|
470
|
+
texts,
|
|
471
|
+
rectangles,
|
|
472
|
+
libBounds: libBodyBounds(sheet.root),
|
|
473
|
+
libPins: libPinDefs(sheet.root),
|
|
474
|
+
};
|
|
475
|
+
});
|
|
476
|
+
}
|
|
229
477
|
/**
|
|
230
478
|
* Geometric connectivity per sheet: pins, labels, and wire endpoints that share
|
|
231
479
|
* coordinates (or are joined by wires) form a group; a group's net name comes
|
|
@@ -234,6 +482,7 @@ export async function listNets(rootSch) {
|
|
|
234
482
|
*/
|
|
235
483
|
export async function pinNets(rootSch) {
|
|
236
484
|
const sheets = await loadSheets(rootSch);
|
|
485
|
+
const powerSyms = collectPowerSymbols(sheets);
|
|
237
486
|
const out = [];
|
|
238
487
|
for (const sheet of sheets) {
|
|
239
488
|
const pinDefs = libPinDefs(sheet.root);
|
|
@@ -261,12 +510,15 @@ export async function pinNets(rootSch) {
|
|
|
261
510
|
}
|
|
262
511
|
const symPins = [];
|
|
263
512
|
for (const { sym, mirror } of symbolsOf(sheet)) {
|
|
264
|
-
|
|
513
|
+
// a placed unit of a multi-unit symbol shows only its own unit's pins;
|
|
514
|
+
// resolving the whole package at each instance would invent phantom
|
|
515
|
+
// connection points at every other unit's coordinates
|
|
516
|
+
const defs = pinsOfUnit(pinDefs.get(sym.libId) ?? [], sym.unit);
|
|
265
517
|
for (const pin of defs) {
|
|
266
518
|
const abs = pinAbsolute(sym.at, mirror, pin);
|
|
267
519
|
const k = key(abs.x, abs.y);
|
|
268
520
|
uf.find(k);
|
|
269
|
-
if (isPowerSymbol(sym.libId)) {
|
|
521
|
+
if (isPowerSymbol(sym.libId, powerSyms)) {
|
|
270
522
|
netNameAt.set(k, sym.value);
|
|
271
523
|
}
|
|
272
524
|
else {
|