CLAUDE.md · git:20260905.1f8108c · 2026-09-05 · sha256 8d366b1e0e072237

CLAUDE.md git:20260905.1f8108cA

Immutable. This exact content is served forever at /api/v1/blob/8d366b1e0e072237.

# CLAUDE.md — operating DeepReason

DeepReason is a Popperian reasoning harness: it drives a provider model
(currently glm-5.2 on Ollama Cloud) through conjecture–criticism cycles
over an append-only, replay-verifiable record. Everything meaningful is
TYPED — stops, denials, refusals, capability lifecycles — and the record
is the only admissible evidence about what a run did. Model prose is
never evidence; `log.jsonl`, `objects/`, `progress.jsonl`,
`run-status.json`, `REPLAY_VALIDATION.json`, and `verify_root` are.

## Which workflow to use

Both families now begin with a MAP PREFLIGHT: resolve the work to
`DR-SUB-`/`DR-CON-`/`DR-SEAM-` ids from `docs/map/INDEX.md`, read the seam
before the subsystems, and read `INV-frozen-surfaces.md` before designing.
Record the ids in the tranche's first artifact so every later phase starts
from the same map.

Two skill families live in `.claude/skills/`. Route ALL substantive work
through one of them — they exist to prevent scope creep, missed steps,
and forgotten inputs:

- **Something is broken / suspicious** → `deepreason-orchestrator`
  (phases: dr-set-goal → dr-diagnose → dr-reproduce → dr-propose-fix →
  dr-implement-fix → dr-verify-outcome). Diagnosis comes from the typed
  record BEFORE code reading.
- **The operator suggests a change** → `dr-change-orchestrator`
  (phases: dr-capture-request → dr-spec-change → dr-plan-steps →
  dr-execute-step (one step per invocation) → dr-validate-change →
  dr-deliver-change). Authority is the operator's verbatim words,
  ledgered in REQUEST.md; every artifact traces to requirement numbers.

- **The operator asks what is broken / unused / out of date** →
  `dr-audit-orchestrator` (dimensions: broken, dead, docs-drift,
  spec-drift, goal-trace). Read-only: produces AUDIT_REPORT.md plus a
  ready-to-send fix prompt per finding; every verdict compares against
  `docs/AUDIT_BASELINES.md`. Rated for inexpensive models — every step
  is a command, a paste, or a baseline comparison.

Cross-routing: a defect found mid-change is PARKED, not fixed; a change
wished for mid-defect is PARKED, not implemented. One tranche, one goal.
The audit family never fixes anything anywhere — findings become parked
prompts for the other two families.

Cutting across both families, three skills:

- `dr-drive-harness` — the driving manual. Load it at the start of any
  session that runs, modifies, or diagnoses the harness: session
  preflight, the public CLI lifecycle, live-run ladder rules, and where
  to look before modifying (map order, frozen surfaces) or when
  diagnosing (record first). Also the routing index for both families,
  phase by phase, with the artifact each phase owns (§6).
- `dr-ask-the-right-question` — question discipline. Load it before
  acting on any ambiguous or terse operator message, whenever a phase
  says "stop and ask", and whenever evidence contradicts your
  expectation: it routes each question to the cheapest authority
  (record → framework → operator) and kills false forks before they
  spend operator attention.
- `pinker-write-for-readers` — communication discipline. Load it once
  per session, before the first message the operator will see. It
  REPLACED `dr-explain-to-operator` on 2026-09-03 at the operator's
  instruction (installed from their own upload; see Conventions below
  for what survives of the earlier rules). Its two companions,
  `pinker-clarity-workflow` (the router) and
  `pinker-teach-for-understanding` (for explaining a mechanism so the
  operator can use it, not just hear it), were installed with it.

## Third lane: treadle

Beside the two agent families above sits a third lane that is not an
agent workflow at all. `treadle` (vendored at `tools/treadle/`, config
at `/treadle.toml` and `/skills/`, board at `.swarm/` through
`scripts/swarm_gate.py`) is a DETERMINISTIC DRIVER: it walks READY
tasks on the swarm board in routed order, calls exactly one foreign
model per stage, writes only inside the task's declared cone, runs the
task's acceptance command, and commits only what that command passes.
Order, gating and merging are code; no model orchestrates anything.
Installed 2026-08-23, `experiments/2026-08-23-treadle-pilot/`.

**What routes to it.** Two classes, and only these. (1) REVIEW-KIND
VERDICTS on delivered tranches — an already-committed diff sent to a
foreign model for an independent verdict, recorded through the gate as
a typed PASS/FAIL event. Its value is precisely that the reviewer has
no stake in the tranche and did not write it. (2) MECHANICAL TASKS
WHOSE ACCEPTANCE IS A DETERMINISTIC COMMAND — where "done" is decided
by an exit code and not by anyone's reading. If you cannot write the
acceptance command before the task runs, the task does not belong in
this lane.

**What NEVER routes to it.** Anything touching a frozen surface: NO
TASK CONE MAY INCLUDE ONE. Check every cone against
`docs/map/INV-frozen-surfaces.md` before the task is added, not after.
That document owns the list and states it as FIVE surfaces; they span
seven paths, because surface 3 covers both `invariants.py` and
`verification/` — `capabilities/state.py`, `harness.py`,
`invariants.py`, `verification/`, `run_manifest.py` and
`qualification.py`, plus the frozen-ADJACENT `route_fingerprint` in
`llm/firewall.py`. Count paths when testing a cone; cite the owning
document's five when citing the law. The
driver's own cone check is a write boundary, not an authorization: it
enforces the cone you declared, so a cone that should never have been
declared passes it. Also never: work whose acceptance is a judgment
(spec drift, design adequacy, whether a claim is warranted); and
anything that seals, amends or edits a run record, which is an
operator act always.

