The substrate
contradiction-preserving · evidence-first

Seeing the Substrate: A Visual Language for Claims That Refuse to Collapse

Why a paraconsistent, bitemporal, evidence-first, query-time-aligned, abundance-native CLAIM substrate needs visualizations of its own — and which standard ones quietly betray it.

2026-06-05

1. Thesis: a substrate that refuses the collapses every chart assumes

Almost every data visualization ever drawn rests on four silent collapses. A bar has one height. A node has one value. A timeline has one axis. A schema has one column per fact, fixed before the first row arrives. These collapses are not malice; they are the inherited grammar of tabular and relational data, where the hard, scarce, human-bottlenecked work of deciding what is true was done long before anything reached the screen.

donto exists precisely because that scarcity is gone. A guided frontier model now emits an unbounded, multi-directional, self-typing firehose of claims about any entity for fractions of a cent. The hard problem flipped — from "how do we generate enough?" to "where do we put an unbounded, contradictory, evidence-anchored firehose without throwing most of it away?" donto's answer is to refuse the four collapses. It holds incompatible claims side by side as legal bitemporal state. It anchors each claim to its source. It keeps every freely-minted predicate. It defers typing, alignment, and identity-resolution to query time. It re-ranks by reality over time instead of deleting on conflict.

This puts the substrate on a collision course with the entire standard visualization toolkit. A bar chart of "the predicates" has already deduplicated the 880,000 the substrate deliberately kept. A node labeled port-louis : City has already argmax'd away the ten other readings the substrate is holding. A single timeline has already flattened the two time axes that are the whole point. A merged entity node has already committed an identity the substrate insists on leaving open. Each of these is not merely a lossy rendering — it is a lie about the data. It draws a confident, collapsed world that the substrate, on disk, explicitly does not believe.

So the move is not to find clever ways to fit donto into existing charts. The move is to derive a visual language from donto's refusals. A visualization that collapses what donto refuses to collapse is not a simplification; it is a misrepresentation. This report derives the design principles, grounds them in the live substrate's real magnitudes, and then catalogs concrete views — ordered from most donto-native to least — each scored on how honestly it serves the substrate it claims to show.

2. Design principles for visualizing donto

Each principle below names the substrate property it follows from and the anti-pattern it forbids. They are not aesthetic preferences; they are correctness constraints. A view that violates one is showing a different, simpler, false substrate.

P1 — Never render a contradiction as a point; render the distribution.

Follows from: paraconsistent contradiction-holding. A (subject, predicate) does not resolve to one object — it holds a whole competing population as legal state. Forbids: the argmax. No single node attribute, no "nearest embedding," no "latest value." If eleven readings of port-louis's type coexist, the mark is a weighted spectrum of eleven bands, never one cell. The leader must not erase the tail; single-source bands stay visible because recall is set by generation, not a dedup threshold.

P2 — Two time axes are not negotiable.

Follows from: bitemporality. tx_time (when believed) and valid_time (when true in the world) are orthogonal facts. The gap between them is often the most important thing on the screen. Forbids: the single timeline, and worse, the silent "current state." A correction caps a claim's tx_time while leaving valid_time untouched — that is honest geometry, not a deletion. Any view that collapses to one time axis cannot show belief latency, since-retracted claims, or "what we wrongly believed in April 2026," all of which the substrate can answer.

P3 — Evidence is always one brush away.

Follows from: evidence-first anchoring. Every claim carries (or honestly lacks) a pointer to a byte range in a real source. Forbids: orphaned facts presented as grounded. The source↔claim binding is a first-class on-screen object, brushable in both directions. And where evidence is absent, the view must say so loudly — a hollow rail, not a hidden gap. Faking a spine is worse than drawing its absence.

P4 — Abundance is aggregated-and-drilled, never enumerated, never pruned.

Follows from: generative abundance / emit-free-untyped. 880K predicates, a long-tail of used-once invention, single spans feeding tens of thousands of claims. Forbids: both the "top-20, tail truncated" bar chart (which prunes abundance) and the literal hairball (which tries to draw 18,508 ribbons). Abundance reads as a measured quantity — a weighted bundle with a count, a Zipf tail rendered as a glorified mass, a star field with progressive LOD — expandable on demand, collapsed for none.

P5 — Alignment is a toggle, not a baked schema.

Follows from: query-time predicate alignment. Variant predicates fold to a chosen canonical per query, reversibly, without deleting the variants. Forbids: eager canonicalization. The fold is a lens you put on and take off — animate variants into orbit, never delete them; keep inverse and sub_property edges uncollapsed (an inverse is a direction-contradiction, a sub-property is a hierarchy; folding either to a synonym is its own betrayal).

P6 — Identity boundaries are soft.

Follows from: identity-as-hypothesis. Sameness is a confidence-weighted field, re-resolvable at query time, never a write-time merge. Forbids: the canonical entity node. Boundaries are feathered hulls that grow and split with an acceptance threshold; competing same / possibly_same / distinct / not_enough_information relations all stay drawn, including conflicting ones on the same symbol.

P7 — Confidence and maturity are channels on every mark.

Follows from: the claim lifecycle and the abundance waterline. Every claim has an E-level (maturity) and may have a confidence; they are independent, and a popular claim is not a proven one. Forbids: "truthiness" as a single fused signal, and binary true/false rendering. Maturity textures the mark (hollow E0 hypothesis → solid E4); the waterline between hypothesis and candidate is drawn inside the view. Long-and-hollow (popular but unproven) must look different from short-and-solid (rare but mature).

P8 — Show motion: claims re-rank over time, they do not get overwritten.

Follows from: bitemporal re-ranking. New evidence re-scores the existing pool; the loser stays. Forbids: the destructive update. A demoted claim flows down a rung, never out. A leader change is a line-crossing, with the former leader continuing at a lower rank. The history of re-ranking is itself data.

P9 — Hold disagreement; never average it.

Follows from: the contradiction frontier as donto's differentiator. The sign and direction of an argument edge (rebuts the conclusion vs undercuts the warrant vs offers a different reading) is the payload. Forbids: the undirected "related" graph and the averaged confidence. Two competing answers are a kept fork whose tines each retain their own evidence, maturity, and confidence — collapse is impossible by construction.

P10 — Draw the holes; absence is a finding, not an omission.

Follows from: measurement-as-steering-wheel and evidence-first honesty. Where coverage is thin — no evidence, no confidence, no alignment, no valid-time — that gap is the steering signal for what to do next. Forbids: hiding empty channels. An all-hollow evidence ring, a "valid-time unwired" hatched band, a 100%-unreviewed faint frontier: these are the instrument readings that tell an operator where to extract, anchor, align, and argue next.

3. Grounding in the real substrate

These principles are not abstract. They have to survive the scale of a live, abundance-native store, and that scale is the first thing the views must honor. The magnitudes below are from live inspection of the donto-pg substrate (snapshot dates around 2026-06-04/05). Where a number could not be safely computed under load — full-table GROUP BYs on the 40M-row statement table time out — the report says so and the views are designed around it.

Layer Live magnitude What it means for the views
Believed statements ~39.5–40.2M rows in donto_statement (reltuples 39,525,760–40,196,522) The firehose. No view may attempt an unbounded full scan; everything is index-bound, range-banded, or precomputed.
Contexts ~45,650–45,661 The macro map's nodes. Average ~880 statements/context, but the distribution is wildly skewed (genealogy + genes ≈ 98.7% of mass).
Evidence links 1,958,290 rows → ~949,268 distinct anchored statements Evidence reaches only ~2.4% of statements. The spine is thin — and the views must show that honestly.
Predicates ~865,834–883,426 distinct, freely-minted The abundance signature. Only ~159 are folded via canonical_of; the rest are open. Live planner shows only ~2,574 ever appear in predicate position — abundance is bimodal: a small used core over a vast legal-but-unexercised tail.
Predicate embeddings / closure ~883,180 embeddings (~100% coverage; ~226 unembedded); closure ~883,226 rows, of which only ~9,611 are non-self edges (close_match 8,390 · exact_equivalent 1,083 · inverse 109 · sub_property 29 · decomposition 12) The alignment fabric. The fold is the closure graph, not a committed column.
Entity embeddings ~305,233 Feeds the identity field's projected positions — but only ~60% of identity-edge symbols are embedded, so the rest must be force-placed, never dropped.
Arguments 2,424–2,433 edges; open: rebuts ~2,225 ≫ supports ~132 (alt-analysis 4, supersedes 2); touching only ~1,247 distinct statements (~0.003% of emit); 100% unreviewed The differentiator is barely exercised. Provenance honesty: ~90% of edges live in ctx:epistemic-sweep/contradictions, not genealogy.
Identity edges 53–124 active; same_referent ~71–72 · distinct ~35 · possibly_same ~16 · not_enough_information 1; ~136 symbols provisional, 6 contested Identity machinery is thin but qualitatively complete — all four relations occur, including held abstention.

Two facts dominate the engineering of every view. First, generation is world-class but joining and reality-pull are the bottleneck: evidence anchors ~2.4% of statements, alignment touches ~0.7% of predicates, argument touches ~0.003% of statements. This is not a flaw to hide — it is the central thing the views must surface, because it is exactly the steering signal. Second, the 40M-row table forbids analytical full scans live, so per-subject lenses (index-bound, often single-digit milliseconds) are the safe primary, and any macro view is fed by precomputed materialized tables refreshed off-peak.

4. The visualization catalog

Ordered from most donto-native to least. Each is scored 1–10 on how honestly it serves the substrate's refusals.


4.1 The Bitemporal Plane — donto-native score: 10

Property served (P2, P8, P9, P3, P10). donto's two time axes drawn as what they actually are: a 2D plane, not a timeline. A single fact occupies a rectangle in (valid × tx) space; a correction caps its tx-extent while leaving valid_time untouched. Retraction is honest geometry — a capped top edge — not a tombstone.

Encoding. X = valid_time (when true in the world; daterange, upper-exclusive). Y = tx_time (when believed). Each statement is a rectangle spanning [valid.lower..valid.upper) × [tx.lower..tx.upper). Fill texture is the load-bearing channel: solid if still believed (upper_inf(tx_time), top edge an open arrow to NOW); hatched if superseded/retracted (a hard horizontal top edge = the instant belief ended). Hue is by predicate — not polarity, because polarity is uniform on most corpora (a tiny ⊖ badge marks the rare negated row). Stroke weight is donto_maturity(flags). A left-margin evidence ribbon is green-proportional, or a visible hollow-red strip at zero. A draggable time-travel crosshair at world-moment W and recording-instant T selects every rectangle containing the point, listing "what donto believed at T about W," each tagged STILL-BELIEVED or SINCE-RETRACTED. A geometrically-derived supersession ladder connects rectangles sharing (subject, predicate, valid_time) ordered by lower(tx_time).

Data source. donto_statement (tx_time tstzrange, valid_time daterange, flags), backed by GiST indexes verified live: donto_statement_tx_time_idx, donto_statement_valid_time_idx, the partial donto_statement_retracted_idx, and donto_statement_spo_idx.

SELECT s.statement_id, s.predicate,
       coalesce(s.object_iri, left(s.object_lit->>'v',60))  AS object,
       lower(s.valid_time) AS world_from, upper(s.valid_time) AS world_to,
       lower(s.tx_time)    AS tx_from,    upper(s.tx_time)    AS tx_to,
       upper_inf(s.tx_time)        AS still_believed,   -- solid vs hatched
       (s.flags::int & 3)          AS polarity,          -- ⊖ badge only when 2
       donto_maturity(s.flags)     AS e_level,           -- stroke weight
       (SELECT count(*) FROM donto_evidence_link el
        WHERE el.statement_id = s.statement_id) AS ev_links  -- 0 = hollow-red
FROM donto_statement s
WHERE s.subject = 'ex:darnell-brooks'
ORDER BY lower(s.tx_time), lower(s.valid_time);

-- time-travel crosshair: what was believed at recording-instant T about world-day W
SELECT subject, predicate, coalesce(object_iri, object_lit->>'v') AS object,
       upper_inf(tx_time) AS still_believed_now
FROM donto_statement
WHERE subject = :subject
  AND tx_time    @> :T::timestamptz    -- believed at T (incl. since-retracted)
  AND valid_time @> :W::date;          -- about world-moment W

What it reveals that nothing else can. A wrongful conviction as geometry. On the verified Darnell Brooks corpus (13 rows, 4 retracted): the DNA-exoneration rectangle is true-in-world from 1996 (its valid-left edge), yet acquires tx-extent only in April 2026 — and the vast empty tx-space between "true in the world since 1996" and "believed by the system in 2026" is the 27 years of harm. It is invisible on any single timeline. The eyewitness ID becomes a 3-rung ladder over one world-day (wrong / recanted-on-top / wrong-re-ingest) — the system changing its mind without erasing what it used to think. Two opposite-content identifiedAs claims over the same valid-day are separate, both crosshair-selectable, never averaged.

Anti-pattern avoided. Flattening to one timeline; drawing retraction as deletion; merging same-(subject,predicate,valid) conflicts to "latest"; encoding the contradiction as polarity when the real conflict is opposite content under uniform polarity; faking an evidence spine (the all-hollow Brooks ribbon honestly exposes ~4.7% anchoring coverage).

  tx_time  (WHEN donto BELIEVED it)                    crosshair T ─┐
   ▲  NOW ════════════════════════════════════════════════════════╪══ ◄ open ↑ = "still believed"
   │ 2026 ┌─dnaResult──────────────────────────────────────────┐  ┊
   │      │SOLID  believed Apr-2026 · valid 1996-04-11→2023-08-30│ ┊   RIGHT RAIL @ (W,T)
   │      └──────────────────────────────────────────────────────┘ ┊   ✗ convictedOf (SINCE-
   │      ┌─identifiedAs──────────────────────────────┐            ┊      RETRACTED — tx-top
   │      │SOLID "i was scared… officer said it was him"│  rung 3   ┊      capped, valid intact)
   │      └────────────────────────────────────────────┘  ▲        ┊   ✗ identifiedAs "i'm
   │      ╱╱╱identifiedAs "i'm sure it was him"╱╱╱╱╱╱╱╱╱╱   │supersedes  sure it was him"
 T ┄┄┄┄┄┄╱╱╱HATCHED 1st belief ~27ms thin╱╱╱╱╱╱╱●┄┄┄┄┄┄┄┄┄│ ladder  ┊   ✔ reportedBy (still
   │      ┌─convictedOf─────────────────────────┐                  ┊      believed)
   │      ╱HATCHED valid 1996-04-11→1997-03-22╱╱╱│ (belief capped)  ┊  ← drag T down = rewind
   └──────┬──────────────────────────┊──────────────────────────────► valid_time (true in world)
   EVID:  ▌ ← ribbon column ALL HOLLOW-RED = 0 evidence_links (honest gap)
       1996-04-11                    ┊ W=1996-04-11        2023-08/09        +inf⇢
  THE GAP: dnaResult is HIGH on tx (believed 2026) but its valid-left sits at 1996 = 27 yrs of harm.

Feasibility. High. All required indexes exist on the live 40M-row table; the three queries run against ex:darnell-brooks. Per-subject lens is index-bound and instant. A BitemporalPlane.tsx renders rectangles in plain SVG with two d3-scales and two draggable guides (~180 lines, no new dependency). The context-wide variant must be range-banded and LIMITed — never an unbounded scan. Effort: ~1 day per-subject, +1 day for the banded wide view.


4.2 The Belief Spectrum — donto-native score: 9

Property served (P1, P7, P8, P3, P10, P5). Paraconsistency rendered as a standing distribution, not a value. For one (subject, predicate), the whole competing population of objects sits side by side as a horizontal weighted spectrum — summed but never argmax'd.

Encoding. One bar per (subject, predicate); one segment per distinct (object, polarity) pair. X-length = support mass w = n_rows + ln(1+evidence_links) + 0.5·max_E, laid end-to-end so the full bar = total competing support (no normalize-to-100%, which would imply candidates apportion a single truth). A faint dashed "argmax cut" marks where a naive KG would slice — drawn only to be visibly rejected, with the tail extending past it. Hue = polarity (asserted slate / negated red / unknown grey / absent amber), so the same object label can occupy two bands at once. Fill texture = maturity (E0 hollow-hatched → E4 solid), with the waterline drawn inside the bar. An evidence rail beneath each segment: one tick per donto_evidence_link; an empty rail reads "asserted but unanchored." A bitemporal scrubber re-ranks the same bands; a "fold aligned predicates" toggle pours closure variants into the same spectrum at query time.

Data source. donto_statement, donto_polarity(flags), donto_maturity(flags), donto_evidence_link, donto_predicate_closure (for the fold), donto_argument (for hover).

SELECT COALESCE(s.object_iri, s.object_lit->>'v')  AS object,
       donto_polarity(s.flags)                     AS polarity,
       count(*)                                    AS n_rows,
       count(DISTINCT s.context)                   AS n_contexts,
       max(donto_maturity(s.flags))                AS max_E,
       count(el.link_id)                           AS evidence_links,
       round((count(*) + ln(1+count(el.link_id))
              + max(donto_maturity(s.flags))*0.5)::numeric,2) AS weight
FROM donto_statement s
LEFT JOIN donto_evidence_link el ON el.statement_id = s.statement_id
WHERE s.subject = 'ex:port-louis' AND s.predicate = 'rdfType'
  AND upper_inf(s.tx_time)         -- scrubber swaps to tx_time @> :as_of
GROUP BY 1,2 ORDER BY weight DESC;
-- LIVE: Place asserted 16src/E4 · City asserted 4src/E4 · ShipbuildingCentre/
--   CommercialHub/NavalBase/Port 1src/E4 · ColonialFoundation 1src/E3 ·
--   City UNKNOWN 2src/E0 · CapitalCity UNKNOWN 2src/E0 · PortCity/Settlement 1src/E0.
--   11 bands; evidence_links = 0 for all (honest hole).

What it reveals. That port-louis is not "a City" but a shape of disagreement: a dominant Place/City core (heavy, mature, multi-source) with a fan of single-source readings a KG would have argmax'd away. Four things at once: how much agreement (leader length vs the bar), how well-grounded (the empty evidence rail screaming "0 anchors: popular ≠ proven"), where the disagreement frontier is (the genuine City-asserted-E4 beside City-unknown-E0 split, taken straight from the rows), and — with the scrubber — the trajectory a snapshot store destroys. The two empty channels (evidence, confidence) double as a data-quality x-ray.

Anti-pattern avoided. The argmax to one object; normalizing to 100%; overwrite-on-update; and — caught in an adversarial pass — fabricating contradiction (an earlier draft painted a red "negated" band that does not exist in the rows; the refined view draws only polarities the query returns).

  ex:port-louis  ──  rdfType          [fold aligned ▢]   as-of: now ◄────────●  tx
  ─────────────────────────────────────────────────────────────────────────────
  ▏support weight →                              ┊ argmax cut a naive KG makes (REJECTED)
  Place        ████████████████████████████████ ┊  16 src · E4 · ev:---- · conf:○
  City         ██████                            ┊   4 src · E4 · ev:---- · conf:○
  NavalBase    ███                               ┊   1 src · E4 · ev:---- · conf:○
  ColonialFnd  ██▒                               ┊   1 src · E3 · ev:---- · conf:○
  City         ▢▢                                ┊   2 src · E0 · ev:---- ← grey: UNKNOWN polarity
  CapitalCity  ▢▢                                ┊   2 src · E0 · ev:----
  ─────────────────────────────────────────────────────────────────────────────
  fill: █ E4 solid  ▒ E3  ▢ E0 hollow   hue: slate=asserted grey=unknown
  ●scrub tx_time → bands re-rank, none deleted (ghost = prior order). No single winner.

Feasibility. Low-medium. The spectrum SQL runs live and returns the 11 bands. A SpectrumBar component reuses the existing CSS bar idiom (flex rows, width = weight%, hue = polarity class, fill = E-level). The contested-pairs discovery (which pairs have >1 object) must come from a precomputed donto_contested_pairs MV refreshed by the alignment daemon, because the full-table scan times out; per-subject render stays index-bound.


4.3 The Evidence Ribbon — donto-native score: 9

Property served (P3, P2, P4, P7, P10). Evidence-first anchoring made a linked, brushable, bitemporal artifact. The source↔claim binding is the primary on-screen object, and it lives in time — you can scrub it through tx_time and watch a document acquire its anchors as belief accreted.

Encoding. Three linked regions with a global time scrubber. Top: a tx_time scrubber over the document's belief timeline (262 distinct points on the verified doc), plus a faint valid_time ghost rail honestly labeled "unbounded" when unset. Left: the source body as a monospace strip with every anchored char range painted inline. Middle gutter: aggregated SVG ribbons. Right: claim cards aligned to their span y-position. Color is the empirically-correct epistemic class — anchored-stated = teal; hypothesis-only, which the live data proves is 100% homeless, gets an amber card in a bottom rail with a broken dotted leader and a "no span" tick. Ribbon width + a count badge = fan-in (a span anchoring N claims emits one bundle, width ~ log N, expandable to ~200 ribbons + "and N more"). Opacity = confidence; left-border thickness = maturity; an icon = polarity; a tx-tick dots each card's mini-axis.

Data source. donto_document_revision (body / body_inline), donto_span (start/end_offset, surface_text), donto_evidence_link (link_type='anchored_at', the dominant type at ~1.78M rows; confidence; its own tx_time), donto_statement, donto_stmt_hypothesis_only.

WITH rev AS (SELECT revision_id FROM donto_document_revision
             WHERE document_id = $1 ORDER BY revision_number DESC LIMIT 1)
SELECT s.statement_id, sp.span_id, sp.start_offset, sp.end_offset, sp.surface_text,
       s.subject, s.predicate, COALESCE(s.object_iri, s.object_lit->>'v') AS object,
       round(el.confidence::numeric,3) AS confidence,   -- opacity
       donto_maturity(s.flags)         AS e_level,       -- card border
       lower(s.tx_time)                AS believed_at,   -- tx-tick / scrub axis
       (h.statement_id IS NOT NULL)    AS is_hypothesis_only
FROM donto_statement s
JOIN donto_evidence_link el ON el.statement_id = s.statement_id
     AND el.link_type='anchored_at' AND el.tx_time @> $2::timestamptz   -- AS-OF
JOIN donto_span sp ON sp.span_id = el.target_span_id
JOIN rev ON sp.revision_id = rev.revision_id
LEFT JOIN donto_stmt_hypothesis_only h ON h.statement_id = s.statement_id
WHERE s.tx_time @> $2::timestamptz
ORDER BY sp.start_offset, el.confidence DESC LIMIT 800;

-- fan-in MUST be aggregated (verified [386,432) → 18,508 claims; never one ribbon each):
SELECT sp.span_id, sp.start_offset, sp.end_offset,
       count(DISTINCT el.statement_id) AS fan_in
FROM donto_span sp JOIN rev ON sp.revision_id=rev.revision_id
JOIN donto_evidence_link el ON el.target_span_id=sp.span_id
     AND el.link_type='anchored_at' AND el.tx_time @> $2::timestamptz
GROUP BY 1,2,3 ORDER BY fan_in DESC;

What it reveals. Faithfulness at a glance: the teal:amber ratio and the size of the homeless rail is the document's evidence-first health. Belief-accretion over tx_time: scrubbing shows anchors fading in as belief accreted across the run. The abundance fan, honestly scaled: one span feeding 18,508 claims as a weighted, counted, expandable bundle — the one-paragraph→many-claims multiplication, neither hidden in a flat table nor faked as a hairball. A hallucinated-span audit: surface_text vs the claim's object side-by-side catches a co-location false positive by eye.

Anti-pattern avoided. Flattening the time axes (an earlier draft showed a static snapshot, discarding the 262 belief-instants); collapsing abundance to a hairball or a winner; mismodeling the epistemic classes (the live data proves hypothesis_only ≡ homeless, so the view models the true 2×2 possibility-space and lets a non-occurring cell read as legal-empty); and silently showing a claim-without-provenance as if grounded.

  tx_time SCRUBBER  ◀ 2026-04-17 ┃━━━━●━━━━━━━━━━━━┃ 2026-04-18 ▶   262 belief-points
  valid_time ghost: ┄┄┄┄┄┄ unbounded (not set on extracted claims) ┄┄┄┄┄┄  (faint, never faked)
  ┌─ SOURCE  body_inline 47,040 ch ─┐  RIBBON (fan AGGREGATED)  ┌─ EXTRACTED CLAIMS ─┐
  │▓tags:[kelly,avani,dna,ancestry]▓│█████████████████▶ ⑱⁵⁰⁸    │███E2 + ·tags·  TEAL c1.00▮│ ◀bold=hi-conf
  │ [386,432) «anchored ×18,508»    │ click bundle → fans to 200 │   '…and 18,308 more'      │
  │▓source: ancestry-dna-C76D4A33▓  │██████▶ fan ⑮⁴⁴⁰ faint(low) │▍E0 + ·source·  teal c0.40•│
  └─────────────────────────────────┘                            └──────────────────────────┘
  ┌─ HOMELESS / HYPOTHESIS-ONLY RAIL (interpreted, NO source home) ─┐  2×2 (empty cell=legal-empty):
  │ ⌀ ··(broken leader)·· ✗no-span ▶ ▍E0 ~ ·inferredKinship· AMBER │   hyp-only: AMBER▒ │ (rare)
  │ on this clean doc the rail is EMPTY → all anchors teal = healthy│   stated:   TEAL▓  │ (grey)
  └────────────────────────────────────────────────────────────────┘

Feasibility. Extends the shipping evidence-anchors lens. A new EvidenceRibbon.tsx (React + inline SVG beziers, no new dep). All queries hit existing indexes; the scrubber is one cheap distinct lower(tx_time) group-by. Fan-expansion must be virtualized (real fan-in reaches 18,508). Effort ~1.5–2 days.


4.4 The Reality Ladder — donto-native score: 9

Property served (P8, P7, P3, P9, P6, the steering loop). donto re-ranks by reality, never by deletion. Two coupled panels make the ladder motion the subject: a cohort Sankey of claims climbing/sliding between maturity rungs over tx_time, and a head-to-head no-deletion rank race over one genuinely-contested question where the leader changes as supports/rebuts edges land yet every loser stays.

Encoding. Panel A (Sankey): vertical bands = E-levels (E0 bottom → E7 top; unreached upper rungs drawn as labeled ghost bands — honesty about how thin promotion is). Horizontal = monthly tx_time buckets. Ribbon width = count making that transition; hue = direction (amber promotion, teal demotion, grey stayed). Demotion ribbons flow down a rung, never out. A bright waterline between E1 and E2 marks the .candidate → .proved gate. Panel B (no-deletion bump race): one polyline per competing claim; y = rank computed at each tick from E-level + Σ supports.strength − Σ rebuts.strength. Evidence-arrival glyphs sit on the lines at each donto_argument edge's tx_time; a hollow circle = a same_referent edge, so a "flip" can be re-read as a merge. A loser does not vanish — its line continues muted at a lower rank. A valid_time sparkline under each label keeps the second axis distinct. Because edges arrive bunched (often within one ingest day), x is a hybrid: monthly buckets coarsely, edge-arrival ordinal within a bucket, with an always-on sparseness badge so motion is never over-claimed.

Data source. donto_statement (donto_maturity(flags) = (flags>>2)&7; tx_time, valid_time), donto_argument (relation, strength, tx_time, evidence_anchor_ids).

-- Panel A: E-level cohort per tx_time bucket (real context, verified live)
SELECT date_trunc('month', lower(tx_time))::date AS bucket,
       donto_maturity(flags) AS e_level, count(*) AS n
FROM donto_statement
WHERE context = 'ctx:genes/annan-river-frontier-violence'  -- 297 rows, E0/E1, Apr+May
GROUP BY 1,2 ORDER BY 1,2;

-- Panel B: bump race for ONE VERIFIED contested question
WITH claims AS (
  SELECT s.statement_id, COALESCE(s.object_lit->>'v', s.object_iri) AS answer,
         donto_maturity(s.flags) AS e_level, lower(s.tx_time) AS believed_at
  FROM donto_statement s
  WHERE s.subject='game:TK5N4/iri/colonel-mustard' AND s.predicate='game:locatedAt')
SELECT c.answer, c.believed_at, c.e_level,
       a.relation, a.strength, lower(a.tx_time) AS edge_at, a.evidence_anchor_ids
FROM claims c
LEFT JOIN donto_argument a ON a.target_statement_id = c.statement_id
     AND upper(a.tx_time) IS NULL
ORDER BY c.answer, edge_at NULLS FIRST;
-- verified: 'kitchen' 4 [email protected] vs 'outside' [email protected], both held open.

What it reveals. That donto prunes by reality, not deletion: the losing answer keeps a continuous lower line, still queryable; the Sankey's demotions flow down a rung, not out. The exact tx_time a rebuts edge (traceable to its source span) flipped the leader. Whether a claim fell because it stopped being believed (tx closed) or stopped being true (valid ended). And at cohort scale, the abundance waterline honestly: almost nothing crosses E1→E2, which is the point — reality filters the firehose to a trickle without throwing rejects away.

Anti-pattern avoided. A static confidence badge; invalidate-on-conflict; and — caught in the adversarial pass — fabricating a contradiction from a one-to-many relation (an earlier draft used hasPassenger, which is 91 co-true passengers, not competing answers; replaced with a verified rebuts pair).

PANEL A — MATURITY-LADDER SANKEY                  PANEL B — NO-DELETION BUMP RACE
 E2..E7 | (ghost: unreached on this context)      Q: colonel-mustard locatedAt ? [edges:5/1 day]
 - - - -+- - - - - - - WATERLINE (E1→E2) - - -    #1 kitchen o========\  vvvv (4 [email protected])
 E1     | ###(118) \__teal v__#(1)                #2 outside o====^====/====LEADER ([email protected])
 E0     | ######(179)#####################        loser keeps a continuous lower line (RANK, not DELETE)
 nothing leaves a band; demotions go DOWN         o = same_referent (a flip… or a MERGE?)
 ghost E2+ bands ARE the abundance story          toggles: [E-only | E+arg-net | task-lift]

Feasibility. Panel B is a near-direct recharts LineChart with custom glyphs and a client-side dense_rank reducer. Panel A's rung-band Sankey needs d3-sankey or hand-rolled SVG ribbons. Both queries are context/subject-scoped onto indexed paths. Ship as a "frontier monitor" that grows as the contradiction machinery is run — never as a demo implying dense motion exists today. Effort: ~1.5 days B, ~2.5 days A.


4.5 The Merge Basin — donto-native score: 10

Property served (P6, P3, P10, P2.) Identity-as-hypothesis made literal: sameness is a confidence-weighted field of four competing relations, rendered as a soft-bordered basin landscape whose boundaries are a live function of one acceptance threshold τ.

Encoding. Each symbol is a dot inside zero or more nested fuzzy hulls. Hue = entity_kind; ring = the full six-valued identity_status (provisional thin grey / contested pulsing amber / stable solid / merged dashed-ghost / split forked / deprecated faded). Position = 2D PCA/UMAP of donto_entity_embedding — but only ~60% of identity-edge symbols have a vector, so unembedded symbols are force-placed from edge neighbors and drawn with a hollow "no-vector" glyph, never dropped. same-edges: width and saturation ∝ confidence, line style = method (human solid, embedding+LLM dashed, test dotted). possibly_same = thin amber dashed. distinct_referent = a red double-bar wall drawn on top — an anti-merge barrier; a same-edge and a distinct-wall can both touch the same pair and both stay drawn. not_enough_information = a dotted-grey abstention bridge with a "?" cap, distinct from "no edge at all." Basin hull = a feathered concave hull around every component formed by same/possibly_same edges with confidence ≥ τ, minus any cut a distinct-wall ≥ τ forces; a basin enclosing an internal wall gets a hatched contested fill. The τ-slider re-thresholds live (pure client-side filter — instant, no re-query): hulls grow/shrink, components fuse/split, with a ghost outline of the previous τ. A tx_time as-of scrubber replays how a basin formed.

Data source. donto_identity_edge (relation enum: same_referent / possibly_same / distinct / not_enough_information; confidence; method; CHECK left<right), donto_entity_symbol (entity_kind, six-valued identity_status), donto_entity_embedding (join by iri, not symbol_id).

SELECT e.edge_id, e.left_symbol_id, e.right_symbol_id, e.relation,
       e.confidence, e.method, e.explanation,
       ls.iri AS left_iri,  ls.entity_kind AS left_kind,  ls.identity_status AS left_status,
       rs.iri AS right_iri, rs.entity_kind AS right_kind, rs.identity_status AS right_status,
       (e.relation = 'distinct_referent')     AS is_wall,
       (e.relation = 'not_enough_information') AS is_abstention
FROM donto_identity_edge e
JOIN donto_entity_symbol ls ON ls.symbol_id = e.left_symbol_id
JOIN donto_entity_symbol rs ON rs.symbol_id = e.right_symbol_id
WHERE upper(e.tx_time) IS NULL              -- believed-now; swap for tx_time @> :asof
ORDER BY e.confidence DESC;
-- LIVE: 123 active edges over 142 symbols (only 85 embedded → 57 force-placed);
--   same 71 / distinct 35 / possibly 16 / not_enough_information 1; 6 contested symbols.
--   τ is a UI value, recomputed client-side — never bound into SQL.

What it reveals. What a deduped graph structurally cannot: the merge basin's shape as a function of your acceptance threshold, and which sameness claims are robust vs fragile. "At τ=0.95, symbols 125/126/127/130 do not all fuse — the 0.99 distinct-wall 126↔130 cleaves the basin." The abstention bridge surfaces cases the substrate honestly declined to decide. The six-valued status shows standing independently of edge geometry. Embedding-projected dots reveal symbols semantically adjacent with no identity edge yet — candidate merges the engine hasn't proposed.

