Docs: structure and hierarchy #311

Open
opened 2026-11-02 14:18:23 +00:00 by kayg · 6 comments
Owner

Owner, 2026-11-02: "we don't need to say 'Off until you turn it on' anywhere, that belongs to the UI elements that already reflect that it's off and in the documentation. we need a proper structure and hierarchy for documentation."

Job J109 has two parts.

A. Copy sweep (product code + mockups tree): remove state and default sentences ("Off until you turn it on.", "Off by default", and similar) from user-facing descriptions. Where a default matters, the relevant docs page states it. Rule: docs/design/TASTE.md, "Descriptions say what a thing does, not what state it is in."

B. Docs structure proposal (no file moves; J101 is editing docs/user): inventory, proposed hierarchy, naming/URLs, sidebar and ⌘K, "?" landing points, developer docs separation, owner questions. Posted as a comment on this issue.

Owner, 2026-11-02: "we don't need to say 'Off until you turn it on' anywhere, that belongs to the UI elements that already reflect that it's off and in the documentation. we need a proper structure and hierarchy for documentation." Job J109 has two parts. **A. Copy sweep** (product code + mockups tree): remove state and default sentences ("Off until you turn it on.", "Off by default", and similar) from user-facing descriptions. Where a default matters, the relevant docs page states it. Rule: docs/design/TASTE.md, "Descriptions say what a thing does, not what state it is in." **B. Docs structure proposal** (no file moves; J101 is editing docs/user): inventory, proposed hierarchy, naming/URLs, sidebar and ⌘K, "?" landing points, developer docs separation, owner questions. Posted as a comment on this issue.
Author
Owner

Start: branch j109-docs-copy-sweep, base origin/dev 17d282a18.

Plan (estimate ~60 min):

  1. (15 min) Grep apps/packages/mockups for state/default sentences in descriptions; Boot Machines is not in dev's product code yet, so the mockup tree and the J92 settings map are the main places. One atomic commit, docs page default noted where a default matters.
  2. (10 min) Mockups tree on dev-02-std: same copy fix, rebuild per serving notes.
  3. (25 min) Read docs/user, docs/CLI.md, J92 map, #302/J101 branches; write the structure proposal as a comment here. No file moves.
  4. (10 min) Gate scripts/verify fast on dev-02-std (via build-slot), push, report.
Start: branch `j109-docs-copy-sweep`, base origin/dev 17d282a18. Plan (estimate ~60 min): 1. (15 min) Grep apps/packages/mockups for state/default sentences in descriptions; Boot Machines is not in dev's product code yet, so the mockup tree and the J92 settings map are the main places. One atomic commit, docs page default noted where a default matters. 2. (10 min) Mockups tree on dev-02-std: same copy fix, rebuild per serving notes. 3. (25 min) Read docs/user, docs/CLI.md, J92 map, #302/J101 branches; write the structure proposal as a comment here. No file moves. 4. (10 min) Gate `scripts/verify fast` on dev-02-std (via build-slot), push, report.
Author
Owner

Docs structure proposal (no files moved)

Facts below come from origin/dev (17d282a18), J101's docs-readable-j101, J92's settings-sections-mock-j92, docs/CLI.md and DECISIONS. Nothing in docs/user/ was touched.

Recommendation in one paragraph

Use a hybrid. Sections are the product's own nouns, in the same words and the same order as Settings (Terminal, Machines, Mesh, You, Sharing, Appearance), plus Get started at the front and Reference at the back. Inside a section, a page is one of three things: the section's overview (a concept), a how-to named with a verb, or a table too long for a section page (reference). A "?" in the product always lands on the heading named after the control it sits next to. Two levels of folders at most: /docs/<section>/<page>/#heading.

Why: people arrive from a "?" next to a thing with a name, so the name has to be the address. A pure by-kind tree (guides / concepts / reference) scatters "Mesh" across three sections. A pure product mirror has no home for "what is Infraternal", the command line or a glossary. The hybrid keeps the name-to-address rule and still has a front door and a lookup shelf.


1. Inventory

Pages that exist (dev) or are in flight

Page Where State
Front page docs/user/index.md on dev; the build appends the page list
The Infraternal Multiplexer docs/user/multiplexer.md, /docs/multiplexer/ on dev; URL already shipped as the notice's "?" (D315, MULTIPLEXER_DOCS_URL)
Keys and how long they last docs/user/keys.md, /docs/keys/ on dev; J101 is adding > [!FACTS], callouts and figures
Command line interface docs/CLI.md a developer contract (action registry, exit codes, skills). It is not a user page. The user-facing sessions commands sit inside multiplexer.md

"?" anchors that already exist (J92 settings-map/catalog.ts, 7 of 22 groups have one)

Settings group Points to today Note
Terminal › Multiplexer multiplexer#what-it-does-for-you the setting is "Offer To Switch"; its explanation is under #the-question-infraternal-asks
You › Passkeys keys#passkey
You › Recovery keys#recovery-words
You › Apps keys#cli-sign-in-api-key
You › Devices keys#browser-sign-in
Machines › New Machines keys#host-join-token
Mesh › Keys keys#wireguard-session-keys

The other 15 groups have no page: Appearance (Theme, Font, Size, Layout), Terminal (Typing, Scrollback), You (Profile), Machines (Updates), Mesh (Names, Access, Connections), Sharing (Published Services, Certificates), About (Version, Licences). Settings rows with a setting of their own: 14 (Lines Kept, Offer To Switch, Keys Last, Browsers Stay Signed In For, Add Link Lasts, Join Code Lasts, Install For, Sign In As, Join The Mesh, Connection Keys, Machine Identity, Renewal Grace Period, Machine Names End In, Renew Early) plus the Appearance, Window Sizes, Typing, Devices and About panels.

Features with a decision but no page (each needs one when it ships): Boot Machines (D253), "Can be controlled from other machines" (D297), network access rules (D154, D164, D216), login access (D235), privileged access upgrade (D286), recovery and its delay (D25, D113), new-device sign-in with device keys (D151, D152), sign-out wipe (D245), updates and channels (D135, D184, D185), app windows (D208), the share card (D126), in-app feedback (D281).

