Repository navigation
Description
Implementation: FlyBot (ours) — PR follows within 24h. Do not pick up without a pickup-ok comment on this issue.
Written-by: FlyBot Lead
Claimed-by: FlyBot Lead
Claim-Id: 17ae8e6a5b164841a68bfb960c57006c
Branch: dev/2-395-wire-hit-targets
Base: de70481
At: 2026-11-02T09:33:54Z
Implementation: FlyBot (ours) — PR follows within 24h. Do not pick up without a pickup-ok comment on this issue.
Written-by: FlyBot Lead
What the user sees
A run's flowchart draws its wires, and nothing about a wire is reachable: the layer that holds them is pointer-events: none (core/src/client/styles.js:551), no path carries a data-key, none has a <title>, and the <svg> is aria-hidden. In the factory delivery graph reviewer>deployer and tester>deployer end at the same point (the top port of deployer, x = 0), so when a narration says "the reviewer hands it back" there is no way to point at which wire — not with a pointer, not with a screen reader.
Reproduction
Open Settings → Workflows and look at a settled factory graph (deliveryWorkflow()): seven wires, no wire answers a pointer, no wire exposes a name. Reading the DOM gives the same answer — every path under the wires layer has data-route only, the layer has pointer-events: none, and the svg carries aria-hidden="true". Hovering the segment between the two ports moves nothing.
Root cause
The wires were built as decoration: one <path> per route with data-route and a marker, inside a layer that is deliberately pointer-transparent, in an svg that is hidden from assistive technology. There is no per-wire identity in the DOM (data-key), no text alternative (<title>/aria-label), and no pointer state, so a wire can be neither hovered nor read.
Expected behaviour
Every wire is an element a person can point at and read:
- a 10px transparent hit path per route carrying
data-keyand its own<title>naming the two cards (A → B), while the drawn path keepsdata-routeand its arrowhead unchanged; - the wires layer remains pointer-transparent for everything else, so the hit path is what receives the pointer;
- hovering one wire marks it
data-activeand dims the others ([data-dim]), and leaving clears both — no layout shift, no re-route; - the
svgis exposed as a group namedConnections(zh: 连线) instead ofaria-hidden, so each wire is reachable by assistive technology; - hovering or clicking a wire in read-only mode commits nothing; the pointer state never reaches
onCommit.
Scope (S)
core/src/client/workflows.js: draw the extra hit path per route, the<title>, the pointer state and thedata-active/data-dimattributes.wireRoutes,cardBoxesandparallelFramesare not touched — the geometry belongs to#2138.core/src/client/styles.js: the hit path,[data-active],[data-dim]and the cursor.core/src/client/i18n.js: one label (Connections/ 连线).core/test/workflows-page.test.js: three cases — every route has a hit path withdata-key, width 10 and afrom → totitle; hovering one wire setsdata-activeon it and[data-dim]on the rest and clears both on leave; a read-only graph callsonCommitzero times after hover, pointerdown/up and click. All three red on basede704814, green after. One existing assertion that counted paths by "d starts with M" becomes a count of drawn wires (data-route), which staysfactory.edges.length.docs/subsystems/core-client.md,changelog.d/<n>-wire-hit-targets.added.md, and thepatches/ds-bot/mirrors viagenerate.
Out of scope: the room side panel's own .wf-wires drawer is a different surface and is unchanged.
Dedupe (checked before opening)
Open issues: hover + wire → three hits, all closed and other surfaces (Add-link form styling, flowchart edges/composer, node card tools); hit + path + wire → the only open one is #2138 (back-edge geometry, this issue's sibling, not the same surface); aria-label + wire → 0. #1662/#1663 are the wrapped-layer crossing fix, closed. No held backlog entry for wire hover or wire identity.
Activity
A wire in the run flowchart can be neither pointed at nor read (Think…