admin.donto.org — Observability Audit
admin.donto.org is a genuinely high-quality, schema-introspection-driven observability console — 8 pages, ~13 API routes, 27 live SQL "lens" panels and a WebGL Belief Nebula, all driven off pg_catalog with zero hardcoded table lists, a real verified read-only Postgres posture (donto_ro), and disciplined big-table query guards (reltuples-not-scan, bounded CTEs, matviews). It nails the "packageable for any donto instance / every table & process introspectable" half of the vision. Honest verdict: we are realizing roughly 55–60% of the full observability vision. The substrate-state layer is excellent; the forward-looking half is essentially unbuilt — there is no global contradiction/argument/identity/discovery explorer (all the differentiator lenses live only inside the per-job page), no "measurement-as-steering-wheel" surface at all, and no real Lens-Engine discovery surface. Three headline gaps dominate: (1) the console is fully PUBLIC with no auth over a substrate containing CARE-governed native-title data and PII (P0); (2) the Contexts page serves a 6-day-stale matview reporting 23,406 contexts when the substrate has 64,055 (a 63% undercount feeding wrong numbers to operators — P0); and (3) the differentiator analytics (donto_argument, donto_evidence_link, paraconsistency density) have no substrate-wide dashboard.
What's working
The good parts are concrete and load-bearing, not stubs:
- Schema-introspection core is real.
lib/introspect.tsdiscovers all 159 live relations (124 tables / 8 matviews / 27 views) frompg_catalogwith no allowlist;listRelations()/relationExists()build the SQL-injection allow-set live, and every dynamic identifier goes throughident()double-quote escaping and allow-set validation. Live-probed:bogus_tableanddonto_statement; DROPboth return a clean 404, anddonto_statement?view=countreturns the reltuples estimate (39.5M) in ~66ms with no scan. - Read-only posture is verified at the DB, not just claimed.
donto_roisrolsuper=f,default_transaction_read_only=on, hasstatement_timeout+idle_in_transactionbaked into the role, zero non-SELECT grants, andCREATE TABLEis rejected with "cannot execute … in a read-only transaction." The pool (lib/db.ts) is server-only andredactDsn()strips the password before any render. - Big-table safety is principled and data-adaptive. All large counts use
pg_class.reltuples(estRows,cheapCount), never blindcount(*);SMALL_THRESHOLD=50k(derived per-relation from reltuples) decides whether to ORDER BY / exact-count / compute distributions, so it adapts to a fresh empty donto vs this 39.5M one. Job panelsLIMIT 3000, all use bounded CTEs (statement_id IN,context = ANY,object_iri IN). - Differentiator data is live, not mocked. The health view returns 39.5M believed statements, 994K predicates, 64K contexts, ~2.48M evidence links, 6.36M contested subject+predicate pairs, 7.66M contradiction pressure, 2,433 argument edges, 124 identity hypotheses — and Overview/Fabric render all of these as tiles.
- The per-job detail page is the strongest realization of the vision.
/jobs/[id]renders a WebGL Belief Nebula (entity⊕predicate PCA, maturity=size, evidence=core, contradictions=multiple star systems, valid_time=comet-tails, tx_time=global clock) plus 27 live SQL lenses that exercise exactly donto's differentiators: contradictions-held, predicate-alignment (closure folding), embedding-neighbors, bitemporal belief, identity hypotheses, cross-source-lens, argument-graph, corroboration, two-hop, aligned-claims, version-history. Theaudit.test.tsrubric encodes a real channel→field mapping (every visual channel must cite a real donto field). - The alignment daemon is genuinely observable and rock-solid.
donto-align-daemon.service+donto-embed-coordinator.serviceboth active;/processesshowsdonto_align_daemon_status(state=sleeping, 550 total_ticks, last_tick ~30s ago, no last_error), 15 recent ticks, backlogs, GLM rate-cap state, acceptance rates, closure rebuilds, plus alignment runs (189) and extraction runs (93). (Caveat: this health is self-reported by the daemon's own tick table — exactly the "looked-launched-but-stalled" trap; an independent liveness probe, e.g. tick-row recency vs wall-clock, would harden it.) - Distributed embedding + BEAM are surfaced.
/embedmonitors the embed queue per target + contributor throughput (m1/m5/m15/m60) + active worker count + last-seen liveness;/jobstracks the BEAM extract queue with status breakdown and per-chunk claim counts. - API layer is uniform and won't drift. Every route is
force-dynamic/revalidate=0, wrapped inguard()/ok()/fail()with a consistent{ok,data,at}envelope andcache-control:no-store; JSON routes reuse the same fetchers the RSC pages use (e.g./api/overviewreusesgetHealth/getDaemon). - Graceful degradation everywhere.
to_regclassguards every optional-table read, so a missing relation renders an "—" tile instead of crashing; HTTP service probes useAbortControllertimeouts → a down upstream degrades one tile, not the page. - No-brittle-logic rule honored.
statusTone()is heuristic regex over free text, predicate families come from the live closure + embedding fabric (not a synonym map),RECENCY_PREFERENCEis a ranked fallback — no hardcoded per-table assumptions.
What needs work (prioritized, merged & deduped across streams)
| Pri | Issue | Evidence | Fix |
|---|---|---|---|
| P0 | Console is fully PUBLIC, no auth — entire substrate world-readable incl. CARE-governed native-title data, genealogy PII, source bodies, raw LLM transcripts | /etc/caddy/Caddyfile admin block is just tls internal; encode; reverse_proxy localhost:3103. Live-probed: curl -A curl/8 https://admin.donto.org/api/health → 200, and /api/table/donto_statement?view=rows&limit=1 returns real statement rows with no token. Read-only stops corruption, NOT exfiltration. (Compounded by /schema + lib/schema-dump.ts, a full unauthenticated schema/catalog export surface.) |
Add basicauth/forward_auth / Cloudflare Access / IP allowlist to the Caddy admin block, or Next.js middleware on a shared secret. At minimum exclude CARE-restricted contexts from row/source/transcript surfaces until access control exists. |
| P0 | Contexts page serves 6-day-stale matview — shows 23,406 contexts vs 64,055 live (63% undercount) | Verified live: donto_mv_context_stats max(refreshed_at)=2026-06-03 14:44:11, count=23406; health view distinct_contexts=64055. app/contexts/page.tsx (via getTopContexts) reads only the matview with no staleness warning. Directly violates the "verify it actually works / don't trust a self-reported number" operating rule. |
Add REFRESH MATERIALIZED VIEW CONCURRENTLY donto_mv_context_stats to the alignment daemon's periodic-rebuild tick (it already rebuilds closure) or a small cron; AND surface refreshed_at age as a visible "stale N days" badge (the fetcher getTopContexts already reads refreshed_at — only the page render is missing, so this is a few lines). Note the denominators: 23,406 (stale matview) vs 64,065 registered contexts (donto_context) — of which ~50,397 actually carry live statements; the 23,406-vs-64,065 gap is the apples-to-apples staleness measure. |
| P1 | SET LOCAL statement_timeout called outside a transaction — floods Postgres logs and raises the cap 8× |
lib/db.ts:119 runs SET LOCAL statement_timeout=120000 per query; node-pg auto-commits each query as its own txn → "SET LOCAL can only be used in transaction blocks" warnings (30+/sec at peak). Also raises the cap from the role's safe 15s to 2 min (×10 pool), so a runaway lens pins a connection for 2 min instead of aborting at 15s. introspect.ts comments still cite "15s" — files disagree. |
Decide one cap: drop SET LOCAL and rely on pool-level statement_timeout (already 120s at db.ts:66) + role default; or wrap in BEGIN…COMMIT; or scope 2-min only to known-heavy panel/nebula routes. Reconcile the stale comments. |
| P1 | One job page fires ~29 concurrent heavy queries against a max:10 pool — the "lazy" panels aren't lazy | app/jobs/[id]/page.tsx:161-163 maps ALL 27 panels to <LazyPanel> + <BeliefNebula> + <JobCharts>. components/lazy-panel.tsx:30,38-41 default open=true and useEffect(()=>load(),[]) fires on mount → 27 panel fetches + nebula + charts ≈ 29 requests at once. Contradictions lens alone measures 3.6s. The burst saturates the 10-conn pool and can starve every other admin page (and the daemon shares donto-pg). |
Default open=false, load on first expand; or render first ~3 lenses eagerly + rest on demand; and/or a small client-side concurrency limiter (N panels at once). |
| P1 | Identity fabric metrics underestimate 1.7–4.3× (reltuples on small tables) | /api/fabric uses estRows(): donto_identity_edge 53 reported vs 124 actual (verified), donto_identity_proposal 48 vs 85, donto_identity_hypothesis 3 vs 13, donto_identity_membership 72 vs 123. Root cause: lib/health.ts getFabricCoverage() ~lines 282-289. |
Replace estRows() with real count(*) for donto_identity_* (all <2K rows, no perf impact). |
| P1 | Evidence-link count uses stale reltuples | /api/fabric reports 2,251,264 (estimate) vs 2,484,472 ground truth (9.4% under). The health view already has the correct count; fabric ignores it. |
Use donto_v_substrate_health.evidence_links (or count(*)) in fabric; decide one policy (estimate vs real) for consistency. |
| P1 | No global argument/contradiction explorer (donto_argument 2,433 rows; verified) |
Only queried per-document in the "contradictions held" lens. v_arguments view exists in schema but is never invoked anywhere. Health view shows 6.36M contested pairs + 7.66M contradiction pressure substrate-wide — operator cannot drill into any of it. |
New /arguments page: count + trend by relation-type (probe the real column — it is NOT edge_type), top contested (subject,predicate) pairs by argument volume, strength distribution, review-state breakdown, evidence-anchor coverage. |
| P1 | No evidence-link analytics page (donto_evidence_link ~2.48M) |
Visible only as a per-job lens. No coverage ratio (anchor coverage is 6.29% substrate-wide), no confidence distribution, no target-type (document/revision/span) breakdown, no per-context gaps. | New /evidence page guarded by reltuples + pre-aggregated matview pattern; coverage ratio, confidence histogram, target-type breakdown, contexts/predicates <50% covered. |
| P1 | No "measurement-as-steering-wheel" surface at all | DONTO-ABUNDANCE.md §5 makes this the scarce resource (EIG-ordered what-to-generate-next queue, info-gain/Bayesian-surprise, novelty/diversity, collapse-delta, downstream task-lift). grep found zero references to EIG/info-gain/collapse-delta/novelty/diversity/task-lift anywhere in app/, lib/, or routes. |
New Steering/Abundance page: claims-emitted-over-time + valid-fact% (from beam.ts data already present), embedding-distance diversity panel, contradiction-pressure-over-time, a collapse-delta tile once the Milestone-2 experiment exists. Start with what's already derivable. |
| P1 | No query-time-alignment / Lens-Engine discovery surface; donto_match_aligned is absent |
Verified: to_regclass('public.donto_match_aligned') = false (does not exist), despite CLAUDE.md §0.5 describing it as the query-time predicate-folding table. The cross-source lens only counts shared entities per other-context — no open-discovery (fan-out from A) or closed-discovery (B-paths between A and C). |
Surface closure-folding live (type a predicate → aligned/folded forms + confidence, using donto_predicate_closure, which IS populated); minimal discovery surface (entity → fabric neighbors → shared-predicate bridges). Reconcile the donto_match_aligned reference — build it or fix CLAUDE.md. |
| P2 | Extract & embed queues effectively hidden in ground-truth terms (donto_extract_queue 360,899; donto_embed_queue 200,008 — both verified) |
Two streams disagree: a /api/embed and /api/beam route DO exist and respond (35ms/151ms) and /embed page renders the embed queue; but the ground-truth stream found queue status not faithfully exposed and BEAM's 343K-pending backlog not prominent on a global surface. Net: queues are partially surfaced but the operator can't see "is the firehose keeping up." |
Ensure /embed and /jobs show pending/leased/done/failed trends, not just point values; add a backlog-over-time view. |
| P2 | Empty panels for some jobs despite extracted statements | Job df7a0c3a-… returns 0 rows for evidence-anchors/contradictions/cross-source despite 187 statements; job 0adc46f5-… returns 107/60 for the same panels. Suggests evidence-link population gaps during ingest. |
Add a per-job evidence-coverage diagnostic panel; verify donto_evidence_link population + indexing during ingest. |
| P2 | Heavy analytical endpoints exceed client timeouts | /api/jobs/{id}/charts ~17.7s (12 distributions w/ PCA), /api/jobs/{id}/nebula ~12.6s (102KB), /jobs listing 9.6–20s. With a 10s client timeout these fail; server cap is 120s. |
Result caching (30–60s TTL) on charts/nebula; lazy-load / paginate the /jobs listing; route-specific refresh intervals; skip refresh for in-flight slow requests. |
| P2 | /api/jobs full count(*) on donto_document + double agentContextCounts GROUP BY = 7.5s |
lib/jobs.ts:152 full table scan when no filter; agentContextCounts (62-116) runs 2 sequential GROUP BYs over 40M rows (bounded ~50 contexts). |
reltuples estimate when unfiltered; merge the 2 GROUP BYs into one UNION; cache the adapter list; consider donto_statement(context,tx_time) index. |
| P2 | ILIKE substring search on donto_document (1M+ rows) has no index |
lib/jobs.ts:136 ILIKE with % wildcards, no index — acceptable now, degrades with growth. |
GIN pg_trgm index on `lower(iri) |
| P2 | Raw Postgres errors leaked with wrong HTTP status | GET /api/jobs/not-a-uuid/panel/contradictions → 500 {"error":"invalid input syntax for type uuid: \"not-a-uuid\""}. guard() (api.ts:27-33) and table route return (e as Error).message verbatim; no UUID shape validation. |
Validate job id is a UUID (404 if not, 400 for malformed); fail() returns a generic message and logs detail server-side. |
| P2 | Daemon observability is tabular only — no time-series | app/processes/page.tsx renders donto_align_daemon_tick (712 rows) as a 15-row table + point-value backlog tiles; no throughput/backlog sparkline → operator can't see if the daemon keeps up (the exact "looked-launched-but-stalled" failure). |
Add a sparkline of per-tick predicates_embedded/entities_embedded/accepted + backlog over the last N ticks (data already in the tick table), reusing job-charts.tsx. |
| P2 | No bitemporal time-travel / "as-of" viewer | Bitemporality (a headline invariant) appears only as per-statement columns in the per-job bitemporal lens + the nebula's tx_time clock. No global/context "what did this believe as of date X." | Add an "as-of" control to Contexts/Tables drill-down: WHERE tx_time @> :asof (tx_time is a tstzrange) — makes retract-not-delete visibly demonstrable. |
| P2 | Paraconsistency density table completely dark | donto_paraconsistency_density exists in the 151 relations but is never queried — zero operator visibility into paraconsistent belief load, donto's core feature. |
One-shot aggregate (density by predicate/context, global avg) on /fabric or /arguments; expose "total paraconsistency pressure" tile on Overview. |
| P2 | No global statement / predicate analytics | donto_statement (39.5M) observable only per-job; no polarity/E-level/maturity/modality distribution. No local predicate frequency/minting-rate/closure-efficiency (Fabric shows top predicates from dontosrv's upstream endpoint, not local). |
Statement-statistics tile or /statements page (cheap GROUP BY on small indexed cols via the health view); /predicates page (frequency, minted-vs-canonical, closure accuracy, minting rate). |
| P2 | Memory chunk embeddings not surfaced | donto_x_memory_chunk_embedding has 59,705 embeddings, absent from Fabric — incomplete embedding-fabric picture (predicates + entities + memory). |
Add to FabricCoverage type and fetch in getFabricCoverage(). |
| P2 | The no-gimmick audit test can't run | components/belief-nebula/audit.test.ts:18 imports vitest, but package.json scripts are only [dev,build,start,lint,typecheck] and no vitest in devDeps. The test that's supposed to enforce "every channel cites a real field" is dead — a decorative-only flourish would NOT fail CI. |
Add vitest + a test script to CI (or move to the monorepo runner). Until then the audit guarantee is documentation, not enforcement. |
| P2 | Statement-timeout errors every ~8 min — NOT the admin console | Postgres logs: 29 canceling statement due to statement timeout in 48h, recurring ~8min, from SELECT count(*) FROM donto_x_memory_record r JOIN donto_statement s … WHERE upper(s.tx_time) IS NULL AND s.predicate <> ALL($1). grep found zero matches in the admin codebase — this is upstream (donto-api / memory / daemon), a full join over 40M rows. |
Not an admin bug. Upstream should optimize/cache the join. Admin could optionally surface a timeout warning badge for visibility. |
Coverage: every table + every process — analyzable or not? (the vision's core test)
This is the vision's literal test ("EVERY table + process + everything about donto COMPLETELY analyzable"). Two measurements:
Tables — schema-introspection coverage is 100% by design; analytics coverage is partial.
- Browsable: 159/159 relations (100%). Every table/matview/view (124 tables / 8 matviews / 27 views) is discoverable and row-/schema-browsable via
/tablesand/api/table/{relation}with no allowlist. This is the strong part — a fresh empty donto would render identically. - First-class analytic surface (a purpose-built dashboard beyond generic browse): roughly 30–40 of 159. The differentiator tables that are only generic-browse or only per-job, with no substrate-level dashboard:
donto_argument(2,433; per-job only,v_argumentsnever called),donto_evidence_link(2.48M; per-job only),donto_paraconsistency_density(never queried),donto_statement(39.5M; per-job drill-down only, no global aggregates),donto_identity_*(counts only, and those counts are 1.7–4.3× wrong via reltuples),donto_predicate/donto_predicate_closure(closure relation-type breakdown is shown on Fabric; local frequency/minting is not),donto_x_memory_chunk_embedding(absent),v_derivations(listed in schema, never called),donto_match_aligned(referenced in CLAUDE.md but does not exist on this instance).
Processes — well covered.
- With a dashboard: ~6–7 of 7. Alignment daemon (✓, live tick table + status + backlogs + GLM cap), distributed embedding workers (✓,
/embed), BEAM extraction (✓,/jobs+ extract queue), donto-api extraction jobs (✓,/processes), memory memorize/recall/ingest (✓,donto_x_memory_job_logon/processes), 3 upstream service health probes (✓, dontosrv/donto-api/donto-memory). The one gap is not a missing process but missing time-series for the daemon (point values, no throughput-over-time chart).
Net: infrastructure/process observability is essentially complete; the gap is differentiator-analytics at substrate scale — contradiction pressure, evidence quality, identity quality, and paraconsistency are either per-document-only or completely dark.
Performance & reliability
The console is well-architected for the 40M-row substrate, and the measured numbers bear that out. Fast paths are genuinely fast; the slow paths are slow for understood reasons.
Fast / instant (pure pg_catalog or matview, no data scan):
/api/table/donto_statement?view=count~66–135ms (reltuples, no scan) ·/api/schema196ms ·/api/contexts41–49ms (pre-aggregateddonto_mv_context_stats) ·/api/embed35ms ·/api/beam120–151ms (small queue reads, not the statement table).
Medium (multiple bounded queries / upstream HTTP):
/api/overview~3.0–4.4s (4 concurrent queries, cold) ·/api/fabric3.4–3.9s (7 reltuples + 1 GROUP BY) ·/api/processes2.3–2.7s (HTTP upstream probes).
Heavy (by design — graph traversal / analytics):
- Job panels: contradictions 0.5–3.6s, entity-reach 533ms, outgoing-graph 665ms, evidence-anchors 678ms, embedding-neighbors 0.37s, aligned-claims 0.34s, two-hop 0.30s; nebula 0.85s; charts 1.3s.
/api/jobs(limit 50–100) 7.5s (fullcount(*)ondonto_document+ doubleagentContextCountsGROUP BY). The 40M-row traps that are correctly avoided: blindcount(*)(always reltuples), unbounded scans (panelsLIMIT 3000+ bounded CTEs), and anIS NULL-matching closure. The traps that remain: the/api/jobsunfiltered count, the unindexed ILIKE document search (growth risk), and the contradictions/entity-reach panels' unbounded final JOIN overdonto_statement(pessimistic plan, fine today at ~500ms but fragile for high-abundance entities).
Reliability findings:
- The recurring ~8-min statement timeouts (29 in 48h) are upstream, not the admin console — verified by
grep: the offendingdonto_x_memory_record JOIN donto_statementquery is nowhere in the admin codebase. The console's own 120s cap lets its queries complete; no admin-originating timeouts were observed. - The one admin-side reliability smell is the
SET LOCALlog flood (P1) and the eager-"lazy" 26-query burst against a max:10 pool (P1) — the latter is a real availability bug where one popular job page can starve the whole console. - Service:
donto-admin-web.serviceactive ~2 days, RSS ~75.8M, stable. TLS valid through Aug 2026, zero SSL/protocol errors across all probes.
The vision gap — full console vs today
The vision (project_donto_observability + DONTO-ABUNDANCE.md + the Lens Engine docs) asks for everything about donto completely analyzable, the differentiator machinery visible and exercised, and measurement as the steering wheel. Here is the honest delta.
What the FULL console looks like: substrate-STATE observability (done) plus a set of global differentiator explorers and a steering layer:
- Alignment-daemon dashboard with time-series — TODAY: live status + a 15-row tick table + point-value backlogs (✓ rock-solid daemon, ✓ its own section). MISSING: throughput/backlog over time (data is already in the 712-row tick table), so the operator can SEE whether it's keeping up. ~70% there.
- Contradiction / argument explorer — TODAY: per-document "contradictions held" lens only;
v_argumentsnever called. MISSING: a global/argumentspage over the 6.36M contested pairs / 7.66M pressure / 2,433 edges — top contested (subject,predicate) pairs, strength distribution, review-state. ~20% there. - Identity browser — TODAY: counts on Fabric (and those counts are wrong: 53 vs 124 actual). MISSING: confidence/method distribution, hypothesis-age, cluster browser over
donto_identity_cluster_cache+ edges (124 edges: 72 same_referent / 35 distinct / 16 possibly / 1 no-info). ~15% there. - Discovery / Lens surface — TODAY: per-job cross-source shared-entity counts. MISSING: open-discovery (fan-out from A) and closed-discovery (B-paths between A and C) per the Lens Engine; a query-time alignment demo.
donto_match_alignedis absent on this instance (verified) though closure IS populated (883K rows, but ~98.9% are 'self' loops — only ~9,623 real edges, which is itself a signal worth surfacing). ~5% there. - Abundance / steering metrics — TODAY: abundance shown only as volume (predicate/statement counts). MISSING: the entire measurement-as-steering-wheel layer the CANONICAL doc calls the scarce resource — EIG-ordered generation queue, information-gain/Bayesian-surprise, novelty/diversity, the collapse-delta benchmark, downstream task-lift-per-fact.
grepfound none of these terms anywhere in the codebase. ~5% there. - Bitemporal time-travel — TODAY: per-statement tx_time/valid_time in one lens + the nebula clock. MISSING: a global/context "as-of" scrubber (
WHERE tx_time @> :asof). ~10% there. - Per-context deep dive — TODAY: a context list (from a 6-day-stale matview showing 63% of the real context count). MISSING: a per-context drill-down with its own contradiction pressure, evidence coverage, predicate inventory, and an as-of view. ~25% there.
The single most damaging concrete defect is the stale Contexts matview (P0) — it directly violates the operator's "don't trust a self-reported number" rule by silently serving 6-day-old, 63%-low data on the one page whose purpose is per-context truth.
Roadmap to the full version
Ordered: quick wins (safety + correctness first, low effort), then the bigger surfaces. Steps 1–6 are cheap and high-leverage; 7–11 build the missing half of the vision (and they reuse SQL already proven in job-panels.ts, just un-scoped from a single document_id).
- Add auth in front of admin.donto.org (P0). Caddy
basicauth/forward_auth / Cloudflare Access / IP allowlist, or Next.js middleware. Until then, exclude CARE-restricted contexts from row/source/transcript surfaces. (Hours.) - Refresh the context matview + add a staleness badge (P0). Add
REFRESH MATERIALIZED VIEW CONCURRENTLY donto_mv_context_statsto the daemon's periodic tick; renderrefreshed_atage. (Hours.) - Fix the
SET LOCALflood + reconcile the timeout cap (P1). DropSET LOCAL, rely on the pool-level 120s, fix the stale "15s" comments. (Minutes.) - Make the job-page panels actually lazy (P1). Default
open=false, render first ~3 eagerly, add a client concurrency limiter. Kills the 26-query pool-saturation burst. (Hours.) - Replace
estRows()with realcount(*)on the small identity tables + use the health-view evidence count (P1).lib/health.ts getFabricCoverage()~282-289 and the fabric route. (Minutes — fixes 1.7–4.3× and 9.4% errors.) - Harden inputs (P2): validate job ids are UUIDs (404/400 not raw-PG-500), generic
fail()messages with server-side logging; add thevitesttest script to CI so the no-gimmick audit actually runs. - Daemon time-series sparkline (P2). Per-tick predicates/entities/accepted + backlog over the last N ticks (data already in
donto_align_daemon_tick), reusingjob-charts.tsx. - Global
/arguments(contradiction) explorer (P1). Top contested (subject,predicate) pairs, relation-type counts (probe the real column), strength distribution, review-state — reuse the contradictions lens SQL un-scoped + the LIMIT-2000 candidate-CTE pattern from/search. - Global
/evidencepage +/identitycluster browser (P1). Coverage ratio, confidence distribution, target-type breakdown; identity confidence/method/age + cluster browser. Guard with reltuples + matview pattern. - Steering / Abundance page (P1). Claims-over-time + valid-fact% (from
beam.tsdata already present), embedding-distance diversity, contradiction-pressure trend, a collapse-delta tile once the Milestone-2 experiment exists. This is the biggest single move toward the forward-looking half of the vision. - Lens-Engine discovery surface + bitemporal as-of viewer (P1/P2). A "type a predicate → see folded forms + confidence" closure widget (closure IS populated); entity → neighbors → shared-predicate B-paths; and a global/context
WHERE tx_time @> :asofscrubber. Reconciledonto_match_aligned(build it or fix CLAUDE.md, since it's absent on this instance).
After steps 1–6 the console is safe and correct; after 7–11 it crosses from ~55–60% to a genuine realization of the full vision.
Verified 2026-06-09 via live probes against admin.donto.org and direct donto_ro/substrate queries: public no-auth access confirmed (/api/health 200 in 3.4s and /api/table/donto_statement?view=rows returns real rows with no token); donto_mv_context_stats last refreshed 2026-06-03 14:44 UTC with 23,406 rows vs live health-view; donto_extract_queue=360,899; donto_embed_queue=200,008; donto_identity_edge=124; donto_argument=2,433; donto_match_aligned absent (to_regclass=false). Substrate snapshot: ~39.5M believed statements, 994K predicates, 64,055 contexts, ~2.48M evidence links, 6.36M contested pairs, 7.66M contradiction pressure. Latencies and file:line references drawn from the six audit streams against /mnt/donto-data/workspace/donto-web/apps/admin/. No files were modified — review only.