Anti-pattern avoided. Hard-dedup merge-on-ingest (discarding variants, confidences, methods, walls, abstentions, and the audit trail); treating unembedded symbols as droppable noise; folding not_enough_information into silence; flattening the six-valued status to a binary.

 IDENTITY MERGE-BASIN  · ●person ◆place ▢no-vector · ── human ┄ embed+llm ··· test
 ┌──────────────────────────────────────────────────────────────────────────────┐
 │   .·°°°·. BASIN A           ╔═══ CONTESTED BASIN B (hatched = contains wall) ══╗ │
 │  ; ●1 ─0.98─ ●3 ;           ║  ●125 ─0.95─ ●127 ─0.94─ ●141                    ║ │
 │  ; ▌▌0.99▌▌ ●2  ; ← WALL    ║   ●126 ▌▌▌ 0.99 ▌▌▌ ●130  ⊛contested            ║ │
 │   '·.(held distinct).·'      ╚═══════════════════════════════════════════════╝ │
 │   ●82 ·····?····· ●96  ← not_enough_information : ASKED, DECLINED (abstain)     │
 │   ▢61 (no embedding → force-placed, kept)   ·· latent (embed-near, NO edge) ·· │
 └──────────────────────────────────────────────────────────────────────────────┘
   τ ◀──────────[●0.95]────▶  at τ=0.95: 7 basins · 18 merged · 2 contested · 1 abstain
   tx_time AS-OF: ◀──[ 2026-06-05 ]──▶  (replay how basins FORMED — never overwrite)

Feasibility. Strong fit but with an honest dependency correction: the admin app has no chart lib installed (the "recharts in node_modules" note was a stale artifact from a sibling app), so this needs d3 (or d3-polygon + d3-force) and ml-pca, both small client-side libs. The data is tiny — 123 edges over 142 symbols ship in one query, no 40M-row scan. τ re-thresholding is pure client-side filtering; only the as-of scrubber re-hits Postgres (cheap, gist index). I3-safe by construction (the propose-same/distinct/insufficient action writes only additive edges). Effort ~1.5–2 days v1, +1 day for the as-of replay and write path.


4.6 The Predicate Constellation — donto-native score: 9

Property served (P4, P5, P9, P10, P2.) Query-time predicate alignment over generative abundance. 880K freely-minted predicates as a UMAP star-map where a fold lens collapses a synonym family to a query-chosen canonical without removing the stars.

Encoding. Position = UMAP of donto_predicate_embedding (the same bge-small space that drives alignment, so proximity is the alignment signal). Size = predicate-position usage (sqrt + floor so the ~880K zero-usage stars stay visible as faint pinpoints — the long tail is the point). Hue = closure family (connected component of synonym-class edges only). Edges are styled by relation, and this is where the refinement bites: exact_equivalent solid and close_match dashed collapse on fold; but inverse_equivalent (a direction-contradiction, drawn with swap_direction) and sub_property_of (a hierarchy) do not collapse — they survive as typed edges between surviving canonicals. The fold toggle animates synonym variants into the canonical's orbit, labeled "+N folded," and the folded stars shrink to a dim satellite ring — abundance visibly held, not deleted. A per-context fold-scope selector re-runs the same closure over a context-filtered edge set and re-chooses canonicals differently. A bitemporal scrubber over first_aligned_at replays families crystallizing as the daemon ran.

Data source. donto_predicate (canonical_of set on only 159 rows — not the fold key), donto_predicate_embedding (~100% coverage), donto_predicate_closure (9,611 non-self edges), donto_statement (usage via donto_statement_predicate_idx). UMAP is precomputed offline into a new donto_predicate_projection table refreshed by the daemon.

WITH usage AS (   -- fast index-only scan; ~2,574 nonzero rows
  SELECT predicate AS iri, count(*) AS n FROM donto_statement
  WHERE upper(tx_time) IS NULL GROUP BY predicate),
syn AS (          -- synonym-class edges only (the ones that may collapse)
  SELECT predicate_iri AS a, equivalent_iri AS b, relation, confidence
  FROM donto_predicate_closure WHERE relation IN ('exact_equivalent','close_match'))
SELECT p.iri, COALESCE(u.n,0) AS usage,
       (e.iri IS NOT NULL)    AS embedded,    -- opacity (~226 false → hollow ring)
       proj.x, proj.y, proj.first_aligned_at
FROM donto_predicate p
LEFT JOIN usage u ON u.iri = p.iri
LEFT JOIN donto_predicate_embedding e ON e.iri = p.iri
LEFT JOIN donto_predicate_projection proj ON proj.iri = p.iri
ORDER BY usage DESC NULLS LAST LIMIT 5000;   -- canvas streams the rest; NOTHING dropped

-- edge layer, relation-styled; inverse/sub_property/decomposition PRESERVED on fold:
SELECT predicate_iri, equivalent_iri, relation, swap_direction, confidence
FROM donto_predicate_closure
WHERE relation IN ('exact_equivalent','close_match','inverse_equivalent',
                   'sub_property_of','decomposition');   -- 9,611 rows, trivial

What it reveals. That 880K predicates are not noise but a navigable, similarity-structured possibility-space whose alignment is reversible, per-query, and relation-typed. You watch the real cross-vocabulary name family (btcrm:name ↔ schema:name ↔ foaf:name ↔ ex:name ↔ dozens of test:ingest:*/name hashes — all live close_match edges) fold into one canonical, then change the fold scope and watch the same stars regroup — proving identity/typing was deferred, not committed. Dense bge-small clusters with no synonym edges (e.g. killedBy near assassinatedBy) are actionable alignment gaps. The usage side-histogram shows the bimodal truth: only ~2,574 IRIs are ever used as predicates; ~880K are legal-but-unexercised.

Anti-pattern avoided. Treating 880K predicates as proliferation (a top-20 bar with the tail truncated, or an eager-deduped canonical set); relying on the near-dead canonical_of path; and — the cardinal sin — flattening every closure family to a point, which would collapse a direction-contradiction (inverse) or a hierarchy (sub-property) into a synonym.

 PREDICATE CONSTELLATION · UMAP(883K stars)  [FOLD:OFF] scope[raw▾] tx⟦●──⟧2026-06
 │  btcrm:name ══exact══(✦NAME)══exact══ makssalons:name        │ USAGE (bimodal)
 │   ·foaf:name ╱ ║ ╲ ·schema:name  ·test:ingest:*/name(×many)  │ used-as-pred ~2,574 ▓
 │   parentOf ↤inverse↦ childOf   (DIRECTION-CONTRADICTION, kept)│ legal/unexercised ~880K ░
 │       │sub_property_of(taper)                                 │ ✦ query-canonical(ring=N)
 │   ·killedBy ·assassinatedBy  ⚠ ALIGNMENT GAP (no synonym edge)│ ◌ unembedded(~226 hollow)
 ── FOLD:ON ── (synonym classes only; inverse+subProp PRESERVED) ──────────────────
 │   (✦ name +40 folded)·°°°°   parentOf ↤inverse↦ childOf  ← NOT collapsed
 │   ·° dim satellites = variants STILL HELD (not deleted)   hasFather/hasMother ↦ subProp
 │   tx-scrub◀ drag back → families minted later FADE OUT (alignment crystallizing)
 fold = reversible query-time LENS (animate-into-orbit, never DELETE) · I3-safe

Feasibility. Needs deck.gl (GPU ScatterplotLayer + LineLayer) to handle 880K points with progressive LOD — SVG/recharts cannot. The fold toggle is pure client state (no DB writes); inverse/sub_property/decomposition render in a separate pass so the fold can't touch them. The offline UMAP + materialized projection table + daemon hook is ~1 day; the deck.gl scatter + typed edges + fold animation ~2–3 days. The usage GROUP BY is index-only and fast (~2,574 distinct) — not a timeout risk.


4.7 The Abundance Signature — donto-native score: 10

