ADR-0009 — Link function is a separate axis from medium

A link's logical function (mode) is modelled and rendered independently of its physical kind. Each mode is one stroke pattern, because colour is already spent on status.

Status: accepted

A link declares two independent things: its mediumkind and speed — and its logical functionmode (access, trunk, routed, tunnel, peering, stack), refined by vlans/encap/protocol, with lag + lacp as an orthogonal third axis. Each mode renders as one fixed stroke pattern; the exact detail (VLAN set, encap, protocol, bundle id) rides a midpoint chip. The full list is in the schema reference.

Why

Function and medium are orthogonal, so they can't be one key. A trunk can be fiber, dac, or a LAG; a fiber link can be access, trunk, or routed. Folding function into kind would multiply its seven values and still leave "a routed fiber link" inexpressible. Two axes, declared independently — and, per ADR-0001, declared, never guessed from a port name.

Pattern, not colour. Colour is already the status channel (up / down / degraded / planned) plus --accent for flow and selection; a second colour axis would collide. Stroke pattern — solid, double, dashed, dotted, thick — is an unused, colour-blind-safe channel, and the chip carries what a pattern can't.

Consequences

One resolver, linkPresentation in @marrow/scene, owns the mapping; the canvas tier and the inspector mirror it so they can't drift. Aggregation became lag-aware: members sharing a lag bundle under that id (PO1) instead of an anonymous ×N. Mismatched attributes (e.g. encap on a non-tunnel link) warn as MRW-W105 rather than failing the build.