copperhead 0.6.0 → 0.8.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 (118) hide show
  1. package/README.md +36 -4
  2. package/dist/agent/animate.js +76 -0
  3. package/dist/agent/animate.js.map +1 -0
  4. package/dist/agent/box.js +89 -0
  5. package/dist/agent/box.js.map +1 -0
  6. package/dist/agent/dock-renderer.js +173 -0
  7. package/dist/agent/dock-renderer.js.map +1 -0
  8. package/dist/agent/logo.js +21 -0
  9. package/dist/agent/logo.js.map +1 -0
  10. package/dist/agent/loop.js +130 -18
  11. package/dist/agent/loop.js.map +1 -1
  12. package/dist/agent/prompts.js +2 -1
  13. package/dist/agent/prompts.js.map +1 -1
  14. package/dist/agent/providers/claude-code.js +85 -116
  15. package/dist/agent/providers/claude-code.js.map +1 -1
  16. package/dist/agent/providers/cursor.js +317 -0
  17. package/dist/agent/providers/cursor.js.map +1 -0
  18. package/dist/agent/providers/tool-protocol.js +205 -0
  19. package/dist/agent/providers/tool-protocol.js.map +1 -0
  20. package/dist/agent/recovery.js +148 -0
  21. package/dist/agent/recovery.js.map +1 -0
  22. package/dist/agent/render.js +44 -12
  23. package/dist/agent/render.js.map +1 -1
  24. package/dist/agent/response-cache.js +81 -0
  25. package/dist/agent/response-cache.js.map +1 -0
  26. package/dist/agent/runmeta.js +4 -5
  27. package/dist/agent/runmeta.js.map +1 -1
  28. package/dist/agent/theme.js +84 -0
  29. package/dist/agent/theme.js.map +1 -0
  30. package/dist/agent/tools.js +61 -4
  31. package/dist/agent/tools.js.map +1 -1
  32. package/dist/agent/transcript.js.map +1 -1
  33. package/dist/cli.js +134 -13
  34. package/dist/cli.js.map +1 -1
  35. package/dist/commands/create.js +482 -38
  36. package/dist/commands/create.js.map +1 -1
  37. package/dist/commands/demo.js +146 -0
  38. package/dist/commands/demo.js.map +1 -0
  39. package/dist/commands/doctor.js +240 -0
  40. package/dist/commands/doctor.js.map +1 -0
  41. package/dist/commands/repl-inspect.js +342 -0
  42. package/dist/commands/repl-inspect.js.map +1 -0
  43. package/dist/commands/repl.js +618 -0
  44. package/dist/commands/repl.js.map +1 -0
  45. package/dist/config.js +24 -2
  46. package/dist/config.js.map +1 -1
  47. package/dist/kicad/bootstrap.js +166 -0
  48. package/dist/kicad/bootstrap.js.map +1 -0
  49. package/dist/kicad/cli.js +126 -6
  50. package/dist/kicad/cli.js.map +1 -1
  51. package/dist/kicad/spice.js +306 -0
  52. package/dist/kicad/spice.js.map +1 -0
  53. package/dist/kicad/symlib.js +228 -0
  54. package/dist/kicad/symlib.js.map +1 -0
  55. package/dist/memory/bom-table.js +193 -22
  56. package/dist/memory/bom-table.js.map +1 -1
  57. package/dist/memory/drift.js +33 -11
  58. package/dist/memory/drift.js.map +1 -1
  59. package/dist/util/cli-args.js +35 -0
  60. package/dist/util/cli-args.js.map +1 -0
  61. package/dist/util/dock.js +155 -0
  62. package/dist/util/dock.js.map +1 -0
  63. package/dist/util/git.js +165 -4
  64. package/dist/util/git.js.map +1 -1
  65. package/dist/util/live-prompt.js +542 -0
  66. package/dist/util/live-prompt.js.map +1 -0
  67. package/dist/util/paths.js +9 -0
  68. package/dist/util/paths.js.map +1 -1
  69. package/dist/util/preflight.js +37 -0
  70. package/dist/util/preflight.js.map +1 -1
  71. package/dist/util/retry.js +23 -0
  72. package/dist/util/retry.js.map +1 -1
  73. package/dist/util/select.js +172 -0
  74. package/dist/util/select.js.map +1 -0
  75. package/dist/util/tmp.js +119 -0
  76. package/dist/util/tmp.js.map +1 -0
  77. package/package.json +3 -2
  78. package/src/agent/animate.ts +90 -0
  79. package/src/agent/box.ts +99 -0
  80. package/src/agent/dock-renderer.ts +181 -0
  81. package/src/agent/logo.ts +23 -0
  82. package/src/agent/loop.ts +148 -18
  83. package/src/agent/prompts.ts +2 -1
  84. package/src/agent/providers/claude-code.ts +91 -122
  85. package/src/agent/providers/cursor.ts +364 -0
  86. package/src/agent/providers/tool-protocol.ts +212 -0
  87. package/src/agent/recovery.ts +162 -0
  88. package/src/agent/render.ts +56 -12
  89. package/src/agent/response-cache.ts +80 -0
  90. package/src/agent/runmeta.ts +6 -7
  91. package/src/agent/theme.ts +91 -0
  92. package/src/agent/tools.ts +62 -4
  93. package/src/agent/transcript.ts +1 -0
  94. package/src/agent/types.ts +17 -0
  95. package/src/cli.ts +139 -15
  96. package/src/commands/create.ts +581 -40
  97. package/src/commands/demo.ts +184 -0
  98. package/src/commands/doctor.ts +289 -0
  99. package/src/commands/repl-inspect.ts +353 -0
  100. package/src/commands/repl.ts +685 -0
  101. package/src/config.ts +40 -3
  102. package/src/kicad/bootstrap.ts +181 -0
  103. package/src/kicad/cli.ts +132 -7
  104. package/src/kicad/spice.ts +399 -0
  105. package/src/kicad/symlib.ts +248 -0
  106. package/src/layout/claude-ui-layout.md +72 -0
  107. package/src/layout/repl-ui-layout.md +139 -0
  108. package/src/memory/bom-table.ts +191 -20
  109. package/src/memory/drift.ts +42 -11
  110. package/src/util/cli-args.ts +42 -0
  111. package/src/util/dock.ts +161 -0
  112. package/src/util/git.ts +176 -4
  113. package/src/util/live-prompt.ts +595 -0
  114. package/src/util/paths.ts +10 -0
  115. package/src/util/preflight.ts +44 -0
  116. package/src/util/retry.ts +29 -0
  117. package/src/util/select.ts +192 -0
  118. package/src/util/tmp.ts +113 -0
