CLAUDE.md keeps only the rules the code cannot teach
This commit is contained in:
parent
3a2837c278
commit
aca3edff41
143
CLAUDE.md
143
CLAUDE.md
@ -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.
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user