diff --git a/.gitignore b/.gitignore index cb7b4be..772c0b5 100644 --- a/.gitignore +++ b/.gitignore @@ -50,7 +50,18 @@ old-ocaml/ /sand.html /sand.js /sand.wasm + +# The agent harness: its settings, its transcripts and the worktrees it +# registers all live here, and none of them are this repository's business. .claude/ + +# A stale unix socket left behind by `flan dev`. The daemon writes one beside +# the program it is serving and unlinks it on a clean exit; a killed daemon +# does not, and the leftover is a socket, not a file worth keeping. +.flan-dev.sock + +# Hand-run scratch: a `probe` executable and the C it was compiled from, from +# poking at codegen by hand rather than through a test. probe probe.c @@ -68,5 +79,10 @@ test/web-files-out.txt # Python bytecode from the tools directory __pycache__/ *.pyc + +# Two more hand-run leftovers: a shared object built beside a form experiment, +# and the history directory a spike driver writes when it is run from the +# source tree. Anchored where they appear, and nothing in the build makes +# either one. /forms.so _hist/ diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 0000000..7ef794a --- /dev/null +++ b/docs/README.md @@ -0,0 +1,61 @@ +# What is in here, and what is still true + +These are the documents that are written once and read occasionally: the reasons behind the code, the +reports from finished investigations, and the record of individual work sessions. The documents that are +edited every day stay at the repository root, because source comments cite them by bare filename from +dozens of places and a path that moves is a path that rots. So `plan.org`, `NEXT.md`, `spec-memory.md` +and `spec-conditions.md` are one directory up, and everything here points back at them. + +A note on how to read the citations below: a document in this directory that says `plan.org` means the +one at the repository root. Nothing in `docs/` is named for a file at the root, so there is no ambiguity, +and rewriting a hundred prose mentions into `../plan.org` would have cost more in readability than it +bought in precision. + +## If you have thirty seconds + +Read **`BUILT.md`**. It is by far the largest document here and it is the one that pays: it holds the +reason behind every part of the compiler that exists, from why nothing is ever `dlclose`d to why the +printer is a compile-time walk over a type rather than a runtime function. It is current, it is +maintained, and deleting it would mean deriving all of it again. If you want to know why a thing is the +shape it is, the answer is in here. + +After that, **`../NEXT.md`** at the root for what is actually in flight, and **`REFERENCES.md`** here for +where the evidence comes from — the reference clones on this machine, what each one answers, and the +standing rule that a claim in these notes was read out of a clone rather than recalled. + +## The current documents + +| File | What it is | +|---|---| +| `BUILT.md` | Why the parts that exist are shaped the way they are. The longest and the most load-bearing document in the repository. **Current.** | +| `DISCUSS.md` | Open questions, raised and deliberately not answered. Nothing in it is a decision or a task; entries that have since been answered say so and point at where the answer landed. **Current**, though it is half archive by now. | +| `PORTING.md` | What the author's game, `siam-farmer`, needs from Flan that Flan does not have yet, measured against the code that exists rather than against a plan. It is the requirements document the language is actually steering by. **Current.** | +| `REFERENCES.md` | The reference clones under `~/Repositories`, what each one is consulted for, and the specific files and lines already cited from them. **Current.** | + +## The reports + +| File | What it is | +|---|---| +| `SPIKE-GENERICS.md` | Milestone 5's parametric polymorphism, run early and out of order as a spike. The spike succeeded and generics landed, so this is the report of finished work rather than a live plan — but its findings about where the cost falls are still the reason the implementation looks the way it does. **Historical, findings still stand.** | +| `overview.md` | The first brainstorm, from before the language had S-expressions. It says in its own first line that it is superseded and no longer accurate. Kept for history only; its table of what changed is the only part worth reading. **Superseded.** | + +## `handoffs/` + +One report per work session, each written by whoever held the branch at the time. They are the +operational record: what was attempted, what was measured, what was decided without being able to ask, +and what was left open for the next lane. They are all historical the moment they are written — a handoff +describes a session that has ended — but they are cited by name from source comments and from `NEXT.md`, +because the reasoning behind a guard or a calling convention is often only written down once and this is +where it was written. + +Six of them are the hand-written x86-64 backend, read in the order the work happened: +`HANDOFF-x86-rt.md` set the remaining-items list that the four after it close, `HANDOFF-x86-redef.md` +built the redefinition emitter, `HANDOFF-x86-aggregates.md` took that across the struct boundary, +`HANDOFF-x86-guards.md` settled the two guards nothing reaches, `HANDOFF-x86-debug.md` added debug +information, and `HANDOFF-x86-cost.md` measured what the backend costs and set the survey running on its +own so a refusal cannot sit unnoticed again. + +The other three sessions are unrelated to each other. `HANDOFF-arith.md` is why a divide by zero is a condition +rather than a `SIGFPE`. `HANDOFF-raylib-ports.md` is the running record of the last two raylib example +ports, whose lasting findings were folded into `PORTING.md`. `HANDOFF-devtest-noise.md` is the linker +error `dune test` used to print on every run. `HANDOFF-tidy.md` is this reorganisation. diff --git a/docs/handoffs/HANDOFF-tidy.md b/docs/handoffs/HANDOFF-tidy.md index 15d9142..6149154 100644 --- a/docs/handoffs/HANDOFF-tidy.md +++ b/docs/handoffs/HANDOFF-tidy.md @@ -22,4 +22,86 @@ newcomer at that. This is the plan and, below it, what actually happened. ## What happened -(filled in as the work lands) +**The moves.** Fifteen files, all with `git mv` so `git log --follow` still +reaches their history. Nothing else moved. + +**The citations.** 238 of them across 52 files, rewritten by zone. The zones +matter and a repository-wide substitution would have corrupted two of them: + +| Citing file lives in | `DISCUSS.md` and its siblings | `HANDOFF-*.md` | +|---|---|---| +| the root, `lib/`, `test/`, `emacs/`, `spike/`, `examples/`, `vendor/` | `docs/DISCUSS.md` | `docs/handoffs/HANDOFF-x.md` | +| `docs/` | unchanged — they are siblings | `handoffs/HANDOFF-x.md` | +| `docs/handoffs/` | `../DISCUSS.md` | unchanged — siblings again | + +Most of the citations are prose inside a source comment rather than a link; +there is not a single markdown link among the fifteen moved documents. So the +rewrite is a rewrite of comments, and in `lib/x86.ml`, `lib/build.ml` and +`test/test_reload.ml` — which another lane is editing at the same time — every +touched line is a comment line. + +**The verification.** Grep cannot tell you a rewrite is finished, because a grep +for `DISCUSS.md` matches `docs/DISCUSS.md` too. So the check resolves instead: +every path-shaped citation in the repository is looked up relative to the file +that wrote it and relative to the root, and anything that resolves to neither is +reported. 817 citations checked. The only failures are seven mentions of +`HANDOFF-f1.md`, `HANDOFF-f2.md` and `HANDOFF-f3.md` in `../../NEXT.md`, which were +already dangling before this work — the prose around each one says the file was +deleted — and one false positive where the pattern caught `"$root/NEXT.md"` out +of a shell variable. + +### The judgement calls + +**`MY-NOTES.org` and `conditions.org` stay at the root.** `MY-NOTES.org` is the +author's scratch — questions to himself about the standard library, in the +second person. `conditions.org` is a live cheatsheet, not a report, and it is +the entry point to `conditions-play.flan` beside it. Neither is a document that +belongs in a directory of finished reports, and personal files are best left +where their owner put them. + +**`conditions-play.flan` stays at the root.** The brief said to move it to +`spike/` if nothing referenced it. Three things do: `conditions.org:5` tells the +reader to run it, `NEXT.md:1306` lists it as the program to poke conditions +with, and `.gitignore` has an anchored `/conditions-play` for the executable it +builds to. It is also not shaped like the rest of `spike/`, which is four +self-contained experiment directories with their own runners, not a home for a +loose `.flan` file. It is a demonstration that belongs next to the cheatsheet +that points at it. + +**`.flan-dev.sock` is not in this worktree.** The stale one is in the author's +main checkout, which a worktree-isolated lane cannot reach. The ignore pattern +is added here so the next one never shows up in `git status`; the existing +socket is the author's to remove. + +**`.gitignore`.** Five entries at the bottom of the file — `.claude/`, `probe`, +`probe.c`, `/forms.so`, `_hist/` — were uncommented stragglers in a file where +everything else explains itself. They are grouped and explained now, and +`.flan-dev.sock` is added. No pattern was removed or changed in meaning. + +### Verification + +- `dune build --root .` exits 0. +- `dune test --root . --force` reports 232 checks, 0 failures. +- `spike/x86/survey.sh`, run detached, reports 103 MATCH / 0 DIFFER / 0 REFUSED. + +### The branch clutter — reported, not acted on + +`git branch --list 'worktree-agent-*'` returns **113** branches. **111** are +fully merged into `dev-loop`. **89** of them have a worktree currently +registered under `.claude/worktrees/`, and deleting one of those would break the +harness. The two unmerged branches are the two lanes running right now. + +That leaves **24** branches that are both merged and have no live worktree, and +those are the only ones safe to delete: + +```sh +comm -23 \ + <(git branch --merged dev-loop --format='%(refname:short)' --list 'worktree-agent-*' | sort) \ + <(git worktree list --porcelain | sed -n 's|^branch refs/heads/||p' | sort) \ + | xargs -r git branch -d +``` + +`git branch -d` rather than `-D` on purpose: it refuses anything that turns out +not to be merged after all. The 89 with live worktrees want +`git worktree prune` and a decision about the directories first, which is the +author's call and not a cleanup to run blind.