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

Crew briefs point at docs/PRINCIPLES.md instead of restating it #8784

Merged opened this

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

Merged

torque/forge:torque/8737-crew-briefs-point-at-docs-principles-md → main 2 commits fork 3 threads · 3 unresolved

  • Merged. torque/8737-crew-briefs-point-at-docs-principles-md was merged into main as 42fc628.

Review

Sign in to review this change.
3 files changed +36 −26
CLAUDE.md +17 −25
@@ -8,14 +8,10 @@ rulebook: the invariants you must not break, and how to work here.
88
99 **Read docs/VISION.md first: it says what the forge is for and the order of work.**
1010
11 **Done means reachable** — a person reaches it from the feed in two taps, an
12 agent through the MCP, a test proves it, a look shows it. A function nobody can
13 call is not done.
14
15 The whole point of forge is that **one person can hold it in their head**. Every
16 change should leave it that way. When something fights you, step up and
17 understand the system before adding code — a workaround usually means the system
18 isn't understood yet.
11 **Done means reachable**, and the rest of what the forge holds to is in
12 docs/PRINCIPLES.md with what enforces each; read it. This file does not repeat it. When
13 something fights you, step up and understand the system before adding code — a
14 workaround usually means the system isn't understood yet.
1915
2016 ## Invariants — do not break these
2117
@@ -30,9 +26,8 @@ isn't understood yet.
3026 3. **Real git, thin wrapper.** Never reimplement pack negotiation, diff, blame,
3127 or merge. Spawn the `git` binary and plumb bytes carefully. Correctness comes
3228 from git; our job is safe arguments and clean I/O.
33 4. **Git is truth; the DB is a derived index.** SQLite holds nothing that can't
34 be rebuilt from the bare repos. `core/reconcile.ts` self-heals the index from
35 git on boot. Don't invent state that lives only in the DB (or only in memory).
29 4. **Derived index** (docs/PRINCIPLES.md). Don't invent state that lives only
30 in the DB (or only in memory).
3631 5. **State changes go through the event outbox.** Every meaningful mutation
3732 `bus.append(...)`s a durable event (`core/events.ts`). Webhooks and SSE ride
3833 that outbox; delivery is retried. Never fire-and-forget something important.
@@ -49,9 +44,9 @@ canAdmin`), token scope (`readForm` floor + `minScope`), and branch
4944 9. **`not_found` is deliberately ambiguous.** A missing resource and a resource
5045 you can't see both return `not_found`, so private repos never leak their
5146 existence. Keep that conflation when you add routes.
52 10. **The crew proposes; a person lands.** An agent (`user.kind === "agent"`)
53 never moves the default branch — the pre-receive hook refuses it,
54 protected or not — and `mergePull` refuses an agent actor. Its only grant
47 10. **The crew proposes; a person lands** (docs/PRINCIPLES.md). An agent
48 (`user.kind === "agent"`) is refused by the pre-receive hook, protected
49 or not, and by `mergePull`. Its only grant
5550 is `repo_crew` (read + write, never admin); its only credential is a
5651 token minted for a run with an expiry, deleted when the run ends, and
5752 bound to the run's repository and the fork it pushes to — every other
@@ -106,20 +101,17 @@ bun run src/main.ts # boots on :3000, data in ./data
106101 `EXCLUDED`, so never hand-edit that move. Never add `retry` — fix the
107102 cause: a shared port, a real clock, order dependence, a leaked server, a
108103 timeout near the real duration, a wall-clock bound under 200 ms on a
109 request or a spawn (`test/flake.test.ts` refuses one). A speed is never bounded by a clock: count work
110 instead (SQL statements with `test/helpers/statements.ts`, spawns, bytes,
111 phases), assert it with `expectWork` (`test/helpers/work.ts`), or use a fake
112 clock (#7789, #7824); `test/flake.test.ts` refuses a raw `under N ms` title
113 or bound.
104 request or a spawn (`test/flake.test.ts` refuses one). Speed is counted in work (docs/PRINCIPLES.md): SQL
105 statements with `test/helpers/statements.ts`, spawns, bytes, phases,
106 asserted with `expectWork` (`test/helpers/work.ts`), or a fake clock
107 (#7789, #7824).
114108 - **Every non-trivial change ships with a test.** Prefer protocol-level tests
115109 that boot a real app (`createApp` + `serve`) over unit mocks. Adversarial
116110 tests (can this be bypassed?) are worth more than happy-path ones.
117 - **Done means reachable.** A new action is called from a route, a page or an
118 MCP tool in the same pull, and a new screen is linked from a page a person
119 can get to. `scripts/hollow.ts` (run by `test/hollow.test.ts` in the gate,
120 or `bun scripts/hollow.ts`) names an exported function in `src/actions/`
121 that nothing that runs reaches (a page function no route names does not
122 count as a caller) and a screen no page links to.
111 - **Reachable** (docs/PRINCIPLES.md). A new action is called from a route, a
112 page or an MCP tool in the same pull, and a new screen is linked from a page
113 a person can get to. `bun scripts/hollow.ts` names what is not (a page
114 function no route names does not count as a caller).
123115 `scripts/hollow-allow.ts` is for hollow work an issue already owns, never
124116 for new work.
125117 - **TypeScript is strict**: `noUncheckedIndexedAccess` (index access is `T |
src/crew/brief.ts +1 −1
@@ -121,7 +121,7 @@ export function systemPrompt(input: BriefInput): string {
121121 agent.brief.trim() === "" ? "" : `\n${agent.brief.trim()}\n`,
122122 `You are working in a clone of the repository on the branch \`${input.branch}\`. The remote \`origin\` is the forge; \`git push\` is already authenticated as you and the branch already tracks \`origin/${input.branch}\`. Git configuration is read-only here — do not try to change it, a plain \`git push\` is all you need.`,
123123 "",
124 "Read docs/VISION.md first: it says what the forge is for and the order of work. Done means reachable — a person reaches it from the feed in two taps, an agent through the MCP, a test proves it, a look shows it. A function nobody can call is not done. Where the repository has docs/PRINCIPLES.md, read it too: what it holds to, and what enforces each.",
124 "Read docs/VISION.md first: it says what the forge is for and the order of work. Done means reachable: a function nobody can call is not done. Where the repository has docs/PRINCIPLES.md, read it too: what it holds to, and what enforces each.",
125125 "",
126126 "How to finish:",
127127 "- Commit your work with clear messages and push: `git push`.",
test/principles.test.ts +18
@@ -64,4 +64,22 @@ describe("who reads it", () => {
6464 expect(prompt).toContain("docs/PRINCIPLES.md");
6565 expect(prompt).toContain("Done means reachable");
6666 });
67
68 const builder = systemPrompt({
69 agent: { user: { username: "bot", displayName: "" }, brief: "" },
70 repo: { ownerName: "a", name: "forge", defaultBranch: "main" },
71 issue: { number: 1 },
72 branch: "b",
73 forgeUrl: "http://f",
74 isApp: true,
75 } as unknown as BriefInput);
76
77 test("the builder brief is at least 100 bytes shorter than on main before #8737 (7303 bytes, an app on the forge)", () => {
78 expect(Buffer.byteLength(builder)).toBeLessThanOrEqual(7303 - 100);
79 });
80
81 test("the brief points at the file, and no longer spells out the two taps", () => {
82 expect(builder).toContain("docs/PRINCIPLES.md");
83 expect(builder).not.toContain("two taps");
84 });
6785 });

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs