Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
41cc160
feat(lint): 1/7 — prose budget ratchet and one home for rationale
uipreliga Sep 15, 2026
5801474
docs: 2/7 — move timing and permissions rationale into .claude/notes
uipreliga Sep 15, 2026
4943b72
docs: 3/7 — move agent-adapter rationale into .claude/notes
uipreliga Sep 15, 2026
d72ac10
docs: 4/7 — move orchestration rationale into .claude/notes
uipreliga Sep 15, 2026
fcad6ae
docs: 5/7 — move isolation, sandbox and CLI rationale into .claude/notes
uipreliga Sep 15, 2026
0feacac
docs: 6/7 — move criteria, routing and judging rationale into .claude…
uipreliga Sep 15, 2026
5aa3ded
docs: 7/7 — move reporting, harbor and telemetry rationale into .clau…
uipreliga Sep 15, 2026
ae47817
test(lint): guard the Rationale pointer's placement, not just its target
uipreliga Sep 15, 2026
a2d8e1d
docs: restore the self-containment clause on reports_html
uipreliga Sep 15, 2026
ab7bc49
docs: record the four harness gaps the prose run did not close
uipreliga Sep 15, 2026
e03a699
fix(docs): restore contracts the prose refactor lost or misstated
uipreliga Sep 15, 2026
279e824
fix(docs): restore the qualifier that made each absolute true
uipreliga Sep 15, 2026
4adca82
fix(docs): stop asserting a tmpfs mask that no longer exists
uipreliga Sep 15, 2026
06b9d1e
feat(lint): replace the prose baseline with two self-adjusting rules
uipreliga Sep 15, 2026
b72e663
docs: update CLAUDE.md with communication style and development comma…
uipreliga Sep 15, 2026
0713f6f
fix(lint): stop the prose budget penalising usage examples
uipreliga Sep 16, 2026
97ced3b
docs(notes): cut the duplicated catalogue and the unbuilt design
uipreliga Sep 16, 2026
aeb1de4
docs: slim CLAUDE.md, and drop a directory that never existed
uipreliga Sep 16, 2026
4941681
docs(harbor): apply the branch's prose rules to the bind-mount rewrite
uipreliga Sep 16, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
128 changes: 0 additions & 128 deletions .claude/architecture-notes.md

This file was deleted.

43 changes: 43 additions & 0 deletions .claude/harness-candidates.md
Original file line number Diff line number Diff line change
Expand Up @@ -873,3 +873,46 @@ re-derive from scratch.
timing work (the function is zero lines of its diff) and not a guardrail
candidate — a small real bug needing its own change. Caught in: the
turn-timing consolidation final review (gpt-5.6-sol).

- [ ] **A comment line that opens mid-sentence directly after one that ended.**
The residue of a block replacement whose anchor matched the wrong line: the
tail of the replaced prose survives as a severed fragment. The exact-form half
of this — a `Rationale:` pointer that is not the last line of its block — was
PROMOTED in the prose-mass-reduction run and now ships as
`prose_budget.check_pointer_placement`. What remains is the general case,
where no pointer is involved, and it is heuristic: a legitimately wrapped
sentence looks identical to a severed one, so it needs an allowlist (a
continuation opening with a backtick, a quote, or a list marker is usually
fine). ~30 min plus the false-positive triage. Caught in: prose mass
reduction, Phases 4-7 review.

- [ ] **Two `.claude/notes/` sections covering ONE topic under different
headings.** The single-home rule is the load-bearing invariant of the notes
tree and nothing enforces it. `check_pointers` proves a pointer resolves;
nothing proves the topic is not also argued three files away. It bit every
phase of the prose-mass-reduction run, including once against a file the
phase never opened (`reporting.md` vs `orchestration.md` on
`nothing_was_measured`). Needs a similarity measure over section bodies —
shared rare tokens, or a shared symbol name appearing as the subject of two
headings — so it is real work rather than a regex. Deferred on cost, not on
value: this is the highest-value unbuilt guard in the notes design. Caught
in: prose mass reduction, all phases.

- [ ] **A `Rationale:` pointer that resolves to a heading which does not hold
the rationale that left the site.** The weaker sibling of the above and the
same shape of miss: the gate goes green while the reader arrives somewhere
unhelpful. Five instances in Phase 5 alone, all fixed by hand. Probably not
mechanizable without a semantic check, but worth recording as a known blind
spot of `check_pointers` so nobody reads its green as "the pointers are
good". Caught in: prose mass reduction, Phases 5-6 review.

