arborist/docs/cti-architecture.md
russell@unturf.com de07ad9392
docs: distill #000008+#000009+#000010 into core docs + diagrams
Three Explore agents fanned out in parallel for a docs/ + diagrams/
+ code-comment audit against the shipped state of the three
preflight tickets. This commit lands all the alignment fixes.

Core docs updates:

  CLAUDE.md
    - dag.py module description: stage counts now read
      "7/8 quote · 9/10 CTI · 3 reject" reflecting #000009 preflight
      stage + reject-broad early-return shape.

  docs/cti-architecture.md §2.2 + §2.3
    - §2.3 Merkle-AGI-DAG section rewritten: documents all five DAG
      shapes (legacy 7/9, post-#000009 8/10, reject-broad 3),
      describes the preflight stage's 5 nested CTI clauses
      (classifier / answer_contract / prompt_contract /
      evidence_contract / policy_refs), pins
      PREFLIGHT_NODE_VERSION = "preflight-node-v1", states the
      audit-replay payoff.
    - §2.2 CTI section: adds the four new modules
      (quantifier, model_profiles, quantifier_reminder,
      metacognition) as code anchors. Notes that pre-answer
      preflight contract extends CTI upstream of retrieval.

  docs/seven-point-program.md
    - D3 status ½ → ¾ — pre-answer preflight contract landed via
      #000008 + #000010. Code anchors + pinning tests updated.
    - D4 status ½ → ¾ — preflight stage adds upstream control
      commitment to the run-DAG. Code anchors include
      build_reject_run_dag + preflight_node_hash.
    - Status snapshot table: tickets column now references
      #000008/#000009/#000010 against D1/D3/D4 directives.
    - "Post-landing addendum (2026-05-03 / 2026-05-04)" subsection
      summarises all three tickets + their commit shas + final
      test count (993 passing, up from 734).

  docs/modules.md
    - Q&A pipeline table: added 4 new modules (quantifier.py,
      model_profiles.py, quantifier_reminder.py, metacognition.py).
      dag.py row updated to "7/8 quote · 9/10 CTI · 3 reject".
    - dag.py subsection rewritten: documents all 5 DAG shapes,
      describes the preflight payload's 5 clauses + question_state.
    - 4 new module subsections (quantifier / model_profiles /
      quantifier_reminder / metacognition) explaining each
      module's purpose, signature, and how it feeds the run-DAG
      preflight clause.

Diagram updates:

  docs/diagrams/query-pipeline.dot + .svg
    - New "PREFLIGHT (#000008 + #000010)" node inserted between
      cache_check and concepts_lookup.
    - New "REJECT-BROAD" node showing the 3-stage minimal DAG
      escape path.
    - render node label extended with the audit-line tail token
      catalog.

  docs/diagrams/aborist-modules.dot + .svg
    - 4 new qa_* nodes in the retrieval & verifier cluster.
    - 8 new edges: qa_query/qa_runner each call into all 4
      preflight modules; qa_dag has dotted edges to qa_quantifier
      + qa_metacognition (preflight clause sources).
    - qa_dag label updated to mention preflight_node_hash + 5 clauses.

  docs/diagrams/verifier-ladder.dot + .svg
    - Soft-demote violations list extended: BROAD_QUANTIFIER_RUNAWAY
      / CAP_APPLIED / SCOPE_UNBOUND, FORMAT_COLLAPSED, BARE_NAME_CLAIM.
    - New "AUDIT-LINE TAILS" annotation node listing all 11 tail
      tokens (#000008 broad-* + #000010 metacog + classic verifier).
    - Dashed edges from each rung to tails note showing tails
      compose onto labels.

Code-side stale-comment fixes (caught by 3rd Explore agent):

  aborist/qa/keys.py:218
    - "The four fields" → "The seven fields"; mention #000010 adds
      six more for metacognition.
  aborist/qa/query.py:2644
    - 7-stage / 9-stage comment expanded to enumerate all four
      base+preflight shapes plus the 3-stage reject path.
  aborist/qa/runner.py:835
    - same expansion as query.py for runner.ask() callsite.

mesh-*.dot, ingest-pipeline.dot, qa-modes-bench.md, bench-maxing.md,
bench-emergent-design.md, verifier-semantic-gap-design.md,
self-reference-design.md, concept-relations-design.md confirmed
orthogonal — no edits needed.

993 tests still passing (no behavior change). 7 files modified
across docs/ + 3 dot diagrams + 3 SVGs + 4 code-comment fixes.
2026-05-03 19:18:22 -04:00

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_mode is 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:

  • aborist/qa/runner.py:ask — orchestrates the full lookup → infer → verify → admissibility flow for the per-document path
  • aborist/qa/query.py:query — same orchestration for the multi-source RAG path
  • DEFAULT_POLICY (runner) and DEFAULT_QUERY_POLICY (query) — the policy dict
  • aborist.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:

  • aborist/qa/parse_claims.py:parse_pointer_claims — the model's pointer-line output → ParsedClaim records (the CTI compile step)
  • aborist/qa/evidence.py:EvidenceObject — typed evidence nodes with evidence_id (content-addressed) + pointer_id (prompt-facing)
  • aborist/qa/evidence.py:render_claim_lattice — the renderer that interpolates source spans by offset
  • aborist/qa/verify.py:verify_claim_lattice — the deterministic verifier (six hard checks + sidecar signals)
  • aborist/qa/verify.py:verify_claim_lattice_json — same for the JSON variant
  • aborist/qa/quantifier.py:classify_question_quantifier — pure 10-rung intensity classifier (#000008); feeds the preflight stage's classifier clause
  • aborist/qa/model_profiles.py:cap_for_intensity — per-model claim-cap profiles (#000008); feeds the answer_contract clause's claim_cap_resolved
  • aborist/qa/quantifier_reminder.py:broad_quantifier_reminder — broad-question reminder text generator (#000008); feeds the prompt_contract clause
  • aborist/qa/metacognition.py:preflight_question — meta-cognition QuestionState detector suite (#000010): temporal, contradiction, false-premise-lite, out-of-corpus. Feeds the preflight stage's question_state clause.

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_hash chains 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_refsgovernance_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:

  • aborist/qa/dag.py:build_run_dag — emits the 7/8/9/10-stage DAG; returns {root, nodes, blob}. preflight_hash parameter optional for backward-compat with legacy roots.
  • aborist/qa/dag.py:build_reject_run_dag — emits the 3-stage reject-path DAG.
  • aborist/qa/dag.py:preflight_node_hash + build_preflight_node_payload — canonical hash of the preflight clause set.
  • aborist/merkle.py — the non-commutative HashCombine + odd-self-duplicate Merkle conventions (Python port of proxy.unturf.com/pkg/verified/merkle.go)
  • aborist.store.append_audit — the only legal entry point for audit_events; computes event_hash = sha256(prev_event_hash || canonical(body))
  • aborist/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 → corpus reverse 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:

  • aborist/qa/evidence.pyEvidenceObject(source_root, document_uri, chunk_root, offset_start, offset_end, source_role, text_hash, span, evidence_id, pointer_id). The pointer_id (E1, E2, …) is what the model sees in the prompt; the evidence_id (content-addressed) is the cache/run-DAG handle. The runtime maps pointer_id → object → content-addressed evidence_id internally.
  • aborist/qa/verify.py:verify_claim_lattice step 6 (citation-overlap check) — the claim → cited_span lexical-coverage gate
  • aborist/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_cache table + the audit_events chain
  • the deliberate honesty boundary: NOT semantic truth, NOT hallucination elimination, NOT formal proof — just admissible provenance

Today's codebase:

  • aborist/qa/keys.py — all eight dimensions hashed into cache_key
  • aborist/store.py — schema, audit chain, transaction helpers
  • aborist/qa/runner.py + aborist/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_ids referencing 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:

  • aborist/qa/client.py:OpenAICompatibleClient — HTTP client with retry on 502/503/504
  • aborist/qa/client.py:StubClient — offline test stub
  • claim_lattice_system_prompt + claim_lattice_grounding_reminder — the prompt fields that frame Hermes' role
  • claim_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:

  1. Verifier-policy-hash separation — landing in this commit pass. Fold answer_mode + parser_version + evidence_schema_version + manual_quote_policy + hard_checks_list into a 9th dimension that's separate from governance_policy_hash. Prevents cross-mode cache aliasing more cleanly.
  2. 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.
  3. Self-reference distillation — STRICT claims become Cores via a new ProvidenceDistiller (see docs/self-reference-design.md). Lets new claims compose from existing facts, not just retrieve them.
  4. PROMETHEUS-Σ explicit naming — deferred. The control logic exists; an extracted prometheus.py module is a refactor with no behavior change.

The architecture is real. The labels above name what's already there.