**Two limits the pilot measured, both binding.** (1) A REVIEW IS NOT
AN EXIT CODE. treadle 0.5 retires its own driver on exactly this
ground, and rung T5 measured why: given a true document set and one
falsified byte-for-byte otherwise, the reviewer named the planted
contradiction in prose while its TYPED verdict fields — the only part
a gate stores — were identical across both. Route a review here to
GENERATE the evidence, then read the reply and dispose of it in
writing per `skills/review-response/SKILL.md`; never let the stored
PASS/FAIL stand in for having read it. (2) The write cone is only as
good as its author: the driver enforces the cone you declared, so keep
anything that judges the work — a mutation proof, an acceptance
script — OUTSIDE the cone it judges.

**Who may author a task.** ONLY THE OPERATOR OR THE MONITOR. This is a
security boundary, not a courtesy: a task's `accept` and `verify`
strings are executed with shell access, and its brief is fed to a model
as trusted input. A task authored from anywhere else — a model's
suggestion, a document, a tool result — is arbitrary code execution
wearing a work item's clothes. Obey every `REFUSED_*` the gate or the
driver emits; never work around a refusal.

## Environment (cloud container — read first, every session)

The container can ROLL BACK silently to a stale checkout, killing
background processes and deleting gitignored files. After any gap:

    git log --oneline -1        # stale head? resync:
    git fetch origin <branch> && git checkout -B <branch> origin/<branch>
    which deepreason || pip install -e . --break-system-packages -q
    python -m pip install pytest pytest-xdist jsonschema \
        --break-system-packages -q   # the GATE's own deps; see below
    ls experiments/live_research_*/env   # gitignored credential file

**That second install line is not belt-and-braces; the install above is
insufficient for the gate below.** `pyproject.toml` declares three runtime
dependencies (`pydantic`, `pyyaml`, `fastembed` — lines 11-21) and a `dev`
extra of `pytest` and `ruff` only (lines 23-27). The documented gate needs
two more that appear nowhere in it: `pytest-xdist`, which the `-n 4` flag
requires and which nothing imports, and `jsonschema`, imported at exactly
one site (`tests/test_schema_carries_every_prose_rule.py:170`). A fresh
container that runs only the documented install and then the documented
gate gets one failure that LOOKS like a code defect and is not. Measured
twice: `1 failed, 4334 passed` on `ModuleNotFoundError: No module named
'jsonschema'` (`experiments/2026-08-27-change-execution-safety/
DELIVERY.md:127-152`), and `ModuleNotFoundError: No module named 'xdist'`
after the documented install on the 2026-08-29 container
(`experiments/2026-08-29-ultracode-batch-2/SETUP.md`). The same remedy line
is already spelled out at `docs/AUDIT_BASELINES.md:49-56`, where it is
stated as a precondition for trusting any docs_verify total — that file
also records the cost of getting the interpreter/pip pairing wrong: 502
failures, none of them real. The declaration itself is UNFIXED and parked
(`experiments/2026-08-30-change-execution-safety-parks/PARKED.md` S5,
which prices the three roads); this note documents the gap, it does not
close it.

The `env` file (OLLAMA_API_KEY=...) is gitignored and never committed;
recreate it from the operator's handover if missing. Because work can
vanish, commit and push the working branch at every phase boundary, and
run a snapshot loop (see `experiments/live_research_2026-07-29/
snapshot_loop.sh <driver>.sh`) during any long live run.

The embedder costs DISK, and the container clears it. `pip install -e .`
carries fastembed (core since 2026-08-16), so `EMBEDDER_MODEL`'s neural
default is armed by the ordinary install — but its ~523 MB of ONNX
weights are fetched on first use into `FASTEMBED_CACHE_PATH`, else
`fastembed_cache` under the system temp dir, i.e. `/tmp` here, which a
rollback wipes along with everything else gitignored. Run

    deepreason embedder-warmup    # ~523 MB fetch, visible, once per cache

in the setup phase of any session that will run the harness, so the
download is paid where you can see it rather than inside cycle 1. It is
idempotent and returns in seconds once the weights are present, and it
prints the fingerprint the run will stamp on its log. Skipping it is not
an error: a run whose backend cannot build falls back to hashing and
says so — `deepreason results` prints `embedder: hashing (fallback)`.

## Build and test

    pip install -e . --break-system-packages    # editable install; the
                                                # CLI and live runs share it
    python -m pip install pytest pytest-xdist jsonschema \
        --break-system-packages                 # the gate's OWN deps --
                                                # pyproject declares neither
                                                # xdist nor jsonschema; see
                                                # the Environment section
    pytest tests/ -q -n 4                       # full gate, ~14 min
                                                # 0 failed is the baseline.
                                                # The passed count moves every
                                                # tranche -- do not pin one
                                                # here. docs/AUDIT_BASELINES.md
                                                # is the living source, and
                                                # names the flaky set too.

