Public: anyone can read this; the crew can change it.

Bring the remaining docs in line with docs/WRITING.md #9525

opened this in answer to

Check · Review · Land · Live — Changes were asked on this head. Next: builder, changes were asked on this head.

A reviewer asked for changes Review

mason/forge:mason/9426-bring-the-remaining-docs-in-line-with-do → main 1 commit fork

Review

Sign in to review this change.
1 file changed +127 −87
docs/STATUS.md +127 −87
@@ -3,32 +3,84 @@
33 This document lists the features that work in today's forge. It is for
44 operators and contributors who need a concrete inventory of shipped
55 capability. Each bullet names one feature and the doors that reach it.
6 Claims match the code on the default branch; cut or fix anything you
7 cannot confirm. A package registry is not shipped yet.
6 Claims match the code on the default branch. A package registry is not
7 shipped yet.
88
9 ## Features
9 ## Accounts and access
10
11 - **Accounts & access**: register/sign in, personal access tokens with coarse
12 scopes (ro/rw/admin), public and private repositories.
13
14 - **Where an account came from**: `GET /api/v1/admin/accounts` lists each
15 account with `via` (`signup`, `edge`, or null) and `signsInThrough`
16 (`"open-platform.sh"` for an account the platform edge made, else null);
17 Settings → Accounts and the inbox's new-account line say "signs in
18 through open-platform.sh" for the same accounts. The terminal and the MCP
19 have no accounts list to carry it.
20
21 - **Removing an account**: `DELETE /api/v1/admin/accounts/:username` (admin
22 only). An account that is the last owner of an organization answers 409 with
23 the organizations named. Send `{"retireOrgs": true}` to preview: the answer
24 lists each organization, its repositories (and the app each runs) and its
25 teams, and changes nothing; the account's own repositories and the app each
26 runs are listed too, under `own`. Send `{"retireOrgs": true, "confirm": true}` to
27 do it: apps are stopped, repositories deleted, organizations retired (the
28 name stays taken), then the account. If a repository will not go, the answer
29 is 500 with `failed` and `removed`; what is left is intact and the same call
30 again finishes the job. The accounts page offers the same flow: Remove →
31 "Remove the organization too" → a confirm page listing everything that goes.
32
33 - **Organizations & teams**: orgs own repos; teams grant read/write/admin
34 resolved through membership.
35
36 ## Code hosting
37
38 - **Git**: push and pull over HTTPS and SSH, browse code (tree, blob with line anchors,
39 commit history) with README rendering and syntax highlighting, protected
40 default branches (force-push and deletion refused, honest fast-forwards
41 allowed).
42
43 - **Issues**: labels, threaded comments, close/reopen, markdown.
44
45 - **Pull requests**: open from a branch, a **diff viewer** (syntax
46 highlighting composed with intra-line word highlighting, mobile-first,
47 collapsible files), merge-commit and squash strategies, conflict detection,
48 and merge commits kept reachable forever via `refs/pull/N/merged`.
49
50 - **Review comments**: anchored to a diff line by content hash, so a
51 force-push re-anchors them or marks them outdated, never misplaces them.
52
53 - **Forks**: alternates-backed (instant, storage-bounded), with cross-repo
54 pull requests (fork → upstream) and detach-before-delete safety.
55
56 - **Commit pages**: every commit's diff through the same viewer.
1057
1158 - **A long file's page** draws its first 1,500 lines and says "N more
1259 lines", with *Show all lines* (`?all=1`) and the raw file. `?all=1` stops at
13 10,000 lines (it was 5,000 for every view before); past that, the raw file is
60 10,000 lines; past that, the raw file is
1461 the way. Highlighted lines are cached by content hash (32 files, least
1562 recently used out). A `#L…` anchor past the cut is redirected to `?all=1` by
1663 the page script; with scripts off the notice says to show all lines.
17 - **A repository's runs page filters by state**: a row of links (All, then each
18 state) above the list, or `/:owner/:name/runs?state=failed` by hand. An unknown
19 state is ignored, and the word filter and the pager keep the chosen state. The
20 terminal does the same: `H` in a repository opens its runs, and `s` cycles
21 All, Failed, Running, Succeeded.
22 - **A run page's live log** rides the page's one `/events` connection (its
23 `run.log` frames); it opens no stream of its own. Known gaps, both silent: a
24 frame the server cuts for size (64 lines or 16 KB) loses its omitted lines
25 until the next reconnect's catch-up read, and a run whose log was already cut
26 to its last 512 KB at render gets no catch-up read. The page says
27 "Reconnecting" while the connection is down.
64
65 - **Settings**: visibility, branch protection, and labels.
66
67 - **Live updates**: a server-sent-event stream turns comment threads live and
68 flags new activity, no refresh.
69
70 - **Origins**: connect GitHub, Forgejo or Gitea (device code, PKCE, or a
71 pasted token), mirror repositories in with their issues and pulls, and write
72 through to the origin on every comment, state change, label and push. Pins
73 say what the local client keeps cloned.
74
75 - **Automation**: a JSON API covering repos, issues, forks, and orgs (the
76 label-as-queue surface), a durable event outbox, and **webhooks** (HMAC-signed
77 delivery with retry). Every send goes through `src/kernel/outbound.ts`:
78 - https URLs only; the host is resolved, private addresses are refused, and no redirect is followed.
79 - A refused delivery fails at once, with the reason shown on the hooks page.
80 - An unreachable or erroring endpoint is retried with growing delay.
2881
2982 - **Cut a wave**: Settings → *Cut a wave* (repository admins, same-origin
30 POST) opens a pull
31 adding `waves/<next>.md`, listing the pulls merged since the last wave and
83 POST) opens a pull adding `waves/<next>.md`, listing the pulls merged since the last wave and
3284 not already in an earlier wave. The headline and highlights are `TODO`
3385 placeholders; no model is called. It refuses, writing nothing, when an
3486 earlier wave does not parse (naming the file) or nothing new has merged.
@@ -46,15 +98,38 @@ cannot confirm. A package registry is not shipped yet.
4698 the waves page; a private repository's feed is a 404 to anyone who cannot
4799 read it.
48100
49 - **Accounts & access**: register/sign in, personal access tokens with coarse
50 scopes (ro/rw/admin), public and private repositories.
51 - **Git**: push and pull over HTTPS **and SSH**, browse code (tree, blob with line anchors,
52 commit history) with README rendering and **syntax highlighting**, protected
53 default branches (force-push and deletion refused, honest fast-forwards
54 allowed).
55 - **System memory**: `/system`, for a forge admin who is a person (anyone else gets 403): the forge's RSS beside its JS heap (`heapStats()` from bun:jsc), hourly mean and max for the last 24 h, drawn on the server. Sampled once a minute into `memory_hour` in `app.db` (a week kept). RSS rising while the heap stays flat is native memory growth. In the terminal the same admin has a **System memory** command in the palette: the last 24 hours as text rows (hour, RSS mean/max, heap mean/max in MiB), read-only. The account menu links `/system` for that admin.
56 - **Flow alarms**: a firing alarm (red main, a stuck approved pull, an idle crew, no release for 90 min) shows as one linked line above home's feed and on `/boards` (admin), under the vitals line of the terminal's Flow dialog and home, as one phone notification when it starts (not repeated while it stands), and in the `flow` tool's `alarms` (MCP, `/api/v1/telemetry/flow`; an agent's cut to public repositories). Nothing firing draws nothing. The dialog also lists the idle crew pulls (number, repository, hours since the last push), oldest first, at most 20 read and five drawn with `+N more`; none draws nothing, and an agent's list is cut to public repositories.
57 - **Clog watch**: the minute tick (`src/flow/clog_tick.ts`) reads the flow; when a clog starts the admin gets one phone notification, and when it clears one `clog.cleared` note (cause, time to clear, peak stranded $) lands once on the admin's feed and as a line on the terminal's home. The watch state is in the database, so a restart repeats neither.
101 ## Apps and crew
102
103 - **Apps**: a repository that runs: production on the default branch, a
104 preview per open pull with its own copy of the data, served by hostname
105 from the forge's own port, every deploy a run and every run a check.
106
107 - **The crew**: agents as accounts with nothing but a run-scoped token,
108 working issues in the background with Claude Code and proposing through
109 pulls a person merges.
110
111 - **The `flow` label**: ready issues labelled `flow` go first; no switch, no state.
112
113 - **The check lane is visible.** Checks run one at a time; an admin's home
114 strip, the terminal dashboard's strip and `GET /api/v1/health` (`lane`) show
115 the queue depth, the running check and its age, the median of the last
116 twenty and the time to clear, and the 30-minute queue card names that cause.
117
118 - **A repository's runs page filters by state**: a row of links (All, then each
119 state) above the list, or `/:owner/:name/runs?state=failed` by hand. An unknown
120 state is ignored, and the word filter and the pager keep the chosen state. The
121 terminal does the same: `H` in a repository opens its runs, and `s` cycles
122 All, Failed, Running, Succeeded.
123
124 - **A run page's live log** rides the page's one `/events` connection (its
125 `run.log` frames); it opens no stream of its own. Known gaps, both silent: a
126 frame the server cuts for size (64 lines or 16 KB) loses its omitted lines
127 until the next reconnect's catch-up read, and a run whose log was already cut
128 to its last 512 KB at render gets no catch-up read. The page says
129 "Reconnecting" while the connection is down.
130
131 ## Boards and flow
132
58133 - **Boards**: `/boards` also shows the pipeline (a row per stage, the bottleneck named) and the held counts (why each autonomous repository's ready issues wait; private repositories included), for the same admin who is a person; they sit as two cards under the board list, not as panels of a board, because they are not saved queries. The terminal's Boards screen does not draw them: its door to the same rows is the **Flow** dialog. `/boards/data`, for a forge admin who is a person (anyone else
59134 gets a 404 on the page): the query is the URL (`?source=runs&aggregate=count&by=day&fcolumn=state&fvalue=failed`),
60135 drawn server-side as the chart chosen beside it (`chart=line|bar|area|number|table|heat`)
@@ -77,72 +152,37 @@ cannot confirm. A package registry is not shipped yet.
77152 The first boot also writes the starting boards, **Usage**, **Serving**, **Crew**, **Releases**, **Apps**, **Security**, **Throughput**, **Reach** and **Forges**; Serving is the forge's event-loop lag p99 beside the checks and crew runs running, so checks' concurrency is raised on numbers. Apps' per-app panels show repo ids until a source exposes a safe name; Security (sign-ins, failed sign-ins, tokens by scope, admin actions, from the admin-only `signins`, `tokens` and `adminActions` sources and `usage`) shows no token text, hash, payload or IP; Throughput is items entering each stage from issue to live, per hour, from the `stages` source. Each is written once: `.offered` in that repo records them, so an edit stays and a deletion sticks.
78153 A live board (any `refresh` but `off`; the form offers off or on, and `10s` and `1m` are still accepted and mean the same) redraws its grid when a run, pull, check, issue or usage event arrives, through the live-region swap
79154 (`/boards/:slug/live`, etag'd, one fetch per burst). The same doors are in the API: `GET /api/v1/boards`, `GET|PUT|DELETE /api/v1/boards/:slug`, and each panel's data as JSON or CSV at `GET /api/v1/boards/:slug/panels/:id?from=&to=&step=5m&format=csv`, bucketed in SQL to the step and never cut short (`docs/APPS.md`); each panel's card links `json` and `csv` (a plain download link) beside `explore`
80 (an agent or anyone but an admin is 403; a panel whose query cannot run is refused with 422). The same four doors are MCP tools (`boards`, `board_write`, `board_delete`; `boards` with a `slug` reads one, and with a `panel` too that panel's data, with the same `from`, `to` and `step`) and, for the same person, a **Boards** screen in the terminal that lists boards and shows a board's panels as text, each with what its data holds now (a time panel's last bucket and step, another's row count). No dependency was added.
155 (an agent or anyone but an admin is 403; a panel whose query cannot run is refused with 422). The same four doors are MCP tools (`boards`, `board_write`, `board_delete`; `boards` with a `slug` reads one, and with a `panel` too that panel's data, with the same `from`, `to` and `step`) and, for the same person, a **Boards** screen in the terminal that lists boards and shows a board's panels as text, each with what its data holds now (a time panel's last bucket and step, another's row count).
156
157 - **Flow alarms**: a firing alarm (red main, a stuck approved pull, an idle crew, no release for 90 min) shows as one linked line above home's feed and on `/boards` (admin), under the vitals line of the terminal's Flow dialog and home, as one phone notification when it starts (not repeated while it stands), and in the `flow` tool's `alarms` (MCP, `/api/v1/telemetry/flow`; an agent's cut to public repositories). Nothing firing draws nothing. The dialog also lists the idle crew pulls (number, repository, hours since the last push), oldest first, at most 20 read and five drawn with `+N more`; none draws nothing, and an agent's list is cut to public repositories.
158
159 - **Clog watch**: the minute tick (`src/flow/clog_tick.ts`) reads the flow; when a clog starts the admin gets one phone notification, and when it clears one `clog.cleared` note (cause, time to clear, peak stranded $) lands once on the admin's feed and as a line on the terminal's home. The watch state is in the database, so a restart repeats neither.
160
81161 - **Parked work**: the terminal's Flow dialog says how many issues the crew parked (an open issue whose newest comment is the crew's `Parked by the crew` note) in the last 24 h and 7 d, and names the newest three; the MCP `flow` tool returns the same as `parked`. The flow panel on `/boards` draws two lines under its numbers, each left out at 0: `N idle pulls` (open crew pulls whose head has not moved for 72 h; the oldest three linked, `and K more` after) and `N parked today, M this week` (linking the newest parked issue). The Flow dialog lists them too (`idle: N`, a row each, `+K more`). `/boards` is the owner's; the MCP `flow` tool, as an agent, reads public repositories only (sealed issues left out). `and K more` opens `/boards?idle=all`, a list of every idle pull. See `docs/TOUR.md`.
82 - **Issues**: labels, threaded comments, close/reopen, markdown.
83 - **Pull requests**: open from a branch, a **diff viewer** (syntax
84 highlighting composed with intra-line word highlighting, mobile-first,
85 collapsible files), merge-commit and squash strategies, conflict detection,
86 and merge commits kept reachable forever via `refs/pull/N/merged`.
87 - **Review comments**: anchored to a diff line by content hash, so a
88 force-push re-anchors them or marks them outdated, never misplaces them.
89 - **Forks**: alternates-backed (instant, storage-bounded), with cross-repo
90 pull requests (fork → upstream) and detach-before-delete safety.
91 - **Organizations & teams**: orgs own repos; teams grant read/write/admin
92 resolved through membership.
93 - **Live updates**: a server-sent-event stream turns comment threads live and
94 flags new activity, no refresh.
95 - **Commit pages**: every commit's diff through the same viewer.
96 - **Settings**: visibility, branch protection, and labels.
97 - **The check lane is visible.** Checks run one at a time; an admin's home
98 strip, the terminal dashboard's strip and `GET /api/v1/health` (`lane`) show
99 the queue depth, the running check and its age, the median of the last
100 twenty and the time to clear, and the 30-minute queue card names that cause.
162
163 - **System memory**: `/system`, for a forge admin who is a person (anyone else gets 403): the forge's RSS beside its JS heap (`heapStats()` from bun:jsc), hourly mean and max for the last 24 h, drawn on the server. Sampled once a minute into `memory_hour` in `app.db` (a week kept). Rising RSS with a flat heap means native memory growth. In the terminal the same admin has a **System memory** command in the palette: the last 24 hours as text rows (hour, RSS mean/max, heap mean/max in MiB), read-only. The account menu links `/system` for that admin.
164
165 ## Terminal
166
101167 - **A terminal UI**: `ssh` in for the whole forge: dashboard, code browsing
102168 with syntax highlighting, issues and pulls with live-updating threads, the
103169 diff viewer with inline review comments, merges, settings, orgs, tokens and
104170 keys. Six themes, remembered per account.
105 - **Origins**: connect GitHub, Forgejo or Gitea (device code, PKCE, or a
106 pasted token), mirror repositories in with their issues and pulls, and write
107 through to the origin on every comment, state change, label and push. Pins
108 say what the local client keeps cloned.
109 - **Automation**: a JSON API covering repos, issues, forks, and orgs (the
110 label-as-queue surface), a durable event outbox, and **webhooks** (HMAC-signed
111 delivery with retry). Every send goes through `src/kernel/outbound.ts`:
112 - https URLs only; the host is resolved, private addresses are refused, and no redirect is followed.
113 - A refused delivery fails at once, with the reason shown on the hooks page.
114 - An unreachable or erroring endpoint is retried with growing delay.
115 - **Where an account came from**: `GET /api/v1/admin/accounts` lists each
116 account with `via` (`signup`, `edge`, or null) and `signsInThrough`
117 (`"open-platform.sh"` for an account the platform edge made, else null);
118 Settings → Accounts and the new-account line in the inbox say "signs in
119 through open-platform.sh" for the same accounts. The terminal and the MCP
120 have no accounts list to carry it.
121 - **Removing an account**: `DELETE /api/v1/admin/accounts/:username` (admin
122 only). An account that is the last owner of an organization answers 409 with
123 the organizations named. Send `{"retireOrgs": true}` to preview: the answer
124 lists each organization, its repositories (and the app each runs) and its
125 teams, and changes nothing; the account's own repositories and the app each
126 runs are listed too, under `own`. Send `{"retireOrgs": true, "confirm": true}` to
127 do it: apps are stopped, repositories deleted, organizations retired (the
128 name stays taken), then the account. If a repository will not go, the answer
129 is 500 with `failed` and `removed`; what is left is intact and the same call
130 again finishes the job. The accounts page offers the same flow: Remove →
131 "Remove the organization too" → a confirm page listing everything that goes.
132 - **Apps**: a repository that runs: production on the default branch, a
133 preview per open pull with its own copy of the data, served by hostname
134 from the forge's own port, every deploy a run and every run a check.
135 - **The crew**: agents as accounts with nothing but a run-scoped token,
136 working issues in the background with Claude Code and proposing through
137 pulls a person merges.
138 - **The `flow` label**: ready issues labelled `flow` go first; no switch, no state.
139171
140 Pages render without a line of JavaScript and are designed thumb-first. Six
141 premade themes (from warm paper to polar night) switch instantly and persist in
142 a cookie; even that works script-free. Still **zero runtime dependencies**.
172 ## Rendering and themes
143173
144 Built since: every app, preview and check runs in a bubblewrap cell
145 (`src/apps/contain.ts`), an app can take a custom domain (MCP `app_domains`,
146 `src/http/mcp/tools/app_domains.ts`), and a pull whose review and checks agree
174 Pages render without JavaScript and are designed for a phone first. Six
175 themes (from warm paper to polar night) switch instantly and persist in a
176 cookie; that works without scripts too. The forge has no runtime dependencies.
177
178 ## Isolation and landing
179
180 Every app, preview and check runs in a bubblewrap cell
181 (`src/apps/contain.ts`). An app can take a custom domain (MCP `app_domains`,
182 `src/http/mcp/tools/app_domains.ts`). A pull whose review and checks agree
147183 lands on its own (`src/checks/landing.ts`, the merge queue in
148 `src/checks/queue.ts`). Not yet: a package registry.
184 `src/checks/queue.ts`).
185
186 ## Not done
187
188 There is no package registry.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs