Skip to content

fix(nodes): new boards counted on every tab, grace from coming online, one log of the physical bus - #154

Merged
mottihoresh merged 2 commits into
fix/chunk-4from
fix/c4a-new-boards-log
Oct 17, 2026
Merged

mottihoresh merged 2 commits into
fix/chunk-4from
fix/c4a-new-boards-log

Conversation

@mottihoresh

Copy link
Copy Markdown
Contributor

Fix-track chunk 4 (#133), the new-boards and event-log items. Behaviour changes on purpose (decided 2026-10-16); nothing else does. Rebased on fix/chunk-4 after #153 (one fault order); its changes are kept as they are.

1. D1 / X3 / R2: strays on every tab

Today After
Strays The 5 s "UNIDENTIFIED" (or SECOND GATEWAY / UNKNOWN BOARD TYPE) warning counted on the Cockpit only. The Overview tile read "no nodes known", with no banner; Connected nodes had no row. One newState(entry, now, live) in node-model.ts: news (adoptable), identifying (with strayAt), stray, or none. isReportableNew is built on it, and attention.ts strayNew reads it. buildCockpitSnapshot hands the same strays to overviewSummary and nodesSummary. The Cockpit, the Overview (tile and banner) and Connection (counts plus a stray row with chip … · can’t be adopted, no zone) all count it after 5 s. NodesSummary.known is the band's total, so a lone stray isn't hidden behind "No nodes reported".

IDENTIFY_WAIT_MS and strayKind moved into node-model.ts. strayFlag is strayKind in capitals.

2. S6: grace from coming online

Today After
Grace Counted from firstSeenAt, which an absent roster row also sets. A board listed absent and coming online later was flagged at once. NodeRoster keeps NodeSeen.onlineSince: set on a present row after an absent one (or the first present row), cleared when the board goes absent (delta or END). The model copies it onto new entries (NodeModelEntry.onlineSince), and newState counts the grace from it.

3. X8 / C6: "from NODE_IDS.md" wording

Today After
A registry board waiting to be added nodeHealth flag NOT IN REGISTRY, the nodeFaultBoxes box "Not in registry", log detail in NODE_IDS.md / not in registry. The Overview already said "from NODE_IDS.md". One newReason(entry) in node-model.ts: from NODE_IDS.md / not in NODE_IDS.md. The flag is FROM NODE_IDS.md / NOT IN NODE_IDS.md. The box title is From NODE_IDS.md (a registry board's text no longer says it isn't listed). The log's "new on the bus" detail reads the same.

A probe test (main/nodes/phase0-probes "X8 / C6") scans every .ts/.tsx in src for not in registry (any case) and the old log literal 'in NODE_IDS.md', and fails on a hit. It was shown to fail when // NOT IN REGISTRY was appended to views.ts.

Left alone: AdoptDialog.tsx's queue label <name> · in NODE_IDS.md is the renderer's own wording for a registry board in the Adopt queue. It was out of scope (that dialog was another PR's file), so it isn't in the probe.

4. D8 / S5 / C4: the log is the physical bus

Today After
Boards outside your cockpit Their offline / bus-off / flag rows were errors and warnings like your own boards' rows. A stray never got any row. Every board on the bus is still logged. A row about a board outside your cockpit is at info, with the detail suffix not in your cockpit (one row() in the tracker). A stray gets one new on the bus · <unidentified | second Gateway | unknown board type> · can’t be adopted row at info once newState says stray. If it later identifies as adoptable, it gets its new row then.
"N online" Counted every board, with nothing to tell them apart. Still counts the whole bus, now with · K not in your cockpit when some aren't yours.
"New" Re-derived in NodeHub (isNew: not known and an adoptable kindOf). Only checked on status rows, so a board identified only by telemetry got no row until its next roster row. announce() reads newState from the model entry, built at most once per line, so it isn't re-derived. It is checked on status and telemetry lines: a PDU identified by its pages gets its row at those pages.
"Seen new" record Survived Forget, so Forget then re-plug logged nothing new. NodeEventTracker.cockpitChanged() runs after every successful mapping change. It drops the record for boards now in your cockpit, so a forgotten board that returns is new again.
Telemetry-only boards No last seen, and no online / offline rows. NodeHub's busTransitions (was rosterTransitions) uses onBusIds: the one availabilityOf rule over roster ∪ telemetry. It runs on roster changes and on page takes, so last seen and un-hide follow pages too. pagesOnline() gives a board online by its pages alone (onlineByPages) online / offline · no telemetry rows. If the roster later lists it, no second online.
Degraded A new fault id while still degraded logged another degraded row. Once per episode: raised, then cleared.

Tests changed on purpose

Test Was Now Why
T1 the Overview does not count the same stray (X1 today) "no nodes known", no banner Banner 1 node needs attention — 1 warning (NODE_ID 9) D1
T1 the 5 s grace counts from firstSeenAt … (F26 today) Stray at once No stray at first, a stray 5 s after onlineSince S6 / F26
T3 the Overview doesn’t count a stray (X1 today) — / "no nodes known" Tile 1 / 1, banner names NODE_ID 9 D1
T4 a board still identifying, or one that can’t be adopted, is not mentioned No status role at all Notice still absent; the banner names the stray (fake clock at T0 so #9 is still identifying) D1: the stray is a warning, not news
T34 the agreement cases (header + 2 tests) Overview / Connection without the stray All three count it (4 / 7, Connection 2/2/2 with the stray's row; next push 6 / 7, 5/1/0) D1
on-the-bus.test link up Connected nodes known 2, rows [2] known 3, warn 1, rows [2, 9] D1 (Connection strays-absent case)
overview-summary.test … without strays Band and items without strays Same equality, strays passed; plus a new stray case D1
events lookup() stub (and the #153 faults.test stub, call-site only) isNew / unmapped / inRegistry outside / entry (the model entry) "New" from newState
events: registry / not-in-registry details in NODE_IDS.md / not in registry from NODE_IDS.md / not in NODE_IDS.md X8
events reports a new node once per app run… roster: 1 node online … · 1 not in your cockpit D8 label
events a new node coming back in a later port session… online [info], offline · no heartbeat [error] … · not in your cockpit [info] D8
events degraded … a new fault id is a new row Second row for fault 9 No row; after a clear, a new episode logs Degraded once per episode
node-hub.seam B33 No row at the pages; one at the next status row One row at the pages, none after C4
main phase0-probes C4 Same as B33 Fixed; plus Forget → re-plug logs "new" again; plus the X8 source probe C4 / X8
renderer phase0-probes D1, S6, C6 Today's behaviour The fixed behaviour D1 / S6 / X8
node-hub.test S1 kind stored { added, kind } after PDU pages Also lastSeen Telemetry-only boards update last seen
node-status-wire.test seen { firstSeenAt, reportedAt } Includes onlineSince (reset on coming back) S6
T22 log fixture detail: 'in NODE_IDS.md' from NODE_IDS.md Fixture mirrors main's wording; the X8 probe covers it

Inputs only, assertions unchanged: scenarios.newBoard also sets onlineSince (its doc already said "online since firstSeenAt"), and the adopt.test / cockpit-host.test / on-the-bus.test stray fixtures set onlineSince. nodesSummary / overviewSummary gained the strays argument ([] in the old cases).

The NODE_ID 0 overview cases (takes / treats NODE_ID 0 like any other node) are unchanged and still pass. Nothing here changes how the summaries treat a NODE_ID 0 entry, and the model has excluded node 0 since #344.

New tests

  • node-model.test: newState (news / stray / identifying with strayAt, none off the bus or unplugged), onlineSince on the model, newReason, strayKind, onlineByPages.
  • node-status-wire.test: onlineSince cleared by absent row or END, reset on coming back.
  • adopt.test: grace from onlineSince.
  • overview-summary.test and connection-summary.test: a stray counted with its row.
  • events: outside rows at info and labelled; baseline count; stray announcements; stray → news; telemetry announce; cockpitChanged; pagesOnline.
  • New main/nodes/new-boards.seam.test.ts, through makeServices() over the fake serial port:
    • a stray on all three tabs after 5 s;
    • the grace from coming online;
    • the FROM NODE_IDS.md flag and log row;
    • outside rows at info and the roster label;
    • Forget → re-plug logs new again;
    • a pages-only PDU's last seen and its online / offline rows.

How verified

API guard: header note only. NodeModelEntry and NodeSeen gained optional onlineSince; there is no channel or intent change.

…e log of the physical bus

Fix-track chunk 4 (#133), part one: new boards and the event log.

- D1 / X3 / R2: one newState (node-model.ts) feeds the Cockpit, the
  Overview and Connection; all three count a stray (a new board that
  can't be adopted, or still unidentified 5 s after it came online).
- S6: the roster tracks onlineSince, reset on each offline -> online;
  the identify grace counts from it, not from first sighting.
- X8 / C6: one newReason: a registry board waiting to be added is
  "from NODE_IDS.md" on its flag, fault box and log row; a probe test
  fails if the old wording is back anywhere in src.
- D8 / S5 / C4: the log is the physical bus. Rows about a board outside
  your cockpit are info, labelled "not in your cockpit"; the baseline
  says how many are not yours. "New on the bus" reads newState (so
  telemetry-identified boards and strays get it too) and is cleared
  when the board joins your cockpit, so Forget then re-plug logs it
  again. Boards online by PDU pages alone update last seen and get
  online / offline rows. Degraded is logged once per episode.
@mottihoresh
mottihoresh merged commit 32d660d into fix/chunk-4 Oct 17, 2026
3 checks passed
@mottihoresh
mottihoresh deleted the fix/c4a-new-boards-log branch October 17, 2026 18:19
mottihoresh added a commit that referenced this pull request Oct 18, 2026
…of the physical bus, safe add all and un-hide all (#155)

Chunk 4 of the fix track (#135): new boards, event log and cockpit
actions. Closes #133.

Item PRs squash-merged into `fix/chunk-4`:
- #153 — one fault order (bus-off → fault → overheat → error-passive) in
the Log and the Cockpit; Add all can't double-run (dialog busy flag +
main re-entry guard); Un-hide all goes on past a failure and lists every
board it couldn't un-hide; Reset preview refetches only when the mapping
changes; Adopt opens on the board asked for and its count matches the
button; an older node model or cockpit snapshot never replaces a newer
one.
- #154 — one `newState`: the unidentified warning counts on Cockpit,
Overview and Connection after 5 s; the 5 s grace counts from when a
board comes online (reset on each offline → online); "from NODE_IDS.md"
wording everywhere (one `newReason`, probe test); the event log is the
physical bus — boards outside your cockpit logged at info with "· not in
your cockpit", a telemetry-only board gets its "new" row and
online/offline rows, "new" is worked out once and cleared on Forget,
degraded is logged once per episode.

Tested on the rig before merge (checklist in #133).

BEGIN_COMMIT_OVERRIDE
fix(nodes): one fault order, add all and un-hide all can't double-run or
stop early, dialogs show the current board
fix(nodes): new boards counted on every tab, grace from coming online,
one log of the physical bus
END_COMMIT_OVERRIDE
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