Skip to content

An electrical identity is scoped to the design it belongs to - #8372

Merged
briansrls merged 2 commits into
mainfrom
session/electrical-design-identity
Aug 18, 2026
Merged

briansrls merged 2 commits into
mainfrom
session/electrical-design-identity

Conversation

@briansrls

Copy link
Copy Markdown
Contributor

Auto-opened by session-dashboard for session zesty-heron-736.
Pushing to session/electrical-design-identity advances this PR.

Worker attestation

Before flipping this PR to ready for review, confirm each item:

  • Title describes the change (not the session id or branch).
  • PR body summarises what and why (replace the TODO below).
  • Tests run: name the command (e.g. npm test, cargo test) and the result.
  • If this closes a work item, the body contains a Closes #N directive.
  • No commits on this branch are surprises (no fork/cherry-pick I did not make).
  • No secrets / credentials / large binaries staged.

Summary

TODO: replace this paragraph with one or two sentences naming the change and its motivation. Reviewers read this first.

Test plan

  • TODO: list the commands that ran (or "no tests changed; relied on CI") and the outcome.

Before this, ComponentInstanceIdentity and NetIdentity were board-global
branded strings, so VCC on one board was structurally the SAME net as VCC
on another. An admitted copper result, a footprint binding or a routing
verdict established against one board was replayable against a different
board whose labels happened to agree, and nothing in the model could tell
them apart. Every board calls a rail VCC, so this is the common case rather
than a corner one.

The design axis lives IN the identity rather than in a per-consumer check,
because a check is a second representation of a constraint the carrier can
hold (DESIGN section 5). With the design inside the identity two boards'
nets are unequal by the same structural equality every join already
performs, and there is no separate same-board predicate a consumer can
forget to call.

TerminalIdentity deliberately gets NO design axis. A terminal is meaningful
only relative to the component that has it, and the component already
carries the design; a second design field would let a terminal disagree
with its own component about which board it is on. Scope comes from
containment, not repetition.

THE WALL IS PROVEN BY SABOTAGE AND GUARDED AGAINST VACUITY. Replacing the
equality with a local-label-only comparison -- the pre-migration behaviour
-- fails exactly the three cross-board claims and leaves the three controls
passing: same net on one board is still one net, different labels on one
board are still different nets, and the local label still reaches targets
unchanged. An equality hardwired to false would satisfy the walls and fail
those controls.

THE FIRST THING THE WALL FOUND was a witness that had been silently mixing
two boards: compute_board_power_distribution perturbs the reference
intent's RAILS while borrowing its BANKS, so a bank on one board was being
supplied by a rail on another. Under branded strings that was invisible and
the test passed. The fixture now says it shares the reference design, which
is what it always meant.

Migrated: 45 identity construction sites plus every read that went through
a string cast, across article, admission, spice_projection,
power_distribution and five witness modules. Local labels are preserved for
diagnostics and for target syntax that has no notion of a design -- SPICE
and Verilog spell a node, not a board -- so no emitted byte changes.

93 witnesses pass across 8 suites. Compile gate: 32 hard diagnostics, all
pre-existing, none naming any file this change touches. The gate caught the
power_distribution consumer that the witness suites alone did not reach.

Stacked on #8363.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@gunbai-bot
gunbai-bot Bot marked this pull request as ready for review August 17, 2026 18:21
@gunbai-bot
gunbai-bot Bot force-pushed the session/electrical-design-identity branch from 70de01e to 53d7086 Compare August 17, 2026 18:21
The design axis on the identity does not catch this on its own, and the
side-chat review was right to ask for it. Scoped identities make two
boards' terminals UNEQUAL, which is what stops a foreign terminal being
FOUND on this net -- but nothing stopped such a net being authored. The
result was a member silently never on its own net: every membership
question about it answers no, and nothing states why. Absent and
wrong-board are different states with different remedies, so collapsing
them is the state-space conflation DESIGN section 5 forbids, one level up
from the equality.

NetMemberBelongsToAnotherDesign names both designs, because the author has
to decide which board the net belongs to and neither side is obviously the
mistake.

It REPLACES the dangling-member cause rather than accompanying it. A
foreign member never resolves to a terminal on this board, so firing both
would name one problem twice and send the author hunting a typo that is not
there -- the same one-cause-per-problem rule the net-grain causes already
follow. Confirmed by execution: with both firing the witness refused as
inexact; with the replacement it names exactly one cause.

20 witnesses pass in the admission suite. Compile gate: 32 hard
diagnostics, all pre-existing, none naming a file this touches.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@gunbai-bot gunbai-bot Bot changed the title mobo design scoping An electrical identity is scoped to the design it belongs to Aug 17, 2026
@briansrls
briansrls merged commit 0b55461 into main Aug 18, 2026
5 checks passed
@briansrls
briansrls deleted the session/electrical-design-identity branch August 18, 2026 00:33
gunbai-bot Bot pushed a commit that referenced this pull request Aug 18, 2026
…s TypeEnvCache

13 conflicts. The eleven dag/ files were main's compute_board work still carrying
import blocks this cut deleted -- took HEAD (import-free) for each.

src/v1/04_infer.dag fused two things in one hunk: #8389's module_type_env_cache
binding (a real removal of recomputation, consumed three times below, so dropping it
would break the file) and an import-era module_imports(n: resolved.module) call. Took
the binding, kept imports: []. Generated v1_compiler_infer.rs taken from this branch
per the source-follows rule; bytes catch up at regen.

