copperhead 0.6.0 → 0.7.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 (58) hide show
  1. package/dist/agent/loop.js +118 -16
  2. package/dist/agent/loop.js.map +1 -1
  3. package/dist/agent/prompts.js +2 -1
  4. package/dist/agent/prompts.js.map +1 -1
  5. package/dist/agent/providers/claude-code.js +207 -27
  6. package/dist/agent/providers/claude-code.js.map +1 -1
  7. package/dist/agent/recovery.js +148 -0
  8. package/dist/agent/recovery.js.map +1 -0
  9. package/dist/agent/render.js +17 -2
  10. package/dist/agent/render.js.map +1 -1
  11. package/dist/agent/response-cache.js +81 -0
  12. package/dist/agent/response-cache.js.map +1 -0
  13. package/dist/agent/tools.js +61 -4
  14. package/dist/agent/tools.js.map +1 -1
  15. package/dist/agent/transcript.js.map +1 -1
  16. package/dist/commands/create.js +470 -35
  17. package/dist/commands/create.js.map +1 -1
  18. package/dist/config.js +19 -0
  19. package/dist/config.js.map +1 -1
  20. package/dist/kicad/bootstrap.js +166 -0
  21. package/dist/kicad/bootstrap.js.map +1 -0
  22. package/dist/kicad/spice.js +306 -0
  23. package/dist/kicad/spice.js.map +1 -0
  24. package/dist/kicad/symlib.js +228 -0
  25. package/dist/kicad/symlib.js.map +1 -0
  26. package/dist/memory/bom-table.js +193 -22
  27. package/dist/memory/bom-table.js.map +1 -1
  28. package/dist/memory/drift.js +33 -11
  29. package/dist/memory/drift.js.map +1 -1
  30. package/dist/util/git.js +37 -1
  31. package/dist/util/git.js.map +1 -1
  32. package/dist/util/preflight.js +37 -0
  33. package/dist/util/preflight.js.map +1 -1
  34. package/dist/util/retry.js +23 -0
  35. package/dist/util/retry.js.map +1 -1
  36. package/dist/util/tmp.js +119 -0
  37. package/dist/util/tmp.js.map +1 -0
  38. package/package.json +1 -1
  39. package/src/agent/loop.ts +136 -16
  40. package/src/agent/prompts.ts +2 -1
  41. package/src/agent/providers/claude-code.ts +207 -24
  42. package/src/agent/recovery.ts +162 -0
  43. package/src/agent/render.ts +28 -1
  44. package/src/agent/response-cache.ts +80 -0
  45. package/src/agent/tools.ts +62 -4
  46. package/src/agent/transcript.ts +1 -0
  47. package/src/agent/types.ts +17 -0
  48. package/src/commands/create.ts +528 -38
  49. package/src/config.ts +34 -0
  50. package/src/kicad/bootstrap.ts +181 -0
  51. package/src/kicad/spice.ts +399 -0
  52. package/src/kicad/symlib.ts +248 -0
  53. package/src/memory/bom-table.ts +191 -20
  54. package/src/memory/drift.ts +42 -11
  55. package/src/util/git.ts +37 -1
  56. package/src/util/preflight.ts +44 -0
  57. package/src/util/retry.ts +29 -0
  58. package/src/util/tmp.ts +113 -0
package/dist/config.js CHANGED
@@ -8,6 +8,19 @@ export const DEFAULTS = {
8
8
  maxTurns: 40,
9
9
  maxRepairCycles: 5,
10
10
  budgets: {},
11
+ // 10 min. A single large capture turn (a full lib_symbols + instances edit,
12
+ // ~40k output tokens) on the claude-code provider legitimately runs several
13
+ // minutes; the old 5-min deadline killed those mid-flight and, because the
14
+ // watchdog budget is spent per stage, could fail a stage that was only slow,
15
+ // not hung. 10 min clears the largest observed turns while still catching a
16
+ // genuinely stuck subprocess.
17
+ turnTimeoutMs: 600000,
18
+ // 30s: within one interval an operator knows a turn is alive, and a full
19
+ // 10-min turn emits ~20 lines — enough to distinguish slow from hung without
20
+ // flooding the log. Quick turns (< 30s) emit nothing.
21
+ heartbeatMs: 30000,
22
+ maxStageRetries: 2,
23
+ llmCache: true,
11
24
  };
