rename docs/ to harness/, and reserve docs/ for the reader
docs/content-model.md opens with "Engine specification". It is also where the rule lives that a leading underscore makes a file unaddressable — and the human who owns this site did not know that rule, because nothing in this repository is addressed to an author. Twelve documents named docs/ while being exclusively about building the parser is a signpost pointing at the wrong room. Naming the directory for its audience makes the gap visible instead of hiding it. docs/ is now reserved and deliberately absent: an empty docs/ is an honest statement that end-user documentation does not exist, where docs/ full of parser specs was a claim that it did. HARNESS.md stays at the root. Root holds the three entry points — README.md for a human, CLAUDE.md for an agent, HARNESS.md for whoever maintains the machine — and harness/README.md is the map of the directory, so moving the guide inside would have collided with it for nothing. Mechanical and wide: 100 path references across 24 files. Every verify.sh gate that names a doc by path, the directory lists the dangling-path and ADR-number gates scan, surface.sh's output target, the Makefile, CLAUDE.md's read order, the skill, four commands, and two Go package comments. A first pass with a shell loop silently edited only four files and the rest still said docs/; the fix was to write the file list out and check the remaining count was zero rather than trust the loop's exit status. No rule, threshold, gate or obligation moved — this is a rename, and the gates demonstrated it twice: they stayed green on the new paths, and the ADR-number gate caught ADR-0082 before the entry existed. Deferred, both on the human's call: the end-user documentation site itself, which wants its own decision about where it lives and whether its claims are gated; and moving examples/ under docs/, since demo-site is a live site root that verify.sh, the coverage test and make demo all point at, and moving it would couple a rename to a design nobody has made. 31 files, +146/-106. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
+25
-22
@@ -4,9 +4,12 @@ Scaffolding that makes an agent build `khosra` the way you want: minimally, surg
|
||||
before code, docs that stay true.
|
||||
|
||||
`README.md` is a two-line signpost — human here, agent to `CLAUDE.md`. `CLAUDE.md` is the
|
||||
constitution (always loaded). `docs/` is what the agent needs to build the
|
||||
engine — anything in it may be pulled into context on demand. `ideas/` and `reference/` sit outside
|
||||
`docs/` deliberately: storage, opened only when you name a file, swept by nothing.
|
||||
constitution (always loaded). `harness/` is what the agent needs to build the
|
||||
engine — anything in it may be pulled into context on demand. It is named for its audience, not its
|
||||
format: `docs/` is reserved for documentation written for whoever *uses* khosra, and is absent because
|
||||
that does not exist yet (ADR-0082). An empty `docs/` says so honestly; `docs/` full of parser
|
||||
specifications said the opposite, and cost its own author a rule he did not know was written down. `ideas/` and `reference/` sit outside
|
||||
`harness/` deliberately: storage, opened only when you name a file, swept by nothing.
|
||||
`.claude/` holds the feature-loop skill (`skills/feature-loop/`), the commands, and `launch.json`.
|
||||
`scripts/` holds the gate. `.scratch/continue.md` is a **temporary** handoff — uncommitted, ungated,
|
||||
discardable — holding the continuation point and the findings worth carrying that no doc owns. It is read
|
||||
@@ -37,7 +40,7 @@ Occasional maintenance, by you:
|
||||
|
||||
- "Park this" → the agent writes `ideas/<slug>.md`, resumable cold, and indexes it. Name the file
|
||||
later to pick the thread up; it reads these only when named. `ideas/exploration.md` is the same idea for
|
||||
engine features nobody has asked for — a catalog, deliberately outside `docs/` so it adds no weight to the
|
||||
engine features nobody has asked for — a catalog, deliberately outside `harness/` so it adds no weight to the
|
||||
working set.
|
||||
- `/audit` every ~5 features — finds abstractions that never earned their keep.
|
||||
- `/invariants` at arc boundaries, before a freeze, before the first deploy — checks the nine
|
||||
@@ -54,7 +57,7 @@ split the difference into a compromise nobody picked.
|
||||
|
||||
**Three surfaces, one of them yours to edit here.** Engine source lives in this repo; content lives in
|
||||
the site root (ADR-0011); the theme is a third surface with its own owner (ADR-0023). A request that spans
|
||||
engine and theme produces a *contract extension* in `docs/theme-contract.md` plus a note of what the theme
|
||||
engine and theme produces a *contract extension* in `harness/theme-contract.md` plus a note of what the theme
|
||||
must do — not the theme. `verify.sh` fails if the embedded reference theme changes without the contract doc
|
||||
changing, because in practice those two drift together — and it fails on a `<script>` tag in that theme,
|
||||
because a reference theme that grows taste stops being a reference (ADR-0026).
|
||||
@@ -68,7 +71,7 @@ without a case there is a feature the demo does not show, and the build says so
|
||||
a site root and there is nothing else to run.
|
||||
|
||||
**The agent names the layer as well as the primitive.** Content on disk, engine, theme, browser — and it builds
|
||||
at the outermost layer that can do the job (`CLAUDE.md` §2, `docs/architecture.md`). This exists because a whole
|
||||
at the outermost layer that can do the job (`CLAUDE.md` §2, `harness/architecture.md`). This exists because a whole
|
||||
feature was built at the wrong one: widow prevention as a Markdown transform that inserted a non-breaking space
|
||||
into an author's prose. It worked and it had tests; `text-wrap: pretty` does it better with no bytes in the
|
||||
content, so the feature was deleted (ADR-0045). If a feature only rearranges how something looks, expect the
|
||||
@@ -81,9 +84,9 @@ history belongs, not here. Read a core raise as evidence something belongs in `i
|
||||
it as evidence the number was small.
|
||||
|
||||
**Context is a budget, and parts of it are mechanical.** The limit on this project is how much
|
||||
work fits in a session, so `docs/context-economy.md` holds the reading, searching and reporting
|
||||
work fits in a session, so `harness/context-economy.md` holds the reading, searching and reporting
|
||||
disciplines — read the compressed form first, batch calls, script anything repeatable, never pay twice
|
||||
for the same bytes (ADR-0053). These are enforced rather than trusted: `docs/surface.md` is
|
||||
for the same bytes (ADR-0053). These are enforced rather than trusted: `harness/surface.md` is
|
||||
regenerated and staged by the pre-commit hook and independently compared by `verify.sh`, so the map of
|
||||
the code cannot mislead — an order of magnitude smaller than the source it stands for — and no one has to
|
||||
remember to run it;
|
||||
@@ -125,23 +128,23 @@ wanting to emit HTML still renders a theme template instead (ADR-0036).
|
||||
In order, cheapest first:
|
||||
|
||||
1. `./scripts/verify.sh` — one command, tells you whether the thing is still coherent and whether
|
||||
`docs/state.md` has fallen behind the code.
|
||||
2. `docs/state.md` — what exists, the earn-it counters, the latent list. This is the only doc that
|
||||
`harness/state.md` has fallen behind the code.
|
||||
2. `harness/state.md` — what exists, the earn-it counters, the latent list. This is the only doc that
|
||||
describes the present, and `verify.sh` compares its last commit against the last `.go` one rather than
|
||||
trusting a sha written by hand (ADR-0057). Its companion `docs/surface.md` is generated:
|
||||
trusting a sha written by hand (ADR-0057). Its companion `harness/surface.md` is generated:
|
||||
every declaration and its line, so you can find your way around without opening anything.
|
||||
3. `git log --oneline` — one revertible unit per commit, each body saying *why* (`conventions.md`). This is the
|
||||
real map of how the code got here.
|
||||
4. `/refresh-docs` — reconciles every doc against the actual code and reports drift, which is exactly the
|
||||
question you have after a year.
|
||||
5. `docs/decisions.md` — the ADR log, when you hit something and think "why on earth is it like this".
|
||||
5. `harness/decisions.md` — the ADR log, when you hit something and think "why on earth is it like this".
|
||||
Each entry names the observation that would overturn it, so you can tell a stale decision from a
|
||||
deliberate one.
|
||||
6. `docs/toolchain.md` — if something is broken rather than merely unfamiliar. It records what this was
|
||||
6. `harness/toolchain.md` — if something is broken rather than merely unfamiliar. It records what this was
|
||||
built against and which agent-tooling contracts it assumes, so a tooling change is diagnosable instead
|
||||
of looking like a harness bug.
|
||||
|
||||
Then `docs/README.md` for whichever topic you are actually here for.
|
||||
Then `harness/README.md` for whichever topic you are actually here for.
|
||||
|
||||
## Why the pieces exist
|
||||
|
||||
@@ -150,7 +153,7 @@ empty (ADR-0070). Four counters had to be re-scoped the first time anything test
|
||||
sentence about what had been wrongly included — so the sentence is now required up front. A counter that
|
||||
cannot name an exclusion is measuring a symptom.
|
||||
|
||||
**Counters in `docs/state.md`** turn "no abstraction before its second use" into arithmetic. Every
|
||||
**Counters in `harness/state.md`** turn "no abstraction before its second use" into arithmetic. Every
|
||||
threshold lives in that one table and nowhere else. The agent cannot argue a pipeline into existence
|
||||
one transform early — it writes the next one inline and lets the count force the extraction. Most
|
||||
load-bearing mechanism here, and the one with least machine enforcement, which is why `verify.sh`
|
||||
@@ -183,7 +186,7 @@ is the engine's own job rather than the gate's. The gate skips `ideas/`, `refere
|
||||
diffed, the theme contract and this file are coupled to what they describe. `.scratch/continue.md` can have
|
||||
none of that: it is gitignored, so there is no commit to compare it against. Two things stand in for the
|
||||
gate it cannot have — it holds the plan and the carried findings but never what landed, and the read order
|
||||
puts `git log` first with the handoff read against it (`docs/README.md`). The one check that *is* mechanical
|
||||
puts `git log` first with the handoff read against it (`harness/README.md`). The one check that *is* mechanical
|
||||
now runs: a `.scratch/` path named in a doc must exist, guarded on the directory being present so a fresh
|
||||
clone with no handoff still passes. A handoff that recorded what landed was believed for a whole session —
|
||||
it said a doc trim awaited a yes while the commit being amended around it had already done the trim.
|
||||
@@ -217,7 +220,7 @@ Softer signals stay advisory: `fmt.Errorf` without `%w`, nesting past 4, exporte
|
||||
and `any` in an **exported** signature — only exported, because ADR-0002 mandates an open page object,
|
||||
so unexported code reading frontmatter takes `any` legitimately and forever.
|
||||
|
||||
**STATUS markers in `docs/architecture.md`** give the target shape *and* what is legal today, so
|
||||
**STATUS markers in `harness/architecture.md`** give the target shape *and* what is legal today, so
|
||||
the agent can read the endgame without building toward it. They are the only markers of that kind left:
|
||||
`content-model.md`'s `[spec]` sections were deleted rather than given a stricter "do not build from this"
|
||||
rule, because a marker inside a doc the agent already has open still gets read. Those shapes moved to
|
||||
@@ -243,30 +246,30 @@ that describe it, in the same change.**
|
||||
`internal/ext/…`, and `verify.sh` states that as one rule rather than a list of the pairs that happen to
|
||||
exist today (ADR-0069) — so a core package added next month cannot quietly import a feature. A feature
|
||||
importing its sibling fails the same rule.
|
||||
- `verify.sh` fails when a `.go` file changes without `docs/state.md` changing, warns when `state.md`'s last
|
||||
- `verify.sh` fails when a `.go` file changes without `harness/state.md` changing, warns when `state.md`'s last
|
||||
commit is older than the last `.go` one — the two together mean the doc ships inside the change, never in a
|
||||
commit trailing it (ADR-0057) — and fails when `cmd/` or
|
||||
`internal/` code changes without a `_test.go` changing — behaviour ships with a test. A comment-only or
|
||||
`gofmt`-only diff is exempt: it ships no behaviour, and failing it would only teach you `--no-verify`.
|
||||
- The gate is not optional. `scripts/hooks/pre-commit` runs it on every commit; enable once per clone
|
||||
with `git config core.hooksPath scripts/hooks`. `--no-verify` bypasses it, and the commit body should
|
||||
say why. The hook also regenerates `docs/surface.md` and stages it, so a generated file is never
|
||||
say why. The hook also regenerates `harness/surface.md` and stages it, so a generated file is never
|
||||
something you have to remember — and it refuses a commit with unstaged `.go` changes, because what it
|
||||
generated describes the working tree rather than what you are committing.
|
||||
- `docs/decisions.md` registers every ADR number ever used, entries and withdrawals alike, so a citation
|
||||
- `harness/decisions.md` registers every ADR number ever used, entries and withdrawals alike, so a citation
|
||||
can resolve to a decision or to a deferral but never to nothing.
|
||||
- `./scripts/verify.sh --list` names every gate that exists. A doc claiming enforcement is checkable
|
||||
against it in one command, and `/refresh-docs` checks it in both directions — a claimed gate that is
|
||||
missing, and a real gate nothing explains. Asserting a mechanism before it exists is the drift that
|
||||
reads as enforcement and is decoration; `CLAUDE.md` rule 8 forbids it.
|
||||
- `docs/README.md` carries three tables: topic → doc to **read before asserting a rule**, change →
|
||||
- `harness/README.md` carries three tables: topic → doc to **read before asserting a rule**, change →
|
||||
doc to **update after making one**, and an authority table naming the one home of every value.
|
||||
A new mechanism adds a row; nothing outside a value's home may restate it. A number written twice
|
||||
eventually disagrees with itself.
|
||||
|
||||
## Open
|
||||
|
||||
- No ADR gate blocks Arc 1. One question remains in `docs/state.md`: the language suffix on the first
|
||||
- No ADR gate blocks Arc 1. One question remains in `harness/state.md`: the language suffix on the first
|
||||
content file.
|
||||
- `go.mod` does not exist yet — `go mod init` belongs to the first feature, and the module path is
|
||||
still unchosen.
|
||||
|
||||
Reference in New Issue
Block a user