@vessel-dsp/compiler 0.0.0-stage → 0.2.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 (226) hide show
  1. package/README.md +314 -2
  2. package/dist/bake.d.ts +38 -0
  3. package/dist/bake.d.ts.map +1 -0
  4. package/dist/bake.js +101 -0
  5. package/dist/bake.js.map +1 -0
  6. package/dist/bbd-clock.d.ts +171 -0
  7. package/dist/bbd-clock.d.ts.map +1 -0
  8. package/dist/bbd-clock.js +1750 -0
  9. package/dist/bbd-clock.js.map +1 -0
  10. package/dist/block-row.d.ts +51 -0
  11. package/dist/block-row.d.ts.map +1 -0
  12. package/dist/block-row.js +17 -0
  13. package/dist/block-row.js.map +1 -0
  14. package/dist/bypass.d.ts +3 -0
  15. package/dist/bypass.d.ts.map +1 -0
  16. package/dist/bypass.js +228 -0
  17. package/dist/bypass.js.map +1 -0
  18. package/dist/compile.d.ts +24 -0
  19. package/dist/compile.d.ts.map +1 -0
  20. package/dist/compile.js +344 -0
  21. package/dist/compile.js.map +1 -0
  22. package/dist/converter-scale.d.ts +14 -0
  23. package/dist/converter-scale.d.ts.map +1 -0
  24. package/dist/converter-scale.js +133 -0
  25. package/dist/converter-scale.js.map +1 -0
  26. package/dist/couple.d.ts +28 -0
  27. package/dist/couple.d.ts.map +1 -0
  28. package/dist/couple.js +567 -0
  29. package/dist/couple.js.map +1 -0
  30. package/dist/dangling-active-terminal.d.ts +47 -0
  31. package/dist/dangling-active-terminal.d.ts.map +1 -0
  32. package/dist/dangling-active-terminal.js +542 -0
  33. package/dist/dangling-active-terminal.js.map +1 -0
  34. package/dist/declared-program.d.ts +23 -0
  35. package/dist/declared-program.d.ts.map +1 -0
  36. package/dist/declared-program.js +387 -0
  37. package/dist/declared-program.js.map +1 -0
  38. package/dist/denomination.d.ts +48 -0
  39. package/dist/denomination.d.ts.map +1 -0
  40. package/dist/denomination.js +27 -0
  41. package/dist/denomination.js.map +1 -0
  42. package/dist/device-laws.d.ts +237 -0
  43. package/dist/device-laws.d.ts.map +1 -0
  44. package/dist/device-laws.js +3497 -0
  45. package/dist/device-laws.js.map +1 -0
  46. package/dist/diagnostics.d.ts +13 -0
  47. package/dist/diagnostics.d.ts.map +1 -0
  48. package/dist/diagnostics.js +19 -0
  49. package/dist/diagnostics.js.map +1 -0
  50. package/dist/emit.d.ts +8 -0
  51. package/dist/emit.d.ts.map +1 -0
  52. package/dist/emit.js +43 -0
  53. package/dist/emit.js.map +1 -0
  54. package/dist/errors.d.ts +22 -0
  55. package/dist/errors.d.ts.map +1 -0
  56. package/dist/errors.js +39 -0
  57. package/dist/errors.js.map +1 -0
  58. package/dist/firmware-class.d.ts +69 -0
  59. package/dist/firmware-class.d.ts.map +1 -0
  60. package/dist/firmware-class.js +20 -0
  61. package/dist/firmware-class.js.map +1 -0
  62. package/dist/fixtures/circuits.d.ts +1721 -0
  63. package/dist/fixtures/circuits.d.ts.map +1 -0
  64. package/dist/fixtures/circuits.js +13404 -0
  65. package/dist/fixtures/circuits.js.map +1 -0
  66. package/dist/fixtures/expected.d.ts +257 -0
  67. package/dist/fixtures/expected.d.ts.map +1 -0
  68. package/dist/fixtures/expected.js +311 -0
  69. package/dist/fixtures/expected.js.map +1 -0
  70. package/dist/fixtures/index.d.ts +4 -0
  71. package/dist/fixtures/index.d.ts.map +1 -0
  72. package/dist/fixtures/index.js +8 -0
  73. package/dist/fixtures/index.js.map +1 -0
  74. package/dist/fixtures/registry.d.ts +52 -0
  75. package/dist/fixtures/registry.d.ts.map +1 -0
  76. package/dist/fixtures/registry.js +341 -0
  77. package/dist/fixtures/registry.js.map +1 -0
  78. package/dist/generic-tube-fit.d.ts +12 -0
  79. package/dist/generic-tube-fit.d.ts.map +1 -0
  80. package/dist/generic-tube-fit.js +45 -0
  81. package/dist/generic-tube-fit.js.map +1 -0
  82. package/dist/grounded-clock-supply.d.ts +13 -0
  83. package/dist/grounded-clock-supply.d.ts.map +1 -0
  84. package/dist/grounded-clock-supply.js +45 -0
  85. package/dist/grounded-clock-supply.js.map +1 -0
  86. package/dist/identify.d.ts +50 -0
  87. package/dist/identify.d.ts.map +1 -0
  88. package/dist/identify.js +319 -0
  89. package/dist/identify.js.map +1 -0
  90. package/dist/index.d.ts +10 -0
  91. package/dist/index.d.ts.map +1 -0
  92. package/dist/index.js +19 -0
  93. package/dist/index.js.map +1 -0
  94. package/dist/inert-controls.d.ts +15 -0
  95. package/dist/inert-controls.d.ts.map +1 -0
  96. package/dist/inert-controls.js +266 -0
  97. package/dist/inert-controls.js.map +1 -0
  98. package/dist/latch-seed.d.ts +53 -0
  99. package/dist/latch-seed.d.ts.map +1 -0
  100. package/dist/latch-seed.js +257 -0
  101. package/dist/latch-seed.js.map +1 -0
  102. package/dist/link.d.ts +7 -0
  103. package/dist/link.d.ts.map +1 -0
  104. package/dist/link.js +270 -0
  105. package/dist/link.js.map +1 -0
  106. package/dist/lower.d.ts +79 -0
  107. package/dist/lower.d.ts.map +1 -0
  108. package/dist/lower.js +1855 -0
  109. package/dist/lower.js.map +1 -0
  110. package/dist/netlist.d.ts +79 -0
  111. package/dist/netlist.d.ts.map +1 -0
  112. package/dist/netlist.js +4746 -0
  113. package/dist/netlist.js.map +1 -0
  114. package/dist/non-executable-clock-drivers.d.ts +8 -0
  115. package/dist/non-executable-clock-drivers.d.ts.map +1 -0
  116. package/dist/non-executable-clock-drivers.js +33 -0
  117. package/dist/non-executable-clock-drivers.js.map +1 -0
  118. package/dist/open-category.d.ts +98 -0
  119. package/dist/open-category.d.ts.map +1 -0
  120. package/dist/open-category.js +111 -0
  121. package/dist/open-category.js.map +1 -0
  122. package/dist/over-driven-node.d.ts +33 -0
  123. package/dist/over-driven-node.d.ts.map +1 -0
  124. package/dist/over-driven-node.js +188 -0
  125. package/dist/over-driven-node.js.map +1 -0
  126. package/dist/part-catalog.d.ts +7 -0
  127. package/dist/part-catalog.d.ts.map +1 -0
  128. package/dist/part-catalog.js +6639 -0
  129. package/dist/part-catalog.js.map +1 -0
  130. package/dist/part-number.d.ts +32 -0
  131. package/dist/part-number.d.ts.map +1 -0
  132. package/dist/part-number.js +80 -0
  133. package/dist/part-number.js.map +1 -0
  134. package/dist/partition.d.ts +7 -0
  135. package/dist/partition.d.ts.map +1 -0
  136. package/dist/partition.js +242 -0
  137. package/dist/partition.js.map +1 -0
  138. package/dist/port-full-scale.d.ts +70 -0
  139. package/dist/port-full-scale.d.ts.map +1 -0
  140. package/dist/port-full-scale.js +235 -0
  141. package/dist/port-full-scale.js.map +1 -0
  142. package/dist/pot-orientation.d.ts +114 -0
  143. package/dist/pot-orientation.d.ts.map +1 -0
  144. package/dist/pot-orientation.js +551 -0
  145. package/dist/pot-orientation.js.map +1 -0
  146. package/dist/power-domain-control.d.ts +40 -0
  147. package/dist/power-domain-control.d.ts.map +1 -0
  148. package/dist/power-domain-control.js +142 -0
  149. package/dist/power-domain-control.js.map +1 -0
  150. package/dist/proxy-declaration.d.ts +121 -0
  151. package/dist/proxy-declaration.d.ts.map +1 -0
  152. package/dist/proxy-declaration.js +50 -0
  153. package/dist/proxy-declaration.js.map +1 -0
  154. package/dist/registry.d.ts +323 -0
  155. package/dist/registry.d.ts.map +1 -0
  156. package/dist/registry.js +192 -0
  157. package/dist/registry.js.map +1 -0
  158. package/dist/sparse-schedule.d.ts +65 -0
  159. package/dist/sparse-schedule.d.ts.map +1 -0
  160. package/dist/sparse-schedule.js +421 -0
  161. package/dist/sparse-schedule.js.map +1 -0
  162. package/dist/speaker-load.d.ts +38 -0
  163. package/dist/speaker-load.d.ts.map +1 -0
  164. package/dist/speaker-load.js +97 -0
  165. package/dist/speaker-load.js.map +1 -0
  166. package/dist/stage-coverage.d.ts +21 -0
  167. package/dist/stage-coverage.d.ts.map +1 -0
  168. package/dist/stage-coverage.js +124 -0
  169. package/dist/stage-coverage.js.map +1 -0
  170. package/dist/stamp-partition.d.ts +314 -0
  171. package/dist/stamp-partition.d.ts.map +1 -0
  172. package/dist/stamp-partition.js +472 -0
  173. package/dist/stamp-partition.js.map +1 -0
  174. package/dist/supply-reference.d.ts +19 -0
  175. package/dist/supply-reference.d.ts.map +1 -0
  176. package/dist/supply-reference.js +66 -0
  177. package/dist/supply-reference.js.map +1 -0
  178. package/dist/supply-short.d.ts +32 -0
  179. package/dist/supply-short.d.ts.map +1 -0
  180. package/dist/supply-short.js +118 -0
  181. package/dist/supply-short.js.map +1 -0
  182. package/dist/supply-stamps.d.ts +51 -0
  183. package/dist/supply-stamps.d.ts.map +1 -0
  184. package/dist/supply-stamps.js +363 -0
  185. package/dist/supply-stamps.js.map +1 -0
  186. package/dist/terminal-role.d.ts +109 -0
  187. package/dist/terminal-role.d.ts.map +1 -0
  188. package/dist/terminal-role.js +46 -0
  189. package/dist/terminal-role.js.map +1 -0
  190. package/dist/terminal-roles.d.ts +59 -0
  191. package/dist/terminal-roles.d.ts.map +1 -0
  192. package/dist/terminal-roles.js +92 -0
  193. package/dist/terminal-roles.js.map +1 -0
  194. package/dist/transformer.d.ts +181 -0
  195. package/dist/transformer.d.ts.map +1 -0
  196. package/dist/transformer.js +476 -0
  197. package/dist/transformer.js.map +1 -0
  198. package/dist/types.d.ts +3157 -0
  199. package/dist/types.d.ts.map +1 -0
  200. package/dist/types.js +11 -0
  201. package/dist/types.js.map +1 -0
  202. package/dist/unbounded-operating-point.d.ts +35 -0
  203. package/dist/unbounded-operating-point.d.ts.map +1 -0
  204. package/dist/unbounded-operating-point.js +181 -0
  205. package/dist/unbounded-operating-point.js.map +1 -0
  206. package/dist/unexecuted-region.d.ts +3 -0
  207. package/dist/unexecuted-region.d.ts.map +1 -0
  208. package/dist/unexecuted-region.js +122 -0
  209. package/dist/unexecuted-region.js.map +1 -0
  210. package/dist/unimplemented-control-role.d.ts +3 -0
  211. package/dist/unimplemented-control-role.d.ts.map +1 -0
  212. package/dist/unimplemented-control-role.js +61 -0
  213. package/dist/unimplemented-control-role.js.map +1 -0
  214. package/dist/unreachable-output.d.ts +3 -0
  215. package/dist/unreachable-output.d.ts.map +1 -0
  216. package/dist/unreachable-output.js +97 -0
  217. package/dist/unreachable-output.js.map +1 -0
  218. package/dist/unreadable-terminal-role.d.ts +67 -0
  219. package/dist/unreadable-terminal-role.d.ts.map +1 -0
  220. package/dist/unreadable-terminal-role.js +409 -0
  221. package/dist/unreadable-terminal-role.js.map +1 -0
  222. package/dist/unverified-pinout.d.ts +27 -0
  223. package/dist/unverified-pinout.d.ts.map +1 -0
  224. package/dist/unverified-pinout.js +121 -0
  225. package/dist/unverified-pinout.js.map +1 -0
  226. package/package.json +75 -5