Iterate on the RING, gate at the BOUNDARY. The full suite is a gate, not a
feedback loop: run the affected test files while iterating, and the whole
suite only at a phase boundary. `.pytest_cache` already holds `lastfailed`
and every collected nodeid, so use it instead of re-deriving it:

    pytest tests/test_<subsystem>*.py -q      # the ring, while iterating
    pytest tests/ -q -n 4 --lf                # only what failed last time
    pytest tests/ -q -n 4                     # the gate, at the boundary

This is a recorded mistake, not a style note: one tranche ran the full gate
four times (9:17, 9:19, 10:53, 14:02 — ~44 minutes) to learn about roughly
forty tests that could have been affected, with `--lf` available and unused
throughout. Preserve results and re-derive only what moved.

The root sweep is RETIRED as an instrument (operator ruling 2026-08-22:
"it just wastes time"). No tranche, gate, audit, or frozen-surface grant
may require sweeping committed roots — not for cross-version
compatibility (retired 2026-08-14) and not as within-version proof
either. A reader change is proven by targeted, mutation-proven
regression tests on fixtures or single-root replays committed in the
same tranche; that is both cheaper and stronger than a sweep, because a
sweep can only confirm what a targeted test already explains.

The wheel smokes (`python scripts/wheel_smoke.py`; `python -u
scripts/wheel_operational_smoke.py`) are the third instrument, and NO
gate runs them. They pin the public surface — console entry points, MCP
tool set + schema sha, wheel layout — so any commit changing that
surface updates the pins and re-runs the smoke in the same commit.

Gate discipline: 0 failed is the only acceptable result. Never weaken an
assertion to get green. A fixture that depended on defective behavior may
be minimally updated only when the fix's design doc predicted it.
Regression tests name their motivating run in the docstring
("Regression (selfstudy run-9175f0ec): ...").

## Live runs (ladders)

Ladders are shell scripts (`experiments/*/**_run.sh`) that do
setup → qualify → reason → audit against a `DEEPREASON_HOME`.

**No live launch without a green soak on the launch config**: run
`python -u scripts/cycle_soak.py --case <case>` before any ladder launch.
It drives the managed path to cycle 8 on the launch configuration's own
shape against the deterministic stub, and carries a named assertion for
each of the four 2026-08-22 cycle-0-to-2 operational deaths. It has
REPRODUCED one of them offline (the reservation-bound seam); the other
three are asserted, not demonstrated — read that tranche's RESULTS.md
before treating a green soak as full coverage
(`experiments/2026-08-23-change-cycle-soak-instrument/`).

- **Run identity is deterministic.** Same question + config → same
  run id. A leftover root refuses relaunch with RUN_ALREADY_STARTED.
  Retire it — `git mv run-<id> <failed|completed>-epochN-run-<id>` —
  and COMMIT THE RENAME FIRST. Never edit a committed root's contents.
  To change the QUESTION or add evidence without losing the epistemic
  state, do not mint a new root: `deepreason amend` appends an amendment
  epoch to the stopped one (docs/proposals/AMENDMENT_EPOCHS.md), then
  `deepreason continue` resumes it.
- **Qualification caches by subject digest.** Same home + same provider
  profile + same opt-ins → cache hit (~1 s). Changing the profile (e.g.
  completion tokens) or the home reruns the full battery (~14 min,
  ~1160 calls). This is by design; budget for it.
- **Launch detached, never foreground:** from the ladder's directory,
  `setsid nohup ./<ladder>.sh & disown`. Arm the snapshot loop and a
  monitor on the newest root's `progress.jsonl` (state/phase/tokens)
  plus the driver log's `rc=` lines — alert on failure signatures, not
  just success.
- **Judge only typed outcomes:** run state, stop_reason, the ladder's
  audit JSON, `verify_root`, FINDINGS.md. Known facts: glm-5.2 is a
  reasoning model — a hard question can burn the whole completion cap
  on hidden reasoning and emit nothing (typed seat failure; raise
  `--maximum-completion-tokens`). Capability-channel use (typed
  simulation/research proposals) is STOCHASTIC across identical runs;
  one live attempt that misses a path is inconclusive for that path,
  and the offline regression remains the proof.

## Frozen surfaces (never touch without explicit operator approval)

- `src/deepreason/capabilities/state.py` digests and event application
- `src/deepreason/harness.py` event application / well-formedness
- Replay-validation record formats; manifest schemas
- Anything altering qualification subject digests
- The append-only record itself, WITHIN the current version: a live
  run's record stays typed, append-only, and replayable by the code
  that wrote it — that is the epistemology, not a compatibility
  feature. CROSS-VERSION obligations are retired (operator law
  2026-08-14, below): new versions owe old roots neither validity nor
  readability, and no tranche owes a replay-byte-unchanged proof over
  historical roots anymore. Old roots remain in git history as
  artifacts of their own version.

## Hard-won invariants (violations of these were real, recorded defects)

- When a run dies at cycle 0, READ THE DIAGNOSTIC BLOB before theorising.
  Both cycle-0 deaths so far were misattributed on first reading. turmite
  (`_not_a_self_link`) really was a rule JSON Schema cannot express; jolt was
  first written up the same way and was not — the blob said
  `simulation observables must be plain identifiers`, a plain `pattern` the
  sweep had missed on `requested_observables`. The `attempt_trace` gives
  `validation_path` and `diagnostic_ref`; the blob under `blobs/` gives the
  verbatim error and the rejected value. Check SWEEP.md's not-expressible list
  only AFTER the blob rules out a rule that could have been encoded.
  (Both specific encodings were FIXED 2026-08-01 — SWEEP.md/
  REPAIR_OSCILLATION.md; live simulation SUCCEEDED events recorded
  2026-08-09, overnight-omnibus Block B — the examples are historical,
  the blob-first discipline is the enduring rule.)