The class-naming invariant earned its keep: main's #8372 added a WHOLLY NEW file,
dag/test/claim/electrical_design_identity_witness_test.dag, with four import statements.
A one-sided add produces no conflict, so nothing in the merge would have flagged it --
only the tree-wide 'zero .dag files carry an import' check did. Stripped and qualified
from the file's own import block as ledger (20 names, 42 references). Verified back to
zero tree-wide.

The resolver change from f22bac0 survived the merge intact: global_bare_module_on_chain
defined at 04_env.dag:561 and consulted at both call sites (568, 769).
gunbai-bot Bot pushed a commit that referenced this pull request Aug 18, 2026
…equality

#8372 made ComponentInstanceIdentity a design-scoped record, so this
branch's string casts stopped holding. The fixture now mints its component
identities against a fixture design, and component_has_duplicate_footprint
compares through component_identity_eq instead of casting both sides to
NonEmptyStr -- which is the same correction the design axis forced
everywhere else, and it means two boards' components with one local label
can no longer read as one duplicated footprint.

Reset onto main and cherry-picked this branch's own delta rather than
merging: #8363 and #8372 both squash-merged, so the stacked history's diff
against main had become a reversion of the work that just landed.

6 witnesses pass. Compile gate: 0 blocking errors.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
briansrls added a commit that referenced this pull request Aug 18, 2026
* The pad: where a component's terminals become copper

Placement establishes where a component's BODY sits. Copper establishes
which net is realized on which layer. Nothing joined them -- no carrier
said that THIS terminal of THIS component is a conductor at THIS coordinate
on THIS layer. That gap is why the plan view renders bodies and no traces,
and it is measurable: zero occurrences of 'terminal' anywhere in the Altra
placement module.

It also meant the board could not refuse the interesting way. A net whose
members name terminals no pad realizes is unroutable, and before this the
fact had no representation, so it could not be observed, counted or
refused.

THE UNIT IS THE PAD, NOT THE PIN NUMBER. A pin number is a vendor indexing
convention that differs between the package drawing, the schematic symbol
and the netlist, so comparing two of them by number is the spelling
coincidence DESIGN section 3 forbids. A pad names the TerminalIdentity the
connectivity model already uses, so 'is this pad on that net' is the same
decidable join the net relation performs.

Proven by sabotage rather than asserted: replacing the component-qualified
join with a terminal-identity-only comparison -- exactly the pin-number
comparison this module refuses -- turns
w_red_a_pad_on_another_component_does_not_satisfy_the_member FAIL while the
positive case still passes.

A CITATION IS REQUIRED, not optional. Pad coordinates are a manufacturer's
recommended land pattern; authored without a source they are someone's
recollection of a drawing and a board built to them does not solder. An
Absent arm would invite filling the gap from memory, so drawing_authority
is plainly required with no legacy arm, and it names a resolvable symbol
rather than a document title.

Four refusals, each counted and located: a net member with no pad (naming
component and terminal, not just the net), two pads on one terminal, a pad
selected against another board's stackup, and two footprints for one
component. AdmittedFootprints is sole_constructor with one admit_callers-
sealed mint.

Footprint admission is deliberately SEPARATE from copper's: it asks whether
the roster can be routed at all, copper asks whether the conductors someone
drew are consistent. Fusing them would make 'there are no pads yet'
indistinguishable from 'the routing is wrong'.

6 witnesses PASS (5 RED controls). Compile gate: 32 hard diagnostics, all
pre-existing, none naming any file this change touches.

Stacked on #8363 -- product.electrical.connectivity is its dependency.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* Rebase onto main and route the footprint join through typed identity equality

#8372 made ComponentInstanceIdentity a design-scoped record, so this
branch's string casts stopped holding. The fixture now mints its component
identities against a fixture design, and component_has_duplicate_footprint
compares through component_identity_eq instead of casting both sides to
NonEmptyStr -- which is the same correction the design axis forced
everywhere else, and it means two boards' components with one local label
can no longer read as one duplicated footprint.

Reset onto main and cherry-picked this branch's own delta rather than
merging: #8363 and #8372 both squash-merged, so the stacked history's diff
against main had become a reversion of the work that just landed.

6 witnesses pass. Compile gate: 0 blocking errors.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Brian Searls <briansearls1@gmail.com>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
gunbai-bot Bot pushed a commit that referenced this pull request Aug 18, 2026
#8372 added NetMemberBelongsToAnotherDesign to BoardArticleRefusal and a
match arm in the witness, but never imported the variant — leaving the
constructor unbound so every scrutinee fell through at runtime (16
witness failures, one per refusal variant).

diagnose_host_network matched std.upsert_decision.Absent on a
NetplanConfigFile? scrutinee; the absent arm belongs to Optional, so
none/null fell through and host_network_diagnosis_witnesses errored.

Co-authored-by: Cursor <cursoragent@cursor.com>
briansrls pushed a commit that referenced this pull request Aug 18, 2026
#8372 added NetMemberBelongsToAnotherDesign to BoardArticleRefusal and a
match arm in the witness, but never imported the variant — leaving the
constructor unbound so every scrutinee fell through at runtime (16
witness failures, one per refusal variant).

diagnose_host_network matched std.upsert_decision.Absent on a
NetplanConfigFile? scrutinee; the absent arm belongs to Optional, so
none/null fell through and host_network_diagnosis_witnesses errored.

Co-authored-by: gunbc-ci-auto-heal <gunbc-ci-auto-heal@users.noreply.github.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
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.

1 participant