| @@ -29,104 +29,29 @@ is for that loop. |
| | - `just changed` names the files changed since tests last passed and the |
| | tests that cover them; `just t-changed` runs those and marks the pass. |
| | `just t <cargo test args>` runs any selection on the shared PDS. |
| | - The web pages are the SvelteKit app in `web/`; knotless-serve answers |
| | what they show as XRPC queries, each with its lexicon under |
| | `lexicons/` and the views it shares in `dev.knotless.defs`, as |
| | atproto's appviews do. The pages' TypeScript types are made from those |
| | lexicons by @atproto/lex (`npm run lex` in `web/`, which `dev`, `build` |
| | and `check` run first), into `web/src/lib/lexicons`, not kept in git. |
| | `just lex` checks the answers the screenshots recorded against their |
| | lexicons, and the `test` check every answer the serve tests receive. |
| | - Before changing a page, load the `ui` skill (`.claude/skills/ui`): |
| | its house rules (sentence case, empty states, space), and `just |
| | look`, which draws any page in any state from the recording as |
| | pictures to open: empty, signed in, a menu open, a long title. Look |
| | at every state you touch before pushing. |
| | - For the web pages: the pull's `shots` check shows what moved, with |
| | pictures. No screenshot is kept anywhere: the pages are shot as main |
| | draws them and as the change does, in one run. To look before pushing, |
| | `just shots`, which builds `web/` and main's, shoots only the pages |
| | whose HTML differs, drawn from `harness/shots/fixtures.json` with no |
| | PDS, and leaves each that moved under `target/shots/results/` (its |
| | expected, actual and diff). After a change to what a page's answer |
| | holds, `just shots-up` in the background once, then `just |
| | shots-record`. Each checkout's shots have three ports of their own, |
| | from its path; `SHOTS_PORT` sets another base for all of these. |
| | - `shots-live` shoots this checkout's pages from the recording and again |
| | through knotless-serve over a world: one that moved means the |
| | recording is out of date. Keep `just shots-up` running in the |
| | background while working on pages: `shots-live` then reuses its world |
| | rather than seeding one, which is most of its time. |
| | - The social cards are drawn by knotless-serve: `just shots-cards` takes |
| | them from a world into `target/shots/cards` to look at. |
| | - The components in `web/src/lib` are layered, atomic design's way: |
| | `atoms` (one element: an icon, an avatar), `molecules` (a few atoms |
| | that mean something together: a person, a commit row), `organisms` (a |
| | part of a page: a check list, a feed), `templates` (a page's layout, |
| | without its data). A component uses its own layer and those below it, |
| | never one above; `just lint` checks it. Pages under `web/src/routes` |
| | fill a template with what the queries answer. |
| | - The pages' styles are `web/src/app.css`, and every colour, size, |
| | space, radius and weight in it is a token from `web/src/tokens.css`: |
| | take one by name rather than writing a value, and add one there when |
| | none fits. A colour for what it means is its role, `--danger`, |
| | `--success`, `--attention`, `--done` or `--neutral`, never the hue |
| | under it (`--red`), so a theme can draw success in blue. Every colour that is text meets WCAG AA (4.5:1) on what |
| | it is drawn on, in every theme: `harness/contrast.mjs` checks it, in |
| | `web` and `just lint`, and a new colour that is text goes in |
| | `web/src/lib/contrast.json`, which the theme editor, and knotless's |
| | own check of a theme made anywhere (`crates/knotless/src/theme.rs`), |
| | hold people's own themes to too. A menu that opens is a `<details class="popover …">`. |
| | - In Svelte markup, keep a run of inline text one expression or one line: |
| | a block or component beside it splits the text into nodes, which shapes |
| | differently from the same text whole and moves pixels. |
| | - Working on the web pages (`web/`): `web/AGENTS.md`, loaded with |
| | them, says how they are built, shot and checked, and to load the `ui` |
| | skill before changing one. |
| | - Done: all seven of the pull's checks pass. When one fails in a way its |
| | log and pictures do not explain, run that one thing here, alone |
| | (`COV_CLEAN=1` rebuilds everything first, for a cov miss that makes no |
| | sense). |
| | |
| | ## Lexicons |
| | |
| | A new or changed schema under `lexicons/` follows the Lexicon Style Guide |
| | (https://atproto.com/guides/lexinomicon) and passes `just lex`: goat's |
| | linter, less two warnings kept on purpose (`pack`'s inline `bytes` and |
| | `listReports`' `id`), then `harness/lexicons.mjs`. That checks what the |
| | linter does not see: `knownValues` rather than `enum`; objects in new |
| | arrays rather than bare values; open unions; a description on every |
| | `main`; a `maxLength` on strings without a format in what people write |
| | (records and procedure input); accounts by DID, not handle. And that every |
| | schema only grows from main's, as the branch left main: a schema already |
| | published is evolved, not changed, with new fields optional and nothing removed, renamed, retyped, |
| | made required or narrowed. Fix anything either says, or say why not. |
| | |
| | Still by hand: no `required` a reader could do without, since it can never |
| | be dropped; a description on any field whose name does not say what it |
| | holds; `maxGraphemes` beside `maxLength` for text people read; reuse of |
| | `dev.knotless.defs` and `com.atproto.repo.strongRef` over new shapes. |
| | |
| | `cargo fmt` can put a `?` on a line of its own, which coverage then counts |
| | as a line never run: bind the value first, or use a named function for a |
| | row mapper, rather than lowering the gate. |
| | |
| | ## Lexicons |
| | |
| | A new or changed schema under `lexicons/` follows `lexicons/AGENTS.md` |
| | and passes `just lex`. |
| | |
| | ## Queries |
| | |
| | A query of the index (`crates/knotless-serve/src/index.rs`) is planned |
| | as the tests run it, against tables said to be prod's size |
| | (`crates/knotless-serve/src/plans.rs`), and `test` fails on any that |
| | scans a table that grows with the network: `forge`, `check_run`, |
| | `comment` and the rest of `GROWING`, or sorts many of its rows (a range |
| | leading its index, or what a search finds for each row of a scan, as a |
| | repository's pushes for every repository). Tests on empty tables pass a query |
| | that takes seconds on prod, so this is what holds them. Its log names |
| | the query and its plan. Give it an index, or a query that uses the one |
| | there: an expression index needs the expression as written, and a |
| | column compared to it marked `+` (`json_extract(c.value, '$.pull') = |
| | +p.uri`), as the column's affinity otherwise keeps the index unused. |
| | A scan meant to be, of a few rows an operator reads now and then, says |
| | so in its SQL with why, `-- scans: forge, as only the operator asks`, |
| | where review sees it; a sort meant to be, `-- sorts: forge, …`. On prod, |
| | a statement slower than 100 ms logs `sql`, with the request's trace. To see the plans while fixing one, run its tests |
| | with `KNOTLESS_PLANS=<dir>` and `node harness/plans.mjs <dir>`. |
| | at prod's size as the tests run it, and `test` fails on one that scans |
| | or sorts a table that grows with the network: |
| | `crates/knotless-serve/AGENTS.md` says how to fix or mark one. |
| | |
| | ## Docs |
| | |
| |