Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions docs/now/2026-09-10-the-site-viewport-contract-as-a-t27-spec.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# NOW -- The site viewport contract as a .t27 spec (2026-09-10)

## The site viewport contract as a .t27 spec (Closes #3557)

- `specs/ui/viewport.t27` (module `ui_viewport`, `KIND = "viewport"`) is the one source for how the explorers of t27.ai (`#/specs`, `#/skills`, `#/crons`, `#/agents`, `#/tools`, `#/functions`) lay themselves out: four tiers by CSS viewport width with inclusive bounds `PHONE_MAX = 600`, `TABLET_MAX = 1024`, `DESKTOP_MAX = 1600`; `HEADER_CHROME_MAX = 1100` (the threshold the explorers' TSX already used for trimming the header, kept inside the desktop tier so 1025-1099 renders as before; not a tier); `PHONE_PANES = 1` (list or card, never both; a `?<key>=` deep link opens the card), `TABLET_PANES = 2`, `DESKTOP_PANES = 2`; `ONE_SCROLLER_PER_PANE = true`, `DOCUMENT_SCROLLS = false`; `TOUCH_TARGET_MIN_PX = 44`, `BACK_CONTROL_MIN_PX = 44`; the six-size QA matrix `390x844 600x900 768x1024 1024x768 1280x800 1920x1080` as labels and as integers, with the tier of each entry; `DESKTOP_REFERENCE_WIDTH = 1280`. Schema and rules in `specs/ui/README.md`.
- Evidence is in the file: the `SOURCE` comment records the live measurement (t27.ai, 2026-09-09, cloud Chromium, DPR 1: at 390x844 `#/tools?tool=mcp%2Fgitbutler` shows only the 62-item list, the card is not in the viewport, document scrollHeight 924 > 844; reproduced on a build of trinity main c881e7f where the hash written after mount is ignored), and the Queen rail numbers (`RAIL_*`) carry the `Queen.css` line each was read from. The rail and HUD are described, not changed: the first consumer is the explorers only (P0), and a QA contract may report the rail as warnings.
- Six `test` blocks, 49 asserts, inside the spec: monotone bounds, the 44 px minimum, every matrix entry in the tier the bounds say, the six quoted sizes, one pane on a phone, and the rail capacity arithmetic per matrix height. Measured under the vendored compiler wasm on the site: typecheck ok, nothing discarded, 49/49 asserts hold. `typecheck.ok` is lenient (true for `assert 1 > 2`), so the site's generator (`scripts/viewport-from-spec.mjs`, gHashTag/trinity) evaluates the asserts from the AST and refuses the spec otherwise; its own tests cover a false assert, a `;` comment inside a block, a matrix tier that disagrees with the bounds, a non-ASCII byte, stale generated files and determinism.
- Inside a `test` block only `//` comments are safe: the parser reads a `;` line inside a block as a statement (recorded in the README).
- English only, ASCII only, no user-visible copy in the spec (so no i18n SCOPE row); no absolute developer home path; the checkout is referred to as `T27_ROOT` or `git rev-parse --show-toplevel`.
- `specs/OWNERS.md` gains the row `ui/` -> **T-Queen**.
- `tools/published_figures.py`: the pinned `test blocks` population follows the corpus, 12456 -> 12462 (the six test blocks of this spec), with the movement written next to the pin as the file's protocol asks; the other nine figures are unchanged and `--check` exits 0.
- Not claimed: the bootstrap compiler on `master` was not run against this file; the Queen rail capacity is a model (a CSS budget plus one consistent observation at 1024x768), not a measurement of every height; `gate-topology` and `untrusted-input` still fail on `master` for already-merged PRs and are not addressed here.
1 change: 1 addition & 0 deletions specs/OWNERS.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
| `functions/` | **T-Queen** | The 28 Inngest functions of `999-multibots-telegraf` as `.t27` specs (`functions/<id>.t27`, `KIND = "function"`): canonical and legacy ids and events, trigger, steps, retries, failure handling, side effects, guard and the 2026-09-09 safe-probe result; the site joins them to a vendored copy of the functions manifest |
| `tools/` | **T-Queen** | The `tri` CLI commands and the MCP servers as `.t27` specs (`tools/tri/<command>.t27`, `tools/mcp/<server>.t27`, `KIND = "tool"`): what a command or server is for, its actions or tools, its source and witness (`source-parse` / `help-output`), and the agent letters a source evidently binds; the three older files at the top of `tools/` are ordinary corpus specs |
| `docs/` | **Z-Zeta** (with **T-Queen** for `chapters/queen.t27`) | The system documentation of `t27.ai/#/docs` as `.t27` specs (`docs/system.t27`, `KIND = "docs"`; `docs/chapters/<id>.t27`, `KIND = "docs-chapter"`): chapter ids, sections, sources, the figure and table the site generates; English prose in `docs/system/<id>.md`, Russian via `i18n/docs-ru.t27` |
| `ui/` | **T-Queen** | The site's viewport contract as a `.t27` spec (`ui/viewport.t27`, `KIND = "viewport"`): tiers by CSS viewport width, panes per tier, the 44 px touch minimum, the six-size QA matrix and the Queen rail capacity read from `Queen.css`; the site (gHashTag/trinity) generates `viewport.generated.ts` / `.css` from a vendored copy and evaluates the spec's own test blocks |

Each subtree with substantial churn should keep a local **`OWNERS.md`** (see below).

Expand Down
71 changes: 71 additions & 0 deletions specs/ui/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
# specs/ui -- the site's viewport contract as a declared spec

> **Where this lives.** `specs/ui/` in `gHashTag/t27` is the canonical home of the
> viewport contract of t27.ai -- edit it here. `gHashTag/trinity` keeps a byte-identical
> vendored copy under `apps/website/public/t27/files/specs/ui/`; its build reads that copy
> through the vendored compiler wasm (`t27_compiler.wasm`) and generates
> `src/lib/viewport.generated.ts` and `src/styles/viewport.generated.css` from it
> (`scripts/viewport-from-spec.mjs`). Nothing is parsed with a regular expression and no
> breakpoint is typed twice. The wasm's `typecheck.ok` is necessary, not sufficient (it
> stays true for `assert 1 > 2`), so the generator also evaluates every `test` block of the
> spec against the declared constants and refuses a spec whose own tests do not hold. The
> bootstrap compiler on `master` was not run against this file in the commit that added it.
> A checkout of this repository is referred to as `T27_ROOT` (an environment variable) or
> `git rev-parse --show-toplevel`; no file here names an absolute path.

## Files

| File | Module | Role |
|---|---|---|
| `viewport.t27` | `ui_viewport` | `KIND = "viewport"`: the four tiers by CSS viewport width, the compact-chrome threshold, the pane rule per tier, the touch-target minimum, the six-size QA matrix with the tier of each entry, the desktop reference width, and the Queen rail capacity table (described, not changed) |

## Fields of `viewport.t27`

| Field | Type | Meaning |
|---|---|---|
| `KIND`, `ID`, `NAME` | `str` | `"viewport"`, `"ui/viewport"`, a display name |
| `GENERATED` | `[2]str` | The two files the site derives from this spec (relative to `apps/website`) |
| `TIERS` | `[4]str` | `phone`, `tablet`, `desktop`, `wide` |
| `PHONE_MAX`, `TABLET_MAX`, `DESKTOP_MAX` | `u16` | Inclusive upper bounds in CSS px: `phone <= PHONE_MAX < tablet <= TABLET_MAX < desktop <= DESKTOP_MAX < wide` |
| `COARSE_POINTER_QUERY` | `str` | The media feature that says the pointer cannot hover |
| `HEADER_CHROME_MAX` | `u16` | Below this width the explorer header drops subtitle and note. Not a tier; it sits strictly inside the desktop tier so 1025-1099 renders as before |
| `PHONE_PANES`, `TABLET_PANES`, `DESKTOP_PANES` | `u8` | Panes visible at once: phone shows list **or** card (master-detail), the others both |
| `ONE_SCROLLER_PER_PANE`, `DOCUMENT_SCROLLS` | `bool` | One vertical scroller per visible pane; the document itself does not scroll |
| `TOUCH_TARGET_MIN_PX`, `BACK_CONTROL_MIN_PX` | `u8` | Smallest interactive box per side on phone and tablet; the phone card's way back to the list meets the same minimum |
| `VIEWPORTS`, `VIEWPORT_WIDTHS`, `VIEWPORT_HEIGHTS`, `VIEWPORT_TIERS` | `[6]str`, `[6]u16`, `[6]u16`, `[6]str` | The QA matrix every viewport contract iterates, written as labels and as integers so a test can index them, plus the tier of each entry |
| `DESKTOP_REFERENCE_WIDTH` | `u16` | The width at which the desktop layout must stay pixel-identical across a change |
| `RAIL_*` | `u8` / `u16` / `[6]u8` | The Queen rail's tile sizes, gaps and chrome heights read from `Queen.css` (file:line in the comments) and the capacity per matrix height they predict. Described, not changed: the first consumer is the explorers only |

## Rules

- **Tests inside the spec.** Every invariant the site relies on (monotone bounds, the 44 px
minimum, every matrix entry in the tier the bounds say, the rail capacity arithmetic) is an
`assert` in a `test` block of the same file. The site's generator evaluates them; a failing
assert is a failed build, not a warning.
- **Evidence in the file.** The `SOURCE` comment names the measurement each number rests on
(live t27.ai, the date, the viewport, what was observed) or the `Queen.css` line it was
read from. A number without a source does not belong here.
- **Comments.** Top-level comments use `;`. Inside a `test` block use `//` only: the parser
reads a `;` line inside a block as a statement, and the site's generator reports it.
- **English only, ASCII only** (LANG-EN, L3). UI copy is not in this spec; the site's
Russian travels through its i18n bundles, which this spec does not name because it carries
no user-visible text.
- **Do not edit the generated files by hand.** Change this spec, re-vendor it byte-identical,
re-run the generator; the generated files carry the spec's sha256 in their header.
- **Not a Queen spec.** The rail and HUD numbers are recorded so a QA contract can report
them; changing the rail is a separate round with its own approval.

## How the site uses it

```
T27_ROOT/specs/ui/viewport.t27
-> trinity apps/website/public/t27/files/specs/ui/viewport.t27 (byte-identical copy)
-> node scripts/viewport-from-spec.mjs (compiler wasm, asserts evaluated)
-> src/lib/viewport.generated.ts tiers, tierOf(width), tierQuery(tier), VIEWPORTS
-> src/styles/viewport.generated.css :root custom properties (touch minimum, rail tiles)
-> src/lib/useViewport.ts { tier, width, height, coarsePointer } via matchMedia + resize
-> qa/explorer-viewport-contract.mjs the six explorers at the six sizes, headless Chrome
```

`npm run check:viewport` fails when the committed generated files are not the ones the
vendored spec produces; `npm run check:explorer-viewport` runs the browser contract.
Loading
Loading