LEDGER — The Append-Only Substrate
Status: DRAFT v2.0 — command-center reviewed 2026-07-20 · ML review pending What this is: the mechanical contract for the one record everything meta computes over. Workers communicate by verdicts, never shared memory; the ledger is where the verdicts live. Monitoring is arithmetic over this file. Self-knowledge is set reconciliation over this file. The Executive Brief is compression of this file. If a fact about the system's behavior is not derivable from the ledger, the system does not know it.
1. Physical form
- One append-only JSONL stream:
data/ledger/ledger.jsonl, one record per line, UTF-8, no BOM,\nterminated. - Segmentation (optional, for size): per-day segment files
data/ledger/segments/YYYY-MM-DD.jsonl. Segments are *appended while current, then frozen forever*. A frozen segment is never edited, compacted, rewritten, or deleted. Rotation is a rename-free cutover: writers switch target at UTC midnight; readers glob the directory. RESOLVED (ML, F5): per-day segments are the default. The day is the system's reporting dimension: every worker, meta-worker, and meta-meta-worker reports daily; segment boundaries align with the reporting cadence. - Append discipline: writers open in append mode, write one complete line, fsync. No in-place mutation ever. Corrections are new records that reference the erroneous record's
id(typeverdictwithverdict: killandreason: supersedes:<id>), never edits. - Timezone: all timestamps are UTC, ISO-8601 with seconds (
2026-07-20T14:03:22Z). Naive local timestamps are a parse error (fixes the v1 day-boundary drift, audit R10). - Concurrency: one writer process per stream at a time, guarded by
data/ledger/.lock(create-exclusive lockfile; stale after 60s). Writers that cannot take the lock queue and retry; they never write unlocked.
2. The record envelope
Every record, regardless of type, is this envelope. Unknown envelope fields are a parse warning; missing required fields make the record invalid — killed at ingest and logged as an alarm, never accepted with defaults (no "unknown" bucketing anywhere in the system).
{
"id": "01J3ZK7Q9W8XN4T2R6VBCM5DPE",
"ts": "2026-07-20T14:03:22Z",
"run_id": "2026-07-20T14-strategy-auditor-r142",
"worker_id": "strategy-auditor",
"class": "monitoring/auditor",
"type": "verdict",
"payload": { },
"provenance": [
{ "kind": "url", "value": "https://example.com/thread/991",
"fingerprint": "sha256:6f2a…", "attested_by": "forum-sensor", "tier": "external-quarantine" }
],
"prev_hash": "sha256:aa41…"
}
| Field | Type | Required | Meaning |
|---|---|---|---|
id | string (ULID) | yes | Globally unique, lexically time-sortable. |
ts | string (ISO-8601 UTC) | yes | When the record was written. |
run_id | string | yes | The fresh-context run that produced it: <ISO-hour>-<worker_id>-r<seq>. The unit of corroboration (Decision 3). |
worker_id | string | yes | The commissioned worker (must exist in the census). |
class | string | yes | <layer>/<class> from the blueprint, e.g. operating/eliminator. |
type | string enum | yes | One of §3. Unknown type → killed. |
payload | object | yes | Type-specific body, schemas in §3. |
provenance | array of fingerprint objects | yes (may be [] only for heartbeat) | What evidence this record rests on. Attested by the ingesting sensor, never self-declared by the proposer (see GATES.md §5). |
prev_hash | string | required | sha256 of the previous line, forming a tamper-evident chain. RESOLVED (ML, F4): mandatory — higher auditability wins. Genesis line uses sha256:0. |
Provenance fingerprint object: {kind, value, fingerprint, attested_by, tier} where kind ∈ {url, domain, claim-hash, artifact, metric-file, sensor, ml-directive}, fingerprint is the canonical dedup key, attested_by is the sensor/worker that ingested the source (must differ from the proposing worker for external kinds), and tier is the source-classification tier. [OPEN — flag for command center: the fingerprint function itself — URL vs. domain vs. claim-hash vs. embedding similarity — is a registered open question (flaws doc); ship claim-hash of the normalized cited span as the default, keep the function pluggable.]
3. Record types
3.1 candidate-registered
Written the moment a proposal enters any gate's field of view. Registration precedes judgment; nothing is judged that was not first registered.
"payload": { "gate": "strategy-consensus", "direction_key": "shift-to-comparison-content",
"proposal_ref": "workers/strategy-auditor/2026-07-20T1403.yaml#doc2",
"epoch": 41 }
3.2 verdict
The output of any orienter — gate script, reviewer, values gate, tier-arbiter.
"payload": { "gate": "strategy-consensus", "direction_key": "shift-to-comparison-content",
"verdict": "pass",
"standard_version": "gate-ramp.yaml@sha256:9c1e…/strategy-consensus/phase:steady",
"reason": "corroboration 4 distinct (run×provenance) ≥ threshold 3",
"counted": { "distinct_runs": 3, "distinct_provenance": 2, "pairs": 4 } }
verdict ∈ {pass, kill, block}. pass = survived elimination; kill = eliminated on the standard; block = stopped by boundary (values, budget, cooldown, console hold) — blocks name their blocker inreason.standard_versionis mandatory: the exact standard (file + hash + phase) the verdict was rendered under. A verdict with no standard version is invalid.
3.3 commit / decommit
Permanent state changed: a page published, a worker commissioned, a directive updated, a standard amended. decommit is its reversal (retirement, unpublish, rollback).
"payload": { "artifact_id": "site:/guides/comparison-methodology", "artifact_kind": "page",
"gate": "gatekeeper", "qualified_ref": "data/gates/qualified/gatekeeper-2026-07-20.jsonl#L14" }
Every commit must be traceable to a pass verdict via qualified_ref. A commit with no ancestry is the highest-severity self-knowledge finding.
3.4 outcome
Post-publication ground truth — the substrate of all improvement measurement.
"payload": { "artifact_id": "site:/guides/comparison-methodology",
"event": "gsc.impressions", "value": 1240,
"observed_at": "2026-07-19T00:00:00Z", "source": "gsc-sensor" }
eventis an observable: an impression count, a click, a ranking position, a citation, a backlink acquired, a 404, a Core Web Vitals number. Attested by the sensor named insource, which must matchattested_byin provenance.- Opinion-typed outcome records are killed at ingest. "This page seems better," scores from a model's own judgment, and any field whose value is prose rather than an observable event are not outcomes. Judgments live in
verdictrecords where their standard is named; outcomes are what the world did.
3.5 alarm
A meter crossed a baseline: drift, staleness, canary degradation, invalid-record kill, loop-closure hole. payload: { meter, baseline_ref, observed, threshold, severity }, severity ∈ {info, warn, critical}. Bad news survives compression: alarms are never deleted, downgraded, or reworded by downstream condensers (V3).
3.6 trial — pre-registration, then result
Two records, strictly ordered. The pre-registration must exist in the ledger before the first trial sample is collected; a result whose trial_id has no earlier pre-registration record is invalid and the trial is void.
"payload": { "phase": "pre-registration", "trial_id": "trial-0047",
"hypothesis": "challenger directive reduces rejection rate",
"champion": "drafter-directive@v12", "challenger": "drafter-directive@v13-c1",
"metric": "reviewer.rejection_rate", "sample_size": 40, "win_margin": 0.10 }
"payload": { "phase": "result", "trial_id": "trial-0047", "samples": 40,
"champion_score": 0.28, "challenger_score": 0.15,
"verdict": "challenger-wins", "margin_achieved": 0.13 }
sample_size and win_margin are frozen at pre-registration; a result reporting a different sample size or a post-hoc margin is invalid. verdict ∈ {champion-holds, challenger-wins, void}.
3.7 escalation-forward / escalation-bounce
A decision moved up the ladder (forward) or was returned with instructions (bounce). payload: { escalation_id, from, to, category, evidence_refs[], deadline_epochs }. The four ML contact categories are enforced here: an escalation-forward with to: "ML" and a category outside the four is itself blocked and alarmed.
3.8 grant
Access changed hands. payload: { grantee, scope, action: granted|revoked|released, granted_by, expires }. granted_by is always ML or a key custodian ML named — access is granted, never derived (V4). Grants have no silent renewals; expiry emits an alarm if the grantee still holds the credential.
3.9 heartbeat
payload: { status: ok|degraded, detail }. The only type permitted an empty provenance list. Silence-detecting workers are never retired on silence; heartbeats are how silence is measured.
4. Rules (the invariants scripts enforce)
- Every proposal carries
run_id+provenance. A proposal artifact lacking either is killed at registration (verdictkill, reasonmalformed:missing-run-idormalformed:missing-provenance) — never counted, never bucketed. - **Corroboration is DISTINCT run_ids × DISTINCT provenance fingerprints — never file dates.**
count = |{(run_id, fingerprint)}|over the group, with the additional floorsmin_distinct_runsandmin_distinct_provenancefrom the ramp config. Day-denominated counting is deleted (fixes the v1 day-collapse, audit §1.2/R1); days survive only as a staleness ceiling (observations older thanday_ceilingare discarded, nothing else about days is counted). Five proposals citing one planted source are one observation (Decision 13). - Consumed-marking. When a direction executes, the executor writes the
commitrecord AND the gate library marks thedirection_keyconsumed (mark_consumed, GATES.md §3). A consumed direction cannot re-qualify from the same evidence; re-qualification requires new observations from post-consumption epochs (fixes v1 repeat-firing, audit R2). - Completeness invariant. Every
candidate-registeredrecord is eventually followed by ≥1verdictfor the same(gate, direction_key)OR an open-assignment record (anescalation-forwardor a standingalarmnaming it). The self-knowledge sweep computes the orphan set nightly by set reconciliation:registered − (judged ∪ assigned) = ∅or an alarm fires per orphan. - Recomputability. Any meter, brief line, graduation decision, or corroboration count must be reproducible by a third party from ledger entries alone — no appeal to worker memory, chat history, or files outside the ledger and the versioned standards it references. If a number in the Executive Brief cannot be recomputed this way, the number is wrong by definition and the funnel audit files an alarm.
- Verdicts carry their standard. No verdict without
standard_version. When a standard changes, old verdicts stay valid under their recorded standard; nothing is retro-judged silently.
5. What the ledger is not
- Not a message bus: channels (CHANNELS.md) carry work; the ledger mirrors verdicts.
- Not a scratchpad: exploration in the sandbox is disposable and unledgered until it proposes something — then it registers.
- Not editable by anyone: the command center appends like everyone else. ML's force actions arrive as
grant/console records, appended, never as rewrites.
Provenance: envelope and rules derived from SYSTEM.md §5 substrate order, the gate mechanic audit (day-collapse §1.2, repeat-firing R2, unknown-bucket R3), and flaws-doc Decisions 3, 4, 6, 13. Trial mechanics from SYSTEM.md §5 item 4.