Files
archy/.planning/phases/01-federation-mesh-hardening/01-12-SUMMARY.md
T
archipelagoandClaude Opus 5 90884e6259
Demo images / Build & push demo images (push) Successful in 4m21s
feat(01-02): chat mutations mutate demo state instead of acking (FED-04)
Reactions, replies, read-receipts, edits, deletes, forwards and channel sends
shared one bare `{ ok: true, sent: true }` case, so none of them rendered on
the demo — the UI derives reaction chips and reply quotes from the message
store, and there was nothing in it to derive from.

Each now mirrors its daemon counterpart. Reactions/replies/receipts push typed
messages carrying the { sender_pubkey, sender_seq } target key Mesh.vue's
reactionIndex and replyTargetPreview read. Edits rewrite the text and set
edited_at; deletes tombstone IN PLACE (plaintext, typed_payload.deleted,
message_type 'delete') because that is what mesh/mod.rs apply_local_delete
does — it does not remove the row.

Edits and deletes go through a per-session overrides overlay keyed by
sender_seq, because mesh.messages rebuilds its seed array on every read, so
in-place mutation would only ever work for messages sent this session.

mesh.refresh and mesh.reboot-radio stay acknowledgements on purpose — the
daemon's handlers have no message-store effect either — with a comment saying
so, so a later reader does not "fix" them into divergence.

Also completes the phase bookkeeping for 01-02/03/11/12/13/14/15 and lands the
orphaned 01-12/01-14 SUMMARYs.

Verified: parity harness 17/17 live assertions; full frontend suite 102 files
/ 822 tests green.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-01 06:37:00 -04:00

13 KiB

