Loop-to-loop replies are mirrored as record posts, and the rail's board hides every one of them behind a one-line rollup that forgets it was opened. When two loops actually discuss something — a root-cause correction, an answer to a review question — the supervisor watching the board sees nothing.
What happened
Two loops (TripleAgentSpawn, IssueTriage) worked through the diagnosis that became #272 entirely over graphcode node send. Five posts landed on the board; one was visible.
| Post |
Topic |
Kind |
Content |
Visible in the rail |
| #69 |
direct |
record |
Reported the codex-pane bug + a test-coverage question |
❌ rollup |
| #70 |
issue-272 |
note |
"Filed #272 and CLAIMING it" |
✅ board list |
| #71 |
direct |
record |
Heads-up to the Release loop about 0.1.61-beta1 |
❌ rollup |
| #72 |
direct |
record |
Root-cause correction: truncation is not the mechanism, zmx run sets .command = null |
❌ rollup |
| #73 |
direct |
record |
Correction accepted + verified, answered the test-coverage question |
❌ rollup |
Store-wide on this project right now: 50 notes, 23 records.
The two posts carrying the actual technical substance (#72, #73) are the two least visible.
Why
graphcode/Sources/Features/LoopWorkspace/ArtifactorySection.swift
| Line |
Behavior |
:19 notes(in:) |
Main list filters to kind == .note |
:26 records(in:) |
Direct messages and handoffs split off — "receipts for deliveries that already happened, not something written to be read here" |
:34 unreadNoteCount |
Records excluded from the badge — "a badge counting mail nobody is being shown is a badge that cannot be cleared" |
:62 |
Records-expanded state is local and unpersisted |
:238-269 |
recordsRollup renders "N message records", expanding to the last 8; older ones have no affordance at all |
Each decision is defensible on its own. Together they mean a channel loops genuinely use for discussion is one a supervisor never reads — which the section's own doc comment names as the failure mode it exists to prevent:
a coordination channel a supervisor never sees is the failure mode, not a missing convenience
The real problem
The direct topic does double duty. It carries both:
- receipts — "handoff delivered", "message staged" — which genuinely are noise, and
- discussion — corrections, answers, review findings — which is exactly what the board is for.
kind == .record is applied on delivery mechanism, not on content, so the two are indistinguishable downstream.
Possible directions
- Persist the expanded state. Smallest fix.
:62's local @State becomes an AppStorage key like the section's own fold. Doesn't fix the badge or the >8 cutoff.
- Count records in the badge once they can be shown and cleared, removing the reason
:34 excludes them.
- Separate receipt from discussion. A delivery receipt is a record; a message a loop wrote is a note. This is the fix that matches the stated intent — the mirrored body is already the full message text, so the information to make the split is present at mirror time.
- Drop the last-8 cutoff in the rollup, or give "N earlier" a way to open.
(3) plus (2) is my read of what the section's own reasoning is asking for, but the call is a design one.
Repro
- Two loops in a project; from one,
graphcode node send <other-id> <a substantive message>.
- Have the target reply the same way.
- Open either loop's rail. The exchange is not in the board list; it is inside a collapsed "2 message records" line, and there is no unread badge for it.
- Expand it, navigate away, come back — it is collapsed again.
Found while verifying #271 and diagnosing #272.
Loop-to-loop replies are mirrored as
recordposts, and the rail's board hides every one of them behind a one-line rollup that forgets it was opened. When two loops actually discuss something — a root-cause correction, an answer to a review question — the supervisor watching the board sees nothing.What happened
Two loops (
TripleAgentSpawn,IssueTriage) worked through the diagnosis that became #272 entirely overgraphcode node send. Five posts landed on the board; one was visible.directrecordissue-272notedirectrecorddirectrecordzmx runsets.command = nulldirectrecordStore-wide on this project right now: 50 notes, 23 records.
The two posts carrying the actual technical substance (#72, #73) are the two least visible.
Why
graphcode/Sources/Features/LoopWorkspace/ArtifactorySection.swift:19notes(in:)kind == .note:26records(in:):34unreadNoteCount:62:238-269recordsRolluprenders "N message records", expanding to the last 8; older ones have no affordance at allEach decision is defensible on its own. Together they mean a channel loops genuinely use for discussion is one a supervisor never reads — which the section's own doc comment names as the failure mode it exists to prevent:
The real problem
The
directtopic does double duty. It carries both:kind == .recordis applied on delivery mechanism, not on content, so the two are indistinguishable downstream.Possible directions
:62's local@Statebecomes anAppStoragekey like the section's own fold. Doesn't fix the badge or the >8 cutoff.:34excludes them.(3) plus (2) is my read of what the section's own reasoning is asking for, but the call is a design one.
Repro
graphcode node send <other-id> <a substantive message>.Found while verifying #271 and diagnosing #272.