docs/ had 26 developer documents flat beside the manual, and the two
audiences are very differently sized: most readers want the manual and
the gesture reference, a few want the register, the designs and the
measurements. The manual and gestures.md stay at the top; everything for
someone changing the code moves to docs/dev/, and the two documents that
name their own successors — the v0.1 milestone and the UI-refinement plan
— go to docs/dev/archive/ rather than being deleted, since both are still
cited. docs/README.md is the index, users first.
Every reference follows: code comments, Cargo manifests, the workflows,
the pre-commit hook, the bench and traceability tools (which locate the
repo root by docs/dev/requirements.md now), packaging, the Docker READMEs,
CLAUDE.md, CONTRIBUTING.md and the README. The matrix links one level
deeper and is regenerated. Links out of the moved documents into the tree
gain a level; a link checker over every Markdown file finds none broken.
Two agents worked in parallel and neither could see this. The frame-budget
instrument matches `ParamKind::Enum { variants }` by value, which was free when
a descriptor was `&'static` and everything in it was borrowed for the life of
the program. Descriptors are owned now — a declaration parsed at run time
cannot hand out a `&'static` — so `variants` is a `Vec` and the arm was moving
out of a shared reference.
Bound by reference instead. The arm only ever reads the length.
The kind of conflict that survives a clean textual merge: git had nothing to
report, and the two changes are only incompatible once they are in the same
tree.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
`docs/display-and-extension.md` §2 fixes a decision rule in advance: if the
99th percentile of a frame sits inside 16 ms, tiled computation is rewritten
as a scheduling concern for export rather than built on the interactive path.
Nothing in the tree could answer that, so the rule had nothing to act on.
This is the instrument. It renders a 60 MP synthetic source through the real
`render_detailed` at three viewport sizes and four chain lengths, fit and
zoomed to 1:1, and reports nearest-rank percentiles rather than means — a
slider drag is judged by its worst frame.
Three things it does that a simpler timer would not:
- It separates the fused pass from the neighbourhood stage. "Every operation
active" mixes one dispatch together with a chain of convolutions, and §2's
question is about the first of those. `point` is every operation that
contributes a fragment to the fused shader; `all` adds the four with
kernels, and M3 times those alone by moving only a detail parameter so
`render_detailed`'s colour reuse skips the fused dispatch. The reuse is
reported rather than assumed — the `colour` column counts fused dispatches
and must be zero for an M3 row to mean what it says.
- It times the CPU half separately. Composition runs per frame in
`DevelopSession::render`, so it is inside the budget whether or not anyone
has looked at it, and if shader assembly were the expensive half then no
tile scheduler could help.
- It builds the "every operation" chain from `EditGraph::capabilities` rather
than from a list, so declaring a new node does not quietly turn that row
into a shorter chain wearing a longer chain's label.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>