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

The forge tells its own story: trevato/forge has its first wave, with a headline and highlights a person would be happy to read #7802

Merged opened this

Check · Review · Land · Live done — Landed and live in production.

Merged

mason/forge:mason/7764-the-forge-tells-its-own-story-trevato-fo → main 2 commits fork

  • Merged. mason/7764-the-forge-tells-its-own-story-trevato-fo was merged into main as bd7b4c7.

Review

Sign in to review this change.
2 files changed +171 −0
test/forge-first-wave.test.ts added +73
@@ -0,0 +1,73 @@
1 /** The forge's own story: the committed `waves/` parse, carry no `TODO` placeholder and stay short enough to read (#7764). */
2 import { afterAll, beforeAll, expect, test } from "bun:test";
3 import { mkdtemp, readdir, rm } from "node:fs/promises";
4 import { tmpdir } from "node:os";
5 import { join } from "node:path";
6 import { commitToBranch, createRepo } from "../src/actions/repos.ts";
7 import { createApp, type App } from "../src/app.ts";
8 import { createUser } from "../src/core/users.ts";
9 import { repoDir } from "../src/git/repos.ts";
10 import { PLACEHOLDER } from "../src/story/cut.ts";
11 import { readWaves } from "../src/story/waves.ts";
12
13 /** A wave is read, not archived: a curated list, well under the reader's 256 KB bound. */
14 const MAX_PULLS = 150;
15 const MAX_WAVE_BYTES = 64 * 1024;
16
17 const WAVES = join(import.meta.dir, "..", "waves");
18
19 let dataDir = "";
20 let app: App;
21
22 beforeAll(async () => {
23 dataDir = await mkdtemp(join(tmpdir(), "forge-first-wave-"));
24 app = createApp({ dataDir, port: 0 });
25 });
26 afterAll(async () => {
27 await rm(dataDir, { recursive: true, force: true });
28 });
29
30 test("the committed waves read through readWaves, each whole, none a draft", async () => {
31 const names = (await readdir(WAVES)).filter((n) => n.endsWith(".md"));
32 expect(names.length).toBeGreaterThanOrEqual(1);
33 const u = await createUser(app.db, {
34 origin: "seed",
35 trusted: true,
36 username: "alice",
37 email: "[email protected]",
38 password: "a-good-passphrase",
39 adminIfFirst: true,
40 });
41 if (!u.ok) throw new Error("user");
42 const r = await createRepo(app, u.value, { name: "forge", visibility: "public" });
43 if (!r.ok) throw new Error("repo");
44 const files = await Promise.all(
45 names.map(async (n) => ({
46 path: `waves/${n}`,
47 content: await Bun.file(join(WAVES, n)).text(),
48 })),
49 );
50 const c = await commitToBranch(app, u.value, r.value, { message: "waves", files });
51 if (!c.ok) throw new Error("commit");
52 const entries = await readWaves(
53 repoDir(app.reposRoot, r.value.ownerName, r.value.name),
54 r.value.defaultBranch,
55 );
56 expect(entries.length).toBe(names.length);
57 for (const e of entries) {
58 if (!e.ok) throw new Error(e.reason);
59 const text = await Bun.file(join(WAVES, e.file)).text();
60 expect(text).not.toContain(PLACEHOLDER);
61 expect(e.wave.highlights.length).toBeGreaterThanOrEqual(3);
62 expect(e.wave.pulls.length).toBeGreaterThan(0);
63 expect(e.wave.pulls.length).toBeLessThanOrEqual(MAX_PULLS);
64 expect(new TextEncoder().encode(text).length).toBeLessThan(MAX_WAVE_BYTES);
65 // Each highlight rests on a pull the wave lists.
66 const listed = new Set(e.wave.pulls.map((p) => /^#(\d+) /.exec(p.title)?.[1]));
67 for (const h of e.wave.highlights) {
68 const cited = [...h.why.matchAll(/#(\d+)/g)].map((m) => m[1]);
69 expect(cited.length).toBeGreaterThan(0);
70 for (const n of cited) expect(listed.has(n)).toBe(true);
71 }
72 }
73 });
waves/0.7.272.md added +98
@@ -0,0 +1,98 @@
1 ---
2 version: 0.7.272
3 date: 2026-11-01
4 headline: The forge keeps its merge queue through a restart, proves its backups by restoring them, and lets agents sign in with OAuth
5 ---
6
7 ## Highlights
8
9 - **Agents sign in to the forge's MCP with OAuth** — a client that speaks the standard can discover the forge, register itself and be told where to authorize, so connecting an agent no longer means pasting a token by hand (#579, #2397)
10 - **The merge queue survives a rollout** — deploying the forge used to throw away a gate half-run; now the new process resumes the same candidate, so a release no longer costs every waiting pull another full check (#6616)
11 - **A backup is proved by restoring it** — the weekly drill boots the restored copy, posts its verdict on the recovery issue and, when it fails, puts a card in the inbox until one passes, so nobody learns a backup is bad on the day they need it (#1717)
12 - **A typical pull is checked in under two minutes** — slow test setup was the longest wait between a pull and its merge; cheaper hashing and SQLite in tests, and the two slowest files split, shorten that wait for everyone (#2064)
13 - **The API is a page you can read and try** — /api renders the forge's own OpenAPI spec by area, with schemas and a way to try a call as yourself, so a person or an agent learns what the forge can do from the forge (#7587)
14
15 ## Pulls
16
17 - [#579 OAuth for the MCP, step one: discovery documents, dynamic client registration, and a 401 that names them](https://forge.open-platform.sh/trevato/forge/pulls/579)
18 - [#886 Make it yours: copies start private, and an account makes at most five a day](https://forge.open-platform.sh/trevato/forge/pulls/886)
19 - [#1717 The weekly restore drill posts its verdict on the recovery issue, and a failed drill is a card in the inbox](https://forge.open-platform.sh/trevato/forge/pulls/1717)
20 - [#1773 The palette's "Tell the crew" opens a composer in place on any repository page and sends the page with the tell](https://forge.open-platform.sh/trevato/forge/pulls/1773)
21 - [#2064 Check time under 2 minutes for a typical pull: Bun-native affected tests, real timings, split the two slowest files, fast git and SQLite in tests](https://forge.open-platform.sh/trevato/forge/pulls/2064)
22 - [#1862 A spawned forge carries a fork of the forge it came from, and the chain shows both ways](https://forge.open-platform.sh/trevato/forge/pulls/1862)
23 - [#2300 Tell the crew from the forge toolbar: the tell carries the page it was sent from](https://forge.open-platform.sh/trevato/forge/pulls/2300)
24 - [#2397 GET /.well-known/oauth-protected-resource answers RFC 9728 JSON naming this forge's /mcp and its authorization server](https://forge.open-platform.sh/trevato/forge/pulls/2397)
25 - [#2436 A proposal to the parent forge reaches an open chain page live, through any door](https://forge.open-platform.sh/trevato/forge/pulls/2436)
26 - [#2440 MCP: propose to the parent forge and list proposals](https://forge.open-platform.sh/trevato/forge/pulls/2440)
27 - [#2468 Boards, step 6a: the forge writes the Usage and Crew starting boards on boot, and never overwrites an edited one](https://forge.open-platform.sh/trevato/forge/pulls/2468)
28 - [#2475 Boards, step 6d: a stages source and the Throughput starting board](https://forge.open-platform.sh/trevato/forge/pulls/2475)
29 - [#2496 MCP OAuth, part 2: authorize with consent and a PKCE token exchange that mints the same ro/rw forge token](https://forge.open-platform.sh/trevato/forge/pulls/2496)
30 - [#2524 On the home, an admin selects apps and archives them in one tap, and the answer offers Undo](https://forge.open-platform.sh/trevato/forge/pulls/2524)
31 - [#2560 Schema migrations are identified by name, so two pulls can each add one without colliding](https://forge.open-platform.sh/trevato/forge/pulls/2560)
32 - [#2604 Take updates from trevato/forge-upstream](https://forge.open-platform.sh/trevato/forge/pulls/2604)
33 - [#2620 The restore drill's time limit grows with the size of the snapshot it restores](https://forge.open-platform.sh/trevato/forge/pulls/2620)
34 - [#2640 take-updates: a forge in take-updates merges its parent's new code when it applies cleanly, and opens the converge issue when it does not](https://forge.open-platform.sh/trevato/forge/pulls/2640)
35 - [#2661 Through MCP an agent reads how a forge stands against its parent forge and takes its new code](https://forge.open-platform.sh/trevato/forge/pulls/2661)
36 - [#2820 Crew teams: a named group of crew members with a charter and a dial the owner sets on one settings page](https://forge.open-platform.sh/trevato/forge/pulls/2820)
37 - [#2792 Every app made from the template measures its visitors and page speed from its first deploy](https://forge.open-platform.sh/trevato/forge/pulls/2792)
38 - [#2948 Strangers cannot exhaust the forge: anonymous clones, code search and streams are rate-limited and capped](https://forge.open-platform.sh/trevato/forge/pulls/2948)
39 - [#2952 Perimeter: the forge's anonymous answers say only what a stranger needs](https://forge.open-platform.sh/trevato/forge/pulls/2952)
40 - [#3000 Each deployed preview of the forge is checked by webspec() and the pull shows its findings, report-only](https://forge.open-platform.sh/trevato/forge/pulls/3000)
41 - [#3104 A pull's looks sit beside the same page's look from main: before and after](https://forge.open-platform.sh/trevato/forge/pulls/3104)
42 - [#3156 A landing gate cut short by a roll is not red: the queue re-gates it on boot](https://forge.open-platform.sh/trevato/forge/pulls/3156)
43 - [#3184 A crew member's scorecard shows the last 30 days beside all time](https://forge.open-platform.sh/trevato/forge/pulls/3184)
44 - [#3304 Issues and pull requests are called issues and pull requests everywhere: retire "Told", "Changes", /tells and /changes](https://forge.open-platform.sh/trevato/forge/pulls/3304)
45 - [#3448 The forge pill can be moved out of the way: drag it to any corner, it stays there per app, and it never covers the app's own controls](https://forge.open-platform.sh/trevato/forge/pulls/3448)
46 - [#3412 Migrate from the terminal: pick a repository and its branch, put a crew on it, watch the job](https://forge.open-platform.sh/trevato/forge/pulls/3412)
47 - [#3760 The `new_app` tool's answer draws a ui://forge/app card: the app coming alive, its preview link and its agent](https://forge.open-platform.sh/trevato/forge/pulls/3760)
48 - [#3772 /apps shows each app's time from New app to its first preview, beside its name](https://forge.open-platform.sh/trevato/forge/pulls/3772)
49 - [#3996 The sentinel files no forge issue for another repository's red main; that repository's owner is told instead, in words that name the fix](https://forge.open-platform.sh/trevato/forge/pulls/3996)
50 - [#3968 A release is never held because main moved: the build accepts a green check of a descendant of the tagged commit](https://forge.open-platform.sh/trevato/forge/pulls/3968)
51 - [#3312 A migrated repository shows its trail: "migrated from github.com/Trevato/SO-ARM100, a fork of TheRobotStudio/SO-ARM100", each a link up - hideable per repository](https://forge.open-platform.sh/trevato/forge/pulls/3312)
52 - [#4176 The asks list holds every pull waiting on a person: handed over, or untouched by a person for 24 h](https://forge.open-platform.sh/trevato/forge/pulls/4176)
53 - [#4220 The landing gate itself lands an upstream pull as a merge, so the upstream's commits stay ancestors of main](https://forge.open-platform.sh/trevato/forge/pulls/4220)
54 - [#4360 Turning following on or off reaches every open page and terminal at once](https://forge.open-platform.sh/trevato/forge/pulls/4360)
55 - [#4236 An upstream merge that conflicts starts one converge run for the crew](https://forge.open-platform.sh/trevato/forge/pulls/4236)
56 - [#4420 GET /review lists every ask as a row with its title, repository, age and why](https://forge.open-platform.sh/trevato/forge/pulls/4420)
57 - [#4736 Each /review row says what the crew advises and why, or that it has not advised yet](https://forge.open-platform.sh/trevato/forge/pulls/4736)
58 - [#5182 Act from /review: Merge, Close, Request changes, Reply, by button or key, then the next item](https://forge.open-platform.sh/trevato/forge/pulls/5182)
59 - [#5932 Drain the 199 open pulls: split src/http/mcp.ts (61 pulls collide on it) into one file per tool, re-cut the open pulls onto it, and a hot-file WIP limit](https://forge.open-platform.sh/trevato/forge/pulls/5932)
60 - [#6116 `ssh <app>@<forge> pulls` prints the app's open pulls a viewer may see, newest first, with each head's check word](https://forge.open-platform.sh/trevato/forge/pulls/6116)
61 - [#6120 `ssh <forge> tell <words>` tells the crew in one line from any shell, and prints where it went](https://forge.open-platform.sh/trevato/forge/pulls/6120)
62 - [#6172 `ssh <app>@<forge> tell <words>` tells that app's crew, and the tell records the app as where it was said](https://forge.open-platform.sh/trevato/forge/pulls/6172)
63 - [#6232 Approved-but-conflicted pulls drain one at a time: give rebases priority in the check lane, spread them across idle builders, and re-cut split files mechanically](https://forge.open-platform.sh/trevato/forge/pulls/6232)
64 - [#5752 MCP `write_file`: commit one file to an existing branch through commitToBranch, refusing in edit_words' sentences](https://forge.open-platform.sh/trevato/forge/pulls/5752)
65 - [#6252 GET /api/v1/feed answers 304 only when nothing the viewer would read has changed: events, shares, dismissals, mutes, chips and the minute](https://forge.open-platform.sh/trevato/forge/pulls/6252)
66 - [#6296 A repository's forks page draws the tree: each fork's own forks beneath it, two levels deep](https://forge.open-platform.sh/trevato/forge/pulls/6296)
67 - [#5708 MCP `app_domains`: list, add, check and remove an app's domains, with the same rules as the API](https://forge.open-platform.sh/trevato/forge/pulls/5708)
68 - [#6360 The forge computes the "stuck pull" flow alarm (#5930)](https://forge.open-platform.sh/trevato/forge/pulls/6360)
69 - [#6364 The forge computes the "no release" flow alarm (#5930)](https://forge.open-platform.sh/trevato/forge/pulls/6364)
70 - [#6400 The forge computes the "drifting pull" flow alarm: an open pull's base is 25 landings or 6 h behind main](https://forge.open-platform.sh/trevato/forge/pulls/6400)
71 - [#6416 The forge's `here` manifest names how to help: GET /api/v1/contribute and MCP `contribute`, no account needed](https://forge.open-platform.sh/trevato/forge/pulls/6416)
72 - [#5388 MCP `releases`: the forge's kept releases, which one is live and since when, for whoever may read /releases](https://forge.open-platform.sh/trevato/forge/pulls/5388)
73 - [#6616 The merge queue survives a rollout: gates in flight resume on the new pod instead of starting over](https://forge.open-platform.sh/trevato/forge/pulls/6616)
74 - [#6564 A pure function turns a day's feed events into at most three digest lines, one per repository, biggest change first, each with its evidence link](https://forge.open-platform.sh/trevato/forge/pulls/6564)
75 - [#6732 A rollout must not turn in-flight gates red: an interrupted gate re-runs as the same candidate, and red (check) retries once before bisecting](https://forge.open-platform.sh/trevato/forge/pulls/6732)
76 - [#6528 An admin can hold new work on one file: the picker starts no build whose issue names it, and the hold says who set it](https://forge.open-platform.sh/trevato/forge/pulls/6528)
77 - [#6776 The flow panel on /boards says the crew's build yield and review latency](https://forge.open-platform.sh/trevato/forge/pulls/6776)
78 - [#6964 MCP `sessions` lists the caller's sign-ins](https://forge.open-platform.sh/trevato/forge/pulls/6964)
79 - [#6940 A repository has a "flow only" switch: one setting, readable and writable by its admin from Settings, the API and MCP](https://forge.open-platform.sh/trevato/forge/pulls/6940)
80 - [#6968 MCP `sessions` ends one sign-in, so a lost device is signed out from anywhere](https://forge.open-platform.sh/trevato/forge/pulls/6968)
81 - [#6820 The command palette's last row is "Tell the crew: <what you typed>", and choosing it sends the tell from wherever you are](https://forge.open-platform.sh/trevato/forge/pulls/6820)
82 - [#7220 POST /api/v1/repos/:owner/:name/pulls/:number/take-back opens the pull that undoes a shipped one, as the page's Take back does](https://forge.open-platform.sh/trevato/forge/pulls/7220)
83 - [#7340 The terminal's waves screen cuts a wave with `c` and a confirm: a draft pull listing every pull merged since the last wave, as the waves page does](https://forge.open-platform.sh/trevato/forge/pulls/7340)
84 - [#7360 The palette's Working now lists every running crew run on this repository with how long it has run, and choosing one opens it](https://forge.open-platform.sh/trevato/forge/pulls/7360)
85 - [#7432 The planner's brief names the files that are hot now, with their pull counts, so it plans around them](https://forge.open-platform.sh/trevato/forge/pulls/7432)
86 - [#7388 Files render in the browser: CSV/TSV as a real table — sticky header, sort, filter, row count](https://forge.open-platform.sh/trevato/forge/pulls/7388)
87 - [#7392 Config files open as a form: JSON edited through a clean, typed UI that commits or proposes](https://forge.open-platform.sh/trevato/forge/pulls/7392)
88 - [#7456 `forge asks --ship/--close/--dismiss <n…>` decides asks from the shell: planned first, applied after a y/N, as POST /api/v1/asks/bulk](https://forge.open-platform.sh/trevato/forge/pulls/7456)
89 - [#7576 Escalate to Opus by need, not by agent: P0s, planning, and any pull sent back twice run on Opus; everything else on the agent's own model](https://forge.open-platform.sh/trevato/forge/pulls/7576)
90 - [#7587 An API reference in the forge: /api renders the forge's OpenAPI spec (and an app's own, if it serves one) — endpoints by area, schemas, and try it as yourself](https://forge.open-platform.sh/trevato/forge/pulls/7587)
91 - [#7548 Choosing a template for a new forge: the spawn path takes a `template`, records it, and `GET /api/v1/forges/templates` + MCP `templates` list what is offered](https://forge.open-platform.sh/trevato/forge/pulls/7548)
92 - [#7528 The commits page shows each commit's check beside it, green, red or not run, and a commit's own page says why, as MCP `commits` does](https://forge.open-platform.sh/trevato/forge/pulls/7528)
93 - [#7620 A pull enters the merge queue only after the full suite passes on its current head merged with main (not the impact-mapped subset)](https://forge.open-platform.sh/trevato/forge/pulls/7620)
94 - [#7608 `forge map` prints the plan of the folder's repository: ready now, being built, and what waits on what](https://forge.open-platform.sh/trevato/forge/pulls/7608)
95 - [#7740 A thought that says only a repository's name opens no issue: it waits as a note and the reply asks what should change](https://forge.open-platform.sh/trevato/forge/pulls/7740)
96 - [#7708 A proof is a run with a state, and a proof that cannot start or is cut off says why on the pull](https://forge.open-platform.sh/trevato/forge/pulls/7708)
97 - [#7744 The Runs page's "Working" tab shows what is working now](https://forge.open-platform.sh/trevato/forge/pulls/7744)
98 - [#7008 Home's builders tile says why builders are idle: the ceiling, no ready issue, or no subscription with headroom](https://forge.open-platform.sh/trevato/forge/pulls/7008)

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs