docs/falsification-layer.md
The falsification layer
The mission this subsystem serves: Cognithamus is not a system that draws
pictures of repositories. It is a system that takes a claim about a codebase
and provides the strongest available mechanism to prove, disprove, weaken,
qualify, or expose the limits of that claim. The layer that does this is
src/lib/inquiry/, and this document records what was built, what was decided,
what was refused, and what is deliberately deferred.
Repository → Acquisition → World → inquire(claim, world, registry) → Inquiry
The epistemic object
An Inquiry is one claim, evaluated against one World, taken apart:
| part | what it is | its law |
|---|---|---|
claim |
the proposition, worded by the instrument that evaluated it | the evaluated wording is part of the output, so the record cannot test one thing and report another |
evidence |
measured statements, each with a bearing | every statement carries ≥ 1 citation, and every citation resolves |
assumptions |
declared premises | each states what would falsify it |
refusals |
what this World cannot answer | each states the measurement that would resolve it |
defeaters |
the claim's declared failure conditions | each reports untested, tested-and-absent, or triggered |
arithmetic |
the counts | travels with the verdict so the derivation is checkable by eye |
standing |
the verdict | a closed classification, derived by a published rule |
nextMeasurements |
what to measure next | derived from refusals and untested defeaters, never invented |
A Citation is not prose. It is a typed pointer — a stored measurement, a
stored link, one side of the placed/unplaced/unobserved partition, the
observation window, the origin revision — and resolves() verifies it against
the World. After a falsifier answers, the engine audits the finding: a citation
that does not resolve, or that falls outside the instrument's declared read
scope, is a thrown FalsifierViolation, not a degraded answer. An instrument
cannot invent evidence, cannot cite what it did not declare, and cannot drop a
failure condition it promised to watch.
What was refused, and why
A confidence number. Nothing in this system measures the probability that
a claim is true, so a scalar confidence would be decorative intelligence inside
the layer built to forbid it. The reader gets the confidence's anatomy instead
— counts, assumptions, refusals, and which failure conditions were actually
looked for — classified by standingOf, whose rule is published in the model
and re-derived independently in the falsification register's harness.
Advocates. buildRegistry refuses any instrument that declares no
defeaters. An evaluator that cannot say what would refute its own claims is an
advocate, and advocacy is not measurement. This is the registration-time twin
of registerConnector refusing a connector that would drift the ontology.
Unavailability as refutation. When coupling was never read (a window with
no usable commits), a hub claim is refused, never refuted — and when
coupling was read and found empty, that is a measured zero, which does
refute. The distinction is quality.ts's Availability three-state carried
into epistemics, and it is a registered law
(inquiry-absence-never-zero, survived 100,000/100,000).
The growth mechanism
The layer is a contract, not a checklist. A falsifier declares its family (open — structural, historical, ownership, dependency, security, …), the one claim kind it evaluates, the evidence it reads (enforced by a scoped view that throws on undeclared access), and its defeaters. Anything satisfying the contract joins the registry; nothing in the engine knows any falsifier by name. New measurement capabilities expand the falsification universe by widening what views can expose and what instruments can therefore declare — never by redesign.
Three instruments ship, chosen because every measurement they consume already exists in acquired Worlds:
coupling-hub(structural) — is this file a co-change hub?partition-coverage(structural) — does the World cover the repository?sole-authorship(ownership) — was every measured file touched by one author?
What running it against reality found
The first execution against site-world.json — this repository, measured at
bcea73f — falsified the first instrument. src/app/robots.ts cleared the
partner-count bar (27 partners, median 10) on links that each rest on exactly
one shared commit: a bulk change, not co-evolution. The declared assumption
("accidental co-commits weaken it") predicted exactly this failure, so it was
promoted from assumption to a second declared defeater, and the misclassified
hub became a REFUTED standing with the tension visible — supporting evidence,
contradicting evidence, and the triggered condition all on the record.
tests/inquiry.test.ts pins the case. That sequence — instrument, deployment,
refutation, strengthened instrument, pinned regression — is the layer working
on itself, and it is the intended loop for every future instrument.
The same run also produced, about this repository: sole authorship
ESTABLISHED (210/210 files, defeater tested and absent); coverage CONTESTED
(202 placed against 117 unobserved paths, with the resolving measurement named
from the measured extension counts: .md (100), .png (7), .json (5)).
Its own laws, measured
Three laws of the layer are entries in the falsification register
(src/lib/ledger/falsification.ts), attacked with randomized Worlds on every
gate run and recorded at the deep rung:
inquiry-standing-lawful— the verdict matches its published table. 100,000/100,000.inquiry-citations-resolve— every produced inquiry is internally honest. 100,000/100,000.inquiry-absence-never-zero— unread evidence never reads as a zero. 100,000/100,000.
The substrate audit (2026-08-24)
The layer was frozen and audited as core substrate before any expansion. Each
property is pinned in tests/substrate-audit.test.ts; findings that changed
code are listed with what they changed.
1. Renders can consume an Inquiry without interpretation logic. Verified
mechanically: an Inquiry survives JSON round-trip identically (no functions,
no clocks, no undefined), every value a renderer would switch on is from a
closed union, and every cited subject id joins back to the World the render
already consumes. The one dependency found and accepted: citations carry ids
(identity) while statements carry labels (prose), so a render pairs the
Inquiry with its World for display — the same World, no second authority, no
inference. The canonical text projection (scripts/inquire.mts) does exactly
this join and nothing else.
2. The World is the only evidence authority. An allowlist boundary test:
inquiry/ imports only itself and the world layer's pure modules
(types, quality, fold), and its source — comments included — contains no
filesystem, subprocess, database, environment, network, clock, or randomness
reference. Widening the allowlist is a deliberate audit event, not a refactor.
3. Registration is additive. The engine and model name no instrument and no claim kind (asserted as text), and the audit registers a fourth probe instrument beside the shipped three with zero engine change — an executable proof, run on every gate.
4. The canonical artifact. docs/public/canonical-inquiries.json holds
one real epistemic object per standing — established (sole authorship),
contested (coverage), refuted (robots.ts as hub), undetermined (a claim kind
no instrument evaluates yet: the registry-boundary object) — all evaluated
against this repository's measured World. A drift guard re-evaluates and
compares on every run; regeneration is node --import tsx scripts/gen-canonical.mts, and a diff in that file is an epistemic change to
be reviewed as one.
5. Citation traceability. Engine-enforced and double-booked in the audit: every citation resolves, every contradiction carries grounds. One documented shape: a measured absence (zero coupling across a usable window) has no stored row to cite, so it cites the observation window — the record that the system looked. Positive counter-evidence always cites its rows.
6. Refusal quality. Mechanical bar on every refusal in the scenario
matrix: the question is a question, the grounds are stated, the resolving
measurement is named, is distinct from both, and appears in
nextMeasurements. Finding fixed during the audit: a claim about a
measured-but-unplaced subject used to get the same refusal as an unknown path;
it now carries the World's recorded basis ("never changed in the same commit
as another source file") and a matching resolution.
Instrument finding. Extending mutation testing to this layer exposed that
the mutation harness's failure detector was environment-blind: node's test
reporter defaults to TAP when not attached to a TTY, and the matcher reads the
spec reporter's ✖ lines. The harness's own instrument control caught it —
it planted a failure, saw nothing, and refused to report, exactly as designed.
The reporter is now pinned (--test-reporter=spec). Three inquiry mutations
joined the harness: disabling citation resolution, admitting advocates, and
ignoring triggered defeaters. Measured on 2026-08-24: all 37 mutations CAUGHT,
each by exactly its intended invariant — the three inquiry defects included —
under the harness's exact blast-radius rule.
Resolved after the freeze lifted (2026-08-24). The audit's recorded
question — should a hub claim about a subject unplaced because it never
co-changed be refuted rather than refused when the window was usable? —
resolved to refutation. The reasoning: a placed file with zero partners in a
usable window is refuted; the unplaced file's recorded basis states the same
measured zero, and one measured fact must not earn two standings depending on
placement. The boundaries hold: budget-refused subjects (which did
co-change; their degree is simply not embedded) remain refusals, and an
unusable window remains a refusal — inquiry-absence-never-zero still
governs. The canonical undetermined example moved to the registry-boundary
object, which downstream consumers will meet anyway.
Deferred, and recorded as such
Per the anti-drift protocol, the following directly serve the mission but are not built yet, and nothing else should be built before them:
- Rendering the epistemic object through the Reality Engine — claims as
structures, evidence as connections, uncertainty as measurable space,
contradictions as tension, missing information as unexplored regions. The
truth model now exists so the render can emerge from it; the render itself
is Phase 4 and must not precede more instruments only if those instruments
strengthen falsification. Today's render is
scripts/inquire.mts, a deliberately generic text projection ofInquiry. - Historical and dependency families — falsifiers over window series (drift: does structure survive a different observation window?) and over import graphs when that measurement lands.
- Inquiries as evidence — recording an inquiry's outcome so a later inquiry can cite it (Action → New Evidence in the loop). Requires an identity and persistence decision that deserves its own document.
- Falsifier generation — deriving candidate defeaters from a claim automatically. Not before the manual contract has more mileage.