12
25
  export function configPath(repoRoot) {
13
26
  return path.join(repoRoot, CONFIG_DIR, 'config.json');
@@ -30,6 +43,12 @@ export async function loadConfig(repoRoot) {
30
43
  ...(Object.keys(stageMaxTurns).length ? { stageMaxTurns } : {}),
31
44
  maxRepairCycles: raw.maxRepairCycles ?? DEFAULTS.maxRepairCycles,
32
45
  budgets: raw.budgets ?? {},
46
+ turnTimeoutMs: typeof raw.turnTimeoutMs === 'number' ? raw.turnTimeoutMs : DEFAULTS.turnTimeoutMs,
47
+ heartbeatMs: typeof raw.heartbeatMs === 'number' ? raw.heartbeatMs : DEFAULTS.heartbeatMs,
48
+ maxStageRetries: Number.isInteger(raw.maxStageRetries) && raw.maxStageRetries >= 0
49
+ ? raw.maxStageRetries
50
+ : DEFAULTS.maxStageRetries,
51
+ llmCache: raw.llmCache !== false,
33
52
  ...(raw.generatedHashes ? { generatedHashes: raw.generatedHashes } : {}),
34
53
  ...(raw.origin === 'create' || raw.origin === 'init' ? { origin: raw.origin } : {}),
35
54
  };
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,166 @@
1
+ import { existsSync } from 'node:fs';
2
+ import { writeFile } from 'node:fs/promises';
3
+ import { createHash } from 'node:crypto';
4
+ import path from 'node:path';
5
+ import { configPath, loadConfig } from '../config.js';
6
+ /**
7
+ * The create pipeline starts from a brief with no KiCad files, but the agent
8
+ * cannot create them: `write_file` refuses KiCad files and `edit_file` only
9
+ * edits existing ones. Without a project on disk the schematic stage can never
10
+ * satisfy its contract (config.schematic stays null), so the pipeline stalls
11
+ * indefinitely. This module scaffolds a minimal, kicad-cli-loadable empty
12
+ * project (schematic ERC-clean, board DRC-clean with a default outline) and
13
+ * wires it into .copperhead/config.json, giving the agent a file to populate.
14
+ */
15
+ /** Slug for the project filename, taken from the brief's first H1 (a leading
16
+ * "Brief:" label is dropped). Falls back to "board". */
17
+ export function projectSlug(brief) {
18
+ const m = brief.match(/^#\s+(.+?)\s*$/m);
19
+ const title = (m?.[1] ?? 'board').replace(/^brief\s*:\s*/i, '');
20
+ const slug = title
21
+ .toLowerCase()
22
+ .replace(/[^a-z0-9]+/g, '-')
23
+ .replace(/^-+|-+$/g, '');
24
+ return slug || 'board';
25
+ }
26
+ /** A stable, valid-shaped v4 UUID derived from a seed, so a given project
27
+ * bootstraps to the same UUIDs on every run (no Date/random — runs stay
28
+ * reproducible). */
29
+ function uuidFrom(seed) {
30
+ const h = createHash('sha256').update(seed).digest('hex');
31
+ return `${h.slice(0, 8)}-${h.slice(8, 12)}-4${h.slice(13, 16)}-8${h.slice(17, 20)}-${h.slice(20, 32)}`;
32
+ }
33
+ function emptySchematic(rootUuid) {
34
+ return `(kicad_sch
35
+ (version 20231120)
36
+ (generator "eeschema")
37
+ (generator_version "8.0")
38
+ (uuid "${rootUuid}")
39
+ (paper "A4")
40
+ (lib_symbols)
41
+ (sheet_instances
42
+ (path "/" (page "1"))
43
+ )
44
+ )
45
+ `;
46
+ }
47
+ function emptyBoard(outlineUuid) {
48
+ // A default 30x20mm outline on Edge.Cuts so the blank board is DRC-clean out
49
+ // of the gate; the layout stage resizes/replaces it with the real outline.
50
+ return `(kicad_pcb
51
+ (version 20240108)
52
+ (generator "pcbnew")
53
+ (generator_version "8.0")
54
+ (general
55
+ (thickness 1.6)
56
+ (legacy_teardrops no)
57
+ )
58
+ (paper "A4")
59
+ (layers
60
+ (0 "F.Cu" signal)
61
+ (31 "B.Cu" signal)
62
+ (32 "B.Adhes" user "B.Adhesive")
63
+ (33 "F.Adhes" user "F.Adhesive")
64
+ (34 "B.Paste" user)
65
+ (35 "F.Paste" user)
66
+ (36 "B.SilkS" user "B.Silkscreen")
67
+ (37 "F.SilkS" user "F.Silkscreen")
68
+ (38 "B.Mask" user)
69
+ (39 "F.Mask" user)
70
+ (40 "Dwgs.User" user "User.Drawings")
71
+ (41 "Cmts.User" user "User.Comments")
72
+ (42 "Eco1.User" user "User.Eco1")
73
+ (43 "Eco2.User" user "User.Eco2")
74
+ (44 "Edge.Cuts" user)
75
+ (45 "Margin" user)
76
+ (46 "B.CrtYd" user "B.Courtyard")
77
+ (47 "F.CrtYd" user "F.Courtyard")
78
+ (48 "B.Fab" user)
79
+ (49 "F.Fab" user)
80
+ )
81
+ (setup
82
+ (pad_to_mask_clearance 0)
83
+ (allow_soldermask_bridges_in_footprints no)
84
+ )
85
+ (net 0 "")
86
+ (gr_rect (start 100 100) (end 130 120)
87
+ (stroke (width 0.1) (type default))
88
+ (layer "Edge.Cuts")
89
+ (uuid "${outlineUuid}")
90
+ )
91
+ )
92
+ `;
93
+ }
94
+ function projectFile(slug, rootUuid) {
95
+ return (JSON.stringify({
96
+ board: { design_settings: { defaults: {}, rules: {} } },
97
+ erc: {
98
+ erc_exclusions: [],
99
+ meta: { version: 0 },
100
+ rule_severities: { footprint_link_issues: 'ignore', lib_symbol_issues: 'ignore' },
101
+ },
102
+ meta: { filename: `${slug}.kicad_pro`, version: 1 },
103
+ net_settings: {
104
+ classes: [
105
+ {
106
+ bus_width: 12,
107
+ clearance: 0.2,
108
+ diff_pair_gap: 0.25,
109
+ diff_pair_via_gap: 0.25,
110
+ diff_pair_width: 0.2,
111
+ line_style: 0,
112
+ microvia_diameter: 0.3,
113
+ microvia_drill: 0.1,
114
+ name: 'Default',
115
+ pcb_color: 'rgba(0, 0, 0, 0.000)',
116
+ schematic_color: 'rgba(0, 0, 0, 0.000)',
117
+ track_width: 0.25,
118
+ via_diameter: 0.6,
119
+ via_drill: 0.3,
120
+ wire_width: 6,
121
+ },
122
+ ],
123
+ meta: { version: 3 },
124
+ },
125
+ schematic: {
126
+ annotate_start_num: 0,
127
+ drawing: { default_line_thickness: 6.0, default_text_size: 50.0 },
128
+ legacy_lib_dir: '',
129
+ legacy_lib_list: [],
130
+ meta: { version: 1 },
131
+ },
132
+ sheets: [[rootUuid, 'Root']],
133
+ text_variables: {},
134
+ }, null, 2) + '\n');
135
+ }
136
+ async function persist(repoRoot, config) {
137
+ await writeFile(configPath(repoRoot), JSON.stringify(config, null, 2) + '\n', 'utf8');
138
+ }
139
+ /**
140
+ * Ensure a KiCad project exists and is wired into config. No-op (returns null)
141
+ * when config already points at a schematic on disk. If project files exist but
142
+ * config doesn't reference them, just wires config. Otherwise scaffolds an empty
143
+ * project. Returns the schematic's repo-relative path when it created or wired
144
+ * one, else null.
145
+ */
146
+ export async function bootstrapKicadProject(repoRoot, brief) {
147
+ const config = await loadConfig(repoRoot);
148
+ if (config.schematic && existsSync(path.join(repoRoot, config.schematic)))
149
+ return null;
150
+ const slug = projectSlug(brief);
151
+ const schRel = `${slug}.kicad_sch`;
152
+ const pcbRel = `${slug}.kicad_pcb`;
153
+ const proRel = `${slug}.kicad_pro`;
154
+ const schAbs = path.join(repoRoot, schRel);
155
+ if (!existsSync(schAbs)) {
156
+ const rootUuid = uuidFrom(slug);
157
+ await writeFile(schAbs, emptySchematic(rootUuid), 'utf8');
158
+ await writeFile(path.join(repoRoot, pcbRel), emptyBoard(uuidFrom(`${slug}:edge`)), 'utf8');
159
+ await writeFile(path.join(repoRoot, proRel), projectFile(slug, rootUuid), 'utf8');
160
+ }
161
+ config.schematic = schRel;
162
+ config.board = existsSync(path.join(repoRoot, pcbRel)) ? pcbRel : null;
163
+ await persist(repoRoot, config);
164
+ return schRel;
165
+ }
166
+ //# sourceMappingURL=bootstrap.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bootstrap.js","sourceRoot":"","sources":["../../src/kicad/bootstrap.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,306 @@
1
+ /**
2
+ * Parser and assertion compiler for the opt-in SPICE verification gate.
3
+ *
4
+ * This module is deliberately pure: it reads strings and produces data or
5
+ * ngspice deck fragments. Process execution belongs to the wrapper in task 1.1.
6
+ */
7
+ export class SimulationParseError extends Error {
8
+ line;
9
+ constructor(line, message) {
10
+ super(`line ${line}: ${message}`);
11
+ this.name = 'SimulationParseError';
12
+ this.line = line;
13
+ }
14
+ }
15
+ const ANALYSES = new Set(['op', 'dc', 'ac', 'tran']);
16
+ const SAFE_TARGET = /^[A-Za-z0-9_./:+-]+$/;
17
+ const SAFE_MEASURE_NAME = /^[A-Za-z_][A-Za-z0-9_]*$/;
18
+ const SI_MULTIPLIERS = {
19
+ '': 1,
20
+ t: 1e12,
21
+ g: 1e9,
22
+ meg: 1e6,
23
+ k: 1e3,
24
+ m: 1e-3,
25
+ u: 1e-6,
26
+ n: 1e-9,
27
+ p: 1e-12,
28
+ f: 1e-15,
29
+ };
30
+ /** Parse a SPICE-style number while preserving the original safe literal. */
31
+ export function parseSpiceNumber(raw, line = 1) {
32
+ const token = raw.trim();
33
+ const match = /^([+-]?(?:\d+(?:\.\d*)?|\.\d+)(?:e[+-]?\d+)?)(meg|[tgkmunpf])?([a-z]*)$/i.exec(token);
34
+ if (!match) {
35
+ throw new SimulationParseError(line, `invalid SPICE number "${raw}"`);
36
+ }
37
+ const base = Number(match[1]);
38
+ const suffix = (match[2] ?? '').toLowerCase();
39
+ // The regex limits suffixes to keys in SI_MULTIPLIERS.
40
+ const multiplier = SI_MULTIPLIERS[suffix];
41
+ const value = base * multiplier;
42
+ if (!Number.isFinite(value)) {
43
+ throw new SimulationParseError(line, `SPICE number is out of range "${raw}"`);
44
+ }
45
+ return {
46
+ raw: token,
47
+ value,
48
+ unit: match[3] ?? '',
49
+ };
50
+ }
51
+ /** Parse one assertion from the closed grammar in the SPICE delta spec. */
52
+ export function parseSpiceAssertion(raw, line = 1) {
53
+ const text = raw.trim();
54
+ const measurableMatch = /^(V|I|corner)\(([^()\s]+)\)\s+(.+)$/i.exec(text);
55
+ if (!measurableMatch) {
56
+ throw new SimulationParseError(line, `invalid SPICE assertion "${raw}"`);
57
+ }
58
+ const target = measurableMatch[2];
59
+ if (!SAFE_TARGET.test(target)) {
60
+ throw new SimulationParseError(line, `invalid measurable target "${target}"`);
61
+ }
62
+ const measurableToken = measurableMatch[1].toLowerCase();
63
+ const measurable = measurableToken === 'v'
64
+ ? { kind: 'voltage', target }
65
+ : measurableToken === 'i'
66
+ ? { kind: 'current', target }
67
+ : { kind: 'corner', target };
68
+ const comparatorText = measurableMatch[3].trim();
69
+ const betweenMatch = /^between\s+(\S+)\s+and\s+(\S+)$/i.exec(comparatorText);
70
+ let comparator;
71
+ if (betweenMatch) {
72
+ const lower = parseSpiceNumber(betweenMatch[1], line);
73
+ const upper = parseSpiceNumber(betweenMatch[2], line);
74
+ if (lower.unit.toLowerCase() !== upper.unit.toLowerCase()) {
75
+ throw new SimulationParseError(line, 'between bounds use different units');
76
+ }
77
+ if (lower.value >= upper.value) {
78
+ throw new SimulationParseError(line, 'between lower bound must be less than upper bound');
79
+ }
80
+ comparator = { kind: 'between', lower, upper };
81
+ }
82
+ else {
83
+ const singleMatch = /^([<>])\s*(\S+)$/.exec(comparatorText);
84
+ if (!singleMatch) {
85
+ throw new SimulationParseError(line, `invalid comparator "${comparatorText}"`);
86
+ }
87
+ const bound = parseSpiceNumber(singleMatch[2], line);
88
+ comparator =
89
+ singleMatch[1] === '<'
90
+ ? { kind: 'less-than', bound }
91
+ : { kind: 'greater-than', bound };
92
+ }
93
+ return { raw: text, line, measurable, comparator };
94
+ }
95
+ /**
96
+ * Parse every `## Simulation` section from SUBSYSTEMS.md.
97
+ *
98
+ * Fields are line-oriented so errors can always identify the source line.
99
+ */
100
+ export function parseSimulationBlocks(markdown) {
101
+ const lines = markdown.split(/\r?\n/);
102
+ const blocks = [];
103
+ let openFence = null;
104
+ let inDocumentComment = false;
105
+ for (let index = 0; index < lines.length; index++) {
106
+ const line = lines[index].trim();
107
+ const fence = markdownFence(line);
108
+ if (openFence) {
109
+ if (fence)
110
+ openFence = toggleFence(openFence, fence);
111
+ continue;
112
+ }
113
+ if (inDocumentComment) {
114
+ if (line.includes('-->'))
115
+ inDocumentComment = false;
116
+ continue;
117
+ }
118
+ if (fence) {
119
+ openFence = fence;
120
+ continue;
121
+ }
122
+ if (line.startsWith('<!--')) {
123
+ if (!line.includes('-->'))
124
+ inDocumentComment = true;
125
+ continue;
126
+ }
127
+ if (!/^##\s+Simulation\s*$/i.test(line))
128
+ continue;
129
+ const headingLine = index + 1;
130
+ const body = [];
131
+ let cursor = index + 1;
132
+ let inComment = false;
133
+ let bodyFence = null;
134
+ for (; cursor < lines.length; cursor++) {
135
+ const text = lines[cursor];
136
+ const trimmed = text.trim();
137
+ const bodyFenceMarker = markdownFence(trimmed);
138
+ if (bodyFence) {
139
+ if (bodyFenceMarker)
140
+ bodyFence = toggleFence(bodyFence, bodyFenceMarker);
141
+ continue;
142
+ }
143
+ if (inComment) {
144
+ if (trimmed.includes('-->'))
145
+ inComment = false;
146
+ continue;
147
+ }
148
+ if (bodyFenceMarker) {
149
+ bodyFence = bodyFenceMarker;
150
+ continue;
151
+ }
152
+ if (/^#{1,6}\s+/.test(trimmed))
153
+ break;
154
+ if (trimmed.startsWith('<!--')) {
155
+ if (!trimmed.includes('-->'))
156
+ inComment = true;
157
+ continue;
158
+ }
159
+ if (trimmed.startsWith('.') || /^[A-Za-z]+\s*:/.test(trimmed)) {
160
+ body.push({ text: trimmed, line: cursor + 1 });
161
+ }
162
+ }
163
+ blocks.push(parseSimulationBlock(body, headingLine));
164
+ index = cursor - 1;
165
+ }
166
+ return blocks;
167
+ }
168
+ function markdownFence(line) {
169
+ return /^(`{3,}|~{3,})/.exec(line)?.[1] ?? null;
170
+ }
171
+ function toggleFence(openFence, marker) {
172
+ if (!openFence)
173
+ return marker;
174
+ if (marker[0] === openFence[0] && marker.length >= openFence.length)
175
+ return null;
176
+ return openFence;
177
+ }
178
+ function parseSimulationBlock(body, headingLine) {
179
+ let scope;
180
+ let analysis;
181
+ const sources = [];
182
+ const assertions = [];
183
+ for (const entry of body) {
184
+ if (entry.text.startsWith('.')) {
185
+ throw new SimulationParseError(entry.line, `raw ngspice statement "${entry.text.split(/\s/, 1)[0]}" is not allowed`);
186
+ }
187
+ const fieldMatch = /^([A-Za-z]+)\s*:\s*(.+)$/.exec(entry.text);
188
+ if (!fieldMatch) {
189
+ throw new SimulationParseError(entry.line, `expected "field: value", got "${entry.text}"`);
190
+ }
191
+ const field = fieldMatch[1].toLowerCase();
192
+ const value = fieldMatch[2].trim();
193
+ switch (field) {
194
+ case 'scope':
195
+ if (scope)
196
+ throw new SimulationParseError(entry.line, 'duplicate scope');
197
+ scope = parseScope(value, entry.line);
198
+ break;
199
+ case 'analysis': {
200
+ if (analysis)
201
+ throw new SimulationParseError(entry.line, 'duplicate analysis');
202
+ const candidate = value.toLowerCase();
203
+ if (!ANALYSES.has(candidate)) {
204
+ throw new SimulationParseError(entry.line, `unsupported analysis "${value}"`);
205
+ }
206
+ analysis = candidate;
207
+ break;
208
+ }
209
+ case 'source':
210
+ case 'sources':
211
+ sources.push(parseSource(value, entry.line));
212
+ break;
213
+ case 'assert':
214
+ assertions.push(parseSpiceAssertion(value, entry.line));
215
+ break;
216
+ default:
217
+ throw new SimulationParseError(entry.line, `unknown Simulation field "${field}"`);
218
+ }
219
+ }
220
+ if (!scope)
221
+ throw new SimulationParseError(headingLine, 'Simulation block is missing scope');
222
+ if (!analysis)
223
+ throw new SimulationParseError(headingLine, 'Simulation block is missing analysis');
224
+ if (assertions.length === 0) {
225
+ throw new SimulationParseError(headingLine, 'Simulation block needs at least one assertion');
226
+ }
227
+ return { line: headingLine, scope, analysis, sources, assertions };
228
+ }
229
+ function parseScope(raw, line) {
230
+ const match = /^(sheet|nets)(?:\s+(.*))?$/i.exec(raw);
231
+ if (!match) {
232
+ throw new SimulationParseError(line, 'scope must be "sheet <path>" or "nets <a>, <b>"');
233
+ }
234
+ const scopeValue = (match[2] ?? '').trim();
235
+ if (match[1].toLowerCase() === 'sheet') {
236
+ if (scopeValue.length === 0) {
237
+ throw new SimulationParseError(line, 'sheet scope is empty');
238
+ }
239
+ return { kind: 'sheet', sheet: scopeValue };
240
+ }
241
+ const netList = scopeValue.replace(/^\[(.*)\]$/, '$1');
242
+ const nets = netList
243
+ .split(',')
244
+ .map((net) => net.trim())
245
+ .filter((net) => net.length > 0);
246
+ if (nets.length === 0 || nets.some((net) => !SAFE_TARGET.test(net))) {
247
+ throw new SimulationParseError(line, 'net scope must contain comma-separated net names');
248
+ }
249
+ return { kind: 'nets', nets: [...new Set(nets)] };
250
+ }
251
+ function parseSource(raw, line) {
252
+ const match = /^([A-Za-z_][A-Za-z0-9_./:+-]*)\s*=\s*(\S+)$/.exec(raw);
253
+ if (!match) {
254
+ throw new SimulationParseError(line, 'source must be "<port>=<number>"');
255
+ }
256
+ return {
257
+ port: match[1],
258
+ value: parseSpiceNumber(match[2], line),
259
+ line,
260
+ };
261
+ }
262
+ /**
263
+ * Compile a parsed assertion to one value measure and one or two margin
264
+ * measures. Inclusive bounds pass at zero; strict bounds must be positive.
265
+ */
266
+ export function compileSpiceAssertion(assertion, analysis, name = `assertion_${assertion.line}`) {
267
+ if (!SAFE_MEASURE_NAME.test(name)) {
268
+ throw new SimulationParseError(assertion.line, `invalid measure name "${name}"`);
269
+ }
270
+ let valueLine;
271
+ if (assertion.measurable.kind === 'corner') {
272
+ if (analysis !== 'ac') {
273
+ throw new SimulationParseError(assertion.line, 'corner() requires an ac analysis');
274
+ }
275
+ valueLine = `.meas ac ${name}_value WHEN vdb(${assertion.measurable.target})=-3 FALL=1`;
276
+ }
277
+ else {
278
+ const expression = assertion.measurable.kind === 'voltage'
279
+ ? `v(${assertion.measurable.target})`
280
+ : `i(${assertion.measurable.target})`;
281
+ const operation = analysis === 'op' ? 'FIND' : 'AVG';
282
+ valueLine = `.meas ${analysis} ${name}_value ${operation} ${expression}`;
283
+ }
284
+ const valueName = `${name}_value`;
285
+ const marginExpressions = assertion.comparator.kind === 'between'
286
+ ? [
287
+ [`${name}_lower_margin`, `${valueName} - ${assertion.comparator.lower.raw}`],
288
+ [`${name}_upper_margin`, `${assertion.comparator.upper.raw} - ${valueName}`],
289
+ ]
290
+ : assertion.comparator.kind === 'less-than'
291
+ ? [[`${name}_margin`, `${assertion.comparator.bound.raw} - ${valueName}`]]
292
+ : [[`${name}_margin`, `${valueName} - ${assertion.comparator.bound.raw}`]];
293
+ const checks = marginExpressions.map(([checkName]) => ({
294
+ name: checkName,
295
+ pass: assertion.comparator.kind === 'between' ? 'nonnegative' : 'positive',
296
+ }));
297
+ const checkLines = marginExpressions.map(([checkName, expression]) => `.meas ${analysis} ${checkName} PARAM='${expression}'`);
298
+ const compiledLines = [valueLine, ...checkLines];
299
+ return {
300
+ valueName,
301
+ checks,
302
+ lines: compiledLines,
303
+ deck: compiledLines.join('\n'),
304
+ };
305
+ }
306
+ //# sourceMappingURL=spice.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spice.js","sourceRoot":"","sources":["../../src/kicad/spice.ts"],"names":[],"mappings":"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"}