Surface Evaluation
An honest evaluation of our component system as drawn in Rust on GPUI (the native app's `layer` crate and its pages), scored per principle against our foundation docs, with the course corrections, the cost of keeping two surfaces, and the skills and tools the work around the GPUI layer calls for. Opens the glossary with Surface.
ReportTwo Surfaces, Scoredtwenty principles, one score each, the evidence and the smallest raise-by-one →Why
The component system now has two expressions. The first is Vue, through q-nuxt-layer. The second has been drawn in Rust on GPUI since c131 D18 ("our layer drawn on GPUI, the kit for the shell"). In three days, agents drew 30 of our components and ported the Inventory section, Status, Activity, the inbox and developer mode. It went fast, and fast work hides its debts. Mark asked for honest evaluation time:
- score the GPUI surface per principle against our foundations;
- find the principles our docs hold that the prompt did not name;
- say plainly how cumbersome two surfaces are, and how much drift we risk;
- find the skills and tools the work calls for.
He also named the thing being evaluated. A Surface is the medium a component is deployed on. The public documentation should track both and be honest where they diverge, welcoming the divergences and writing them down for the operators who deploy the components.
Documents: the plan · the findings · review stop 1 and its rulings · the hand-on to qnative · the web bugs for qdash · the two tools · Mark's prompt · the glossary: brand/glossary.md
Pages: Two Surfaces, Scored · The Cost of Two Surfaces · Skills and Tools
Objective
Done means:
- The glossary: a design-system glossary exists, opened by Surface, with what it is not (the colour roles, the Data Surface family, market-analyst's product surfaces, the capture manifest's field).
- The rubric: a 1–5 scale, set before the evidence, with a trend against the Vue surface, the smallest raise-by-one, and each divergence marked as a flavor, a gap or a flaw.
- The scores: the eight principles Mark named and the twelve our docs add, each with evidence by file and line at a named commit.
- The cost of two: where one change lands, what a machine checks, the drift so far, the logic held twice, and the seed of a divergence register.
- The tools: every step the records show done by hand more than twice, as a candidate skill, script or check, with its evidence.
- The pages: the findings on the design site as cycle reports, and the calls at a review stop.
Scope
- Cycle docs:
cycles/c140.surface-evaluation/(plan.md,findings.md,review-1.md,handon-qnative.md,qdash-todos.md,rescued-specs/) - Brand:
brand/glossary.md(new) - Design site:
app/data/c140-evaluation.ts;app/pages/cycles/design/c140/{scorecard,parity,tools}.vue - Read, never changed:
../qnative(main e609f42),../q-nuxt-layer(e7e1454),../qcontrol/crates/qdash/ui - Out: changing any code in qnative or the layer (proposed, not done); re-auditing the Vue surface (c135); building the dual-surface docs (a ruling first)
Key Changes
- Kick-off, evidence, scores (2026-11-12): the cycle opened from Mark's prompt, quoted verbatim in
initial-prompt.md, with his note that another thread was merging. The work, in order:- The rubric first.
plan.mdwas written before the evidence came back. - Four readers, read-only. They covered the layer's component APIs, the token path, parity and drift across repos, and the app's pages with the manual work around them. The sharper claims were spot-checked by hand at qnative e609f42: the copied
.qp()inharness.rs:280, the 433 literal type sizes, the stale scorecard rows, the inbox'sunwrap_or_default, the missing specs andPATTERNS.md. - The scores. Twenty rows: none at 5, three at 4 (data boundaries, replicate first, the budget), eleven at 3, six at 2 (tokens, two surfaces, accessibility, states, docs architecture, naming).
- The glossary.
brand/glossary.mdopened with Surface. - The specs rescued. The ten port specs (
spec-*.md, about 400 KB, cited 30 times in code and docs) were found only in a session scratchpad under/private/tmpand copied intorescued-specs/(uncommitted; their home is qnative c2). - Merges during the work. Design main moved from 4453a8c085 to 416de93c6a during the work (the c139 merge and the c4/c6 captures).
- The rubric first.
- The pages (2026-11-12): three cycle reports were built from the layer and read from
app/data/c140-evaluation.ts:/cycles/design/c140/scorecard: the twenty rows, the verdict, the five questions;/cycles/design/c140/parity: the cost of two surfaces, the drift log, the divergence register's seed, the docs proposal;/cycles/design/c140/tools: ten candidates, ranked.
- Review stop 1 walked and ruled (2026-11-12, Mark): the eleven calls were walked in the session in four sets, with fourteen rulings (
review-1.md§ Ruled). Four differ from the default:- D1: the second surface is QGUIkit, now. D2 follows: the crate
layerbecomesqguikit. - D6: the slot equivalents are named now and the APIs refactored later. DataTable's silent truncation stays a recorded gap until then.
- D7: keyboard and focus come after V1 ships, a gap written down for operators.
- D11:
/native-portandspec-measureare built first.
The rest took the defaults:- D3: the dual-surface docs get a new cycle.
- D4: c135 covers both surfaces.
- D5: the token sweep, with motion tokens and a lint.
- D8: the web's names.
- D9: the full crate restructure.
- D10: the manifest field split.
- D12: the web bugs filed back.
- D13: all four small items, after the merge.
- D14: one qnative cycle for the code.
Carried the same day:- The glossary names QGUIkit, and GPUI and GPUI Kit are told apart.
- The pages say QGUIkit and show each ruling beside its correction, with an outcome box on the scorecard.
handon-qnative.md: the qnative cycle's brief, five steps in Mark's order with two review stops.qdash-todos.md: the three web bugs with the native fix for each, ready to file. qdash's todos live in Mark's Logseq, which this session doesn't write.- c141 Surface Docs opened at Stage 1 (
../c141.surface-docs/initial-prompt.md). - c135's CYCLE.md records D4.
- D1: the second surface is QGUIkit, now. D2 follows: the crate
- qnative c8, steps 1–2 (2026-11-12, run in this session on Mark's word):
- c7 was merged first, on his ruling.
- The four commits on qnative
main, unpushed:- D2: the crate is
qguikit(a5ca520). - D13: the token bridge moved to qnative, with
--checkand a CI job (8b1af18); design'sscripts/tokens-to-kit.mjsis now a wrapper. - D13: the six flaws (
be4545f). - D13: the specs committed in qnative c2, and the bridge's source named (
bc60635).
- D2: the crate is
- Here: the bridge fixture synced, and qdash todo #4 (the empty box in dark mode).
- qnative c8 is at review stop 1 (
../../../qnative/cycles/c8.qguikit-cleanup/review-1.md) with three calls.
- The two tools, D11 (2026-11-12, run in this session on Mark's word; built by a helper agent, checked by hand):
scripts/spec-measure.mjs: Playwright on qdash at 1120 × 720 writes a JSON and a markdown spec, with:- the column widths;
- type per text role;
- colours mapped to the layer's roles in light and dark;
- radii and the copy;
--statesfor loading, failed and filtered-to-nothing;--nativeto check a Rust page's widths.
It takes 4 s a route. On Tools it matches the hand spec within 1 px on all 7 columns and the native page on 0 of 7: the native widths were set by hand, and the native grid scrolls by 88 px where the web's scrolls by 30..claude/skills/native-port/: the eight-step port loop./gpui-storyfixed:- the page tests run in
-p stories; - the four worlds,
meridian-day90the default; - the region-text test written out;
- the dead
PATTERNS.mdpointer redirected.
- the page tests run in
- The record:
native-port-tools.mdand the worked run inspecs/. - The states pass found a fifth web bug (qdash-todos #5): the Tools band shows zeros while loading and when qdash is down.
Outcome
The shape
The problem. Two implementations of one vocabulary drift apart silently, one small change at a time, wherever a person, not a machine, is the one who remembers. They also drift wherever a difference is never written down, so the next person cannot tell a decision from an accident.
The core idea. Score each principle by how it is held:
- 5: by construction;
- 4: in practice;
- 3: with named exceptions;
- 2: only by care;
- 1: not at all.
The course correction for each is the smallest move up that ladder, and most of them turn an eye-held check into a machine-held one.
The pieces.
- the rubric (
plan.md); - four readers' evidence;
- twenty rows;
- the three worked changes;
- the check table (machine · eye · nothing);
- the drift log;
- the copies;
- the divergence register's seed;
- the docs proposal;
- fifteen course corrections;
- ten tools.
The pattern. Every divergence is one of:
- a flavor (welcome it, write it down);
- a gap (write it down until it closes);
- a flaw (fix it).
The Surface glossary entry is the rule, and the register is where it lives.
What stays open. The eleven calls in review-1.md:
- the second surface's name;
- where the dual-surface docs are built;
- c135's scope;
- tokens for type, radius and motion;
- the slot equivalents;
- the keyboard pass;
- names;
- what leaves the component crate;
- the manifest field;
- which tools first;
- the web bugs the port fixed.