From a21515da98d1dd35aac80335089a6e09315bff27 Mon Sep 17 00:00:00 2001 From: Becky Still Date: Sun, 19 Jul 2026 13:37:06 +0100 Subject: [PATCH 01/32] =?UTF-8?q?docs(ux):=20a=20UX=20review=20of=20agentc?= =?UTF-8?q?ulture.org=20=E2=80=94=20findings=20and=20proposals?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit An outside UX review contributed as docs/ux-review/. Additive only: no file under site-astro/ is modified. Reviewed against a local production build at d71a719. Seven findings, each with its measurement and a re-run recipe: - /agents/ renders 30 cards in one visual language leading to three kinds of destination (4 in-site pages, 25 GitHub, 1 other host) with no signal which - the clickable region on those cards is 4% of the card; the home page already solves this with a whole-card anchor - the intro copy ("Every entry links to its public repository") is now false for 5 of 30 entries - 30 entries across 6 groups with no jump list, anchors or counts - /learn/ sits first in the primary nav and 404s until cutover - the four agent pages are structural clones; ReachyTerminal is ColleagueTerminal with every class r-prefixed, against Astro's automatic style scoping - 92 outbound links carry no off-site affordance Also records what was checked and found correct — contrast (AA in both themes, lowest 6.37:1), heading order on all 8 routes, scrollable-table role/tabindex/aria-label, mobile layout at 360px, and the reduced-motion and no-JS handling. Those sections mark what a fix could regress. Artefacts are self-contained HTML and markdown so they can be read by agents or opened in a browser without a build step. Each copies the site's own tokens verbatim; none introduces a colour, font or radius the site does not already define. Note for review: no version bump is included. The version-check job fails any PR whose pyproject.toml version matches main's, so run the version-bump skill before opening this. --- docs/ux-review/README.md | 115 ++ docs/ux-review/agent-page-scaling.md | 235 +++ docs/ux-review/agents-directory.html | 719 +++++++++ docs/ux-review/captures-layout.html | 1488 +++++++++++++++++++ docs/ux-review/findings.md | 299 ++++ docs/ux-review/spacing-type-and-captures.md | 247 +++ docs/ux-review/spacing-type-system.html | 421 ++++++ 7 files changed, 3524 insertions(+) create mode 100644 docs/ux-review/README.md create mode 100644 docs/ux-review/agent-page-scaling.md create mode 100644 docs/ux-review/agents-directory.html create mode 100644 docs/ux-review/captures-layout.html create mode 100644 docs/ux-review/findings.md create mode 100644 docs/ux-review/spacing-type-and-captures.md create mode 100644 docs/ux-review/spacing-type-system.html diff --git a/docs/ux-review/README.md b/docs/ux-review/README.md new file mode 100644 index 0000000..5c721b1 --- /dev/null +++ b/docs/ux-review/README.md @@ -0,0 +1,115 @@ +# UX review — agentculture.org + +An outside UX review of the built site, contributed for the maintainers and their +agents to work with. Nothing here changes any site file; every artefact is a +proposal, and each states its method so it can be checked rather than taken on +trust. + +Reviewed against a local production build at commit `d71a719` +(`site-astro@0.0.1`, Astro static output, 8 routes). + +## Start here + +**[`findings.md`](findings.md)** — the audit. Seven findings, each with the +measurement behind it and a re-run recipe. It also records what was checked and +found correct, which matters as much as the findings: contrast, heading order, +scrollable-table accessibility, mobile layout and the reduced-motion / no-JS +handling are all in good shape, and it would be easy to regress them while +addressing something else. + +## The artefacts + +The review comes in two halves, written independently and gathered here. + +**Site-wide** — information architecture, affordance and pattern consistency +across all 8 routes: + +| File | Kind | Covers | +|------|------|--------| +| [`findings.md`](findings.md) | Markdown | The full audit — findings 1–7, method, and what is already right | +| [`agents-directory.html`](agents-directory.html) | Interactive | Findings 1–4. Live before/after on real data, three options measured | +| [`agent-page-scaling.md`](agent-page-scaling.md) | Markdown | Finding 6 in full, with a proposed component API and sequencing | + +**Section-level** — spacing, type rhythm and layout, measured against +`/agents/devague/`: + +| File | Kind | Covers | +|------|------|--------| +| [`spacing-type-and-captures.md`](spacing-type-and-captures.md) | Markdown | The write-up for both artefacts below — evidence, tokens, and the layout recommendation | +| [`spacing-type-system.html`](spacing-type-system.html) | Interactive | Spacing and type tokens, with the operator-skills section rendered live from them | +| [`captures-layout.html`](captures-layout.html) | Interactive | Four layouts for the captures section, measured, recommending option D | + +The HTML files are self-contained — no build step, no network requests, no +dependencies. Open them directly in a browser, or serve the folder: + +```bash +npx serve docs/ux-review -l 4400 +``` + +Each one copies the site's own token values verbatim from +`site-astro/src/styles/global.css`. No artefact introduces a colour, font, radius +or shadow that the site does not already define. Where a proposal adds a token — +the spacing and line-height scales in `spacing-type-system.html` — it is marked +as proposed and shown against the current value it replaces. + +## Suggested reading order + +For a maintainer or an agent picking this up cold: + +1. `findings.md` — the summary table alone gives the shape of it. +2. `agents-directory.html` — the highest-value change, and the one with the + smallest diff. Findings 1 and 2 share a fix that costs one derived boolean. +3. `agent-page-scaling.md` — the finding that compounds. Cheaper to act on before + the fifth agent page than after. +4. `spacing-type-and-captures.md` and its two artefacts, which are narrower, + measured against `/agents/devague/`, and can be picked up independently of + everything above. + +The two halves reach the same conclusion from opposite ends. The site-wide audit +finds the pattern library drifting because it is copied per page +(`agent-page-scaling.md`); the section-level work finds spacing drifting because +it is `em`-derived rather than tokenised (`spacing-type-and-captures.md`). Both +are the same class of problem — a value that is re-decided in each new place +instead of being defined once — and the fixes are complementary rather than +overlapping. + +## What has and has not been verified + +**Verified by measurement** — every number in `findings.md` was taken from the +built site or the source, and the command that produced it is quoted alongside. +The `agents-directory.html` demo re-derives its central measurement live in the +browser from the rendered DOM rather than asserting it, and independently arrives +at the same 4% figure quoted in the audit. + +**Not verified** — none of the proposals has been implemented against the real +site, so none has been through the repo's own gates: `npm run build`, +`org site link-check`, `markdownlint-cli2`, or the SonarCloud quality gate. The +component API sketched in `agent-page-scaling.md` is a proposal, not tested code; +it should be treated as a starting shape to argue with, not a specification. + +**One correction worth surfacing** — an earlier pass of this review recorded a +scroll-reveal bug on `/agents/`, where elements sat at `opacity: 0` inside the +viewport. That was wrong, and it is retracted in `findings.md`. The +`IntersectionObserver` threshold behaviour is correct, and the blank renders that +prompted it came from a stuck renderer in the review tooling, not from the site. +The reveal system is sound. It is flagged here because a reader skimming for +problems should not carry away a defect that does not exist. + +## Constraints respected + +- **No site files touched.** This folder is additive; nothing under `site-astro/` + is modified. +- **Markdown lints clean** against the repo's `.markdownlint-cli2.yaml`. +- **Version bump.** The repo's `version-check` CI job fails any PR whose + `pyproject.toml` version matches `main`'s, including docs-only changes. That + bump has not been made here — use the `version-bump` skill before opening a PR. +- **`main` is protected**, so this arrives as a branch for review rather than a + direct push. + +## Scope + +This review covers the site's user experience: information architecture, +interaction, affordance, accessibility and the consistency of the pattern +library. It does not cover the Python CLI, the deploy workflow, the vendored +skills, or content accuracy beyond the one place where copy contradicts the page +it sits on (finding 3). diff --git a/docs/ux-review/agent-page-scaling.md b/docs/ux-review/agent-page-scaling.md new file mode 100644 index 0000000..89b88e0 --- /dev/null +++ b/docs/ux-review/agent-page-scaling.md @@ -0,0 +1,235 @@ +# Agent pages don't scale — finding 6 in full + +The four presentation pages under `/agents/` are the best work on the site. They +are also, structurally, one page written four times. This note sets out the +measurement, why it is a UX problem rather than only a tidiness problem, and a +proposed shape that keeps everything good about the current pages. + +This is the one finding that is cheaper to act on before the fifth page than +after. + +## What is there now + +| Page | Lines | Diagram | Terminal | Terminal lines | +|------|-------|---------|----------|----------------| +| `colleague.astro` | 844 | `ColleagueDiagram` | `ColleagueTerminal` | 485 | +| `reachy-mini-cli.astro` | 634 | `ReachyDiagram` | `ReachyTerminal` | 406 | +| `devague.astro` | 612 | `DevagueFlow` | `DevagueTerminal` | 426 | +| `lobes.astro` | 497 | `LobesDiagram` | `LobesTerminal` | 200 | + +2,587 lines of page, 1,517 lines of terminal component. Four agents presented. +Thirty in the directory. + +Every page imports the same seven modules in the same order: + +```astro +import Layout from "../../layouts/Layout.astro"; +import PageHero from "../../components/PageHero.astro"; +import Diagram from "../../components/Diagram.astro"; +import Terminal from "../../components/Terminal.astro"; +import site from "../../data/site"; +import from "../../data/"; +``` + +Every page opens with a `Fast facts` section and closes with `Closing`. In +between, the four share no structure whatsoever: + +| | Sections between `Fast facts` and `Closing` | +|---|---| +| colleague | The paradigm · Three tiers · The work loop · The workforce · Cortex and senses · Eidetic memory · More surfaces · Dogfood · What's next | +| devague | The pipeline · The method · The human gate · The operator skills · Real captures · What's next | +| lobes | The lobes · The command · Profiles · The Mesh-brain · Benchmarks | +| reachy | The body · The noun map · The single-SDK-owner model · The senses, live · Thinking out loud · Agent-first · What's next | + +Some of that divergence is real and good — a robot page should not be shaped +like a spec-pipeline page. But the *shared* parts diverge too, and that is the +part worth fixing. + +## The terminal components are the clear case + +All four render the same idea: a captured terminal session with a title bar, a +timestamp, a prompt, and output. `ReachyTerminal` is `ColleagueTerminal` with +every class name given an `r` prefix: + +| ColleagueTerminal | ReachyTerminal | +|-------------------|----------------| +| `.term` | `.rterm` | +| `.term-head` | `.rterm-head` | +| `.dot` | `.rdot` | +| `.stamp` | `.rstamp` | +| `.title` | `.rtitle` | +| `.context` | `.rcontext` | +| `.source` | `.rsource` | + +Astro scopes component styles automatically — every element in the built HTML +carries a `data-astro-cid-*` attribute, and the four terminals already have four +different ones. The rename prevented a collision that could not have occurred. +That is the signature of copy-paste rather than of divergent design need. + +Reproduce: + +```bash +cd site-astro/src/components +diff <(sed 's/[Cc]olleague//g' ColleagueTerminal.astro) \ + <(sed 's/[Rr]eachy//g' ReachyTerminal.astro) | grep -c '^[<>]' +``` + +## Why this is a UX problem, not only a code problem + +Four independent copies means four places where the same decision gets made, and +nothing holds them in agreement. + +The drift is already measurable. `LobesTerminal` is 200 lines; `ColleagueTerminal` +is 485. The two render the same concept at less than half the fidelity — the +lobes terminal has no `.context`, no `.source`, no provenance tagging, where the +colleague one does. A visitor moving between the two pages is looking at two +different components that are trying to be the same thing. + +With four pages this reads as variety. With ten it reads as inconsistency, and +the site stops feeling like one site. The presentation pages are the org's +strongest argument that it builds carefully; a directory of pages that each +handle a terminal capture slightly differently undercuts exactly that argument. + +There is also a straightforward cost argument. Written this way, agent five is +another ~600 lines of page and another ~400 of terminal, most of it transcribed +from a sibling. Written against a shared shell, agent five is a data module. + +## The data layer is already the right shape + +This is the part that makes the fix cheap. The per-agent data modules already +exist and already separate content from presentation: + +```text +src/data/colleague.ts 657 lines +src/data/devague.ts 445 +src/data/reachy-mini-cli.ts 562 +src/data/lobes.ts 236 +src/data/*-captures.ts (four more, capture content) +src/data/types.ts the shared shape +``` + +The pages are not carrying the content — the data modules are. What the pages +carry is layout, and that is what has been copied. The refactor is therefore +mostly deletion, not redesign. + +## Proposed shape + +Two shared components and one convention. Nothing here changes what any page +says, only how it is assembled. + +### 1. `` — one component, content from data + +```astro +--- +// src/components/Terminal.astro +interface Props { + /** Window title — e.g. "colleague run --task …" */ + title: string; + /** Timestamp shown in the head bar. */ + stamp?: string; + /** Where this capture came from — repo, run id, or doc reference. */ + source?: string; + /** Working context line shown above the prompt. */ + context?: string; + /** The captured lines. */ + lines: TerminalLine[]; + /** Provenance: "fresh" | "ported" — rendered as a tag when present. */ + provenance?: "fresh" | "ported"; +} +--- +``` + +`TerminalLine` goes in `src/data/types.ts` alongside the existing shapes: + +```ts +export type TerminalLine = + | { kind: "prompt"; text: string } + | { kind: "out"; text: string; accent?: string } + | { kind: "ellipsis" }; +``` + +Every accent class currently hard-coded per agent — `.accent-dogfood`, +`.accent-lobes`, `.leg-challenge`, `.prov-ported` and the rest — becomes the +`accent` field on a line, resolved against one shared map. That is what makes a +single component able to serve all four pages without losing any of the +per-agent colour they currently have. + +### 2. `` — the shell + +```astro +--- +// src/components/AgentPage.astro +interface Props { + /** Matches the directory entry name in data/site.ts. */ + name: string; + /** One-line role, reused from data/site.ts — single source of truth. */ + role: string; + /** The Fast facts rows every page already opens with. */ + facts: Fact[]; + /** The closing section every page already ends with. */ + closing: string[]; +} +// Sections in between arrive via named slots, so pages keep full freedom +// over their own middle while the shell guarantees the shared parts. +--- +``` + +Pages then read as their own structure and nothing else: + +```astro + +
…the lobes…
+
…the command…
+
+``` + +### 3. Keep the bespoke diagrams + +`ColleagueDiagram`, `LobesDiagram`, `ReachyDiagram` and `DevagueFlow` should stay +separate. They genuinely draw different things — a tier stack, a lobe map, a +robot body, a nine-stage flow — and there is no shared abstraction worth +inventing for four drawings that have nothing in common. This proposal is about +the parts that are the same, not the parts that merely sit in the same slot. + +## What this buys + +| | Now | Proposed | +|---|---|---| +| Lines to add agent five | ~1,000 | a data module | +| Places a terminal style is defined | 4 | 1 | +| Guarantee two pages agree | none | structural | +| Per-agent visual identity | per-page CSS | `accent` in data | +| Bespoke diagrams | 4 | 4, unchanged | + +## Suggested sequence + +The refactor is worth doing in this order, because each step is independently +reviewable and each leaves the site working: + +1. **Add `TerminalLine` to `types.ts` and build ``** against the + richest existing case, `ColleagueTerminal`. Nothing else changes yet. +2. **Port `lobes` to it** — the smallest and least risky of the four, and the one + that currently loses the most by being a thin copy. This is where the + consistency win becomes visible. +3. **Port `reachy` and `devague`.** Delete the three superseded components. +4. **Extract ``** once three pages have been through step 3 and the + genuinely shared shell is known from evidence rather than guessed at. + +Step 4 deliberately comes last. The shell should be extracted from what the pages +turned out to share, not designed up front — the current pages are the best +available evidence of what an agent page actually needs, and that evidence is +easier to read once the terminals stop varying. + +## What this proposal does not touch + +- No change to any page's copy, section order, or bespoke diagram. +- No change to the data modules' content — only the addition of `TerminalLine` + to `types.ts`. +- No change to the accessibility work, which is correct throughout and documented + in [`findings.md`](findings.md) under *What is already right*. In particular the + `role="region"` / `tabindex="0"` / `aria-label` treatment on scrollable tables + is consistent across all four tables today and must survive any shell + extraction. +- No new runtime dependency. `pyproject.toml`'s zero-dependency rule is a Python + constraint and does not reach the site, but the site has no framework JS today + and this proposal does not add any. diff --git a/docs/ux-review/agents-directory.html b/docs/ux-review/agents-directory.html new file mode 100644 index 0000000..365f08a --- /dev/null +++ b/docs/ux-review/agents-directory.html @@ -0,0 +1,719 @@ + + + + + +The agents directory — proposal for agentculture.org + + + + +
+
+ +

The agents directory — one affordance, two destinations

+

+ Four findings on /agents/, worked as one change because they + share a fix. Measured against the built site at commit d71a719. + Every card below is a real entry from src/data/site.ts. +

+ +

0 — What the audit found

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
#FindingMeasured
130 cards, one visual language, three kinds of destination — 4 in-site + pages, 25 GitHub repos, 1 other hosted site. No signal which.4 / 25 / 1High
2Only the agent name is an anchor. The card is the visual target; + one line of text is the real one.4% of card
24px tall
High
3Intro says “Every entry links to its public repository.” Five no + longer do.5 / 30 falseMedium
4Six groups, no jump list, no anchors, no counts. Groups are only + findable by scrolling past them.30 entriesMedium
+ +

+ Findings 1 and 2 have the same fix, and it is a small one: the data layer + already knows which entries are in-site, because their url starts + with /. Nothing new needs to be stored and no content needs + rewriting — the distinction just needs to be rendered. +

+ +

1 — The card, before and after

+ +

+ Same eight entries, same tokens, same grid. Toggle between the current build + and the proposal, and turn on show click targets to see + finding 2 directly — the shaded region is what actually responds to a click. +

+ +
+
+
+ + +
+
+ +
+
+
+
+
+

Mesh & platform

+
    +
    +
    +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    MeasureCurrentProposedChange
    Clickable share of card4%100%×25
    Target height24px~250px≥44px
    Destination legible before clicknoyesfixed
    Matches the home-page card modelnoyesfixed
    + +

    + The “proposed” treatment is not new design — it is the treatment already used + by the three teasers on /, which are a.card with a + hover lift and a sliding arrow. This makes the two card grids agree rather + than introducing a third pattern. +

    + +

    2 — Telling the two destinations apart

    + +

    + Three ways to signal it, in increasing strength. All three are shown against + real entries: colleague and lobes-cli have pages, + the rest do not. +

    + +
    +
    +
    + + + +
    +
    +
    +
    +
    +
    + + + + + + + + + + + + + + + + + + + + + + + +
    OptionReads at a glanceCostRisk
    A — label + glyph
    “Read the page →” vs a repo glyph
    StrongestOne derived boolean, one line of markupAdds a line of height per card
    B — glyph only
    A small mark in the corner
    ModerateLowest — no layout changeGlyphs alone are learned, not read; needs assistive text
    C — separate the groups
    Pages promoted above the fleet
    StrongestHighest — reorders the pageBreaks the existing “grouped by what it does” model
    + +

    + Recommendation: A. It is the only one that states the + difference in words rather than asking the visitor to infer it, and it costs + one derived boolean: +

    + +

    const hasPage = agent.url.startsWith("/");

    + +

    + C is worth revisiting when there are more than about ten presentation pages. + Today, with four, promoting them above the six existing groups would fight the + page's own organising idea for a section that would hold four cards. +

    + +

    3 — Wayfinding at thirty entries

    + +

    + A jump list with counts, and id anchors on each group so a group + is linkable. The filter is a progressive enhancement — with JavaScript off, + the jump list is plain anchor links and everything still works. +

    + +
    +
    + Proposed — jump list, anchors, optional filter +
    +
    +
    + + +
    +
    +
    + +
      +
    • Group headings get ids, so /agents/#edge-robotics + becomes a shareable link — useful when pointing an agent or a person at one + part of the fleet.
    • +
    • Counts set expectations before the scroll starts.
    • +
    • The filter announces its result count via role="status", so a + screen reader hears the list change.
    • +
    • Filtering hides groups that empty out, so there are no orphan headings.
    • +
    + +

    4 — The intro sentence

    + +

    Finding 3 is one string in src/data/site.ts. Current:

    +

    + This is a curated selection of the fleet, grouped by what each agent does. + Every entry links to its public repository. +

    +

    Suggested, once the cards distinguish themselves:

    +

    + This is a curated selection of the fleet, grouped by what each agent does. + Some have a page here; the rest link straight to their public + repository. +

    +

    + The replacement is a stronger sentence than a merely accurate one: it tells + the visitor the presentation pages exist, which the current copy actively + conceals. +

    + +

    5 — What this does not change

    + +
      +
    • No new colour, font, radius or shadow. Every value is an existing token.
    • +
    • No change to the six groups or their order.
    • +
    • No change to any role text or repo name.
    • +
    • No JavaScript required for anything except the filter, which is additive.
    • +
    • Heading order stays h1 → h2 → h3, unchanged.
    • +
    + +
    +

    + Part of docs/ux-review/ — see findings.md for the + full audit and method. +

    + +
    +
    + + + + + diff --git a/docs/ux-review/captures-layout.html b/docs/ux-review/captures-layout.html new file mode 100644 index 0000000..3b5c943 --- /dev/null +++ b/docs/ux-review/captures-layout.html @@ -0,0 +1,1488 @@ + + + + + +Captures section — layout options + + + + +
    +
    +

    Captures section — three ways to kill the whitespace

    +

    Measured on the live page at 1280×720. All three options below use the real captured transcripts, so the card heights are truthful. Colour and content unchanged.

    + +

    What is actually causing it

    +

    The ten captures are not one gallery. They are five separate .term-grid containers, each holding exactly two figures. Each pair is sized independently, so a short card can never borrow the space left by its tall neighbour — the gap below it is structural, not a styling oversight.

    +
    + + + + + + + + + + +
    RowLeftRightDead space
    1 — frame announce / interrogate742px948px206px
    2 — the gate / plan496px945px449px
    3 — scope / the gate refuses1084px684px400px
    4 — deviate / summary205px563px358px
    5 — challenge sweep / adjudicate712px377px335px
    Total1748px
    +
    +

    Either option requires the same markup change: all ten figures move into one container. That is the real work; the CSS is small.

    + +

    Type and spacing fixes, applied to both

    +
    + + + + + + + + + + + + +
    PropertyNowProposedWhy
    pre line-height1.7--lh-normal · 1.551.7 is prose leading applied to a code block. Tightening is more readable for monospace and takes roughly 9% off every card's height — it helps the whitespace problem directly.
    pre padding16.8 / 18.4 / 19.2--space-5 · 24Three different values on one element, none of them round. Nothing is gained by the asymmetry.
    .term-head padding11.2 / 18.4--space-3 / --space-5Snaps the head to the same rhythm as the body.
    Head meta tracking+0.03em--ls-flat · 0Positive tracking on monospace again — same issue as .skill-name in the other section.
    Head meta line-height1.7--lh-ui · 1.25Single-line labels carrying prose leading — the phantom-leading bug, here too.
    Grid gap20.8px--space-5 · 24The “standard gap”, and the same value as the card padding.
    Transcript size10.23px--fs-term · 13The one I would fix first. See below.
    Elision notes8.70px--fs-term-note · 12Sub-9px italic on a dark background is decorative rather than readable.
    +
    + +

    The legibility problem underneath

    +

    The transcripts do not render at 12.48px. pre is 12.48px, but code and .tl inside it shrink again by .82em, so the actual rendered transcript text is 10.23px — and the elision notes, shrunk once more, land at 8.70px. Nobody chose those numbers; they are what em compounding produces through three nested levels.

    +

    This is the same root cause as the fractional spacing, but here it costs legibility rather than rhythm. Both mocks below set the size once on pre and let it inherit. The cards get taller as a result — that is the honest price of readable text, and it is an argument for Option B rather than against the fix.

    + +

    Option A — masonry, the gallery pattern

    +

    CSS multi-column. Uniform gap, cards at their natural height, no dead space. This is what you described, and it does exactly what it promises.

    +
      +
    • Reading order changes. Columns flow top-to-bottom then across, so you read captures 1–5 down the left, then 6–10 down the right. These captures are a pipeline narrative — scope, frame, challenge, plan, deviate, summary — so that reordering has a cost.
    • +
    • The section gets very long. Removing the dead space does not remove the content; the tallest transcript is ~19,500 characters. Scroll the mock and you will feel it.
    • +
    • grid-template-rows: masonry is not broadly shipped, so multi-column or JS are the real choices today. Multi-column needs no JS, which is why it is used here.
    • +
    +
    +
    + +
    +
    +
    +
    Option A — masonryno dead space · reading order changes
    +
    + +
    +
    +
    +
    + +
    +
    +

    Option B — uniform grid, capped, scrolls inside

    +

    Every card the same height; the transcript scrolls within it. No dead space either, but the section stays a fixed, scannable size and the sequence survives.

    +
      +
    • Reading order is preserved — left to right, in the order the pipeline runs.
    • +
    • The tallest card today is 1084px, which nobody reads as a static block anyway. Terminals scroll; this is the honest metaphor rather than a decorative one.
    • +
    • The section becomes scannable. Ten equal cards read as a set you can survey, rather than a wall you must scroll past to reach the next section.
    • +
    • The cost: content is hidden behind a scroll, so the page no longer shows everything at once. A bottom fade signals there is more.
    • +
    +
    +
    + +
    +
    +
    +
    Option B — capped & scrollingno dead space · order preserved
    +
    + +
    +
    +
    +
    + +
    +
    +

    Option C — one column, full width

    +

    The whitespace problem exists because there are two columns. Remove the second one and no mismatch is possible — there is no neighbour to be shorter than. Cards take their natural height, nothing is capped, nothing is hidden, nothing reorders.

    +
      +
    • Wide lines are the native format for terminal output. At full width the transcripts wrap roughly half as much, which is why this is not simply “twice as tall as two columns”. Less wrapping is also genuinely easier to read — wrapped monospace is the thing that makes transcripts hard to follow.
    • +
    • Nothing is hidden and nothing is nested. No scroll-within-a-scroll, which is the real cost of Option B — nested scrolling is awkward on a trackpad and worse on touch.
    • +
    • Order is exact, and the section reads as a chronology rather than a grid.
    • +
    • The cost is honesty about length. At 6300px this is the longest of the three — but only 1.3× Option A, not 2×, because of the reduced wrapping. It does not pretend the content is smaller than it is.
    • +
    +
    +
    + +
    +
    +
    +
    Option C — single columnnothing hidden · nothing reordered
    +
    + +
    +
    +
    +
    + +
    +
    +

    Option D — capped preview, expands in place

    +

    The compact-but-complete answer. Cards are capped to a preview height and clipped — not scrolled — and any card whose content is cut gets an expand control. Opening a card spans it across both columns at full width, where it wraps less and reads better than it could in either grid.

    +
      +
    • It removes Option B's worst trait. Nothing scrolls inside anything. Nested scrolling is the thing that makes B awkward on a trackpad and genuinely bad on touch; here the page scrolls and cards open.
    • +
    • max-height, not height. A genuinely short card — deviate is 226px — stays short instead of padding itself out to a uniform size with empty dark space. Dead space inside a card reads as a bug; a short card next to a tall one reads as content.
    • +
    • Expanded is the best reading mode on the page. Full width means far less wrapping, so an opened card is shorter and clearer than the same transcript in Option C's single column.
    • +
    • Order survives. Cards open in place, so the sequence never changes.
    • +
    • The cost: it needs JavaScript. About fifteen lines. A CSS-only version is possible with <details>, but that cannot show a clipped preview — closed means empty — and the checkbox-and-label alternative has real accessibility problems. A button with aria-expanded is the honest way to build this.
    • +
    • The fade is applied only where content is actually clipped, measured after layout — so short cards do not get a fade over empty space, and their expand control is removed rather than left to do nothing.
    • +
    +
    +
    + +
    +
    +
    +
    Option D — expand in placecompact · complete · nothing nested
    +
    + +
    +
    +
    +
    + +
    +
    +

    The four, measured

    +

    Section height at a 1400px viewport, same content, same type fixes applied to all four:

    +
    + + + + + + + + +
    OptionHeightDead spaceOrderHidden content
    A — masonry4840pxnonescrambled — 1–4 left, 5–10 rightnone
    B — capped + scroll2496pxnonepreserved9 of 10 cards scroll
    C — single column6300pxnonepreservednone
    D — expand in place2496px254px*preservedone click, nothing nested
    +
    +

    * Option D's 254px is one row, beside the deviate capture, which is genuinely only 226px of content. Option B reaches 0 only by padding that same card out to a uniform 480px — the empty space still exists, it just sits inside the card instead of beside it. The two are equivalent; D's is the more honest presentation.

    + +

    Recommendation

    +

    The measurement undercuts Option A. Masonry sits in the middle on height (4840px) while being the only one of the four that reorders the captures. It pays a real cost — a pipeline narrative read out of sequence — and does not buy the shortest section in return. On these numbers it is hard to argue for.

    +

    Option D is the strongest of the four. It matches Option B's 2496px collapsed — the shortest of the four — while removing every one of B's costs. Nothing scrolls inside anything. Nothing is permanently hidden. Order is preserved, verified with a card open. And an expanded card is the best reading mode on the page: at full width the transcript wraps so much less that capture 1 shows completely in 607px, having needed a 480px window to show a fraction of itself collapsed.

    +
      +
    • The real cost is the JavaScript — about fifteen lines, and a <details> version cannot show a clipped preview. If a no-JS constraint exists, that rules D out and the choice falls back to C.
    • +
    • Option C remains the best no-JS answer. 6300px, nothing hidden, nothing nested, nothing reordered. Longer, but honest and completely static.
    • +
    • Option B is now hard to justify. D matches its height and beats it on every other axis.
    • +
    +

    All four need the same markup change first: ten figures, one container.

    +
    +
    + + + + + diff --git a/docs/ux-review/findings.md b/docs/ux-review/findings.md new file mode 100644 index 0000000..b83744c --- /dev/null +++ b/docs/ux-review/findings.md @@ -0,0 +1,299 @@ +# UX findings — agentculture.org + +An outside review of the built site, measured against a local production build +at commit `d71a719` (`site-astro@0.0.1`, Astro static output, 8 routes). + +Every claim below is measured, not impressionistic. Method is stated per finding +so an agent can re-run it and confirm or refute independently. Where the site was +checked and found correct, that is recorded too — see +[What is already right](#what-is-already-right). Those sections are not padding: +they mark the things a well-meaning refactor could easily break. + +## How to re-run the measurements + +```bash +cd site-astro +npm ci && npm run build # needs Node >= 22.12 (.nvmrc says 24) +npx serve dist -l 4321 +``` + +Then evaluate the snippets quoted in each finding against the served page. + +## Summary + +| # | Finding | Surface | Severity | +|---|---------|---------|----------| +| 1 | One affordance, two destinations — cards leave the site with no signal | `/agents/` | High | +| 2 | The clickable region is 4% of the card | `/agents/` | High | +| 3 | Intro copy contradicts the page it introduces | `/agents/` | Medium | +| 4 | 30 entries, 6 groups, no wayfinding | `/agents/` | Medium | +| 5 | `Learn` is in the primary nav and 404s in this build | all pages | Medium | +| 6 | Agent pages are structural clones — the pattern does not scale | `/agents/*` | Structural | +| 7 | 92 outbound links, no "leaves the site" affordance | all pages | Low | + +Findings 1–4 are one page and are worth fixing together; a worked, interactive +proposal for all four is in [`agents-directory.html`](agents-directory.html). +Finding 6 is the one that compounds — see +[`agent-page-scaling.md`](agent-page-scaling.md). + +## 1 — One affordance, two destinations + +`/agents/` renders 30 cards in a single visual language. They lead to three +different kinds of place: + +| Destination | Count | Example | +|-------------|-------|---------| +| An in-site presentation page | 4 | `colleague` → `/agents/colleague/` | +| GitHub, off-site | 25 | `irc-lens` → `github.com/agentculture/irc-lens` | +| A different hosted site | 1 | `learn-cli` → `agentculture.org/learn/` | + +Nothing in the card distinguishes them. A visitor who clicks `colleague` lands on +a considered 844-line presentation page and learns the org builds those. The same +visitor clicking `irc-lens` — visually identical, one card away — is thrown to a +GitHub repo, out of the site, with no way back but the back button. + +The four presentation pages are the most substantial work in the repo, and the +directory hides them behind the same treatment as a bare repo link. This is the +finding with the largest gap between effort spent and effort visible. + +**Method.** From `src/data/site.ts`: + +```bash +node -e ' +const s=require("fs").readFileSync("src/data/site.ts","utf8"); +const urls=[...s.matchAll(/url: "([^"]+)",\n\s+role:/g)].map(m=>m[1]); +console.log(urls.length, urls.filter(u=>u.startsWith("/")).length, + urls.filter(u=>u.startsWith("https://github.com")).length);' +# → 30 4 25 +``` + +**Suggested direction.** The data layer already knows which is which — `url` +starting with `/` is in-site. The distinction can be derived, with no new field +and no content edit. Rendering it is the whole fix: a "Read the page →" action on +the four, a repo glyph on the rest. Worked in +[`agents-directory.html`](agents-directory.html), option A. + +## 2 — The clickable region is 4% of the card + +On `/agents/` the card is a `div.card.entry`; only the agent name inside `h3` is +an anchor. The visual target is the card, the actual target is one short line of +text. + +| Measure | Value | +|---------|-------| +| Card area (1280px viewport) | 54,903 px² | +| Anchor area, median | ~1,700 px² | +| Anchor as share of card | **4%** | +| Anchor height | 24 px | + +24 px meets WCAG 2.2 SC 2.5.8 (Target Size Minimum, 24×24) but sits well under +the 44×44 that platform guidance and SC 2.5.5 (AAA) ask for. + +The same site already does this the other way round. On `/`, the three teasers +are `a.card` — the whole card is the anchor, with a hover lift and an arrow that +slides. Two card grids, two interaction models, one site. + +**Method.** On `/agents/`: + +```js +[...document.querySelectorAll('.entry')].map(c => { + const a = c.querySelector('h3 a'), cr = c.getBoundingClientRect(); + const ar = a.getBoundingClientRect(); + return (ar.width * ar.height) / (cr.width * cr.height); +}); +// → median ≈ 0.04 +``` + +**Suggested direction.** Promote the card to `a.card`, matching the home page. +This also resolves finding 1's affordance problem for free: a whole-card anchor +has somewhere to put a destination cue. + +## 3 — Intro copy contradicts the page it introduces + +`/agents/` opens with (`src/data/site.ts`, `agents.intro[1]`): + +> This is a curated selection of the fleet, grouped by what each agent does. +> Every entry links to its public repository. + +Five of the 30 no longer do — the four presentation pages and `learn-cli`. The +sentence was true when written and the site outgrew it. + +This is the drift `CLAUDE.md` already names under *"Self-description must track +reality"*, and the `doc-test-alignment` skill exists to catch. It is worth noting +that the skill did not catch this one, because the claim is prose in the data +layer rather than a doc assertion — which may be a gap worth closing separately. + +**Suggested direction.** Rewrite to describe both destinations, which is a +stronger sentence anyway once finding 1 is fixed — the presentation pages become +something the intro can advertise rather than something it denies. + +## 4 — 30 entries, 6 groups, no wayfinding + +The page is a flat scroll. The six group headings (`Mesh & platform`, `Memory & +data`, `Developer tooling`, `Cloud & infrastructure`, `Edge & robotics`, +`Learning & play`) are only discoverable by scrolling past them, there is no jump +list, no filter, no count, and no anchor links to share a group. + +At 30 entries this is friction. The org is visibly still growing. + +**Suggested direction.** A sticky group jump-list, and `id` anchors on group +headings so `/agents/#edge-robotics` is linkable. A text filter is proposed as a +progressive enhancement only — it must not become the only way to find something. +Worked in [`agents-directory.html`](agents-directory.html), option B. + +## 5 — `Learn` is in the primary nav and 404s in this build + +`src/components/Header.astro` hard-codes four nav links, the first being +`/learn/`. No `/learn/` route exists in this repo, and `npm run build` emits no +`dist/learn/`: + +```bash +npm run build && ls dist/learn +# → ls: dist/learn: No such file or directory +``` + +Commit `1e2816f` records the intent — the `learn-cli` site merges in at cutover — +so this is deliberate and dated, not an oversight. Flagging it for two reasons: + +- If the site deploys before the `learn-cli` merge, the first item in the primary + nav is a 404 on every page of the site. +- `org site link-check` walks `dist/` for internal links that 404. Either it + catches this and CI is red, or it does not walk the header, which is a gap in + the check. Both are worth knowing before cutover. + +**Suggested direction.** Nothing in the site's design needs to change. Confirm +which of the two cases holds, and gate the nav item on the merge if the deploy +could land first. + +## 6 — Agent pages are structural clones + +The four presentation pages are, structurally, one page written four times. + +| Page | Lines | Bespoke components | +|------|-------|--------------------| +| `colleague.astro` | 844 | `ColleagueDiagram`, `ColleagueTerminal` (485) | +| `reachy-mini-cli.astro` | 634 | `ReachyDiagram`, `ReachyTerminal` (406) | +| `devague.astro` | 612 | `DevagueFlow`, `DevagueTerminal` (426) | +| `lobes.astro` | 497 | `LobesDiagram`, `LobesTerminal` (200) | + +Every one imports the same seven modules in the same order, opens with a +`Fast facts` section and closes with `Closing`. In between they share no +structure at all. + +The terminal components are the clearest case. All four render the same idea — a +captured terminal session. `ReachyTerminal` is `ColleagueTerminal` with every +class name given an `r` prefix: + +| ColleagueTerminal | ReachyTerminal | +|-------------------|----------------| +| `.term` | `.rterm` | +| `.term-head` | `.rterm-head` | +| `.dot` | `.rdot` | +| `.stamp` | `.rstamp` | +| `.title` | `.rtitle` | +| `.context` | `.rcontext` | +| `.source` | `.rsource` | + +Astro scopes component styles automatically (`data-astro-cid-*` is on every +element in the built HTML), so the rename prevented a collision that could not +have happened. That is the signature of copy-paste, not of divergent design need. + +**Why it matters for UX, not just for the codebase.** Four independent copies +means four places for a spacing decision to be made differently, and nothing +holds them in agreement. The drift is already visible — `LobesTerminal` is 200 +lines against `ColleagueTerminal`'s 485, so the two render meaningfully different +UI for the same concept. There are 30 agents in the directory and four pages +built. Written this way, agent five is another ~600 lines and another chance to +diverge, and the pages stop feeling like one site. + +**Method.** + +```bash +cd site-astro/src/components +diff <(sed 's/[Cc]olleague//g' ColleagueTerminal.astro) \ + <(sed 's/[Rr]eachy//g' ReachyTerminal.astro) | grep -c '^[<>]' +``` + +**Suggested direction.** A shared `` shell plus one `` taking +its content from the per-agent data module — which already exists and is already +the right shape (`data/colleague.ts`, `data/lobes.ts`, …). Sketched with a +proposed component API in [`agent-page-scaling.md`](agent-page-scaling.md). + +This is the one finding that is cheaper to act on before the fifth page than +after. + +## 7 — 92 outbound links, no "leaves the site" affordance + +92 anchors across the built site point at external origins. None carry a visual +or assistive cue that the destination is off-site. + +```bash +grep -ohE ']*href="https?://[^"]*"' dist/*.html dist/*/index.html \ + dist/agents/*/index.html | wc -l +# → 92 +``` + +Worth stating clearly: none use `target="_blank"`, so there is **no** +`rel="noopener"` vulnerability here and none needs adding. Navigation happens in +the same tab, which is the right default and should be kept. The gap is purely +that the visitor cannot tell in advance. + +**Suggested direction.** A small outbound glyph on external anchors, plus visually +hidden text for screen reader users. Lowest priority of the seven — it only +becomes pressing on `/agents/`, where finding 1 makes it acute. + +## What is already right + +Checked, measured, and found correct. Recorded so that work on the findings above +does not regress any of it. + +**Colour contrast passes AA everywhere, in both themes.** The claim in +`global.css`'s header comment is accurate. All ten text/background token pairs: + +| Pair | Light | Dark | +|------|-------|------| +| `--ink` on `--bg` | 12.78 | 16.15 | +| `--ink-soft` on `--bg` | 6.86 | 8.88 | +| `--ink-soft` on `--surface` | 7.46 | 7.88 | +| `--accent` on `--bg` | 6.37 | 11.77 | +| `--accent` on `--surface` | 6.93 | 10.44 | + +Lowest is 6.37:1 against a 4.5:1 requirement. There is real headroom, which is +what makes the palette safe to extend. + +**Heading order is clean on all 8 routes.** No skipped levels, exactly one `h1` +per page, `h2`/`h3` properly nested — including the 37-heading `/agents/` page and +the 39-heading `colleague` page. + +**Scrollable tables are correctly exposed.** All four wide tables across three +pages carry `tabindex="0"`, `role="region"` and a descriptive `aria-label`, so +they are keyboard-scrollable and announced. This is done consistently on every +one, which is rarer than it should be. + +**Mobile layout holds at 360px.** No horizontal page scroll; the one element wider +than the viewport is the roles table, correctly contained in its `.table-wrap` +scroller rather than pushing the page. + +**Reduced motion and no-JS are handled thoroughly.** Entrance-hidden states are +gated behind both `html.js` and `prefers-reduced-motion: no-preference`, so the +site renders complete and composed with JavaScript off or motion suppressed — +and there is a global kill switch catching component-scoped transitions too. The +reveal system degrades to nothing rather than to blank content. + +> One correction to an earlier draft of this review: elements sitting at +> `opacity: 0` while inside the viewport were briefly recorded here as a reveal +> bug. They were not. The `IntersectionObserver` uses `threshold: 0.12` with +> `rootMargin: "0px 0px -36px 0px"`, so an element peeking a few pixels above the +> fold correctly has not yet triggered. The blank screenshots that prompted it +> came from a stuck renderer in the review tooling; `document.elementFromPoint` +> confirmed the content painted at `opacity: 1` throughout. The reveal system is +> sound. + +## Artefacts in this folder + +| File | What it is | +|------|------------| +| [`agents-directory.html`](agents-directory.html) | Interactive. Findings 1–4, live before/after, three options measured | +| [`agent-page-scaling.md`](agent-page-scaling.md) | Finding 6 in full, with a proposed component API | +| [`spacing-type-system.html`](spacing-type-system.html) | Interactive. Spacing and type tokens for the operator-skills section | +| [`captures-layout.html`](captures-layout.html) | Interactive. Three layouts for the captures section, measured | diff --git a/docs/ux-review/spacing-type-and-captures.md b/docs/ux-review/spacing-type-and-captures.md new file mode 100644 index 0000000..16b7776 --- /dev/null +++ b/docs/ux-review/spacing-type-and-captures.md @@ -0,0 +1,247 @@ +# UX review — spacing, type and layout + +A UX/UI contribution for `/agents/devague/`. Two areas: a **spacing and type token +system**, and the **captures section layout**. + +Everything here is additive. No existing file in this repo has been modified — this +folder contains only new documents. Colour, copy and content are unchanged throughout; +the proposals touch spacing, line-height, letter-spacing and layout only. + +| File | What it is | +| --- | --- | +| [`spacing-type-system.html`](./spacing-type-system.html) | The token proposal, with the operator-skills section rendered live from those tokens | +| [`captures-layout.html`](./captures-layout.html) | Four layout options for the captures section, each built with the real transcripts | + +Both are self-contained — open them in a browser, no build step, no network. + +**How this was measured.** Values were read from the live page at +`https://agentculture.org/agents/devague/` via computed styles and bounding boxes, at a +1280×720 viewport unless stated. Nothing here is estimated from a screenshot. + +--- + +## The short version + +The site already has a real token layer — colour, shadow, radius, fonts, easing, +`--section-pad`. What it has **no tokens for is spacing and type rhythm**, and that is +where the incoherence shows. + +Three findings are worth acting on regardless of what you think of the layout proposals: + +1. **`em` compounding is producing every fractional value on the page.** One section uses + nine distinct spacing values, none of them round. +2. **A line-height of `1.7` is inherited by single-line labels**, giving them invisible + phantom leading that makes your spacing values mean different things in different + places. +3. **The captures render at 10.23px, not 12.48px.** Same root cause, but here it costs + legibility rather than rhythm. + +--- + +## 1. Spacing — the evidence + +The operator-skills section currently uses **nine distinct spacing values**: + +```text +4.8 5.6 17.6 18.7 20.16 22.4 24 35.2 43.2 +``` + +None are round, because all are `em`-derived — so the same intended gap computes to a +different pixel value depending on the font-size it happens to sit next to. That is the +mechanism behind the wonkiness. It is not carelessness; it is a unit choice. + +### Proposed scale — 8 fixed tokens + +Fixed `rem` on a 4px base. Eight is the useful ceiling: enough for micro, component and +section rhythm, few enough that two developers reach for the same one. + +| Token | Value | +| --- | --- | +| `--space-1` | 4px | +| `--space-2` | 8px | +| `--space-3` | 12px | +| `--space-4` | 16px | +| `--space-5` | 24px | +| `--space-6` | 32px | +| `--space-7` | 48px | +| `--space-8` | 64px | + +Two **fluid** values sit alongside the fixed scale, because section padding and page +gutters legitimately scale with viewport: the existing `--section-pad`, and a proposed +`--gutter: clamp(2rem, 5vw, 6rem)`. + +### Where each lands + +| Relationship | Now | Proposed | +| --- | --- | --- | +| `.eyebrow` → `h2` | 17.6px | `--space-4` · 16 | +| `h2` → `.prose` | 20.16px | `--space-5` · 24 | +| `.prose p` → `p` | 18.7px | `--space-4` · 16 | +| `.prose` → `.skills` | 35.2px | `--space-7` · 48 | +| `.skills` gap | 17.6px | `--space-5` · 24 | +| `.skill-card` padding | 22.4 / 24px | `--space-5` · 24 | +| `.skill-name` → `.skill-leg` | 4.8px | `--space-2` · 8 | +| `.skill-leg` → `.skill-duty` | 10.4px | `--space-4` · 16 | + +Note `.skill-card` padding is currently **asymmetric** — 22.4px block, 24px inline. +Almost certainly unintended (`1.4em` vs `24px`). + +--- + +## 2. Line-height — the finding that matters most + +**`1.7` is currently inherited by every element in the section, including single-line +labels.** This is the root cause of the spacing looking arbitrary, and it is invisible in +devtools unless you go looking for it. + +Concretely: `.skill-leg` is 11.2px text in a **19.04px line box**. That is 7.8px of +leading the element carries with it — roughly 3.9px above and below the glyphs. So the +4.8px margin in the stylesheet renders as about **8.7px** of visible space. Every label on +the page is silently padded by a different amount, because the phantom leading scales with +each element's own font-size. + +Fix the leading and the spacing tokens start meaning what they say. + +| Role | Now | Proposed | +| --- | --- | --- | +| Display heading, ≥32px | 1.14 | `--lh-tight` · 1.1 | +| Long-form prose | 1.7 | `--lh-prose` · 1.7 — unchanged, correct at a 672px measure | +| Card body copy | 1.55 | `--lh-normal` · 1.55 — unchanged, already right | +| Single-line labels & titles | 1.7 | `--lh-ui` · 1.25 — **the fix** | + +--- + +## 3. Letter-spacing + +| Role | Now | Proposed | +| --- | --- | --- | +| Display, ≥32px | −0.012em | `--ls-display` · −0.02em | +| Body & card copy, 14–19px | normal | `--ls-flat` · 0 — unchanged | +| Monospace (`.skill-name`) | **+0.01em** | `--ls-flat` · 0 | +| Uppercase, ≤13px | 0.17 / 0.12em | `--ls-caps` · 0.12em | + +**Never track monospace positively.** The even glyph advance is the point of the face; +adding to it reads as accidentally broken rather than deliberately wide. This appears in +two places — `.skill-name` and the terminal head meta. + +The rule behind the table, for anything not listed: **tracking is inversely proportional +to size** — negative above 32px, zero in the 14–19px band, positive only for uppercase at +13px and below, always zero for monospace. **Leading is inversely proportional to size and +directly proportional to measure.** + +--- + +## 4. Layout findings — operator skills + +- **Card text is misaligned with the prose by 25px.** Heading and prose start at x=96; the + first card's text starts at x=121. The card *border* is aligned instead of the card + *copy*. Fixed by outdenting the grid one card-padding plus the 1px border. +- **The two card rows are different heights** — 282px and 236px — so the block reads as two + mismatched bands. `grid-auto-rows: 1fr` makes all seven equal. +- **The outdent has a precondition:** the gutter must exceed it. The live gutter floor is + 24px and the outdent is 25px, so at narrow widths cards would overhang by 1px. Raise the + floor to 32px, or drop the outdent below the 4-column breakpoint. It only appears in a + band of viewport widths, which is how this kind of thing ships unnoticed. +- **The empty eighth grid slot is correct as-is.** Seven items in a four-column grid always + leaves one gap; centring the last row would break the left edge every other element + shares. Noted so nobody "fixes" it later. + +--- + +## 5. Captures section — the whitespace + +### What is actually causing it + +The ten captures are **not one gallery**. They are five separate `.term-grid` containers, +each holding exactly two figures. Each pair sizes independently, so a short card can never +borrow the space left by its tall neighbour. The gap below it is structural. + +| Row | Left | Right | Dead space | +| --- | --- | --- | --- | +| 1 — frame announce / interrogate | 742px | 948px | 206px | +| 2 — the gate / plan | 496px | 945px | 449px | +| 3 — scope / the gate refuses | 1084px | 684px | 400px | +| 4 — deviate / summary | 205px | 563px | 358px | +| 5 — challenge sweep / adjudicate | 712px | 377px | 335px | +| **Total** | | | **1748px** | + +**Every option below requires the same markup change:** all ten figures move into one +container. That is the real work; the CSS is small. + +### The legibility problem underneath + +The transcripts do not render at 12.48px. `pre` is 12.48px, but `code` and `.tl` inside it +shrink again by `.82em`, so **the actual rendered transcript text is 10.23px** — and the +elision notes, shrunk once more, land at **8.70px**. Nobody chose those numbers; they are +what `em` compounding produces through three nested levels. + +Set the size once on `pre` and let it inherit. Cards get taller as a result — that is the +honest price of readable text, and it argues *for* a capped option rather than against the +fix. + +### The four options, measured at 1400px + +| Option | Height | Dead space | Order | Hidden content | +| --- | --- | --- | --- | --- | +| A — masonry (CSS columns) | 4840px | none | **scrambled** — 1–4 left, 5–10 right | none | +| B — capped + internal scroll | 2496px | none | preserved | 9 of 10 cards scroll | +| C — single column, full width | 6300px | none | preserved | none | +| **D — capped preview, expands in place** | **2496px** | 254px \* | preserved | one click, nothing nested | + +\* Option D's 254px is one row, beside the *deviate* capture, which is genuinely only 226px +of content. Option B reaches 0 only by padding that same card out to a uniform 480px — the +empty space still exists, it just sits inside the card instead of beside it. The two are +equivalent; D's is the more honest presentation. + +### Recommendation — Option D + +**The measurement undercuts masonry.** Option A sits in the middle on height while being +the only one of the four that reorders the captures. It pays a real cost — a pipeline +narrative read out of sequence — and does not buy the shortest section in return. + +**Option D matches B's 2496px, the shortest of the four, while removing every one of B's +costs.** Nothing scrolls inside anything. Nothing is permanently hidden. Order is +preserved, verified with a card open. And an expanded card is the best reading mode on the +page: at full width the transcript wraps so much less that capture 1 shows *completely* in +607px, having needed a 480px window to show a fraction of itself collapsed. + +Two caveats: + +- **The cost is the JavaScript** — about fifteen lines. A `
    ` version cannot show a + clipped preview, because closed means empty; the checkbox-and-label alternative has real + accessibility problems. A `devague review
  • · confirm

    Confirm a batch of claims

    transactional — one bad id in the batch and nothing changes at all

    devague confirm c2 h1 h3
  • · confirm

    Confirm from an edited file

    applies the confirm/reject decisions from an edited review file

    devague confirm --from-review <file>
  • · reject

    Reject a claim

    the other half of the gate — a rejected claim stays on the record as rejected, not deleted

    devague reject c3
  • · deviate

    Flag a deviation from plan

    mid-build, the same rule — an agent-raised deviation lands as proposed, with a reason and a classification, never as approved

    devague deviate "…" --task t3 --origin llm
  • · deviate

    Confirm a deviation

    user-only, like every confirm — you approve that specific departure, or --reject it; either way it stays on the ledger

    devague deviate --confirm d1
  • the operator skills

    devague keeps score; operators make the moves

    Around the CLI sit seven operator skills — authored in the devague repo, broadcast to the AgentCulture mesh — one per leg: /scope surveys before the frame, /think walks an idea to an exported spec, /challenge pressure-tests that exported spec for blind spots before planning, /spec-to-plan walks the challenged spec to an exported plan, /assign-to-workforce fans the plan out to a parallel workforce, /deviate stops the run when execution must leave the plan, and /summarize-delivery closes the loop.

    Note what devague itself never does: orchestrate. devague plan waves only describes the dependency graph — deterministic metadata, nothing more. Spawning agents, managing worktrees, gating merges: that is the operator's job. The tool that keeps score should not also play the game.

    • idea → scope/scope

      survey the surfaces the idea touches before framing — each finding lands on the frame citing what was actually read

    • idea → spec/think

      drive the frame engine — announce, capture, interrogate, park; export once the frame converges

    • between spec and plan/challenge

      run a risk-scaled blind-spot pass over the exported spec — findings land proposed for the human, and a clean pass records the lenses examined and the residual uncertainty, never a claim of no unknown unknowns

    • spec → plan/spec-to-plan

      drive the plan engine — tasks that cover every confirmed target, with acceptance criteria and honest dependencies

    • plan → build/assign-to-workforce

      fan the plan's waves out to parallel agents in isolated git worktrees, with TDD-gated merges — the human owns three gates: the spec, the split plan, the final PR

    • during the build/deviate

      stop the run the moment execution must leave the plan; the approved departure lands on the ledger before work resumes

    • after the build/summarize-delivery

      record planned versus actual, mid-work decisions, classified drift, and evidence-backed claims — on complete, partial, and failed runs alike

    real captures

    This page specced itself — three times now

    Three real working sessions are replayed below — recorded live, never edited, never reworded. Each is told twice: first the story in plain language, then the terminal record it comes from. The human gate is real, not ceremony.

    + + +
    +

    Session 1 · 14 July 2026 · devague 0.17

    +

    The page specs itself

    +

    Before this page was built, the team ran devague on the idea of the page. One sentence — “imagine this page is live: what does it contain?” — was broken into eighteen separate promises. A human approved or rejected every one. Only when each promise had an answer did the tool write the final spec — and the build plan’s first task was to record this very session, so you can read it below.

    +

    Read the full session

    +
    frame legframe — announce & captureorg repo · frame leg · devague /thinkdevague 0.17.0 · captured 2026-07-14
    $ devague new "agentculture.org/agents/devague is live a presentation-grade page introducing devague: the CLI that turns a vague idea into a buildable spec, then a buildable plan, by working backwards; the page presents the method (announcement frame, interrogation, convergence, human review loop), the command surface, real captured sessions, and a what's-next drawn from its issue tracker good enough that Ori can present by just showing the page"
    +created frame 'agentculture-org-agents-devague-is-live-a-presenta' (announcement = c1)
    +$ devague capture --origin llm --kind audience "A live-presentation audience first: Ori presents and just shows this page while explaining. Secondarily, humans and agents browsing agentculture.org/agents/."
    +captured c2 (audience, proposed)
    +$ devague capture --origin llm --kind after_state "agentculture.org/agents/devague presents devague end to end: the idea-to-spec-to-plan pipeline, the announcement-frame method (capture, interrogate, park, converge, export), the human review loop (proposals stay proposed until a human confirms), the deterministic no-LLM CLI, the operator skills (/think, /spec-to-plan, /assign-to-workforce), real captured sessions, and a what's-next drawn from the open issue tracker. The /agents/ directory gains a devague card linking to the page."
    +captured c4 (after_state, proposed)
    +… (why_it_matters c5, boundary c6 captures elided)
    +$ devague capture --origin llm --kind success_signal "Same measurable floor as /agents/lobes: Lighthouse performance and accessibility >= 95 on the built page, light and dark themes both pass WCAG AA, animations compositor-only honoring prefers-reduced-motion, zero client-side network calls; plus an explicit presentable-as-is preview sign-off from Ori before merge/deploy."
    +captured c8 (success_signal, proposed)
    +$ devague capture --origin llm --kind decision "Centerpiece demo is the dogfood loop: the captured session shown on the page is the real devague frame that specced this very page announcement to converge to export so the page demonstrates the tool by exhibiting its own origin."
    +captured c13 (decision, proposed)
    +
    + +
    +

    Session 2 · 15 July 2026 · devague 0.18

    +

    The tool outgrows its own page

    +

    By the next day the tool had grown three new abilities — which made this page out of date the moment they shipped. So the page went back through its own process. This session ran before the seventh leg existed, and its transcript honestly announces the method as it then stood: one leg shorter. This time, the tool refused to finish until the missing evidence arrived.

    +

    Read the full session

    +
    scope legscope — survey the surfaces, seed the frameorg repo · scope leg · devague /scopedevague 0.18.0 · captured 2026-07-15
    $ devague new "agentculture.org/agents/devague now presents devague as the complete six-leg method scope, think, spec-to-plan, assign-to-workforce, deviate, summarize-delivery as a pure product presentation: the pipeline and method arc carry the execution seam (scope entries on the frame, the deviation ledger, the delivery summary), the operator-skills section shows all six legs, real captured sessions demonstrate the new legs, launch-day meta (public-since dates, dated version chips) is gone, and what's-next is re-verified against the live tracker good enough that Ori presents the product by just showing the page" --title "devague page: six-leg update"
    +created frame 'devague-page-six-leg-update' (announcement = c1)
    +$ devague capture --origin llm --kind requirement "Pipeline, diagram, and skills copy reflect the devague 0.18 surface verified against the installed CLI and CHANGELOG: the scope verb (pre-frame scoping recorded on the frame), the deviate verb (append-only deviation ledger under .devague/deliveries/), the summary verb (render-only eight-section skeleton, --pr variant), and plan deliverables/amend."
    +captured c6 (requirement, proposed)
    +$ devague capture --origin llm --kind requirement "whatsNext is re-distilled from the live tracker at authoring time (gh issue list on agentculture/devague, 2026-07-15): the resolution-moves cluster (#60, #57, #55, #52, #49, #48, #45) and the consolidated board (#36) remain open; #62, #68, #69, #70 are closed and must not be linked as direction."
    +captured c15 (requirement, proposed)
    +… (c2–c5, c7–c14, c16–c18 captures elided)
    +$ devague scope "site-astro/src/data/devague.ts" --finding "carries all page copy: fact chips incl. 'public since 2026-07-14' and 'version 0.17.2 2026-07-14', the went-public hero paragraph, a 3-stage pipeline, 3 skill cards, and whatsNext linking #62/#68/#69/#70 all closed by 0.18.0" --seeds c3 c5
    +recorded s1 (site-astro/src/data/devague.ts)
    +$ devague scope "devague 0.18.0 (devague --help; ../devague/CHANGELOG.md 0.18.0)" --finding "ships the scope, deviate, and summary verbs plus plan deliverables/amend; docs name the six-leg flow scope→think→spec-to-plan→assign-to-workforce→deviate→summarize-delivery" --seeds c6
    +recorded s2 (devague 0.18.0 (devague --help; ../devague/CHANGELOG.md 0.18.0))
    +$ devague scope "site-astro/src/data/devague-captures.ts" --finding "verbatim-replay contract: every line captured from a real run, cuts marked with first-class ellipsis lines, versions and dates carried as pane provenance new panes must meet the same bar" --seeds c7 c10
    +recorded s3 (site-astro/src/data/devague-captures.ts)
    +$ devague scope --list
    +s1: site-astro/src/data/devague.ts -> carries all page copy: fact chips incl. 'public since 2026-07-14' and 'version 0.17.2 — 2026-07-14', the went-public hero paragraph, a 3-stage pipeline, 3 skill cards, and whatsNext linking #62/#68/#69/#70 — all closed by 0.18.0 [seeds: c3, c5]
    +s2: devague 0.18.0 (devague --help; ../devague/CHANGELOG.md 0.18.0) -> ships the scope, deviate, and summary verbs plus plan deliverables/amend; docs name the six-leg flow scope→think→spec-to-plan→assign-to-workforce→deviate→summarize-delivery [seeds: c6]
    +s3: site-astro/src/data/devague-captures.ts -> verbatim-replay contract: every line captured from a real run, cuts marked with first-class ellipsis lines, versions and dates carried as pane provenance — new panes must meet the same bar [seeds: c7, c10]
    +… (s4 through s8 — DevagueTerminal.astro, DevagueFlow.astro, the live issue tracker, docs/skill-sources.md, site.ts — cut for length)
    +
    + +
    +

    Session 3 · 15 July 2026 · devague 0.19

    +

    The what-did-we-miss pass

    +

    One more ability arrived: a formal blind-spot check. It swept the finished spec through a fixed checklist of angles — hidden assumptions, security, what-if-it-breaks, can-we-undo-it — specifically to catch what nobody had thought to ask.

    +

    Read the full session

    +
    challenge legchallenge — sweep the lenses, route the findingsorg repo · challenge leg · devague /challengedevague 0.19.0 · captured 2026-07-15
    $ devague capture --origin llm --kind assumption "the seventh skill card reads acceptably in the existing auto-fit grid (3+3+1); if it reads awkward at build time the task owner may give the row a deliberate treatment like the moves grid's full-width lead card a styling call inside the task, not a new requirement"
    +captured c19 (assumption, proposed)
    +$ devague scope "challenge pass / unstated-assumptions lens: devague.astro skills grid CSS" --finding "the six cards sit 3+3; a seventh lands 3+3+1 with the last card alone surfaced the layout assumption nobody had stated and proposed it for adjudication" --seeds c19
    +recorded s10 (challenge pass / unstated-assumptions lens: devague.astro skills grid CSS)
    +… (adjacent-systems lenses s11–s12 — DevagueFlow/DevagueTerminal imports, the site.ts directory entry — both clean; cut for length)
    +$ devague scope "challenge pass / operations+reversibility lens: .github/workflows/deploy.yml" --finding "merge to main auto-deploys site-astro/** to Cloudflare Pages (push-path trigger, secrets-gated, PR builds included) the page goes live on merge with no separate operator step, and a git revert redeploys the old page; no rollback gap"
    +recorded s13 (challenge pass / operations+reversibility lens: .github/workflows/deploy.yml)
    +$ devague scope "challenge pass / cheap-probe lens: npm run build on the untouched tree" --finding "astro build exits 0 (6 pages, ~209ms) c15's verification lane confirmed live before the workforce depends on it; dist/ is gitignored so the probe mutated nothing tracked"
    +recorded s14 (challenge pass / cheap-probe lens: npm run build on the untouched tree)
    +$ devague park "how the re-timed 9-stage cascade and raised stacking breakpoint read at mid-tablet widths is only observable in a browser during the build residual until the flow task verifies it" --kind unknown_nonblocking
    +parked v1 (unknown_nonblocking)
    +
    +

    Transcripts are stored verbatim in a data module and replayed as text — the page never runs devague in your browser, and nothing is invented.

    what's next

    The tracker is public too — this is direction, not a promise

    devague is small and moving, and its direction is checkable the same way its facts are: on the open tracker. Three themes stand out in the open issues.

    devague

    devague is open source, Apache-2.0, and deliberately small — a scorekeeper, not a player. It earned this page the honest way, three times over: the page was specced, planned, and built through the tool it presents, and this very update ran all seven legs, scope to delivery summary — including the challenge pass on its own spec. Every fact above traces to the public repo, PyPI, the open tracker, or the CLI's own output. Nothing was invented.

    Read the code →uv tool install devague

    + + + + \ No newline at end of file diff --git a/docs/ux-review/mocks/devague/2026-07-21-review-style/apple-touch-icon.png b/docs/ux-review/mocks/devague/2026-07-21-review-style/apple-touch-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..b17d4af33f23fa4d1348f69cfe292184a5ee627b GIT binary patch literal 1533 zcmbW1X*kpg9LIS`GpxH^_h49ZAC2Uy{9Pe8>2U0t$0p}P)-gJ$|1{(dG31!s*R+F> zW28*T^(V?OqZ*}Qc4!!s$fmY^_T4_uzW9B9Z@$mxN7(*^wfmRf zvUf0nFSHmDFy!Ic*Jp2S=@~b}rjMn{+Z=ev=}r*i7rj}=peQjc19XuoW&4Ghy-GD@ z{BF%<$e`(*B+B(ZYfFY6tU&_aupeI2t0d?qj*66WL4N3I>B5T4L(lNbi_433ALYqn zO=i!mM%qIBdp7HW**D}?4kr4XJ_J)j9S=%`cnFqX$qVp-0)(%G35&^s0(;z>eB*x( zVPQ(&biBazFVeq7d(y8WF0B3HZZBgQr#L(R{PL%CIN=$x;xcm@6B(UQe}uELlGiuJ zhz;*xBha?YNQtPU>%D_`32zeVlLu#j)0XVSjEsCKX}9qv6uG7vvAxaq3kuMNcSnnu zZ(a(?u1?uBtO7@Ygjikoa$L5d&b+b#=qF1c35eEr@<}kV$&e-J#wP;WAbQ3~CCDE=tG zFuXV&nurBQ9hk6)G!p^^0-qGz)NGOmZ{yTjEL}BJQQRo88EqY3J0|}YLF!CQrD7qZ zC60j^!MZ&~$Srf!;ZP@KLjGt-M2T+em1&K`yBGA<%&zXbUE=IGNA4y)ev%6fsqoXt ze{}YLjEG4+)Z-hb8nYeVrRFEM!kNSQ%XtHOnVF-09ctW)>1sXS66%^bfx?m^YaZ>~ zerJ@e9>0JUMmsWJ!#P!f+VQIc^}DlfwY1sr)pY~8G0YA*K~x3}i1xE%E%ZH}jKq$O ztRs}!4Vy4(1lfjK1o4Sa#29owA6eBSM#zQ$n=YWFufu66jCmaM0@|5*#VWmVt>@HJ zDbeJxM_>n}Lj3UsY6C==Po7rA`AA`stKk-LH6+ePb@!aMTNg(`43p)m^0_Bf1~rF% zZuF)aPS>!qXm>h=sE^}v%E_X@ruXqhUj#2j93tkrC%CF|fygzeIl$+hb1+pDXdB(< z(u&P+T8e*Mwpz15J4{lJ4w&kQugDlXrXYfCC)p=VwF*VPIv+|cdaQX7Fg}r&URfG| zsGWZoC{Q&BZzI72pEe&Rs3%LK@7H!LnDGuCZ3cSL@-a@fDxbK*t>8x3$Gu#i5v-vrJO! zlHm&qq1I@s-@ov~u)iN|G1ReXAWh7a5AUI?(X;xwU#pWZI0mrOy-(Y{8?2ZXk3qSw zWF}9y4f(plE%e3TQSzntUF#@*@A!ZfHDZ#R)p@{FiJOShkmc{cx=oB?HQw1$9)?mT zHiGU?%NtCbeL#G{T9uD7h(~veDt#TW5Zm?)^#Fqb% vQ$l@DS|aqlegBHp_hkK#_U%Pd+Gv-zlBI2RhYXp0$vTg{jk7fo_~qJP|E7(8&dVjm1!VGidbk7uX`l)Q1r9bKSzJ~11xUU1 zba4!+xRsnB!MZp>geUaCTq$87E}m~~`pkX`--7K=|8IQ2P-XeRj*tD$^6AX~9v@Ox zV_`Gn{n7SBdxm@JK5@T3=4hTpjy3lu)G$_AChX1kush+zs&W5-xypZgk2!MF*d27W z9fb26y3{Y2yjW;=zh6Bi<2lFu34cDHaO`)DV_4PptM3Ev$@%_02T$~E=s7dz{9LKc z^0S;BwlMCTrtYBoUft1uzfY1{-9i^GX>~z22WQ% Jmvv4FO#r``c|ZUF literal 0 HcmV?d00001 diff --git a/docs/ux-review/mocks/devague/2026-07-21-review-style/favicon.svg b/docs/ux-review/mocks/devague/2026-07-21-review-style/favicon.svg new file mode 100644 index 0000000..659066a --- /dev/null +++ b/docs/ux-review/mocks/devague/2026-07-21-review-style/favicon.svg @@ -0,0 +1,16 @@ + + + + + + + + diff --git a/docs/ux-review/pipeline-layout-plan.md b/docs/ux-review/pipeline-layout-plan.md index 1f67f48..bd04753 100644 --- a/docs/ux-review/pipeline-layout-plan.md +++ b/docs/ux-review/pipeline-layout-plan.md @@ -8,7 +8,11 @@ approach that was tried and rejected (change 2), and a card treatment (changes 3–4) that was later superseded by the reference-list treatment (change 5, the reviewer-approved direction). Three animation bugs found along the way are specced at the bottom; they ship regardless of the -layout choices. No code in this plan has been applied to the site. +layout choices. The +[21 July full-page mock](mocks/devague/2026-07-21-review-style/README.md) +retains the last successful integrated render; its manifest records the two +pipeline restoration requests made after that render. No code in this plan has +been applied to the site. ## The problems, measured diff --git a/docs/ux-review/spacing-type-and-captures.md b/docs/ux-review/spacing-type-and-captures.md index 16b7776..9c9174f 100644 --- a/docs/ux-review/spacing-type-and-captures.md +++ b/docs/ux-review/spacing-type-and-captures.md @@ -1,5 +1,10 @@ # UX review — spacing, type and layout +> **Status:** The spacing, leading, tracking, and legibility diagnosis remains +> supporting evidence. The option D captures recommendation is historical and +> has been superseded by the +> [`captures-story-plan.md`](captures-story-plan.md) guided-session direction. + A UX/UI contribution for `/agents/devague/`. Two areas: a **spacing and type token system**, and the **captures section layout**. From f6c582fe32b53b72fc201d3800a5e5c1ffafaffe Mon Sep 17 00:00:00 2001 From: Becky Still Date: Wed, 22 Jul 2026 10:33:39 +0100 Subject: [PATCH 05/32] docs(ux-review): add design system adoption plan --- docs/ux-review/README.md | 17 +- docs/ux-review/current-direction.md | 22 +- docs/ux-review/design-system.md | 470 ++++++++++++++++++++++++++++ docs/ux-review/mocks/README.md | 1 - 4 files changed, 493 insertions(+), 17 deletions(-) create mode 100644 docs/ux-review/design-system.md diff --git a/docs/ux-review/README.md b/docs/ux-review/README.md index 9bb3585..1236291 100644 --- a/docs/ux-review/README.md +++ b/docs/ux-review/README.md @@ -29,6 +29,7 @@ original site-wide audit, and the earlier section-level explorations. | File | Kind | Covers | |------|------|--------| | [`current-direction.md`](current-direction.md) | Markdown | Status, precedence, current decisions, and open calls | +| [`design-system.md`](design-system.md) | Markdown | Design-system layers, mock-to-site collision map, component catalogue, staged adoption plan, and regression gates | | [`mocks/devague/2026-07-21-review-style/`](mocks/devague/2026-07-21-review-style/README.md) | Full-page snapshot | Latest integrated Devague mock plus the documented responsive diagram repair | | [`captures-story-plan.md`](captures-story-plan.md) | Markdown | Guided three-session captures handoff and complete copy deck | | [`pipeline-layout-plan.md`](pipeline-layout-plan.md) | Markdown | Pipeline hierarchy, reference-list treatment, and animation fixes | @@ -73,13 +74,14 @@ as proposed and shown against the current value it replaces. For a maintainer or an agent picking this up cold: 1. `current-direction.md` — the precedence and status map. -2. The preserved full-page Devague mock — the latest integrated visual state. -3. `captures-story-plan.md` and `pipeline-layout-plan.md` — the implementation +2. `design-system.md` — the safe ownership, containment, and adoption method. +3. The preserved full-page Devague mock — the latest integrated visual state. +4. `captures-story-plan.md` and `pipeline-layout-plan.md` — the implementation handoffs, including the pipeline work requested after the final mock render. -4. `findings.md` — the measured baseline and verified strengths. -5. `agents-directory.html` and `agent-page-scaling.md` — independent site-wide +5. `findings.md` — the measured baseline and verified strengths. +6. `agents-directory.html` and `agent-page-scaling.md` — independent site-wide proposals not superseded by the Devague work. -6. The spacing/type and captures explorations when their rationale is needed. +7. The spacing/type and captures explorations when their rationale is needed. The site-wide audit finds the pattern library drifting because it is copied per page (`agent-page-scaling.md`); the section-level work finds spacing drifting @@ -95,8 +97,9 @@ The `agents-directory.html` demo re-derives its central measurement live in the browser from the rendered DOM rather than asserting it, and independently arrives at the same 4% figure quoted in the audit. -**Not verified** — none of the proposals has been implemented against the real -site, so none has been through the repo's own gates: `npm run build`, +**Not implemented** — none of the proposals has been applied to the real site. +The documentation and current-site baseline may be checked with the repo's own +gates, but the proposed components have not yet been through `npm run build`, `org site link-check`, `markdownlint-cli2`, or the SonarCloud quality gate. The component API sketched in `agent-page-scaling.md` is a proposal, not tested code; it should be treated as a starting shape to argue with, not a specification. diff --git a/docs/ux-review/current-direction.md b/docs/ux-review/current-direction.md index c9fc4c0..fe6b3a0 100644 --- a/docs/ux-review/current-direction.md +++ b/docs/ux-review/current-direction.md @@ -18,14 +18,16 @@ that later work superseded. When two documents disagree, use this order: 1. This current-direction map for status and precedence. -2. The [preserved full-page Devague mock](mocks/devague/2026-07-21-review-style/README.md) +2. The [`design-system.md`](design-system.md) adoption plan for ownership, + containment, promotion, and regression gates. +3. The [preserved full-page Devague mock](mocks/devague/2026-07-21-review-style/README.md) for the last successfully rendered integrated composition. -3. The two current Devague handoffs: +4. The two current Devague handoffs: [`captures-story-plan.md`](captures-story-plan.md) and [`pipeline-layout-plan.md`](pipeline-layout-plan.md). -4. The original audit for measured evidence: +5. The original audit for measured evidence: [`findings.md`](findings.md). -5. Earlier interactive explorations for rationale, not implementation +6. Earlier interactive explorations for rationale, not implementation authority. The full-page Devague review mock is retained in this worktree. Its HTML and @@ -40,6 +42,7 @@ evidence and the handoff as the intended implementation direction. | Artefact | Status | How to use it now | |---|---|---| | `current-direction.md` | Current map | Start here for precedence and scope. | +| [`design-system.md`](design-system.md) | Current adoption plan | Use to classify mock patterns, contain changes, assess overwrite risk, and gate promotion into the shared site. | | [Devague full-page mock](mocks/devague/2026-07-21-review-style/README.md) | Latest retained mock | Review the complete composition, interactions, and responsive diagram repair. The manifest records the final pipeline requests that did not land in the Claude render. | | [`captures-story-plan.md`](captures-story-plan.md) | Current handoff | Governs the Devague real-captures redesign. | | [`pipeline-layout-plan.md`](pipeline-layout-plan.md) | Current handoff | Governs the Devague pipeline layout and animation fixes. | @@ -182,10 +185,11 @@ accessibility, responsive, theme, no-JavaScript, and reduced-motion checks. ## Suggested reading order 1. This document. -2. The [preserved full-page Devague mock](mocks/devague/2026-07-21-review-style/README.md). -3. [`captures-story-plan.md`](captures-story-plan.md). -4. [`pipeline-layout-plan.md`](pipeline-layout-plan.md). -5. [`findings.md`](findings.md), for the measured baseline and verified +2. [`design-system.md`](design-system.md). +3. The [preserved full-page Devague mock](mocks/devague/2026-07-21-review-style/README.md). +4. [`captures-story-plan.md`](captures-story-plan.md). +5. [`pipeline-layout-plan.md`](pipeline-layout-plan.md). +6. [`findings.md`](findings.md), for the measured baseline and verified strengths. -6. The relevant supporting prototype or architecture note only when its topic +7. The relevant supporting prototype or architecture note only when its topic is being implemented. diff --git a/docs/ux-review/design-system.md b/docs/ux-review/design-system.md new file mode 100644 index 0000000..110604c --- /dev/null +++ b/docs/ux-review/design-system.md @@ -0,0 +1,470 @@ +# Design-system adoption plan + +> **Status:** Current working agreement, 22 July 2026. Audited on branch +> `ux-review` at `ef392d9`, after merging `origin/main` at `aea608b`. This is a +> documentation-only plan: no file under `site-astro/` has been changed. + +The Devague mock is now rich enough to be treated as design-system evidence, +but it is not a replacement stylesheet for the site. It contains a mixture of +good shared foundations, promising reusable components, Devague-specific +composition, and retained prototype residue. Its compiled bundle also changes +global rules that every route depends on. + +The safe approach is therefore: + +1. keep the current Astro source as the production baseline; +2. extract decisions from the mock, not generated markup or CSS; +3. contain the first implementation inside a Devague page namespace; +4. prove each pattern locally and across the regression matrix; and +5. promote a pattern globally only when it has a second real consumer. + +This document records what belongs at each layer, where adoption would collide +with the current site, and the sequence for implementing the work without a +site-wide restyle by accident. + +## Sources and authority + +| Source | What it is authoritative for | +|---|---| +| [`site-astro/src/styles/global.css`](../../site-astro/src/styles/global.css) | Current production tokens, base elements, layout primitives, cards, focus, reveal, and reduced-motion behaviour. | +| [`site-astro/src/layouts/Layout.astro`](../../site-astro/src/layouts/Layout.astro) | Current document shell, metadata, fonts, header/footer, and shared reveal observer. | +| [`site-astro/src/pages/agents/devague.astro`](../../site-astro/src/pages/agents/devague.astro) | Current production Devague semantics, section order, and component boundaries. | +| [`site-astro/src/components/DevagueFlow.astro`](../../site-astro/src/components/DevagueFlow.astro) | Current production pipeline component and its progressive-enhancement contract. | +| [`site-astro/src/components/DevagueTerminal.astro`](../../site-astro/src/components/DevagueTerminal.astro) | Current production terminal semantics, replay behaviour, and capture rendering. | +| [Retained full-page mock](mocks/devague/2026-07-21-review-style/README.md) | The latest integrated visual direction and interaction specimen. | +| [`captures-story-plan.md`](captures-story-plan.md) | Intended guided-session content model, verbatim-evidence contract, and source-component handoff. | +| [`pipeline-layout-plan.md`](pipeline-layout-plan.md) | Intended pipeline hierarchy, responsive behaviour, and animation repairs. | +| [`spacing-type-and-captures.md`](spacing-type-and-captures.md) | Measurements behind the proposed spacing, leading, tracking, and terminal-legibility changes. | +| [`agent-page-scaling.md`](agent-page-scaling.md) | Longer-term sequence for sharing terminal and agent-page architecture. | + +When these sources differ, use [`current-direction.md`](current-direction.md) for +status and precedence. Use the retained mock to judge the composition, but use +the current Astro source to understand what an implementation would replace. + +### What must not become source + +Do not copy the retained `_astro/` CSS, HTML shell, or scripts into +`site-astro/`. In particular: + +- `data-astro-cid-*` selectors are build output, not stable authored APIs; +- the built header, footer, and layout predate current source changes; +- hidden comparison variants are provenance, not approved interface states; +- the snapshot duplicates observers and interaction scripts already owned by + source components; and +- broad selectors such as `body`, `h1`, `.container`, `.card`, and `code` in the + bundle would escape the Devague page if transplanted. + +## The system model + +Every decision should have one owner. A useful five-layer model is: + +| Layer | Owns | Current examples | Adoption rule | +|---|---|---|---| +| **1. Foundations** | Theme colours, families, raw spacing, type metrics, radii, elevation, easing | `:root` in `global.css` | Global only when the meaning is stable across the site. Never redefine these from a page bundle. | +| **2. Primitives** | Page rail, reading measure, section rhythm, text roles, focus, surface | `.container`, `.prose`, `.section`, `.eyebrow`, `.card` | Keep backward-compatible. Add a named variant instead of changing the base while one page is being redesigned. | +| **3. Components** | A reusable visual and behavioural contract | `PageHero`, terminal, copy control, disclosure, transcript modal | Own markup, styles, state, accessibility, and tests together. Prefer Astro scoping and explicit props. | +| **4. Compositions** | Page-specific ordering and content | Devague pipeline, seven moves, three capture sessions | Compose primitives and components; do not promote exact content structures into global CSS. | +| **5. Experiments** | Alternatives retained for comparison | Hidden flow variants and unused capture layouts | Keep in review artefacts only. Mark as superseded or remove when provenance is no longer needed. | + +This prevents a common failure mode: promoting a visually successful page rule +straight into `global.css` before its meaning is understood. + +## Current production foundation + +The site already has a coherent visual foundation. It should be extended, not +replaced. + +### Existing global tokens + +The current root has 26 tokens: + +- core theme colours: background, surface, ink, accent, and line roles; +- decorative sky and mesh colours; +- two elevation roles; +- display, body, and monospace font families; +- two easing curves; and +- section padding and radius. + +Light and dark themes share the same semantic names. The global stylesheet also +owns the focus ring, skip link, one-time reveal system, and the universal +reduced-motion kill switch. Those are system contracts, not Devague styling. + +### Gaps the mock usefully exposes + +There is no global spacing scale, type-size scale, breakpoint scale, or named +component-density system. The live stylesheet therefore mixes `rem`, `em`, +pixels, `vh`, and component-local values. The measured consequences are: + +- nested `em` sizes and margins compound into fractional values; +- prose leading leaks into single-line labels and adds phantom vertical space; +- global `code { font-size: 0.82em; }` shrinks terminal text a second time; and +- sections can appear to have different gutters when page rail, reading measure, + and component padding are used as if they were the same dimension. + +The design-system work should solve those causes without retuning the whole site +inside the Devague change. + +## Candidate foundations + +The following are candidates extracted from the mock. “Candidate” means they +may be used in a Devague-scoped implementation; it does not mean they are +approved root replacements. + +### Spacing + +Use a fixed 4px-based raw scale for component relationships: + +| Role | Value | +|---|---:| +| `space-1` | 4px | +| `space-2` | 8px | +| `space-3` | 12px | +| `space-4` | 16px | +| `space-5` | 24px | +| `space-6` | 32px | +| `space-7` | 48px | +| `space-8` | 64px | + +Raw scale names should not appear everywhere in component markup. Components +should map them to local semantic roles such as `--card-padding`, +`--label-to-title`, or `--section-intro-gap`. That leaves room to tune a +component without changing every use of `space-5`. + +For the first implementation, scope the raw values to `.devague-page` and +prefix them if necessary, for example `--devague-space-5`. Promote the scale to +`:root` only in a dedicated migration after a collision check. + +### Type roles + +| Role | Candidate value | Owner now | Intended use | +|---|---:|---|---| +| Body/prose | `1.0625rem` | Global, already live | Default long-form copy; preserve. | +| Eyebrow | `0.75rem` | Global, already live | Uppercase section metadata. | +| Card title | `1.25rem` | Devague candidate | Method, reference, gate, and skill-card titles where the current role is too quiet. | +| Card/body UI | Component-defined | Candidate | Short explanatory copy, not a replacement body size. | +| Terminal | `0.8125rem` | Terminal component candidate | Set once on the transcript and inherit through nested `code`. | +| Terminal note | `0.75rem` | Terminal component candidate | Elision and supporting terminal metadata. | +| Compact tag | `0.6875rem` | Component candidate | Terminal legs and skill metadata, with a legibility check. | + +The semantic role matters more than the number. Do not add a token for every +literal size in the mock. The latest snapshot audit found 87 size-setting +declarations: eight use a size token, 77 still use literal values, one inherits, +and one uses zero as a layout technique. Consolidate those literals by role as +source components are written; tokenising a value is not evidence that the role +itself is reusable. + +### Leading and tracking + +| Token role | Value | Use | +|---|---:|---| +| Tight display leading | `1.1` | Large display headings. | +| UI leading | `1.25` | Single-line labels, controls, and compact titles. | +| Normal leading | `1.55` | Card body copy. | +| Prose leading | `1.7` | Long-form copy at the 42rem reading measure. | +| Display tracking | `-0.02em` | Large display type. | +| Heading tracking | `-0.01em` | Smaller editorial headings. | +| Flat tracking | `0` | Body and monospace. | +| Caps tracking | `0.12em` | Uppercase labels at 13px and below. | + +The first corrective change should be local: reset nested terminal code to +inherit its component size and give one-line labels UI leading. Changing the +global body or generic `code` selector would be a much larger migration. + +### Horizontal rhythm: three separate jobs + +The mock demonstrated why “gutter” cannot be one catch-all measurement. Keep +these roles separate: + +1. **Page rail** — the common outer edge shared by hero, sections, header, and + footer. +2. **Reading measure** — the maximum line length, currently 42rem; it may sit + inside a wider rail. +3. **Surface inset** — padding inside a card, terminal, diagram, or modal. + +All Devague sections should use the same page rail. A component may constrain +its contents or add surface padding, but it must not nest another page container +and create a second gutter. This is the method for keeping the page edges +consistent at every width. + +Keep the live `.container` (`68rem` maximum with 24px minimum edge gutters) as +the site-wide primitive. If Devague needs a narrower presentation rail, add an +explicit local variant. Do not replace `.container` with the mock's `58rem` +maximum plus independent responsive padding: that changes both the width and +the gutter model and can double-count the inset. + +## Component catalogue + +Use these maturity labels: + +- **Existing** — already shared in production; preserve its public contract. +- **Candidate** — strong enough to implement locally and test. +- **Page-only** — deliberately belongs to the Devague composition. +- **Dormant** — retained comparison or unused prototype; do not ship from it. +- **Promoted** — proven by at least two real consumers and cross-route tests. + +### Existing production contracts + +| Pattern | Status | Direction | +|---|---|---| +| Layout, header, footer, and page sky | Existing | Keep current source. Never replace from the built mock. | +| `PageHero` | Existing | Keep shared title, intro, and decorative flourish semantics. Scope any Devague title tuning outside the component until it is proven site-wide. | +| Page rail and reading measure | Existing | Preserve `.container` and `.prose`; add named variants rather than silently changing their meanings. | +| Focus and skip-link treatment | Existing | Preserve. All new controls inherit or visibly meet this standard. | +| Reveal and reduced motion | Existing | Preserve the `html.js` progressive-enhancement convention and global reduced-motion override. | +| Card surface | Existing primitive | Preserve the base. Use Devague-specific card components or modifiers for density and hierarchy. | + +### Candidates from the mock + +| Pattern | Reusable contract | Page-owned content | +|---|---|---| +| Fast-facts strip | Label/value items and responsive wrapping | The four Devague facts. | +| Process-diagram shell | Figure surface, breakpoint layout, semantic fallback, caption/reference relationship | The nine glyphs, labels, and exact 5+4 / 3×3 / one-column narrative. | +| Quiet reference list | Name/meta, description, tags, separators | The seven pipeline transitions. | +| Method card | Eyebrow, title/question, detail, consistent internal rhythm | The seven moves and their order. | +| Human-gate card | Gate explanation plus terminal thumbnail | The six gates and commands. | +| Copy control | Explicit accessible name, clipboard result, visible success/failure status | The command or skill string copied. | +| Capability card | Metadata, structural title, duty copy, 3/2/1-column layout | The seven operator skills. Keep a real heading in the document outline even when the visual title is monospace. | +| Terminal | Figure/caption, status header, transcript region, line roles, leg modifier, optional replay | Devague transcript data and leg colours. | +| Guided session | Session introduction, one hero preview, narrative beats, raw-evidence links | The three sessions, 14 beats, and ten source panes. | +| Beat timeline | Headline, narration, note, exact terminal excerpt | Devague's chronological story. | +| Disclosure | `aria-expanded`, controlled region, no-JS-readable fallback | Which raw evidence is grouped under a session. | +| Transcript modal | Dialog semantics, focus trap/restore, Escape/backdrop close, previous/next boundaries, scroll restoration | Pane registry, order, captions, and transcripts. | +| Closing band | Compact page CTA separated from the site footer | Devague's closing mark and wording. | + +The modal and terminal are reusable in principle, but they are not yet generic +production components. Implement the current capture handoff against a single +source of transcript data; do not clone snapshot DOM into a second data path. + +### Page-only visual language + +Keep the exact nine-stage glyph sequence, seven transitions, seven method moves, +six human gates, seven skills, three sessions, issue groupings, and Devague +closing mark in the Devague composition. Bespoke diagrams are an intentional +part of the agent pages; sharing their shell does not require generalising their +content. + +### Dormant prototype residue + +The retained snapshot includes a hidden original flow, a hidden static flow, +and unused selectors for earlier terminal-grid, capture-grid, primer, and +session-hero variants. They remain useful provenance, but are not accepted +patterns and must not appear in the production component inventory. + +## Overwrite and collision map + +The current `global.css` is imported by all 12 route files. The new presentation +deck also uses the global `.container` for each slide and consumes shared colour, +radius, line, font, and surface tokens. A change can therefore pass a content +test while still breaking its geometry. + +| Proposed or mock-level change | Blast radius | Risk | Safe containment | +|---|---|---:|---| +| Replace root palette/font/radius tokens | All routes and diagrams | High even when colours look equivalent | Keep current source tokens. Add aliases only when semantics genuinely differ. Keep browser theme-colour metadata in sync with any later root change. | +| Body size from live 17px to browser-default 16px | All prose, navigation, footer, cards, and presentation captions | High | Preserve the live body size. Assign explicit named roles inside Devague components. | +| `h1` maximum from 4.5rem to 3.6rem | Every shared `PageHero` route | High | Scope a Devague title variant only if the page still needs it. | +| Global fixed `h2` at 1.5rem | Content hierarchy across the site | High | Do not adopt. The mock later restores the live fluid Devague section size anyway. | +| `.container` from 68rem to 58rem plus new padding | Header, footer, heroes, nearly every route, and every new presentation slide | High | Keep the live primitive. Use one Devague rail modifier without nested/double gutters. | +| Change `.prose` or `.lede` globally | Agent intros, articles, framework, and presentation copy | Medium–high | Preserve the 42rem measure. Add a specific intro role if needed. | +| Restyle generic `code` as a chip or change its size | Inline commands, terminal descendants, articles, and presentation code | Medium–high | Use `.command-chip`; reset terminal descendants locally to `font-size: inherit`. | +| Tighten global `.card` padding and move hover motion | Home, directory, agent, article, presentation, and engage grids | High | Create a Devague card grammar. Keep hover transforms inside the no-preference motion query. | +| Add unscoped mock `--space-*` / `--fs-*` root tokens | Future namespace collisions and accidental cross-route consumption | Medium | Scope or prefix on `.devague-page`; promote through a separate global-token change. | +| Change global `.section` padding or introduce `vh` seams | Every content page; viewport-height-dependent blank bands | High | Give Devague one local vertical-rhythm owner. Test every adjacent section boundary. | +| Replace `DevagueFlow` from generated snapshot CSS | Devague only, but duplicates DOM, observer, and stale breakpoints | Medium–high | Author a source component or explicit mode from accepted markup. Remove the old path only when the replacement is accepted. | +| Rebuild method, gate, and skill cards | Devague only | Medium | Use semantic source components/data maps; preserve heading levels and accessible copy feedback. | +| Replace captures with sessions, disclosure, and modal | Devague only, with complex focus/state/data behaviour | High | Componentise from the handoff, reuse one terminal source, and add interaction/no-JS tests before visual polish is accepted. | +| Copy snapshot header, footer, reveal, or terminal scripts | Every route or duplicated Devague lifecycle | High | Keep current source shell and observer. Make page interactions idempotent and component-owned. | +| Add new global breakpoints | Shell, Devague, and presentation boundary collisions | High | Keep new queries page/component-scoped; prefer component/container intent over a second site-wide breakpoint system. | + +## Adoption sequence + +Each phase should be a separate, reviewable change. Do not combine a global +primitive migration with a page composition rewrite. + +### Phase 0 — freeze the baseline + +- Work on a feature/UX branch, never directly on `main`. +- Update from `origin/main` before implementation and record the baseline SHA. +- Build the current site and capture reference images for the regression routes. +- Record light/dark, JavaScript/no-JavaScript, and reduced-motion states. +- Keep the retained mock immutable; create a new snapshot if its specimen state + changes materially. + +**Gate:** the baseline is reproducible and failures are known before code is +changed. + +### Phase 1 — add a Devague namespace with no visual change + +- Add one `.devague-page` root around page-owned sections. +- Define candidate spacing/type aliases on that root, without switching existing + consumers yet. +- Establish one page rail, one reading measure, and named component insets. +- Add component names based on responsibility, not appearance. + +**Gate:** computed tokens do not leak to a second route; all baseline images are +unchanged. + +### Phase 2 — adopt low-interaction visual components + +- Implement facts, reference rows, method cards, gate cards, skill cards, and + command chips from source data. +- Apply the larger card-title role where the hierarchy requires it. +- Correct UI leading, monospace tracking, and local terminal inheritance. +- Keep the production `PageHero`, header, footer, and global card primitive. + +**Gate:** heading outline, keyboard names, copy result states, 3/2/1-column +behaviour, gutters, and theme contrast pass. + +### Phase 3 — replace the pipeline deliberately + +- Implement the approved light diagram surface in both site themes, with an + explicit component-owned surface/ink pairing rather than a global theme + override. +- Build the accepted source component with one semantic DOM path. +- Preserve a readable no-JavaScript list and the global reduced-motion contract. +- Verify one-column up to 40rem, 3×3 from 40–60rem, and 5+4 above 60rem. +- Remove a superseded flow and observer only in the same change that proves the + replacement. + +**Gate:** node order and labels are correct; no duplicate hidden flow, observer, +or horizontal overflow remains. + +### Phase 4 — implement guided captures + +- Follow the data and component boundary in + [`captures-story-plan.md`](captures-story-plan.md). +- Resolve excerpts by exact anchors from the single transcript source and fail + the build when an anchor drifts. +- Implement session headers, beats, terminal preview, disclosure, and modal as + separate source components. +- Make the full evidence readable or reachable without JavaScript. +- Test repeated open/close cycles so focus, scroll state, and listeners do not + leak. + +**Gate:** transcript bytes and chronological order are unchanged; modal focus, +Escape/backdrop close, focus restoration, previous/next boundaries, no-JS, and +reduced motion all pass. + +### Phase 5 — promote only proven patterns + +- Use a candidate on a second real page before calling it global. +- Compare both consumers and name only the shared semantics. +- Move the component and its tokens together, with a migration note. +- Leave Devague content and glyphs local. + +Likely first promotion candidates are the copy control, terminal shell, quiet +reference row, and transcript modal. The shared terminal work should follow the +richest-case-first sequence in [`agent-page-scaling.md`](agent-page-scaling.md), +not be hidden inside the Devague redesign. + +**Gate:** two consumers, cross-route snapshots, accessibility tests, and a clear +rollback path. + +## Regression matrix + +### Routes + +Broad primitive or token changes require all current routes: + +- `/` +- `/agents/` +- `/agents/devague/` +- `/agents/colleague/` +- `/agents/lobes/` +- `/agents/reachy-mini-cli/` +- `/articles/` +- `/articles/mind-nervous-system-body/` +- `/engage/` +- `/framework/` +- `/presentations/` +- `/presentations/mind-nervous-system-body/` + +A Devague-scoped component change still needs one non-Devague sentinel route and +the new presentation deck to prove containment. + +### Viewports and boundary checks + +Use representative snapshots at 375, 640, 768, 960, and 1440px. When a change +touches queries, also test one pixel either side of every relevant boundary: +544, 640, 736, 768, 832, 960, and 1056px. The pipeline specifically needs its +40rem and 60rem transitions checked. + +### State and behaviour + +For each affected pattern, check: + +- light and dark colour schemes; +- normal and reduced motion; +- JavaScript enabled and disabled; +- keyboard-only focus order and visible focus; +- 200% text zoom and long inline-code wrapping; +- no horizontal page or transcript overflow; +- consistent page rails at every section seam; +- logical heading order and landmark semantics; +- no hidden content at first paint or after back/forward navigation; +- no new client-side network dependency; and +- verbatim transcript/provenance integrity. + +Repository content/structure checks remain necessary, but are not sufficient. +For example, `check:presentations` does not detect a narrower global container +breaking slide geometry, so visual containment needs its own assertion. + +### Dated baseline result + +The merged baseline was checked on 22 July 2026 before any site implementation: + +- `npm run build` passes on Node 24.14.0 and generates all 12 routes; +- Markdown lint passes across `docs/ux-review/`; +- `git diff origin/main -- site-astro` is empty; and +- `npm run check:presentations` already fails four of 20 contracts on the + unchanged `origin/main` site: the library-card title, accessible architecture + diagram, verbatim thesis, and Reachy repository link. + +That presentation result is a known baseline failure, not an effect of this +documentation. It should be resolved or explicitly accepted before visual +implementation begins, so later regressions are attributable. + +## Change record for each adoption + +Every design-system PR should answer these questions in its description: + +| Field | Required record | +|---|---| +| Decision | What user or content problem is being solved? | +| Layer and owner | Foundation, primitive, component, composition, or experiment; which source file owns it? | +| Status | Candidate, page-only, promoted, or superseded. | +| Existing contract touched | Selectors, components, tokens, data, and interaction lifecycle. | +| Consumers | Every route/component that currently matches the changed contract. | +| Containment | Namespace, component scope, modifier, or migration strategy. | +| Accessibility | Semantics, name/role/value, focus, contrast, motion, and no-JS behaviour. | +| Evidence | Mock state, measured finding, screenshots, and automated checks. | +| Rollback | Component/variant or commit that can be removed without restoring a mutated base rule. | + +## Current decisions and open calls + +### Decisions recorded here + +- The current Astro site is the production source of truth. +- The retained mock is a specimen, not an installable stylesheet. +- Global palette, fonts, body size, heading scale, container, header, footer, + reveal, and reduced-motion contracts stay unchanged during the Devague work. +- The pipeline diagram uses the approved light background rather than returning + to the earlier dark treatment. +- Devague card titles use the larger `1.25rem` semantic role where the mock has + established that hierarchy; this does not retune global `h3` elements. +- The first implementation is Devague-scoped. +- Page rail, reading measure, and component inset are separate roles. +- A shared token or component requires a second consumer and regression proof. +- Dormant comparison variants do not enter the production system. + +### Human decisions still required before their phase + +1. Whether the pipeline copy reductions listed in + [`current-direction.md`](current-direction.md) are accepted. +2. Which Devague candidates should be trialled on a second page and in what + order. +3. Whether the raw spacing scale eventually becomes global or remains expressed + through component-owned semantic tokens. + +Those choices do not block the documentation, namespace, or baseline work. They +do block treating the relevant visual decision as a shared, finished system +rule. diff --git a/docs/ux-review/mocks/README.md b/docs/ux-review/mocks/README.md index a49a223..93ca42d 100644 --- a/docs/ux-review/mocks/README.md +++ b/docs/ux-review/mocks/README.md @@ -9,4 +9,3 @@ repository. They are review artefacts, not implementations of the live site. Each dated snapshot is immutable. Preserve a later iteration in a new dated folder rather than overwriting an earlier review state. - From 0f14ef74bdf3c4e8fcd0eae669afc4af7ffa3028 Mon Sep 17 00:00:00 2001 From: Becky Still Date: Wed, 22 Jul 2026 11:17:18 +0100 Subject: [PATCH 06/32] docs(ux-review): establish system before migration --- docs/ux-review/current-direction.md | 11 +- docs/ux-review/design-system.md | 200 +++++++++++++++++----------- 2 files changed, 133 insertions(+), 78 deletions(-) diff --git a/docs/ux-review/current-direction.md b/docs/ux-review/current-direction.md index fe6b3a0..16cffe7 100644 --- a/docs/ux-review/current-direction.md +++ b/docs/ux-review/current-direction.md @@ -169,8 +169,9 @@ plan: operator-skills section own it, leaving the pipeline with three engine-level summaries. 2. Whether to reduce the eight-line flow caption to one or two sentences. -3. Where the directory and shared agent-page work sit relative to the Devague - implementation in delivery order. +3. Which existing route becomes the second design-system consumer after + Devague, and where the directory/shared-agent-page work sits in that later + migration order. ## Implementation boundary @@ -178,6 +179,12 @@ No proposal in this folder has been applied to `site-astro/` in this worktree. The original Devague page and its capture data remain unchanged. Adding this document does not change that boundary. +The delivery order is now fixed: establish and prove the opt-in system against +an isolated reference specimen first; migrate Devague as its first production +consumer second; then plan migration of the remaining routes separately. The +system-first phase must not alter a current public route or redefine a current +global primitive. + If implementation is requested later, begin with the current handoffs, preserve the safeguards above, and then run the repository's build, link, lint, accessibility, responsive, theme, no-JavaScript, and reduced-motion checks. diff --git a/docs/ux-review/design-system.md b/docs/ux-review/design-system.md index 110604c..6038bff 100644 --- a/docs/ux-review/design-system.md +++ b/docs/ux-review/design-system.md @@ -14,9 +14,13 @@ The safe approach is therefore: 1. keep the current Astro source as the production baseline; 2. extract decisions from the mock, not generated markup or CSS; -3. contain the first implementation inside a Devague page namespace; -4. prove each pattern locally and across the regression matrix; and -5. promote a pattern globally only when it has a second real consumer. +3. establish an opt-in system of tokens, primitives, components, and contracts + before changing the live Devague route; +4. prove that system against an isolated reference specimen based on the mock; +5. migrate Devague as the first production consumer only after the system gate; + and +6. migrate other routes later, promoting a pattern to a global default only + when it has a second real consumer. This document records what belongs at each layer, where adoption would collide with the current site, and the sequence for implementing the work without a @@ -107,8 +111,8 @@ inside the Devague change. ## Candidate foundations The following are candidates extracted from the mock. “Candidate” means they -may be used in a Devague-scoped implementation; it does not mean they are -approved root replacements. +may enter the opt-in system and its reference specimen; it does not mean they +are approved root replacements or may change a production route yet. ### Spacing @@ -130,9 +134,11 @@ should map them to local semantic roles such as `--card-padding`, `--label-to-title`, or `--section-intro-gap`. That leaves room to tune a component without changing every use of `space-5`. -For the first implementation, scope the raw values to `.devague-page` and -prefix them if necessary, for example `--devague-space-5`. Promote the scale to -`:root` only in a dedicated migration after a collision check. +For the system implementation, give new tokens a collision-safe namespace, for +example `--ac-space-5`, and define them in the system layer or the component +that owns them. Keep the existing root tokens as the compatibility layer. The +Devague page namespace begins consuming the new tokens only during migration; +promoting them to root defaults is a later, dedicated change. ### Type roles @@ -197,7 +203,11 @@ the gutter model and can double-count the inset. Use these maturity labels: - **Existing** — already shared in production; preserve its public contract. -- **Candidate** — strong enough to implement locally and test. +- **Candidate** — specified strongly enough to build and test in the reference + specimen. +- **Established** — implemented as opt-in and has passed the system acceptance + gate without changing a production route. +- **Migrated** — adopted by a named production consumer. - **Page-only** — deliberately belongs to the Devague composition. - **Dormant** — retained comparison or unused prototype; do not ship from it. - **Promoted** — proven by at least two real consumers and cross-route tests. @@ -232,8 +242,9 @@ Use these maturity labels: | Closing band | Compact page CTA separated from the site footer | Devague's closing mark and wording. | The modal and terminal are reusable in principle, but they are not yet generic -production components. Implement the current capture handoff against a single -source of transcript data; do not clone snapshot DOM into a second data path. +production components. Build the opt-in versions against a single source of +transcript data in the reference specimen; do not clone snapshot DOM into a +second data path. ### Page-only visual language @@ -267,7 +278,7 @@ test while still breaking its geometry. | Change `.prose` or `.lede` globally | Agent intros, articles, framework, and presentation copy | Medium–high | Preserve the 42rem measure. Add a specific intro role if needed. | | Restyle generic `code` as a chip or change its size | Inline commands, terminal descendants, articles, and presentation code | Medium–high | Use `.command-chip`; reset terminal descendants locally to `font-size: inherit`. | | Tighten global `.card` padding and move hover motion | Home, directory, agent, article, presentation, and engage grids | High | Create a Devague card grammar. Keep hover transforms inside the no-preference motion query. | -| Add unscoped mock `--space-*` / `--fs-*` root tokens | Future namespace collisions and accidental cross-route consumption | Medium | Scope or prefix on `.devague-page`; promote through a separate global-token change. | +| Add unscoped mock `--space-*` / `--fs-*` root tokens | Future namespace collisions and accidental cross-route consumption | Medium | Use a collision-safe system namespace; only the Devague consumer opts in during its migration. Promote through a separate global-token change. | | Change global `.section` padding or introduce `vh` seams | Every content page; viewport-height-dependent blank bands | High | Give Devague one local vertical-rhythm owner. Test every adjacent section boundary. | | Replace `DevagueFlow` from generated snapshot CSS | Devague only, but duplicates DOM, observer, and stale breakpoints | Medium–high | Author a source component or explicit mode from accepted markup. Remove the old path only when the replacement is accepted. | | Rebuild method, gate, and skill cards | Devague only | Medium | Use semantic source components/data maps; preserve heading levels and accessible copy feedback. | @@ -280,6 +291,23 @@ test while still breaking its geometry. Each phase should be a separate, reviewable change. Do not combine a global primitive migration with a page composition rewrite. +“System established” has a concrete meaning here. Before the production +Devague route changes, the following must exist: + +- a named token registry covering spacing, type, colour, surface, elevation, + motion, page rail, reading measure, and component inset roles; +- opt-in primitives and component APIs, including their states and variants; +- an isolated reference specimen that exercises the system against the approved + Devague mock without replacing a public route; +- responsive, theme, keyboard, focus, reduced-motion, and no-JavaScript + acceptance contracts; and +- a status record separating established system rules from Devague-only content + and unresolved decisions. + +This is system-first without pretending the design is universal. The mock is +the reference evidence, the specimen proves the implementation, and Devague is +the first production migration. + ### Phase 0 — freeze the baseline - Work on a feature/UX branch, never directly on `main`. @@ -292,64 +320,79 @@ primitive migration with a page composition rewrite. **Gate:** the baseline is reproducible and failures are known before code is changed. -### Phase 1 — add a Devague namespace with no visual change - -- Add one `.devague-page` root around page-owned sections. -- Define candidate spacing/type aliases on that root, without switching existing - consumers yet. -- Establish one page rail, one reading measure, and named component insets. -- Add component names based on responsibility, not appearance. - -**Gate:** computed tokens do not leak to a second route; all baseline images are -unchanged. - -### Phase 2 — adopt low-interaction visual components - -- Implement facts, reference rows, method cards, gate cards, skill cards, and - command chips from source data. -- Apply the larger card-title role where the hierarchy requires it. -- Correct UI leading, monospace tracking, and local terminal inheritance. -- Keep the production `PageHero`, header, footer, and global card primitive. - -**Gate:** heading outline, keyboard names, copy result states, 3/2/1-column -behaviour, gutters, and theme contrast pass. - -### Phase 3 — replace the pipeline deliberately - -- Implement the approved light diagram surface in both site themes, with an - explicit component-owned surface/ink pairing rather than a global theme - override. -- Build the accepted source component with one semantic DOM path. -- Preserve a readable no-JavaScript list and the global reduced-motion contract. -- Verify one-column up to 40rem, 3×3 from 40–60rem, and 5+4 above 60rem. -- Remove a superseded flow and observer only in the same change that proves the - replacement. - -**Gate:** node order and labels are correct; no duplicate hidden flow, observer, -or horizontal overflow remains. - -### Phase 4 — implement guided captures - -- Follow the data and component boundary in - [`captures-story-plan.md`](captures-story-plan.md). -- Resolve excerpts by exact anchors from the single transcript source and fail - the build when an anchor drifts. -- Implement session headers, beats, terminal preview, disclosure, and modal as - separate source components. -- Make the full evidence readable or reachable without JavaScript. -- Test repeated open/close cycles so focus, scroll state, and listeners do not - leak. - -**Gate:** transcript bytes and chronological order are unchanged; modal focus, -Escape/backdrop close, focus restoration, previous/next boundaries, no-JS, and -reduced motion all pass. - -### Phase 5 — promote only proven patterns - -- Use a candidate on a second real page before calling it global. -- Compare both consumers and name only the shared semantics. -- Move the component and its tokens together, with a migration note. -- Leave Devague content and glyphs local. +### Phase 1 — specify and approve the system + +- Complete the token registry and map every accepted mock value to a semantic + role, an existing compatibility token, or a documented page-only exception. +- Freeze the page rail, reading measure, component-inset, type-role, surface, + motion, and breakpoint contracts. +- Define component responsibilities, props, states, semantics, and ownership. +- Record the approved light pipeline surface, larger card-title role, and + content that deliberately remains Devague-only. +- Do not edit `devague.astro` or change a current global selector. + +**Gate:** the system contract is reviewable as a whole, every mock pattern has +an owner/status, and no production route has changed. + +### Phase 2 — build and prove the opt-in system + +- Add collision-safe tokens and opt-in primitives without changing the current + global defaults. +- Build the facts, reference-row, method-card, gate-card, capability-card, + command-chip, terminal, pipeline, guided-session, disclosure, and modal + contracts as source components. +- Exercise them together in an isolated reference specimen using the real mock + content and transcript data. +- Resolve excerpts by exact transcript anchors and fail validation when an + anchor drifts. +- Keep the live `PageHero`, header, footer, Devague route, and other routes + unchanged. + +**Gate:** the specimen reaches visual and interaction parity with the approved +mock; heading outline, keyboard names, copy states, focus lifecycle, 3/2/1 +layouts, pipeline breakpoints, gutters, themes, reduced motion, no-JavaScript, +and transcript integrity pass; production route snapshots remain unchanged. + +### Phase 3 — migrate Devague as the first consumer + +- Add the `.devague-page` consumer namespace and assemble the established + system components in the live source route. +- Cut over in small commits on the UX branch, but judge acceptance against the + complete page rather than shipping a mixture of old and new systems. +- Preserve the current source Layout, `PageHero`, header, footer, data + provenance, and global progressive-enhancement contracts. +- Use the approved light pipeline surface with one semantic DOM path and verify + one column up to 40rem, 3×3 from 40–60rem, and 5+4 above 60rem. +- Migrate all three guided sessions, disclosures, and transcript-modal + interactions from the established components. +- Remove superseded Devague components, hidden variants, and observers only + after parity is proven. + +**Gate:** the production Devague page matches the accepted specimen across the +full regression matrix, with no duplicate flow, data source, observer, listener, +or horizontal overflow. + +### Phase 4 — harden the system after first migration + +- Run the cross-route containment suite, including the presentation deck. +- Fix weaknesses in the system owner rather than adding Devague-local patches. +- Reconcile the implemented token/component registry with this document and + record any deliberate exceptions. +- Keep all non-Devague routes on their existing design until separately planned. + +**Gate:** Devague is a clean first consumer, the system contract still describes +the implementation, and no other route has visually migrated by accident. + +### Phase 5 — migrate the rest of the site separately + +- Choose a second real consumer through a separate migration plan. +- Compare it with Devague and generalise only the semantics both genuinely + share. +- Promote opt-in tokens or primitives to global defaults only with cross-route + evidence and an explicit compatibility strategy. +- Migrate remaining routes in bounded groups rather than through one global CSS + switch. +- Keep Devague content, glyphs, and composition local. Likely first promotion candidates are the copy control, terminal shell, quiet reference row, and transcript modal. The shared terminal work should follow the @@ -431,7 +474,7 @@ Every design-system PR should answer these questions in its description: |---|---| | Decision | What user or content problem is being solved? | | Layer and owner | Foundation, primitive, component, composition, or experiment; which source file owns it? | -| Status | Candidate, page-only, promoted, or superseded. | +| Status | Candidate, established, page-only, migrated, promoted, or superseded. | | Existing contract touched | Selectors, components, tokens, data, and interaction lifecycle. | | Consumers | Every route/component that currently matches the changed contract. | | Containment | Namespace, component scope, modifier, or migration strategy. | @@ -451,9 +494,14 @@ Every design-system PR should answer these questions in its description: to the earlier dark treatment. - Devague card titles use the larger `1.25rem` semantic role where the mock has established that hierarchy; this does not retune global `h3` elements. -- The first implementation is Devague-scoped. +- The system is specified, built, and proven in an isolated reference specimen + before the live Devague route is migrated. +- Devague is the first production consumer; other routes migrate in later, + separately approved passes. - Page rail, reading measure, and component inset are separate roles. -- A shared token or component requires a second consumer and regression proof. +- A token or component may be established as opt-in from the mock and reference + specimen; becoming a global default requires a second real consumer and + regression proof. - Dormant comparison variants do not enter the production system. ### Human decisions still required before their phase @@ -465,6 +513,6 @@ Every design-system PR should answer these questions in its description: 3. Whether the raw spacing scale eventually becomes global or remains expressed through component-owned semantic tokens. -Those choices do not block the documentation, namespace, or baseline work. They -do block treating the relevant visual decision as a shared, finished system -rule. +Those choices do not block establishing the opt-in system or migrating Devague +as its first consumer. They do block later global promotion and the migration of +other routes. From 23cabf15c9aa795cbb996a2a25a5a9f33eb30198 Mon Sep 17 00:00:00 2001 From: Becky Still Date: Wed, 22 Jul 2026 12:11:47 +0100 Subject: [PATCH 07/32] docs(ux-review): add visual design system --- docs/ux-review/README.md | 59 +- docs/ux-review/current-direction.md | 28 +- docs/ux-review/design-system.html | 3039 +++++++++++++++++++++++++++ docs/ux-review/design-system.md | 6 + 4 files changed, 3100 insertions(+), 32 deletions(-) create mode 100644 docs/ux-review/design-system.html diff --git a/docs/ux-review/README.md b/docs/ux-review/README.md index 1236291..85e2cfe 100644 --- a/docs/ux-review/README.md +++ b/docs/ux-review/README.md @@ -14,6 +14,11 @@ Reviewed against a local production build at commit `d71a719` It reconciles the measured audit with the later Devague work and labels each artefact as current, supporting, or superseded. +**[`design-system.html`](design-system.html)** is the visual review surface. It +renders the proposed foundations, layout roles, responsive pipeline, +components, interactions, ownership boundaries, and migration gate without +changing the Astro site. + The original [`findings.md`](findings.md) remains the evidence baseline: seven findings with measurements and re-run recipes, plus the accessibility, responsive, reduced-motion, and no-JavaScript behaviour that later work must @@ -29,6 +34,7 @@ original site-wide audit, and the earlier section-level explorations. | File | Kind | Covers | |------|------|--------| | [`current-direction.md`](current-direction.md) | Markdown | Status, precedence, current decisions, and open calls | +| [`design-system.html`](design-system.html) | Interactive visual reference | Established foundations, Devague-derived candidates, page-only content, working interactions, and the system gate | | [`design-system.md`](design-system.md) | Markdown | Design-system layers, mock-to-site collision map, component catalogue, staged adoption plan, and regression gates | | [`mocks/devague/2026-07-21-review-style/`](mocks/devague/2026-07-21-review-style/README.md) | Full-page snapshot | Latest integrated Devague mock plus the documented responsive diagram repair | | [`captures-story-plan.md`](captures-story-plan.md) | Markdown | Guided three-session captures handoff and complete copy deck | @@ -52,9 +58,18 @@ across all 8 routes: | [`spacing-type-system.html`](spacing-type-system.html) | Interactive | Spacing and type tokens, with the operator-skills section rendered live from them | | [`captures-layout.html`](captures-layout.html) | Historical interactive exploration | Four measured gallery layouts; option D was later superseded by the guided-session direction | -The early HTML prototypes are self-contained and can be opened directly. The -preserved full-page mock is a small static bundle with local CSS and fonts; serve -its snapshot folder as the HTTP root: +The HTML review artefacts are self-contained. To review the visual system with +its local fonts and links intact, serve this folder as the HTTP root: + +```bash +python3 -m http.server 4620 --directory docs/ux-review +``` + +Then open . + +The preserved full-page mock is a small static bundle with local CSS and fonts; +to render its original `/agents/devague/` path, serve the snapshot folder as the +HTTP root: ```bash python3 -m http.server 4601 \ @@ -63,25 +78,25 @@ python3 -m http.server 4601 \ Then open . -Each one copies the site's own token values verbatim from -`site-astro/src/styles/global.css`. No artefact introduces a colour, font, radius -or shadow that the site does not already define. Where a proposal adds a token — -the spacing and line-height scales in `spacing-type-system.html` — it is marked -as proposed and shown against the current value it replaces. +The visual system preserves the site's semantic colour, font, radius, shadow, +and theme contracts. New spacing, type-size, leading, and tracking scales are +visibly labelled as candidates. Devague leg colours and the always-light +pipeline pairing are explicitly page-owned rather than implied global tokens. ## Suggested reading order For a maintainer or an agent picking this up cold: 1. `current-direction.md` — the precedence and status map. -2. `design-system.md` — the safe ownership, containment, and adoption method. -3. The preserved full-page Devague mock — the latest integrated visual state. -4. `captures-story-plan.md` and `pipeline-layout-plan.md` — the implementation +2. `design-system.html` — the visual system and interactive review surface. +3. `design-system.md` — the safe ownership, containment, and adoption method. +4. The preserved full-page Devague mock — the source visual evidence. +5. `captures-story-plan.md` and `pipeline-layout-plan.md` — the implementation handoffs, including the pipeline work requested after the final mock render. -5. `findings.md` — the measured baseline and verified strengths. -6. `agents-directory.html` and `agent-page-scaling.md` — independent site-wide +6. `findings.md` — the measured baseline and verified strengths. +7. `agents-directory.html` and `agent-page-scaling.md` — independent site-wide proposals not superseded by the Devague work. -7. The spacing/type and captures explorations when their rationale is needed. +8. The spacing/type and captures explorations when their rationale is needed. The site-wide audit finds the pattern library drifting because it is copied per page (`agent-page-scaling.md`); the section-level work finds spacing drifting @@ -97,12 +112,16 @@ The `agents-directory.html` demo re-derives its central measurement live in the browser from the rendered DOM rather than asserting it, and independently arrives at the same 4% figure quoted in the audit. -**Not implemented** — none of the proposals has been applied to the real site. -The documentation and current-site baseline may be checked with the repo's own -gates, but the proposed components have not yet been through `npm run build`, -`org site link-check`, `markdownlint-cli2`, or the SonarCloud quality gate. The -component API sketched in `agent-page-scaling.md` is a proposal, not tested code; -it should be treated as a starting shape to argue with, not a specification. +**Not implemented in Astro** — none of the proposals has been applied to the +real site. The standalone visual system makes candidate interactions operable +for review, but it is not the source component implementation and does not move +any candidate to “Established”. + +The review documents pass Markdown lint and local-link checks. A future Astro +implementation must still pass `npm run build`, `org site link-check`, the +responsive and accessibility suites, and the SonarCloud quality gate. The +component API sketched in `agent-page-scaling.md` remains a proposal rather than +tested source; treat it as a starting shape to argue with, not a specification. **One correction worth surfacing** — an earlier pass of this review recorded a scroll-reveal bug on `/agents/`, where elements sat at `opacity: 0` inside the diff --git a/docs/ux-review/current-direction.md b/docs/ux-review/current-direction.md index 16cffe7..426e718 100644 --- a/docs/ux-review/current-direction.md +++ b/docs/ux-review/current-direction.md @@ -1,6 +1,6 @@ # UX direction after the Devague mock -> **Status:** Current decision map, 21 July 2026. This file is additive. It +> **Status:** Current decision map, 22 July 2026. This file is additive. It > does not replace the original audit, alter an existing mock, or authorize a > change to the live site. @@ -18,16 +18,18 @@ that later work superseded. When two documents disagree, use this order: 1. This current-direction map for status and precedence. -2. The [`design-system.md`](design-system.md) adoption plan for ownership, +2. The [`design-system.html`](design-system.html) visual review surface for the + candidate tokens, layout roles, components, interactions, and system gate. +3. The [`design-system.md`](design-system.md) adoption plan for ownership, containment, promotion, and regression gates. -3. The [preserved full-page Devague mock](mocks/devague/2026-07-21-review-style/README.md) +4. The [preserved full-page Devague mock](mocks/devague/2026-07-21-review-style/README.md) for the last successfully rendered integrated composition. -4. The two current Devague handoffs: +5. The two current Devague handoffs: [`captures-story-plan.md`](captures-story-plan.md) and [`pipeline-layout-plan.md`](pipeline-layout-plan.md). -5. The original audit for measured evidence: +6. The original audit for measured evidence: [`findings.md`](findings.md). -6. Earlier interactive explorations for rationale, not implementation +7. Earlier interactive explorations for rationale, not implementation authority. The full-page Devague review mock is retained in this worktree. Its HTML and @@ -42,6 +44,7 @@ evidence and the handoff as the intended implementation direction. | Artefact | Status | How to use it now | |---|---|---| | `current-direction.md` | Current map | Start here for precedence and scope. | +| [`design-system.html`](design-system.html) | Current visual review surface | Review the proposed system, responsive states, and working interactions. It deliberately labels candidates and does not establish them in Astro. | | [`design-system.md`](design-system.md) | Current adoption plan | Use to classify mock patterns, contain changes, assess overwrite risk, and gate promotion into the shared site. | | [Devague full-page mock](mocks/devague/2026-07-21-review-style/README.md) | Latest retained mock | Review the complete composition, interactions, and responsive diagram repair. The manifest records the final pipeline requests that did not land in the Claude render. | | [`captures-story-plan.md`](captures-story-plan.md) | Current handoff | Governs the Devague real-captures redesign. | @@ -192,11 +195,12 @@ accessibility, responsive, theme, no-JavaScript, and reduced-motion checks. ## Suggested reading order 1. This document. -2. [`design-system.md`](design-system.md). -3. The [preserved full-page Devague mock](mocks/devague/2026-07-21-review-style/README.md). -4. [`captures-story-plan.md`](captures-story-plan.md). -5. [`pipeline-layout-plan.md`](pipeline-layout-plan.md). -6. [`findings.md`](findings.md), for the measured baseline and verified +2. [`design-system.html`](design-system.html). +3. [`design-system.md`](design-system.md). +4. The [preserved full-page Devague mock](mocks/devague/2026-07-21-review-style/README.md). +5. [`captures-story-plan.md`](captures-story-plan.md). +6. [`pipeline-layout-plan.md`](pipeline-layout-plan.md). +7. [`findings.md`](findings.md), for the measured baseline and verified strengths. -7. The relevant supporting prototype or architecture note only when its topic +8. The relevant supporting prototype or architecture note only when its topic is being implemented. diff --git a/docs/ux-review/design-system.html b/docs/ux-review/design-system.html new file mode 100644 index 0000000..3bf9f62 --- /dev/null +++ b/docs/ux-review/design-system.html @@ -0,0 +1,3039 @@ + + + + + + + AgentCulture visual system — Devague reference + + + + + + +
    +
    +
    + + AgentCulture visual system +
    + +
    +
    +
    + Candidate + Devague reference + System-first +
    +

    First light over the mesh.

    +

    + A visual reference for reviewing the system before any production page migrates. + The Devague mock supplies the evidence; this page separates reusable rules from + page-owned composition and makes the proposed interactions real enough to test. +

    +
    + +
    +
    +
    + Review artefact +
    +

    No production route has changed. Appearance here means “ready to review”, not “established in Astro”.

    + +
    + +
    + Review theme +
    + + + +
    +
    +
    +
    +
    +
    + +
    + + +
    +
    +
    + 01 · review key +

    See the lifecycle before judging the details.

    +

    + The visual system is deliberately opt-in. A pattern can be visible and operable here + while still waiting for approval, source implementation, and a production consumer. +

    +
    + +
      +
    1. ExistingAlready part of the production contract.
    2. +
    3. CandidateSpecified strongly enough to review and build.
    4. +
    5. EstablishedOpt-in source implementation passes its system gate.
    6. +
    7. MigratedA named production page consumes it.
    8. +
    9. PromotedTwo real consumers prove it can become a shared default.
    10. +
    + +
    +
    + Page-only +

    Devague content, glyphs, ordering, and evidence remain local even when their shell is reusable.

    +
    +
    + Dormant +

    Retained comparison variants stay in provenance only and are not presented as options.

    +
    +
    + Open decision +

    A review choice that must not be hidden inside implementation work.

    +
    +
    +
    + +
    +
    + 02 · foundations +

    One sky at two hours.

    +

    + Dawn and pre-dawn use the same semantic roles. The diagram keeps its approved light + pairing in both themes; terminals remain dark evidence windows. +

    +
    + +
    +
    +
    DawnPre-dawn
    +
    --bg#f4f5fb / #0b0f20
    +
    +
    +
    DawnPre-dawn
    +
    --surface#ffffff / #161b36
    +
    +
    +
    DawnPre-dawn
    +
    --ink#232a4d / #e9ecf8
    +
    +
    +
    DawnPre-dawn
    +
    --ink-soft#4d546f / #a9b0cf
    +
    +
    +
    DawnPre-dawn
    +
    --accent#0b655c / #7fdcc9
    +
    +
    +
    DawnPre-dawn
    +
    --line14% semantic ink
    +
    +
    + +
    +

    Devague evidence palette

    +
    +
    frame · #7fdcc9
    +
    plan · #f2b774
    +
    check · #a9b0cf
    +
    scope · #7fb3f2
    +
    challenge · #e6cd7a
    +
    deviate · #f2789a
    +
    summary · #b49cf2
    +
    +
    +
    + +
    +
    + 03 · typography +

    Editorial argument, technical evidence.

    +

    + Fraunces carries the idea; Albert Sans explains it; monospace identifies state, + commands, and provenance. Sizes are roles rather than nested percentages. +

    +
    + +
    +
    +
    Display / H1Existing · fluid 41.6–72px
    +
    Accountable delivery.
    +
    +
    +
    Section / H2Existing · fluid 25.6–33.6px
    +
    A vague idea in, an accountable delivery out.
    +
    +
    +
    Card titleCandidate · 20px / 1.25 / −.01em
    +
    What does this idea touch?
    +
    +
    +
    ProseExisting alias · 17px / 1.7
    +
    The frame engine works backwards from the announcement, keeping each claim inspectable before anything becomes a plan.
    +
    +
    +
    Eyebrow / labelCandidate metrics · 12px / 1.25 / .12em
    +
    The operator skills
    +
    +
    +
    TerminalCandidate · 13px / 1.55 / flat tracking
    +
    $ devague capture --kind audience
    +
    +
    + +
    +
    --ac-lh-tight1.1Display
    +
    --ac-lh-ui1.25Labels and titles
    +
    --ac-lh-normal1.55Card body
    +
    --ac-lh-prose1.7Long reading
    +
    +
    + +
    +
    + 04 · spacing +

    A fixed rhythm with semantic ownership.

    +

    + Eight raw steps replace accidental em compounding. Components map those steps to + named relationships rather than scattering raw scale values through markup. +

    +
    + +
      +
    1. --ac-space-14px
    2. +
    3. --ac-space-28px
    4. +
    5. --ac-space-312px
    6. +
    7. --ac-space-416px
    8. +
    9. --ac-space-524px
    10. +
    11. --ac-space-632px
    12. +
    13. --ac-space-748px
    14. +
    15. --ac-space-864px
    16. +
    + +
    +
    space-3Label → title
    +
    space-5Card / terminal inset
    +
    space-6Capability grid gap
    +
    space-7Intro → module
    +
    +
    + +
    +
    + 05 · layout +

    Rail, measure, and inset are three different jobs.

    +

    + Consistent gutters come from one page edge. Reading measure constrains prose inside + it; component inset creates breathing room inside a surface. None should masquerade + as another container. +

    +
    + +
    +
    Existing production rail · 68rem max / 24px minimum edge +
    Candidate Devague presentation rail · 58rem max +
    Existing reading measure · 42rem +
    Candidate surface inset · 24px
    +
    +
    +
    +
    +
    + Existing page rail + Candidate local rail + Reading measure +
    + +
    +
    + Existing +

    Default surface

    +

    --radius: 1.25rem with the established low elevation.

    +
    +
    + Existing +

    Lifted surface

    +

    Reserved for interaction emphasis and full transcript focus.

    +
    +
    +
    + +
    +
    + 06 · primitives +

    The smallest repeatable agreements.

    +

    These specimens show the vocabulary from which larger Devague compositions are assembled.

    +
    + +
    +
    + Section introduction +
    ExistingMetrics candidate
    +
    +
    +
    + The frame engine +

    Before there is a frame, survey the surfaces.

    +

    Each finding lands as first-class state citing what was actually read—provenance, not disclaimers.

    +
    +
    +
    + +
    +
    + Fast facts +
    Candidate shellDevague content
    +
    +
    +
      +
    • Installuv tool install devague
    • +
    • Repoagentculture/devague
    • +
    • Packagedevague · PyPI
    • +
    • LicenseApache-2.0
    • +
    +
    +
    + +
    +
    + Quiet reference rows +
    Candidate shellSeven transitions
    +
    +
    +
      +
    1. +
      idea → scopeThe frame engine
      +

      Survey the surfaces the idea touches before framing it.

      +
      scope "<surface>"--finding--seeds
      +
    2. +
    3. +
      idea → specThe frame engine
      +

      Work backwards from the announcement and pressure-test every claim.

      +
      captureinterrogateconverge
      +
    4. +
    +
    +
    +
    + +
    +
    + 07 · responsive process +

    One semantic sequence, three spatial arrangements.

    +

    + The shell is a candidate component. The exact glyphs, labels, and nine-stage order + remain Devague-owned. The surface stays light in every review theme. +

    +
    + +
    +
    + Pipeline summary +
    Candidate shellPage-only narrative
    +
    +
    + Preview container width +
    + + + +
    +
    +
    +
    +
    +
      +
    1. + + ideaannouncement +
    2. + +
    3. + + framecapture · confirm +
    4. + +
    5. + + convergegate +
    6. + +
    7. + + specexport +
    8. + +
    9. + + challengeblind spots +
    10. + +
    11. + + wavesplan +
    12. + +
    13. + + buildworkforce +
    14. + +
    15. + + deviateledger +
    16. + +
    17. + + summaryartifact +
    18. +
    +
    + A vague idea becomes an announcement frame, a defensible spec, a challenged plan, + a workforce build, an append-only departure ledger, and a closing accountability artifact. +
    +
    +
    +
    +
    +
    + +
    +
    + 08 · component gallery +

    Reusable shells, explicitly local content.

    +

    Each component owns its layout, state, semantics, and tokens. Devague owns the example data.

    +
    + +
    +
    + Method cards +
    Candidate shellSeven moves
    +
    +
    +
    +
    01 · scope

    What does this idea touch?

    Read the surfaces before a frame exists.

    +
    02 · capture

    What must be true?

    Turn claims into inspectable proposed state.

    +
    03 · converge

    Who confirms the frame?

    A human closes every gate a machine cannot grade.

    +
    +
    +
    + +
    +
    + Human gate +
    Candidate shellSix gates
    +
    +
    +
    +
    01 · human gate

    Confirm the frame

    Nothing converges until a person confirms that specific claim.

    +
    +
    +
    Human gate + +
    + $ devague confirm c1 +
    +
    +
    +
    +
    +
    + +
    +
    + Capability cards +
    Candidate shellSeven skills
    +
    +
    +
    +
    + Frame · operator skill +

    /scope + +

    +

    Surveys before the frame.

    +
    +
    +
    Frame · operator skill

    /think

    Walks an idea to an exported spec.

    +
    Challenge · operator skill

    /challenge

    Pressure-tests the exported spec for blind spots.

    +
    +
    +
    + +
    +
    + Terminal +
    Candidate shellTranscript data
    +
    +
    +
    +
    FRAME LEGidea → spec + +
    +
    $ devague capture --kind audience "operators"
    +captured c2 (proposed)
    +
    +$ devague confirm c2
    +confirmed c2
    +
    +… settled transcript, never nested smaller than 13px
    +
    +
    +
    +
    + +
    +
    + Guided session +
    Candidate shellThree sessions · 14 beats
    +
    +
    +
    +
    + Session 01 · frame engine +

    An idea becomes a defensible spec

    +

    Plain-language beats sit beside tiny verbatim excerpts, with the full record always reachable.

    +
      +
    1. +
      +

      Promises land as proposed

      The announcement becomes state a human can challenge.

      $ devague capture --kind audience
      captured c2 (proposed)
      +
    2. +
    3. +
      +

      The human closes the gate

      Confirmation records the decision without pretending the tool made it.

      +
    4. +
    +
    + Walk through this session +
    +

    The complete walkthrough remains readable without JavaScript and changes state without height animation.

    + Read raw capture +
    +
    +
    + +
    +
    SESSION PREVIEW
    +
    $ devague frame announce
    +frame f1 opened
    +
    +$ devague capture --kind audience
    +captured c2 (proposed)
    +
    +$ devague confirm c2
    +confirmed c2
    +
    +
    + +
    + + Without JavaScript, the raw transcript above remains the fallback. +
    +
    +
    +
    + +
    +
    + 09 · interaction contract +

    State is visible, announced, and recoverable.

    +

    + Copy targets are at least 44px, disclosure uses a native control, and the transcript + modal uses the platform dialog contract with Escape, backdrop close, and focus restoration. +

    +
    + +
    +
    + Copy control +

    Success and failure both speak.

    +

    Select this command even if clipboard access is denied: /summarize-delivery

    +
    + + +
    +
    +
    + Focus state +

    Keyboard focus stays obvious.

    +

    The same semantic accent outlines buttons, links, dialog controls, and scrollable transcript regions.

    +
    +
    +
    +
    + +
    +
    + 10 · ownership boundaries +

    Do not mistake a successful page for a universal primitive.

    +

    Mixed patterns are split into reusable shell and Devague-owned content before implementation begins.

    +
    + +
    +
    Page-only register
    +

    Devague keeps ownership of:

    +
      +
    • the exact nine-stage glyph narrative;
    • +
    • seven pipeline transitions;
    • +
    • seven method moves and their order;
    • +
    • six human gates and commands;
    • +
    • seven operator skills;
    • +
    • three sessions, 14 beats, and ten transcripts;
    • +
    • terminal leg colours and pane order;
    • +
    • issue groupings and closing mark.
    • +
    +
    + +
    +
    Dormant · do not adopt
    +

    Retained for provenance, not rendered as options:

    +
      +
    • the hidden original flow variant;
    • +
    • the hidden static flow variant;
    • +
    • the earlier terminal grid;
    • +
    • the capped capture grid and expand control;
    • +
    • the unused primer card;
    • +
    • the unused session-hero variant.
    • +
    +
    +
    + +
    +
    + 11 · system gate +

    What must pass before Devague migrates.

    +

    This visual reference is the review surface. Source implementation is established only after these contracts pass.

    +
    + +
      +
    • Widths360, 375, 640, 768, 960, and 1440px; diagram checks at its 639/640/641 and 799/800/801 container boundaries.
    • +
    • ThemesSystem, dawn, and pre-dawn; pipeline remains light and terminal remains dark.
    • +
    • KeyboardLogical tab order, visible focus, 44px targets, Escape and focus restoration.
    • +
    • MotionFinished content at first paint; no reveal, typing, or smooth movement under reduced motion.
    • +
    • No JavaScriptTranscripts and walkthroughs remain readable; enhancement-only controls disappear.
    • +
    • IntegrityNo horizontal page overflow, one pipeline DOM, one transcript source, byte-identical evidence.
    • +
    + +
    +
    + Approved +

    System-first order

    +
      +
    • Establish the opt-in system.
    • +
    • Prove the reference specimen.
    • +
    • Migrate Devague first.
    • +
    • Migrate other routes separately.
    • +
    +
    +
    + Approved +

    Visual direction

    +
      +
    • Light pipeline surface.
    • +
    • 20px semantic card title.
    • +
    • One page rail per section.
    • +
    • Fixed spacing and explicit type metrics.
    • +
    +
    +
    + Open +

    Later decisions

    +
      +
    • Pipeline copy reductions.
    • +
    • Whether the 58rem local rail is accepted.
    • +
    • Which route becomes the second consumer.
    • +
    • Whether raw spacing becomes a root default.
    • +
    +
    +
    +
    +
    +
    + +
    +
    + AgentCulture visual system · Devague reference · review artefact only · 22 July 2026 +
    +
    + + +
    +
    +
    +

    Frame engine

    +

    Session 1 of 3 · idea → spec

    +
    + +
    +
    +

    Session 01 · Frame engine

    +
    +
    FRAME LEG
    +
    
    +        
    +
    + +
    +
    + + + + diff --git a/docs/ux-review/design-system.md b/docs/ux-review/design-system.md index 6038bff..b4323e7 100644 --- a/docs/ux-review/design-system.md +++ b/docs/ux-review/design-system.md @@ -4,6 +4,11 @@ > `ux-review` at `ef392d9`, after merging `origin/main` at `aea608b`. This is a > documentation-only plan: no file under `site-astro/` has been changed. +> **Visual review companion:** open [`design-system.html`](design-system.html) +> to inspect the token roles, layout rails, responsive pipeline, candidate +> components, interaction contracts, and adoption boundary described here. It +> is a standalone review specimen, not an Astro source implementation. + The Devague mock is now rich enough to be treated as design-system evidence, but it is not a replacement stylesheet for the site. It contains a mixture of good shared foundations, promising reusable components, Devague-specific @@ -35,6 +40,7 @@ site-wide restyle by accident. | [`site-astro/src/pages/agents/devague.astro`](../../site-astro/src/pages/agents/devague.astro) | Current production Devague semantics, section order, and component boundaries. | | [`site-astro/src/components/DevagueFlow.astro`](../../site-astro/src/components/DevagueFlow.astro) | Current production pipeline component and its progressive-enhancement contract. | | [`site-astro/src/components/DevagueTerminal.astro`](../../site-astro/src/components/DevagueTerminal.astro) | Current production terminal semantics, replay behaviour, and capture rendering. | +| [`design-system.html`](design-system.html) | Current visual review surface for the candidate system, with working interaction and responsive specimens. Appearance here means ready to review, not established in source. | | [Retained full-page mock](mocks/devague/2026-07-21-review-style/README.md) | The latest integrated visual direction and interaction specimen. | | [`captures-story-plan.md`](captures-story-plan.md) | Intended guided-session content model, verbatim-evidence contract, and source-component handoff. | | [`pipeline-layout-plan.md`](pipeline-layout-plan.md) | Intended pipeline hierarchy, responsive behaviour, and animation repairs. | From b12762ef882e90d31dfc3951c23edb9736a400d7 Mon Sep 17 00:00:00 2001 From: Becky Still Date: Thu, 23 Jul 2026 19:24:43 +0100 Subject: [PATCH 08/32] feat(site): unify navigation, wayfinding, and design system --- .github/workflows/tests.yml | 8 + docs/ux-review/README.md | 75 +-- .../global-type-and-section-width-system.md | 456 ++++++++++++++++++ site-astro/package.json | 4 + site-astro/scripts/check-closing-bands.mjs | 150 ++++++ site-astro/scripts/check-design-system.mjs | 107 ++++ site-astro/scripts/check-presentations.mjs | 17 +- site-astro/scripts/check-wayfinding.mjs | 217 +++++++++ .../src/components/AgentDirectoryCard.astro | 105 ++++ site-astro/src/components/Breadcrumbs.astro | 85 ++++ site-astro/src/components/ClosingBand.astro | 107 ++++ .../src/components/ColleagueTerminal.astro | 28 +- .../src/components/DevagueTerminal.astro | 24 +- .../src/components/ExternalLinkIcon.astro | 20 + site-astro/src/components/Footer.astro | 157 ++++-- site-astro/src/components/Header.astro | 130 +++-- site-astro/src/components/LobesTerminal.astro | 16 +- site-astro/src/components/PageHero.astro | 14 +- .../src/components/PrimaryNavigation.astro | 146 ++++++ .../src/components/ReachyTerminal.astro | 28 +- site-astro/src/components/SectionNav.astro | 70 +++ site-astro/src/data/navigation.test.mjs | 216 +++++---- site-astro/src/data/navigation.ts | 111 ++++- site-astro/src/data/site.ts | 74 +-- site-astro/src/data/types.ts | 20 +- site-astro/src/pages/agents.astro | 131 +++-- site-astro/src/pages/agents/colleague.astro | 213 ++++---- site-astro/src/pages/agents/devague.astro | 179 +++---- site-astro/src/pages/agents/lobes.astro | 130 ++--- .../src/pages/agents/reachy-mini-cli.astro | 150 +++--- site-astro/src/pages/articles/index.astro | 16 +- .../articles/mind-nervous-system-body.astro | 85 ++-- site-astro/src/pages/engage.astro | 11 +- site-astro/src/pages/framework.astro | 8 +- site-astro/src/pages/index.astro | 44 +- .../src/pages/presentations/index.astro | 16 +- .../mind-nervous-system-body.astro | 53 +- site-astro/src/styles/global.css | 150 +++++- 38 files changed, 2762 insertions(+), 809 deletions(-) create mode 100644 docs/ux-review/global-type-and-section-width-system.md create mode 100644 site-astro/scripts/check-closing-bands.mjs create mode 100644 site-astro/scripts/check-design-system.mjs create mode 100644 site-astro/scripts/check-wayfinding.mjs create mode 100644 site-astro/src/components/AgentDirectoryCard.astro create mode 100644 site-astro/src/components/Breadcrumbs.astro create mode 100644 site-astro/src/components/ClosingBand.astro create mode 100644 site-astro/src/components/ExternalLinkIcon.astro create mode 100644 site-astro/src/components/PrimaryNavigation.astro create mode 100644 site-astro/src/components/SectionNav.astro diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 611b0b4..e7a834f 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -94,6 +94,14 @@ jobs: - run: npm run build + - run: npm run test:navigation + + - run: npm run check:wayfinding + + - run: npm run check:closing-bands + + - run: npm run check:design-system + - run: npm run check:presentations - run: node --experimental-strip-types --test src/data/mind-nervous-system-body-slides.test.mjs diff --git a/docs/ux-review/README.md b/docs/ux-review/README.md index 85e2cfe..d490bd3 100644 --- a/docs/ux-review/README.md +++ b/docs/ux-review/README.md @@ -1,18 +1,32 @@ # UX review — agentculture.org -An outside UX review of the built site, contributed for the maintainers and their -agents to work with. Nothing here changes any site file; every artefact is a -proposal, and each states its method so it can be checked rather than taken on -trust. - -Reviewed against a local production build at commit `d71a719` +This folder began as an outside UX review of the built site. It now contains a +mixture of historical proposals, retained visual evidence, and the current +review record for work implemented in the uncommitted `ux-review` working tree. +Each artefact states its date and method so it can be checked rather than taken +on trust. + +> **Current working-tree implementation record:** +> [`global-type-and-section-width-system.md`](global-type-and-section-width-system.md) +> audits the present 12-route `ux-review` worktree and the retained Devague +> mock, records the adopted global typography and rail decisions, and reports +> their current verification status. The eight-route baseline and earlier +> adoption-status statements below remain historical. + +The original review baseline was a local production build at commit `d71a719` (`site-astro@0.0.1`, Astro static output, 8 routes). ## Start here -**[`current-direction.md`](current-direction.md)** is the current decision map. -It reconciles the measured audit with the later Devague work and labels each -artefact as current, supporting, or superseded. +For the new site-wide typography and section-width initiative, start with +**[`global-type-and-section-width-system.md`](global-type-and-section-width-system.md)**. +It audits the current source and explicitly identifies which older documents +are dated. + +**[`current-direction.md`](current-direction.md)** remains the decision map for +the earlier Devague-composition work. It reconciles the measured audit with +that later mock and labels each artefact as current, supporting, or superseded +at the time it was written. **[`design-system.html`](design-system.html)** is the visual review surface. It renders the proposed foundations, layout roles, responsive pipeline, @@ -33,6 +47,7 @@ original site-wide audit, and the earlier section-level explorations. | File | Kind | Covers | |------|------|--------| +| [`global-type-and-section-width-system.md`](global-type-and-section-width-system.md) | Markdown | Current 12-route typography/rail evidence, stale-document reconciliation, adopted roles, migration status, and verification record | | [`current-direction.md`](current-direction.md) | Markdown | Status, precedence, current decisions, and open calls | | [`design-system.html`](design-system.html) | Interactive visual reference | Established foundations, Devague-derived candidates, page-only content, working interactions, and the system gate | | [`design-system.md`](design-system.md) | Markdown | Design-system layers, mock-to-site collision map, component catalogue, staged adoption plan, and regression gates | @@ -87,16 +102,18 @@ pipeline pairing are explicitly page-owned rather than implied global tokens. For a maintainer or an agent picking this up cold: -1. `current-direction.md` — the precedence and status map. -2. `design-system.html` — the visual system and interactive review surface. -3. `design-system.md` — the safe ownership, containment, and adoption method. -4. The preserved full-page Devague mock — the source visual evidence. -5. `captures-story-plan.md` and `pipeline-layout-plan.md` — the implementation +1. `global-type-and-section-width-system.md` — the current implementation and + verification record. +2. `current-direction.md` — the earlier Devague precedence and status map. +3. `design-system.html` — the historical visual-system review surface. +4. `design-system.md` — the earlier ownership, containment, and adoption method. +5. The preserved full-page Devague mock — the source visual evidence. +6. `captures-story-plan.md` and `pipeline-layout-plan.md` — the implementation handoffs, including the pipeline work requested after the final mock render. -6. `findings.md` — the measured baseline and verified strengths. -7. `agents-directory.html` and `agent-page-scaling.md` — independent site-wide +7. `findings.md` — the measured baseline and verified strengths. +8. `agents-directory.html` and `agent-page-scaling.md` — independent site-wide proposals not superseded by the Devague work. -8. The spacing/type and captures explorations when their rationale is needed. +9. The spacing/type and captures explorations when their rationale is needed. The site-wide audit finds the pattern library drifting because it is copied per page (`agent-page-scaling.md`); the section-level work finds spacing drifting @@ -112,10 +129,11 @@ The `agents-directory.html` demo re-derives its central measurement live in the browser from the rendered DOM rather than asserting it, and independently arrives at the same 4% figure quoted in the audit. -**Not implemented in Astro** — none of the proposals has been applied to the -real site. The standalone visual system makes candidate interactions operable -for review, but it is not the source component implementation and does not move -any candidate to “Established”. +**Current Astro status** — the global typography/rail system and related IA +work are implemented only in the uncommitted `ux-review` working tree. The +standalone HTML artefacts remain historical review surfaces rather than source +components. Older statements that no proposal has touched Astro describe their +own earlier baselines, not the current working tree. The review documents pass Markdown lint and local-link checks. A future Astro implementation must still pass `npm run build`, `org site link-check`, the @@ -131,16 +149,17 @@ prompted it came from a stuck renderer in the review tooling, not from the site. The reveal system is sound. It is flagged here because a reader skimming for problems should not carry away a defect that does not exist. -## Constraints respected +## Current constraints -- **No site files touched.** This folder is additive; nothing under `site-astro/` - is modified. -- **Markdown lints clean** against the repo's `.markdownlint-cli2.yaml`. +- **Site files are changed locally for review.** Nothing has been committed, + pushed, deployed, or submitted as a PR. +- **Learn is untouched.** The separate Learn source and deployment are outside + this migration. - **Version bump.** The repo's `version-check` CI job fails any PR whose `pyproject.toml` version matches `main`'s, including docs-only changes. That - bump has not been made here — use the `version-bump` skill before opening a PR. -- **`main` is protected**, so this arrives as a branch for review rather than a - direct push. + bump has not been made because no PR is being prepared yet. +- **`main` is protected.** The current work remains on `ux-review` for local + review. ## Scope diff --git a/docs/ux-review/global-type-and-section-width-system.md b/docs/ux-review/global-type-and-section-width-system.md new file mode 100644 index 0000000..4b2d66d --- /dev/null +++ b/docs/ux-review/global-type-and-section-width-system.md @@ -0,0 +1,456 @@ +# Global typography and section-width system + +> **Status:** Implemented in the current `ux-review` working tree on 22 July +> 2026 and awaiting user visual review. The work is uncommitted: no push, PR, +> deployment, route change, or Learn source/deployment change has been made. + +> **Audit baseline:** the current `ux-review` working tree at `2cb8101`, plus +> its uncommitted information-architecture and navigation work. That worktree +> contains 12 owned routes, the six-item primary navigation ending in +> **Open Learn**, breadcrumbs, local section navigation, and the grouped footer. + +## Adopted direction in one paragraph + +The migration adopts the Devague work as a role-based global system, but does +not copy its built CSS and does not replace `.container` in one operation. It +preserves 17px for real body/prose copy; adopts the mock's smaller page-title +ceiling, lede scale, heading measure, terminal size, compact leading, and +tracking roles; and adds +named page, shell, wide, heading, and prose rails. A faithful 58rem shell also +requires moving the desktop-navigation breakpoint because the current six-item +header uses all available inline space at 768px. Bespoke diagrams and the +presentation deck need explicit wide/deck roles rather than inheriting the +standard page rail. + +## Scope + +This migration covers four connected foundations: + +1. font-size roles; +2. line-height roles; +3. letter-spacing roles; and +4. section rails and reading measures. + +It deliberately does **not** cover: + +- font-family, weight, colour, radius, shadow, or motion changes; +- navigation order, current-state matching, breadcrumbs, footer information + architecture, or the Open Learn destination; +- changes in the separate Learn source or deployment; +- route, redirect, content, transcript, or presentation-story changes; +- making bespoke diagram labels use editorial text roles; or +- card padding and vertical section spacing, except where later layout testing + proves they must be adjusted to support the approved type and rail choices. + +## Evidence and authority + +The sources do not describe one consistent final system. Use this order for +this initiative: + +| Priority | Source | Use | +|---:|---|---| +| 1 | Current authored Astro source under [`site-astro/src`](../../site-astro/src) | The source of truth for today's structure, inheritance, components, breakpoints, and blast radius. | +| 2 | The retained [Devague full-page mock](mocks/devague/2026-07-21-review-style/README.md), judged from its rendered computed styles | Visual evidence for the desired density and hierarchy. It is not source code to transplant. | +| 3 | [`spacing-type-system.html`](spacing-type-system.html) and [`spacing-type-and-captures.md`](spacing-type-and-captures.md) | The rationale behind the role model and the terminal-legibility fix. | +| 4 | Earlier UX-review status and adoption documents | Historical context only where they agree with the current source and this reviewed proposal. | + +The retained mock began from the production build at `d71a719`, then changed in +a scratchpad and was retained at `cea730b`. The local `ux-review-spacing` branch +currently points to `35cdfd3`. Neither baseline contains the current header, +footer, breadcrumbs, route inventory, or navigation behaviour. + +### Dated documents that must not silently govern this work + +| Document or artefact | Dated assumption | Treatment here | +|---|---|---| +| [`README.md`](README.md) and [`findings.md`](findings.md) | Audit `d71a719`, `site-astro@0.0.1`, and eight routes. | Retain measured historical evidence; do not use their route count or current-state claims. | +| [`current-direction.md`](current-direction.md) | Says no proposal in the folder has been applied to `site-astro/`. | That describes an earlier worktree and does not describe the current uncommitted IA/navigation implementation. | +| [`design-system.md`](design-system.md) | Freezes the 68rem container, treats Devague as opt-in only, and records four failures in a 20-check presentation baseline. | Its ownership and regression principles remain useful. Its containment decision is the question now being reopened; its test status is stale. The current presentation checker passes 21 checks. | +| [`spacing-type-system.html`](spacing-type-system.html) | Shows a 36px display role, four-column operator-skills layout, grid outdent, 32–96px gutter, 68rem container, and 17px prose. | Use its type-role rationale, not its example layout as the final mock. | +| Retained mock HTML/CSS | Uses an old four-link header and flat footer; contains generated selectors and layered prototype overrides. | Use rendered appearance and measurements only. Never copy `_astro` output into source. | + +This document is the review surface for the implemented migration. It does not +retroactively rewrite the intent of the older artefacts. + +## What the retained mock actually renders + +The final retained page is not the same as the early spacing prototype. The +following values were measured in a local browser against the retained +snapshot, not inferred from comments: + +| Role | 390px viewport | 768px viewport | 1280px viewport | Final rendered rule | +|---|---:|---:|---:|---| +| Body | 16px | 16px | 16px | Browser-default `1rem`, leading `1.7`. | +| Page h1 | 38.4px | 46.08px | 57.6px | `clamp(2.4rem, 6vw, 3.6rem)`, leading `1.1`, tracking `-0.015em`. | +| Lede | 18.4px | 18.4px | 21.6px | `clamp(1.15rem, 2.2vw, 1.35rem)`, leading `1.6`. | +| Section h2 | 25.6px | 25.6px | 33.6px | Restored to `clamp(1.6rem, 3vw, 2.1rem)`, leading `1.14`, tracking `-0.01em`, 44rem maximum. | +| Ordinary section paragraph | 15.2px | 15.2px | 15.2px | A late `.95rem` page override, leading `1.7`. | +| Pipeline card title | 20px | 20px | 20px | `1.25rem`, leading `1.25`, tracking `-0.01em`. | +| Card/skill explanatory copy | 14.72px | 14.72px | 14.72px | `.92rem`, leading `1.55`. | +| Operator-skill title | 18.4px | 18.4px | 18.4px | A later `1.15rem` exception, leading `1.3`. | +| Terminal transcript | 13px | 13px | 13px | `.8125rem`, leading `1.55`, flat tracking; nested code inherits. | + +The mock's `.container` has a 58rem **outer** maximum and includes its side +padding because the site uses `box-sizing: border-box`: + +| Viewport | Outer container | Inline padding | Usable content width | +|---:|---:|---:|---:| +| 390px | 390px | 20px each side | 350px | +| 768px | 768px | 38.4px each side | 691.2px | +| 1024px and above | 928px | 48px each side | 832px / 52rem | + +That distinction matters: “58rem section width” in this mock does not mean +58rem of usable content plus gutters. + +### Conflicts inside the old work + +The old work contains at least six material conflicts that require an explicit +choice: + +1. Intended prose is 17px in the early system, 16px on the mock body, and + 15.2px in most final mock sections. +2. Intended display tracking is `-0.02em`; the retained h1 actually renders at + `-0.015em`. +3. A late mock rule first flattened h2 to 24px, then another rule restored the + existing responsive 25.6–33.6px h2. +4. Uppercase tracking is proposed as `0.12em`, but untouched mock eyebrows + still render at `0.17em`. +5. Operator skills move from the early four-column/outdented example to the + retained three-column/aligned layout. +6. The card-title token is 20px, while a later operator-skill title exception + renders at 18.4px. + +These are prototype seams, not a global specification. + +## Adopted type roles + +The following is the recommended normalization. Token names are draft API +names for review; the values and semantic boundaries matter more than the +exact spelling. + +| Role | Recommended value | Applies to | Does not automatically apply to | +|---|---:|---|---| +| Page title | `clamp(2.4rem, 6vw, 3.6rem)` | Shared `PageHero` titles and equivalent editorial page titles. | Home brand hero, article talk title, or deck slide titles until each is deliberately mapped. | +| Section title | `clamp(1.6rem, 3vw, 2.1rem)` | Editorial h2 headings at the section level. | Card headings, diagram labels, or slide typography. | +| Card title | `1.25rem` | Structural card and reference-row titles. | Every h3 merely because it is an h3. | +| Component title | `1.15rem` | Compact component titles where 20px is too loud. | Long editorial headings. | +| Lede | `clamp(1.15rem, 2.2vw, 1.35rem)` | Page introductions and intentional closing statements. | All first paragraphs by selector. | +| Body/prose | `1.0625rem` / 17px | Long-form paragraphs and substantial card copy. | Navigation, metadata, terminal transcripts, or diagram labels. | +| UI/supporting | `0.92rem` / 14.72px | Short navigation/supporting labels with adequate targets. | Paragraph-length explanatory card copy. | +| Metadata | `0.75rem` / 12px | Eyebrows, short tags, and non-essential context. | Primary instructions or essential content. | +| Micro metadata | `0.6875rem` / 11px | Non-essential compact terminal/leg labels only, after zoom and contrast review. | Body copy or interactive labels. | +| Terminal | `0.8125rem` / 13px | Transcript content, set once on the terminal region. | Inline code in prose. | + +The recommendation intentionally does **not** carry the mock's 15.2px section +paragraph rule into the global system. It would make long-form copy smaller +than the current site and smaller than the early system intended. Likewise, +`.92rem` is a compact UI role, not a new default card-body size. Multi-line +reading copy should remain at least 1rem, with 17px retained for prose. + +### Adopted leading roles + +| Role | Value | Intended use | +|---|---:|---| +| Display | `1.1` | Large page titles. | +| Heading | `1.14` | Responsive editorial section headings. | +| Compact UI | `1.25` | Eyebrows, tags, single-line controls, and compact titles. | +| Card copy | `1.55` | Short-measure multi-line supporting copy. | +| Lede | `1.6` | Introductions and highlighted statements. | +| Prose | `1.7` | Long-form reading copy at the prose measure. | + +This adds a named `1.14` heading role because both the current site and the +final rendered mock use it. Forcing every h2 into either `1.1` or `1.25` would +lose an established and visually useful middle role. + +### Adopted tracking roles + +| Role | Value | Intended use | +|---|---:|---| +| Display | `-0.015em` | Page titles; this follows the retained rendered result. | +| Heading | `-0.01em` | Section, card, and component headings. | +| Flat | `0` | Body text and all monospace transcripts. | +| Caps | `0.12em` | Uppercase metadata at 13px and below. | +| Identity | Existing local values | Wordmarks and other brand marks remain deliberate exceptions. | + +The global `code, .repo { font-size: .82em; letter-spacing: .01em; }` rule must +not be allowed to shrink or track terminal descendants. Terminals should set +13px once and make their nested `code` and line spans inherit both size and +tracking. + +### Implemented token shape + +The implemented global API uses these names and values: + +```css +--ac-type-page-title: clamp(2.4rem, 6vw, 3.6rem); +--ac-type-section-title: clamp(1.6rem, 3vw, 2.1rem); +--ac-type-card-title: 1.25rem; +--ac-type-component-title: 1.15rem; +--ac-type-lede: clamp(1.15rem, 2.2vw, 1.35rem); +--ac-type-body: 1.0625rem; +--ac-type-ui: 0.92rem; +--ac-type-meta: 0.75rem; +--ac-type-micro: 0.6875rem; +--ac-type-terminal: 0.8125rem; + +--ac-leading-display: 1.1; +--ac-leading-heading: 1.14; +--ac-leading-ui: 1.25; +--ac-leading-card: 1.55; +--ac-leading-lede: 1.6; +--ac-leading-prose: 1.7; + +--ac-tracking-display: -0.015em; +--ac-tracking-heading: -0.01em; +--ac-tracking-flat: 0; +--ac-tracking-caps: 0.12em; +``` + +The `--ac-` namespace avoids collisions with the mock's unscoped `--fs-*`, +`--lh-*`, and `--ls-*` experiment tokens. + +## Adopted horizontal system + +One global width cannot safely serve text, navigation, cards, terminals, +diagrams, and presentation slides. The design system names each job: + +| Role | Adopted maximum | Purpose | +|---|---:|---| +| Standard page rail | 58rem outer width, including fluid gutters | Shared heroes and ordinary content sections; this is the retained mock's visual rail. | +| Shell rail | 58rem with a 52rem desktop-menu threshold | Header and grouped footer; the details menu now remains active through 51.99rem. | +| Wide rail | 74rem outer width, providing 68rem of usable content at the maximum gutter | Agent diagrams, dense grids, multi-column terminal compositions, and data-rich surfaces that lose meaning at 58rem. | +| Deck content rail | 68rem usable width inside its existing 24px viewport inset | Six full-viewport slides and their internal compositions; it does not inherit a changed generic `.container`. The name deliberately avoids the deck's existing `.deck-rail` slide navigation. | +| Heading measure | 44rem | Long section headings, with ordinary greedy wrapping rather than globally balanced wrapping. | +| Prose measure | 42rem | Long-form copy; target roughly 65–75 characters per line. | +| Page gutter | `clamp(1.25rem, 5vw, 3rem)` | The retained mock's 20–48px responsive inset. Surface padding remains separate. | + +### Header constraint created by the new navigation + +At a 768px viewport, the current desktop header measures: + +- 158.9px wordmark; +- 537.1px desktop-menu region; +- 24px gap; and +- 720px available width on the current rail. + +When the mock's 58rem rail and fluid gutter are simulated, the navigation +shrinks to its 508.3px minimum and the three pieces consume the entire 691.2px +usable width. It fits, but with effectively no tolerance for font metrics, +copy, or browser differences. The retained mock did not reveal this because it +only had four primary links. + +The review considered two coherent options: + +| Option | Result | Trade-off | +|---|---|---| +| **A — recommended for visual consistency:** use the 58rem shell rail and move the desktop-menu threshold from 48rem to about 52rem. | Header, hero, sections, and footer share one edge system; 768px uses the accessible details menu. | Changes the already-reviewed menu breakpoint and therefore requires another focused navigation test. | +| **B — lowest navigation risk:** retain the 68rem shell rail and its 48rem breakpoint; use 58rem for ordinary page sections only. | Preserves current header behaviour. | Shell and content edges no longer reproduce the retained mock's single rail. | + +Option A is adopted. The 58rem shell and 52rem threshold are implemented and +covered by the navigation and rendered geometry checks. + +### Why `.container` must not be flipped globally + +The current `.container` appears in 55 authored wrappers across 15 files. It +controls the header, footer, `PageHero`, all route families, and every slide in +the current deck. Replacing its declaration would simultaneously: + +- change shell fit and the mobile-menu threshold; +- rewrap breadcrumbs and “On this page” links; +- reduce several four-column grids to three and several three-column grids to + two; +- narrow fixed two-column agent/profile arrangements; +- change terminal viewport widths and internal scrolling; and +- alter six slide compositions without any presentation-specific diff. + +Introduce named rail primitives and migrate wrappers intentionally. Keep +`.container` as a compatibility alias until every use has an assigned role; +do not make a base-selector edit the migration mechanism. + +## Current blast-radius audit + +The current source contains 231 `font-size`, 56 `line-height`, 71 +`letter-spacing`, and 67 `max-width` declarations across authored Astro/CSS. +This is not a defect by itself: diagram labels, terminals, slide art, and +editorial copy need different roles. It does mean a global selector change +cannot establish the system safely. + +### Shared surfaces + +| Surface | Current dependency | Impact and required treatment | +|---|---|---| +| [`global.css`](../../site-astro/src/styles/global.css) | 17px body, 1.7 leading, 2.6–4.5rem h1, 1.6–2.1rem h2, 42rem prose, 68rem container, generic `.82em` code. | Add namespaced roles first. Avoid changing body, h1, `.container`, `.card`, or `code` as a migration shortcut. | +| [`Layout.astro`](../../site-astro/src/layouts/Layout.astro) | Imports the global sheet and renders shell components for every route. | Makes every base-selector change site-wide. No new document-shell behaviour is needed. | +| [`Header.astro`](../../site-astro/src/components/Header.astro) and [`PrimaryNavigation.astro`](../../site-astro/src/components/PrimaryNavigation.astro) | Current rail, 48rem menu breakpoint, 1.22rem wordmark, `.92rem` links and Open Learn CTA. | Assign shell rail and UI roles together. Keep Open Learn last, green, new-tab, and outside current-section matching. Re-test exact breakpoint fit. | +| [`Footer.astro`](../../site-astro/src/components/Footer.astro) | Current rail plus several local text sizes and grouped navigation. | Assign shell rail and supporting/meta roles; verify group wrapping and external-link cues in both themes. | +| [`PageHero.astro`](../../site-astro/src/components/PageHero.astro) | Global h1, lede, prose, and container inherited by nine routes. | First shared editorial consumer. A title or rail change immediately affects nine route openings, breadcrumbs, intros, and local section navigation. | +| [`Breadcrumbs.astro`](../../site-astro/src/components/Breadcrumbs.astro) | `.82rem` text and wrapping inside heroes/deck opening. | Map to compact UI without reducing the 44px interactive target context; test long current-page labels at 320px. | +| [`SectionNav.astro`](../../site-astro/src/components/SectionNav.astro) | `.72rem` caps label and `.82rem` links. | Map label to caps/meta and links to compact UI; verify wrapping and focus order after rail changes. | +| [`AgentDirectoryCard.astro`](../../site-astro/src/components/AgentDirectoryCard.astro) | Local title, role, repository, and destination sizes. | Map by semantic role. The role paragraph is reading copy and should not be reduced to the compact `.92rem` default merely because it sits in a card. | + +### Route families + +| Routes | What will move | Primary risks / required exception | +|---|---|---| +| `/` | Home title and tagline are explicitly sized; About and Explore still use global rail/prose; five Explore cards use a 15.5rem auto-fit grid. | Keep a named brand-hero type separate from page-title type. A 58rem inner width changes the Explore layout from roughly 4+1 to 3+2 at wide screens; review that composition, do not accept it accidentally. Keep the mesh scene on its 76rem visual rail. | +| `/framework/` | Shared hero plus a 46rem pillar column with local h2/tagline/point sizes. | Standard-page candidate. Preserve the vertical thread alignment when heading metrics change. | +| `/agents/` | Shared hero, Browse-by-area jump list, group headings, destination labels, and auto-fill directory grid. | A 58rem rail changes the wide directory from four cards to three. Recheck group-anchor landings, counts, and whole-card focus/hover states. | +| `/agents/devague/` | Shared hero plus pipeline, facts, cards, skills, terminals, issue grids, and a custom 56rem flow cap. | Reference consumer for the role system, not source CSS. Decide which compositions need page versus wide rail. Preserve transcript data and progressive enhancement. | +| `/agents/colleague/` | Shared hero plus the largest local type surface: facts, pills, tables, capability grids, diagrams, terminals, and two-column evidence layouts. | Highest profile-page regression risk. Several 15–16rem auto-fit grids lose a column; tables and terminals need independent overflow checks. | +| `/agents/lobes/` | Shared hero, method/capability grids, diagrams, code surfaces, and terminals. | 13.5–15rem grids can lose columns. Keep diagram typography isolated from editorial roles. | +| `/agents/reachy-mini-cli/` | Shared hero, runtime diagram, agent/robot facts, terminal evidence, and 2:3 evidence layout. | Physical-system diagrams and wide terminal evidence require wide-rail review; its 2:3 layout already collapses at 52rem, which may collide with a new shell breakpoint. | +| `/articles/` | Shared hero and 20rem minimum library cards. | A 58rem usable width changes the likely wide layout from three cards to two. Map topic/source metadata separately from summaries. | +| `/articles/mind-nervous-system-body/` | Bespoke 2.8–6rem talk title, breadcrumbs, section nav, 47rem intro, 46rem narrative blocks, beat grid, evidence grid, diagram, and closing links. | Treat the talk title as an editorial-feature role, not the normal page-title token. Test long-form measure, heading wrapping, beat numbering, evidence cards, and sticky/jump offsets. | +| `/presentations/` | Shared hero, 20rem library cards, thumbnail pairs, metadata, and summaries. | Same three-to-two-column risk as Articles, plus thumbnail legibility. | +| `/presentations/mind-nervous-system-body/` | Six full-viewport slides use `.container`, many local clamps, 26–58rem content caps, responsive multi-column layouts, and presentation breadcrumbs. | Must receive an explicit deck rail and retain its own type scale. Only shared breadcrumbs/shell tokens should migrate automatically. Global `.container`, h1, h2, or body changes must not resize slide art by inheritance. | +| `/engage/` | Shared hero and 46rem channel list. | Standard-page candidate; verify icon/title alignment and 44px interactive targets after type mapping. | + +### Component classes that need containment + +1. **Editorial text:** `PageHero`, article narrative, framework, directory + summaries, card summaries. These should consume the new global roles. +2. **Shell/UI text:** header, footer, breadcrumbs, local navigation, tags, and + destination cues. These use compact roles but retain 44px targets. +3. **Terminal text:** all four agent terminal components. These need one 13px + transcript role, flat tracking, nested inheritance, and intentional + horizontal scrolling. +4. **Diagram/data labels:** agent diagrams, article architecture diagram, home + mesh, and deck illustrations. Their pixel/rem values are visual-encoding + choices and should remain component-owned in this pass. +5. **Presentation typography:** slide titles, statements, captions, rails, and + source labels. The deck is its own responsive type system and opts out of + editorial defaults. + +## Implementation sequence and current status + +Each stage remains a reviewable working-tree change. No PR or handoff is +implied. Phases 1–7 are implemented; phase 8 remains intentionally deferred +until visual review confirms the migration. + +### Phase 0 — record decisions — complete + +Approve or amend the choices at the end of this document. Capture reference +screenshots of all 12 current routes before visual changes. + +### Phase 1 — add tokens — complete + +Add namespaced type, leading, tracking, measure, and rail tokens. Initially map +existing selectors to their current computed values so token introduction and +visual redesign are separate diffs. + +### Phase 2 — add named text and rail primitives — complete + +Add explicit page, shell, wide, deck, prose, and heading roles. Do not redefine +`.container`. Add compatibility aliases only where they preserve current +rendering. + +### Phase 3 — migrate shell and shared wayfinding — complete + +Migrate Header, PrimaryNavigation, Footer, Breadcrumbs, SectionNav, and +PageHero. If shell option A is approved, change and test the menu breakpoint in +this phase with the rail; never as a later incidental fix. + +### Phase 4 — migrate standard/index routes — complete + +Migrate Framework, Engage, Home prose/Explore, Agents directory, Articles +index, and Presentations index. Review grid column-count changes as design +decisions rather than generic responsive fallout. + +### Phase 5 — migrate long-form editorial content — complete + +Migrate the article detail route, preserving its feature-title role and 42rem +reading measure. Review every section heading at actual copy length. + +### Phase 6 — migrate agent profiles one at a time — complete + +Use Devague first to prove the roles, then Colleague, Lobes, and Reachy. Assign +page versus wide rails section by section. Consolidate terminal typography as +a component change, not repeated page overrides. + +### Phase 7 — contain and verify the deck — complete + +Give the presentation an explicit deck rail and type ownership. Only then +remove any remaining dependence on the legacy `.container` meaning. + +### Phase 8 — decide legacy cleanup — deferred + +After all 12 routes have an assigned role, decide whether `.container`, +generic h1/h2 rules, and generic code sizing can be deprecated or safely +aliased. Cleanup is not part of the first visual migration. + +## Acceptance plan + +### Automated contracts + +- `npm run build` produces all 12 routes. +- `npm run test:navigation` retains exact order, descendant matching, false- + prefix rejection, and Open Learn metadata. +- `npm run check:wayfinding` retains breadcrumbs, structured data, anchors, + footer groups, and new-tab cues. +- `npm run check:presentations` remains green; add geometry-oriented deck + assertions because content contracts cannot detect a narrowed slide. +- Link checking remains green and no Learn source/deployment is touched. +- Add a rendered-style audit that fails when terminal `code` is smaller than + its terminal container or when page/shell rails use an unassigned width. + +### Visual and accessibility matrix + +Test all 12 routes at 320, 375, 768, 1024, and 1440px, plus one pixel on each +side of every changed breakpoint. Run in light and dark themes, JavaScript on +and off, reduced motion, keyboard-only navigation, and at 200% browser zoom. + +Verify: + +- no horizontal page overflow; +- header and Open Learn remain visible and reachable; +- mobile `
    ` has one logical tab sequence; +- headings do not orphan a single short word unnecessarily; +- ordinary prose stays near 65–75 characters per line; +- body and substantial card copy remain at least 16px; +- 11–12px metadata is non-essential, high-contrast, and legible at zoom; +- every interactive target remains at least 44px; +- directory and library column-count changes look intentional; +- breadcrumbs and local section navigation wrap without collisions; +- terminal transcript text computes to 13px and nested code inherits; +- terminals scroll internally where necessary without causing page overflow; +- bespoke diagrams retain label fit and accessible descriptions; and +- all six slides preserve their intended composition and viewport behaviour. + +## Recorded decisions for this migration + +| Decision | Recommendation | Approval | +|---|---|---| +| Body/prose size | Keep 17px; reject the mock's 15.2px section override as a global role. | Adopted | +| Shared page-title size | Adopt `clamp(2.4rem, 6vw, 3.6rem)` for normal page titles. | Adopted | +| Home/article/deck titles | Keep explicit feature roles; review them separately rather than inheriting the normal page title. | Adopted | +| Section h2 | Keep the final responsive 25.6–33.6px rule, 1.14 leading, `-0.01em` tracking, and 44rem measure. | Adopted | +| Display tracking | Use the retained rendered `-0.015em`, not the earlier `-0.02em` intention. | Adopted | +| Caps tracking | Normalize ordinary uppercase metadata to `0.12em`; keep identity exceptions local. | Adopted | +| Compact copy | Limit `.92rem` to short supporting/UI text; keep substantial multi-line copy at least 1rem. | Adopted | +| Terminal typography | Adopt 13px / 1.55 / flat tracking with nested inheritance across all four terminal components. | Adopted | +| Standard page rail | Adopt the retained 58rem outer rail with 20–48px fluid gutters. | Adopted | +| Shell rail and nav breakpoint | Use the 58rem shell and a 52rem desktop-menu threshold. | Adopted | +| Wide and deck rails | Add explicit roles; do not force diagrams, dense terminal grids, or slides onto the standard rail. | Adopted | +| Grid reflow | Assign page and wide rails route by route, then review the rendered column counts rather than inheriting one global width. | Implemented; user visual review pending | + +## Implementation boundary and verification + +Implementation remains confined to this `org` repository and uncommitted. It +does not modify or deploy Learn. The existing information-architecture work, +grouped site footer, and four-profile `ClosingBand` treatment remain separate +semantic surfaces and are preserved by dedicated contracts. + +The current working tree has passed: + +- a 12-route production build and local link check with zero broken links; +- 7 navigation tests and 38 wayfinding checks; +- the 4-route closing-band contract, including all 7 reviewed actions; +- 103 design-system checks, including explicit wrapper roles, shell geometry, + six deck content rails, and four terminal inheritance contracts; +- 21 presentation checks and 17 slide-data tests; and +- a rendered route matrix in both themes at 320, 375, 768, 832, 833, 1024, + and 1440px, with reduced motion, JavaScript disabled, 200% text sizing, + terminal inheritance, 44px Open Learn targets, and horizontal overflow + checks. + +Manual visual and keyboard review remains appropriate before any commit or PR. diff --git a/site-astro/package.json b/site-astro/package.json index da0882a..8fff3ac 100644 --- a/site-astro/package.json +++ b/site-astro/package.json @@ -8,7 +8,11 @@ "scripts": { "dev": "astro dev", "build": "astro build", + "check:closing-bands": "node scripts/check-closing-bands.mjs", + "check:design-system": "node scripts/check-design-system.mjs", "check:presentations": "node scripts/check-presentations.mjs", + "check:wayfinding": "node --experimental-strip-types scripts/check-wayfinding.mjs", + "test:navigation": "node --experimental-strip-types --test src/data/navigation.test.mjs", "preview": "astro preview", "astro": "astro" }, diff --git a/site-astro/scripts/check-closing-bands.mjs b/site-astro/scripts/check-closing-bands.mjs new file mode 100644 index 0000000..af98e67 --- /dev/null +++ b/site-astro/scripts/check-closing-bands.mjs @@ -0,0 +1,150 @@ +import { existsSync, readFileSync } from "node:fs"; +import { dirname, join, resolve } from "node:path"; +import { fileURLToPath } from "node:url"; + +const siteRoot = resolve(dirname(fileURLToPath(import.meta.url)), ".."); +const distRoot = join(siteRoot, "dist"); + +const adoptedRoutes = new Map([ + [ + "/agents/devague/", + { + name: "devague", + actions: [ + ["https://github.com/agentculture/devague", "Read the code →"], + ["https://pypi.org/project/devague/", "uv tool install devague"], + ], + }, + ], + [ + "/agents/colleague/", + { + name: "colleague", + actions: [ + ["https://github.com/agentculture/colleague", "Read the code →"], + ["https://pypi.org/project/colleague/", "uv tool install colleague"], + ], + }, + ], + [ + "/agents/lobes/", + { + name: "lobes", + actions: [["https://github.com/agentculture/lobes-cli", "Read the code →"]], + }, + ], + [ + "/agents/reachy-mini-cli/", + { + name: "reachy-mini-cli", + actions: [ + ["https://github.com/agentculture/reachy-mini-cli", "Read the code →"], + [ + "https://pypi.org/project/reachy-mini-cli/", + "uv tool install 'reachy-mini-cli[daemon]'", + ], + ], + }, + ], +]); + +const unchangedRoutes = [ + "/", + "/agents/", + "/articles/", + "/articles/mind-nervous-system-body/", + "/engage/", + "/framework/", + "/presentations/", + "/presentations/mind-nervous-system-body/", +]; + +const failures = []; +const check = (condition, message) => { + if (!condition) failures.push(message); +}; + +function htmlFor(route) { + const path = route === "/" ? join(distRoot, "index.html") : join(distRoot, route, "index.html"); + check(existsSync(path), `${route}: built output is missing`); + return existsSync(path) ? readFileSync(path, "utf8") : ""; +} + +function decodeHtml(value) { + return value + .replace(/&#x([0-9a-f]+);/gi, (_, code) => String.fromCodePoint(Number.parseInt(code, 16))) + .replace(/&#([0-9]+);/g, (_, code) => String.fromCodePoint(Number.parseInt(code, 10))) + .replace(/&/g, "&") + .replace(/>/g, ">") + .replace(/</g, "<") + .replace(/"/g, '"') + .replace(/'/g, "'"); +} + +function textContent(value) { + return decodeHtml(value.replace(/<[^>]+>/g, " ")).replace(/\s+/g, " ").trim(); +} + +function closingBand(html) { + return html.match(/]*data-closing-band[^>]*>[\s\S]*?<\/section>/i)?.[0] ?? ""; +} + +for (const [route, expected] of adoptedRoutes) { + const html = htmlFor(route); + if (!html) continue; + + const bands = html.match(/data-closing-band/g) ?? []; + const band = closingBand(html); + const mainStart = html.indexOf(""); + const bandStart = html.indexOf("data-closing-band"); + const footerStart = html.indexOf('