Skip to content

Regulated audit

The failure this prevents: an answer cites a document nobody agreed was in scope. It has a real document ID, a real page and a verbatim quote. At the point of use it is indistinguishable from a correct citation — and the cite-or-abstain guarantee still holds, because that guarantee is scoped to the index, while the auditor’s question is scoped to the corpus.

Every other freshness mechanism is change-driven: it reacts to an ingest, an update, a revoke. None of them notice an artifact that arrived by a path the change log never saw — a crashed ingest, a restored snapshot, a shared bucket prefix, a run against the wrong config.

  1. Declare the agreed corpus. The manifest is authored by you, not derived from the index — a manifest generated from the index could never disagree with it, which is the entire point.

    from citenexus.reconcile import CorpusManifest, CorpusEntry
    manifest = CorpusManifest(
    manifest_version="2026-08-16",
    entries=(
    CorpusEntry(document_id="policy-handbook", sha256="3c58d7e6…",
    version="4.1", current=True,
    effective_date="2026-01-01"),
    CorpusEntry(document_id="pension-schedule", sha256="9a01bb2f…",
    version="2.0", current=True),
    ),
    )
  2. Reconcile. It reads; it changes nothing.

    report = rag.reconcile(manifest)
    report.orphans # indexed, NOT in the manifest -> the ghost documents
    report.missing # in the manifest, NOT indexed -> a failed ingest
    report.drifted # in both, content hash differs -> the source changed

    The three sets are disjoint, and running it twice on an unchanged index produces an identical report. A clean corpus reports empty.

  3. Remediate explicitly, never as a side effect.

    if report.orphans:
    removal = rag.remediate(report) # routes through the same revoke path
    assert not rag.reconcile(manifest).orphans

A diagnostic that deletes is a diagnostic nobody dares run. Auto-remediation on a shared bucket is a data-loss footgun, so reconcile() is read-only by construction and remediate() is the deliberate second step. Removal goes through the existing revoke path — one deletion mechanism, not two.

When the manifest designates one version of a document as current, earlier versions of the same document_id are reported as drifted, not as orphans. They are a known, declared state rather than something that snuck in.

Reconciliation proves a cited document belongs to the agreed corpus. It does not rank the documents inside it, so an in-scope but non-binding source can still win the citation. Attach each document’s standing at ingest and make strict mode refuse below a floor: see Authority — grounding is not standing.

Each run appends to an append-only stream, so “the index matched the agreed corpus at time T” becomes an evidence artifact rather than a verbal assurance. It is a plain JSONL object in the store, one line per run, under the partition’s eval/ prefix — so reading it needs no API at all:

import json
from pathlib import Path
# eval/<partition>/reconcile_log.jsonl — here, the default workspace=default.
log = Path("./citenexus-data/eval/workspace=default/reconcile_log.jsonl")
for line in log.read_text(encoding="utf-8").splitlines():
print(json.loads(line)) # timestamp, manifest_version, counts per set

That the artifact is readable with json and nothing else is the point: an auditor does not have to trust — or install — this library to read it. On S3 it is the same key under the bucket. There is no public accessor for the stream today; citenexus.reconcile.read_audit exists but takes the storage backend, which the client does not expose.

Pass audit=False for a strictly zero-write run when you need to prove the diagnostic touched nothing at all.