@@ -30,31 +30,202 @@ export function parseMarkdownTables(md) {
30
30
  * Refdes or Pin column, so one check covers both doc types. */
31
31
  export const isHeader = (row) => row.cells.some((c) => /^(refdes|pin)$/i.test(c));
32
32
  /**
33
- * Parses BOM.md's data rows into typed rows. Rows without a refdes in
34
- * column 1 are dropped rather than thrown on: a hand-edited doc with a
35
- * ragged or partial table shouldn't crash `check` or `export bom`, it
36
- * should just be skipped (drift/export callers report the gaps that
37
- * matter through their own comparisons against the schematic).
33
+ * Data rows of the CANONICAL table(s) only those introduced by a Refdes/Pin
34
+ * header row (`isHeader`). BOM.md and PINOUT.md legitimately carry supporting
35
+ * tables (a quiescent-current roll-up, a net-meaning legend); their rows are
36
+ * NOT parts/pins and must never be compared against the schematic. The flat
37
+ * `parseMarkdownTables(md).filter(!isHeader)` does exactly that it merges
38
+ * every table's rows — so a second table's first cell gets read as a refdes and
39
+ * flagged "not in schematic", which pushes the agent to degrade good docs into
40
+ * bullet lists just to appease the drift gate.
41
+ *
42
+ * This groups lines into tables (a run of pipe-rows, ended by any non-pipe
43
+ * line), keeps only the groups whose first row is a Refdes/Pin header, and
44
+ * returns those groups' data rows (header dropped). A table with no recognized
45
+ * header — including a bare data-only block — is ignored, preserving the
46
+ * fixed-column contract (design D9) while letting docs hold extra tables.
47
+ */
48
+ export function parseCanonicalRows(md) {
49
+ return parseCanonicalTables(md).flatMap((t) => t.rows);
50
+ }
51
+ /**
52
+ * Like parseCanonicalRows, but keeps each kept table's header row so a caller
53
+ * can resolve columns by *name* instead of a fixed position. PINOUT.md's
54
+ * column count is not fixed in practice: the scaffold writes
55
+ * `Refdes | Pin | Name | Net | Notes`, but a hand- or LLM-authored table may
56
+ * legitimately drop the optional Name/Notes columns and write
57
+ * `Refdes | Pin | Net`. A fixed positional net index then reads the wrong cell
58
+ * and reports every pin as net "NC" against a doc that is in fact correct —
59
+ * a false drift the agent cannot diagnose (the doc plainly shows the net), so
60
+ * it loops on finish forever. Resolving by header name fixes that.
61
+ */
62
+ export function parseCanonicalTables(md) {
63
+ const groups = [];
64
+ let current = null;
65
+ for (const line of md.split('\n')) {
66
+ const t = line.trim();
67
+ if (!t.startsWith('|')) {
68
+ current = null; // a blank or prose line terminates the current table
69
+ continue;
70
+ }
71
+ const cells = t
72
+ .split('|')
73
+ .slice(1, -1)
74
+ .map((c) => c.trim());
75
+ if (cells.every((c) => /^:?-+:?$/.test(c)))
76
+ continue; // separator row: stays within the table
77
+ if (!current) {
78
+ current = [];
79
+ groups.push(current);
80
+ }
81
+ current.push({ cells });
82
+ }
83
+ const tables = [];
84
+ for (const g of groups) {
85
+ if (g.length && isHeader(g[0]))
86
+ tables.push({ header: g[0], rows: g.slice(1) });
87
+ }
88
+ return tables;
89
+ }
90
+ /**
91
+ * PINOUT.md pin assignments, resolved by column *name* and tolerant of the
92
+ * optional Name/Notes columns (see parseCanonicalTables). Only the canonical
93
+ * table that carries both a Pin and a Net header is read; a supporting table
94
+ * (e.g. a `Net | Role` legend) is ignored. Net names are compared bare, so the
95
+ * common `` `VBUS` `` markdown-backtick styling is stripped — the schematic
96
+ * stores plain net names, and a backtick-only difference is not real drift.
97
+ */
98
+ export function parsePinoutRows(md) {
99
+ const out = [];
100
+ const strip = (s) => (s ?? '').replace(/`/g, '').trim();
101
+ for (const { header, rows } of parseCanonicalTables(md)) {
102
+ const col = (re) => header.cells.findIndex((c) => re.test(c));
103
+ const refI = col(/^refdes$/i);
104
+ const pinI = col(/^pin$/i);
105
+ const netI = col(/^net$/i);
106
+ if (pinI < 0 || netI < 0)
107
+ continue; // not the pin-assignment table
108
+ for (const row of rows) {
109
+ out.push({
110
+ ref: refI >= 0 ? strip(row.cells[refI]) : '',
111
+ pin: strip(row.cells[pinI]),
112
+ net: strip(row.cells[netI]),
113
+ });
114
+ }
115
+ }
116
+ return out;
117
+ }
118
+ /**
119
+ * Fold the semantically-identical encodings that the model and KiCad render
120
+ * differently, so a value that differs only in *encoding* is not flagged as
121
+ * drift (#I11). A design that reached ERC-clean once churned for turns on
122
+ * `Ihold≥3A` vs `Ihold>=3A` and `0.1"` vs `0.1in` — byte differences with zero
123
+ * electrical meaning. Folded here: ≥/>=, ≤/<=, Ω/ohm(s), µ/μ/u, smart quotes,
124
+ * and the inch mark (`"` / `″` / a trailing `in`/`inch` after a number). NFKC
125
+ * first collapses width/compatibility variants; the explicit rules cover the
126
+ * cases NFKC leaves alone (≥, smart quotes, the ohm/inch words).
127
+ */
128
+ export function foldEncodings(s) {
129
+ if (!s)
130
+ return '';
131
+ return s
132
+ .normalize('NFKC')
133
+ .replace(/≥/g, '>=')
134
+ .replace(/≤/g, '<=')
135
+ .replace(/[ΩΩ]/g, 'ohm') // ohm sign U+2126 / greek capital omega U+03A9
136
+ .replace(/\bohms\b/gi, 'ohm')
137
+ .replace(/[µμ]/g, 'u') // micro sign U+00B5 / greek small mu U+03BC
138
+ .replace(/[“”″]/g, '"') // smart double quotes and double-prime → "
139
+ .replace(/[‘’′]/g, "'") // smart single quotes and prime → '
140
+ .replace(/(?<=[\d.])\s*(?:inches|inch|in)\b/gi, '"') // 0.1in / 0.1 inch → 0.1"
141
+ .trim();
142
+ }
143
+ /**
144
+ * Value-cell equality key: `foldEncodings` plus case- and whitespace-folding.
145
+ * Used to compare BOM.md value/footprint cells against schematic symbol values
146
+ * so an encoding/case/spacing-only difference is not reported as drift.
147
+ */
148
+ export function normalizeValue(s) {
149
+ return foldEncodings(s).replace(/\s+/g, '').toLowerCase();
150
+ }
151
+ /**
152
+ * Footprint equality key: like `normalizeValue` but WITHOUT case-folding (F6).
153
+ * A footprint is a KiCad library reference (`Resistor_SMD:R_0603_1608Metric`)
154
+ * whose casing is significant — `R_0603` and `r_0603` are not the same library
155
+ * id — so lowercasing it would hide a real footprint difference. Encoding and
156
+ * spacing are still folded (a stray space or unicode variant is not real drift).
157
+ */
158
+ export function normalizeFootprint(s) {
159
+ return foldEncodings(s).replace(/\s+/g, '');
160
+ }
161
+ /**
162
+ * Which of the canonical pin-assignment columns PINOUT.md actually provides.
163
+ * `checkDrift` uses this to emit ONE explicit "no Net column" message when the
164
+ * doc omits the column entirely, instead of silently checking nothing (a
165
+ * correct doc then looks unverified) or — the old positional bug (#I12) —
166
+ * reading the wrong cell and reporting every pin as a false `NC` mismatch.
167
+ * `hasTable` is false when the doc has no Refdes/Pin-headed table at all.
168
+ */
169
+ export function pinoutColumnReport(md) {
170
+ let hasTable = false;
171
+ let pin = false;
172
+ let net = false;
173
+ let refdes = false;
174
+ for (const { header } of parseCanonicalTables(md)) {
175
+ hasTable = true;
176
+ const has = (re) => header.cells.some((c) => re.test(c));
177
+ if (has(/^pin$/i))
178
+ pin = true;
179
+ if (has(/^net$/i))
180
+ net = true;
181
+ if (has(/^refdes$/i))
182
+ refdes = true;
183
+ }
184
+ return { hasTable, pin, net, refdes };
185
+ }
186
+ /**
187
+ * Parses BOM.md's data rows into typed rows. Columns are resolved by header
188
+ * *name* (Refdes/Value/Footprint/MPN), falling back to the canonical position
189
+ * when a header is absent — the same header-name discipline `parsePinoutRows`
190
+ * uses (#I12), so a doc that reorders or drops an optional column is still read
191
+ * correctly instead of silently shifting every cell. Rows without a refdes are
192
+ * dropped rather than thrown on: a hand-edited doc with a ragged or partial
193
+ * table shouldn't crash `check` or `export bom`, it should just be skipped
194
+ * (drift/export callers report the gaps that matter against the schematic).
38
195
  */
39
196
  export function parseBomTable(md) {
40
- const rows = parseMarkdownTables(md).filter((r) => !isHeader(r));
41
197
  const out = [];
42
- for (const row of rows) {
43
- const [refdes, value, footprint, mpn] = row.cells;
44
- if (!refdes)
45
- continue;
46
- const flags = [];
47
- if (mpn === 'UNVERIFIED')
48
- flags.push('UNVERIFIED');
49
- else if (!mpn)
50
- flags.push('MISSING_MPN');
51
- out.push({
52
- refdes,
53
- value: value || undefined,
54
- footprint: footprint || undefined,
55
- mpn: mpn || undefined,
56
- flags,
57
- });
198
+ for (const { header, rows } of parseCanonicalTables(md)) {
199
+ // Resolve by header name; -1 means "not found", so fall back to the
200
+ // canonical index for that column (Refdes 0, Value 1, Footprint 2, MPN 3).
201
+ const col = (re, fallback) => {
202
+ const i = header.cells.findIndex((c) => re.test(c));
203
+ return i >= 0 ? i : fallback;
204
+ };
205
+ const refI = col(/^refdes$/i, 0);
206
+ const valI = col(/^value$/i, 1);
207
+ const fpI = col(/^footprint$/i, 2);
208
+ const mpnI = col(/^mpn$/i, 3);
209
+ for (const row of rows) {
210
+ const refdes = row.cells[refI];
211
+ if (!refdes)
212
+ continue;
213
+ const value = row.cells[valI];
214
+ const footprint = row.cells[fpI];
215
+ const mpn = row.cells[mpnI];
216
+ const flags = [];
217
+ if (mpn === 'UNVERIFIED')
218
+ flags.push('UNVERIFIED');
219
+ else if (!mpn)
220
+ flags.push('MISSING_MPN');
221
+ out.push({
222
+ refdes,
223
+ value: value || undefined,
224
+ footprint: footprint || undefined,
225
+ mpn: mpn || undefined,
226
+ flags,
227
+ });
228
+ }
58
229
  }
59
230
  return out;
60
231
  }
@@ -1 +1 @@
1
- {"version":3,"file":"bom-table.js","sourceRoot":"","sources":["../../src/memory/bom-table.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMD;;;;;GAKG;AACH,MAAM,UAAU,mBAAmB,CAAC,EAAU;IAC5C,MAAM,IAAI,GAAe,EAAE,CAAC;IAC5B,KAAK,MAAM,IAAI,IAAI,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;QAClC,MAAM,CAAC,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;QACtB,IAAI,CAAC,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC;YAAE,SAAS;QACjC,MAAM,KAAK,GAAG,CAAC;aACZ,KAAK,CAAC,GAAG,CAAC;aACV,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;aACZ,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;QACxB,IAAI,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAAE,SAAS,CAAC,gBAAgB;QACtE,IAAI,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;IACvB,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED;+DAC+D;AAC/D,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC,GAAa,EAAW,EAAE,CACjD,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;AAiBnD;;;;;;GAMG;AACH,MAAM,UAAU,aAAa,CAAC,EAAU;IACtC,MAAM,IAAI,GAAG,mBAAmB,CAAC,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;IACjE,MAAM,GAAG,GAAa,EAAE,CAAC;IACzB,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,MAAM,CAAC,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,GAAG,CAAC,GAAG,GAAG,CAAC,KAAK,CAAC;QAClD,IAAI,CAAC,MAAM;YAAE,SAAS;QACtB,MAAM,KAAK,GAAa,EAAE,CAAC;QAC3B,IAAI,GAAG,KAAK,YAAY;YAAE,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;aAC9C,IAAI,CAAC,GAAG;YAAE,KAAK,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;QACzC,GAAG,CAAC,IAAI,CAAC;YACP,MAAM;YACN,KAAK,EAAE,KAAK,IAAI,SAAS;YACzB,SAAS,EAAE,SAAS,IAAI,SAAS;YACjC,GAAG,EAAE,GAAG,IAAI,SAAS;YACrB,KAAK;SACN,CAAC,CAAC;IACL,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC"}
1
+ {"version":3,"file":"bom-table.js","sourceRoot":"","sources":["../../src/memory/bom-table.ts"],"names":[],"mappings":"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"}
@@ -2,7 +2,7 @@ import { readFile } from 'node:fs/promises';
2
2
  import { existsSync } from 'node:fs';
3
3
  import path from 'node:path';
4
4
  import { listSymbols, pinNets } from '../kicad/sexp.js';
5
- import { parseMarkdownTables, isHeader } from './bom-table.js';
5
+ import { parseCanonicalRows, parseBomTable, parsePinoutRows, pinoutColumnReport, normalizeValue, normalizeFootprint, } from './bom-table.js';
6
6
  /**
7
7
  * The zero-symbol carve-out in checkDrift is right for the create pipeline,
8
8
  * but it would let `check` silently pass an established repo whose schematic
@@ -18,8 +18,7 @@ export async function emptySchematicWarning(repoRoot, docsDir, schematic) {
18
18
  const bomPath = path.join(repoRoot, docsDir, 'BOM.md');
19
19
  if (!existsSync(bomPath))
20
20
  return null;
21
- const refs = parseMarkdownTables(await readFile(bomPath, 'utf8'))
22
- .filter((r) => !isHeader(r))
21
+ const refs = parseCanonicalRows(await readFile(bomPath, 'utf8'))
23
22
  .map((r) => r.cells[0])
24
23
  .filter(Boolean);
25
24
  if (!refs.length)
@@ -41,10 +40,11 @@ export async function checkDrift(repoRoot, docsDir, schematic) {
41
40
  const byRef = new Map(symbols.map((s) => [s.ref, s]));
42
41
  const bomPath = path.join(repoRoot, docsDir, 'BOM.md');
43
42
  if (existsSync(bomPath)) {
44
- const rows = parseMarkdownTables(await readFile(bomPath, 'utf8')).filter((r) => !isHeader(r));
43
+ // Resolve BOM columns by header name via the shared parseBomTable (F5), so
44
+ // the drift reader and `export bom` never disagree on a reordered table.
45
+ const rows = parseBomTable(await readFile(bomPath, 'utf8'));
45
46
  const seen = new Set();
46
- for (const row of rows) {
47
- const [ref, value, footprint] = row.cells;
47
+ for (const { refdes: ref, value, footprint } of rows) {
48
48
  if (!ref)
49
49
  continue;
50
50
  seen.add(ref);
@@ -53,10 +53,16 @@ export async function checkDrift(repoRoot, docsDir, schematic) {
53
53
  mismatches.push({ doc: 'BOM.md', claim: `${ref} exists`, actual: `${ref} not in schematic` });
54
54
  continue;
55
55
  }
56
- if (value !== undefined && value !== sym.value) {
56
+ // Compare on the semantic value, not the byte-exact string: `Ihold≥3A` and
57
+ // `Ihold>=3A` are the same value written two ways (#I11). Raw `!==` flagged
58
+ // them as drift and whack-a-moled the agent across finish attempts.
59
+ if (value !== undefined && normalizeValue(value) !== normalizeValue(sym.value)) {
57
60
  mismatches.push({ doc: 'BOM.md', claim: `${ref} value ${value}`, actual: `${ref} value ${sym.value}` });
58
61
  }
59
- if (footprint !== undefined && footprint !== '' && footprint !== sym.footprint) {
62
+ // Footprint compare folds encoding/spacing but keeps case (F6): a footprint
63
+ // library id is case-sensitive, so lowercasing would hide a real mismatch.
64
+ if (footprint !== undefined &&
65
+ normalizeFootprint(footprint) !== normalizeFootprint(sym.footprint)) {
60
66
  mismatches.push({
61
67
  doc: 'BOM.md',
62
68
  claim: `${ref} footprint ${footprint}`,
@@ -72,11 +78,27 @@ export async function checkDrift(repoRoot, docsDir, schematic) {
72
78
  }
73
79
  const pinoutPath = path.join(repoRoot, docsDir, 'PINOUT.md');
74
80
  if (existsSync(pinoutPath)) {
81
+ const pinoutMd = await readFile(pinoutPath, 'utf8');
75
82
  const nets = await pinNets(schPath);
76
83
  const netOf = new Map(nets.map((p) => [`${p.ref}:${p.pinNumber}`, p.net]));
77
- const rows = parseMarkdownTables(await readFile(pinoutPath, 'utf8')).filter((r) => !isHeader(r));
78
- for (const row of rows) {
79
- const [ref, pinNumber, , net] = row.cells;
84
+ // If the doc has a Refdes/Pin table but no Net column, say so once and
85
+ // explicitly, rather than silently checking nothing (a correct doc then
86
+ // reads as unverified) the counterpart to the old positional bug that
87
+ // reported every pin as a false NC (#I12). This tells the model what to fix
88
+ // (add the column) instead of leaving it guessing why nets aren't verified.
89
+ const cols = pinoutColumnReport(pinoutMd);
90
+ if (cols.hasTable && !cols.net) {
91
+ mismatches.push({
92
+ doc: 'PINOUT.md',
93
+ claim: 'the pin table has a Net column (expected header: Refdes | Pin | Net)',
94
+ actual: 'no Net column in the pin table, so pin-to-net assignments cannot be checked; add a Net column',
95
+ });
96
+ }
97
+ // Resolve columns by header name, not position: the PINOUT table may be
98
+ // `Refdes | Pin | Net` or the scaffold's `Refdes | Pin | Name | Net | Notes`.
99
+ // A fixed net index read every pin as "NC" on the 3-column form (#I12).
100
+ const rows = parsePinoutRows(pinoutMd);
101
+ for (const { ref, pin: pinNumber, net } of rows) {
80
102
  if (!ref || !pinNumber)
81
103
  continue;
82
104
  const k = `${ref}:${pinNumber}`;
@@ -1 +1 @@
1
- {"version":3,"file":"drift.js","sourceRoot":"","sources":["../../src/memory/drift.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"drift.js","sourceRoot":"","sources":["../../src/memory/drift.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Pure argument helpers for the CLI surface. They live here rather than in
3
+ * cli.ts because that module wires up commander and parses argv at import
4
+ * time, which makes it untestable in-process: importing it runs the program.
5
+ * Anything with a branch worth pinning belongs on this side of the line.
6
+ */
7
+ import path from 'node:path';
8
+ /** Resolve `--repo` against the working directory; absolute paths pass through. */
9
+ export function repoOf(opts) {
10
+ return path.resolve(opts.repo ?? process.cwd());
11
+ }
12
+ /** `--max-turns` accepts only a positive integer; "5oops" and "NaN" refuse to start. */
13
+ export function parseMaxTurns(raw) {
14
+ const n = Number(raw);
15
+ if (!Number.isInteger(n) || n <= 0) {
16
+ throw new Error(`--max-turns must be a positive integer, got "${raw}"`);
17
+ }
18
+ return n;
19
+ }
20
+ /**
21
+ * Turns offered when the budget runs out: ceil of the ORIGINAL budget (design
22
+ * D1), so repeat extensions offer the same increment instead of escalating
23
+ * with the already-extended turn count.
24
+ */
25
+ export function budgetExtraTurns(stats) {
26
+ return Math.ceil(stats.maxTurns / 2);
27
+ }
28
+ /** The attended "continue?" question, with the cost of the run so far spelled out. */
29
+ export function budgetPromptText(stats) {
30
+ const k = (n) => `${(n / 1000).toFixed(1)}k`;
31
+ return (`Turn budget exhausted (${stats.turnsUsed} turns, ${k(stats.tokensIn)} in / ${k(stats.tokensOut)} out, ` +
32
+ `${stats.filesTouched.length} file(s) touched, ${stats.openObligations} open obligation(s)). ` +
33
+ `Continue with ${budgetExtraTurns(stats)} more turns?`);
34
+ }
35
+ //# sourceMappingURL=cli-args.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli-args.js","sourceRoot":"","sources":["../../src/util/cli-args.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,IAAI,MAAM,WAAW,CAAC;AAG7B,mFAAmF;AACnF,MAAM,UAAU,MAAM,CAAC,IAAuB;IAC5C,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;AAClD,CAAC;AAED,wFAAwF;AACxF,MAAM,UAAU,aAAa,CAAC,GAAW;IACvC,MAAM,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;IACtB,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QACnC,MAAM,IAAI,KAAK,CAAC,gDAAgD,GAAG,GAAG,CAAC,CAAC;IAC1E,CAAC;IACD,OAAO,CAAC,CAAC;AACX,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,gBAAgB,CAAC,KAA6C;IAC5E,OAAO,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,GAAG,CAAC,CAAC,CAAC;AACvC,CAAC;AAED,sFAAsF;AACtF,MAAM,UAAU,gBAAgB,CAAC,KAA2B;IAC1D,MAAM,CAAC,GAAG,CAAC,CAAS,EAAU,EAAE,CAAC,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC;IAC7D,OAAO,CACL,0BAA0B,KAAK,CAAC,SAAS,WAAW,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC,QAAQ;QACxG,GAAG,KAAK,CAAC,YAAY,CAAC,MAAM,qBAAqB,KAAK,CAAC,eAAe,wBAAwB;QAC9F,iBAAiB,gBAAgB,CAAC,KAAK,CAAC,cAAc,CACvD,CAAC;AACJ,CAAC"}
@@ -0,0 +1,155 @@
1
+ /**
2
+ * Bottom-of-viewport dock built on DECSTBM scroll regions: content is fenced
3
+ * into rows [1, H - dockHeight] and the dock is painted with absolute cursor
4
+ * addressing below the scroll margin, so no amount of content output (or
5
+ * mouse wheel) can ever move it. Runs inside the alternate screen buffer the
6
+ * REPL enters at startup. This is the FrankenTUI/ratatui-inline technique;
7
+ * see also DECSTBM (CSI r).
8
+ */
9
+ import { truncateVisible } from '../agent/box.js';
10
+ const HIDE = '\x1b[?25l';
11
+ const SHOW = '\x1b[?25h';
12
+ /** Synchronized-output guards; terminals without support ignore them. */
13
+ const SYNC_ON = '\x1b[?2026h';
14
+ const SYNC_OFF = '\x1b[?2026l';
15
+ /** Reset the scroll region to the full screen. Homes the cursor (hence DECSC/DECRC around it). */
16
+ const REGION_RESET = '\x1b[r';
17
+ const SAVE = '\x1b7';
18
+ const RESTORE = '\x1b8';
19
+ export class TerminalDock {
20
+ out;
21
+ /** Rows the dock currently occupies at the bottom of the screen. */
22
+ dockH = 0;
23
+ /**
24
+ * True while the real cursor is parked at a caret position inside the dock
25
+ * (the DECSC slot then holds the content-region position to return to).
26
+ */
27
+ parked = false;
28
+ /** Last set() payload, replayable after an external overdraw (animations). */
29
+ last = null;
30
+ constructor(out) {
31
+ this.out = out;
32
+ }
33
+ cols() {
34
+ return typeof this.out.columns === 'number' && this.out.columns ? this.out.columns : 80;
35
+ }
36
+ rows() {
37
+ return typeof this.out.rows === 'number' && this.out.rows ? this.out.rows : 24;
38
+ }
39
+ /**
40
+ * Replace the docked region. On a height change the content scroll region
41
+ * is re-fenced; same-height repaints are pure absolute-addressed writes and
42
+ * can never scroll anything. With `caret` (dock-relative 1-based row and
43
+ * column) the real terminal cursor is left parked there, Claude Code-style.
44
+ */
45
+ set(lines, caret) {
46
+ if (!lines.length) {
47
+ this.release();
48
+ return;
49
+ }
50
+ const h = this.rows();
51
+ const shown = lines.slice(0, Math.max(1, h - 3)).map((l) => truncateVisible(l, this.cols() - 1));
52
+ const newH = shown.length;
53
+ let seq = SYNC_ON + HIDE;
54
+ if (this.parked) {
55
+ // Return to the content position first so the SAVE/RESTORE pairs below
56
+ // keep preserving it, not the old caret.
57
+ seq += RESTORE;
58
+ this.parked = false;
59
+ }
60
+ if (this.dockH === 0) {
61
+ // First activation: free the bottom rows by scrolling exactly as much
62
+ // as needed (preserves the banner above), then fence content into
63
+ // [1, h - newH]. DECSTBM homes the cursor; save/restore keeps it.
64
+ seq += SAVE + REGION_RESET + RESTORE;
65
+ seq += '\n'.repeat(newH) + `\x1b[${newH}A`;
66
+ seq += SAVE + `\x1b[1;${h - newH}r` + RESTORE;
67
+ }
68
+ else if (newH !== this.dockH) {
69
+ // Height change while active (menu open/close): overlay mode. Re-fence
70
+ // and clear any rows freed by a shrink; never scroll content.
71
+ seq += SAVE + `\x1b[1;${h - newH}r`;
72
+ for (let r = h - Math.max(this.dockH, newH) + 1; r <= h - newH; r++) {
73
+ seq += `\x1b[${r};1H\x1b[2K`;
74
+ }
75
+ seq += RESTORE;
76
+ }
77
+ seq += SAVE;
78
+ for (let i = 0; i < newH; i++) {
79
+ seq += `\x1b[${h - newH + 1 + i};1H\x1b[2K${shown[i]}`;
80
+ }
81
+ seq += RESTORE;
82
+ if (caret) {
83
+ const row = Math.min(h, h - newH + Math.max(1, caret.row));
84
+ const col = Math.max(1, Math.min(this.cols(), caret.col));
85
+ seq += SAVE + `\x1b[${row};${col}H`;
86
+ this.parked = true;
87
+ }
88
+ seq += SHOW + SYNC_OFF;
89
+ this.out.write(seq);
90
+ this.dockH = newH;
91
+ this.last = caret ? { lines, caret } : { lines };
92
+ }
93
+ /** Replay the last set() (e.g. after an animation overdrew part of the screen). */
94
+ repaint() {
95
+ if (this.last)
96
+ this.set(this.last.lines, this.last.caret);
97
+ }
98
+ /** Rows available to content above the dock. */
99
+ contentRows() {
100
+ return Math.max(1, this.rows() - this.dockH);
101
+ }
102
+ /**
103
+ * Absolute-paint the whole content region (rows 1..contentRows) from the
104
+ * given lines — used by history scrolling to show any window of the session
105
+ * log. Does not touch the DECSC slot or the fence; callers repaint() the
106
+ * dock afterwards to restore the caret.
107
+ */
108
+ paintContent(lines) {
109
+ const rowsN = this.contentRows();
110
+ const shown = lines.slice(-rowsN).map((l) => truncateVisible(l, this.cols() - 1));
111
+ let seq = SYNC_ON + HIDE;
112
+ for (let r = 1; r <= rowsN; r++) {
113
+ seq += `\x1b[${r};1H\x1b[2K${shown[r - 1] ?? ''}`;
114
+ }
115
+ seq += SYNC_OFF;
116
+ this.out.write(seq);
117
+ }
118
+ /**
119
+ * Write a scrollback line above the dock. With the fence in place a plain
120
+ * write cannot touch the dock rows; if the cursor is parked at the caret,
121
+ * hop back to the content region for the write and re-park after.
122
+ */
123
+ log(line) {
124
+ if (!this.parked) {
125
+ this.out.write(line + '\n');
126
+ return;
127
+ }
128
+ this.out.write(SYNC_ON + RESTORE + line + '\n' + SAVE + SYNC_OFF);
129
+ // The slot now holds the advanced content position; the caret will be
130
+ // re-established by the next set() with a caret argument.
131
+ this.parked = false;
132
+ }
133
+ /** Drop the fence, clear the dock rows, and restore the cursor. */
134
+ release() {
135
+ if (!this.dockH) {
136
+ this.out.write(SHOW);
137
+ return;
138
+ }
139
+ const h = this.rows();
140
+ let seq = SYNC_ON;
141
+ if (this.parked) {
142
+ seq += RESTORE;
143
+ this.parked = false;
144
+ }
145
+ seq += SAVE + REGION_RESET + RESTORE;
146
+ seq += SAVE;
147
+ for (let r = h - this.dockH + 1; r <= h; r++)
148
+ seq += `\x1b[${r};1H\x1b[2K`;
149
+ seq += RESTORE + SHOW + SYNC_OFF;
150
+ this.out.write(seq);
151
+ this.dockH = 0;
152
+ this.last = null;
153
+ }
154
+ }
155
+ //# sourceMappingURL=dock.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dock.js","sourceRoot":"","sources":["../../src/util/dock.ts"],"names":[],"mappings":"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"}