@@ -0,0 +1,97 @@
1
+ // A program that reaches its output port with nothing at all.
2
+ //
3
+ // **The question a builder actually asks, and the one nothing answered.** Wire a guitar signal
4
+ // into a chip the registry cannot model -- an omitted codec, a DSP declared as a pin shell, a
5
+ // package whose analog pins the packet never traced -- and the chip lowers to `open`. The
6
+ // compiled program is then byte-for-byte the circuit *without* it: the stages before it stamp
7
+ // exactly as they did, the document is `ok`, and the output jack sits on a node no live block
8
+ // produces. `ic-not-executed` names the chip; nothing named the consequence.
9
+ //
10
+ // **What this proves, and it is a proof rather than an inference.** `link.ts` already computes
11
+ // which blocks reach the output (`blocksReachingOutput`) and emits only those into `order`. A
12
+ // program whose `order` is empty executes no block under any runtime, at any control position,
13
+ // at any sample rate. It cannot produce audio. That is a statement about the emitted program,
14
+ // not a claim about a graph.
15
+ //
16
+ // **Why this is not path-finding, which was the obvious design and is the wrong one.**
17
+ // `scripts/report-signal-path.ts` walks input to output over device conduction, and its own
18
+ // header records the trap: a non-inverting op-amp stage has no passive route from its signal
19
+ // input to its output, so `vemuram-jan-ray`, `mxr-micro-amp` and `jhs-morning-glory` all read
20
+ // "no path" while rendering perfectly well. A warning built on that graph would fire on working
21
+ // pedals, and a warning that cries wolf on a working pedal is worse than no warning. The first
22
+ // attempt here made a smaller version of the same mistake -- comparing `ports.output`, a global
23
+ // node id, against the node ids inside stamps -- and flagged 42 of 118 packets including
24
+ // `mxr-micro-amp` and `mxr-carbon-copy`. Block node ids are block-local; the comparison was
25
+ // meaningless. Measured against the emitted `order` instead, the false-alarm count is zero.
26
+ //
27
+ // **What it does not prove.** Not that a program with a non-empty `order` is audible: a block
28
+ // can execute and still be attenuated to nothing, which is `report-signal-path.ts`'s question
29
+ // and stays there. And a live `macro` block whose write-back reaches no block claiming the
30
+ // output port is *not* caught, because `blocksReachingOutput` treats every macro as live by
31
+ // construction; `boss-ps-2` and `boss-tu-3` are in that position and are deliberately left
32
+ // alone rather than flagged on a rule this cannot back.
33
+ //
34
+ // **Warning, not refusal**, for the reason the repository settles this trade every time: four
35
+ // corpus packets are in this state today (`boss-bf-3`, `boss-hr-2`, `boss-oc-3`, `boss-st-2`,
36
+ // each a digital pedal whose audio path crosses a chip that is not modelled) and refusing them
37
+ // would trade a compiling packet for a stricter gate. `boss-bf-3` is the one to look at first:
38
+ // it compiles **148 blocks and executes none of them**.
39
+ import { deviceCountByNode } from "./device-laws.js";
40
+ /**
41
+ * How much of the document is wired, as a sentence, or empty when it is wired normally.
42
+ *
43
+ * **The number that explains the block count.** `boss-bf-3` compiles 148 blocks of one stamp each
44
+ * and runs none, and the block count alone reads like a compiler defect. It is not: its 166
45
+ * devices declare 458 terminals across 418 non-ground nodes and only **10** of those nodes are
46
+ * touched by more than one device. A node one device touches is not a net, so the document is a
47
+ * terminalized parts list rather than a circuit, which is exactly the graph coverage its own
48
+ * README claims (`terminalized-source-shell`).
49
+ *
50
+ * Reported as a measurement with no threshold and no verdict, because the corpus has a spread
51
+ * rather than two classes: the median packet shares 93.3% of its non-ground nodes, and the tail
52
+ * runs 2.1% (`boss-oc-3`), 2.4% (`boss-bf-3`), 4.8% (`boss-bf-2`), 11.5% (`boss-dd-5`). Naming a
53
+ * cutoff would invent a boundary the data does not have; the reader can see the ratio.
54
+ */
55
+ function wiringSummary(netlist) {
56
+ const counts = deviceCountByNode(netlist);
57
+ let nets = 0;
58
+ let shared = 0;
59
+ for (const [node, devices] of counts) {
60
+ if (node === 0) {
61
+ continue;
62
+ }
63
+ nets += 1;
64
+ if (devices >= 2) {
65
+ shared += 1;
66
+ }
67
+ }
68
+ if (nets === 0) {
69
+ return "";
70
+ }
71
+ const terminals = netlist.devices.reduce((total, device) => total + device.nodes.length, 0);
72
+ return (` Its ${netlist.devices.length} devices declare ${terminals} terminals across ${nets} ` +
73
+ `non-ground nodes, and ${shared} of those nodes are touched by more than one device: a node ` +
74
+ "only one device touches is not a net, so a low share here means the document's " +
75
+ "connectivity was never captured rather than that a component is missing a model.");
76
+ }
77
+ export function findUnreachableOutput(program, netlist) {
78
+ if (program.order.length > 0) {
79
+ return [];
80
+ }
81
+ const macros = program.blocks.filter((block) => block.kind === "macro" || block.kind === "composed").length;
82
+ return [
83
+ {
84
+ code: "output-port-unreachable",
85
+ device: null,
86
+ detail: `no block reaches the output port, so this program's execution order is empty: ` +
87
+ `${program.blocks.length} block${program.blocks.length === 1 ? " was" : "s were"} compiled ` +
88
+ `(${macros} of them DSP blocks) and none of them runs. It can produce no audio at any ` +
89
+ "control position. The usual cause is a component on the signal path that carries no " +
90
+ "executable model, which an `ic-not-executed` or `electrically-isolated-ic` warning " +
91
+ "beside this one will name: the stages around it still compile, so the document looks " +
92
+ "whole while the path to the jack is severed." +
93
+ wiringSummary(netlist),
94
+ },
95
+ ];
96
+ }
97
+ //# sourceMappingURL=unreachable-output.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"unreachable-output.js","sourceRoot":"","sources":["../src/unreachable-output.ts"],"names":[],"mappings":"AAAA,8DAA8D;AAC9D,EAAE;AACF,+FAA+F;AAC/F,8FAA8F;AAC9F,0FAA0F;AAC1F,8FAA8F;AAC9F,8FAA8F;AAC9F,6EAA6E;AAC7E,EAAE;AACF,+FAA+F;AAC/F,8FAA8F;AAC9F,+FAA+F;AAC/F,8FAA8F;AAC9F,6BAA6B;AAC7B,EAAE;AACF,uFAAuF;AACvF,4FAA4F;AAC5F,6FAA6F;AAC7F,8FAA8F;AAC9F,gGAAgG;AAChG,+FAA+F;AAC/F,gGAAgG;AAChG,yFAAyF;AACzF,4FAA4F;AAC5F,4FAA4F;AAC5F,EAAE;AACF,8FAA8F;AAC9F,8FAA8F;AAC9F,2FAA2F;AAC3F,4FAA4F;AAC5F,2FAA2F;AAC3F,wDAAwD;AACxD,EAAE;AACF,8FAA8F;AAC9F,8FAA8F;AAC9F,+FAA+F;AAC/F,+FAA+F;AAC/F,wDAAwD;AACxD,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAGlD;;;;;;;;;;;;;;GAcG;AACH,SAAS,aAAa,CAAC,OAAgB;IACtC,MAAM,MAAM,GAAG,iBAAiB,CAAC,OAAO,CAAC,CAAC;IAC1C,IAAI,IAAI,GAAG,CAAC,CAAC;IACb,IAAI,MAAM,GAAG,CAAC,CAAC;IACf,KAAK,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,MAAM,EAAE,CAAC;QACtC,IAAI,IAAI,KAAK,CAAC,EAAE,CAAC;YAChB,SAAS;QACV,CAAC;QACD,IAAI,IAAI,CAAC,CAAC;QACV,IAAI,OAAO,IAAI,CAAC,EAAE,CAAC;YAClB,MAAM,IAAI,CAAC,CAAC;QACb,CAAC;IACF,CAAC;IACD,IAAI,IAAI,KAAK,CAAC,EAAE,CAAC;QAChB,OAAO,EAAE,CAAC;IACX,CAAC;IACD,MAAM,SAAS,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,CACvC,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,CAAC,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,MAAM,EAC9C,CAAC,CACD,CAAC;IACF,OAAO,CACN,QAAQ,OAAO,CAAC,OAAO,CAAC,MAAM,oBAAoB,SAAS,qBAAqB,IAAI,GAAG;QACvF,yBAAyB,MAAM,8DAA8D;QAC7F,iFAAiF;QACjF,kFAAkF,CAClF,CAAC;AACH,CAAC;AAED,MAAM,UAAU,qBAAqB,CACpC,OAAgB,EAChB,OAAgB;IAEhB,IAAI,OAAO,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC9B,OAAO,EAAE,CAAC;IACX,CAAC;IACD,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,CACnC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,KAAK,OAAO,IAAI,KAAK,CAAC,IAAI,KAAK,UAAU,CAC9D,CAAC,MAAM,CAAC;IACT,OAAO;QACN;YACC,IAAI,EAAE,yBAAyB;YAC/B,MAAM,EAAE,IAAI;YACZ,MAAM,EACL,gFAAgF;gBAChF,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,SAAS,OAAO,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,YAAY;gBAC5F,IAAI,MAAM,6EAA6E;gBACvF,sFAAsF;gBACtF,qFAAqF;gBACrF,uFAAuF;gBACvF,8CAA8C;gBAC9C,aAAa,CAAC,OAAO,CAAC;SACvB;KACD,CAAC;AACH,CAAC"}
@@ -0,0 +1,67 @@
1
+ import type { Device, LawedNetlist, NonExecutableSupportShellWarning, UnreadableTerminalRoleWarning } from "./types";
2
+ /**
3
+ * A component declared as one transistor that is really **several devices in one shell**.
4
+ *
5
+ * `boss-ce-1` declares `SRC_CE1_Q3_Q6_D01_D05_CLOCK_BRIDGE_SUPPORT` as `kind: bjt` with
6
+ * **nineteen** terminals, standing for four transistors and five diodes, and
7
+ * `SRC_CE1_Q15_Q16_Q17_POWER_REGULATOR` as `kind: bjt` with eight, standing for three. Stamping
8
+ * either as a single transistor invents a device: the packet's own `Description` says "Exact
9
+ * physical package C/B/E orientation … remain unresolved", so there is no base, collector or
10
+ * emitter to bind, and declaration order supplies one anyway.
11
+ *
12
+ * **Two conditions, and the conjunction is what makes this safe.**
13
+ *
14
+ * - *The law cannot consume the terminals.* A `bjt`/`fet` law binds exactly three nodes, so a
15
+ * component declaring more has terminals no stamp can reach.
16
+ * - *And its roles cannot be read.* This is the discriminator. Measured across the corpus, 20
17
+ * devices declare more terminals than their kind's law consumes, and almost all are
18
+ * legitimate: 14 are multi-junction diodes (bridges, dual tube rectifiers) that
19
+ * `diodeJunctions` places by role, and `moogerfooger-mf-102`'s four `MPQ3906` sections are a
20
+ * quad transistor array declaring `collector`/`base`/`emitter` plus two unused package pins,
21
+ * which read cleanly. Only `boss-ce-1`'s two shells fail both tests.
22
+ *
23
+ * **Why not read `PartNumber`.** These shells announce themselves there —
24
+ * `"Q3/Q4 2SA493; Q5/Q6 2SC536F; D01-D05 1S1555"` is plainly several parts — and splitting that
25
+ * string on its separators is exactly the prose parsing this repository forbids for a
26
+ * classification decision. Terminal count against a law's fixed arity, and whether a closed role
27
+ * vocabulary reads, are structural facts about the document instead.
28
+ *
29
+ * Deliberately not extended to `opamp`: an op-amp package legitimately declares more terminals
30
+ * than its law binds (supplies, a second section), so arity says nothing there. `boss-dm-3`'s
31
+ * 8-pin `IC1` is that case and is a registry-expansion question, not a shell.
32
+ */
33
+ export declare function isMultiDeviceTransistorShell(device: Device): boolean;
34
+ export declare function findUnreadableTerminalRoles(lawed: LawedNetlist): readonly UnreadableTerminalRoleWarning[];
35
+ /**
36
+ * The multi-device shells stage 3 resolved to `open`, so a packet is told the component was
37
+ * dropped rather than silently losing it.
38
+ *
39
+ * Paired with `isMultiDeviceTransistorShell`'s use in `resolveDevice`: that decides the law, this
40
+ * reports it. Conjoined with the law so a device the predicate matches but some other rule opened
41
+ * — an isolated IC, a charge pump — is not attributed to this one.
42
+ */
43
+ export declare function findMultiDeviceShells(lawed: LawedNetlist): readonly NonExecutableSupportShellWarning[];
44
+ /**
45
+ * An `opamp` whose own device-class law cannot bind its terminals, so a registry `sections` entry
46
+ * is the only thing that can place them.
47
+ *
48
+ * **The direction matters, and it is the OTA rule inverted.** `sectionDevices` records that for an
49
+ * OTA "the registry only wins when it can bind by role", because an OTA carries a correct
50
+ * role-bound device-class law and a positional guess from an entry written for other spellings is
51
+ * strictly worse. An op-amp is in the same position, so the same principle gives the mirror rule:
52
+ * **the device-class law wins wherever it can read the terminals, and the registry is consulted
53
+ * only where it cannot.** That keeps every ordinary op-amp exactly where it is.
54
+ *
55
+ * Measured over the corpus: 113 `opamp` devices declare three terminals, 195 declare five, four
56
+ * declare seven (`LM308`/`OP07CP` balance pins, `HA1457W` compensation pins) and **one** declares
57
+ * eight -- `boss-dm-3`'s `IC1`, a whole `NJM4558DD` dual package as a single component. Only that
58
+ * one fails to bind, because it names two non-inverting inputs and `uniqueRoleIndex` refuses an
59
+ * ambiguous read. Stamped as one op-amp it put both inputs on node 4 and drove node 10, which is
60
+ * *both* sections' non-inverting input.
61
+ *
62
+ * Widening `mayCarryRegistrySections` to every `opamp` was tried on 2026-09-02 and measured wrong:
63
+ * `boss-dm-3` itself became `unsupported` and 14 other packets' programs moved. This predicate is
64
+ * why the fix is scoped rather than a kind test.
65
+ */
66
+ export declare function opampNeedsRegistrySections(device: Device): boolean;
67
+ //# sourceMappingURL=unreadable-terminal-role.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"unreadable-terminal-role.d.ts","sourceRoot":"","sources":["../src/unreadable-terminal-role.ts"],"names":[],"mappings":"AAmCA,OAAO,KAAK,EACX,MAAM,EACN,YAAY,EACZ,gCAAgC,EAChC,6BAA6B,EAC7B,MAAM,SAAS,CAAC;AAwDjB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,wBAAgB,4BAA4B,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAqBpE;AA8HD,wBAAgB,2BAA2B,CAC1C,KAAK,EAAE,YAAY,GACjB,SAAS,6BAA6B,EAAE,CAqI1C;AAED;;;;;;;GAOG;AACH,wBAAgB,qBAAqB,CACpC,KAAK,EAAE,YAAY,GACjB,SAAS,gCAAgC,EAAE,CAuB7C;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,0BAA0B,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAQlE"}
@@ -0,0 +1,409 @@
1
+ // A device that **named** its terminals in a spelling no resolver recognises, and was therefore
2
+ // wired by declaration order.
3
+ //
4
+ // **The defect class this closes.** Four asymmetric-device resolvers in `lower.ts` -- transistor,
5
+ // op-amp, two-terminal diode, supply -- fall back to declaration order when they cannot read a
6
+ // terminal role. That fallback is correct for a document of bare lugs, which carries no
7
+ // orientation evidence at all. It is a *guess* for a document that named its terminals in a
8
+ // vocabulary the resolver does not speak, and the guess is silent: the packet compiles `ok`,
9
+ // renders, and sounds like something. `bjtTerminals`' own comment records why that matters --
10
+ // 449 of the corpus's 490 transistors do not declare their control terminal first, so positional
11
+ // order exchanges base and collector on nearly every transistor there is.
12
+ //
13
+ // **Why a warning and not a refusal.** The 2026-09-02 census (R1 in
14
+ // `thoughts/shared/plans/archive/2026-08-31-v2-complexity-reduction-plan.md`) measured the residue after
15
+ // the true synonyms were absorbed: five packets that compile today carry a device this would
16
+ // refuse, and all five render. `CompileWarning`'s own contract is the rule for exactly this
17
+ // situation -- "things that compiled but will not behave. A warning never blocks a program ... but
18
+ // it must not be silent either" -- and this repository's standing principle is not to trade a
19
+ // working product for a stricter gate. So the silent class becomes *named* here, which was the
20
+ // whole complaint, and promoting these rows to refusals is a later layer, once the named rows are
21
+ // corrected at the source.
22
+ //
23
+ // **What this does not claim.** A warning here says the resolver could not read the declared
24
+ // roles and fell back to position. It does **not** say the resulting wiring is wrong: declaration
25
+ // order may coincide with the right answer, and on a symmetric device it always does. The
26
+ // `orientationFreeRoles` escape hatch removes the cases where the fallback is the document's
27
+ // intended reading, so what remains is "a stated fact this pipeline could not use" -- which is
28
+ // the same bar `report-source-coverage.ts` applies on the property side.
29
+ import { orientationFreeRoles, supplyDriveRoles, } from "./terminal-roles.js";
30
+ import { foldToken } from "./registry.js";
31
+ import { otaPackageOrderAssumed } from "./device-laws.js";
32
+ import { optocouplerBinding } from "./lower.js";
33
+ /**
34
+ * The one terminal index whose role is in `accepted`, or null when none or several are.
35
+ *
36
+ * Mirrors `lower.ts`'s `uniqueRoleIndex` deliberately, including its refusal of an ambiguous
37
+ * match: a device declaring two terminals that both read as one slot is more than one device in
38
+ * one component, and the resolver falls back for that reason too.
39
+ */
40
+ function unique(roles, accepted) {
41
+ const found = roles.flatMap((role, index) => role !== null && accepted.has(role) ? [index] : []);
42
+ return found.length === 1 ? (found[0] ?? null) : null;
43
+ }
44
+ const allSlotsRead = (roles, slots) => slots.every((slot) => unique(roles, slot) !== null);
45
+ /**
46
+ * The declared roles a resolver was given and could not place: everything the document named,
47
+ * minus the tokens that deliberately state no orientation. Empty means there was nothing to
48
+ * misread — either the document named nothing, or what it named carries no electrode claim.
49
+ */
50
+ function unplaceableRoles(roles, slots) {
51
+ const named = roles.filter((role) => role !== null);
52
+ if (named.length === 0 || allSlotsRead(roles, slots)) {
53
+ return [];
54
+ }
55
+ return named.filter((role) => !orientationFreeRoles.has(role));
56
+ }
57
+ /** A transistor whose declared roles do not give exactly one full electrode triple. */
58
+ function transistorDeclaredRolesMissing(device) {
59
+ // Fewer than three terminals is not a transistor this law can bind at all, and a device with
60
+ // none reaches no resolver.
61
+ if (device.nodes.length < 3) {
62
+ return false;
63
+ }
64
+ const declared = device.identity.declaredTerminalRoles;
65
+ const has = (role) => declared.filter((value) => value === role).length === 1;
66
+ return !((has("base") && has("collector") && has("emitter")) ||
67
+ (has("gate") && has("drain") && has("source")));
68
+ }
69
+ /**
70
+ * A component declared as one transistor that is really **several devices in one shell**.
71
+ *
72
+ * `boss-ce-1` declares `SRC_CE1_Q3_Q6_D01_D05_CLOCK_BRIDGE_SUPPORT` as `kind: bjt` with
73
+ * **nineteen** terminals, standing for four transistors and five diodes, and
74
+ * `SRC_CE1_Q15_Q16_Q17_POWER_REGULATOR` as `kind: bjt` with eight, standing for three. Stamping
75
+ * either as a single transistor invents a device: the packet's own `Description` says "Exact
76
+ * physical package C/B/E orientation … remain unresolved", so there is no base, collector or
77
+ * emitter to bind, and declaration order supplies one anyway.
78
+ *
79
+ * **Two conditions, and the conjunction is what makes this safe.**
80
+ *
81
+ * - *The law cannot consume the terminals.* A `bjt`/`fet` law binds exactly three nodes, so a
82
+ * component declaring more has terminals no stamp can reach.
83
+ * - *And its roles cannot be read.* This is the discriminator. Measured across the corpus, 20
84
+ * devices declare more terminals than their kind's law consumes, and almost all are
85
+ * legitimate: 14 are multi-junction diodes (bridges, dual tube rectifiers) that
86
+ * `diodeJunctions` places by role, and `moogerfooger-mf-102`'s four `MPQ3906` sections are a
87
+ * quad transistor array declaring `collector`/`base`/`emitter` plus two unused package pins,
88
+ * which read cleanly. Only `boss-ce-1`'s two shells fail both tests.
89
+ *
90
+ * **Why not read `PartNumber`.** These shells announce themselves there —
91
+ * `"Q3/Q4 2SA493; Q5/Q6 2SC536F; D01-D05 1S1555"` is plainly several parts — and splitting that
92
+ * string on its separators is exactly the prose parsing this repository forbids for a
93
+ * classification decision. Terminal count against a law's fixed arity, and whether a closed role
94
+ * vocabulary reads, are structural facts about the document instead.
95
+ *
96
+ * Deliberately not extended to `opamp`: an op-amp package legitimately declares more terminals
97
+ * than its law binds (supplies, a second section), so arity says nothing there. `boss-dm-3`'s
98
+ * 8-pin `IC1` is that case and is a registry-expansion question, not a shell.
99
+ */
100
+ export function isMultiDeviceTransistorShell(device) {
101
+ if (device.kind !== "bjt" &&
102
+ device.kind !== "jfet" &&
103
+ device.kind !== "mosfet") {
104
+ return false;
105
+ }
106
+ if (device.nodes.length <= 3) {
107
+ return false;
108
+ }
109
+ // **The declared triple, not a table of spellings.** This predicate decides the *program* --
110
+ // a shell is opened rather than stamped -- so it was the last program-affecting reader of
111
+ // `transistorControlRoles` and its two siblings -- now deleted, since diagnostics were their
112
+ // only other reader and it needed neither. Every device this distinguishes already declares
113
+ // its electrodes, which is what makes the swap behaviour-neutral: `moogerfooger-mf-102`'s
114
+ // four `MPQ3906` sections declare `collector`/`base`/`emitter` beside two unused package
115
+ // pins, `fulltone-ocd`'s and `mxr-carbon-copy`'s MOSFETs declare `drain`/`gate`/`source`
116
+ // beside `bulk`, and `boss-ce-1`'s two shells declare nothing at all -- which is exactly the
117
+ // distinction being drawn.
118
+ return transistorDeclaredRolesMissing(device);
119
+ }
120
+ /**
121
+ * The slot sets each law's resolver reads, or null for a law this check does not cover.
122
+ *
123
+ * Only the four asymmetric resolvers that **fall back to declaration order** are listed. A
124
+ * resolver that already refuses on an unreadable role needs nothing here -- the triode, the
125
+ * pentode, the tube diode, the transformer and the multi-junction diode all name the offending
126
+ * token themselves. Deliberately absent for a different reason: a **pot**, whose unresolved
127
+ * orientation is a quiet-reference hint rather than a topology decision ("an unresolved pot,
128
+ * never a wrong one" -- `lowerRegion`'s own parameter docs); a **switch**, where the corpus
129
+ * routinely leaves the common terminal unnamed and `switchPoles` treats the first contact as
130
+ * common by design; and an **OTA**, whose binding permits a null bias pin outright and whose
131
+ * package fallback requires eight all-null roles, so a named OTA never reaches it.
132
+ */
133
+ function slotsForLaw(law, device) {
134
+ // `bjt`, `fet` and `ideal-opamp` are handled by `declaredRolesMissing` instead: since
135
+ // 2026-09-03 their resolvers read the declared `role` rather than the terminal name, so
136
+ // checking the name vocabulary here would report a device as readable that the resolver then
137
+ // refuses or wires positionally -- the silent fallback this warning exists to catch. Keeping
138
+ // a warning on a different vocabulary from the resolver it guards is how that bug was
139
+ // introduced once already, in this same file, on the same day.
140
+ if (law === "bjt" || law === "fet" || law === "ideal-opamp") {
141
+ return null;
142
+ }
143
+ // A two-terminal diode is handled by `diodeDeclaredRolesMissing` for the same reason: its
144
+ // resolver reads the declared `anode`/`cathode`, so a name check here would call a device
145
+ // readable that the resolver then orients by declaration order.
146
+ if (law === "diode" && device.nodes.length === 2) {
147
+ return null;
148
+ }
149
+ // A rail declares one terminal and means "against ground", which is not a polarity
150
+ // question -- `supplyTerminals` returns early for it and reads no role at all.
151
+ if ((law === "voltage-source" || law === "ac-source") &&
152
+ device.nodes.length > 1) {
153
+ return [supplyDriveRoles];
154
+ }
155
+ return null;
156
+ }
157
+ /**
158
+ * `supplyTerminals` resolves from **either** end alone -- one named terminal beside an unlabelled
159
+ * lug is enough, and requiring both would discard the evidence in a supply declaring `positive`
160
+ * next to a bare pin. So its readable test is a disjunction where the other three are
161
+ * conjunctions, and treating it as a conjunction here would warn about supplies the resolver
162
+ * orients correctly.
163
+ *
164
+ * **The return half of the disjunction is gone**, along with `supplyReturnRoles`. Emptying that
165
+ * set left the corpus's `terminal-role-unreadable` count unchanged at 34, and removing its slot
166
+ * outright left it unchanged again -- so no corpus supply was being spared a warning by a
167
+ * `negative`/`neutral`/`return` *name*. Its declared counterpart is what `supplyTerminals` reads.
168
+ */
169
+ function supplyReadable(roles) {
170
+ return roles.some((role) => role !== null && supplyDriveRoles.has(role));
171
+ }
172
+ /**
173
+ * The three-terminal roles a `bjt`/`fet` resolver needs, and whether the device declares them.
174
+ *
175
+ * Kept beside the name-based check rather than merged with it, because the two ask different
176
+ * questions now: this one asks what the *source declared*, which is what `lower.ts` reads.
177
+ */
178
+ /**
179
+ * A switch with three or more contacts that declares no pole, so `switchPoles` takes the first
180
+ * contact as the common.
181
+ *
182
+ * **Two contacts are exempt, and the exemption is measured rather than assumed.** A closed contact
183
+ * pair is a symmetric conductance, so which terminal is called the pole cannot change the circuit
184
+ * -- verified by swapping the two terminals of `earthquaker-devices-plumes`'s `SW` and diffing the
185
+ * program: the only difference is the stamp's `a` and `b` fields exchanging, `{"a":25,"b":0}` for
186
+ * `{"a":0,"b":25}`. The digest moves and the circuit does not, which is the one case where the
187
+ * digest gate reports a difference that is not there.
188
+ *
189
+ * At three contacts it matters: the pole is the node every throw hangs off, and choosing the wrong
190
+ * one rewires the switch. 118 corpus switches name what each contact *connects to* -- `effect`,
191
+ * `bypass`, `rectifier_output` -- which says nothing about which is the pole, and 32 of those have
192
+ * three or more contacts.
193
+ */
194
+ function switchPoleUnreadable(device) {
195
+ const declared = device.identity.declaredTerminalRoles;
196
+ if (declared.some((role) => role === "common")) {
197
+ return false;
198
+ }
199
+ // The name rung this used to mirror is gone from `switchPoles` along with
200
+ // `switchCommonRoles`, so the declared role above is the whole test. It stays worth
201
+ // recording that mirroring mattered: checking only the declaration once reported 62
202
+ // switches, and its first two examples had a terminal literally named `common`, which the
203
+ // compiler was still reading -- a warning naming a mechanism the compiler did not use is
204
+ // worse than none.
205
+ // Contacts only: a `coil` or `pin` terminal is not part of the mechanism's contact set, and a
206
+ // document declaring neither still has every terminal to choose a pole from.
207
+ const contacts = declared.some((role) => role !== null)
208
+ ? declared.filter((role) => role === "throw").length
209
+ : device.nodes.length;
210
+ return contacts >= 3;
211
+ }
212
+ /**
213
+ * A two-terminal diode that declares no orientation, so `diodeTerminals` takes its direction from
214
+ * declaration order.
215
+ *
216
+ * **`end`/`end` is the case this exists for.** Core's `end` means two interchangeable ends, which
217
+ * is true of a resistor and false of a diode: a diode has a direction, so `end`/`end` says the
218
+ * source did not state it rather than that there is nothing to state. 13 corpus diodes are in
219
+ * that position, and reversing one of them moves the program — measured by mutation, in a review
220
+ * that found this while `orientationFreeRoles` was keeping the warning quiet about it.
221
+ */
222
+ function diodeDeclaredRolesMissing(device) {
223
+ const declared = device.identity.declaredTerminalRoles;
224
+ return !(declared.includes("anode") && declared.includes("cathode"));
225
+ }
226
+ /** An op-amp whose declared roles do not give exactly one of each signal pin. */
227
+ function opampDeclaredRolesMissing(device) {
228
+ const declared = device.identity.declaredTerminalRoles;
229
+ return !["nonInverting", "inverting", "output"].every((role) => declared.filter((value) => value === role).length === 1);
230
+ }
231
+ export function findUnreadableTerminalRoles(lawed) {
232
+ const warnings = [];
233
+ // Read the law rather than `device.kind`, because a multi-section part has already become
234
+ // one device per section by this stage, with its roles rewritten to canonical ones -- so a
235
+ // dual op-amp the registry recognises is correctly wired and must not be reported here.
236
+ const lawByDevice = new Map(lawed.resolutions.flatMap((resolution) => resolution.outcome === "law"
237
+ ? [[resolution.device, resolution.law.kind]]
238
+ : []));
239
+ for (const device of lawed.netlist.devices) {
240
+ const law = lawByDevice.get(device.id);
241
+ if (law === undefined) {
242
+ continue;
243
+ }
244
+ if (law === "selector") {
245
+ if (switchPoleUnreadable(device)) {
246
+ const named = device.identity.terminalRoles
247
+ .filter((role) => role !== null)
248
+ .map((role) => `"${role}"`);
249
+ warnings.push({
250
+ code: "terminal-role-unreadable",
251
+ device: device.id,
252
+ detail: `switch ${device.id} declares no \`common\` among its ${device.nodes.length} ` +
253
+ "terminals' roles, so the first contact was taken as the pole and every other " +
254
+ `contact hung off it${named.length > 0 ? ` (its terminals are named ${named.join(", ")})` : ""}. ` +
255
+ "With three or more contacts the pole decides the wiring; with two it cannot.",
256
+ });
257
+ }
258
+ continue;
259
+ }
260
+ if (law === "ota") {
261
+ if (otaPackageOrderAssumed(device)) {
262
+ warnings.push({
263
+ code: "terminal-role-unreadable",
264
+ device: device.id,
265
+ detail: `OTA ${device.id} names none of its eight terminals and declares no ` +
266
+ "electrodes, so its inputs, output and bias were read as DIP-8 package " +
267
+ "order. That is a better assumption than declaration order, which puts the " +
268
+ "output on pin 3, but it is still the package's convention rather than " +
269
+ "anything this document states.",
270
+ });
271
+ }
272
+ continue;
273
+ }
274
+ if (law === "optocoupler") {
275
+ const binding = optocouplerBinding(device);
276
+ if (binding !== "declared") {
277
+ warnings.push({
278
+ code: "terminal-role-unreadable",
279
+ device: device.id,
280
+ detail: binding === "named"
281
+ ? `optocoupler ${device.id} declares no anode or cell ends, so its LED ` +
282
+ "direction was taken from its terminals' names instead. The wiring is " +
283
+ "right and the evidence is prose: declaring `anode` and two `end` " +
284
+ "roles states the same fact in a form nothing has to spell-match."
285
+ : `optocoupler ${device.id} declares no roles and names none its ` +
286
+ "resolver recognises, so its LED and cell were taken in declaration " +
287
+ "order. An LED has a direction and the source did not state one.",
288
+ });
289
+ }
290
+ continue;
291
+ }
292
+ if (law === "diode" && device.nodes.length === 2) {
293
+ if (diodeDeclaredRolesMissing(device)) {
294
+ const named = device.identity.terminalRoles
295
+ .filter((role) => role !== null)
296
+ .map((role) => `"${role}"`);
297
+ warnings.push({
298
+ code: "terminal-role-unreadable",
299
+ device: device.id,
300
+ detail: `diode ${device.id} declares no anode and cathode among its terminals' roles, ` +
301
+ `so its direction was taken in declaration order instead${named.length > 0 ? ` (its terminals are named ${named.join(", ")})` : ""}. ` +
302
+ "A diode has a direction and `end` does not state one, so declaration order " +
303
+ "may or may not be the way this one conducts.",
304
+ });
305
+ }
306
+ continue;
307
+ }
308
+ if (law === "bjt" || law === "fet") {
309
+ if (transistorDeclaredRolesMissing(device)) {
310
+ const named = device.identity.terminalRoles
311
+ .filter((role) => role !== null)
312
+ .map((role) => `"${role}"`);
313
+ warnings.push({
314
+ code: "terminal-role-unreadable",
315
+ device: device.id,
316
+ detail: `${device.kind} ${device.id} does not declare a base/collector/emitter or ` +
317
+ "gate/drain/source among its terminals' roles, so they were taken in " +
318
+ `declaration order instead${named.length > 0 ? ` (its terminals are named ${named.join(", ")})` : ""}. ` +
319
+ "Declaration order may or may not be the right wiring.",
320
+ });
321
+ }
322
+ continue;
323
+ }
324
+ const slots = slotsForLaw(law, device);
325
+ if (slots === null) {
326
+ continue;
327
+ }
328
+ const roles = device.identity.terminalRoles;
329
+ // A supply resolves from **either** end alone, so its readable test is a disjunction
330
+ // where the other three are conjunctions; `unplaceableRoles` asks the conjunction.
331
+ if ((law === "voltage-source" || law === "ac-source") &&
332
+ supplyReadable(roles)) {
333
+ continue;
334
+ }
335
+ // Empty covers all three silent cases at once: nothing declared (bare lugs, where
336
+ // declaration order is all the document supports), roles that read cleanly, and roles
337
+ // that are orientation-free and so state no electrode to have missed.
338
+ const unreadable = unplaceableRoles(roles, slots);
339
+ if (unreadable.length === 0) {
340
+ continue;
341
+ }
342
+ warnings.push({
343
+ code: "terminal-role-unreadable",
344
+ device: device.id,
345
+ detail: `${device.kind} ${device.id} declares terminal role${unreadable.length === 1 ? "" : "s"} ` +
346
+ `${unreadable.map((role) => `"${role}"`).join(", ")} that its ${law} lowering ` +
347
+ "cannot place, so its terminals were taken in declaration order instead. Declaration " +
348
+ "order may or may not be the right wiring; the device's declared roles were not used.",
349
+ });
350
+ }
351
+ return warnings;
352
+ }
353
+ /**
354
+ * The multi-device shells stage 3 resolved to `open`, so a packet is told the component was
355
+ * dropped rather than silently losing it.
356
+ *
357
+ * Paired with `isMultiDeviceTransistorShell`'s use in `resolveDevice`: that decides the law, this
358
+ * reports it. Conjoined with the law so a device the predicate matches but some other rule opened
359
+ * — an isolated IC, a charge pump — is not attributed to this one.
360
+ */
361
+ export function findMultiDeviceShells(lawed) {
362
+ const opened = new Set(lawed.resolutions.flatMap((resolution) => resolution.outcome === "law" && resolution.law.kind === "open"
363
+ ? [resolution.device]
364
+ : []));
365
+ return lawed.netlist.devices.flatMap((device) => opened.has(device.id) && isMultiDeviceTransistorShell(device)
366
+ ? [
367
+ {
368
+ code: "non-executable-support-shell",
369
+ device: device.id,
370
+ detail: `${device.kind} ${device.id} declares ${device.nodes.length} terminals for a law that ` +
371
+ "binds three, and names none of them readably, so it stands for several devices " +
372
+ "rather than one. It is not executed: stamping it as a single transistor would " +
373
+ "invent a base, collector and emitter the source does not state.",
374
+ },
375
+ ]
376
+ : []);
377
+ }
378
+ /**
379
+ * An `opamp` whose own device-class law cannot bind its terminals, so a registry `sections` entry
380
+ * is the only thing that can place them.
381
+ *
382
+ * **The direction matters, and it is the OTA rule inverted.** `sectionDevices` records that for an
383
+ * OTA "the registry only wins when it can bind by role", because an OTA carries a correct
384
+ * role-bound device-class law and a positional guess from an entry written for other spellings is
385
+ * strictly worse. An op-amp is in the same position, so the same principle gives the mirror rule:
386
+ * **the device-class law wins wherever it can read the terminals, and the registry is consulted
387
+ * only where it cannot.** That keeps every ordinary op-amp exactly where it is.
388
+ *
389
+ * Measured over the corpus: 113 `opamp` devices declare three terminals, 195 declare five, four
390
+ * declare seven (`LM308`/`OP07CP` balance pins, `HA1457W` compensation pins) and **one** declares
391
+ * eight -- `boss-dm-3`'s `IC1`, a whole `NJM4558DD` dual package as a single component. Only that
392
+ * one fails to bind, because it names two non-inverting inputs and `uniqueRoleIndex` refuses an
393
+ * ambiguous read. Stamped as one op-amp it put both inputs on node 4 and drove node 10, which is
394
+ * *both* sections' non-inverting input.
395
+ *
396
+ * Widening `mayCarryRegistrySections` to every `opamp` was tried on 2026-09-02 and measured wrong:
397
+ * `boss-dm-3` itself became `unsupported` and 14 other packets' programs moved. This predicate is
398
+ * why the fix is scoped rather than a kind test.
399
+ */
400
+ export function opampNeedsRegistrySections(device) {
401
+ if (device.kind !== "opamp") {
402
+ return false;
403
+ }
404
+ // The same question `opampTerminals` asks, on the same field: a package declares two of each
405
+ // signal role and the resolver refuses it, so this predicate has to agree with that or the
406
+ // two disagree about which devices need sections.
407
+ return opampDeclaredRolesMissing(device);
408
+ }
409
+ //# sourceMappingURL=unreadable-terminal-role.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"unreadable-terminal-role.js","sourceRoot":"","sources":["../src/unreadable-terminal-role.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ import type { PartRegistry } from "./registry";
2
+ import type { CompileWarning, Netlist } from "./types";
3
+ /**
4
+ * Parts whose terminals are mapped to law slots by declaration order alone.
5
+ *
6
+ * **Measured 2026-09-03: 30 devices across 21 packets, and one of them is wrong.**
7
+ * (55 corpus devices take the positional rung; the 30 are those whose entry pinout is null
8
+ * throughout, so nothing checks the order at all.)
9
+ * `moogerfooger-mf-102`'s `U13` is a 78L05 whose three terminals are `pin1`/`pin2`/`pin3`, and the
10
+ * order the entry assumed puts the regulator's reference on the pedal's own rail: node 3 carries
11
+ * 24 devices and solves to **-4.9989 V**, so 18 of the packet's 26 active devices sit dark with
12
+ * their base-emitter junctions reverse-biased by a whole supply.
13
+ *
14
+ * **There is no connectivity rule to fall back on, and that was tested rather than assumed.**
15
+ * "The reference is the grounded terminal and the output is the busier of the rest" agrees with
16
+ * four of the corpus's named regulators, disagrees with `boss-dd-3b`'s `TA78L05F`, and cannot
17
+ * apply to `boss-rv-3`, whose 78L05 has no terminal on ground at all. A rule that fixes one
18
+ * packet and breaks another is not a rule.
19
+ *
20
+ * Nor does the corpus agree on the order itself: three packets name a 78Lxx `in, gnd, out` and
21
+ * `electro-harmonix-q-tron` names it `in, out, ground`. So this is reported rather than repaired
22
+ * -- the order has to be asserted by the entry's `pinout` or by the document's own terminal
23
+ * roles, and until one of them does, an author who writes a package's pins in a different order
24
+ * gets a different circuit with no diagnostic.
25
+ */
26
+ export declare function findUnverifiedPinoutBindings(netlist: Netlist, registry: PartRegistry): readonly CompileWarning[];
27
+ //# sourceMappingURL=unverified-pinout.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"unverified-pinout.d.ts","sourceRoot":"","sources":["../src/unverified-pinout.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAa,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1D,OAAO,KAAK,EAAE,cAAc,EAAU,OAAO,EAAE,MAAM,SAAS,CAAC;AAoE/D;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,4BAA4B,CAC3C,OAAO,EAAE,OAAO,EAChB,QAAQ,EAAE,YAAY,GACpB,SAAS,cAAc,EAAE,CAgC3B"}