Skip to content

reader: draw doctor findings on the map, not only declared_but_unrouted - #34

Merged
fdaviddpt merged 3 commits into
mainfrom
fix/28
Sep 20, 2026
Merged

fdaviddpt merged 3 commits into
mainfrom
fix/28

Conversation

@fdaviddpt

Copy link
Copy Markdown
Contributor

Closes #28.

Today the reader only drew declared_but_unrouted on the picture; every other doctor finding (a handback nobody routes, a spawn with wider authority than its parent, an agent no edge reaches, two paths for one job) existed only as text. This wires the doctor's whole finding set onto the map.

What changed

  • scripts/swarm_doctor.py --json now emits explicit edge/agent fields per finding, set at each rule's own Result(...) call site rather than guessed post-hoc from the ref's shape (the guess broke on a real ref-namespace collision -- an agent literally named like an edge id, and R08's flow-name ref colliding with an agent name -- both reproduced live during self-review and fixed here).
  • scripts/swarm_reader.py gains --findings PATH, embedding the doctor's --json array into reader/reader.html (defaults to [] when omitted).
  • reader/reader.html colours nodes/edges by finding level (error/warning/info/could-not-check), shows finding text on click, and renders one legend entry per rule that fired -- per the issue's own spec text -- with could-not-check rules named as such rather than silently absent.
  • commands/read.md runs the doctor first and passes --findings to the reader, so /oss:read already carries the overlay.
  • esc() in reader.html now also escapes quotes, closing a title-attribute injection path fed by untrusted swarm.json text (also closes the same pre-existing gap in idTag's data-copy attribute).
  • The intermediate findings file in commands/read.md moved off a shared /tmp path to a worktree-local dotfile, guarded with trap ... EXIT so a crash between write and cleanup cannot leave it behind in the tracked worktree.

Tests

tests/test_doctor_json_findings.py and tests/test_reader_findings.py are new, both red before the change (KeyError on missing edge/agent fields; missing --findings flag, missing JS hooks, missing doctor wiring) and green after. Full targeted suite after all commits: python3 -m pytest tests/test_doctor_json_findings.py tests/test_reader_findings.py tests/test_reader_embed.py tests/test_example_validates.py tests/test_r01.py tests/test_r02.py tests/test_r03.py tests/test_swarm_compile.py -q -- 77 passed.

Self-review

Two rounds (Explore + oss:auditor, spawned concurrently each round). All fixable findings fixed -- see commit history. One finding argued down: the legend showing one chip per rule regardless of instance count is the issue's own specified behaviour ("adds one legend entry per rule that fired"), not a bug. One finding logged rather than fixed, ranked misreports/ship-behind-trap.d by the reviewer: R04's synthetic edge-id fallback is passed as an edge= value the reader can never match against a real edge id, so that one finding silently never highlights on the map -- see trap.d/28.r04-synthetic-edge-id.md.

Not in scope

Fixing anything the overlay shows, or changing the doctor's rules -- per the issue.

[AI-generated]

Florian DAVID added 3 commits September 20, 2026 13:49
…ed (#28)

swarm_doctor.py --json now names which of edge/agent a finding is about, split out of
the overloaded ref field. swarm_reader.py accepts --findings PATH (the doctor's --json
output) and embeds it next to the swarm payload; reader.html colours the named nodes
and edges by finding level, shows the finding text on click, and lists a legend entry
per rule that fired -- could-not-check rules included, never silently absent.
commands/read.md now runs the doctor first and wires the result in.

Co-Authored-By: Max <noreply>
…quote-escape, edge-id guard

Two independent self-review passes (Explore + oss:auditor) found the ref
classification heuristic in swarm_doctor.py was unsound: an edge id and an
agent name are not actually disjoint namespaces (nothing constrains an
agent name against the edge-id schema pattern), and R08's ref is a third,
flow-name namespace that can collide with an agent name too -- both were
reproduced live. Replaced the post-hoc _classify_ref heuristic with explicit
edge=/agent= kwargs set at each rule's own call site, where the rule already
knows unambiguously which one it has.

Also: reader.html's findingsForEdgeId no longer treats an id-less edge as a
wildcard match for every unattached finding; esc() now escapes quotes too,
closing a title-attribute injection path fed by untrusted swarm.json text
(also closes the same pre-existing gap in idTag's data-copy attribute);
commands/read.md writes its intermediate findings file to a worktree-local
dotfile instead of a shared, predictable /tmp path, and removes it after;
and the two new test files gained a positive-control assertion and tightened
logic-marker assertions respectively, so a stub implementation could not
pass either.

Co-Authored-By: Max <noreply>
#28)

Second self-review pass (over the first fixup commit) found: the cleanup
line for commands/read.md's intermediate .swarm-findings.json ran only if
every prior line in the block succeeded, so a crash in swarm_reader.py
between write and cleanup could leave the dotfile behind inside the user's
own tree, unlike the previous /tmp path. Guarded with `trap ... EXIT`
instead.

Also logged a non-blocking trap.d note for a second-pass finding: R04's
synthetic edge id (when an edge is missing its own `id`) is now passed as
an explicit `edge=` value the reader can never match against a real edge,
so that finding silently never renders on the map. Ranked misreports,
ships fine as-is; left for a later curation pass per the review disposition
table.

Co-Authored-By: Max <noreply>
@fdaviddpt
fdaviddpt merged commit 37be1f1 into main Sep 20, 2026
10 checks passed
@fdaviddpt
fdaviddpt deleted the fix/28 branch September 20, 2026 12:25
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.

reader: draw doctor findings on the map, not only declared_but_unrouted

1 participant