modified: .gitlab-ci.yml modified: bench/qa_questions.txt modified: bench/qa_sweep.py modified: bench/run.sh modified: docs/TICKETS.md modified: docs/_source/README.md modified: docs/_source/_ext/makefile_targets.py modified: docs/_source/api/cli.rst modified: docs/_source/api/distill.rst modified: docs/_source/api/mesh.rst modified: docs/_source/api/qa.rst modified: docs/_source/api/retrieval.rst modified: docs/_source/api/storage.rst modified: docs/_source/api/substrate.rst modified: docs/_source/concepts.rst modified: docs/_source/conf.py modified: docs/_source/cookbook.rst modified: docs/_source/index.rst modified: docs/_source/license.rst modified: docs/_source/quickstart.rst modified: docs/bench-maxing.md modified: docs/benchmarks.md modified: docs/cti-architecture.md modified: docs/diagrams/aborist-modules.dot modified: docs/diagrams/aborist-modules.svg modified: docs/diagrams/mesh-data-flow.dot modified: docs/diagrams/mesh-epoch-lifecycle.dot modified: docs/diagrams/mesh-epoch-lifecycle.svg modified: docs/diagrams/mesh-group-decisions.dot modified: docs/diagrams/mesh-group-decisions.svg modified: docs/diagrams/mesh-identity-stack.dot modified: docs/diagrams/mesh-secret-envelope.dot modified: docs/mesh.md modified: docs/qa-modes-bench.md modified: docs/seven-point-program.md modified: docs/tickets/ticket-000001-retrieval-keywords-audit-gap.md modified: docs/tickets/ticket-000002-reference-frame-polarity-contract.md modified: docs/tickets/ticket-000003-anchor-class-warrant.md modified: docs/tickets/ticket-000005-label-ladder-migration.md modified: docs/tickets/ticket-000006-bench-emergent-findings.md modified: docs/tickets/ticket-000007-query-layer-hyphen-fold.md modified: docs/tickets/ticket-000008-broad-quantifier-preflight-guard.md modified: docs/tickets/ticket-000009-quantifier-preflight-dag-binding.md modified: docs/tickets/ticket-000010-metacognition-preflight-guard.md modified: docs/tickets/ticket-000011-soft-preflight-hint-sidecar.md modified: scripts/backfill_concepts.py modified: scripts/bench_emergent.py modified: tests/crawler/test_async_web_fetcher.py modified: tests/crawler/test_bridge.py modified: tests/crawler/test_web_fetch.py modified: tests/test_bench_qa_sweep.py modified: tests/test_burn.py modified: tests/test_burn_doc.py modified: tests/test_claim_lattice.py modified: tests/test_cli_render.py modified: tests/test_compress.py modified: tests/test_concepts.py modified: tests/test_dag.py modified: tests/test_directives.py modified: tests/test_distill.py modified: tests/test_distill_recursive.py modified: tests/test_evict.py modified: tests/test_frame.py modified: tests/test_grok_source.py modified: tests/test_html_source.py modified: tests/test_ingest.py modified: tests/test_inspect.py modified: tests/test_journal.py modified: tests/test_keys.py modified: tests/test_llm_context_base.py modified: tests/test_merkle.py modified: tests/test_mesh.py modified: tests/test_mesh_aead.py modified: tests/test_mesh_chain.py modified: tests/test_mesh_cli.py modified: tests/test_mesh_cli_pull.py modified: tests/test_mesh_wire.py modified: tests/test_mesh_wire_e2e.py modified: tests/test_metacognition.py modified: tests/test_migration_audit_mode.py modified: tests/test_providence_source.py modified: tests/test_qa.py modified: tests/test_qa_quality_live.py modified: tests/test_quantifier_caps.py modified: tests/test_quantifier_classifier.py modified: tests/test_quantifier_phase4.py modified: tests/test_quantifier_reminder.py modified: tests/test_query.py modified: tests/test_reclassify.py modified: tests/test_repair.py modified: tests/test_resume.py modified: tests/test_snapshot.py modified: tests/test_soft_preflight.py modified: tests/test_tfidf.py modified: tests/test_vcs_source.py modified: tests/test_verify.py modified: tests/test_verify_json.py modified: tests/test_versioned_ingest.py modified: tests/test_warrant.py modified: tests/test_wikipedia_old.py modified: tests/test_wikipedia_xml.py modified: tests/test_wikitext.py
18 KiB
CTI architecture — layer cake mapped onto today's codebase
Date: 2026-05-01 Audience: fox + future blackops shifts. Purpose: name the architectural layers fox's de novo synthesis identifies (PROMETHEUS-Σ / CTI / Merkle-AGI-DAG / Reverse-RAG / v9.8 / Hermes) against the modules that already exist, so future work has a stable vocabulary for which layer it touches.
This is a mapping doc, not a rename. The codebase keeps its internal terms (claim_lattice, claim_lattice_pointer, verify_claim_lattice); the architectural labels (CTI, PROMETHEUS-Σ, Merkle-AGI) live in docs and commit messages where the cross-cutting story matters.
1. The layer cake
┌────────────────────────────────────────────────────────────┐
│ PROMETHEUS-Σ │
│ policy / admissibility / one-shot mode / cache reuse │
└────────────────────────────────────────────────────────────┘
│
▼
┌────────────────────────────────────────────────────────────┐
│ CTI — Clause Tree Intelligence │
│ claim nodes · evidence edges · statuses · falsifiers │
│ (the runtime IR for reasoning, NOT a model output format)│
└────────────────────────────────────────────────────────────┘
│
▼
┌────────────────────────────────────────────────────────────┐
│ Merkle-AGI-DAG │
│ roots · run-DAG · path proofs · audit lineage │
└────────────────────────────────────────────────────────────┘
│
▼
┌────────────────────────────────────────────────────────────┐
│ Reverse-RAG (Merkle Providence) │
│ answer claim → evidence pointer → source span → root │
└────────────────────────────────────────────────────────────┘
│
▼
┌────────────────────────────────────────────────────────────┐
│ v9.8 Merkle Providence Runtime │
│ 8-dim cache_key · falsification states · audit chain │
└────────────────────────────────────────────────────────────┘
│
▼
┌────────────────────────────────────────────────────────────┐
│ Hermes (and any other base model) │
│ weak proposer of natural-language pointer-line clauses │
└────────────────────────────────────────────────────────────┘
The animating principle: the model proposes, the runtime structures, the verifier falsifies, the renderer quotes, the Merkle-DAG commits, PROMETHEUS-Σ admits. Authority moves DOWN the stack — from training-time priors into runtime artifacts.
2. Per-layer responsibility + module map
2.1 PROMETHEUS-Σ (controller)
Owns:
- which
answer_modeis active - whether cache read / write is allowed
- whether a record is admissible for reuse (the 8-dim match + state filter)
- whether a verifier policy changed (governance hash bump)
- whether a run is scoreable under one-shot rules
- which falsification triggers stale a record
Today's codebase:
arborist/qa/runner.py:ask— orchestrates the full lookup → infer → verify → admissibility flow for the per-document patharborist/qa/query.py:query— same orchestration for the multi-source RAG pathDEFAULT_POLICY(runner) andDEFAULT_QUERY_POLICY(query) — the policy dictarborist.qa.keys.governance_policy_hash— folds policy into the cache_key
Status: Implicit. The layer exists as code but is not named. The de-novo doc proposes naming it; the codebase doesn't need a prometheus.py module today — the dispatch logic in runner.py and query.py IS PROMETHEUS-Σ.
2.2 CTI — Clause Tree Intelligence (reasoning IR)
Owns:
- claim nodes with text + evidence edges
- per-claim statuses (PARSED, NO_EVIDENCE_POINTER, EVIDENCE_LINKED, EVIDENCE_LINKED_PARTIAL, UNKNOWN_EVIDENCE_ID, SOURCE_ROLE_BLOCKED, CITATION_MISMATCH, SCHEMA_INVALID, etc.)
- soft-signal sidecars: lazy-anchor smell, deflection, partial-grounding split, semantic-entailment (designed in
docs/verifier-semantic-gap-design.md) - the boundary between hard checks (lexical, deterministic) and soft checks (heuristic, demote-only)
Today's codebase:
arborist/qa/parse_claims.py:parse_pointer_claims— the model's pointer-line output →ParsedClaimrecords (the CTI compile step)arborist/qa/evidence.py:EvidenceObject— typed evidence nodes withevidence_id(content-addressed) +pointer_id(prompt-facing)arborist/qa/evidence.py:render_claim_lattice— the renderer that interpolates source spans by offsetarborist/qa/verify.py:verify_claim_lattice— the deterministic verifier (six hard checks + sidecar signals)arborist/qa/verify.py:verify_claim_lattice_json— same for the JSON variantarborist/qa/quantifier.py:classify_question_quantifier— pure 10-rung intensity classifier (#000008); feeds the preflight stage'sclassifierclausearborist/qa/model_profiles.py:cap_for_intensity— per-model claim-cap profiles (#000008); feeds theanswer_contractclause'sclaim_cap_resolvedarborist/qa/quantifier_reminder.py:broad_quantifier_reminder— broad-question reminder text generator (#000008); feeds theprompt_contractclausearborist/qa/metacognition.py:preflight_question— meta-cognition QuestionState detector suite (#000010): temporal, contradiction, false-premise-lite, out-of-corpus. Feeds the preflight stage'squestion_stateclause.
Status: Real. CTI is what claim_lattice already is. The architectural insight from fox's synthesis — that this is an INTERNAL bytecode for reasoning, not a model output format — is the right reading: the model emits weak pointer lines; the runtime parses them into the CTI lattice; the lattice is what the verifier and renderer operate on. The pre-answer preflight contract (#000008 quantifier classifier + #000010 metacognition QuestionState) extends CTI upstream of retrieval — the runtime now classifies the question before generating an answer, so policy can refuse, cap, or reject without burning an LLM call.
2.3 Merkle-AGI-DAG (commitment)
Owns:
- per-run Merkle DAG; four shapes depending on path:
- Quote mode (legacy) — 7 stages: question / retrieval / context / prompt / answer / verify / final_label.
- Quote mode + preflight (post-#000009) — 8 stages: question / preflight / retrieval / context / prompt / answer / verify / final_label.
- Pointer-mode CTI (legacy) — 9 stages: question / retrieval / evidence_map / prompt / raw_answer / parsed_claim_lattice / verify / render / final_label.
- Pointer-mode CTI + preflight (post-#000009) — 10 stages: question / preflight / retrieval / evidence_map / prompt / raw_answer / parsed_claim_lattice / verify / render / final_label.
- Reject-broad (post-#000009 §8) — 3 stages: question / preflight / final_label. Emitted by
build_reject_run_dag()when the broad-quantifier guard early-returns before the LLM call. Audit replay can identify reject-path rows by stage count alone.
run_dag_root(sha256 of the canonical DAG)run_dag_blob(the structured data for inspection)- the audit-chain integrity (each
audit_event_hashchains to the previous) - inclusion proofs from chunk → document_root → source corpus
The preflight stage payload (#000009 + #000010). Single Merkle leaf, nested-clause structure for diff legibility:
classifier— quantifier classifier output (#000008): intensity, matched_token, explicit_count, scope_bound_hint, is_broad, classifier_version, operational_shape.answer_contract— guard / cap / reject / metacog state taken on this run: guard_enabled, mode_gated, apply_caps_active, claim_cap_resolved, claim_cap_applied, reject_broad_active, metacognition_enabled, etc.prompt_contract— reminder_enabled, reminder_injected, reminder_template_id (broad-quantifier-bounded-v1/broad-quantifier-unbounded-v1).evidence_contract— max_evidence_ids_exposed, one_claim_per_line.policy_refs—governance_policy_hash,model_profile_hash,answer_mode(reference-by-hash; raw policy state isn't double-committed).question_state— meta-cognition QuestionState (#000010): logical_statuses, question_shape, false_premise_hints, contradiction_pairs, temporal_sensitivity, scope_bound_hint, preflight_result.
PREFLIGHT_NODE_VERSION = "preflight-node-v1" is folded into the payload so legacy runs without the stage can be unambiguously labeled unavailable_legacy_run by audit tools.
Audit-replay payoff: two cache rows that share the same question + same model output + same verifier verdict but different preflight policy state (cap on/off, reminder on/off, reject path taken/not, metacog gates) now produce different run_dag_root values.
Today's codebase:
arborist/qa/dag.py:build_run_dag— emits the 7/8/9/10-stage DAG; returns{root, nodes, blob}.preflight_hashparameter optional for backward-compat with legacy roots.arborist/qa/dag.py:build_reject_run_dag— emits the 3-stage reject-path DAG.arborist/qa/dag.py:preflight_node_hash+build_preflight_node_payload— canonical hash of the preflight clause set.arborist/merkle.py— the non-commutative HashCombine + odd-self-duplicate Merkle conventions (Python port ofproxy.unturf.com/pkg/verified/merkle.go)arborist.store.append_audit— the only legal entry point foraudit_events; computesevent_hash = sha256(prev_event_hash || canonical(body))arborist/qa/keys.py:cache_key— the 8-dim composite hash that gates record reuse
Status: Real. The base 7/9-stage DAG was the F-track work earlier in the session; preflight binding landed 2026-05-03 (#000009 base, c36e85c) and was restructured to nested-clause shape 2026-05-04 (111dda6).
2.4 Reverse-RAG / Merkle Providence (evidence direction)
Owns:
- the
claim → evidence_id → source_span → source_root → corpusreverse path - per-claim provenance: every claim links forward to an evidence edge that maps to a chunk_root that proves into a document_root that proves into a source_root
- the renderer pulls source text by
(chunk_root, offset_start, offset_end)— the model NEVER owns the quote text; the runtime interpolates it
Today's codebase:
arborist/qa/evidence.py—EvidenceObject(source_root, document_uri, chunk_root, offset_start, offset_end, source_role, text_hash, span, evidence_id, pointer_id). Thepointer_id(E1, E2, …) is what the model sees in the prompt; theevidence_id(content-addressed) is the cache/run-DAG handle. The runtime maps pointer_id → object → content-addressed evidence_id internally.arborist/qa/verify.py:verify_claim_latticestep 6 (citation-overlap check) — theclaim → cited_spanlexical-coverage gatearborist/qa/evidence.py:render_claim_lattice— interpolates source spans by offset, not Hermes text. Synthetic-elision is impossible by construction in pointer mode because the model never produces the quote string.
Status: Real. Pointer mode makes the reverse-RAG direction explicit; the model produces the LEFT side of the chain (claim) and points to the RIGHT side (evidence_id) — the runtime walks the rest.
2.5 v9.8 Merkle Providence Runtime (admissibility ledger)
Owns:
- the 8-dim cache_key:
source_root | question_hash | model_profile_hash | conversation_hash | governance_policy_hash | schema_version | canonicalization_version | chunking_version falsification_state ∈ {live, failed, stale, quarantined}and the rules for transitions- the
providence_cachetable + theaudit_eventschain - the deliberate honesty boundary: NOT semantic truth, NOT hallucination elimination, NOT formal proof — just admissible provenance
Today's codebase:
arborist/qa/keys.py— all eight dimensions hashed intocache_keyarborist/store.py— schema, audit chain, transaction helpersarborist/qa/runner.py+arborist/qa/query.py— the cache-lookup-then-infer-then-write flow
Status: Real and honest. CLAUDE.md "Schema invariants (do not break)" enforces this boundary.
2.6 Hermes (proposer)
Owns:
- emitting weak pointer-line claims like
Steve Jobs co-founded Apple. [E1] - emitting JSON with
evidence_idsreferencing the same pointer ids - nothing else — every other artifact (the lattice, the verdict, the rendered prose, the run DAG) comes from the runtime
Today's codebase:
arborist/qa/client.py:OpenAICompatibleClient— HTTP client with retry on 502/503/504arborist/qa/client.py:StubClient— offline test stubclaim_lattice_system_prompt+claim_lattice_grounding_reminder— the prompt fields that frame Hermes' roleclaim_lattice_json_system_prompt+claim_lattice_json_grounding_reminder— JSON variant
Status: Real. The negation-removal + atomic-claim work earlier in the session was about tightening the proposer's output shape so the runtime has cleaner input to compile.
3. The two information-flow directions
Two flows traverse the layers in opposite directions:
Inference flow (top-to-bottom-then-up):
question → PROMETHEUS-Σ (admissibility check) → cache miss →
retrieval (Reverse-RAG path: titles → chunks → evidence map) →
Hermes prompt (with pointer ids) →
Hermes response (pointer-line clauses) →
CTI compile (parse_pointer_claims) →
CTI verify (verify_claim_lattice) →
CTI render (render_claim_lattice + spotlight excerpts) →
Merkle-AGI commit (build_run_dag + audit_event) →
v9.8 cache write (providence_cache row) →
PROMETHEUS-Σ admit (audit_mode + falsification_state)
Audit flow (bottom-to-top, on demand):
cache_key lookup → record + run_dag_blob →
rebuild CTI lattice from run_dag stages →
re-verify hard checks against current evidence map →
if mismatch: PROMETHEUS-Σ falsifies → state flips
The audit flow is what makes Merkle-AGI O(log N + k) per challenged claim — you don't re-run Hermes; you replay the deterministic CTI verify path against the committed run-DAG.
4. Where each design doc lives
| concern | doc |
|---|---|
| this layer-cake | docs/cti-architecture.md (you are here) |
| QA mode bench journey | docs/qa-modes-bench-2026-04-30.md |
| NLI semantic-gap sidecar | docs/verifier-semantic-gap-design.md |
| Self-reference (flat MVP) | docs/self-reference-design.md |
| Self-reference (deep, distillation-based) | docs/self-reference-design.md |
| Bench-maxing discipline | CLAUDE.md "Bench-maxing" section |
| Schema invariants | CLAUDE.md "Schema invariants (do not break)" |
| Convention list | CLAUDE.md "Conventions (do not silently change)" |
5. What this layering DOESN'T claim
Per fox's de-novo synthesis (and CLAUDE.md's existing honesty boundary):
- Merkle-AGI does NOT make full-model verification free. It moves construction to O(N) once; targeted audit becomes O(log N + k). Full-model proof remains expensive.
- CTI is NOT semantic truth. The hard checks are lexical (substring, source-role, evidence-id resolution). Semantic checks (NLI, entailment, predicate compatibility) live in the soft-signal sidecar layer and never enter the proof path.
- v9.8 admissibility is NOT correctness. A STRICT record means "every claim grounded under the current verifier policy" — the policy is fallible (lazy-anchor false-positives, the Great Wall case in the bench journey doc). PROMETHEUS-Σ falsification is the corrective mechanism.
- Reverse-RAG does NOT prove sources are authoritative. It proves the answer pointed at the source the runtime committed to. Source quality is a separate problem (handled at retrieval time via
_classify_source_role, noisy markers, title-purity rerank).
The substrate's honesty boundary stays where v9.8 placed it. The layer cake names the machinery; it does not extend the claims.
6. What's still open
These are the layer-cake-shaped work items still on the roadmap:
- Verifier-policy-hash separation — landing in this commit pass. Fold
answer_mode + parser_version + evidence_schema_version + manual_quote_policy + hard_checks_listinto a 9th dimension that's separate fromgovernance_policy_hash. Prevents cross-mode cache aliasing more cleanly. - Soft-signal taxonomy expansion — the NLI sidecar (
docs/verifier-semantic-gap-design.md) is one. Predicate-compatibility, completeness, counterevidence, source-authority, scope-ambiguity are others. All demote-only, all out of the proof path. Implementations come one at a time as the bench surfaces motivating cases. - Self-reference distillation — STRICT claims become Cores via a new
ProvidenceDistiller(seedocs/self-reference-design.md). Lets new claims compose from existing facts, not just retrieve them. - PROMETHEUS-Σ explicit naming — deferred. The control logic exists; an extracted
prometheus.pymodule is a refactor with no behavior change.
The architecture is real. The labels above name what's already there.