Files
bdeshiandClaude Opus 5 b313b729d9 review 130 feature ideas, and delete the lists that held them
One idea at a time: definition, necessity, priority, layer, recommendation. Every
row is now shipped, scheduled, parked with a trigger, or dropped with a reason —
so both tracking files are gone rather than left as a parallel backlog.

Roughly a third already shipped. A quarter needed only a theme fragment or CSS,
including several the list assumed were features: arbitrary `theme.*` frontmatter
attributes already reach templates through Extra (verified), native lazy loading
already ships and is deliberately absent on lead figures, and in-page timelines
are a theme-defined container.

roadmap.md gains an "Order of work" — nine bodies of work in sequence, because the
sections this review added had accumulated without one. Item 0 is a decision, not
work: core sits at ~2965 of 3000 and logging alone wants the remainder, so
discover.go moves out *and* the ceiling rises with an ADR. feed.go and
web/extras.go cannot move; they are resolver cases, and three parked items now
wait on that same seam decision.

Two ADRs came out of it.

ADR-0083: the dependency rule described a practice it forbade. "Stdlib first,
always" and "usually 40 lines of stdlib" would, read literally, have argued
against all five modules here — every one is a format or algorithm somebody else
specified, and their allowlist comments say so. Surfaced when this agent proposed
hand-rolling Reed–Solomon for QR encoding. The test is now whether you can verify
it, not whether you can write it, with compute-versus-hold as the counterweight.
conventions.md and allowed-deps.txt contradicted it and were realigned.

ADR-0084: the Effect primitive said every Effect is "idempotent and re-runnable
from scratch" — true of derivatives, false of anything outbound, since a sent
message cannot be recalled. Split into artifact-producing and outbound, the latter
idempotent only against a delivery ledger, at-least-once with a dedupe key, and
ledgers in a -state directory distinct from the disposable cache. Asked for as
forward-looking design so webmentions need no redesign; recorded as a shape rather
than built, the way extensions.md records the Extension struct. Also fixed a
STATUS claiming Effects were "not buildable yet" when the derivative pass has
inhabited them since ADR-0042.

Findings that were defects rather than ideas: the Atom feed emits no <author>,
which RFC 4287 requires. HTML comments in content are published verbatim —
verified — so anything commented out is already public, and a check warning is
scheduled rather than the engine deleting authored bytes. `Page` has no Date, so a
theme cannot mark up dt-published or show an article's own date.

A frontmatter naming rule after this agent proposed `archive` alongside the
accepted `archived`: no near-homograph keys, and name the benefit rather than the
vendor.

reference/microformats-and-indieweb.md is new and is the reference asked for —
microformats2 properties and IndieWeb rel values mapped to where a theme puts
them, with spec URLs, marked scheduled. rel="me" is the highest-value lowest-cost
item in that space and needs no endpoint at all.

Four things this agent got wrong and the human caught: asserting "the engine never
fetches" from a sentence scoped to the content repo, twice; inventing a
data-sovereignty argument for an item he had filed as "a cool geeky thing", when
the raw Markdown in his git already is the sovereignty; the archive naming; and
claiming microformats could be fully implemented today.

15 files, +556/-385. No code changed. Nothing was scheduled that this agent could
not name a consumer for.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-03 16:14:52 +06:00

136 lines
10 KiB
Markdown

# Harness doc map
The docs an agent reads to build the engine. Read the one you need. Do not read them all.
This directory was `docs/` until ADR-0082 renamed it: `docs/` is reserved for documentation written for
whoever *uses* khosra, which does not exist yet. Everything here is engine- and agent-facing — a
specification, a rule, or a record — and none of it is written for an author.
| Doc | Contains | Mutability |
|---|---|---|
| `architecture.md` | The six primitives, invariants, per-primitive STATUS | Only via an ADR |
| `state.md` | What exists now: inventory, earn-it counters, latent items | Every feature |
| `decisions.md` | ADR log — one entry per load-bearing choice | Append-only. One exception: a superseded entry's **Status** line is annotated in place to name what replaced it, because a reader arriving at the older entry has no other way to learn it was replaced. Never the Decision text — that stands as history |
| `roadmap.md` | Arcs, earn-triggers, the core freeze point | When an arc completes |
| `content-model.md` | On-disk layout, frontmatter, post types, permalinks — **what the parser accepts today**, never a plan | When the disk format changes |
| `conventions.md` | Go style floor, package layout, perf and test rules | Rarely; via ADR if contested |
| `extensions.md` | Extension/plugin contract: target shape + earn gates | When earned or frozen |
| `toolchain.md` | Versions and agent-tooling contracts this was built against | When you deliberately move a version |
| `theme-contract.md` | What the engine promises a theme; the only theme-facing obligation | When the contract is extended — additively only |
| `context-economy.md` | How the agent spends context: what to read, in what form, and the floor no saving may cross | When a technique or a gate for one changes |
| `surface.md` | **Generated.** Every top-level declaration with its line — read before opening source | Never by hand; `make surface` |
Sibling folders sit **outside** `harness/` because they are storage, not working material:
`../ideas/` (parked ideas, any topic, and `exploration.md` — the catalog of engine features nobody has asked
for yet) and `../reference/` (durable facts from conversation). Write there when asked to park something;
open a file only when the human names it. Nothing sweeps them.
## Topic ownership — read before you assert
The inverse of the refresh triggers: those say what to update *after* changing code, this says what
to read *before* writing a rule — including when you are only writing an ADR or a comment about it.
Nearly always exactly one doc; if two seem to apply, the single-source rule is already broken and
that is the finding to report.
| About to assert something about… | Read first |
|---|---|
| plugins, extensions, features-as-packages, stage phases | `extensions.md` |
| a primitive, an invariant, or what is "earned" | `architecture.md` + counters in `state.md` |
| URL paths, permalinks, frontmatter, on-disk layout, post types | `content-model.md` (+ ADR-0008) |
| Go style, package layout, file/function size, test shape | `conventions.md` + `scripts/budgets.env` |
| a dependency | `scripts/allowed-deps.txt` + ADR-0007 |
| a budget or a gate | `scripts/budgets.env` + `scripts/verify.sh` |
| the untrusted boundary, comments, webmentions, form input | ADR-0003 + `extensions.md` |
| language, translation, fallback | ADR-0004 + ADR-0009 |
| deploy, containers, external services | ADR-0010 |
| whether a future feature is worth building | `ideas/exploration.md` + `roadmap.md` |
| **which list owns a piece of pending work** | four kinds, deliberately not merged: **might be built**`ideas/exploration.md` — the catalogue, plus parked and dropped items each with a trigger or a reason · **is scheduled**`roadmap.md`, whose "Order of work" says which is next · **is broken and known** → the Latent list in `state.md` · **waits on an observation**`ideas/deferred-decisions.md` "Triggers — the one list". Merging them would flatten four levels of authority and make pending work expensive to ignore, which is the property that keeps `ideas/` safe to keep |
| what to build next | the harness first (`CLAUDE.md` §1 read order) and `git log` for what landed, **then** `.scratch/continue.md` for the continuation point and `roadmap.md` for the arc. The handoff is temporary and ungated: check anything it calls pending with `git log -- <the path it names>` before planning from it |
| how the harness works — a gate, counter, budget, the loop | `HARNESS.md` + `scripts/verify.sh` + `CLAUDE.md` |
| what one commit contains, and when one happens | `conventions.md` "Git" (shape) + `CLAUDE.md` §4 (cadence, ADR-0052) |
| how to read, search, or report without wasting context | `context-economy.md` (+ ADR-0053) |
| a tool version, or why agent tooling stopped working | `toolchain.md` |
| templates, layout, presentation, what a theme can rely on | `theme-contract.md` (+ ADR-0019, ADR-0023) |
## Single-source rule
Each fact lives in exactly one doc. Need it elsewhere? Link. This binds ADRs too: an ADR restating
a rule an owning doc already carries is a duplicate, not a decision — delete it and amend the owner.
Values that have drifted before, and their one home. Everywhere else names the concept and points
here; nothing else may state the value:
| Fact | Sole home |
|---|---|
| Earn-it thresholds (transforms, routes, views, extensions) | the counters table in `state.md` |
| LOC ceilings, size warnings, dependency cap, the `CLAUDE.md` ceiling | `scripts/budgets.env` |
| The permalink path shape | `content-model.md` (decision recorded in ADR-0008) |
| Which language is at the root, and the prefix form | ADR-0009 |
| The leaf/trunk definition | `architecture.md` invariant 7 |
| The sovereignty test | `roadmap.md` Governors |
| Package layout and the forbidden package names | `conventions.md` |
| What exists in the code right now | `state.md` inventory |
| What un-defers a deferred decision | the Triggers table in `ideas/deferred-decisions.md` |
A value restated in two places is not redundancy for safety; it is a future contradiction waiting for
whichever copy gets edited alone.
`state.md` is the only doc describing the present; the rest describe rules, shapes, or intentions.
When code and `state.md` disagree, the code wins and `state.md` is wrong.
## Refresh triggers
Update in the Document step of the change that caused them. Not later.
| Change | Update |
|---|---|
| Any code change at all | `state.md` inventory — in the same commit, which is what `verify.sh` compares (ADR-0057) |
| New transform, route, view, extension, or dependency | the counters table in `state.md` |
| A choice expensive to reverse | new ADR in `decisions.md` |
| A primitive becomes real (earned) | STATUS line in `architecture.md` + counters |
| New frontmatter field, post type, or path shape | `content-model.md` |
| New dependency approved | `scripts/allowed-deps.txt` + ADR |
| Budget raised | `scripts/budgets.env` + ADR — once the first feature has shipped. While the harness is still being tuned, edit in place. |
| A latent item fixed | remove from the Latent list in `state.md` |
| A planned item completed | **after** the commit lands, delete it from `.scratch/continue.md` and note anything learned that changes a later one. Never during Document: a handoff written mid-change describes the plan, and an amend moves the commit under it — which is how one was written at 01:06 saying a trim awaited a yes that the 01:12 commit had already done |
| Arc finished | `roadmap.md` + a retro line in `state.md` |
| Catalog item accepted or rejected | verdict line in `ideas/exploration.md` |
| `CLAUDE.md`, `scripts/` or `.claude/` changed | `HARNESS.md`, same change. Enforced by `verify.sh`. |
| A tool version deliberately moved, or a new external contract relied on | `toolchain.md` |
| The theme contract extended, or embedded templates changed | `theme-contract.md`, same change. Enforced by `verify.sh`. |
| A request spans engine and theme | contract extension here + a written note of the theme's part; never the theme itself |
| A new gate, counter, or budget added | `HARNESS.md` "Why the pieces exist" + a row in one of these tables |
| A top-level declaration added, renamed or moved | nothing by hand — `make surface`, which `verify.sh` then compares |
| A rule, value, name or path changed | grep the repo for the old form; every doc naming the concept, same change |
| The disk contract changed | `content-model.md` + `testdata/` fixtures + a written migration step for the site root, which the engine repo cannot touch |
| A doc or ADR mandates what a change made optional | supersede the ADR; do not reword it in place |
| A request reversed a recorded decision | new ADR, or supersede the old one — the request does not win by being newer |
| A request exceeded a convention on purpose | note the deviation where the convention lives |
| An idea floated, not built now | a file in `../ideas/` + its index line. Adopted later: `Status: adopted → <where>` |
| A fact worth keeping surfaced in conversation | a file in `../reference/` + its index line, stating how it was established |
## Staleness
`/refresh-docs` reconciles docs against code and reports drift. Run it after a burst of work,
before a new arc, and any time a doc surprises you.
## House style
Present tense. Terse. Written for a reader who has forgotten everything, including their own
reasoning. No changelog prose, no "recently we…", no preamble. Delete a line before rewriting it.
A doc needing a table of contents is too long.
## Compression contract
Shortening a harness doc removes **words, never instructions**. Same rules, gates, thresholds,
triggers and table rows before and after; the agent must act identically. Redundancy between
`CLAUDE.md` and `SKILL.md` is deliberate — the constitution is always loaded, the skill is not —
and is not duplication to be collapsed.
Deleting a rule, adding one, or narrowing one is a rule change: it needs its own decision and its
own reason, and it never rides along in a compression pass.
Verify before reporting a saving: table rows, headings, list items and checklist boxes must match
the pre-pass file (`git diff --stat`, or a snapshot if the change is uncommitted). Report word count,
not lines — reflowing prose shrinks lines without saving anything.