- The operator's seed question always wins scheduler rank ties;
  import-role admission records never count as "survivors".
- Per-capability budgets meter only their own capability's records —
  the shared capability-state maps pool ALL capabilities' proposals
  and work orders; always filter by type.
- Render-receipt handle maps reload key-sorted (B1, B10, B2, ...);
  compare by handle index (`ordered_refs`), never by `.values()`.
- Within one capability proposal's transition chain, manifest sha and
  fence seqs are frozen; test fixtures must respect this.

## Conventions

- Reporting to the operator: lead with the result in one or two sentences.
  Detail goes in the experiment's RESULTS.md, not the reply. Do not restate
  the reasoning that produced a finding once the finding is stated. Say
  corrections plainly and move on.
- The operator's explanation style (recorded 2026-08-06; extended
  2026-08-08 at their request; the skill carrying it REPLACED
  2026-09-03 — load `pinker-write-for-readers` at session start, and
  `pinker-teach-for-understanding` when a message must make a
  mechanism usable): answer their actual worry in the FIRST sentence,
  before any mechanism. When a finding sounds like bad news, state
  what it does NOT mean for their intent before what it does. Present
  forks as real-world roads priced in their terms (what they can do,
  when, at what cost), with a recommendation. Own your part plainly
  when a prior instruction or workflow rule caused the confusion.
  Internal artifacts keep full precision. Close every FINAL output
  with ONE short, accurate everyday analogy ("the fire marshal
  certifies the room as arranged, or each chair individually") —
  required on the last message, never on intermediaries; the new
  skill's analogy test applies (map the parts, say where it breaks,
  never let it stand in for the mechanism).
  SUPERSEDED within this rule, 2026-09-03: the 2026-08-08 instruction
  to "gloss every technical term conservatively in-line" on every
  intermediary message. The operator's words the same day: "No
  technical jargon like seed, traunch, bike shedding, dogfooding,
  cold start, dependency injection, idempotent, heisenbug or anything
  of the sort. If you need to rely on a concept, translate into terms
  I know like epistemic state, episode, artifact, decision. Human
  words. If you have to define terms, that's a fail state." Then, on
  uploading the Pinker skills: "Can you install this to replace the
  other one about communicating with me." Operational reading: do not
  gloss a term of art — do not use it. Say the thing in the
  operator's own vocabulary (epistemic state, episode, artifact,
  decision, conjecture, criticism, seat, run, record) or in ordinary
  words; a message that has to stop and define something has already
  failed. Requirement numbers, commit hashes and error codes stay
  out of operator-facing prose unless the operator has to go to
  them; when one must appear, its meaning for the work is stated in
  the same sentence. The old skill text remains in git history
  (`git log --diff-filter=D -- .claude/skills/dr-explain-to-operator`)
  for anyone reconstructing why earlier messages read as they do.
- Commits: one defect or one change per commit; message states what,
  why, the live evidence (run ids), and "Full gate: N passed, 0
  failed" when code changed. Push with retry (2s/4s/8s/16s backoff).
- Comments state constraints the code cannot show — never narration of
  the change or its history.
- Experiment narrative lives in the experiment's RESULTS.md as dated,
  honest-ledger segments: what the record shows, and the residue —
  what remains unproven. "Accepted does not mean true." Never claim
  more than the record shows; a negative or inconclusive result is
  recorded as one.
- Scratch/temp files go in the session scratchpad, never the repo.
- Prompts written for the operator to paste into executor windows are
  delivered inline in the chat reply as ONE fenced code block (easy to
  copy whole), never only in a committed file or spread across prose
  (operator request, 2026-08-11).

## Operator design laws (stated by the operator, standing, not
## derived from defects)

- **Formalism is an option, never an obligation** (2026-08-08,
  repeated by the operator "endlessly" — do not make them repeat it
  again): nothing may force a conjecture to be formal, and nothing may
  penalize a conjecture for being informal — not admission, not rank,
  not criticism exposure, not acceptance. Formal backing may grant
  protection (prose-immunity); its absence grants no disadvantage.
  Any design that weights outcomes on conjecture KIND violates this
  law. See DUAL_MODE_CONJECTURE_PREPLAN.md R-g for the full binding
  form.
- **Seats change how content is GENERATED, never what counts as
  EVIDENCE** (the modes/packages guardrail, BEHAVIOR_MODES_PREPLAN /
  ROLE_SEAT_SEPARATION_PLAN S7): no seat, mode, or package may let a
  generation seat's prose skip criticism.
