Skip to content

Fabric switch: actuation log, 16 modeling gaps, and the convergence build plan - #11524

Merged
briansrls merged 10 commits into
mainfrom
session/calm-badger-275-switch-docs
Sep 18, 2026
Merged

briansrls merged 10 commits into
mainfrom
session/calm-badger-275-switch-docs

Conversation

@gunbai-bot

@gunbai-bot gunbai-bot Bot commented Sep 17, 2026

Copy link
Copy Markdown
Contributor

Design + record for converging the CRS812 fabric lanes to 100GBASE-CR2 through a modeled path. No code — this is the design the credential/read/converge PRs implement, and the honest record of the manual actuation those PRs dissolve. Follows PR #11504 (the EEPROM read grant).

Context (what happened on the hardware)

The operator recoded the QSFP56 host ends with an FS BOX; PR #11504 landed the grant to read the leg EEPROM. This branch investigated the switch end:

  • Found and read the CRS812 for the first time (192.168.1.240, RouterOS 7.20.8).
  • QSFP56 host recode verified working: byte 192 0x0B→0x40, NIC Supported Cable Speed: 50G_2X→100G_2X, advertises 100GBASE-CR2, former refusal gone.
  • No bilateral 100G link trains against the still-Generic QSFP-DD switch end — under autoneg or forced (mstlink --link_mode_force -s 100G_2X), across every switch FEC mode. Host sits in Polling; switch reports auto-init-failed / eeprom-checksum: bad on the DD end.
  • All 8 legs restored to known-good 50G.

Verdict is stated at witnessed confidence: switch-side coding is the leading hypothesis, not proven. The isolating test is a hardware substitution control, not more configuration.

What's here

  • fabric-switch-actuation-log.md — the out-of-band actuation (operator-approved), the reviewer correction that MikroTik requires forced/autoneg-off (my "non-compliant" framing was wrong), a credential/restore incident (token expired mid-op, left srv5 down until re-auth), and the transcription source for the modeled apply.
  • fabric-switch-100g-convergence-gap-analysis.md §6 — 16 modeling gaps (G1–G16) found by driving the real hardware: no autoneg axis, FEC enum can't express RS(544,514), live/two-ended link outcome unmodeled, no REST reader/apply, no switch credential, mstlink unmodeled, fabric_switch_observed stale, dispatch can't fan out, ad-hoc-curl scaffold to kill.
  • fabric-switch-convergence-build-plan.md — the normal path, layered per DESIGN §3, credential mirroring spark bootstrap, and the PR sequence.

A deliberate sequencing decision (§4d)

The read path is built first (safe, groundable in captured data). The converge apply is deferred until the hardware links at 100G, because its FEC/autoneg specifics are currently inferred, not witnessed — modeling the apply now would assert as fact what we haven't observed. PR-3's converge will correctly refuse/report Polling until the coding is fixed, which is the honest behavior.

🤖 Generated with Claude Code

Brian Searls and others added 2 commits September 17, 2026 16:06
…uild plan

Documents the switch-side investigation and defines the modeled path to
converge the CRS812 fabric lanes to 100GBASE-CR2 when the correctly-coded
QSFP-DD end arrives. No code yet; this is the design that the credential /
read / converge PRs implement, plus the honest record of the manual
actuation those PRs dissolve.

- fabric-switch-actuation-log.md: the out-of-band actuation done under
  operator approval (find + read the switch, force-100G experiments on
  srv5, restore), the reviewer correction that MikroTik requires
  forced/autoneg-off (my "non-compliant" framing was wrong), the
  credential/restore incident, and the verdict at witnessed confidence:
  the QSFP56 host recode succeeded (byte 192 0x0B->0x40, NIC Supported
  Cable Speed 50G_2X->100G_2X) but no bilateral 100G link trains against
  the still-Generic QSFP-DD end, under either autoneg or forced paths,
  across all switch FEC modes. Switch-side coding is the leading
  hypothesis, NOT proven; the isolating test is a substitution control.