Property served (P4, P9, P3, P7, P2, P5.) Generative abundance made legible as a positive shape — paired with a provenance-carrying, multi-directional claim fan, so abundance is shown globally (the Zipf tail) and locally (one entity's radial decomposition) without dropping any of the other invariants.

Encoding. Two coupled, linked views. View A — rank-frequency (Zipf), log-log: one point per distinct believed-predicate; x = log10(usage rank), y = log10(count). Hue = usage zone (head cool, midband teal, hapax hot magenta — deliberately the most saturated, inverting the "tail = noise" instinct). A small ring marks the 159 aligned predicates vs the ~880K open ones (deferred alignment, visible). The right-edge hapax cloud is one translucent mass band with a callout "N predicates used ONCE = abundance asset (kept, never pruned)." A faint reference line at ideal Zipf slope (−1) makes donto's fatter-than-power-law tail read as more free invention. An "as-of tx_date" toggle re-runs the rollup at a prior transaction time. View B — the multi-directional claim fan (radial): subject at center; one ray per believed (predicate, object); angle = hash(predicate name) so unrelated predicates spread in all directions; radius inversely proportional to global predicate frequency, so self-invented predicates sit on the rim. Each ray carries five channels: leaf disc filled (has evidence) vs hollow (unanchored); stroke weight = maturity; opacity = confidence; dashed = hypothesis_only; a badge = valid_time + tx-status. Where ≥2 rays share a predicate but differ in object, draw forked twin/triple rays joined by a dashed crimson arc — each tine keeping its own evidence, maturity, and confidence.

Data source. donto_predicate (883,426 rows; 159 aliased via canonical_of), donto_statement (~40.2M), and the side tables donto_stmt_extraction_level, donto_stmt_confidence, donto_stmt_hypothesis_only, plus donto_evidence_link. View A needs a nightly donto_predicate_usage rollup (does not yet exist; the full 40M-row group-by times out, but each per-predicate count is an index-only scan ~40ms).

-- View A rollup (nightly; cheap because each count is index-only)
CREATE TABLE donto_predicate_usage AS
SELECT predicate, count(*) AS uses, rank() OVER (ORDER BY count(*) DESC) AS usage_rank
FROM donto_statement WHERE upper(tx_time) IS NULL GROUP BY predicate;

-- View B: one entity's provenance-carrying multi-directional fan (index-backed, live)
SELECT s.statement_id, s.predicate, COALESCE(s.object_iri, s.object_lit->>'v') AS object,
       u.uses AS pred_global_uses, p.canonical_of AS aligned_to,
       lower(s.valid_time) AS valid_from, upper_inf(s.tx_time) AS believed_now,
       el.level AS maturity, (ho.statement_id IS NOT NULL) AS hypothesis_only,
       cf.confidence,
       EXISTS (SELECT 1 FROM donto_evidence_link e
               WHERE e.statement_id = s.statement_id) AS has_evidence
FROM donto_statement s
LEFT JOIN donto_predicate_usage       u  ON u.predicate     = s.predicate
LEFT JOIN donto_predicate             p  ON p.iri           = s.predicate
LEFT JOIN donto_stmt_extraction_level el ON el.statement_id = s.statement_id
LEFT JOIN donto_stmt_hypothesis_only  ho ON ho.statement_id = s.statement_id
LEFT JOIN donto_stmt_confidence       cf ON cf.statement_id = s.statement_id
WHERE s.subject = 'ex:george-edgar-davis' AND upper(s.tx_time) IS NULL
ORDER BY u.uses ASC NULLS FIRST LIMIT 200;
-- verified: 156 believed rays; birthYear cluster {1883-09-03, 1886, 1887, ~1887 vs 1883};
--   diedAt → 3 objects; causeOfDeath 1a/1b; AND a self-minted discrepancyInField → ex:birth-year.

What it reveals. That abundance has a measurable, beautiful shape, and that donto keeps — with full provenance and both time axes — the part every other system deletes. A standard KG shows a clean canonical-predicate table of a few hundred rows; it literally cannot render the tail (folded at write time), the held fork (one side invalidated on insert), or per-claim evidence/maturity/valid-time (collapsed into "current state"). Here: the fatter-than-Zipf tail, the magenta mass of used-once predicates as legal state, that almost every predicate is still open, and that one entity is described in dozens of orthogonal self-invented directions with disagreeing directions held as forks. The most striking reveal: the substrate even mints meta-claims about its own contradictions (discrepancyInField → ex:birth-year). And the honest twist — drawing evidence truthfully shows these held contradictions are not yet anchored (mostly hollow leaves), which is exactly the steering signal for what to anchor next.

Anti-pattern avoided. The fixed-schema canonical-predicate table; the muted-gray "noise to clean" tail; collapsing the fork to an average; flattening the time axes; hiding provenance/confidence behind a single boolean.

VIEW A — predicate rank-frequency (log-log)   [. head : midband # used-once  o ring=aligned]
1e4 |  ..:                . . . ideal Zipf slope -1
1e2 |     :::::
 10 |          ::::::::::
  1 |.............. ###################  <- HAPAX (brightest) | 883,426 distinct predicates
                                          o aligned 159  o OPEN/foldable 883,267  ~88% used ≤5×

VIEW B — provenance fan of ex:george-edgar-davis (rare preds on rim; 156 rays)
  leaf (*)=anchored (o)=hollow/unanchored · stroke=maturity · dashed=hypothesis · opacity=conf
           birthYearCirca --(o)1886    birthImpliedYear --(o)1887   )BIRTH-YEAR
   bornOn --(o)1883-09-03   birthYearCandidate +--(o)~1887 +--(o)1883 )CONTRADICTION (held)
   diedAt +--(o)district-hospital-mossman +--(o)ex:mossman +--(o)'Mossman'(lit)  )HELD ×3
   discrepancyInField --(o)ex:birth-year  ← substrate's OWN meta-claim about the discord
   honest finding: nearly every leaf is (o) hollow → these contradictions NOT yet anchored

Feasibility. Low-to-medium. recharts (in the admin node_modules) covers View A directly (~1 day). The one hard prerequisite is the nightly donto_predicate_usage rollup. View B is a hand-rolled SVG radial layout or d3-force with the five LEFT JOINs and the contradiction GROUP BY … HAVING count(DISTINCT object) > 1 (~2–3 days). It directly upgrades five currently-tabular lenses (Predicate Reach, Entity Reach, Contradictions Held, Provenance & Maturity, Bitemporal Belief) into one provenance-honest object.


4.8 The Contradiction Frontier (Argument Graph) — donto-native score: 9

Property served (P9, P3, P7, P2, P10.) donto_argument is the only place where claims argue with each other as typed, signed, evidence-anchored edges. The view renders the contradiction frontier as a defended/besieged/undercut landscape — the sign and direction of each relation being the payload.

Encoding. Marks are claim-nodes (both donto_argument endpoints are statements; the arguing agent is edge metadata, surfaced on click — never a phantom node). Polarity of the relation is the load-bearing channel: supports solid green (filled arrowhead at the conclusion); rebuts solid red (open-V at the conclusion); undercuts dashed orange (arrowhead on the edge midpoint — the warrant, not the conclusion, AIF-faithful); qualifies thin blue; supersedes purple with a clock glyph (a tx-ordered replacement, not a logical attack); alternative_analysis_of grey-dotted brace (two readings). An unrecognized relation stays grey-dotted and labeled with its raw string. Edge width = strength, but NULL strength renders as a distinct hairline-hollow "unweighted assertion" glyph (never zero, never a faked default). Edge opacity = review_state — and since the live frontier is 100% unreviewed, the whole graph renders faint = adjudication debt. Node size = evidence-link count (0 = hollow ring); fill saturation = donto_maturity (0–7); a two-arc polarity halo (green = Σ incoming support, red = Σ incoming attack) is the at-a-glance defensibility gauge. Layout is sign-biased: supports attract, rebuts/undercuts repel, so camps self-separate. Two scrubbers, never merged: a tx_time replay of the frontier forming, and a valid_time lane that — where NULL on the seed — renders a hatched "valid_time unwired" band rather than a fabricated timeline.

Data source. donto_argument (relation, strength, context, agent_id, evidence_anchor_ids, tx_time — no valid_time column, so edge bitemporality is tx_time only), donto_statement, donto_evidence_link, donto_maturity/donto_polarity.

WITH edges AS (
  SELECT a.argument_id, a.relation, a.strength, a.review_state,
         a.source_statement_id AS src, a.target_statement_id AS tgt,
         lower(a.tx_time) AS asserted_at, a.context, a.agent_id, a.evidence_anchor_ids
  FROM donto_argument a
  WHERE a.context = 'ctx:genes/hardening/contradictions'  -- the dense Caroline seed (7 edges)
    AND upper(a.tx_time) IS NULL),
nodes AS (
  SELECT s.statement_id, s.subject, s.predicate,
         COALESCE(s.object_iri, s.object_lit->>'v') AS object,
         donto_maturity(s.flags) AS maturity, donto_polarity(s.flags) AS polarity,
         lower(s.valid_time) AS valid_from,
         (SELECT count(*) FROM donto_evidence_link el
          WHERE el.statement_id = s.statement_id) AS evidence_n
  FROM donto_statement s
  WHERE s.statement_id IN (SELECT src FROM edges UNION SELECT tgt FROM edges))