phase, plan, subsystem, tags, requires, provides, affects, tech-stack, key-files, key-decisions, requirements-completed, coverage, duration, completed, status
phase plan subsystem tags requires provides affects tech-stack key-files key-decisions requirements-completed coverage duration completed status
01-federation-mesh-hardening 12 ui
vue
tailwind
flexbox
css-grid
web5
scroll
phase provides
01-federation-mesh-hardening Web5.vue's existing xl:grid-cols-2 row layout and Web5ConnectedNodes.vue's tabbed card (quick task 260729-je5 made the list fill the card's height; this plan adds the missing other half)
A bounded, sibling-matched scroll contract on Web5ConnectedNodes.vue's three tab panes (trusted/observers/requests), pinned by a structural vitest suite
Settled verdict on the second 'connected nodes' surface flagged by the originating todo: AccountInfoSection.vue's hits are changelog prose describing the feature, not a second scrolling list — no fix needed there
web5
federation-mesh-hardening
added patterns
Sibling-matched equal-height row + inner-scroll: give the growing child `xl:flex-1 xl:basis-0` (zero flex-basis so it contributes no intrinsic height) instead of `flex-auto`/no-basis, so a CSS Grid row's default `align-items: stretch` sizes the card by its sibling, and the pane's own overflow-y-auto scrolls inside the leftover height. Card root needs `min-h-0` for the flex column to be allowed to shrink below content height, plus a row-breakpoint `xl:min-h-[Nrem]` floor for the case where the sibling itself is short.
created modified
neode-ui/src/views/web5/__tests__/Web5ConnectedNodesScroll.test.ts
neode-ui/src/views/web5/Web5ConnectedNodes.vue
Row-breakpoint height floor set to xl:min-h-[40rem] (not the planner's initial 20rem guess) — confirmed via Dorian's live-browser check: with node discovery disabled, Web5NodeVisibility (the row sibling) renders short, the floor takes over, and 20rem looked stunted; he asked for double, i.e. 40rem.
Settings 'connected nodes' surface (AccountInfoSection.vue) is unrelated to this defect — its 10 'connected' hits are all changelog/what's-new prose describing the Connected Nodes feature by name, not a second scrolling list component. No code change made there.
Live-browser verification for wide (>=1280px xl breakpoint, sibling-height match + forced-overflow scroll) and narrow (<1280px, stacked layout unchanged) viewports was performed by Dorian directly on his own already-running dev session, not by the executor — the executor does not touch :8100/:5173/:5175/:5959/:3141 (a hard constraint clarified mid-execution to mean 'never kill/restart/disturb', not 'never read from').
UIFIX-02
id description requirement verification human_judgment
D1 The connected-nodes card's height at the xl (row) breakpoint tracks its Web5NodeVisibility sibling via CSS Grid stretch + a zero-basis flex child, instead of growing to fit every row UIFIX-02
kind ref status
unit neode-ui/src/views/web5/__tests__/Web5ConnectedNodesScroll.test.ts#gives all three tab panes the bounded, sibling-matched scroll contract pass
kind ref status
manual_procedural Dorian's direct visual check on his running :8100 session, wide viewport — reported 'we are good' for height match, scroll, and stacked layout pass
false
id description requirement verification human_judgment
D2 The inner list scrolls within the matched height rather than growing scroll-free, for all three tabs (trusted/observers/requests) UIFIX-02
kind ref status
unit neode-ui/src/views/web5/__tests__/Web5ConnectedNodesScroll.test.ts#gives all three tab panes the bounded, sibling-matched scroll contract pass
kind ref status
manual_procedural Dorian's direct visual check — scroll behaviour confirmed correct pass
false
id description requirement verification human_judgment
D3 A short sibling (discovery disabled) still leaves a usable list height via the xl:min-h-[40rem] floor, rather than collapsing to header+tabs UIFIX-02
kind ref status
unit neode-ui/src/views/web5/__tests__/Web5ConnectedNodesScroll.test.ts#gives the card root a min-h-0 flex column with a row-breakpoint height floor pass
kind ref status
manual_procedural Dorian's direct feedback ('too short when discovery is disabled, should be twice as tall') drove the 20rem -> 40rem correction, applied and re-verified pass
false
id description requirement verification human_judgment
D4 The stacked (below-xl) single-column layout is byte-identical to before: same capped max-h-72 height, same scroll UIFIX-02
kind ref status
unit neode-ui/src/views/web5/__tests__/Web5ConnectedNodesScroll.test.ts (max-h-72 asserted on all three panes; git diff confirms Web5.vue untouched and no script-block change) pass
kind ref status
manual_procedural Dorian's direct visual check, narrow viewport — stacked layout confirmed unchanged pass
false
id description requirement verification human_judgment
D5 The zero-node/empty-list edge case still renders the existing empty/loading row and the pane stays in the tree (does not collapse) UIFIX-02
kind ref status
unit neode-ui/src/views/web5/__tests__/Web5ConnectedNodesScroll.test.ts#still renders the empty-state row for each pane when the node list is empty pass
false
id description verification human_judgment
D6 The second 'connected nodes' surface flagged by the originating todo (settings AccountInfoSection.vue) is investigated and given an explicit verdict rather than silently skipped
kind ref status
other grep -n -i connected neode-ui/src/views/settings/AccountInfoSection.vue — all 10 hits are changelog prose, not a scrolling list pass
false
105min 2026-07-31 complete

Phase 1 Plan 12: Connected-Nodes Row-Matched Scroll (UIFIX-02) Summary

Gave the connected-nodes card's three tab panes a zero-basis flex-grow contract so the card's height at the row breakpoint comes from its Web5NodeVisibility sibling via Grid's default stretch, with the list scrolling inside that height instead of growing to fit every row — floor tuned to 40rem per Dorian's live-browser feedback.

Performance

  • Duration: ~105 min (across two work sessions, separated by a live-browser verification checkpoint)
  • Completed: 2026-07-31
  • Tasks: 2/2 (Task 2's dev-preview portion completed by Dorian directly, not the executor — see Deviations)
  • Files modified: 2 (1 component, 1 new test file)

Accomplishments

  • All three tab panes (trusted/observers/requests) in Web5ConnectedNodes.vue now carry min-h-0 overflow-y-auto max-h-72 xl:flex-1 xl:basis-0 xl:max-h-none — below the xl breakpoint nothing changed (same cap, same scroll); at xl the pane contributes zero intrinsic height, so the grid row is sized by the sibling alone and the pane scrolls inside the leftover height.
  • Card root gained min-h-0 xl:min-h-[40rem] so a short sibling (e.g. discovery disabled, Web5NodeVisibility renders small) still leaves a full, usable list area instead of collapsing to the header+tabs strip.
  • New structural test Web5ConnectedNodesScroll.test.ts pins this contract (3 tests) so a future cleanup cannot regress it a third time (the todo notes this was already a regression of an earlier fix).
  • Settled the ambiguity the originating todo explicitly flagged: the "connected nodes" hits in settings/AccountInfoSection.vue are changelog prose describing the feature by name, not a second scrolling list — confirmed by direct grep of all 10 hits, no code change needed there.
  • Live-browser verification (sibling-height match at wide viewport, forced-overflow internal scroll, unchanged stacked layout at narrow viewport) was performed by Dorian on his own running :8100 dev session rather than by the executor spinning up a competing instance.

Task Commits

Each task was committed atomically, across two rounds (the second correcting the height floor per live feedback):

  1. Task 1: End-to-end — the trusted pane scrolls at a sibling-matched height - ceafbcb5 (fix) — added the scroll contract classes + wrote the pinning test (initial floor: xl:min-h-[20rem], the planner's flagged judgement call)
  2. Task 2 correction: raise the height floor to 40rem - b5628d96 (fix) — Dorian verified height-match/scroll/stacked-layout were all correct on his own running session but reported the floor was too short with discovery disabled ("should be twice as tall"); floor changed 20rem40rem, test's expected value updated to match

Both commits pushed to gitea-ai main. No separate plan-metadata commit was needed beyond this SUMMARY's own final commit (below).

Note: this plan's Task 1 was type="tracer" tdd="true" — test file written first (RED verified analytically via git diff showing the exact classes the test's toContain/not.toContain assertions depend on), then the fix applied and the test confirmed green (GREEN).

Files Created/Modified

  • neode-ui/src/views/web5/Web5ConnectedNodes.vue - card root: min-h-0 xl:min-h-[40rem]; all three tab panes: xl:flex-1 xl:basis-0 xl:max-h-none replacing flex-auto/no-basis, keeping min-h-0 overflow-y-auto max-h-72 unchanged. No script-block, header, tab-strip, row-markup, or Web5.vue changes (verified via git diff --stat showing zero change to Web5.vue, and zero <script diff lines).
  • neode-ui/src/views/web5/__tests__/Web5ConnectedNodesScroll.test.ts - new: 3 tests pinning (1) the bounded scroll contract classes on all three panes, (2) the card root's min-h-0/flex-col/xl:min-h-[40rem] floor, (3) the empty-state row still rendering for each pane.

Decisions Made

  • Height floor: xl:min-h-[40rem] (final, confirmed value) — see key-decisions above for the full reasoning trail (planner's 20rem guess → Dorian's live feedback → 40rem).
  • Settings AccountInfoSection.vue "connected nodes" surface: confirmed unrelated (changelog prose), left untouched.
  • Live-browser verification delegated to Dorian's own already-running dev session rather than the executor starting a competing instance — see Deviations.

Deviations from Plan

Auto-fixed Issues

None beyond the planned scope — the height/overflow class changes and test file are exactly what the plan specified (with the floor value corrected per live feedback, which the plan itself flagged as an open judgement call to be settled at this exact step).

Process deviation: live-browser verification performed by the user, not the executor

Found during: Task 2, precondition step ("local dev preview can be started... on :8100") Issue: The session's hard constraints (as initially worded) listed :8100/:5173/:5175/:5959/:3141 as ports the executor must never touch. All of :8100, :5959, :5173, :5175 were confirmed (via ss -ltnp) to already be live processes belonging to running vite/mock-backend sessions in this same working tree, so starting a new instance risked colliding with a live session. The executor halted and returned a checkpoint:human-verify rather than starting anything or reading from those ports. Resolution: Dorian checked his own already-running :8100 session directly (a live vite dev server on this exact neode-ui checkout, which had already hot-reloaded the template change via HMR) and reported: height match, internal scroll, and stacked layout all correct ("we are good"), with the floor value needing to double. The coordinator also clarified mid-execution that the constraint's intent was "never kill/restart/disturb," not "never read from" — read-only observation of an already-running dev server is fine going forward. Files modified: none as a result of this deviation itself (informational); the floor-value correction it produced is neode-ui/src/views/web5/Web5ConnectedNodes.vue (commit b5628d96). Commit: N/A (process note, not a code fix)

Auth gates

None encountered.

Known Stubs

None — no hardcoded empty values, placeholder text, or unwired data introduced by this plan.

Threat Flags

None — this plan is a template-class-only change plus a new test file; no new endpoints, auth paths, or trust-boundary surface introduced.

Self-Check: PASSED

  • FOUND: neode-ui/src/views/web5/Web5ConnectedNodes.vue (modified, confirmed via git diff)
  • FOUND: neode-ui/src/views/web5/tests/Web5ConnectedNodesScroll.test.ts (created)
  • FOUND commit ceafbcb5 (git log --oneline --all | grep ceafbcb5)
  • FOUND commit b5628d96 (git log --oneline --all | grep b5628d96)
  • CONFIRMED: neode-ui/src/views/dashboard/__tests__/keepAliveTabs.test.ts byte-identical (git diff --stat shows no change) and green in every npx vitest run pass during this plan.