- fabric-switch-100g-convergence-gap-analysis.md §6: 16 modeling gaps
  found while driving the hardware (G1 no autoneg axis, G2 FEC enum
  cannot express RS(544,514) that 100GBASE-CR2 needs, G3/G4 live/two-ended
  link outcome unmodeled, G6 no REST reader/apply, G7 no switch credential
  standing, G9 mstlink unmodeled, G10 ethtool cannot pin CR2, G12
  fabric_switch_observed stale post-recode, G13 dispatch cannot fan out,
  G16 actuation ran on ad-hoc curl -- the scaffold to kill).

- fabric-switch-convergence-build-plan.md: the normal path, layered per
  DESIGN §3 (extdeps interface / REST-transport realization / workflow
  policy), the credential mirroring spark bootstrap, and the PR sequence:
  read path first (safe, groundable now), converge apply deferred until
  the hardware links at 100G because its FEC/autoneg specifics are
  currently inferred not witnessed (§4d).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- FEC meaning fork (§3) + over-promotion (§4d): the actuation log called fec91
  "correct for 100GBASE-CR2" and mapped the 100G intent to Fec91, contradicting
  this PR's own G2 (fec91 = RS(528,514); 100GBASE-CR2 needs RS(544,514)/KP4).
  That was a 50G observation promoted into a 100G requirement. Corrected in
  place with a CORRECTION note, the same treatment the autoneg "non-compliant"
  claim already had: fec91 is the FEC running at 50G, NOT the established 100G
  intent, and converge must not assume it (G2 obligates refusal if the switch
  cannot offer the mode's codeword).

- Standing-observation fork (§3): §0 said the EEPROM was not re-read and
  establishing the coding was the "first work item", while G12 states byte 192 =
  0x40 and NIC 100G_2X. Amended §0 with a SUPERSEDED note pointing at G12 as the
  one current roster: the bytes were read, the re-flash took, the host-coding
  question is closed, the live blocker is the switch-side QSFP-DD end.

- PR-3/PR-4 dependency: PR-3's success criterion named "host mstlink", which is
  PR-4's deliverable. Reworded: the host negotiated-speed READ is unprivileged
  (ethtool, no grant), so PR-3's observe-both-ends criterion does not depend on
  PR-4; only FORCING the host does. PR-3 alone converges the switch and reports
  the host still at 50G rather than claiming success off the switch's local
  link-ok; PR-3 + PR-4 together achieve 100G.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@gunbai-bot

gunbai-bot Bot commented Sep 17, 2026

Copy link
Copy Markdown
Contributor Author

All three findings in review 67282 verified and fixed in the latest commit.

1. FEC meaning fork + §4d over-promotion — confirmed, corrected. The actuation log did call fec91 "correct for 100GBASE-CR2" and map the 100G intent to Fec91, directly contradicting this PR's own G2 (fec91 = RS(528,514); 100GBASE-CR2 needs RS(544,514)/KP4). You're right that it was a 50G observation promoted into a 100G requirement, and right that the autoneg claim got a correction while this one didn't. Fixed the same way: the FEC block now states fec91 is the FEC running at 50G, not the established 100G intent, with a CORRECTION (added with G2) note. Converge must not assume it — G2 obligates refusal if the switch cannot offer the mode's codeword.

2. Standing-observation fork — confirmed, superseded. §0 said the EEPROM was not re-read and establishing the coding was the "first work item"; G12 says byte 192 = 0x40, NIC 100G_2X. Same doc, two current answers. Added a SUPERSEDED 2026-09-17 (see G12) note to §0: the bytes were read, the re-flash took, cause (1) is ruled out, and the one current roster is G12 — the live blocker is the switch-side QSFP-DD end, not the host coding. Kept §0's original text as framing, not as an open question.

3. PR-3 depends on PR-4's deliverable — confirmed, decoupled. PR-3's success criterion named "host mstlink," which is PR-4's tool. The fix is a real distinction I'd conflated: reading the host's negotiated speed is unprivileged (ethtool <dev>, no grant), while forcing it needs PR-4's mstlink grant. Reworded so PR-3's observe-both-ends criterion uses the unprivileged read and does not depend on PR-4; PR-3 alone converges the switch and reports the host still at 50G rather than claiming success off the switch's local link-ok. PR-3 + PR-4 together achieve 100G.

Thanks — all three were real, and the FEC one in particular was the exact §4d trap (a 50G reading standing in for a 100G fact) that the rest of this PR exists to document.

…y failure mode

review 67285 (claude/opus), both findings:

- The PR proved a modeled authority false (byte 192 = 0x40, NIC 100G_2X)
  and left the stale row standing with the correction only in prose. Marked
  it ON THE CARRIER: an annotation on gunbc.spark.fabric_switch_observed
  fabric_leg_cable_observed says nic_supported_speeds is now WRONG post-recode
  (still says 50G_2X), that linked_speed_gbps: 50 stays true only by
  coincidence (switch-side blocker, not a NIC cap), names this the
  a_live_authority_name_carries_a_superseded_claim class, and states the
  trigger (the G12 event model supersedes the row rather than overwriting it).
  A doc note is not the mark; the carrier now carries it.

- The credential/restore incident (GCP token expired mid-experiment, srv5
  left forced-100G / NO-CARRIER with no in-session recovery path) was a
  discovered error class recorded only as G16 prose. Filed the row per
  DESIGN §4b: gunbc.recurring_failure_mode
  a_rollback_depends_on_a_credential_that_can_expire_mid_actuation -- invalid
  state, why it survives testing, the srv5 specimen, the discriminator
  (bites out-of-band per-step-credential actuation, not the modeled
  once-per-run path), rung (mitigatable), ceiling (eliminated by not
  actuating out of band), next-rung trigger (the modeled converge path
  becomes the only actuation path), and the review tell. The roster is
  gitignored and regenerates from the directory at compile.

New row compiles green (claim_batch, the_new_failure_mode_row_compiles).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@gunbai-bot

gunbai-bot Bot commented Sep 17, 2026

Copy link
Copy Markdown
Contributor Author

Both findings in review 67285 addressed in the latest commit.

1. Superseded fact left in prose — now marked on the carrier. You're right: the PR proved fabric_leg_cable_observed false and left the correction only in docs/plans/. Added the annotation on the carrier itself (gunbc.spark.fabric_switch_observed): it states that nic_supported_speeds: "50G_2X..." is now wrong post-recode (byte 192 = 0x40, NIC reports 100G_2X), that linked_speed_gbps: 50 stays true only by coincidence (the blocker is switch-side, not a NIC cap), names it the a_live_authority_name_carries_a_superseded_claim class, and states the trigger — the G12 event model supersedes the row rather than overwriting it. A doc note wasn't the mark; the carrier now carries it.

2. Restore incident owes a recurring_failure_mode row — filed. Per DESIGN §4b, added gunbc.recurring_failure_mode.a_rollback_depends_on_a_credential_that_can_expire_mid_actuation: the invalid state (rollback gated on a credential that can expire mid-run, mutation already applied, no held recovery path), why it survives testing (happy path works the whole valid window; only a long session trips it), the srv5 specimen, the discriminator (bites out-of-band per-step-credential actuation; not the modeled once-per-run-and-removed path), rung (mitigatable), ceiling (eliminated by not actuating out of band), the next-rung trigger (the modeled converge path becomes the only actuation path), and the review tell. It compiles green (the_new_failure_mode_row_compiles); the roster is gitignored and regenerates from the directory at compile.

Both were the right call — the superseded-authority one is literally the class that's already rostered, and the incident genuinely earned its own row rather than a markdown bullet. Thank you.

review 67294 (claude/opus): the previous commit's `//` annotation was
itself a §4c violation -- it asserted a machine claim in prose ("so a
reader does not consume nic_supported_speeds as current") that no Accepted
program can read, while a value the commit itself calls WRONG kept
answering (§5: a wrong answer is a loud error, never a warning).

The honest value was already in the diff. Corrected the literal:
nic_supported_speeds now carries the post-recode mstlink Supported Cable
Speed (100G_2X, 50G_1X, 50G_2X, 25G, 10G, 1G), so the field is TRUE.
linked_speed_gbps stays 50 because the link still trains at 50G for a
switch-side reason, so the two fields are independently true. The
annotation is rewritten as honest rationale -- why the value is what it is
and that G12's event model will make it derived -- with no prose standing
in for a machine check. G12 supersedes a true reading just as well as it
would have a false one.

Verified nic_supported_speeds is read by nothing (only linked_speed_gbps
is consumed, by fabric_rail_desired and the witness, both unchanged); the
observed witness stays green.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@gunbai-bot

gunbai-bot Bot commented Sep 17, 2026

Copy link
Copy Markdown
Contributor Author

Fixed in the latest commit — you're right, and my annotation-only fix was itself the violation.

The // annotation asserted a machine claim in prose ("so a reader does not consume nic_supported_speeds as current") that no Accepted program can read (§4c), while a value the same commit calls WRONG kept answering (§5: a wrong answer is a loud error, not a warning). A dissolution trigger doesn't authorize leaving known-false data standing.

Took your first resolution: corrected the literal to the post-recode truth. nic_supported_speeds now carries the mstlink Supported Cable Speed after the recode — 100G_2X, 50G_1X, 50G_2X, 25G, 10G, 1G — so the field is true. linked_speed_gbps stays 50 because the link still trains at 50G for a switch-side reason, so the two are independently true rather than one implying the other. The annotation is rewritten as honest rationale (why the value is what it is, and that G12's event model will make it derived) with no prose standing in for a machine check — and as you noted, G12 supersedes a true reading just as well as it would a false one.

Verified nic_supported_speeds is read by nothing (only linked_speed_gbps, by fabric_rail_desired and the witness, both unchanged); the observed witness stays green.

Thanks — this was the right call. I'd tried to discharge a §5 debt with a §4c annotation, which is exactly the trap.

review 67302 (claude/opus): two claims stood UNMARKED at their own sites
with corrections elsewhere -- the recurring meaning-fork this PR keeps
tripping on.

- build-plan.md: "forced-both is what actually trains 100G on this
  hardware" was asserted as fact, and this PR's own log falsifies it (the
  one mstlink forced-both run stayed in Polling, no link). §4d: do not
  assert as deduced what is only inferred. Restated at log-supported
  confidence: forced-both is the MikroTik-required production CANDIDATE,
  the one run of it did NOT train, so PR-3 + PR-4 together let us RE-TEST
  it once the coding is fixed rather than achieve convergence by
  themselves.

- actuation-log.md: "forced path is non-compliant for CR" (:130) and
  "VERDICT: 100G will not come up in any configuration" (:138) stood
  unmarked while their retraction sat 25 lines below. Marked both AT their
  sites -- struck through with a pointer to the mstlink re-test section --
  so a reader hits the correction where the wrong claim is, not 25 lines
  later.

Docs only.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@gunbai-bot

gunbai-bot Bot commented Sep 17, 2026

Copy link
Copy Markdown
Contributor Author

Both fixed in the latest commit.

1. build-plan §4d over-assertion. You're right — "forced-both is what actually trains 100G on this hardware" is asserted as fact and this PR's own log falsifies it (the one mstlink forced-both run stayed in Polling, no bilateral link). Restated at the confidence the log supports: forced-both is the MikroTik-required production candidate, the one run of it did not train, so PR-3 + PR-4 together let us re-test forced-both properly once the QSFP-DD coding is fixed — they don't, on current evidence, achieve convergence by themselves. That removes the false signal to a PR-4 worker that building the mstlink grant achieves convergence.

2. actuation-log unmarked superseded claims. The "forced path is non-compliant for CR" claim and the "VERDICT: 100G will not come up in any configuration" both stood unmarked at their sites while the retraction sat 25 lines below. Marked both at their sites — struck through with a pointer to the mstlink re-test section — so a reader hits the correction where the wrong claim is, not 25 lines later.

This is the third time a review has caught me leaving a superseded claim standing with the correction elsewhere — it's a real habit in how I was writing this log, and co-locating is the fix. Thanks for holding the line on it.

review 67308 (claude/opus): correcting the stale value in the previous
commit grew a `String` leaf that hides named parts already modeled -- the
link-mode set (extdeps.ethernet.link_mode LinkMode rows this module
already imports), the reading instrument, and the date. "100G_2X, 50G_1X,
..." is the nicknaming §3 forbids and the anemic leaf §2 forbids, and the
firmware/date suffix is the instrument-output transcription §6 forbids.

The field is read by nothing (only linked_speed_gbps is consumed, by
fabric_rail_desired and the witness), so the honest fix is to DELETE it,
not enrich it into a List<LinkMode> that nothing would read (a richly
modeled dead field is still a §3c dead field). Removed from the type and
the data row; the "what the link reports" note now says the NIC advertised
mode set wants a typed List<LinkMode> cited to its instrument and is not
carried until a consumer needs it. The NIC-supported-mode observation
(post-recode 100G_2X, mstlink) lives in the actuation log and lands typed
when G12's event model gives it a consumer.

Verified nothing else constructs FabricLegCableObserved or reads the field;
the observed witness stays green.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@gunbai-bot

gunbai-bot Bot commented Sep 17, 2026

Copy link
Copy Markdown
Contributor Author

Fixed — deleted the field rather than growing it.

You're right on both counts: correcting the stale value in the prior commit grew a String leaf hiding named parts this module already models — the link-mode set (extdeps.ethernet.link_mode LinkMode rows imported right here), the instrument, and the date. "100G_2X, 50G_1X, ..." is the §3 nickname, and the mstlink, fw 28.45.4028 suffix is the §6 instrument-output transcription.

Since nic_supported_speeds is read by nothing (only linked_speed_gbps is consumed, by fabric_rail_desired and the witness), the coherent fix is to delete it, not enrich it into a List<LinkMode> that nothing would read — a richly-modeled dead field is still a §3c dead field. Removed from the type and the data row; the "what the link reports" note now states the NIC advertised mode set wants a typed List<LinkMode> cited to its instrument and isn't carried until a consumer needs it. The observation itself (post-recode 100G_2X, mstlink) lives in the actuation log and lands typed when G12's event model gives it a consumer.

Verified nothing else constructs FabricLegCableObserved or reads the field; the observed witness stays green.

This closes the loop the earlier review (review 67294) opened — it offered delete-or-correct, I chose correct, and correcting turned out to grow the anemic leaf, so delete was the right call after all.

…+ standing claim)

review 67317 (claude/opus): I marked the nic_supported_speeds deletion on
the carrier but left two other stale claims in the SAME file unmarked --
the "HONEST STANDING CLAIM" prose ("the coding does not attest the required
mode and the NIC refuses it today") and the primary_compliance_code: 11
(0x0B) eeprom rows for spark-a3ee/ac79. The recode falsified the prose and
the eeprom rows are a pre-recode snapshot, so a consumer of
fabric_leg_observation_for got the stale verdict with nothing on the
carrier saying so.

Swept the whole file this time rather than one claim per round:
- SUPERSEDED banner over the pre-recode narrative (:39-63): the coding now
  attests 100GBASE-CR2 (byte 192 0x40), the "Cable speed not enabled"
  refusal is gone, the live blocker moved switch-side. Kept as the
  pre-recode reading rather than rewritten, because the fix is the G12
  event model (PR-1), named as the trigger.
- The eeprom observation rows are marked as the 2026-09-08 pre-recode
  acquisition. NOT re-valued: a receipt is a dated snapshot and overwriting
  it falsifies the record; the post-recode reading is a new acquisition
  that lands as an additional row under G12. Stated as a temporal fact
  (these ARE the pre-recode coding; current is byte 192 = 0x40 per the
  actuation log), not a machine directive to the reader.

Observed witness stays green.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@gunbai-bot

gunbai-bot Bot commented Sep 17, 2026

Copy link
Copy Markdown
Contributor Author

Fixed — and you're right that I'd marked one stale claim in this file while leaving two others unmarked.

I swept the whole file this time rather than one claim per round:

  • SUPERSEDED banner over the pre-recode narrative (:39–63) — the "COMPLIANCE CODING IS A DEMONSTRATED BLOCKER" / "nothing attests 100GBASE-CR2" / "refuses it today" claims now carry a banner: the coding attests 100GBASE-CR2 post-recode (byte 192 = 0x40), the refusal is gone, the live blocker moved switch-side. Kept as the pre-recode reading rather than rewritten, with G12's event model (PR-1) named as the trigger.
  • The eeprom observation rows are marked as the 2026-09-08 pre-recode acquisition. I deliberately did not re-value primary_compliance_code: 11 — a receipt is a dated snapshot, and overwriting it would falsify the historical record; the post-recode reading is a new acquisition that lands as an additional row under G12. Stated as a temporal fact (these are the pre-recode coding; the current reading is byte 192 = 0x40 per the actuation log), not as a machine directive to the reader — which is the distinction from the nic_supported_speeds case, where the value was wrong-and-unread so deletion was right.

Observed witness stays green.

This is the recurring pattern from the last few rounds and I own it: I'd been marking the claim I happened to be editing rather than sweeping the file. Done that now.

review 67327 (cursor): my SUPERSEDED `//` banner on the eeprom rows was the
§4c trap again -- the row is NOT a dated receipt, it is the LIVE plant
reading (FabricLegEepromObservation has no acquisition timestamp, and
.first() / fabric_leg_reading -> LegReadingTaken -> fabric_cable_plant
consume it as current). So primary_compliance_code: 11 on spark-a3ee was a
known-false LegReadingTaken -- silent wrongness on the plant path (§5) that
a comment cannot discharge, with the true value parked in markdown (§6).

Took the reviewer's option 1: re-valued spark-a3ee to the complete
post-recode dump I actually read -- byte 192 = 0x40 = 64 (attests
100GBASE-CR2), date_code 260914 -- so the plant now answers the current
coding. spark-ac79 keeps its last ACTUAL reading (11): the operator
re-flashed it too but it was not re-read, and re-valuing it would fabricate
an observation nobody took (the reviewer noted ac79 is fine to leave). The
two legs now DISAGREE by coding, which the distinct-serial witness exists
to keep representable, and the module's own note says the model must
represent one leg recoded and the other not.

The banner is replaced by a factual note (which leg is post-recode, which
is last-actual), not a directive to the reader. G12's event model (PR-1)
still lands dated multi-acquisition history and a re-read of ac79 appends
rather than overwrites.

All 7 fabric-switch witnesses green, incl. the coding-ceiling and
two-legs-distinct claims.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@gunbai-bot

gunbai-bot Bot commented Sep 17, 2026

Copy link
Copy Markdown
Contributor Author

Fixed — you're right, and this closes the gap in my earlier reasoning.

My SUPERSEDED // banner on the eeprom rows was the §4c trap I'd argued my way out of: I claimed these were dated receipts, but FabricLegEepromObservation has no acquisition timestamp and .first() → fabric_leg_reading → LegReadingTaken → fabric_cable_plant consumes the row as the live reading. So primary_compliance_code: 11 on spark-a3ee was a known-false LegReadingTaken — silent wrongness on the plant path (§5), with the true value parked in markdown (§6), which a comment can't discharge.

Took your option 1: re-valued spark-a3ee to the complete post-recode dump I actually read — byte 192 = 0x40 = 64 (attests 100GBASE-CR2), date_code 260914 — so the plant answers the current coding. spark-ac79 keeps its last actual reading (11): it was re-flashed too but not re-read, and re-valuing it would fabricate an observation nobody took (per your note that ac79 is fine to leave). The two legs now disagree by coding, which the distinct-serial witness exists to keep representable — and the module's own note says the model must represent one leg recoded and the other not.

The banner is replaced with a factual note (which leg is post-recode, which is last-actual), not a reader directive. All 7 fabric-switch witnesses green, including the coding-ceiling and two-legs-distinct claims.

This was the crux the whole fabric_switch_observed thread kept circling: I treated a consumed live value as if a comment could mark it stale. It can't — the carrier had to carry the truth.

Brian Searls and others added 2 commits September 17, 2026 20:09
Decision (operator asked me to choose): the actuation log had drawn seven
review rounds, all against a blow-by-blow narrative that preserved every
wrong turn in prose (forced-non-compliant then corrected, a verdict then
re-tested, an FEC sweep, strike-throughs). That narrative is the liability;
its value is three things -- the facts established, the exact commands run
(the transcription source PR-3's converge is built from), and the verdict
at witnessed confidence.

Rewrote to those essentials (195 -> 76 lines). Each conclusion is stated
once, correctly: host recode confirmed (and carried on the modeled carrier,
not just here), the commands (switch REST + host mstlink + restore), the
verdict (no bilateral 100G under any tested config; switch-side coding the
leading hypothesis, NOT proven; substitution control is the isolating
test), and cross-references to the failure-mode row, the gaps, and the
build plan. Git history carries the exploration; the file is the current
honest record.

All cross-references to this file are by filename and still hold.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ionale)

review 67338 (claude/opus): re-valuing spark-a3ee to 0x40 falsified two
current-tense claims I did not sweep.

- fabric_switch_observed.dag: the FabricLegEepromObservation type annotation
  still said "the two legs agree today", one carrier contradicting the new
  block 18 lines below ("the two legs now DISAGREE"). §4c: an annotation may
  not restate what the declarations structurally say, and this said it
  wrong. Corrected: whether they agree is derived, and they now disagree
  (a3ee re-read to 0x40, ac79 still at last pre-recode 0x0B).

- fabric_switch_desired.dag crs812_desired_fec(): the rationale "Clause 91,
  the FEC the 100GBASE-CR2 attestation is conditional on" was true of 0x0B
  (attests ieee_50gbase_cr2 RequiresClause91Fec), but code 64 attests
  ieee_100gbase_cr2 FecUnconditional -- so my re-value falsified it. Fixed
  the rationale: the conditional-on justification was for the pre-recode
  coding; the real 100G FEC (RS(544,514)/KP4, gap G2, maybe not exposed by
  the CRS812) is an open question, and the returned Fec91 is retained as the
  provisional forced-DAC value, NOT asserted as correct -- decided by the
  converge test (PR-3), deferred until the hardware links (§4d). Value
  unchanged; comment only.

Assessment witness green.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@gunbai-bot

gunbai-bot Bot commented Sep 17, 2026

Copy link
Copy Markdown
Contributor Author

Both fixed — both are consequences of the a3ee re-value that I failed to sweep, and you're right that I applied the correct standard everywhere else and missed these.

1. The "two legs agree today" type annotation at fabric_switch_observed.dag:242 contradicted my own new block 18 lines below saying they now disagree. §4c — an annotation may not restate what the declarations structurally say, and this said it wrong. Corrected: whether they agree is derived, and they now disagree (a3ee re-read to 0x40, ac79 still at its last pre-recode 0x0B), which is the divergence the per-row shape exists to keep representable.

2. The crs812_desired_fec() rationale — "Clause 91, the FEC the 100GBASE-CR2 attestation is conditional on" — was true of the 0x0B coding (attests ieee_50gbase_cr2 RequiresClause91Fec), but my re-value to code 64 makes a3ee attest ieee_100gbase_cr2 FecUnconditional, so the rationale is falsified. Fixed the comment: the conditional-on justification was for the pre-recode coding; the real 100G FEC (RS(544,514)/KP4 per gap G2, which the CRS812 may not even expose) is an open question; the returned Fec91 is retained as the provisional forced-DAC value and not asserted as the correct 100G FEC — that's decided by the converge test (PR-3), deferred until the hardware links (§4d). Value unchanged, comment only.

Assessment witness green.

This is the tail of the re-value: correcting a consumed data row propagates to every annotation and rationale that referenced the old value, and I should have swept both files in the same commit. Done now.

@briansrls
briansrls added this pull request to the merge queue Sep 17, 2026
Merged via the queue into main with commit 4269078 Sep 18, 2026
4 checks passed
@briansrls
briansrls deleted the session/calm-badger-275-switch-docs branch September 18, 2026 00:09
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