SELECT * FROM nodes;  -- + the edges CTE; verified to return 8 nodes + 7 edges live
-- Provenance check so the rebuts≫supports ratio isn't mis-sourced:
--   SELECT context, count(*) FROM donto_argument WHERE upper(tx_time) IS NULL
--   GROUP BY context;  -- ctx:epistemic-sweep/contradictions ≈ 90% of all edges.

What it reveals. A defended/besieged/undercut landscape no tabular lens or undirected graph can: which claims are well-defended (green halo, evidence>0) vs besieged (red-dominant) vs undercut-at-the-warrant (dashed orange even when the conclusion has support) — a state invisible to any system that flattens direction. The macro truth drawn literally: rebuts ~2,225 ≫ supports ~132 (donto overwhelmingly records disagreement), and — honestly — ~90% of it lives in ctx:epistemic-sweep/contradictions, not genealogy, so the thesis carries correct provenance. The Caroline-motherOf cluster: three rival mothers held side by side, plus an explicit lexical negation (notMotherOf, polarity=asserted) paired to its positive twin by a mutual rebuts. And adjudication debt: 100% unreviewed renders faint, ranking which clusters need triage.

Anti-pattern avoided. The undirected "related" force graph (collapsing all signs to grey adjacency); collapsing a contradiction set to a winner; full opacity (hiding the unreviewed signal); faking confidence on NULL strength; faking negation via flags&2 (which actually selects polarity absent/unknown — on this data the negation is lexical, in the predicate string); flattening the two time axes; mis-sourcing the macro thesis to genealogy.

 CONTRADICTION FRONTIER  ctx:[genes/hardening/contradictions]  (global edges 90% epistemic-sweep)
  Disputed slot: motherOf( ? , caroline-rose-davis )    ← one paraconsistent SET (no winner)
  [jessie-buchanan -motherOf-> caroline] mat:0 ev:1  halo(R..)= besieged
        <===RED rebut (open V at conclusion, UNWEIGHTED hairline: strength NULL)===
  [jessie-buchanan -notMotherOf-> caroline] *explicit-negation* (LEXICAL, not a flags strikethrough)
  [kitty-maymi -motherOf-> caroline] ev:1  halo(....)= un-attacked, faint
  [babi-milpijan -motherOf-> caroline] ev:2 (bigger node = 2 evidence links)
  ====GREEN==> supports  ----RED--[> rebuts(conclusion)  - -ORG-[< undercuts(warrant)
  ====PURP=oclk supersedes(tx-ordered)  ........grey alt_analysis  hairline+hollow = strength NULL
  opacity: ALL faint ==> review_state 100% UNREVIEWED (adjudication debt)
  valid_time: ////UNWIRED for this ctx////   GLOBAL: rebuts 2225 | supports 132  most-besieged 10/0

Feasibility. This is already lens #16 but renders tabular. A NetworkDiagram component using d3-force (signed layout) + SVG for a single cluster, canvas for the global ~2,363-edge view. Bounded by context, it touches only the ~2.4K-row argument table + endpoint statements — no 40M-row scans. The AIF-faithful detail (undercuts against the edge midpoint, NULL-strength hairlines, decoding flags via the SQL columns not JS bit math) is what raises it above a generic signed graph. Effort ~1–1.5 days cluster, +1 day global + tx scrubber, +0.5 day valid_time lane.


4.9 The Claim Cascade — donto-native score: 9

Property served (P4, P7, P9, P8, P10.) donto's defining health signal is not "how many statements" but "how far down the lifecycle the firehose actually gets pulled — and whether the non-advancing remainder is treated as legal possibility-space." A single 39.5M counter is a lie of composition.

Encoding. A horizontal log10 cascade of nested reservoirs, run as two unit-pure tracks so no rung is ever divided by a rung in a different unit. Track A (statements): emit (39.5M) → anchor (949K distinct anchored) → argued (1,247 distinct statements touched). Track B (predicates): minted (~866K) → aligned (~6,213 distinct source predicates). Identity-resolved (53 edges, a third unit) is a corner badge, never a rung. The non-advancing portion of each rung is a separate lighter, hatched retained reservoir segment — "these are HELD as legal state, click to query" — never slanted off-canvas as loss. Hue = stage family (generation teal, joining amber, reality-pull violet). A bright waterline between E1 and E2 marks the promotion gate. Drop-off ratio labels appear only between same-unit rungs. A contradiction-pressure chip on the argued rung (rebuts 2,225 / supports 132) shows disagreement held, not averaged. A tx_time spark-column per rung shows additive accumulation, never overwrite.

Data source. donto_statement (reltuples for the 39M top — no scan), donto_evidence_link (949,268 distinct), donto_predicate, donto_predicate_alignment (6,213 distinct source), donto_argument (1,247 distinct touched), donto_identity_edge.

-- Track A: statement lifecycle (one unit: distinct live statements)
WITH a AS (
  SELECT 1 ord,'1·emit' lbl,(SELECT reltuples::bigint FROM pg_class
                              WHERE relname='donto_statement') n
  UNION ALL SELECT 2,'2·anchor',(SELECT count(DISTINCT statement_id) FROM donto_evidence_link)
  UNION ALL SELECT 3,'3·argued',(SELECT count(DISTINCT s) FROM (
     SELECT source_statement_id s FROM donto_argument WHERE upper(tx_time) IS NULL
     UNION SELECT target_statement_id FROM donto_argument WHERE upper(tx_time) IS NULL) q))
SELECT ord,lbl,n, round(n::numeric/NULLIF(lag(n) OVER (ORDER BY ord),0),5) AS retained_vs_prev
FROM a ORDER BY ord;
-- Track B kept SEPARATE (never divided into Track A):
SELECT (SELECT reltuples::bigint FROM pg_class WHERE relname='donto_predicate') AS minted,
       (SELECT count(DISTINCT source_iri) FROM donto_predicate_alignment
        WHERE upper(tx_time) IS NULL) AS aligned;
-- Maturity waterline (sampled for speed; full GROUP BY on 39M times out):
SELECT donto_maturity(flags::smallint) AS e_level, count(*)
FROM donto_statement TABLESAMPLE SYSTEM (0.5) WHERE upper(tx_time) IS NULL GROUP BY 1;

What it reveals, unit-honestly. The generation engine is world-class but joining/reality-pull is the bottleneck, pinned with only valid same-unit arithmetic. Track A: evidence anchors 949K / 39.5M = 2.40% (a ×41.6 cliff), argument touches 1,247 = 0.0032% of emit (a further ×761 cliff). Track B: alignment touches 6,213 / 866K = 0.72% (a ×139 cliff). The corrected argued figure (1,247 distinct statements, not 2,424 raw edges) makes donto's own thesis sharper: the contradiction machinery is barely load-bearing. The waterline shows the gate is real — only ~6% have ever climbed to E2+. And because each held reservoir is clickable, an operator can ask "show me the 38.5M statements parked, unanchored, as legal hypothesis_only state" and treat that pool as a work queue.

Anti-pattern avoided. The single total-statement counter; the linear-scale funnel (which renders post-anchor rungs as sub-pixel slivers — itself an abundance collapse); drawing non-advancing flow as lost; a static snapshot with no bitemporal channel; and — the subtlest, which an earlier draft itself committed — the unit-mixing composition-lie of dividing distinct-statements by distinct-predicates by raw-edges to manufacture cross-unit "×N" drop-offs.

  THE CLAIM CASCADE · log10 · pool ░ = HELD legal state, not loss
  TRACK A — STATEMENT lifecycle (unit: distinct live statements)        reached   tx_30d
1 emit           ██████████████████████████████████ 39.53M  ▁▂▃▅█
  │  ░░░░░░░ pool: 38.58M HELD (hypothesis_only, never anchored)
  │  ↓ ×41.6   only 2.40% advance
2 anchor         █████████████████████████░          949,268 ▂▃▃▄▆
  │  ↓ ×761   0.0032% of emit
3 argued         ██████░                               1,247  ▁▁▂▂▃
       ▸ rebuts 2225 · supports 132  (donto HOLDS disagreement, not averages)
  ╠════════ WATERLINE · E1→E2 · 6.2% above / 93.8% below ════╣
  TRACK B — PREDICATE lifecycle (unit: distinct predicates)  [NOT divided into A]
b1 minted        ███████████████████████████████░    865,834
b2 aligned       █████████████░  (×139 cliff, 0.72%)    6,213
  ▸ click HELD pool ░ → query parked claims (work queue)  · identity-resolved: 53 (badge)

Feasibility. Low-to-medium. Track A returns 3 rows, Track B 1 row, each <1s (the 39M top uses reltuples; the lower counts are index-backed and verified <60s). The maturity band uses TABLESAMPLE SYSTEM(0.5) (~1s). Rendered as a custom log-scale bar component (extend the existing BarList + a hatched second segment). The design never does a full scan. Effort ~1 day static + drill, +0.5 day sparks/animation. Held at 9 because cascade-as-funnel is still a borrowed chart family, even though every channel is donto-native.

5. The donto Observatory — composing the views into one console

The catalog is not nine separate dashboards. It composes into one continuous instrument: the Substrate Observatory, which holds donto's whole-vs-one duality in a single frame and lets you fall through it without changing tools.

The macro map is a force-directed galaxy of contexts: nodes sized by live statement count (read from the existing donto_mv_context_stats matview — no scan), hued by namespace family, with test:* dimmed so the thousands of fixture contexts recede. Between contexts run bridge arcs whose thickness = the count of distinct subjects co-asserted across the two contexts, and whose hue runs on a diverging blue→red scale by discord ratio — how often those shared subjects carry competing objects across the pair. That bridge is the Lens-Engine triangulation thesis at substrate scale: "discord is the map of novelty." A thick red bridge literally means investigate here next. The two channels are deliberately separate so mere overlap can never masquerade as signal — dedup-noise stays blue and recedes; contested overlap glows red.

The bridge matrix is the only heavy compute, and it must be materialized nightly into a donto_x_observatory_bridge table (a single live context-count took ~10s; a 45k×45k shared-subject scan over 40M rows is hopeless). A Rust crate in the donto workspace — per the Rust-first rule — bounded to top-N contexts and shared_subjects >= 3, fills it off-peak.

Clicking a bridge, or searching a subject in the omnibox (reusing the live FTS /search), drills into the micro dossier: one radial panel composing all sixteen admin lenses about a single entity at once — its predicate fan (abundance, near-synonyms bracketed as a reversible alignment hint, never folded at rest), its contradiction spokes (one predicate radiating to equal competing objects under a "held, not resolved" bracket), an evidence ring that tells the truth (filled = anchored / STATED; hollow = hypothesis-only / INTERPRETED), an identity halo of variant symbols as a graded competing-hypothesis cloud, and a bitemporal panel along the bottom keeping both axes distinct.

The crucial design fact is that the same four channels — contradiction, identity, evidence, bitemporal — render at both zooms. A thick red macro bridge and a fan of competing micro spokes are literally the same phenomenon at two scales, so the drill from firehose to a single audited (or honestly-unanchored) claim is continuous. On the verified live example ex:rosie-reynolds (271 statements, 107 contexts, 183 predicates, 4.7ms query), bornIn is held as three competing objects {coen, mcivor-river, mcivor-river-qld} (the last a second-order identity near-duplicate held apart), motherOf radiates to eight children including an edgar vs edgar-reynolds identity collision — and the evidence ring is entirely hollow (0 of 271 anchored), so the dossier banners "hypothesis-only entity: provenance gap, not proof." That is the Observatory working as intended: it refuses to lie about which claims are grounded.

Connection to admin.donto.org. The Observatory is not greenfield. The existing admin console already exposes the sixteen capability lenses — Evidence Anchors, Contradictions Held, Predicate Alignment, Semantic Neighbors, Bitemporal Belief, Identity Hypotheses, Provenance & Maturity, Cross-Source, Entity Reach, Outgoing/Incoming Edges, Predicate Reach, Sibling Sources, Co-occurring Entities, Predicate Neighbors, Argument Graph — each backed by a live SQL query in lib/job-panels.ts. They are entirely tabular today. The Observatory composes those exact, already-proven queries into the radial micro-dossier instead of sixteen generic tables, and adds the macro galaxy on top. The infrastructure (Next.js 16, React 19, the read-only donto_ro pool, the matview) is in place; what is missing is the rendering layer that translates tabular lens results into the visual language this report derives.

6. Implementation path

The honest summary: the SQL is mostly there, the schema is right, and the bottleneck is rendering plus a handful of precompute tables — not new substrate work.

The stack as it actually is. The admin app is Next.js 16 + React 19 + Tailwind on the read-only donto_ro pool, with custom CSS primitives (MetricTile, ProgressBar, BarList) and a LazyPanel → DataTable drill pattern. One correction the catalog forced: the often-repeated "recharts is in node_modules" is true for a sibling app but the admin app currently depends only on next/react/pg/@donto-web/ui. So node-link and projection views need new (small) client-side deps: d3-force / d3-polygon for graphs and hulls, ml-pca for in-browser projection of the tiny identity set, and deck.gl only for the 880K-point Predicate Constellation.

Precompute, off-peak, never live-scan. The 40M-row table forbids analytical full scans, so the following materialized tables, refreshed by the alignment daemon or a cron, are genuine prerequisites: donto_contested_pairs (for the Belief Spectrum's "most contested" picker), donto_predicate_usage (the Zipf rollup — cheap because each per-predicate count is an index-only scan), donto_predicate_projection (the offline UMAP coords + first_aligned_at), and donto_x_observatory_bridge (the macro galaxy). Per-subject and per-context lenses, by contrast, are index-bound and genuinely live (single-digit milliseconds).

Build order — highest insight per unit effort first.

  1. The Bitemporal Plane (4.1). Score 10, ~1 day, all indexes exist, queries verified. It is the single most donto-native view and the most legible argument for why the substrate is built the way it is (the wrongful-conviction gap). Build it first.
  2. The Merge Basin (4.5). Score 10, ~1.5–2 days, the data is tiny (123 edges) so no precompute, and τ-thresholding is pure client-side. Maximum donto-nativeness for minimal infrastructure.
  3. The Belief Spectrum (4.2) + the Contradiction Frontier (4.8). The spectrum SQL already runs; the frontier upgrades an existing tabular lens in place. Both need only one precompute table apiece (or none, scoped per-subject/per-context).
  4. The Evidence Ribbon (4.3) and the Abundance Signature (4.7). Both fuse several currently-tabular lenses into one provenance-honest object; both need one cheap nightly rollup.
  5. The Reality Ladder (4.9 cascade and 4.4 ladder). Honest "frontier monitors" that grow as the contradiction/maturity machinery is actually run — ship them deliberately as instruments that show thin motion now, never as demos faking dense activity.
  6. The Predicate Constellation (4.6). Last, because it alone needs deck.gl + the offline UMAP pipeline. Highest visual payoff, highest setup cost.
  7. The Observatory (§5). Composes the above; build once the micro-dossier components from 4.2/4.3/4.5/4.7/4.8 exist and the bridge matview is filled.

A consistent rendering discipline runs through all of them: SVG/canvas for the bounded views, deck.gl only where the count demands GPU, and — critically — no view ever issues an unbounded query against the 40M-row table.

7. Measurement as the steering wheel

These views are not decoration. They are the instrument panel of an abundance-native substrate, and the substrate's defining doctrine is that measurement is not a backward judge but the active steering wheel that decides what to generate, anchor, align, and argue next. Read that way, every honest hole the catalog insists on drawing becomes a control input.

The Claim Cascade is the master gauge: it shows, in valid same-unit arithmetic, that generation is world-class while joining and reality-pull are starved — evidence at 2.4%, alignment at 0.7%, argument at 0.003%. That is not a verdict; it is a throttle reading. It tells the operator the next marginal unit of effort belongs on anchoring and arguing, not on emitting more. The Predicate Constellation's edgeless-but-dense clusters (killedBy near assassinatedBy) are a literal to-align queue. The Merge Basin's merge/split frontier — the edges that flip at the current τ — is the human-adjudication worklist, and its latent embedding-near dots are merge candidates the engine has not yet proposed. The Contradiction Frontier's all-faint, 100%-unreviewed rendering ranks which clusters need triage by contested-ness × evidence-thinness. The Belief Spectrum's and Evidence Ribbon's empty rails point exactly at which popular-but-unanchored claims to send the citer after. The Bitemporal Plane's belief-latency rectangles flag where reality was true long before the system believed it — the highest-value re-ranking targets.

This is the deepest reason donto needs its own visual language. A chart built on the four classic collapses cannot steer this substrate, because it has already thrown away the very signals that steering depends on: the disagreement distribution, the second time axis, the soft identity boundaries, the held tail, the visible holes. It draws a confident, finished world and hands the operator nothing to do. The donto-native views do the opposite. They draw an unfinished, contested, evidence-thin, perpetually re-rankable world — honestly — and in doing so they turn "39.5M statements across 45,661 contexts" from a dead number into a navigable surface where discord points at the next investigation, hollow rings point at the next anchor, and the waterline shows reality slowly, non-destructively, pulling a vanishing fraction of an unbounded firehose up toward proof.

That is what it means to see the substrate: not a picture of what donto has decided, but an instrument for steering what it decides next.