CLAUDE.md keeps only the rules the code cannot teach

This commit is contained in:
Joseph Ferano 2026-09-25 10:32:05 +07:00
parent 3a2837c278
commit aca3edff41

143
CLAUDE.md
View File

@ -1,125 +1,54 @@
# Working in this repository # Working in this repository
For any agent working here, including a lane in its own worktree. These are Standing rules for any agent here, including a lane in its own worktree.
standing rules, not preferences. Where a rule has a reason, the reason is given
once — the rules without one are the ones that have already cost something.
## Never ## Never
- **Never touch anything under `/home/joe/Development/fnm/`.** That is the - **Touch anything under `/home/joe/Development/fnm/`.** The author's live
author's own working copy of the falling-sand game, open in an editor with a working copy, with an editor session attached. This repository's `sand.flan`
live session attached. `fnm/flan/sand.flan` is not the same file as this is a different file and may be edited normally.
repository's `sand.flan` and is never to be read-and-written-back, moved or - **Execute `examples/*.flan`, `sand.flan`, or anything linking raylib.** They
edited. The copy in this repository is ordinary tracked source and may be open a window that strobes the author's desktop. Compile, emit, diff — never run.
edited like any other file. - **Run `dune clean`.** It escapes a worktree and deletes the main checkout's
- **Never execute `examples/*.flan`, `sand.flan`, or anything that links `_build`. Run `dune` with `--root .` from inside your own worktree.
raylib.** They open a window on the author's desktop, which strobes it. - **Kill a `flan dev` daemon you did not start.** The author keeps one attached
Compile them, emit them, diff them — never run them. to their editor.
- **Never run `dune clean`.** It walks up out of a worktree and deletes the main - **Put `Co-Authored-By`, a `Claude-Session` trailer or any watermark in a commit.**
checkout's `_build`, which takes the author's `flan` binary with it. This has
happened. Run `dune` with `--root .` from inside your own worktree.
- **Never kill a `flan dev` daemon you did not start.** The author keeps a live
one attached to their editor all day. Orphans from finished lanes are fair
game; anything whose cwd is under `fnm/` is not.
- **Never put a `Co-Authored-By`, a `Claude-Session` trailer, or any other
watermark in a commit message.**
## Commits and branches ## Commits
`master` is the trunk and tracks `origin/master`. Lanes work in their own git `master` is the trunk. Lanes work in their own worktree and never merge or push;
worktree off it and do not merge or push — merges are resolved by the session the dispatching session merges. A commit message is one declarative sentence
that dispatched the lane. saying what is now true, not what was done.
A commit message is a single declarative sentence in the repository's voice,
saying what is now true rather than what was done: "A thunk named for the order
it was minted in is a different signature after a reorder", not "fix thunk
naming bug". A body is for the reasoning, when there is any.
## Tests ## Tests
`dune test --root .` is the suite and takes seconds. Run it constantly; it must `dune test --root .` must be green before a lane reports; grep its output for
be green before a lane reports. FAIL, since the exit code alone has lied. `@checks` (`@page`, `@x86`, `@cells`),
`@sanitize` and `@valgrind` are slow and run once between batches of lanes, with
`dune build @checks` is `@page`, `@x86` and `@cells` — the reference page's the author's permission, never inside a lane. ASan misses uninitialised stack
examples still compile and print what the page says, the hand-written x86 reads; `@valgrind` catches them.
backend still agrees with LLVM, and a `--dev` build still calls through its
indirection cells. `@sanitize` and `@valgrind` run the corpus under ASan/UBSan
and memcheck and take tens of minutes.
Those three stay out of a lane's own run. They are swept in a batch after
several lanes have merged, and the fixes are batched with them. Keeping the
default run fast is deliberate: a suite that takes tens of minutes is a suite
nobody runs.
Note that ASan does not see a stack-lifetime bug — uninitialised stack reads
need `@valgrind`.
## Evidence ## Evidence
Read the source, do not recall it. `docs/REFERENCES.md` lists the reference Read the source, do not recall it — this repository and the reference clones
clones on this machine — Odin, SBCL, Zig, Carp, clojure-mode, CIDER, raylib and listed in `docs/REFERENCES.md`. Verify a brief's facts before building on them.
the rest — and what each one answers. A claim in these notes that came from one
of them was read out of the clone; the ones that were recalled instead have been
wrong before.
The same applies to this repository. Cite a file and a line because you opened ## Records
it. When a brief hands you a list of facts, verify them before building on them
— a brief written from a stale tree has sent a lane a full day in the wrong
direction.
## Diagnostics Keep only what the code cannot say.
Elm's shape: the source line, a caret, what the compiler understood, and the fix - `TODO.org` — one `**` heading per item under a subsystem: `TODO` a gap, `NEXT`
named. Beyond that: decided and queued, `WAIT` blocked (say on what), `CANCELLED` rejected with a
one-line reason so it is not re-proposed, `DONE` only when the decision is not
obvious from the code (two lines, what it rules out). On a merge conflict keep
both sides.
- The reason for non-obvious code goes in a comment beside it.
- `docs/BUILT.md` holds only reasoning that spans several files.
- No handoff files.
- A message is written for someone who has never used Flan and does not know its ## Reviews
history. Never "X is now Y", never "X was renamed", never our rationale. If
`defvar` no longer exists, the message says `defvar` does not exist — not that
it became something else.
- The clauses come in one order: what the compiler understood, then what
conflicts with it, then the fix — "expected i32, found string".
- Every suggestion a message prints must compile.
- An assertion about the compiler's own invariants is prefixed `internal:` and
says it is a compiler bug. A user never caused one.
## Writing Every lane gets an independent adversarial review before it merges: build and
run rather than read, measure both sides of a claimed fix, and reproduce any
User-facing prose — the README, `web/index.html`, the Emacs manual — is plain. number a lane reports.
Odin's website is the reference: declarative rather than second-person, the
concept defined before the mechanics, the code example after the prose that
frames it, and rationale given its own subsection rather than mixed in.
No aphorisms, no closing lines built for effect, no rhetorical inversions. If a
sentence's only content is its own style, cut it. This applies to reports and
commit messages as much as to documentation.
## The records
- `TODO.org` — every decision, question and known gap, one `**` heading each
under a subsystem heading, with an org keyword saying where it stands: `TODO`
for a gap, `NEXT` for what is queued, `WAIT` for what is blocked and on what,
`DONE` for what was settled, `CANCELLED` for an idea considered and rejected.
A lane records its decision here, as a few lines saying what was decided and
what it rules out — never the argument and never the measurements. On a merge
conflict in this file, keep both sides: two lanes recording two decisions is
not a conflict.
- `docs/BUILT.md` — why the parts that exist are shaped the way they are. The
largest and most load-bearing document here. Reasoning that will not fit in a
few lines goes here, and `TODO.org` carries one line pointing at it.
- `docs/handoffs/` — one report per finished work session.
- `docs/README.md` indexes all of it.
A `CANCELLED` entry is not housekeeping. An idea rejected without a record is an
idea that gets re-proposed, so the one-line reason is the whole value of it.
## The shape of the work
The author dogfoods the language in a separate project, hits friction, and
reports it. Work is dispatched as parallel lanes in isolated worktrees; every
lane is reviewed by an independent agent before it merges; the dispatching
session resolves the merges.
A review is adversarial. Verify by building and running rather than by reading,
measure both sides of a claimed fix, and say what you actually measured. A lane
that reports a number you did not reproduce is a lane with a number you should
reproduce.