- [ ] **A criterion-class first docstring line changing without
`make plugin-reference` in the same commit.** CE033 already diffs the
generated `plugins/coder-eval/reference/criteria.md`, so drift IS caught —
but only for classes that reach the generated file, and only as "the
generated file is stale" rather than "you edited a generated surface". A
commit-scoped guard would name the cause. Deferred because the lint harness
has no access to a commit-scoped diff today; the ad-hoc version
(AST-comparing every `ClassDef` first line against a base ref) was written
and used throughout Phase 6 and is the thing to promote if that access
appears. Caught in: prose mass reduction, Phase 6.
66 changes: 66 additions & 0 deletions .claude/notes/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
# Architecture notes

Design rationale moved out of `CLAUDE.md` and out of `src/` docstrings, so both stay
working references rather than changelogs. Nothing here is deleted history.

**These notes are NOT auto-loaded into context.** Read the file for a subsystem when you
touch it — each entry explains *why* the design is shaped the way it is, and most of them
are written around a specific shipped defect.

Authoritative sources, when a note and the code disagree: the code wins, then the lint
rule docstrings in `tests/lint/rules/`, then the guides under `docs/`.

## Contents

- [agents.md](agents.md) — agent adapters, the turn lifecycle, token reconciliation, harness parity
- [contracts.md](contracts.md) — criteria, datasets, aggregation, judging
- [isolation.md](isolation.md) — the docker driver, the sandbox, detached grading
- [orchestration.md](orchestration.md) — config merge, resume, early stop, execute vs. run
- [permissions.md](permissions.md) — the chmod window and the reference anti-cheat
- [persistence.md](persistence.md) — atomic writes and judge persistence
- [reporting.md](reporting.md) — reports, pricing, harbor, telemetry, the plugin and Action
- [timing.md](timing.md) — the turn clock and the single subtraction seam

## What belongs here, and what stays in the source

Every paragraph in a docstring or comment sorts into exactly one bucket:

| Bucket | Test | Action |
|---|---|---|
| **CONTRACT** | A caller must know it to call correctly: what it returns, what it mutates, what it raises, an invariant they must maintain. | **Keep** in the source, compressed to its claim. |
| **HAZARD** | A future editor breaks something if they do not know it. Reads as "do not X without Y" — a coupling between two distant places. | **Keep** in the source, 1–3 lines, stating the coupling only. |
| **RATIONALE** | Why the design is this shape; what was considered and cut; what defect motivated it; what was verified experimentally. | **Move** here, to `<subsystem>.md`. |
| **HISTORY** | "used to", "no longer", "previously", "an earlier revision", "shipped once as". | **Delete.** Git holds it. |
| **CROSS-MODULE CLAIM** | Asserts a current property of a different module or harness. | **Delete**, replaced by a link to that module's SSOT. |

## The pointer line

Moved rationale leaves exactly one line behind, at the end of the docstring or comment
block it came from:

```
Rationale: .claude/notes/timing.md § subtract_tool_time
```

Path relative to the repo root, then `§`, then the target `##` heading text verbatim.
There is no other accepted form: `tests/lint/prose_budget.py` parses this one and fails
`make docs-budget` when the file or the heading does not exist.

## The prose budget is one number, not a lint rule

`make docs-budget` reports the standing total and fails when it grows. It is deliberately
**not** a `CE` rule: `tests/lint/rules/` polices per-pattern invariants one AST at a time,
while this is a single whole-tree total. Making it a rule would mean a rule class, a rule
test and a catalogue entry to enforce one integer — enlarging the harness the budget
exists to shrink. Do not "fix" this by promoting it.

Nothing here states how many `CE` rules exist. `tests/lint/rules/` owns that count, and a
number written down anywhere else is a second declaration that will be wrong.

## Where a CE rule's rationale lives

Each rule's authoritative rationale is its own module docstring under
`tests/lint/rules/` — or, for the doc-surface and whole-tree rules, the corresponding
`@pytest.mark.lint` class in `tests/test_custom_lint.py`. Read that before editing,
suppressing or widening a rule. No prose summary is kept here: a second copy is a second
declaration, and it is the one that goes stale.
Loading
Loading