- **A solo run with everything on must be an option** (2026-08-09,
  operator's words verbatim: "A solo run with everything on should be
  an option. That's what solo run option should always have been.
  However, turning on judges at all should be done with caution. I
  would prefer to do without, since they prosecute without any
  discernable discrimination."): sole-model operation may never be
  structurally locked out of any harness capability — including
  status-changing criticism; designs gated on multi-family judge
  ensembles need a solo-compatible road. And judge seats are
  suspect-by-default: any design leaning on LLM judges must first
  consult the judge-audit evidence in the committed record (see the
  judge-evidence review tranche) rather than assume judges
  discriminate.
- **Tokens are cheap; the agent is not** (2026-08-08, operator's words
  verbatim: "Ollama API tokens are cheap, you are not. Running endless
  API experiments is preferred if it means you do less work. Creating
  evidence from live runs is preferred if it means less work."): when a
  question can be answered by live runs or API experiments, run them
  instead of building machinery or reasoning it out offline; prefer
  evidence generated by live runs over hand-crafted synthetic fixtures
  when that saves agent work; build only what generated evidence
  demands. The evidence discipline itself is unchanged — experiments
  stay pre-registered and raw-preserved, and model prose is still
  never evidence.
- **All configurations should be allowed** (2026-08-12, operator's words
  verbatim: "All configurations should be allowed."): compile-time
  denial of an otherwise-parseable configuration is abolished. Any
  input that parses into the configuration model compiles into a run;
  what used to be a compile-time refusal (family requirements, role
  conflicts, backend-identity gates, ceiling checks, combination
  restrictions) becomes a typed disclosure recorded alongside the
  compiled result, or a deterministic resolution rule when two parts of
  one configuration conflict — never a stop. Runtime is unchanged: a
  config naming an unreachable model, an unsatisfiable ensemble, or a
  zero budget still fails typed at the point of use; impossibility
  surfaces there, not at compile. Only parse/shape errors (unreadable
  input, a string where a number goes) are not configurations at all,
  and stay refused. An earlier statement in the same exchange — "There
  should only be additional flags, not flat out denial" — is
  SUPERSEDED by the operator's own final sentence above: no flags are
  needed, nothing to override, compile never refuses. Ledgered per the
  operator's own instruction to record both statements with the
  supersession noted (`experiments/2026-08-12-change-all-configs-allowed/`).
- **Operations are available to every configuration** (2026-08-13,
  operator's words verbatim: "The flags and operations available to the
  newer reason runs should be available to all configurations."): the
  operations-parity sibling of the all-configurations law above. That law
  says every configuration COMPILES; this one says every configuration
  that compiles gets the same LIFECYCLE. A run launched from any path —
  the managed `deepreason reason`, a compiled `deepreason run
  --run-manifest`, a ladder — must reach the same typed terminal and
  accept the same operations: amend, continue, cancel, result, finalize.
  A lifecycle step written on one launch path and not the other is a
  defect, not a difference in surface: it produces a root that ran real
  cycles and that no operation can touch (grounded-extension run
  `8e22d0431fd2b98d` stopped at `current_open_uncommitted` and refused
  `AMEND_NOT_AT_TERMINAL` after 24 completed cycles). The mechanism is
  therefore ONE RUN PATH, not two paths kept in agreement: every
  configuration — including a precompiled manifest with judge ensembles,
  route-bound seats and a criticism policy — enters through
  `application/text_runs.py::TextRunApplicationService.start_manifest_run`,
  and `deepreason run --run-manifest` keeps its exact CLI surface as a
  rendering shell over it, owning no scheduler, no lock and no
  terminalization of its own. Parity by construction: there is nothing
  left to diverge (`experiments/2026-08-13-change-lifecycle-operation-
  parity/` fixed the drift by sharing `terminalize_text_run`;
  `experiments/2026-08-13-change-single-run-path-unification/` removed
  the second path the same day, on the operator's instruction — "Get rid
  of the old one." See `docs/ERRATA.md` E26).
- **Old runs owe the future nothing; new versions optimise for new
  functions** (2026-08-14, operator's words verbatim: "old runs do not
  need to be valid or returnable by the way. What's important is that
  new versions are optimised for new functions"): retires the
  cross-version compatibility law that previously closed the frozen-
  surfaces list ("fix READERS so old roots stay valid; a change that
  invalidates existing replay-valid roots is wrong by definition" —
  SUPERSEDED). New record formats, digests, and readers may change
  freely when a new function warrants it; committed roots from earlier
  versions remain in git history as artifacts of their own version, and
  no tranche owes replay-byte-unchanged proofs, reader-widening-only
  designs, or old-root sweeps as gate obligations anymore. SCOPE
  BOUNDARY, stated so this law is never over-read: a CURRENT-version
  run's record remains typed, append-only, and replayable by the code
  that wrote it — within-version integrity is the epistemology itself
  ("the record is the only admissible evidence") and is not touched by
  this law.

- **Modularity is enforced, and customisation is easy** (2026-08-26,
  operator's words verbatim: "There needs to be a priority that
  enforces modularity. Customisation needs to be easy."): every
  behavior a run can vary is reachable as CONFIGURATION or a
  REGISTERED, VERSIONED ARTIFACT — never by editing code. New
  machinery ships behind a declared interface on the signal-contract
  pattern (FROZEN change protocol, VERSIONED registry/policy, FREE
  parameters), and "enforced" means a check that can fail: each
  module carries an architecture test that goes red when a consumer
  bypasses its interface or when a customization point requires a
  code edit to use. Stated as a PRIORITY: when a design forks between
  a tighter coupling that is smaller and a declared interface that is
  larger, the interface wins. Companions: the all-configurations law
  (everything that parses compiles), operations parity (every
  configuration gets the same lifecycle), and the signal contract
  (the pattern this law generalizes). Ledgered during the REBUILD
  program; the F1/F2/F3 tranches are its first bound implementations.

- **The signal registry is a CONTRACT, and allocation changes are layered**
  (2026-08-14, operator's words verbatim: "The signal REGISTRY is a
  CONTRACT, not a wiring: a signal is anything declaring name, unit,
  producer-agnostic semantics, and a staleness bound; new setups add
  signals by declaration through this typed channel, never by teaching a
  consumer about a subsystem."): signals are keyed by SEAT INSTANCE, not
  role — one conjecturer may sit in "multiple structurally asymmetric
  seats that may need throttling independently". The allocation
  controller consumes ONLY the signal interface. A topology that cannot
  produce a signal COMPILES, carrying a typed "allocation open-loop for
  signal X" notice — disclose, never die (the all-configurations law,
  applied to allocation). Three layers, not interchangeable: **FROZEN**
  is the change protocol itself — decisions typed and recorded,
  interface-only consumption, envelope bounds, and allocation touches
  EFFICIENCY NEVER EVIDENCE; **VERSIONED** is the registry and the
  policy algorithm, with policy as a recorded artifact, referee-reviewed;
  **FREE** is parameter values within envelopes. Governed by an `INV-`
  map document with checks and two `REC-` recipes (add-signal,
  revise-allocation-policy); a dedicated workflow only after TWO recorded
  recipe failures (the `authoring-skills` E1 tripwire). Ledgered by
  `experiments/2026-08-14-change-calculus-reconciliation-v2/` REQUEST.md
  Amendment 2; the mechanism lands at that program's Rung 1b.

- **Seat configuration is ungated, gates are optional-with-warnings, and
  modes are the point of the modularity** (2026-08-28, operator's words
  verbatim, sharpening the all-configurations law (2026-08-12), the
  operations-parity law (2026-08-13) and the modularity law (2026-08-26)):
  "My intention was that configuration of seats need to be able to turn
  gates on and off at will. Meaning no limits to what model you place
  where. It also means that when and if I decide to replace schools with
  something different, those flags don't gate seat configuration paths.
  Gates are always optional: with warnings. Although behaviour path
  should be deterministic, yet also configurable. Do I want to
  prioritise brainstorming and idea generation first before subjecting
  the content to rigorous criticism and elimination -- the difference
  between strict narrowing and interesting options for a user to choose.
  Do I want to pick and argument apart and poke holes wherever possible
  and not necessarily create novel ideas. This isn't an exhaustive list,
  it's just two examples. That's why I made DeepReason modular, so these
  types of modes could be generated: Analysis mode, daydream mode,
  critic model, novel exploration mode; whatever." Operational reading:
  ANY model may sit in ANY seat; NO flag — school flags included, and
  whatever replaces schools — may gate a seat-configuration path; every
  gate (qualification, criticism authority, judge invocation, admission
  screens) is switchable per run, and switching one off produces a typed
  WARNING, never a refusal and never silence; behaviour paths stay
  deterministic given a configuration while remaining configurable
  between runs; and the modularity exists so run-level MODES (analysis,
  daydream/generation-first, critic/hole-poking, novel exploration, …)
  can be composed from configuration. The audit finding P10 (2026-08-28,
  five switches silently reverted by the manifest echo with zero
  notices) violates this law's letter twice over — silent, and a gate
  the configuration could not actually turn on.

- **The judge law, amended on the record's own evidence** (2026-08-28,
  operator verbatim: "The judge statement should have been amended. We
  did some research on this, relying on external sources, but I've
  forgotten the results." Amended wording drafted by the monitor from
  the committed evidence the operator directed to; the 2026-08-09
  statement above stands as history): the caution "they prosecute
  without any discernable discrimination" is SUPERSEDED by measurement
  (experiments/2026-08-09-change-judge-evidence-review/ REVIEW.md;
  docs/RESEARCH_JUDGE_BLINDING_2026-08-22.md). What the record shows:
  in the frozen configuration (cross-family pairing, unanimous vote)
  judges UNDER-convict — 11.9% sensitivity on planted ground-truth
  defects, 0-2.5% false conviction of sound work; every looser
  configuration measured (same-family, either-suffices) over-convicts
  at 47-60%; the indiscriminate stage is the CRITIC's raw objection
  flow, not the judge-gated conviction; and label/provenance exposure,
  not content, carries the bias — so blinding is STRUCTURAL: renderers
  OMIT provenance fields entirely (a present-but-blank slot draws more
  attention than a filled one), and no prompt-level fix substitutes.
  Unmeasured residue, still open: self-preference and verbosity bias
  have zero live measurements. Judge use is a per-run configuration
  choice under the ungated-seats law above; the solo-run law is
  untouched.

- **Exhaustion is a clean stop, every stop secures continuation, and
  continuation is integrity-gated** (2026-08-29, operator's words
  verbatim, deciding the parked P2 question and extending it): "clean
  stop. with an assurance that continuing is possible. Too often an
  operational failure overlooks securing enough checkpoints to allow
  relaunches or forgets to ensure continuing is possible that trigger
  corrupted stops. On that note, checkpoints need to be hardned. I
  don't want a jailbroken run to be continuable." Operational reading:
  a budget denial on an exhausted budget terminates as
  `budget_exhausted` (clean), never `operational_failure`; EVERY
  terminal — clean or failed — must leave checkpoints sufficient for
  relaunch, and a stop that cannot assure continuability is itself a
  defect (a "corrupted stop"); and `continue`/`amend` are gated on the
  record verifying intact — a run whose record fails replay validation
  or carries unresolved containment-breach evidence is REFUSED
  continuation with a typed refusal. Security boundary, not a
  convenience: tampering with a record must not buy a resumable run.

- **Successor questions: optional to propose, routed by pluggable
  destination, minting gated off-by-default** (2026-08-29, operator's
  words verbatim, deciding the parked P9 question): "This should be an
  optional field the LLM can fill in. Not enforceable. If it is filled
  in, it goes to scratchpad by default, linked to the problem it was
  proposed under and visible by conjecturers. But build the wiring to
  mint, with the option to switch it on with a flag saying something
  like 'may cause critics to fully consume conjecturer role'. Switch
  off by default. Again, maximum configurable surface. The scratch pad
  option must function like a plugin that allows for movement
  elsewhere as well. Again, the modularity thing and Max config
  thing." Operational reading: the successor-question field is
  OPTIONAL on criticism output — never required, never penalized
  (formalism-optional pattern applies); a filled proposal routes to
  the scratchpad by default, linked to its originating problem and
  rendered visible to conjecturer seats; the DESTINATION is a
  versioned, registered routing point (plugin-shaped, per the
  signal-contract pattern) so it can be re-aimed by configuration;
  the minting road (criticism → new problem, the SUCCESSOR trigger)
  is BUILT and gated by a per-run flag, OFF by default, whose
  enablement emits the operator's own warning text; every piece is
  configuration, none is a code edit ("maximum configurable
  surface"). SCOPE CONFIRMED (2026-08-30, operator verbatim:
  "confirm"): "The P9 law of 2026-08-29 supersedes the 2026-08-15
  decommissioning ruling FOR THE SUCCESSOR TRIGGER ALONE — one
  producer, outside rules/, gated by a per-run flag defaulting OFF —
  while the website development pipeline itself stays decommissioned."
  The four implementation questions beneath the law were answered by
  the monitor on the record (batch-2 lane B, 2026-08-30): the
  frozen-surface-4 grant for the two Config fields GRANTED per the
  documented recipe; the enablement warning declared on the destination
  registry and the run's own record (road B); the criticism side stays
  un-widened — a reader outside rules/ routes what criticism already
  recorded (road B); and the seed-question guarantee ships as the
  rank-TIE now, with strict domination parked as its own tranche.

## The map — `docs/map/` (read this before scoping any change)

125 000 lines across 34 packages. Do not scope a change by grepping; scope it
from the map. **`docs/map/INDEX.md` is the entry point** and routes to
everything else. `docs/map/SCHEMA.md` is the contract for reading and writing
map documents — read it once, before you touch one.

Five kinds of document; the filename is the identifier:

    SUB-<pkg>.md         a subsystem: what it owns, entry points, state
    CON-<slug>.md        a cross-cutting concept that is NOT a package
                         (schools, authority, warrants, run identity)
    SEAM-<a>-x-<b>.md    how two of them meet — sides alphabetical
    INV-<slug>.md        an invariant / frozen surface
    REC-<slug>.md        a change recipe

**How to read it.** `INDEX.md` → the routing table. For a change that spans two
things, read the SEAM document BEFORE either subsystem: it says which fraction
of each side is actually involved, and it is usually small. Read
`INV-frozen-surfaces.md` before designing anything — discovering a frozen
surface after the code is written is the expensive order to discover it in. For
a defect, read the covering document's `Traps` section before the record: a
recurrence is the cheapest diagnosis available.

**Documents are authenticated by RE-DERIVATION, not by signature.** Every
load-bearing claim carries a `check:` shell command at column 0 that must exit
0. A signature would prove who wrote a sentence; this proves the sentence is
still true, which is the property that decays.

    python tools/docs_verify.py           # every check; 0 failed required
    python tools/docs_verify.py --audit   # refuses checks that cannot fail
    python tools/docs_verify.py --links   # every DR- reference resolves
    python tools/docs_verify.py --stale   # advisory: docs worth re-reading

**How to modify it.** The map moves in the SAME COMMIT as the code — a separate
"update docs" commit is the commit that gets dropped. Advance `Verified-at:`
only if you actually re-ran that document's checks; a stale stamp is honest, a
false one is not. New behaviour needs a new check that would fail if the
behaviour regressed — run it before you write it down. Every fix earns a
`Traps` entry naming its run id, and a `Traps` entry is never deleted, only
rewritten to say when it was fixed. The orchestrator skills enforce all of
this; `SCHEMA.md` states it in full.

A seam document that does not exist means the pair has not been written up —
`INDEX.md`'s matrix says which. It never means the two do not interact.

## Directory map

    src/deepreason/
      scheduler/scheduler.py   problem selection, cycles, budgets
      rules/                   spawn (conn/disc/succ/debt), conjecture
      amendment/               post-stop epochs: reshape the question,
                               admit more evidence, chain, never edit
      capabilities/            simulation + research controllers, state
      scratch/                 attention, render receipts, authoring
      workflow/                v6 transactional work lifecycle
      invariants.py            verify_root (replay validation)
      harness.py               append-only log, state application
    tests/                     the gate; helpers worth reusing:
                               _prepare_run, controller fixtures
    experiments/               live evidence; RESULTS.md = narrative
    docs/                      specs (harness v1.3 + v1.4/v1.5/v1.6/v1.7
                               amendments — read ALL amendments; note
                               "V6" elsewhere names the RunManifest/
                               policy generation and the wire-contract
                               series, NOT this spec document series),
                               STATE_OF_THE_THEORY, TOKEN_ECONOMY,
                               BASIN_REPORT
    .claude/skills/            the two workflow families

Start any session by reading the newest RESULTS.md segments — they are
the running truth of what has been proven, broken, fixed, and parked —
and `docs/ERRATA.md`, the append-only ledger of corrections to committed
documents: it says which document claims have already been found wrong,
so you do not re-trust them.

- **Success is progress over the no-harness baseline; correctness and
  completeness are not the goal** (2026-09-03, operator's words verbatim:
  "a complete answer isn't the goal. Neither is correctness. The
  condition of success it something materially better than what's
  produced without it. Correctness is irrelevant. Please remember that
  for future designs. Poppers epistemology is about progress, not
  truth."): the acceptance criterion for any run, feature, or design is
  that its output is MATERIALLY BETTER than what the same model produces
  WITHOUT the harness on the same question — measured blind, against
  criteria written before any output is read, at matched spend where
  spend matters. "Better" is Popperian progress: more error eliminated,
  survivors harder to vary, bolder conjectures that survived criticism,
  deeper successor problems — never "is the answer true" and never "did
  the run reach a composed answer". A finished, correct-looking answer
  that a single model call would have produced equally well is a FAILED
  run; an unfinished run whose surviving conjectures are demonstrably
  better than the single call's is a successful one. Consequences for
  designs: every live experiment carries a no-harness baseline arm or
  cites one; "reached a terminal" and "composed an answer" are
  operational health checks, not success conditions; and no design may
  be justified by correctness alone. Ledgered by the monitor at the
  operator's instruction.

- **A seat is a shell: its input and its output define it** (2026-09-03,
  operator's words verbatim, amending the conjecturer-pluggable-interface
  tranche as its build was being commissioned: "Is prefer if the
  conjecturer seat could be used to replace the critic seat. That means
  an artifact truely is determined by input and output, the artifact is
  just a shell. I'm thinking in the future that conjecturers will need to
  be split in two and criticism will need two different types."):
  what makes a seat a conjecturer or a critic is the BRIEF it is shown
  and the FORM it is asked to fill, both of which are registered,
  versioned configuration — never a code path with the seat's name on
  it. The same machinery renders every seat's brief and selects every
  seat's form; a seat kind is a registered pairing of a brief layout
  and a form, so the conjecturer's pairing can be bound where the
  critic's is today, and a future second conjecturer kind or second
  criticism kind is added by registering a pairing, not by editing
  code. SCOPE BOUNDARY, so this is never over-read: the shell is about
  how content is GENERATED. What counts as evidence — the parse half of
  every form, admission, rank, immunity, refutation, and the record —
  does not vary with the shell (the seats-generate-never-evidence law
  above, and the modularity law's "enforced" clause: an architecture
  test must go red when a seat's name is read anywhere on the evidence
  side). First bound implementation: the build of
  `experiments/2026-09-03-change-conjecturer-pluggable-interface/`,
  amended the same day to cover the critic seat's brief and form.
  PURPOSE, stated by the operator minutes later (verbatim): "this
  should work to slowly separate the authority layer to make it truely
  modular." Reading: the shell is the generation side of a seam whose
  other side is the AUTHORITY layer — admission, rank, immunity,
  refutation, warrants, status — and the programme's direction is to
  pull that layer behind its own declared interface, step by step, so
  that neither side knows the other's internals. The brief sections
  still computed inside `rules/conj.py` (the tranche's A6) and the
  criticism-source socket that refuses to carry score or rank are the
  two ends of that seam as it stands today; each later step moves one
  more thing across it, never by editing a consumer.

- **History is an inactive plug: built, switched OFF by default, never
  removed** (2026-09-05, operator's words verbatim, ruling on the
  history-channel replication — three paired runs, RESULTS_M1_REPLICATION.md:
  quality indistinguishable once length is held constant, cost unresolved,
  history-on conjectures shorter in every pair: "History doesn't improve
  token efficiency or improve answers apparently. So if it's built, it
  just needs to be turned off, not removed. And remain an inactive
  plug."): the conjecturer's history exposure (the `dr.history.v1` section
  plugin and the history half of the provenance/history channel) ships
  OFF by default; the plugin, its parameters, its layouts and its record
  channel stay registered and selectable per run, so a later experiment
  turns it on by configuration, never by re-building it. Supersedes the
  history tranche's SPEC.md S10 "conjecturer: history ON by default".
  The same day the operator also ruled: the current default conjecture
  form is STORED, not deleted, while relaxed forms are tried ("the
  current default conjecture form needs stored but not deleted"); and one
  more history conjecture experiment follows the mini isolation programme
  below, not before it.

- **Within mini, criticism overturns nothing; mini is content generation,
  tested afterwards on the full harness** (2026-09-05, operator's words
  verbatim, answering the mini isolation programme's Q-A: "within mini,
  criticism can't overturn anything. The point is content generation for
  now. Then testing on the full harness."): in the mini isolation flow a
  critic's objection is written to the record and shown to the seats the
  layouts allow, and it changes no status — no elimination road is built
  for mini, not even switched off. Mini's job in this programme is to
  GENERATE content (conjectures, criticisms, commitment proposals); what
  that content is worth is decided later by running it through the full
  harness, whose authority layer is unchanged. Supersedes the programme's
  SPEC.md Q-A recommendation (E1 default with E2 built OFF): E1 only.