Concepts the product uses (each needs one plain-words definition, in the glossary and at its section's start): machine, mesh, session, multiplexer, window / view / canvas, key, access (two kinds, see Q4), app (two meanings, see Q4), device, sharing, recovery, update, role, "infraternal agent" versus "AI agent".

Defaults the docs must state (the owner's other half of this change: the UI control shows on/off, the docs say what the default is and why):

Setting Default Source
Boot Machines off; one boot node per LAN D253
Can be controlled from other machines off D297
Mesh on; machines may reach each other until rules are added D216, D228
Extended info off, kept on this device only D126, D156
Recording and audit mode off, per host D128, D186
Every duration and range in Settings (keys, links, codes) shown by the control as its default and Reset J92 catalog

● exists · ◐ exists, being rewritten (J101) · ○ new. Order inside a section is overview first, then how-tos, then reference.

/docs/                                  Documentation (the sections as cards)
├─ start/                               Get started        overview: what Infraternal is, in one screen
│  ├─ set-up-your-server/            ○  server init, first-owner setup code, first sign-in
│  ├─ add-your-first-machine/        ○  join link or `up` code
│  └─ your-first-session/            ○  open a terminal, close the tab, come back
├─ terminal/                            Terminal           overview: sessions and windows
│  ├─ multiplexer/                   ◐  was /docs/multiplexer/
│  ├─ scrollback-and-typing/         ○
│  └─ sessions-from-the-command-line/ ○ today a section of the multiplexer page
├─ machines/                            Machines           overview: what a machine is
│  ├─ add-a-machine/                 ○  token lifetimes, install for, sign in as, join the mesh
│  ├─ updates/                       ○
│  ├─ control-from-other-machines/   ○  (D297)
│  └─ boot-machines/                 ○  only when it ships (D253)
├─ mesh/                                Mesh               overview: what the mesh is and why
│  ├─ connections/                   ○  direct, relayed, offline
│  ├─ names/                         ○
│  └─ keys/                          ○  settings: connection keys, identity, grace period
├─ access/                              Access             overview: who may reach what, who may become whom
│  ├─ network-access/                ○  the Mesh view's arrows (D154, D164, D216)
│  ├─ login-access/                  ○  (D235)
│  └─ privileged-access/             ○  (D286)
├─ you/                                 You                overview: your account and your devices
│  ├─ sign-in-and-passkeys/          ○
│  ├─ recovery/                      ○  (D25, D113)
│  ├─ devices/                       ○  (D151, D152, D245)
│  └─ tool-keys/                     ○  command-line and AI-tool keys (name: see Q4)
├─ sharing/                             Sharing            overview
│  ├─ published-services/            ○
│  └─ certificates/                  ○
├─ appearance/                          Appearance         one page: theme, font, size, layout
└─ reference/                           Reference
   ├─ keys/                          ◐  was /docs/keys/ (stays whole: it is a table by nature)
   ├─ command-line/                  ○  user commands; docs/CLI.md stays the developer contract
   ├─ keyboard-shortcuts/            ○
   ├─ glossary/                      ○
   └─ licences/                      ○

Size: 9 sections, about 30 pages when everything ships; today 3. Rules that keep it small: at most two folder levels, at most 3 heading levels (the build already fails a page that skips one), a section overview is one screen, and a page for something not built yet does not exist (see Q5).

Where a default lives. Every setting is a ### heading named exactly like its Settings title ("Connection Keys"), with a > [!FACTS] block that gives what it does, the default and the range ("Every machine swaps these keys every 7 days. Range 1 to 30 days."). That block is what J92's "?" preview shows, so the default is one click from the control and nowhere else. No separate "defaults" page (it would copy every value and go stale), and no default in the Settings description (TASTE: descriptions say what a thing does).

Alternative: by kind (Diátaxis).

/docs/start/{what-is-infraternal, set-up-your-server, add-a-machine}
/docs/guides/{use-the-multiplexer, rotate-keys, recover-your-account, publish-a-service, …}
/docs/concepts/{sessions, mesh, access, keys, …}
/docs/reference/{keys, command-line, shortcuts, glossary, settings}

Good: well-known, each page has one job. Against: a "?" next to Mesh › Keys has three candidate pages; the same noun is split across guides, concepts and reference; Settings names and doc names drift apart; and a small product gets a mostly empty "concepts" section. Best fit when there are 50+ pages; not at 30.


3. Naming, URLs, the Docs cluster, ⌘K, "?"

Names. Sections and pages are lowercase, hyphenated, singular nouns for things (mesh, multiplexer) and a verb first for tasks (add-a-machine). A page title is the same words with capitals, and a section title is exactly the Settings component title. A page never repeats its section in its slug (mesh/keys, not mesh/mesh-keys).

URLs. docs/user/<NN-section>/<NN-page>.md becomes /docs/<section>/<page>/; a section's index.md is /docs/<section>/. This extends what the build does today (NN- only orders, index.md is a front page, "there is no list of pages"), so no manifest is added. The shipped flat URLs (/docs/multiplexer/, /docs/keys/) keep working: a page lists its former slugs on one comment line and the build writes a redirect page for each. The same tree is published at infraternal.com/docs (D315). A heading anchor is its text slug and is part of the address, so renaming a heading is a link change; the build should fail when a "?" in the Settings catalog or the app points at a page or heading that does not exist (the catalog's docs: {page, heading} is already data, so the check is a loop over it).

Docs cluster (the Docs view). Mirror Settings: the same grid, one band per section and one window per page inside it, section overview first. Today it is one flat column of windows per page. The sidebar has two levels, section then page, with the open page's headings under it; the breadcrumb reads Docs › Mesh › Keys, and each pill's menu is centred on the pill (TASTE). A window title is the page title; the section is the band label, so nothing repeats the heading (TASTE: never repeat the heading in the rows below it).

⌘K. Three row kinds, all matched by title only (never body text, as now): sections (Mesh, hint "4 pages"), pages (Mesh › Keys, hint = the page summary), and headings, shown only when typing (Connection Keys, hint Mesh › Keys; today the hint is only the page title). Action ids extend canvas:docs:<slug>#<heading> to canvas:docs:<section>/<page>#<heading>. Enter flies to the page's window at the heading.

"?" landing rules.

  1. A "?" next to a control lands on the heading with that control's name, never on a page top.
  2. A "?" next to a group lands on the page for that group; next to a section, on its overview.
  3. The preview text is that heading's [!FACTS]; a heading without one falls back to the page summary.
"?" Lands on
Multiplexer notice (D315) terminal/multiplexer/ (page top: it is a question, not a setting)
Terminal › Multiplexer › Offer To Switch terminal/multiplexer/#the-question-infraternal-asks (not #what-it-does-for-you)
Terminal › Scrollback › Lines Kept terminal/scrollback-and-typing/#lines-kept
You › Passkeys / Recovery you/sign-in-and-passkeys/#passkey / you/recovery/
You › Apps (name: Q4) › Keys Last reference/keys/#cli-sign-in-api-key, with you/tool-keys/ as the how-to
You › Devices › Browsers Stay Signed In For you/devices/#browsers-stay-signed-in-for
Machines › New Machines › Add Link Lasts machines/add-a-machine/#add-link-lasts
Mesh › Keys › Connection Keys mesh/keys/#connection-keys
Mesh › Access access/network-access/
Sharing › Certificates › Renew Early sharing/certificates/#renew-early

Developer docs stay separate. docs/user/ is the only folder the build publishes (already true: every *.md in it is a page, and nothing outside it is read). Everything else under docs/ is for people who build Infraternal and is never published: ARCHITECTURE, PROCESS, RUST, CLI.md, operations/, perf/, plans/, reviews/, verification/, design/, plus DECISIONS and research/. User pages never cite a decision in their body (only in the footer after the last rule, as now), and developer pages never explain a feature to a reader. The one overlap, the command line, is two documents on purpose: reference/command-line/ tells a person what to type; docs/CLI.md tells an engineer what the registry guarantees. Later, the user page's command list can be generated from infraternal skill so it cannot drift; that is a separate job and not needed now.


4. What this costs (after your answers, not before)

Step Size
Build: nested folders, section overviews, former-slug redirects, "? target exists" check about half a day
Docs view: a band per section; sidebar, breadcrumb and ⌘K hints about half a day
Move multiplexer and keys under their sections (J101 must have merged) an hour, plus the redirects
New pages one page per feature as it ships, not in one batch

5. Questions for the owner

  1. Section model. Hybrid (Settings-named sections, plus Get started and Reference), or by kind (start / guides / concepts / reference)? Recommended: hybrid.
  2. URLs. Nested /docs/<section>/<page>/ with redirects from the two shipped flat URLs, or keep flat slugs and put the section in page metadata? Recommended: nested with redirects; the folder tree is then the table of contents and nothing else has to be kept in step.
  3. Defaults. One ### heading per setting with a quick-facts block that states what it does, the default and the range, and no default anywhere else? Recommended: yes.
  4. Two names that mean two things. "Apps": app windows (D208) versus the command-line and AI-tool keys in Settings › You › Apps; and "Access": network access (Mesh arrows) versus login access (D235). Rename Settings › You › Apps to "Tool Keys", and give Access its own docs section (Settings keeps it under Mesh)? Recommended: yes to both; the docs headings say "Network access" and "Login access" regardless.
  5. Pages for features that are not built. None: a "Planned" callout inside the nearest page (as J101's keys page does), and the page appears when the feature ships (as D299 hides unbuilt commands). Boot Machines, control from other machines and the access pages follow this. Recommended: yes.
## Docs structure proposal (no files moved) Facts below come from `origin/dev` (17d282a18), J101's `docs-readable-j101`, J92's `settings-sections-mock-j92`, `docs/CLI.md` and DECISIONS. Nothing in `docs/user/` was touched. ### Recommendation in one paragraph Use a **hybrid**. Sections are the product's own nouns, in the same words and the same order as Settings (Terminal, Machines, Mesh, You, Sharing, Appearance), plus **Get started** at the front and **Reference** at the back. Inside a section, a page is one of three things: the section's overview (a concept), a how-to named with a verb, or a table too long for a section page (reference). A "?" in the product always lands on the heading named after the control it sits next to. Two levels of folders at most: `/docs/<section>/<page>/#heading`. Why: people arrive from a "?" next to a thing with a name, so the name has to be the address. A pure by-kind tree (guides / concepts / reference) scatters "Mesh" across three sections. A pure product mirror has no home for "what is Infraternal", the command line or a glossary. The hybrid keeps the name-to-address rule and still has a front door and a lookup shelf. --- ### 1. Inventory **Pages that exist (dev) or are in flight** | Page | Where | State | |---|---|---| | Front page | `docs/user/index.md` | on dev; the build appends the page list | | The Infraternal Multiplexer | `docs/user/multiplexer.md`, `/docs/multiplexer/` | on dev; URL already shipped as the notice's "?" (D315, `MULTIPLEXER_DOCS_URL`) | | Keys and how long they last | `docs/user/keys.md`, `/docs/keys/` | on dev; J101 is adding `> [!FACTS]`, callouts and figures | | Command line interface | `docs/CLI.md` | a **developer contract** (action registry, exit codes, skills). It is not a user page. The user-facing sessions commands sit inside `multiplexer.md` | **"?" anchors that already exist** (J92 `settings-map/catalog.ts`, 7 of 22 groups have one) | Settings group | Points to today | Note | |---|---|---| | Terminal › Multiplexer | `multiplexer#what-it-does-for-you` | the setting is "Offer To Switch"; its explanation is under `#the-question-infraternal-asks` | | You › Passkeys | `keys#passkey` | | | You › Recovery | `keys#recovery-words` | | | You › Apps | `keys#cli-sign-in-api-key` | | | You › Devices | `keys#browser-sign-in` | | | Machines › New Machines | `keys#host-join-token` | | | Mesh › Keys | `keys#wireguard-session-keys` | | The other 15 groups have no page: Appearance (Theme, Font, Size, Layout), Terminal (Typing, Scrollback), You (Profile), Machines (Updates), Mesh (Names, Access, Connections), Sharing (Published Services, Certificates), About (Version, Licences). Settings rows with a setting of their own: 14 (Lines Kept, Offer To Switch, Keys Last, Browsers Stay Signed In For, Add Link Lasts, Join Code Lasts, Install For, Sign In As, Join The Mesh, Connection Keys, Machine Identity, Renewal Grace Period, Machine Names End In, Renew Early) plus the Appearance, Window Sizes, Typing, Devices and About panels. **Features with a decision but no page** (each needs one when it ships): Boot Machines (D253), "Can be controlled from other machines" (D297), network access rules (D154, D164, D216), login access (D235), privileged access upgrade (D286), recovery and its delay (D25, D113), new-device sign-in with device keys (D151, D152), sign-out wipe (D245), updates and channels (D135, D184, D185), app windows (D208), the share card (D126), in-app feedback (D281). **Concepts the product uses** (each needs one plain-words definition, in the glossary and at its section's start): machine, mesh, session, multiplexer, window / view / canvas, key, access (two kinds, see Q4), app (two meanings, see Q4), device, sharing, recovery, update, role, "infraternal agent" versus "AI agent". **Defaults the docs must state** (the owner's other half of this change: the UI control shows on/off, the docs say what the default is and why): | Setting | Default | Source | |---|---|---| | Boot Machines | off; one boot node per LAN | D253 | | Can be controlled from other machines | off | D297 | | Mesh | on; machines may reach each other until rules are added | D216, D228 | | Extended info | off, kept on this device only | D126, D156 | | Recording and audit mode | off, per host | D128, D186 | | Every duration and range in Settings (keys, links, codes) | shown by the control as its default and Reset | J92 catalog | --- ### 2. Proposed hierarchy (recommended: hybrid) ● exists · ◐ exists, being rewritten (J101) · ○ new. Order inside a section is overview first, then how-tos, then reference. ``` /docs/ Documentation (the sections as cards) ├─ start/ Get started overview: what Infraternal is, in one screen │ ├─ set-up-your-server/ ○ server init, first-owner setup code, first sign-in │ ├─ add-your-first-machine/ ○ join link or `up` code │ └─ your-first-session/ ○ open a terminal, close the tab, come back ├─ terminal/ Terminal overview: sessions and windows │ ├─ multiplexer/ ◐ was /docs/multiplexer/ │ ├─ scrollback-and-typing/ ○ │ └─ sessions-from-the-command-line/ ○ today a section of the multiplexer page ├─ machines/ Machines overview: what a machine is │ ├─ add-a-machine/ ○ token lifetimes, install for, sign in as, join the mesh │ ├─ updates/ ○ │ ├─ control-from-other-machines/ ○ (D297) │ └─ boot-machines/ ○ only when it ships (D253) ├─ mesh/ Mesh overview: what the mesh is and why │ ├─ connections/ ○ direct, relayed, offline │ ├─ names/ ○ │ └─ keys/ ○ settings: connection keys, identity, grace period ├─ access/ Access overview: who may reach what, who may become whom │ ├─ network-access/ ○ the Mesh view's arrows (D154, D164, D216) │ ├─ login-access/ ○ (D235) │ └─ privileged-access/ ○ (D286) ├─ you/ You overview: your account and your devices │ ├─ sign-in-and-passkeys/ ○ │ ├─ recovery/ ○ (D25, D113) │ ├─ devices/ ○ (D151, D152, D245) │ └─ tool-keys/ ○ command-line and AI-tool keys (name: see Q4) ├─ sharing/ Sharing overview │ ├─ published-services/ ○ │ └─ certificates/ ○ ├─ appearance/ Appearance one page: theme, font, size, layout └─ reference/ Reference ├─ keys/ ◐ was /docs/keys/ (stays whole: it is a table by nature) ├─ command-line/ ○ user commands; docs/CLI.md stays the developer contract ├─ keyboard-shortcuts/ ○ ├─ glossary/ ○ └─ licences/ ○ ``` Size: 9 sections, about 30 pages when everything ships; today 3. Rules that keep it small: at most two folder levels, at most 3 heading levels (the build already fails a page that skips one), a section overview is one screen, and a page for something not built yet does not exist (see Q5). **Where a default lives.** Every setting is a `###` heading named exactly like its Settings title ("Connection Keys"), with a `> [!FACTS]` block that gives what it does, the default and the range ("Every machine swaps these keys every 7 days. Range 1 to 30 days."). That block is what J92's "?" preview shows, so the default is one click from the control and nowhere else. No separate "defaults" page (it would copy every value and go stale), and no default in the Settings description (TASTE: descriptions say what a thing does). **Alternative: by kind (Diátaxis).** ``` /docs/start/{what-is-infraternal, set-up-your-server, add-a-machine} /docs/guides/{use-the-multiplexer, rotate-keys, recover-your-account, publish-a-service, …} /docs/concepts/{sessions, mesh, access, keys, …} /docs/reference/{keys, command-line, shortcuts, glossary, settings} ``` Good: well-known, each page has one job. Against: a "?" next to Mesh › Keys has three candidate pages; the same noun is split across guides, concepts and reference; Settings names and doc names drift apart; and a small product gets a mostly empty "concepts" section. Best fit when there are 50+ pages; not at 30. --- ### 3. Naming, URLs, the Docs cluster, ⌘K, "?" **Names.** Sections and pages are lowercase, hyphenated, singular nouns for things (`mesh`, `multiplexer`) and a verb first for tasks (`add-a-machine`). A page title is the same words with capitals, and a section title is exactly the Settings component title. A page never repeats its section in its slug (`mesh/keys`, not `mesh/mesh-keys`). **URLs.** `docs/user/<NN-section>/<NN-page>.md` becomes `/docs/<section>/<page>/`; a section's `index.md` is `/docs/<section>/`. This extends what the build does today (`NN-` only orders, `index.md` is a front page, "there is no list of pages"), so no manifest is added. The shipped flat URLs (`/docs/multiplexer/`, `/docs/keys/`) keep working: a page lists its former slugs on one comment line and the build writes a redirect page for each. The same tree is published at infraternal.com/docs (D315). A heading anchor is its text slug and is part of the address, so renaming a heading is a link change; the build should fail when a "?" in the Settings catalog or the app points at a page or heading that does not exist (the catalog's `docs: {page, heading}` is already data, so the check is a loop over it). **Docs cluster (the Docs view).** Mirror Settings: the same grid, one **band per section** and one **window per page** inside it, section overview first. Today it is one flat column of windows per page. The sidebar has two levels, section then page, with the open page's headings under it; the breadcrumb reads `Docs › Mesh › Keys`, and each pill's menu is centred on the pill (TASTE). A window title is the page title; the section is the band label, so nothing repeats the heading (TASTE: never repeat the heading in the rows below it). **⌘K.** Three row kinds, all matched by title only (never body text, as now): sections (`Mesh`, hint "4 pages"), pages (`Mesh › Keys`, hint = the page summary), and headings, shown only when typing (`Connection Keys`, hint `Mesh › Keys`; today the hint is only the page title). Action ids extend `canvas:docs:<slug>#<heading>` to `canvas:docs:<section>/<page>#<heading>`. Enter flies to the page's window at the heading. **"?" landing rules.** 1. A "?" next to a control lands on the heading with that control's name, never on a page top. 2. A "?" next to a group lands on the page for that group; next to a section, on its overview. 3. The preview text is that heading's `[!FACTS]`; a heading without one falls back to the page summary. | "?" | Lands on | |---|---| | Multiplexer notice (D315) | `terminal/multiplexer/` (page top: it is a question, not a setting) | | Terminal › Multiplexer › Offer To Switch | `terminal/multiplexer/#the-question-infraternal-asks` (not `#what-it-does-for-you`) | | Terminal › Scrollback › Lines Kept | `terminal/scrollback-and-typing/#lines-kept` | | You › Passkeys / Recovery | `you/sign-in-and-passkeys/#passkey` / `you/recovery/` | | You › Apps (name: Q4) › Keys Last | `reference/keys/#cli-sign-in-api-key`, with `you/tool-keys/` as the how-to | | You › Devices › Browsers Stay Signed In For | `you/devices/#browsers-stay-signed-in-for` | | Machines › New Machines › Add Link Lasts | `machines/add-a-machine/#add-link-lasts` | | Mesh › Keys › Connection Keys | `mesh/keys/#connection-keys` | | Mesh › Access | `access/network-access/` | | Sharing › Certificates › Renew Early | `sharing/certificates/#renew-early` | **Developer docs stay separate.** `docs/user/` is the only folder the build publishes (already true: every `*.md` in it is a page, and nothing outside it is read). Everything else under `docs/` is for people who build Infraternal and is never published: ARCHITECTURE, PROCESS, RUST, CLI.md, `operations/`, `perf/`, `plans/`, `reviews/`, `verification/`, `design/`, plus DECISIONS and `research/`. User pages never cite a decision in their body (only in the footer after the last rule, as now), and developer pages never explain a feature to a reader. The one overlap, the command line, is two documents on purpose: `reference/command-line/` tells a person what to type; `docs/CLI.md` tells an engineer what the registry guarantees. Later, the user page's command list can be generated from `infraternal skill` so it cannot drift; that is a separate job and not needed now. --- ### 4. What this costs (after your answers, not before) | Step | Size | |---|---| | Build: nested folders, section overviews, former-slug redirects, "? target exists" check | about half a day | | Docs view: a band per section; sidebar, breadcrumb and ⌘K hints | about half a day | | Move `multiplexer` and `keys` under their sections (J101 must have merged) | an hour, plus the redirects | | New pages | one page per feature as it ships, not in one batch | ### 5. Questions for the owner 1. **Section model.** Hybrid (Settings-named sections, plus Get started and Reference), or by kind (start / guides / concepts / reference)? *Recommended: hybrid.* 2. **URLs.** Nested `/docs/<section>/<page>/` with redirects from the two shipped flat URLs, or keep flat slugs and put the section in page metadata? *Recommended: nested with redirects; the folder tree is then the table of contents and nothing else has to be kept in step.* 3. **Defaults.** One `###` heading per setting with a quick-facts block that states what it does, the default and the range, and no default anywhere else? *Recommended: yes.* 4. **Two names that mean two things.** "Apps": app windows (D208) versus the command-line and AI-tool keys in Settings › You › Apps; and "Access": network access (Mesh arrows) versus login access (D235). Rename Settings › You › Apps to "Tool Keys", and give Access its own docs section (Settings keeps it under Mesh)? *Recommended: yes to both; the docs headings say "Network access" and "Login access" regardless.* 5. **Pages for features that are not built.** None: a "Planned" callout inside the nearest page (as J101's keys page does), and the page appears when the feature ships (as D299 hides unbuilt commands). Boot Machines, control from other machines and the access pages follow this. *Recommended: yes.*
Author
Owner

Part A done; Part B above

Head: f85b62785 on branch j109-boot-copy-mockups (pushed to origin; based on mockups-2026-11-01-j52 40f321ae6).

Sweep result. Product code on origin/dev 17d282a18 has no state or default sentence in a user-facing description (grepped apps/ and packages/ for "off until", "until you turn", "by default", "is off/on", "stays off", "currently", and so on; the only hits are code comments and data values). The Boot Machines copy exists only in the mockups tree, so the one atomic commit is there:

  • Settings → Boot Machines intro: dropped "Off until you turn it on."
  • Boot-server switch hint: "On. {node} answers boot requests…" / "Off. Machines on {lan} cannot start…" is now one sentence for both states: "{node} answers boot requests on {lan} next to your router's DHCP, so machines there can start from the network."
  • Left as is on purpose: the idle status line "Off. Turn on the boot server on …" (a status with the next step, not a description); the blocking message "Boot Machines is off on {lan}…"; the mockups.html reviewer note "Off is how the product ships it" (an index note, not product copy).
  • J92's Settings catalog (settings-sections-mock-j92) has no such sentence either.
  • Defaults for the docs: the table in "Defaults the docs must state" above lists every one (Boot Machines off, control from other machines off, mesh on, and so on). The Boot Machines page does not exist and, under Q5, is written when the feature ships; I did not add it to docs/user (J101 is editing there).

Mockups preview. Copy synced to ~/worktrees/mockups on infraternal-dev-02-std and rebuilt (INFRATERNAL_CLUSTERS_PREVIEW=1 bun run build.ts, BUILD_EXIT=0). The bundle has the new text, 0 chunks have the old text, and http://10.69.69.117:47650/mockups.html answers 200. mockups.html itself was not edited.

Gate (scripts/verify fast, dev-02-std aarch64, via build-slot): exit 1, one Rust failure, in a test that does not touch this change (the diff is 1 file, 3 insertions, 2 deletions in apps/tracer/src/canvas/mock/boot-r1/settings.ts):

test bare_infraternal_is_the_overview_and_points_to_help ... FAILED
assertion `left == right` failed   (crates/infraternal/tests/cli_envelope.rs:211)
  left: Some(5)
 right: Some(0)
test result: FAILED. 7 passed; 1 failed
+---------------------------+--------------+
| Rust gate                 | Result       |
+---------------------------+--------------+
| fmt                       | PASS         |
| VT native fmt             | PASS         |
| CLI plugin compile-out    | PASS         |
| clippy                    | PASS         |
| SSH runtime test helper   | PASS         |
| real-binary fixture paths | PASS         |
| test                      | FAIL (101)   |
| SSH inode reuse fixture   | PASS         |
| shim process-per-user     | PASS         |
| cargo-deny                | PASS         |
| gate architecture         | PASS         |
| static builds             | SKIP (x86)   |
+---------------------------+--------------+
VERIFY_EXIT=1

Static builds are skipped on the arm VM. Cargo stops at the first failing test binary, so later test binaries did not run; this is the inherited dev failure set, and I did not re-run it on a clean dev checkout.

Cleanup: gate target dir and VM worktree ~/worktrees/j109 removed; the local infraternal-j109 worktree (no commits) removed.

## Part A done; Part B above **Head:** `f85b62785` on branch `j109-boot-copy-mockups` (pushed to origin; based on `mockups-2026-11-01-j52` 40f321ae6). **Sweep result.** Product code on origin/dev 17d282a18 has **no** state or default sentence in a user-facing description (grepped apps/ and packages/ for "off until", "until you turn", "by default", "is off/on", "stays off", "currently", and so on; the only hits are code comments and data values). The Boot Machines copy exists only in the mockups tree, so the one atomic commit is there: - Settings → Boot Machines intro: dropped "Off until you turn it on." - Boot-server switch hint: "On. {node} answers boot requests…" / "Off. Machines on {lan} cannot start…" is now one sentence for both states: "{node} answers boot requests on {lan} next to your router's DHCP, so machines there can start from the network." - Left as is on purpose: the idle status line "Off. Turn on the boot server on …" (a status with the next step, not a description); the blocking message "Boot Machines is off on {lan}…"; the mockups.html reviewer note "Off is how the product ships it" (an index note, not product copy). - J92's Settings catalog (`settings-sections-mock-j92`) has no such sentence either. - Defaults for the docs: the table in "Defaults the docs must state" above lists every one (Boot Machines off, control from other machines off, mesh on, and so on). The Boot Machines page does not exist and, under Q5, is written when the feature ships; I did not add it to `docs/user` (J101 is editing there). **Mockups preview.** Copy synced to `~/worktrees/mockups` on infraternal-dev-02-std and rebuilt (`INFRATERNAL_CLUSTERS_PREVIEW=1 bun run build.ts`, BUILD_EXIT=0). The bundle has the new text, 0 chunks have the old text, and http://10.69.69.117:47650/mockups.html answers 200. `mockups.html` itself was not edited. **Gate (`scripts/verify fast`, dev-02-std aarch64, via build-slot):** exit 1, one Rust failure, in a test that does not touch this change (the diff is 1 file, 3 insertions, 2 deletions in `apps/tracer/src/canvas/mock/boot-r1/settings.ts`): ``` test bare_infraternal_is_the_overview_and_points_to_help ... FAILED assertion `left == right` failed (crates/infraternal/tests/cli_envelope.rs:211) left: Some(5) right: Some(0) test result: FAILED. 7 passed; 1 failed ``` ``` +---------------------------+--------------+ | Rust gate | Result | +---------------------------+--------------+ | fmt | PASS | | VT native fmt | PASS | | CLI plugin compile-out | PASS | | clippy | PASS | | SSH runtime test helper | PASS | | real-binary fixture paths | PASS | | test | FAIL (101) | | SSH inode reuse fixture | PASS | | shim process-per-user | PASS | | cargo-deny | PASS | | gate architecture | PASS | | static builds | SKIP (x86) | +---------------------------+--------------+ VERIFY_EXIT=1 ``` Static builds are skipped on the arm VM. Cargo stops at the first failing test binary, so later test binaries did not run; this is the inherited dev failure set, and I did not re-run it on a clean dev checkout. Cleanup: gate target dir and VM worktree `~/worktrees/j109` removed; the local `infraternal-j109` worktree (no commits) removed.
Author
Owner

J114 start (docs structure, D317). Branch docs/j114-sections, base origin/dev 1f005f2bc. Worktree ~/Developer/Worktrees/infraternal-j114.

Findings that shape the plan:

  • J92's Settings catalog (settings-map/catalog.ts, with the docs: { page, heading } anchors) is not on origin/dev. On dev the only "?" is the multiplexer notice (MULTIPLEXER_DOCS_URL). So the build check scans the app source for both shapes ("/docs/<path>/#heading" literals and docs: { page, heading } entries). It covers the catalog as soon as J92 merges, and J92's page names (keys, multiplexer) will fail it until they become reference/keys and terminal/multiplexer. I will not push to J92's branch; the one-line anchor fix (#the-question-infraternal-asks) is in my report for the J92 owner.
  • The settings catalog is mostly placeholders, so "one heading per setting" covers only settings the two pages document today: Offer To Switch, Keys Last, Browsers Stay Signed In For, Add Link Lasts, Join Code Lasts, Connection Keys, Machine Identity, Renewal Grace Period. A range appears only where the code or an owner decision states it; I will not invent one.

Plan (estimate ~3 h):

  1. (45 min) Build: nested read of docs/user/<NN-section>/<NN-page>.md, section index.md required, two levels max, former-slugs line to redirect pages (meta refresh plus a hash-keeping line), sections on the front page, index.json slugs section/page.
  2. (30 min) Build check: every "?" target in app source, the catalog shape and docs-to-docs links must exist; names a moved page. Unit tests.
  3. (30 min) Content: move multiplexer to terminal/, keys to reference/, nine one-screen overviews, a heading and [!FACTS] per documented setting, "Planned" callouts.
  4. (30 min) App: ⌘K section/page/heading rows and canvas:docs:<section>/<page>#<heading> ids, nested slugs in the Docs view (one window per page, layout untouched), fragment URLs, in-canvas links, MULTIPLEXER_DOCS_URL.
  5. (45 min) Tests, deferred-JS budget measurement, scripts/verify fast on the emptier VM, push, report here.
**J114 start (docs structure, D317).** Branch `docs/j114-sections`, base origin/dev `1f005f2bc`. Worktree `~/Developer/Worktrees/infraternal-j114`. Findings that shape the plan: - J92's Settings catalog (`settings-map/catalog.ts`, with the `docs: { page, heading }` anchors) is **not on origin/dev**. On dev the only "?" is the multiplexer notice (`MULTIPLEXER_DOCS_URL`). So the build check scans the app source for both shapes (`"/docs/<path>/#heading"` literals and `docs: { page, heading }` entries). It covers the catalog as soon as J92 merges, and J92's page names (`keys`, `multiplexer`) will fail it until they become `reference/keys` and `terminal/multiplexer`. I will not push to J92's branch; the one-line anchor fix (`#the-question-infraternal-asks`) is in my report for the J92 owner. - The settings catalog is mostly placeholders, so "one heading per setting" covers only settings the two pages document today: Offer To Switch, Keys Last, Browsers Stay Signed In For, Add Link Lasts, Join Code Lasts, Connection Keys, Machine Identity, Renewal Grace Period. A range appears only where the code or an owner decision states it; I will not invent one. Plan (estimate ~3 h): 1. (45 min) Build: nested read of `docs/user/<NN-section>/<NN-page>.md`, section `index.md` required, two levels max, former-slugs line to redirect pages (meta refresh plus a hash-keeping line), sections on the front page, `index.json` slugs `section/page`. 2. (30 min) Build check: every "?" target in app source, the catalog shape and docs-to-docs links must exist; names a moved page. Unit tests. 3. (30 min) Content: move `multiplexer` to `terminal/`, `keys` to `reference/`, nine one-screen overviews, a heading and `[!FACTS]` per documented setting, "Planned" callouts. 4. (30 min) App: ⌘K section/page/heading rows and `canvas:docs:<section>/<page>#<heading>` ids, nested slugs in the Docs view (one window per page, layout untouched), fragment URLs, in-canvas links, `MULTIPLEXER_DOCS_URL`. 5. (45 min) Tests, deferred-JS budget measurement, `scripts/verify fast` on the emptier VM, push, report here.
Author
Owner

J114 progress (about 1 h 45 min in). WIP pushed: docs/j114-sections at f18ce52f2.

Done and unit-tested on compute01 (bun run check exit 0; 55 docs/palette/startup tests pass):

  • Build reads docs/user/<NN-section>/<NN-page>.md; a section folder needs an index.md overview and may not nest deeper; slugs are section/page.
  • <!-- Former slugs: … --> becomes a redirect page at each former address (meta refresh plus a line that keeps the #heading).
  • New docs-anchors.ts: the build fails if a quoted /docs/… address in the app source, a catalog docs: { page, heading } entry or a link between pages names a page or heading that does not exist. It says when the address is a moved page's old one.
  • ⌘K rows: Section, Section › Page and heading rows, title match only, ids canvas:docs:<section>/<page>#<heading>. Docs view: same one-window-per-page layout, window ids d-<section>_<page>.
  • Nine one-screen section overviews; multiplexer is terminal/multiplexer, keys is reference/keys. The multiplexer notice's "?" is /docs/terminal/multiplexer/.

Still to do: JS budget measurement (running), scripts/verify fast, commit split, final report.

**J114 progress (about 1 h 45 min in).** WIP pushed: `docs/j114-sections` at `f18ce52f2`. Done and unit-tested on compute01 (`bun run check` exit 0; 55 docs/palette/startup tests pass): - Build reads `docs/user/<NN-section>/<NN-page>.md`; a section folder needs an `index.md` overview and may not nest deeper; slugs are `section/page`. - `<!-- Former slugs: … -->` becomes a redirect page at each former address (meta refresh plus a line that keeps the `#heading`). - New `docs-anchors.ts`: the build fails if a quoted `/docs/…` address in the app source, a catalog `docs: { page, heading }` entry or a link between pages names a page or heading that does not exist. It says when the address is a moved page's old one. - ⌘K rows: `Section`, `Section › Page` and heading rows, title match only, ids `canvas:docs:<section>/<page>#<heading>`. Docs view: same one-window-per-page layout, window ids `d-<section>_<page>`. - Nine one-screen section overviews; `multiplexer` is `terminal/multiplexer`, `keys` is `reference/keys`. The multiplexer notice's "?" is `/docs/terminal/multiplexer/`. Still to do: JS budget measurement (running), `scripts/verify fast`, commit split, final report.
Author
Owner

J114 done: D317 implemented

Branch docs/j114-sections, head 0ef98fea8, base origin/dev 1f005f2bc. Two commits:

  1. 7dd462e9e sections, nested addresses, redirects, the "?" target check, ⌘K rows
  2. 0ef98fea8 one heading per setting, defaults only in its [!FACTS]

What changed

  • docs/user/<NN-section>/<NN-page>.md is /docs/<section>/<page>/#<heading>. Nine sections in D317 order (start, terminal, machines, mesh, access, you, sharing, appearance, reference), each with a one-screen index.md. multiplexer is terminal/multiplexer, keys is reference/keys. "Apps" stays the name. No pages for unbuilt features; each overview has a "Planned" callout.
  • <!-- Former slugs: multiplexer --> produces a redirect page at /docs/multiplexer/ and /docs/keys/ (meta refresh plus a line that keeps #heading). A former slug may not be live or claimed twice.
  • docs-anchors.ts: the build fails when a quoted /docs/... string in apps/tracer/src or packages/ui/src, a catalog docs: { page, heading } entry, or a link between pages names a page or heading that doesn't exist. It also names the new address when the old one is used. Proof: with the old URL string put back, the build stops ("is the old address of terminal/multiplexer").
  • ⌘K: Section, Section › Page, heading rows (title match only); ids canvas:docs:<section>/<page>#<heading>. Docs view layout untouched (one window per page, ids d-<section>/<page>).
  • Eight settings have a heading named like their Settings title: Offer To Switch, Keys Last (30 days, 1 to 365), Browsers Stay Signed In For, Add Link Lasts, Join Code Lasts, Connection Keys, Machine Identity, Renewal Grace Period. Values elsewhere on the pages now link to the heading. I wrote a range only where one is decided; the catalog's other ranges are placeholders.

Needs the J92 owner (not on dev, so not done here)

J92's catalog (settings-map/catalog.ts) isn't on dev and I don't push to other branches. When it rebases, the new check will fail until its anchors read:

  • Offer To Switch: { page: "terminal/multiplexer", heading: "offer-to-switch" } (or the-question-infraternal-asks, as the brief says; both exist)
  • Passkeys reference/keys / passkey; Recovery reference/keys / recovery-words
  • Apps / Keys Last reference/keys / keys-last; Devices reference/keys / browsers-stay-signed-in-for
  • New Machines / Add Link Lasts reference/keys / add-link-lasts
  • Mesh Keys / Connection Keys reference/keys / connection-keys (it pointed at the 2-minute session keys; Connection Keys is the 7-day static key)

Gate

scripts/verify fast on compute01 (x86_64), run 2: VERIFY_EXIT=0 at tree 4da8d43bb, which differs from the head only by test-file edits and the commit split.
Run 1 failed only the Rust row: agent_sessions::latency_fixture_accepts_the_unsolicited_startup_inventory timed out (TimeoutError in scripts/agent_fixture.py, a 1 s read) while the VM was loaded. I touched no Rust. It passed on re-run, so I treat it as a load flake, not a docs problem.

| Rust gate                 | Result       |
| fmt                       | PASS         |
| VT native fmt             | PASS         |
| CLI plugin compile-out    | PASS         |
| clippy                    | PASS         |
| SSH runtime test helper   | PASS         |
| real-binary fixture paths | PASS         |
| test                      | PASS         |
| SSH inode reuse fixture   | PASS         |
| shim process-per-user     | PASS         |
| cargo-deny                | PASS         |
| gate architecture         | PASS         |
| static builds             | PASS         |
x86_64 musl: size 22419344 bytes; baseline 22418256; delta +1088 bytes (report only)
aarch64 musl (run 1): size 20454176; baseline 20453280; delta +896 bytes
Ran 497 tests across 80 files.   (bun, src/canvas etc.; docs-build and docs-anchors tests included)
VERIFY_EXIT=0

Not in verify fast, run on dev-02-std (aarch64): docs-palette, startup-demo (14 tests pass); docs, docs-reading, docs-figures (13 pass, 6 skipped: figures are not captured, as before). Two of them needed spec updates (the front page lists sections; more quick-facts blocks), included in the commits.

Deferred JS budget

before (origin/dev) after
deferred gzip 61274 / 61440 (166 left) 61286 / 61440 (154 left)
deferred brotli 54101 / 55296 54006 / 55296
critical gzip 311299 / 327680 311301 / 327680

The only deferred change is the notice's URL string (/docs/terminal/multiplexer/, +9 B raw, +12 B gzip). All other app code is in on-demand chunks. My first version added a shared helper chunk, which cost 33 B gzip in critical and 26 B in deferred; I removed it by keeping window ids as the plain d-<slug>.

For the owner

  • Docs detached from the app (D317 open item): the build output is the same tree; nothing here depends on the app besides the Docs view reading index.json.
  • No screenshots: the only visual change is the front page listing sections instead of pages; the specs measure its alignment as before.
## J114 done: D317 implemented **Branch** `docs/j114-sections`, **head `0ef98fea8`**, base origin/dev `1f005f2bc`. Two commits: 1. `7dd462e9e` sections, nested addresses, redirects, the "?" target check, ⌘K rows 2. `0ef98fea8` one heading per setting, defaults only in its `[!FACTS]` ### What changed - `docs/user/<NN-section>/<NN-page>.md` is `/docs/<section>/<page>/#<heading>`. Nine sections in D317 order (start, terminal, machines, mesh, access, you, sharing, appearance, reference), each with a one-screen `index.md`. `multiplexer` is `terminal/multiplexer`, `keys` is `reference/keys`. "Apps" stays the name. No pages for unbuilt features; each overview has a "Planned" callout. - `<!-- Former slugs: multiplexer -->` produces a redirect page at `/docs/multiplexer/` and `/docs/keys/` (meta refresh plus a line that keeps `#heading`). A former slug may not be live or claimed twice. - `docs-anchors.ts`: the build fails when a quoted `/docs/...` string in `apps/tracer/src` or `packages/ui/src`, a catalog `docs: { page, heading }` entry, or a link between pages names a page or heading that doesn't exist. It also names the new address when the old one is used. Proof: with the old URL string put back, the build stops ("is the old address of terminal/multiplexer"). - ⌘K: `Section`, `Section › Page`, heading rows (title match only); ids `canvas:docs:<section>/<page>#<heading>`. Docs view layout untouched (one window per page, ids `d-<section>/<page>`). - Eight settings have a heading named like their Settings title: Offer To Switch, Keys Last (30 days, 1 to 365), Browsers Stay Signed In For, Add Link Lasts, Join Code Lasts, Connection Keys, Machine Identity, Renewal Grace Period. Values elsewhere on the pages now link to the heading. I wrote a range only where one is decided; the catalog's other ranges are placeholders. ### Needs the J92 owner (not on dev, so not done here) J92's catalog (`settings-map/catalog.ts`) isn't on dev and I don't push to other branches. When it rebases, the new check will fail until its anchors read: - Offer To Switch: `{ page: "terminal/multiplexer", heading: "offer-to-switch" }` (or `the-question-infraternal-asks`, as the brief says; both exist) - Passkeys `reference/keys` / `passkey`; Recovery `reference/keys` / `recovery-words` - Apps / Keys Last `reference/keys` / `keys-last`; Devices `reference/keys` / `browsers-stay-signed-in-for` - New Machines / Add Link Lasts `reference/keys` / `add-link-lasts` - Mesh Keys / Connection Keys `reference/keys` / `connection-keys` (it pointed at the 2-minute session keys; Connection Keys is the 7-day static key) ### Gate `scripts/verify fast` on compute01 (x86_64), run 2: **`VERIFY_EXIT=0`** at tree `4da8d43bb`, which differs from the head only by test-file edits and the commit split. Run 1 failed only the Rust row: `agent_sessions::latency_fixture_accepts_the_unsolicited_startup_inventory` timed out (`TimeoutError` in `scripts/agent_fixture.py`, a 1 s read) while the VM was loaded. I touched no Rust. It passed on re-run, so I treat it as a load flake, not a docs problem. ``` | Rust gate | Result | | fmt | PASS | | VT native fmt | PASS | | CLI plugin compile-out | PASS | | clippy | PASS | | SSH runtime test helper | PASS | | real-binary fixture paths | PASS | | test | PASS | | SSH inode reuse fixture | PASS | | shim process-per-user | PASS | | cargo-deny | PASS | | gate architecture | PASS | | static builds | PASS | x86_64 musl: size 22419344 bytes; baseline 22418256; delta +1088 bytes (report only) aarch64 musl (run 1): size 20454176; baseline 20453280; delta +896 bytes Ran 497 tests across 80 files. (bun, src/canvas etc.; docs-build and docs-anchors tests included) VERIFY_EXIT=0 ``` Not in `verify fast`, run on dev-02-std (aarch64): `docs-palette`, `startup-demo` (14 tests pass); `docs`, `docs-reading`, `docs-figures` (13 pass, 6 skipped: figures are not captured, as before). Two of them needed spec updates (the front page lists sections; more quick-facts blocks), included in the commits. ### Deferred JS budget | | before (origin/dev) | after | |---|---|---| | deferred gzip | 61274 / 61440 (166 left) | 61286 / 61440 (**154 left**) | | deferred brotli | 54101 / 55296 | 54006 / 55296 | | critical gzip | 311299 / 327680 | 311301 / 327680 | The only deferred change is the notice's URL string (`/docs/terminal/multiplexer/`, +9 B raw, +12 B gzip). All other app code is in on-demand chunks. My first version added a shared helper chunk, which cost 33 B gzip in critical and 26 B in deferred; I removed it by keeping window ids as the plain `d-<slug>`. ### For the owner - Docs detached from the app (D317 open item): the build output is the same tree; nothing here depends on the app besides the Docs view reading `index.json`. - No screenshots: the only visual change is the front page listing sections instead of pages; the specs measure its alignment as before.
Sign in to join this conversation.
No labels
launch-qa
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
kayg/infraternal#311
No description provided.