Working state — a note taken while the work happens, not a specification. The system as it is meant to be is in Architecture.
How this work goes
Written for whoever picks this up — including a future me. The durable, project-owned
practices live on the website now: docs/architecture/principles.md (what the system is)
and docs/architecture/implementors-guide.md (how to work on it — pit-over-C, named
refusals, docs-first, guard comments, lifetimes, the C safety rules). This file is what
remains deliberately local: the working agreement with John, and the operational lore of
running this rebuild with subagents. The historical ruling record is
plans/archive/edicts-2026-07.md.
The loop
implement the docs
→ hit work the docs do not scope, or do not make clear
→ raise it to John rather than deciding
→ his answer is almost always simpler than the code
→ the doc is made explicit
→ the code aligns to the doc
→ which exposes the next unscoped thing
→ repeat
The docs are about 80% right, and the default action is to follow them. This is John’s own calibration and it sets the posture: you are here to implement, not to audit. A page that reads oddly but tells you what to build is a page you build from.
The trigger for asking is unscoped or unclear work — not noticing something. If you start on something the docs do not cover, or cover ambiguously enough that two readings would produce different code, stop and ask. That specific trigger matters because those questions are almost never local: the reason a doc is silent is usually that it brushes against another part of the system, and John following that thread is where the design actually advances.
So do not queue up small observations for review. A stale sentence, a dead file, a rule bent — fix it or mention it in passing and keep going. Spend the interrupt on the thing you cannot proceed on.
After a ruling, the doc changes first and the code follows it. Never the reverse, and never code-only: the docs are the record of intent, so an implemented ruling that is not written down has already begun to rot. Making the doc explicit is part of the work item, not follow-up.
Two consequences worth stating, because both have already bitten:
- A ruling can invalidate work that is already committed, and the answer is to delete it. Edict 1 applies to our own output. The gate exists so we can delete fearlessly; a commit is not a reason to defend a design John has since replaced.
- The roadmap is an ordering, not a contract. Nearly every raised question deletes or reshapes something below it. Phases D and E in particular should be expected to shrink as earlier phases remove the problems they were solving.
Rules that earned their place
Verify; do not trust a report. Every gate gets re-run independently before a commit.
This is not ceremony — a subagent reported ALL GREEN while having deleted a function and
left nine call sites, because make check builds only the utf32 text arm. Another agent
caught it days later by accident.
make check is one point in a multi-axis space. text=kim8, gc=compact,
numrep=nan32 and the console reps are never compiled by it. Build the arms your change
could touch. (make check-web self-skips without emcc — confirm a red is yours before
chasing it.) make budget is the SHOP budget only since 2026-08-06; the compiler half
was retired and compiler cost now lives in perf/ir_census.py and make bench.
Audits are evidence, not instructions. Two audit findings I relayed to agents were
wrong: instr_facts was called dead and is live (deleting it would have broken
generation-time fusion), and an ABI bump was called free because the seed self-reseeds — it
is not, because seed: depends on all, so the binary is rebuilt before the producer runs.
Both were caught by agents re-verifying. Tell agents to check the list they are given.
Port nothing faithfully. 9466791a never built — it added a translation unit without
regenerating the build manifests and uses assert() without including <assert.h>. Treat
every line as unverified. If a ported block contains a fallback, the fallback does not come
with it.
Raise it when you hit it; do not queue it. John answers as things come up. A ruling
goes straight into the docs (docs/architecture/principles.md, the glossary, or the page
it touches) if it is a standing rule, or into the live plan for the arc it belongs to
(plans/work-proposal.md’s lanes, or plans/carried.md if it belongs to no lane) if it is work;
an open question goes to him in conversation. There was briefly a review queue, for a stretch
when he was asleep and decisions had to accumulate — it is archived at
plans/archive/review-queue-2026-07-25.md and should not be worked from.
What made that queue useful is still worth keeping, though, in whatever form: write down the reasoning, not just the decision. Two calls were overturned cheaply because the argument was on the page rather than buried in a diff, and one of those — keeping record-shape interning — was wrong in a way that would have been expensive to find later.
Working with subagents
- Isolated worktrees for code, because two agents cannot build in one tree — the daemon is process-global per shop, and any boot-input change regenerates binary artifacts. Read-only audits parallelize freely.
- Their worktrees are created from a stale base. Agents have found themselves
hundreds of commits behind. Every brief must name the exact base commit and say: verify
git log --oneline -1,git checkout <sha>if wrong (worktrees share refs), and run plainmakefirst — otherwise./pitsilently resolves to the main checkout’s shop and daemon. - Merge source-only, then reseed and re-verify yourself. Never merge an agent’s regenerated boot artifacts.
- Tell them not to commit and not to
git add. A staged deletion from one agent was swept into an unrelated commit of mine becausegit commitwithout a pathspec takes whatever is in the index. - Give them the target design, not just the task — a paragraph of where it is going. Every agent that had it made better calls at the edges than the brief anticipated.
- Tell them to stop and ask. The best outcomes came from agents that refused: one
stopped rather than enforce the
internal/rule after finding 86 imports depending on it being unenforced; another withheld a construction step whose dependency was not yet landed and quoted the original call at the site instead.
The shape of the system, for calibration
Programs import modules; modules import other modules; both use endowments; endowments can be denied by the shop; an executable is an ordered list of things to run to start an actor; module choice can branch on the target; mcode files lower into single mach images sharing a stone pool of shapes, text, bytecode and numbers; those are objects like any other on an actor’s heap.
If a change makes that description longer, be suspicious. The system is simple and grew out of hand; the work is putting it back. John’s answer will nearly always be the simpler one, so when two readings are defensible, ask — do not pick the elaborate one and build it.
What has actually worked, concretely
Two things produced nearly every substantial finding, and they are cheap to repeat.
Build the gate before the work. check-arms did not exist at the start of this arc. Since
then it has caught, none of them on any worklist: a meson-vs-C guard drift on fixed32;
PIT_MACH_DEBUG_CONTRACTS compiled by nothing; NDEBUG defined in no arm, so the hot loop’s
bound check is always live; a kim8 equality bug making every multi-byte key compare unequal on
a real target; and four live GC rooting bugs, one in scheduler.c’s letter path. A gate
that compiles one point in a multi-axis space is a gate that ships breakage.
Make agents verify the premise, not the suite. Briefs are wrong often enough that checking
them is where the value is. Corrected this way: the “obvious” seed-ordering fix turned out
worse than the bug (a quiet success leaving an unbootable tree); a proposed compiler fold
would not fire because the index and the comparison sit in different functions with no
inliner; pmac is not the sectioned pmp1 format at all; the pool expansion was 2.72× not 4×.
Three of those corrected me. Say “prove it against the failure, not against a green suite.”
Guard comments bind within a world, not across one (RULED, John 2026-07-31). A “do not relax this assertion” comment is written to stop drive-by softening — it is NOT a veto over a ruled rework. When a landing executes a ruling that inverts the old world (M1-era pmcd assertions under the carts-carry-pools ruling, say), the ruling is the authority and the comment is overridden by name: the new assertion cites the ruling it enforces and becomes the new “do not relax”. Two duties follow. For a large rework’s brief: say explicitly that old-world guard comments do not bind — batch them for a ruling if the inversion is unclear, override them citing the ruling when it is. At arc close-out: sweep the surviving guard comments and re-anchor each to the current ruling it protects, so the next world’s migration is never argued against by a fossil.
Where things stand
docs/architecture/principles.md — the standing rules, and the whole system in six lines.
docs/glossary.md — the ratified vocabulary.
plans/programs.md — start here. The programs arc’s rulings (ratified 2026-08-05).
plans/work-proposal.md — its lanes, sequencing, and gate discipline.
plans/measurement-suite.md — the measurement floor everything is judged against.
plans/carried.md — the ledger: everything carried out of the retired plans, plus the
defects logged during integration. An item leaves it by being fixed or promoted into a lane.
plans/memory-arc.md and plans/compiler-vision.md — the queued next arcs.
plans/archive/ — superseded plans (one-binary.md, compiler-perf.md, derivations.md,
board.md, todo.md, finalization-arc.md, the night-2026-08-04/ investigations) and
the historical ruling record (edicts-2026-07.md), for reasoning only.
The spine in one line: Pit emits, C reads; pools are the only executable; one
binary; one lane. The finalization and one-binary arcs made most of it true; the
programs arc (plans/programs.md) is what makes products real on top of it, with
plans/compiler-vision.md and plans/memory-arc.md holding what it has not absorbed.
Source: plans/method.md