Skip to content

framework: passive + diode terminals mandatory - #32

Merged
raeq merged 1 commit into
mainfrom
framework-passive-terminals-mandatory
May 19, 2026
Merged

framework: passive + diode terminals mandatory#32
raeq merged 1 commit into
mainfrom
framework-passive-terminals-mandatory

Conversation

@raeq

@raeq raeq commented May 19, 2026

Copy link
Copy Markdown
Owner

Summary

Continuation of #31 (formerly #29). The same physical-fidelity violation that left LED.cathode floating was also present on every other passive component: Resistor, Capacitor, Inductor, and every diode subclass had their terminals declared mandatory=False with the "structurally inert under graph evaluation" shortcut. Real components with dangling terminals do nothing — they sit on the BOM but contribute nothing to the circuit.

  • Resistor.t1/t2, Capacitor.t1/t2, Inductor.t1/t2, and every Diode subclass's anode/cathode now mandatory=True.
  • Six demos (backup_power, bldc_motor, dice, doorbell_protector, fan_cooling, isolated_rs232) declared BOM-only passives that were never wired. Each now wires them either to their datasheet-correct net (e.g. DoorbellProtector's flyback diode anode joining the relay's coil_minus) or as an isolated 0-Ω passthrough with dynamically_driven=True where the part is genuinely BOM-only and the voltage-only simulator can't model its behaviour. Comments at each call site explain which.
  • New regression tests:
    • tests/components/test_resistor.py, test_capacitor.py, test_inductor.pytest_terminals_are_mandatory + test_floating_*_refused_at_circuit_construction
    • tests/components/test_diode_mandatory_terminals.py (new file) — parametrized across all 7 diode subclasses

After this PR, the breadboard SVGs from #28 show every BOM-listed part connected to something — no more orphaned caps and resistors floating without jumpers.

Test plan

  • uv run pytest — 4382 passed (20 new regression tests).
  • uv run mypy src/ demos/ clean.
  • All demo docs regenerated; per-format goldens refreshed where the rewired demos produced different output.

Supersedes the auto-closed #30 (the base branch was deleted when #29/#31 merged).

Continuation of the LED.cathode regression fix (#29). Resistor,
Capacitor, Inductor, and every Diode subclass had their terminals
declared `mandatory=False` with the same "structurally inert under
graph evaluation" justification — letting demos declare BOM-only
timing / decoupling / pull-up parts without wiring them, then ship
breadboard SVGs and netlists where those parts sat orphaned.

A real resistor / capacitor / inductor / diode with a dangling
terminal does nothing. Marking the ports mandatory closes the
silent regression at the framework layer.

  - `src/components/passives/{resistor,capacitor,inductor}.py` and
    every diode subclass under `src/components/diodes/` now declare
    their terminals `mandatory=True`.
  - `tests/components/test_{resistor,capacitor,inductor}.py`:
    regression tests pin the new contract per component.
  - `tests/components/test_diode_mandatory_terminals.py` (new):
    parametrized over D1N4001 / D1N4007 / D1N4148 / D1N4728A /
    D1N4733A / D1N4742A / D1N5817.
  - Six demos (`backup_power`, `bldc_motor`, `dice`,
    `doorbell_protector`, `fan_cooling`, `isolated_rs232`) had
    declared-but-unwired passives — each now wires them either to
    their datasheet-correct net (e.g. DoorbellProtector's flyback
    diode anode joins the relay coil_minus net) or as an isolated
    0-Ω passthrough with `dynamically_driven=True` where the part
    is genuinely BOM-only and the voltage-only simulator can't
    honour its behaviour. Comments at each call site explain
    which kind.
  - Test fixtures across CLI, refdes, format-roundtrip, kicad
    import, and per-format renderer tests updated so they still
    pin down the specific error each one exists to catch without
    tripping the new mandatory-pin check first.
  - All demo docs regenerated; goldens refreshed.

After this commit the breadboard SVGs show every BOM part connected
to something — no more orphaned caps and resistors floating without
jumpers.
Copilot AI review requested due to automatic review settings May 19, 2026 16:35
@raeq
raeq merged commit 9717654 into main May 19, 2026
5 checks passed
@raeq
raeq deleted the framework-passive-terminals-mandatory branch May 19, 2026 16:37

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR continues the framework’s “physical-fidelity” enforcement by making passive-component terminals and all discrete diode terminals mandatory, preventing circuits from constructing with BOM-listed parts left electrically floating. It then updates affected demos and fixtures to explicitly wire previously-orphaned passives/diodes (either to a real net or as isolated/pass-through wiring with dynamically_driven=True where the simulator can’t model the analog behavior), and adds regression tests to lock the behavior in.

Changes:

  • Enforce mandatory=True for Resistor.t1/t2, Capacitor.t1/t2, Inductor.t1/t2, and all discrete diode anode/cathode ports.
  • Update multiple demos/exports/goldens to ensure BOM-only parts are no longer left dangling (pass-through or isolated wiring patterns).
  • Add new regression tests to ensure floating passives/diodes are refused at Circuit construction time.

Reviewed changes

Copilot reviewed 102 out of 115 changed files in this pull request and generated no comments.

Show a summary per file
File Description
src/components/passives/resistor.py Make resistor terminals mandatory to prevent dangling BOM parts.
src/components/passives/capacitor.py Make capacitor terminals mandatory; update rationale comment.
src/components/passives/inductor.py Make inductor terminals mandatory; align behavior with resistor/capacitor.
src/components/diodes/d1n4001.py Make diode terminals mandatory.
src/components/diodes/d1n4007.py Make diode terminals mandatory.
src/components/diodes/d1n4148.py Make diode terminals mandatory.
src/components/diodes/d1n4728a.py Make diode terminals mandatory.
src/components/diodes/d1n4733a.py Make diode terminals mandatory.
src/components/diodes/d1n4742a.py Make diode terminals mandatory.
src/components/diodes/d1n5817.py Make diode terminals mandatory.
tests/components/test_resistor.py Add mandatory-terminal + dangling-resistor construction regression tests.
tests/components/test_capacitor.py Add mandatory-terminal + dangling-capacitor construction regression tests.
tests/components/test_inductor.py Update existing expectations and add mandatory/dangling construction tests.
tests/components/test_diode_mandatory_terminals.py New parametrized tests covering all discrete diode subclasses.
tests/framework/test_refdes.py Update refdes-collision tests to satisfy new mandatory-terminal validation.
tests/framework/test_format_roundtrip.py Update hand-edited-format fixture to include wiring that satisfies mandatory checks.
tests/framework/export/mermaid/test_mermaid_components.py Update test circuit to include wiring/rail so mandatory resistor terminals are connected.
tests/framework/export/dot/test_dot_components.py Update test circuit to include wiring/rail so mandatory resistor terminals are connected.
tests/framework/export/bom/test_bom_components.py Update header-column test to satisfy mandatory resistor terminal requirements.
tests/framework/import_kicad/fixtures/regulator_with_named_rail.net Fixture tweak to reflect capacitor participation in the VIN net.
tests/cli/fixtures/floating_net.py Adjust fixture to pass mandatory-pin checks while still triggering FloatingNetError.
demos/dice/dice.py Wire previously BOM-only timing/pull-up passives onto a driven rail net to satisfy mandatory pins.
demos/dice/docs/Dice.* Regenerated outputs reflecting new wiring/nets.
demos/doorbell_protector/doorbell_protector.py Wire flyback diode anode + relay coil-minus net; wire BOM-only timing/decoupling passives onto VCC net.
demos/doorbell_protector/docs/DoorbellProtector.* Regenerated outputs reflecting rewiring and updated net structure.
demos/fan_cooling/fan_cooling.py Wire BOM-only zener/resistors as isolated pass-through nets with dynamically_driven=True.
demos/fan_cooling/docs/FanCoolingBoard.* Regenerated outputs reflecting isolated nets for BOM-only parts.
demos/fan_cooling/docs/CooledSystem.* Regenerated outputs reflecting isolated nets in the composed system.
demos/bldc_motor/bldc_motor.py Wire BOM-only bootstrap/decoupling caps + reset pull-up as isolated pass-through nets (dynamically_driven=True).
demos/bldc_motor/docs/BLDCSystem.* Regenerated outputs reflecting new isolated nets for BOM-only passives.
demos/bldc_motor/docs/BLDCControllerBoard.* Regenerated outputs reflecting new isolated nets for BOM-only passives.
demos/isolated_rs232/isolated_rs232.py Wire BOM-only charge-pump/decoupling caps as isolated pass-through nets (dynamically_driven=True).
demos/isolated_rs232/docs/IsolatedRS232Board.* Regenerated outputs reflecting new isolated capacitor nets.
demos/isolated_rs232/docs/IsolatedRS232Link.* Regenerated outputs reflecting new isolated capacitor nets.
demos/backup_power/backup_power.py Add wiring to connect all BOM-only passives onto a driven rail net to satisfy mandatory pins.
demos/backup_power/docs/BackupPower.* Regenerated outputs reflecting new wiring/nets.
tests/golden/assembly_guide/dice.md Updated golden assembly guide reflecting additional jumper instructions.
tests/golden/assembly_guide/doorbell_protector.md Updated golden assembly guide reflecting additional jumper instructions.
demos/dice/docs/Dice.breadboard.svg Updated breadboard SVG reflecting added rail jumpers.
tests/golden/breadboard/dice.breadboard.svg Updated golden breadboard SVG reflecting added rail jumpers.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants