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.
This commit is contained in:
russell@unturf.com 2026-05-03 19:18:22 -04:00
parent 111dda6160
commit de07ad9392
No known key found for this signature in database
13 changed files with 907 additions and 507 deletions

View file

@ -57,7 +57,7 @@ aborist/
│ ├── verify.py # layered verifier + claim-lattice verifiers (G0)
│ ├── evidence.py # EvidenceObject + spotlight excerpt
│ ├── inspect.py # read-only sidecars (deflection, title-relevance)
│ ├── dag.py # per-run Merkle-DAG (7-stage quote / 9-stage CTI)
│ ├── dag.py # per-run Merkle-DAG (7/8 quote · 9/10 CTI · 3 reject)
│ ├── quantifier.py # broad-quantifier classifier (#000008 P1)
│ ├── model_profiles.py # per-model claim-cap profiles (#000008 P2)
│ ├── quantifier_reminder.py # broad-query reminder text (#000008 P3)

View file

@ -215,9 +215,11 @@ _VERIFIER_POLICY_FIELDS = frozenset({
# 2026-05-02b, Rule 9). Threshold of question∩claim content tokens
# absent from cited evidence union that demotes STRICT → HYBRID.
"claim_lattice_subject_tokens_absent_threshold",
# Ticket #000008 Phase 2 — quantifier preflight guard. The four
# Ticket #000008 Phase 2-4 — quantifier preflight guard. The seven
# fields together control whether broad-quantifier classification
# affects the per-call claim cap and which modes are gated.
# affects the per-call claim cap, which modes are gated, whether
# the reminder fires, and whether reject-broad early-return takes
# over. Plus #000010 adds six more for metacognition (see below).
# Adding a model to model_profiles.py PROFILES doesn't bump
# governance_policy_hash on its own (the dict isn't policy);
# but flipping any of these knobs DOES bump the hash, which

View file

@ -2641,12 +2641,15 @@ def query(
}
proof_blob = json.dumps(proof_obj, separators=(",", ":"))
# Per-run Merkle-DAG. Quote mode keeps the original 7-stage
# shape (question / retrieval / context / prompt / answer /
# verify / final_label). Pointer mode swaps to the 9-stage CTI
# shape — context drops out, answer splits into raw_answer /
# parsed_claim_lattice / render — and threads violations +
# answer_mode into the verify/final_label payloads.
# Per-run Merkle-DAG. Quote mode base shape: 7 stages
# (question / retrieval / context / prompt / answer / verify
# / final_label); becomes 8 when preflight_hash is supplied
# (#000009 inserts ``preflight`` between question & retrieval).
# Pointer mode base shape: 9 stages (question / retrieval /
# evidence_map / prompt / raw_answer / parsed_claim_lattice /
# verify / render / final_label); becomes 10 with preflight.
# Reject-broad early-return path uses a 3-stage minimal DAG
# (question / preflight / final_label) via build_reject_run_dag().
ev_root = evidence_map_root(evidence_map) if evidence_map else None
parsed_lattice = None
is_lattice_mode = answer_mode in ("claim_lattice_pointer", "claim_lattice")

View file

@ -831,10 +831,11 @@ def ask(
}
proof_blob = json.dumps(proof_obj, separators=(",", ":"))
# Per-run Merkle-DAG (see aborist/qa/dag.py). Single-doc shape: the
# only "source" is document_root. Pointer mode swaps the 7-stage
# quote shape for the 9-stage CTI shape — context drops out and
# answer splits into raw_answer / parsed_claim_lattice / render.
# Per-run Merkle-DAG (see aborist/qa/dag.py). Single-doc shape:
# the only "source" is document_root. Quote mode: 7 stages base
# (8 with #000009 preflight). Pointer mode: 9 stages base (10 with
# preflight); context drops out and answer splits into raw_answer
# / parsed_claim_lattice / render.
ev_root = evidence_map_root(evidence_map) if evidence_map else None
parsed_lattice = None
is_lattice_mode = answer_mode in ("claim_lattice_pointer", "claim_lattice")

View file

@ -84,25 +84,49 @@ The animating principle: **the model proposes, the runtime structures, the verif
- `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.
**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 over the 9 stages (question / retrieval / evidence_map / prompt / raw_answer / parsed_claim_lattice / verify / render / final_label)
- 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_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:**
- `aborist/qa/dag.py:build_run_dag` — emits the 9-stage DAG; returns `{root, nodes, blob}`
- `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 9-stage DAG was the F-track work earlier in the session.
**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)

View file

@ -57,9 +57,14 @@ digraph aborist_modules {
qa_warrant[label="qa/warrant.py\n5 anchor classes\n(proper-noun · date · count\n · entity-list · cause)", fillcolor="#ffe6f0"]
qa_evidence[label="qa/evidence.py\nEvidenceObject + spotlight", fillcolor="#ffe6f0"]
qa_runner [label="qa/runner.py\nask(): single-doc Q&A", fillcolor="#ffe6f0"]
qa_dag [label="qa/dag.py\nper-run Merkle DAG\n(7 / 9 stages)", fillcolor="#ffe6f0"]
qa_dag [label="qa/dag.py\nper-run Merkle DAG\n(7/8 quote · 9/10 CTI · 3 reject)\npreflight_node_hash + 5 clauses", fillcolor="#ffe6f0"]
qa_keys [label="qa/keys.py\n8-dim cache_key + question_hash", fillcolor="#ffe6f0"]
qa_inspect[label="qa/inspect.py\nsidecar diagnostic\n(read-only)", fillcolor="#ffe6f0"]
// Preflight modules (Tickets #000008 + #000010)
qa_quantifier [label="qa/quantifier.py\n10-rung intensity classifier\n(#000008)", fillcolor="#ffe6f0"]
qa_model_profiles [label="qa/model_profiles.py\nper-model claim-cap profiles\n(#000008)", fillcolor="#ffe6f0"]
qa_quantifier_reminder[label="qa/quantifier_reminder.py\nbroad-query reminder text\n(#000008)", fillcolor="#ffe6f0"]
qa_metacognition [label="qa/metacognition.py\nQuestionState + 4 detectors\n(temporal · contradiction ·\n false-premise · out-of-corpus)\n(#000010)", fillcolor="#ffe6f0"]
}
// ---- Distill (surface → core) ----
@ -99,6 +104,18 @@ digraph aborist_modules {
qa_runner -> qa_query
qa_inspect -> qa_query [style=dashed, label="read-only sidecar"]
// Preflight wiring (#000008 + #000010 → #000009 DAG binding)
qa_query -> qa_quantifier [label="classify_question_quantifier"]
qa_query -> qa_model_profiles [label="cap_for_intensity"]
qa_query -> qa_quantifier_reminder [label="broad_quantifier_reminder"]
qa_query -> qa_metacognition [label="preflight_question"]
qa_runner -> qa_quantifier
qa_runner -> qa_model_profiles
qa_runner -> qa_quantifier_reminder
qa_runner -> qa_metacognition
qa_dag -> qa_quantifier [style=dotted, label="preflight clause"]
qa_dag -> qa_metacognition [style=dotted, label="preflight clause"]
// Concepts reads existing edges
concepts -> store [label="reads edges,\nwrites concept_relations"]

View file

@ -4,440 +4,541 @@
<!-- Generated by graphviz version 2.43.0 (0)
-->
<!-- Title: aborist_modules Pages: 1 -->
<svg width="1613pt" height="953pt"
viewBox="0.00 0.00 1613.00 952.66" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 948.66)">
<svg width="1663pt" height="1147pt"
viewBox="0.00 0.00 1663.00 1146.81" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 1142.81)">
<title>aborist_modules</title>
<polygon fill="white" stroke="transparent" points="-4,4 -4,-948.66 1609,-948.66 1609,4 -4,4"/>
<polygon fill="white" stroke="transparent" points="-4,4 -4,-1142.81 1659,-1142.81 1659,4 -4,4"/>
<g id="clust1" class="cluster">
<title>cluster_substrate</title>
<path fill="white" stroke="#999999" stroke-dasharray="5,2" d="M1245,-506.67C1245,-506.67 1585,-506.67 1585,-506.67 1591,-506.67 1597,-512.67 1597,-518.67 1597,-518.67 1597,-623.67 1597,-623.67 1597,-629.67 1591,-635.67 1585,-635.67 1585,-635.67 1245,-635.67 1245,-635.67 1239,-635.67 1233,-629.67 1233,-623.67 1233,-623.67 1233,-518.67 1233,-518.67 1233,-512.67 1239,-506.67 1245,-506.67"/>
<text text-anchor="middle" x="1415" y="-620.47" font-family="Times,serif" font-size="14.00">substrate</text>
<path fill="white" stroke="#999999" stroke-dasharray="5,2" d="M1295,-692.88C1295,-692.88 1635,-692.88 1635,-692.88 1641,-692.88 1647,-698.88 1647,-704.88 1647,-704.88 1647,-809.88 1647,-809.88 1647,-815.88 1641,-821.88 1635,-821.88 1635,-821.88 1295,-821.88 1295,-821.88 1289,-821.88 1283,-815.88 1283,-809.88 1283,-809.88 1283,-704.88 1283,-704.88 1283,-698.88 1289,-692.88 1295,-692.88"/>
<text text-anchor="middle" x="1465" y="-806.68" font-family="Times,serif" font-size="14.00">substrate</text>
</g>
<g id="clust2" class="cluster">
<title>cluster_storage</title>
<path fill="white" stroke="#999999" stroke-dasharray="5,2" d="M710,-506.67C710,-506.67 1188,-506.67 1188,-506.67 1194,-506.67 1200,-512.67 1200,-518.67 1200,-518.67 1200,-623.67 1200,-623.67 1200,-629.67 1194,-635.67 1188,-635.67 1188,-635.67 710,-635.67 710,-635.67 704,-635.67 698,-629.67 698,-623.67 698,-623.67 698,-518.67 698,-518.67 698,-512.67 704,-506.67 710,-506.67"/>
<text text-anchor="middle" x="949" y="-620.47" font-family="Times,serif" font-size="14.00">storage</text>
<path fill="white" stroke="#999999" stroke-dasharray="5,2" d="M745,-692.88C745,-692.88 1230.5,-692.88 1230.5,-692.88 1236.5,-692.88 1242.5,-698.88 1242.5,-704.88 1242.5,-704.88 1242.5,-809.88 1242.5,-809.88 1242.5,-815.88 1236.5,-821.88 1230.5,-821.88 1230.5,-821.88 745,-821.88 745,-821.88 739,-821.88 733,-815.88 733,-809.88 733,-809.88 733,-704.88 733,-704.88 733,-698.88 739,-692.88 745,-692.88"/>
<text text-anchor="middle" x="987.75" y="-806.68" font-family="Times,serif" font-size="14.00">storage</text>
</g>
<g id="clust3" class="cluster">
<title>cluster_sources</title>
<path fill="white" stroke="#999999" stroke-dasharray="5,2" d="M221.5,-586.67C221.5,-586.67 580,-586.67 580,-586.67 586,-586.67 592,-592.67 592,-598.67 592,-598.67 592,-865.67 592,-865.67 592,-871.67 586,-877.67 580,-877.67 580,-877.67 221.5,-877.67 221.5,-877.67 215.5,-877.67 209.5,-871.67 209.5,-865.67 209.5,-865.67 209.5,-598.67 209.5,-598.67 209.5,-592.67 215.5,-586.67 221.5,-586.67"/>
<text text-anchor="middle" x="400.75" y="-862.47" font-family="Times,serif" font-size="14.00">sources/</text>
<path fill="white" stroke="#999999" stroke-dasharray="5,2" d="M221.5,-761.88C221.5,-761.88 580,-761.88 580,-761.88 586,-761.88 592,-767.88 592,-773.88 592,-773.88 592,-1040.88 592,-1040.88 592,-1046.88 586,-1052.88 580,-1052.88 580,-1052.88 221.5,-1052.88 221.5,-1052.88 215.5,-1052.88 209.5,-1046.88 209.5,-1040.88 209.5,-1040.88 209.5,-773.88 209.5,-773.88 209.5,-767.88 215.5,-761.88 221.5,-761.88"/>
<text text-anchor="middle" x="400.75" y="-1037.68" font-family="Times,serif" font-size="14.00">sources/</text>
</g>
<g id="clust4" class="cluster">
<title>cluster_retrieval</title>
<path fill="white" stroke="#999999" stroke-dasharray="5,2" d="M220,-121.67C220,-121.67 1200,-121.67 1200,-121.67 1206,-121.67 1212,-127.67 1212,-133.67 1212,-133.67 1212,-438.67 1212,-438.67 1212,-444.67 1206,-450.67 1200,-450.67 1200,-450.67 220,-450.67 220,-450.67 214,-450.67 208,-444.67 208,-438.67 208,-438.67 208,-133.67 208,-133.67 208,-127.67 214,-121.67 220,-121.67"/>
<text text-anchor="middle" x="710" y="-435.47" font-family="Times,serif" font-size="14.00">retrieval &amp; verifier</text>
<path fill="white" stroke="#999999" stroke-dasharray="5,2" d="M220,-35.88C220,-35.88 1250,-35.88 1250,-35.88 1256,-35.88 1262,-41.88 1262,-47.88 1262,-47.88 1262,-613.88 1262,-613.88 1262,-619.88 1256,-625.88 1250,-625.88 1250,-625.88 220,-625.88 220,-625.88 214,-625.88 208,-619.88 208,-613.88 208,-613.88 208,-47.88 208,-47.88 208,-41.88 214,-35.88 220,-35.88"/>
<text text-anchor="middle" x="735" y="-610.68" font-family="Times,serif" font-size="14.00">retrieval &amp; verifier</text>
</g>
<!-- merkle -->
<g id="node1" class="node">
<title>merkle</title>
<path fill="#fff7e6" stroke="black" d="M1577,-577.67C1577,-577.67 1439,-577.67 1439,-577.67 1433,-577.67 1427,-571.67 1427,-565.67 1427,-565.67 1427,-553.67 1427,-553.67 1427,-547.67 1433,-541.67 1439,-541.67 1439,-541.67 1577,-541.67 1577,-541.67 1583,-541.67 1589,-547.67 1589,-553.67 1589,-553.67 1589,-565.67 1589,-565.67 1589,-571.67 1583,-577.67 1577,-577.67"/>
<text text-anchor="middle" x="1508" y="-562.67" font-family="Helvetica,sans-Serif" font-size="10.00">merkle.py</text>
<text text-anchor="middle" x="1508" y="-551.67" font-family="Helvetica,sans-Serif" font-size="10.00">(Python port of Go merkle.go)</text>
<path fill="#fff7e6" stroke="black" d="M1627,-763.88C1627,-763.88 1489,-763.88 1489,-763.88 1483,-763.88 1477,-757.88 1477,-751.88 1477,-751.88 1477,-739.88 1477,-739.88 1477,-733.88 1483,-727.88 1489,-727.88 1489,-727.88 1627,-727.88 1627,-727.88 1633,-727.88 1639,-733.88 1639,-739.88 1639,-739.88 1639,-751.88 1639,-751.88 1639,-757.88 1633,-763.88 1627,-763.88"/>
<text text-anchor="middle" x="1558" y="-748.88" font-family="Helvetica,sans-Serif" font-size="10.00">merkle.py</text>
<text text-anchor="middle" x="1558" y="-737.88" font-family="Helvetica,sans-Serif" font-size="10.00">(Python port of Go merkle.go)</text>
</g>
<!-- document -->
<g id="node2" class="node">
<title>document</title>
<path fill="#fff7e6" stroke="black" d="M1378,-604.67C1378,-604.67 1253,-604.67 1253,-604.67 1247,-604.67 1241,-598.67 1241,-592.67 1241,-592.67 1241,-580.67 1241,-580.67 1241,-574.67 1247,-568.67 1253,-568.67 1253,-568.67 1378,-568.67 1378,-568.67 1384,-568.67 1390,-574.67 1390,-580.67 1390,-580.67 1390,-592.67 1390,-592.67 1390,-598.67 1384,-604.67 1378,-604.67"/>
<text text-anchor="middle" x="1315.5" y="-589.67" font-family="Helvetica,sans-Serif" font-size="10.00">document.py</text>
<text text-anchor="middle" x="1315.5" y="-578.67" font-family="Helvetica,sans-Serif" font-size="10.00">Document · Edge · Chunker</text>
<path fill="#fff7e6" stroke="black" d="M1428,-790.88C1428,-790.88 1303,-790.88 1303,-790.88 1297,-790.88 1291,-784.88 1291,-778.88 1291,-778.88 1291,-766.88 1291,-766.88 1291,-760.88 1297,-754.88 1303,-754.88 1303,-754.88 1428,-754.88 1428,-754.88 1434,-754.88 1440,-760.88 1440,-766.88 1440,-766.88 1440,-778.88 1440,-778.88 1440,-784.88 1434,-790.88 1428,-790.88"/>
<text text-anchor="middle" x="1365.5" y="-775.88" font-family="Helvetica,sans-Serif" font-size="10.00">document.py</text>
<text text-anchor="middle" x="1365.5" y="-764.88" font-family="Helvetica,sans-Serif" font-size="10.00">Document · Edge · Chunker</text>
</g>
<!-- document&#45;&gt;merkle -->
<g id="edge1" class="edge">
<title>document&#45;&gt;merkle</title>
<path fill="none" stroke="black" d="M1390.15,-576.23C1398.9,-574.99 1407.91,-573.72 1416.85,-572.45"/>
<polygon fill="black" stroke="black" points="1417.5,-575.89 1426.91,-571.02 1416.51,-568.96 1417.5,-575.89"/>
<path fill="none" stroke="black" d="M1440.15,-762.44C1448.9,-761.2 1457.91,-759.93 1466.85,-758.66"/>
<polygon fill="black" stroke="black" points="1467.5,-762.1 1476.91,-757.23 1466.51,-755.17 1467.5,-762.1"/>
</g>
<!-- wikitext -->
<g id="node3" class="node">
<title>wikitext</title>
<path fill="#fff7e6" stroke="black" d="M1362.5,-550.67C1362.5,-550.67 1268.5,-550.67 1268.5,-550.67 1262.5,-550.67 1256.5,-544.67 1256.5,-538.67 1256.5,-538.67 1256.5,-526.67 1256.5,-526.67 1256.5,-520.67 1262.5,-514.67 1268.5,-514.67 1268.5,-514.67 1362.5,-514.67 1362.5,-514.67 1368.5,-514.67 1374.5,-520.67 1374.5,-526.67 1374.5,-526.67 1374.5,-538.67 1374.5,-538.67 1374.5,-544.67 1368.5,-550.67 1362.5,-550.67"/>
<text text-anchor="middle" x="1315.5" y="-535.67" font-family="Helvetica,sans-Serif" font-size="10.00">wikitext.py</text>
<text text-anchor="middle" x="1315.5" y="-524.67" font-family="Helvetica,sans-Serif" font-size="10.00">to_base() prose&#45;strip</text>
<path fill="#fff7e6" stroke="black" d="M1412.5,-736.88C1412.5,-736.88 1318.5,-736.88 1318.5,-736.88 1312.5,-736.88 1306.5,-730.88 1306.5,-724.88 1306.5,-724.88 1306.5,-712.88 1306.5,-712.88 1306.5,-706.88 1312.5,-700.88 1318.5,-700.88 1318.5,-700.88 1412.5,-700.88 1412.5,-700.88 1418.5,-700.88 1424.5,-706.88 1424.5,-712.88 1424.5,-712.88 1424.5,-724.88 1424.5,-724.88 1424.5,-730.88 1418.5,-736.88 1412.5,-736.88"/>
<text text-anchor="middle" x="1365.5" y="-721.88" font-family="Helvetica,sans-Serif" font-size="10.00">wikitext.py</text>
<text text-anchor="middle" x="1365.5" y="-710.88" font-family="Helvetica,sans-Serif" font-size="10.00">to_base() prose&#45;strip</text>
</g>
<!-- store -->
<g id="node4" class="node">
<title>store</title>
<path fill="#e6f0ff" stroke="black" d="M1180,-556.17C1180,-556.17 1079,-556.17 1079,-556.17 1073,-556.17 1067,-550.17 1067,-544.17 1067,-544.17 1067,-527.17 1067,-527.17 1067,-521.17 1073,-515.17 1079,-515.17 1079,-515.17 1180,-515.17 1180,-515.17 1186,-515.17 1192,-521.17 1192,-527.17 1192,-527.17 1192,-544.17 1192,-544.17 1192,-550.17 1186,-556.17 1180,-556.17"/>
<text text-anchor="middle" x="1129.5" y="-544.17" font-family="Helvetica,sans-Serif" font-size="10.00">store.py</text>
<text text-anchor="middle" x="1129.5" y="-533.17" font-family="Helvetica,sans-Serif" font-size="10.00">v9.8 SQLite schema +</text>
<text text-anchor="middle" x="1129.5" y="-522.17" font-family="Helvetica,sans-Serif" font-size="10.00">audit chain helpers</text>
<path fill="#e6f0ff" stroke="black" d="M1222.5,-742.38C1222.5,-742.38 1121.5,-742.38 1121.5,-742.38 1115.5,-742.38 1109.5,-736.38 1109.5,-730.38 1109.5,-730.38 1109.5,-713.38 1109.5,-713.38 1109.5,-707.38 1115.5,-701.38 1121.5,-701.38 1121.5,-701.38 1222.5,-701.38 1222.5,-701.38 1228.5,-701.38 1234.5,-707.38 1234.5,-713.38 1234.5,-713.38 1234.5,-730.38 1234.5,-730.38 1234.5,-736.38 1228.5,-742.38 1222.5,-742.38"/>
<text text-anchor="middle" x="1172" y="-730.38" font-family="Helvetica,sans-Serif" font-size="10.00">store.py</text>
<text text-anchor="middle" x="1172" y="-719.38" font-family="Helvetica,sans-Serif" font-size="10.00">v9.8 SQLite schema +</text>
<text text-anchor="middle" x="1172" y="-708.38" font-family="Helvetica,sans-Serif" font-size="10.00">audit chain helpers</text>
</g>
<!-- store&#45;&gt;merkle -->
<g id="edge2" class="edge">
<title>store&#45;&gt;merkle</title>
<path fill="none" stroke="black" d="M1190.03,-515.15C1203.96,-511.22 1218.87,-507.7 1233,-505.67 1302.07,-495.77 1321.85,-490.7 1390,-505.67 1417.34,-511.68 1445.91,-524.71 1467.97,-536.47"/>
<polygon fill="black" stroke="black" points="1466.55,-539.68 1477,-541.41 1469.9,-533.54 1466.55,-539.68"/>
<path fill="none" stroke="black" d="M1234.65,-701.97C1250.26,-697.79 1267.11,-694.01 1283,-691.88 1352.16,-682.62 1371.85,-676.91 1440,-691.88 1467.34,-697.89 1495.91,-710.92 1517.97,-722.68"/>
<polygon fill="black" stroke="black" points="1516.55,-725.89 1527,-727.62 1519.9,-719.75 1516.55,-725.89"/>
</g>
<!-- store&#45;&gt;document -->
<g id="edge3" class="edge">
<title>store&#45;&gt;document</title>
<path fill="none" stroke="black" d="M1192.03,-552.73C1207.25,-556.95 1223.73,-561.51 1239.52,-565.89"/>
<polygon fill="black" stroke="black" points="1238.68,-569.29 1249.25,-568.59 1240.55,-562.54 1238.68,-569.29"/>
<path fill="none" stroke="black" d="M1234.65,-738.3C1251.19,-742.7 1269.3,-747.53 1286.6,-752.13"/>
<polygon fill="black" stroke="black" points="1286.11,-755.63 1296.67,-754.82 1287.91,-748.86 1286.11,-755.63"/>
</g>
<!-- ingest -->
<g id="node5" class="node">
<title>ingest</title>
<path fill="#e6f0ff" stroke="black" d="M897,-604.67C897,-604.67 718,-604.67 718,-604.67 712,-604.67 706,-598.67 706,-592.67 706,-592.67 706,-580.67 706,-580.67 706,-574.67 712,-568.67 718,-568.67 718,-568.67 897,-568.67 897,-568.67 903,-568.67 909,-574.67 909,-580.67 909,-580.67 909,-592.67 909,-592.67 909,-598.67 903,-604.67 897,-604.67"/>
<text text-anchor="middle" x="807.5" y="-589.67" font-family="Helvetica,sans-Serif" font-size="10.00">ingest.py</text>
<text text-anchor="middle" x="807.5" y="-578.67" font-family="Helvetica,sans-Serif" font-size="10.00">normalize → chunk → merkle → upsert</text>
<path fill="#e6f0ff" stroke="black" d="M932,-790.88C932,-790.88 753,-790.88 753,-790.88 747,-790.88 741,-784.88 741,-778.88 741,-778.88 741,-766.88 741,-766.88 741,-760.88 747,-754.88 753,-754.88 753,-754.88 932,-754.88 932,-754.88 938,-754.88 944,-760.88 944,-766.88 944,-766.88 944,-778.88 944,-778.88 944,-784.88 938,-790.88 932,-790.88"/>
<text text-anchor="middle" x="842.5" y="-775.88" font-family="Helvetica,sans-Serif" font-size="10.00">ingest.py</text>
<text text-anchor="middle" x="842.5" y="-764.88" font-family="Helvetica,sans-Serif" font-size="10.00">normalize → chunk → merkle → upsert</text>
</g>
<!-- ingest&#45;&gt;document -->
<g id="edge5" class="edge">
<title>ingest&#45;&gt;document</title>
<path fill="none" stroke="black" d="M909.07,-586.67C1003.2,-586.67 1142.19,-586.67 1230.52,-586.67"/>
<polygon fill="black" stroke="black" points="1230.77,-590.17 1240.77,-586.67 1230.77,-583.17 1230.77,-590.17"/>
<path fill="none" stroke="black" d="M944.26,-772.88C1042.2,-772.88 1189.2,-772.88 1280.86,-772.88"/>
<polygon fill="black" stroke="black" points="1280.93,-776.38 1290.93,-772.88 1280.93,-769.38 1280.93,-776.38"/>
</g>
<!-- ingest&#45;&gt;store -->
<g id="edge4" class="edge">
<title>ingest&#45;&gt;store</title>
<path fill="none" stroke="black" d="M909.31,-570.61C957.24,-562.97 1013.42,-554.01 1056.9,-547.08"/>
<polygon fill="black" stroke="black" points="1057.5,-550.53 1066.82,-545.5 1056.39,-543.62 1057.5,-550.53"/>
<path fill="none" stroke="black" d="M944.43,-757.16C994.58,-749.35 1053.99,-740.1 1099.39,-733.03"/>
<polygon fill="black" stroke="black" points="1100.1,-736.46 1109.44,-731.47 1099.02,-729.55 1100.1,-736.46"/>
</g>
<!-- evict -->
<g id="node6" class="node">
<title>evict</title>
<path fill="#e6f0ff" stroke="black" d="M838.5,-550.67C838.5,-550.67 776.5,-550.67 776.5,-550.67 770.5,-550.67 764.5,-544.67 764.5,-538.67 764.5,-538.67 764.5,-526.67 764.5,-526.67 764.5,-520.67 770.5,-514.67 776.5,-514.67 776.5,-514.67 838.5,-514.67 838.5,-514.67 844.5,-514.67 850.5,-520.67 850.5,-526.67 850.5,-526.67 850.5,-538.67 850.5,-538.67 850.5,-544.67 844.5,-550.67 838.5,-550.67"/>
<text text-anchor="middle" x="807.5" y="-535.67" font-family="Helvetica,sans-Serif" font-size="10.00">evict.py</text>
<text text-anchor="middle" x="807.5" y="-524.67" font-family="Helvetica,sans-Serif" font-size="10.00">hot ↔ cold tier</text>
<path fill="#e6f0ff" stroke="black" d="M873.5,-736.88C873.5,-736.88 811.5,-736.88 811.5,-736.88 805.5,-736.88 799.5,-730.88 799.5,-724.88 799.5,-724.88 799.5,-712.88 799.5,-712.88 799.5,-706.88 805.5,-700.88 811.5,-700.88 811.5,-700.88 873.5,-700.88 873.5,-700.88 879.5,-700.88 885.5,-706.88 885.5,-712.88 885.5,-712.88 885.5,-724.88 885.5,-724.88 885.5,-730.88 879.5,-736.88 873.5,-736.88"/>
<text text-anchor="middle" x="842.5" y="-721.88" font-family="Helvetica,sans-Serif" font-size="10.00">evict.py</text>
<text text-anchor="middle" x="842.5" y="-710.88" font-family="Helvetica,sans-Serif" font-size="10.00">hot ↔ cold tier</text>
</g>
<!-- evict&#45;&gt;store -->
<g id="edge27" class="edge">
<g id="edge37" class="edge">
<title>evict&#45;&gt;store</title>
<path fill="none" stroke="black" d="M850.66,-533.07C902.99,-533.56 993.06,-534.4 1056.43,-535"/>
<polygon fill="black" stroke="black" points="1056.72,-538.5 1066.75,-535.09 1056.79,-531.5 1056.72,-538.5"/>
<path fill="none" stroke="black" d="M885.64,-719.27C939.6,-719.76 1033.89,-720.62 1099.25,-721.22"/>
<polygon fill="black" stroke="black" points="1099.45,-724.73 1109.48,-721.32 1099.51,-717.73 1099.45,-724.73"/>
</g>
<!-- wikipedia -->
<g id="node7" class="node">
<title>wikipedia</title>
<path fill="#e7ffe7" stroke="black" d="M324.5,-792.67C324.5,-792.67 229.5,-792.67 229.5,-792.67 223.5,-792.67 217.5,-786.67 217.5,-780.67 217.5,-780.67 217.5,-768.67 217.5,-768.67 217.5,-762.67 223.5,-756.67 229.5,-756.67 229.5,-756.67 324.5,-756.67 324.5,-756.67 330.5,-756.67 336.5,-762.67 336.5,-768.67 336.5,-768.67 336.5,-780.67 336.5,-780.67 336.5,-786.67 330.5,-792.67 324.5,-792.67"/>
<text text-anchor="middle" x="277" y="-777.67" font-family="Helvetica,sans-Serif" font-size="10.00">wikipedia.py</text>
<text text-anchor="middle" x="277" y="-766.67" font-family="Helvetica,sans-Serif" font-size="10.00">cur + old SQL dumps</text>
<path fill="#e7ffe7" stroke="black" d="M324.5,-967.88C324.5,-967.88 229.5,-967.88 229.5,-967.88 223.5,-967.88 217.5,-961.88 217.5,-955.88 217.5,-955.88 217.5,-943.88 217.5,-943.88 217.5,-937.88 223.5,-931.88 229.5,-931.88 229.5,-931.88 324.5,-931.88 324.5,-931.88 330.5,-931.88 336.5,-937.88 336.5,-943.88 336.5,-943.88 336.5,-955.88 336.5,-955.88 336.5,-961.88 330.5,-967.88 324.5,-967.88"/>
<text text-anchor="middle" x="277" y="-952.88" font-family="Helvetica,sans-Serif" font-size="10.00">wikipedia.py</text>
<text text-anchor="middle" x="277" y="-941.88" font-family="Helvetica,sans-Serif" font-size="10.00">cur + old SQL dumps</text>
</g>
<!-- wikipedia&#45;&gt;ingest -->
<g id="edge6" class="edge">
<title>wikipedia&#45;&gt;ingest</title>
<path fill="none" stroke="black" d="M336.82,-788.51C426.22,-805.68 595.67,-822.41 688,-729.67 702.98,-714.63 685.5,-651.83 698,-634.67 705.68,-624.12 716.21,-615.86 727.7,-609.39"/>
<polygon fill="black" stroke="black" points="729.35,-612.47 736.64,-604.79 726.15,-606.25 729.35,-612.47"/>
<path fill="none" stroke="black" d="M336.71,-953.21C444.91,-957.98 669.64,-961.12 723,-908.88 737.06,-895.11 721.35,-836.74 733,-820.88 740.78,-810.3 751.41,-802.01 762.99,-795.53"/>
<polygon fill="black" stroke="black" points="764.69,-798.59 772,-790.92 761.5,-792.36 764.69,-798.59"/>
</g>
<!-- wiki_xml -->
<g id="node8" class="node">
<title>wiki_xml</title>
<path fill="#e7ffe7" stroke="black" d="M317.5,-684.67C317.5,-684.67 236.5,-684.67 236.5,-684.67 230.5,-684.67 224.5,-678.67 224.5,-672.67 224.5,-672.67 224.5,-660.67 224.5,-660.67 224.5,-654.67 230.5,-648.67 236.5,-648.67 236.5,-648.67 317.5,-648.67 317.5,-648.67 323.5,-648.67 329.5,-654.67 329.5,-660.67 329.5,-660.67 329.5,-672.67 329.5,-672.67 329.5,-678.67 323.5,-684.67 317.5,-684.67"/>
<text text-anchor="middle" x="277" y="-669.67" font-family="Helvetica,sans-Serif" font-size="10.00">wikipedia_xml.py</text>
<text text-anchor="middle" x="277" y="-658.67" font-family="Helvetica,sans-Serif" font-size="10.00">phase IV iterparse</text>
<path fill="#e7ffe7" stroke="black" d="M317.5,-859.88C317.5,-859.88 236.5,-859.88 236.5,-859.88 230.5,-859.88 224.5,-853.88 224.5,-847.88 224.5,-847.88 224.5,-835.88 224.5,-835.88 224.5,-829.88 230.5,-823.88 236.5,-823.88 236.5,-823.88 317.5,-823.88 317.5,-823.88 323.5,-823.88 329.5,-829.88 329.5,-835.88 329.5,-835.88 329.5,-847.88 329.5,-847.88 329.5,-853.88 323.5,-859.88 317.5,-859.88"/>
<text text-anchor="middle" x="277" y="-844.88" font-family="Helvetica,sans-Serif" font-size="10.00">wikipedia_xml.py</text>
<text text-anchor="middle" x="277" y="-833.88" font-family="Helvetica,sans-Serif" font-size="10.00">phase IV iterparse</text>
</g>
<!-- wiki_xml&#45;&gt;ingest -->
<g id="edge7" class="edge">
<title>wiki_xml&#45;&gt;ingest</title>
<path fill="none" stroke="black" d="M329.54,-659.8C407.32,-649.31 559.3,-628.33 688,-607.67 690.66,-607.24 693.36,-606.81 696.08,-606.36"/>
<polygon fill="black" stroke="black" points="696.72,-609.8 706.01,-604.71 695.57,-602.9 696.72,-609.8"/>
<path fill="none" stroke="black" d="M329.8,-836.57C412.88,-827.9 580.98,-809.8 723,-790.88 725.53,-790.54 728.08,-790.2 730.66,-789.85"/>
<polygon fill="black" stroke="black" points="731.26,-793.3 740.69,-788.45 730.3,-786.36 731.26,-793.3"/>
</g>
<!-- html_page -->
<g id="node9" class="node">
<title>html_page</title>
<path fill="#e7ffe7" stroke="black" d="M572,-725.67C572,-725.67 489,-725.67 489,-725.67 483,-725.67 477,-719.67 477,-713.67 477,-713.67 477,-701.67 477,-701.67 477,-695.67 483,-689.67 489,-689.67 489,-689.67 572,-689.67 572,-689.67 578,-689.67 584,-695.67 584,-701.67 584,-701.67 584,-713.67 584,-713.67 584,-719.67 578,-725.67 572,-725.67"/>
<text text-anchor="middle" x="530.5" y="-710.67" font-family="Helvetica,sans-Serif" font-size="10.00">html_page.py</text>
<text text-anchor="middle" x="530.5" y="-699.67" font-family="Helvetica,sans-Serif" font-size="10.00">selectolax + httpx</text>
<path fill="#e7ffe7" stroke="black" d="M572,-900.88C572,-900.88 489,-900.88 489,-900.88 483,-900.88 477,-894.88 477,-888.88 477,-888.88 477,-876.88 477,-876.88 477,-870.88 483,-864.88 489,-864.88 489,-864.88 572,-864.88 572,-864.88 578,-864.88 584,-870.88 584,-876.88 584,-876.88 584,-888.88 584,-888.88 584,-894.88 578,-900.88 572,-900.88"/>
<text text-anchor="middle" x="530.5" y="-885.88" font-family="Helvetica,sans-Serif" font-size="10.00">html_page.py</text>
<text text-anchor="middle" x="530.5" y="-874.88" font-family="Helvetica,sans-Serif" font-size="10.00">selectolax + httpx</text>
</g>
<!-- html_page&#45;&gt;ingest -->
<g id="edge8" class="edge">
<title>html_page&#45;&gt;ingest</title>
<path fill="none" stroke="black" d="M584.01,-708.28C617.86,-705.86 660.53,-697.09 688,-670.67 699.97,-659.16 687.14,-647.24 698,-634.67 707.16,-624.07 719.1,-615.72 731.71,-609.17"/>
<polygon fill="black" stroke="black" points="733.49,-612.2 740.98,-604.7 730.45,-605.89 733.49,-612.2"/>
<text text-anchor="middle" x="645" y="-718.47" font-family="Helvetica,sans-Serif" font-size="9.00">parse_html →</text>
<text text-anchor="middle" x="645" y="-708.47" font-family="Helvetica,sans-Serif" font-size="9.00">edges rows</text>
<path fill="none" stroke="black" d="M584.36,-885.73C626.4,-885.18 684.37,-877.8 723,-845.88 732.23,-838.26 724.69,-829.49 733,-820.88 743.22,-810.28 756.2,-801.86 769.6,-795.22"/>
<polygon fill="black" stroke="black" points="771.3,-798.29 778.91,-790.91 768.36,-791.94 771.3,-798.29"/>
<text text-anchor="middle" x="662.5" y="-897.68" font-family="Helvetica,sans-Serif" font-size="9.00">parse_html →</text>
<text text-anchor="middle" x="662.5" y="-887.68" font-family="Helvetica,sans-Serif" font-size="9.00">edges rows</text>
</g>
<!-- crawler -->
<g id="node10" class="node">
<title>crawler</title>
<path fill="#e7ffe7" stroke="black" d="M313.5,-738.67C313.5,-738.67 240.5,-738.67 240.5,-738.67 234.5,-738.67 228.5,-732.67 228.5,-726.67 228.5,-726.67 228.5,-714.67 228.5,-714.67 228.5,-708.67 234.5,-702.67 240.5,-702.67 240.5,-702.67 313.5,-702.67 313.5,-702.67 319.5,-702.67 325.5,-708.67 325.5,-714.67 325.5,-714.67 325.5,-726.67 325.5,-726.67 325.5,-732.67 319.5,-738.67 313.5,-738.67"/>
<text text-anchor="middle" x="277" y="-723.67" font-family="Helvetica,sans-Serif" font-size="10.00">crawler/</text>
<text text-anchor="middle" x="277" y="-712.67" font-family="Helvetica,sans-Serif" font-size="10.00">async HTML BFS</text>
<path fill="#e7ffe7" stroke="black" d="M313.5,-913.88C313.5,-913.88 240.5,-913.88 240.5,-913.88 234.5,-913.88 228.5,-907.88 228.5,-901.88 228.5,-901.88 228.5,-889.88 228.5,-889.88 228.5,-883.88 234.5,-877.88 240.5,-877.88 240.5,-877.88 313.5,-877.88 313.5,-877.88 319.5,-877.88 325.5,-883.88 325.5,-889.88 325.5,-889.88 325.5,-901.88 325.5,-901.88 325.5,-907.88 319.5,-913.88 313.5,-913.88"/>
<text text-anchor="middle" x="277" y="-898.88" font-family="Helvetica,sans-Serif" font-size="10.00">crawler/</text>
<text text-anchor="middle" x="277" y="-887.88" font-family="Helvetica,sans-Serif" font-size="10.00">async HTML BFS</text>
</g>
<!-- crawler&#45;&gt;html_page -->
<g id="edge9" class="edge">
<title>crawler&#45;&gt;html_page</title>
<path fill="none" stroke="black" d="M325.6,-718.21C365.55,-716.15 422.93,-713.18 466.65,-710.92"/>
<polygon fill="black" stroke="black" points="467.07,-714.4 476.88,-710.39 466.71,-707.41 467.07,-714.4"/>
<path fill="none" stroke="black" d="M325.6,-893.42C365.55,-891.36 422.93,-888.39 466.65,-886.13"/>
<polygon fill="black" stroke="black" points="467.07,-889.61 476.88,-885.6 466.71,-882.62 467.07,-889.61"/>
</g>
<!-- grok -->
<g id="node11" class="node">
<title>grok</title>
<path fill="#e7ffe7" stroke="black" d="M298.5,-630.67C298.5,-630.67 255.5,-630.67 255.5,-630.67 249.5,-630.67 243.5,-624.67 243.5,-618.67 243.5,-618.67 243.5,-606.67 243.5,-606.67 243.5,-600.67 249.5,-594.67 255.5,-594.67 255.5,-594.67 298.5,-594.67 298.5,-594.67 304.5,-594.67 310.5,-600.67 310.5,-606.67 310.5,-606.67 310.5,-618.67 310.5,-618.67 310.5,-624.67 304.5,-630.67 298.5,-630.67"/>
<text text-anchor="middle" x="277" y="-615.67" font-family="Helvetica,sans-Serif" font-size="10.00">grok.py</text>
<text text-anchor="middle" x="277" y="-604.67" font-family="Helvetica,sans-Serif" font-size="10.00">xAI export</text>
<path fill="#e7ffe7" stroke="black" d="M298.5,-805.88C298.5,-805.88 255.5,-805.88 255.5,-805.88 249.5,-805.88 243.5,-799.88 243.5,-793.88 243.5,-793.88 243.5,-781.88 243.5,-781.88 243.5,-775.88 249.5,-769.88 255.5,-769.88 255.5,-769.88 298.5,-769.88 298.5,-769.88 304.5,-769.88 310.5,-775.88 310.5,-781.88 310.5,-781.88 310.5,-793.88 310.5,-793.88 310.5,-799.88 304.5,-805.88 298.5,-805.88"/>
<text text-anchor="middle" x="277" y="-790.88" font-family="Helvetica,sans-Serif" font-size="10.00">grok.py</text>
<text text-anchor="middle" x="277" y="-779.88" font-family="Helvetica,sans-Serif" font-size="10.00">xAI export</text>
</g>
<!-- grok&#45;&gt;ingest -->
<g id="edge10" class="edge">
<title>grok&#45;&gt;ingest</title>
<path fill="none" stroke="black" d="M310.66,-611.07C385.85,-607.37 574.05,-598.11 695.75,-592.12"/>
<polygon fill="black" stroke="black" points="696.04,-595.61 705.86,-591.62 695.7,-588.62 696.04,-595.61"/>
<path fill="none" stroke="black" d="M310.73,-787.01C390.97,-784.87 600.41,-779.3 730.93,-775.82"/>
<polygon fill="black" stroke="black" points="731.06,-779.32 740.96,-775.56 730.87,-772.32 731.06,-779.32"/>
</g>
<!-- vcs -->
<g id="node12" class="node">
<title>vcs</title>
<path fill="#e7ffe7" stroke="black" d="M309.5,-846.67C309.5,-846.67 244.5,-846.67 244.5,-846.67 238.5,-846.67 232.5,-840.67 232.5,-834.67 232.5,-834.67 232.5,-822.67 232.5,-822.67 232.5,-816.67 238.5,-810.67 244.5,-810.67 244.5,-810.67 309.5,-810.67 309.5,-810.67 315.5,-810.67 321.5,-816.67 321.5,-822.67 321.5,-822.67 321.5,-834.67 321.5,-834.67 321.5,-840.67 315.5,-846.67 309.5,-846.67"/>
<text text-anchor="middle" x="277" y="-831.67" font-family="Helvetica,sans-Serif" font-size="10.00">vcs.py</text>
<text text-anchor="middle" x="277" y="-820.67" font-family="Helvetica,sans-Serif" font-size="10.00">git + Mercurial</text>
<path fill="#e7ffe7" stroke="black" d="M309.5,-1021.88C309.5,-1021.88 244.5,-1021.88 244.5,-1021.88 238.5,-1021.88 232.5,-1015.88 232.5,-1009.88 232.5,-1009.88 232.5,-997.88 232.5,-997.88 232.5,-991.88 238.5,-985.88 244.5,-985.88 244.5,-985.88 309.5,-985.88 309.5,-985.88 315.5,-985.88 321.5,-991.88 321.5,-997.88 321.5,-997.88 321.5,-1009.88 321.5,-1009.88 321.5,-1015.88 315.5,-1021.88 309.5,-1021.88"/>
<text text-anchor="middle" x="277" y="-1006.88" font-family="Helvetica,sans-Serif" font-size="10.00">vcs.py</text>
<text text-anchor="middle" x="277" y="-995.88" font-family="Helvetica,sans-Serif" font-size="10.00">git + Mercurial</text>
</g>
<!-- vcs&#45;&gt;ingest -->
<g id="edge11" class="edge">
<title>vcs&#45;&gt;ingest</title>
<path fill="none" stroke="black" d="M321.57,-838.93C408.53,-856.48 602.61,-880.42 688,-768.67 706.13,-744.94 680.79,-659.07 698,-634.67 705.4,-624.18 715.63,-615.95 726.87,-609.51"/>
<polygon fill="black" stroke="black" points="728.82,-612.44 736.07,-604.71 725.59,-606.23 728.82,-612.44"/>
<path fill="none" stroke="black" d="M321.63,-1013.59C412.09,-1030.86 620.19,-1055.15 723,-940.88 740.9,-920.99 717.48,-842.68 733,-820.88 740.45,-810.42 750.7,-802.21 761.95,-795.77"/>
<polygon fill="black" stroke="black" points="763.9,-798.7 771.16,-790.98 760.67,-792.49 763.9,-798.7"/>
</g>
<!-- search -->
<g id="node13" class="node">
<title>search</title>
<path fill="#ffe6f0" stroke="black" d="M854.5,-245.67C854.5,-245.67 760.5,-245.67 760.5,-245.67 754.5,-245.67 748.5,-239.67 748.5,-233.67 748.5,-233.67 748.5,-221.67 748.5,-221.67 748.5,-215.67 754.5,-209.67 760.5,-209.67 760.5,-209.67 854.5,-209.67 854.5,-209.67 860.5,-209.67 866.5,-215.67 866.5,-221.67 866.5,-221.67 866.5,-233.67 866.5,-233.67 866.5,-239.67 860.5,-245.67 854.5,-245.67"/>
<text text-anchor="middle" x="807.5" y="-230.67" font-family="Helvetica,sans-Serif" font-size="10.00">search/</text>
<text text-anchor="middle" x="807.5" y="-219.67" font-family="Helvetica,sans-Serif" font-size="10.00">FTS5 backend + ABC</text>
<path fill="#ffe6f0" stroke="black" d="M889.5,-534.88C889.5,-534.88 795.5,-534.88 795.5,-534.88 789.5,-534.88 783.5,-528.88 783.5,-522.88 783.5,-522.88 783.5,-510.88 783.5,-510.88 783.5,-504.88 789.5,-498.88 795.5,-498.88 795.5,-498.88 889.5,-498.88 889.5,-498.88 895.5,-498.88 901.5,-504.88 901.5,-510.88 901.5,-510.88 901.5,-522.88 901.5,-522.88 901.5,-528.88 895.5,-534.88 889.5,-534.88"/>
<text text-anchor="middle" x="842.5" y="-519.88" font-family="Helvetica,sans-Serif" font-size="10.00">search/</text>
<text text-anchor="middle" x="842.5" y="-508.88" font-family="Helvetica,sans-Serif" font-size="10.00">FTS5 backend + ABC</text>
</g>
<!-- search&#45;&gt;store -->
<g id="edge24" class="edge">
<g id="edge34" class="edge">
<title>search&#45;&gt;store</title>
<path fill="none" stroke="black" d="M866.62,-236.81C881.21,-240.8 896.31,-246.51 909,-254.67 984.15,-303 991.42,-332.83 1037,-409.67 1047.99,-428.2 1043.58,-436.41 1055,-454.67 1067.09,-474.01 1084,-493.02 1098.56,-507.77"/>
<polygon fill="black" stroke="black" points="1096.36,-510.51 1105.92,-515.07 1101.29,-505.54 1096.36,-510.51"/>
<path fill="none" stroke="black" d="M901.71,-520.02C952.63,-525.75 1025.52,-541.57 1072,-584.88 1087.76,-599.57 1078.72,-611.53 1090,-629.88 1104.4,-653.31 1124.9,-676.52 1141.67,-693.77"/>
<polygon fill="black" stroke="black" points="1139.56,-696.61 1149.08,-701.26 1144.53,-691.69 1139.56,-696.61"/>
</g>
<!-- concepts -->
<g id="node14" class="node">
<title>concepts</title>
<path fill="#ffe6f0" stroke="black" d="M875.5,-419.17C875.5,-419.17 739.5,-419.17 739.5,-419.17 733.5,-419.17 727.5,-413.17 727.5,-407.17 727.5,-407.17 727.5,-390.17 727.5,-390.17 727.5,-384.17 733.5,-378.17 739.5,-378.17 739.5,-378.17 875.5,-378.17 875.5,-378.17 881.5,-378.17 887.5,-384.17 887.5,-390.17 887.5,-390.17 887.5,-407.17 887.5,-407.17 887.5,-413.17 881.5,-419.17 875.5,-419.17"/>
<text text-anchor="middle" x="807.5" y="-407.17" font-family="Helvetica,sans-Serif" font-size="10.00">concepts/</text>
<text text-anchor="middle" x="807.5" y="-396.17" font-family="Helvetica,sans-Serif" font-size="10.00">synonym &amp; rivalry overlay</text>
<text text-anchor="middle" x="807.5" y="-385.17" font-family="Helvetica,sans-Serif" font-size="10.00">(per&#45;shard concept_relations)</text>
<path fill="#ffe6f0" stroke="black" d="M910.5,-594.38C910.5,-594.38 774.5,-594.38 774.5,-594.38 768.5,-594.38 762.5,-588.38 762.5,-582.38 762.5,-582.38 762.5,-565.38 762.5,-565.38 762.5,-559.38 768.5,-553.38 774.5,-553.38 774.5,-553.38 910.5,-553.38 910.5,-553.38 916.5,-553.38 922.5,-559.38 922.5,-565.38 922.5,-565.38 922.5,-582.38 922.5,-582.38 922.5,-588.38 916.5,-594.38 910.5,-594.38"/>
<text text-anchor="middle" x="842.5" y="-582.38" font-family="Helvetica,sans-Serif" font-size="10.00">concepts/</text>
<text text-anchor="middle" x="842.5" y="-571.38" font-family="Helvetica,sans-Serif" font-size="10.00">synonym &amp; rivalry overlay</text>
<text text-anchor="middle" x="842.5" y="-560.38" font-family="Helvetica,sans-Serif" font-size="10.00">(per&#45;shard concept_relations)</text>
</g>
<!-- concepts&#45;&gt;store -->
<g id="edge23" class="edge">
<g id="edge33" class="edge">
<title>concepts&#45;&gt;store</title>
<path fill="none" stroke="black" d="M887.73,-405.83C933.45,-412.47 990.84,-425.23 1037,-449.67 1063.92,-463.93 1088.72,-488.25 1105.69,-507.4"/>
<polygon fill="black" stroke="black" points="1103.05,-509.7 1112.24,-514.97 1108.35,-505.12 1103.05,-509.7"/>
<text text-anchor="middle" x="982" y="-462.47" font-family="Helvetica,sans-Serif" font-size="9.00">reads edges,</text>
<text text-anchor="middle" x="982" y="-452.47" font-family="Helvetica,sans-Serif" font-size="9.00">writes concept_relations</text>
<path fill="none" stroke="black" d="M922.61,-581.14C968.43,-587.9 1025.95,-600.91 1072,-625.88 1102.79,-642.58 1130.72,-671.55 1149.01,-693.31"/>
<polygon fill="black" stroke="black" points="1146.48,-695.74 1155.53,-701.25 1151.89,-691.3 1146.48,-695.74"/>
<text text-anchor="middle" x="1017" y="-638.68" font-family="Helvetica,sans-Serif" font-size="9.00">reads edges,</text>
<text text-anchor="middle" x="1017" y="-628.68" font-family="Helvetica,sans-Serif" font-size="9.00">writes concept_relations</text>
</g>
<!-- qa_query -->
<g id="node15" class="node">
<title>qa_query</title>
<path fill="#ffe6f0" stroke="black" d="M569.5,-302.67C569.5,-302.67 491.5,-302.67 491.5,-302.67 485.5,-302.67 479.5,-296.67 479.5,-290.67 479.5,-290.67 479.5,-278.67 479.5,-278.67 479.5,-272.67 485.5,-266.67 491.5,-266.67 491.5,-266.67 569.5,-266.67 569.5,-266.67 575.5,-266.67 581.5,-272.67 581.5,-278.67 581.5,-278.67 581.5,-290.67 581.5,-290.67 581.5,-296.67 575.5,-302.67 569.5,-302.67"/>
<text text-anchor="middle" x="530.5" y="-287.67" font-family="Helvetica,sans-Serif" font-size="10.00">qa/query.py</text>
<text text-anchor="middle" x="530.5" y="-276.67" font-family="Helvetica,sans-Serif" font-size="10.00">multi&#45;source RAG</text>
<path fill="#ffe6f0" stroke="black" d="M569.5,-391.88C569.5,-391.88 491.5,-391.88 491.5,-391.88 485.5,-391.88 479.5,-385.88 479.5,-379.88 479.5,-379.88 479.5,-367.88 479.5,-367.88 479.5,-361.88 485.5,-355.88 491.5,-355.88 491.5,-355.88 569.5,-355.88 569.5,-355.88 575.5,-355.88 581.5,-361.88 581.5,-367.88 581.5,-367.88 581.5,-379.88 581.5,-379.88 581.5,-385.88 575.5,-391.88 569.5,-391.88"/>
<text text-anchor="middle" x="530.5" y="-376.88" font-family="Helvetica,sans-Serif" font-size="10.00">qa/query.py</text>
<text text-anchor="middle" x="530.5" y="-365.88" font-family="Helvetica,sans-Serif" font-size="10.00">multi&#45;source RAG</text>
</g>
<!-- qa_query&#45;&gt;wikitext -->
<g id="edge18" class="edge">
<title>qa_query&#45;&gt;wikitext</title>
<path fill="none" stroke="black" d="M535.39,-266.28C542.84,-235.71 562.03,-174.56 602,-141.67 811.45,30.71 1005.11,54.79 1212,-120.67 1271.51,-171.14 1302.69,-419.93 1311.7,-504.49"/>
<polygon fill="black" stroke="black" points="1308.24,-505.05 1312.76,-514.63 1315.2,-504.32 1308.24,-505.05"/>
<text text-anchor="middle" x="982" y="-20.47" font-family="Helvetica,sans-Serif" font-size="9.00">to_base()</text>
<path fill="none" stroke="black" d="M533.91,-355.86C541.47,-302.1 566.29,-144.37 602,-108.88 751.2,39.42 871.92,12.11 1072,-52.88 1171.26,-85.12 1205.93,-102.86 1262,-190.88 1316.16,-275.91 1351.88,-593.14 1361.73,-690.37"/>
<polygon fill="black" stroke="black" points="1358.28,-691 1362.76,-700.61 1365.24,-690.31 1358.28,-691"/>
<text text-anchor="middle" x="1017" y="-55.68" font-family="Helvetica,sans-Serif" font-size="9.00">to_base()</text>
</g>
<!-- qa_query&#45;&gt;search -->
<g id="edge12" class="edge">
<title>qa_query&#45;&gt;search</title>
<path fill="none" stroke="black" d="M581.62,-274.28C625.53,-265.18 689.76,-251.87 738.34,-241.8"/>
<polygon fill="black" stroke="black" points="739.06,-245.22 748.14,-239.77 737.64,-238.37 739.06,-245.22"/>
<path fill="none" stroke="black" d="M545.34,-391.98C558.39,-407.93 579.29,-430.75 602,-444.88 654.6,-477.6 722.96,-496.21 773.17,-506.28"/>
<polygon fill="black" stroke="black" points="772.8,-509.77 783.28,-508.24 774.13,-502.9 772.8,-509.77"/>
</g>
<!-- qa_query&#45;&gt;concepts -->
<g id="edge13" class="edge">
<title>qa_query&#45;&gt;concepts</title>
<path fill="none" stroke="black" d="M562.57,-302.69C595.39,-321.16 649.07,-349.78 698,-368.67 704.31,-371.11 710.89,-373.43 717.57,-375.63"/>
<polygon fill="black" stroke="black" points="716.79,-379.06 727.38,-378.77 718.92,-372.39 716.79,-379.06"/>
<text text-anchor="middle" x="645" y="-376.47" font-family="Helvetica,sans-Serif" font-size="9.00">synonym_expand /</text>
<text text-anchor="middle" x="645" y="-366.47" font-family="Helvetica,sans-Serif" font-size="9.00">rivalry_excluded</text>
<path fill="none" stroke="black" d="M540.59,-391.89C552.34,-413.75 574.58,-450.68 602,-474.88 644.77,-512.63 703.93,-537.27 752.75,-552.53"/>
<polygon fill="black" stroke="black" points="751.78,-555.89 762.36,-555.46 753.82,-549.2 751.78,-555.89"/>
<text text-anchor="middle" x="662.5" y="-553.68" font-family="Helvetica,sans-Serif" font-size="9.00">synonym_expand /</text>
<text text-anchor="middle" x="662.5" y="-543.68" font-family="Helvetica,sans-Serif" font-size="9.00">rivalry_excluded</text>
</g>
<!-- qa_verify -->
<g id="node16" class="node">
<title>qa_verify</title>
<path fill="#ffe6f0" stroke="black" d="M880,-191.17C880,-191.17 735,-191.17 735,-191.17 729,-191.17 723,-185.17 723,-179.17 723,-179.17 723,-162.17 723,-162.17 723,-156.17 729,-150.17 735,-150.17 735,-150.17 880,-150.17 880,-150.17 886,-150.17 892,-156.17 892,-162.17 892,-162.17 892,-179.17 892,-179.17 892,-185.17 886,-191.17 880,-191.17"/>
<text text-anchor="middle" x="807.5" y="-179.17" font-family="Helvetica,sans-Serif" font-size="10.00">qa/verify.py</text>
<text text-anchor="middle" x="807.5" y="-168.17" font-family="Helvetica,sans-Serif" font-size="10.00">quote/span/entity/paraphrase</text>
<text text-anchor="middle" x="807.5" y="-157.17" font-family="Helvetica,sans-Serif" font-size="10.00">+ claim_lattice (7 hard checks)</text>
<path fill="#ffe6f0" stroke="black" d="M915,-480.38C915,-480.38 770,-480.38 770,-480.38 764,-480.38 758,-474.38 758,-468.38 758,-468.38 758,-451.38 758,-451.38 758,-445.38 764,-439.38 770,-439.38 770,-439.38 915,-439.38 915,-439.38 921,-439.38 927,-445.38 927,-451.38 927,-451.38 927,-468.38 927,-468.38 927,-474.38 921,-480.38 915,-480.38"/>
<text text-anchor="middle" x="842.5" y="-468.38" font-family="Helvetica,sans-Serif" font-size="10.00">qa/verify.py</text>
<text text-anchor="middle" x="842.5" y="-457.38" font-family="Helvetica,sans-Serif" font-size="10.00">quote/span/entity/paraphrase</text>
<text text-anchor="middle" x="842.5" y="-446.38" font-family="Helvetica,sans-Serif" font-size="10.00">+ claim_lattice (7 hard checks)</text>
</g>
<!-- qa_query&#45;&gt;qa_verify -->
<g id="edge15" class="edge">
<title>qa_query&#45;&gt;qa_verify</title>
<path fill="none" stroke="black" d="M562.57,-266.65C595.39,-248.18 649.07,-219.57 698,-200.67 703.74,-198.45 709.72,-196.33 715.77,-194.3"/>
<polygon fill="black" stroke="black" points="716.91,-197.62 725.34,-191.21 714.75,-190.96 716.91,-197.62"/>
<path fill="none" stroke="black" d="M550.9,-391.9C564.26,-403.24 582.96,-417.15 602,-424.88 647.88,-443.51 702.27,-452.4 747.61,-456.58"/>
<polygon fill="black" stroke="black" points="747.47,-460.08 757.73,-457.45 748.07,-453.11 747.47,-460.08"/>
</g>
<!-- qa_evidence -->
<g id="node18" class="node">
<title>qa_evidence</title>
<path fill="#ffe6f0" stroke="black" d="M1192,-165.67C1192,-165.67 1067,-165.67 1067,-165.67 1061,-165.67 1055,-159.67 1055,-153.67 1055,-153.67 1055,-141.67 1055,-141.67 1055,-135.67 1061,-129.67 1067,-129.67 1067,-129.67 1192,-129.67 1192,-129.67 1198,-129.67 1204,-135.67 1204,-141.67 1204,-141.67 1204,-153.67 1204,-153.67 1204,-159.67 1198,-165.67 1192,-165.67"/>
<text text-anchor="middle" x="1129.5" y="-150.67" font-family="Helvetica,sans-Serif" font-size="10.00">qa/evidence.py</text>
<text text-anchor="middle" x="1129.5" y="-139.67" font-family="Helvetica,sans-Serif" font-size="10.00">EvidenceObject + spotlight</text>
<path fill="#ffe6f0" stroke="black" d="M1234.5,-437.88C1234.5,-437.88 1109.5,-437.88 1109.5,-437.88 1103.5,-437.88 1097.5,-431.88 1097.5,-425.88 1097.5,-425.88 1097.5,-413.88 1097.5,-413.88 1097.5,-407.88 1103.5,-401.88 1109.5,-401.88 1109.5,-401.88 1234.5,-401.88 1234.5,-401.88 1240.5,-401.88 1246.5,-407.88 1246.5,-413.88 1246.5,-413.88 1246.5,-425.88 1246.5,-425.88 1246.5,-431.88 1240.5,-437.88 1234.5,-437.88"/>
<text text-anchor="middle" x="1172" y="-422.88" font-family="Helvetica,sans-Serif" font-size="10.00">qa/evidence.py</text>
<text text-anchor="middle" x="1172" y="-411.88" font-family="Helvetica,sans-Serif" font-size="10.00">EvidenceObject + spotlight</text>
</g>
<!-- qa_query&#45;&gt;qa_evidence -->
<g id="edge16" class="edge">
<title>qa_query&#45;&gt;qa_evidence</title>
<path fill="none" stroke="black" d="M543.93,-266.59C568.54,-232.79 627.25,-161.53 698,-140.67 814.5,-106.32 956.55,-118.4 1044.77,-131.8"/>
<polygon fill="black" stroke="black" points="1044.31,-135.27 1054.73,-133.36 1045.39,-128.36 1044.31,-135.27"/>
<path fill="none" stroke="black" d="M581.56,-378.23C588.43,-378.8 595.39,-379.37 602,-379.88 774.34,-393.27 976.19,-407 1087.19,-414.38"/>
<polygon fill="black" stroke="black" points="1087.11,-417.88 1097.32,-415.05 1087.57,-410.89 1087.11,-417.88"/>
</g>
<!-- qa_dag -->
<g id="node20" class="node">
<title>qa_dag</title>
<path fill="#ffe6f0" stroke="black" d="M852,-305.17C852,-305.17 763,-305.17 763,-305.17 757,-305.17 751,-299.17 751,-293.17 751,-293.17 751,-276.17 751,-276.17 751,-270.17 757,-264.17 763,-264.17 763,-264.17 852,-264.17 852,-264.17 858,-264.17 864,-270.17 864,-276.17 864,-276.17 864,-293.17 864,-293.17 864,-299.17 858,-305.17 852,-305.17"/>
<text text-anchor="middle" x="807.5" y="-293.17" font-family="Helvetica,sans-Serif" font-size="10.00">qa/dag.py</text>
<text text-anchor="middle" x="807.5" y="-282.17" font-family="Helvetica,sans-Serif" font-size="10.00">per&#45;run Merkle DAG</text>
<text text-anchor="middle" x="807.5" y="-271.17" font-family="Helvetica,sans-Serif" font-size="10.00">(7 / 9 stages)</text>
<path fill="#ffe6f0" stroke="black" d="M918,-354.88C918,-354.88 767,-354.88 767,-354.88 761,-354.88 755,-348.88 755,-342.88 755,-342.88 755,-314.88 755,-314.88 755,-308.88 761,-302.88 767,-302.88 767,-302.88 918,-302.88 918,-302.88 924,-302.88 930,-308.88 930,-314.88 930,-314.88 930,-342.88 930,-342.88 930,-348.88 924,-354.88 918,-354.88"/>
<text text-anchor="middle" x="842.5" y="-342.88" font-family="Helvetica,sans-Serif" font-size="10.00">qa/dag.py</text>
<text text-anchor="middle" x="842.5" y="-331.88" font-family="Helvetica,sans-Serif" font-size="10.00">per&#45;run Merkle DAG</text>
<text text-anchor="middle" x="842.5" y="-320.88" font-family="Helvetica,sans-Serif" font-size="10.00">(7/8 quote · 9/10 CTI · 3 reject)</text>
<text text-anchor="middle" x="842.5" y="-309.88" font-family="Helvetica,sans-Serif" font-size="10.00">preflight_node_hash + 5 clauses</text>
</g>
<!-- qa_query&#45;&gt;qa_dag -->
<g id="edge17" class="edge">
<title>qa_query&#45;&gt;qa_dag</title>
<path fill="none" stroke="black" d="M581.62,-284.67C626.17,-284.67 691.61,-284.67 740.42,-284.67"/>
<polygon fill="black" stroke="black" points="740.57,-288.17 750.57,-284.67 740.57,-281.17 740.57,-288.17"/>
<path fill="none" stroke="black" d="M581.65,-366.6C625.61,-360.22 690.75,-350.76 744.81,-342.92"/>
<polygon fill="black" stroke="black" points="745.38,-346.37 754.77,-341.47 744.37,-339.44 745.38,-346.37"/>
</g>
<!-- qa_keys -->
<g id="node21" class="node">
<title>qa_keys</title>
<path fill="#ffe6f0" stroke="black" d="M887.5,-359.67C887.5,-359.67 727.5,-359.67 727.5,-359.67 721.5,-359.67 715.5,-353.67 715.5,-347.67 715.5,-347.67 715.5,-335.67 715.5,-335.67 715.5,-329.67 721.5,-323.67 727.5,-323.67 727.5,-323.67 887.5,-323.67 887.5,-323.67 893.5,-323.67 899.5,-329.67 899.5,-335.67 899.5,-335.67 899.5,-347.67 899.5,-347.67 899.5,-353.67 893.5,-359.67 887.5,-359.67"/>
<text text-anchor="middle" x="807.5" y="-344.67" font-family="Helvetica,sans-Serif" font-size="10.00">qa/keys.py</text>
<text text-anchor="middle" x="807.5" y="-333.67" font-family="Helvetica,sans-Serif" font-size="10.00">8&#45;dim cache_key + question_hash</text>
<path fill="#ffe6f0" stroke="black" d="M922.5,-284.88C922.5,-284.88 762.5,-284.88 762.5,-284.88 756.5,-284.88 750.5,-278.88 750.5,-272.88 750.5,-272.88 750.5,-260.88 750.5,-260.88 750.5,-254.88 756.5,-248.88 762.5,-248.88 762.5,-248.88 922.5,-248.88 922.5,-248.88 928.5,-248.88 934.5,-254.88 934.5,-260.88 934.5,-260.88 934.5,-272.88 934.5,-272.88 934.5,-278.88 928.5,-284.88 922.5,-284.88"/>
<text text-anchor="middle" x="842.5" y="-269.88" font-family="Helvetica,sans-Serif" font-size="10.00">qa/keys.py</text>
<text text-anchor="middle" x="842.5" y="-258.88" font-family="Helvetica,sans-Serif" font-size="10.00">8&#45;dim cache_key + question_hash</text>
</g>
<!-- qa_query&#45;&gt;qa_keys -->
<g id="edge14" class="edge">
<title>qa_query&#45;&gt;qa_keys</title>
<path fill="none" stroke="black" d="M581.62,-295.06C617.26,-302.45 666.28,-312.61 709.46,-321.56"/>
<polygon fill="black" stroke="black" points="708.93,-325.02 719.44,-323.63 710.35,-318.17 708.93,-325.02"/>
<path fill="none" stroke="black" d="M573.14,-355.85C582.6,-351.84 592.62,-347.66 602,-343.88 659.79,-320.56 673.54,-312.55 733,-293.88 739.88,-291.72 747.04,-289.62 754.26,-287.61"/>
<polygon fill="black" stroke="black" points="755.4,-290.93 764.13,-284.92 753.56,-284.17 755.4,-290.93"/>
</g>
<!-- qa_quantifier -->
<g id="node23" class="node">
<title>qa_quantifier</title>
<path fill="#ffe6f0" stroke="black" d="M1233,-241.38C1233,-241.38 1111,-241.38 1111,-241.38 1105,-241.38 1099,-235.38 1099,-229.38 1099,-229.38 1099,-212.38 1099,-212.38 1099,-206.38 1105,-200.38 1111,-200.38 1111,-200.38 1233,-200.38 1233,-200.38 1239,-200.38 1245,-206.38 1245,-212.38 1245,-212.38 1245,-229.38 1245,-229.38 1245,-235.38 1239,-241.38 1233,-241.38"/>
<text text-anchor="middle" x="1172" y="-229.38" font-family="Helvetica,sans-Serif" font-size="10.00">qa/quantifier.py</text>
<text text-anchor="middle" x="1172" y="-218.38" font-family="Helvetica,sans-Serif" font-size="10.00">10&#45;rung intensity classifier</text>
<text text-anchor="middle" x="1172" y="-207.38" font-family="Helvetica,sans-Serif" font-size="10.00">(#000008)</text>
</g>
<!-- qa_query&#45;&gt;qa_quantifier -->
<g id="edge23" class="edge">
<title>qa_query&#45;&gt;qa_quantifier</title>
<path fill="none" stroke="black" d="M544.11,-355.81C557.07,-338.27 578.59,-311.73 602,-293.88 653.53,-254.59 670.02,-245.13 733,-229.88 854.18,-200.55 999.77,-205.09 1088.82,-212.15"/>
<polygon fill="black" stroke="black" points="1088.6,-215.65 1098.85,-212.98 1089.18,-208.67 1088.6,-215.65"/>
<text text-anchor="middle" x="842.5" y="-232.68" font-family="Helvetica,sans-Serif" font-size="9.00">classify_question_quantifier</text>
</g>
<!-- qa_model_profiles -->
<g id="node24" class="node">
<title>qa_model_profiles</title>
<path fill="#ffe6f0" stroke="black" d="M909,-125.38C909,-125.38 776,-125.38 776,-125.38 770,-125.38 764,-119.38 764,-113.38 764,-113.38 764,-96.38 764,-96.38 764,-90.38 770,-84.38 776,-84.38 776,-84.38 909,-84.38 909,-84.38 915,-84.38 921,-90.38 921,-96.38 921,-96.38 921,-113.38 921,-113.38 921,-119.38 915,-125.38 909,-125.38"/>
<text text-anchor="middle" x="842.5" y="-113.38" font-family="Helvetica,sans-Serif" font-size="10.00">qa/model_profiles.py</text>
<text text-anchor="middle" x="842.5" y="-102.38" font-family="Helvetica,sans-Serif" font-size="10.00">per&#45;model claim&#45;cap profiles</text>
<text text-anchor="middle" x="842.5" y="-91.38" font-family="Helvetica,sans-Serif" font-size="10.00">(#000008)</text>
</g>
<!-- qa_query&#45;&gt;qa_model_profiles -->
<g id="edge24" class="edge">
<title>qa_query&#45;&gt;qa_model_profiles</title>
<path fill="none" stroke="black" d="M532.11,-355.81C534.48,-315.49 546.03,-217.68 602,-165.88 642.73,-128.19 703.44,-113.01 753.54,-107.22"/>
<polygon fill="black" stroke="black" points="754.15,-110.68 763.74,-106.15 753.43,-103.71 754.15,-110.68"/>
<text text-anchor="middle" x="662.5" y="-168.68" font-family="Helvetica,sans-Serif" font-size="9.00">cap_for_intensity</text>
</g>
<!-- qa_quantifier_reminder -->
<g id="node25" class="node">
<title>qa_quantifier_reminder</title>
<path fill="#ffe6f0" stroke="black" d="M903.5,-184.38C903.5,-184.38 781.5,-184.38 781.5,-184.38 775.5,-184.38 769.5,-178.38 769.5,-172.38 769.5,-172.38 769.5,-155.38 769.5,-155.38 769.5,-149.38 775.5,-143.38 781.5,-143.38 781.5,-143.38 903.5,-143.38 903.5,-143.38 909.5,-143.38 915.5,-149.38 915.5,-155.38 915.5,-155.38 915.5,-172.38 915.5,-172.38 915.5,-178.38 909.5,-184.38 903.5,-184.38"/>
<text text-anchor="middle" x="842.5" y="-172.38" font-family="Helvetica,sans-Serif" font-size="10.00">qa/quantifier_reminder.py</text>
<text text-anchor="middle" x="842.5" y="-161.38" font-family="Helvetica,sans-Serif" font-size="10.00">broad&#45;query reminder text</text>
<text text-anchor="middle" x="842.5" y="-150.38" font-family="Helvetica,sans-Serif" font-size="10.00">(#000008)</text>
</g>
<!-- qa_query&#45;&gt;qa_quantifier_reminder -->
<g id="edge25" class="edge">
<title>qa_query&#45;&gt;qa_quantifier_reminder</title>
<path fill="none" stroke="black" d="M533.46,-355.83C538.28,-320.9 554.04,-244.16 602,-205.88 614.41,-195.98 694.95,-183.21 759.26,-174.36"/>
<polygon fill="black" stroke="black" points="759.99,-177.79 769.43,-172.98 759.05,-170.86 759.99,-177.79"/>
<text text-anchor="middle" x="662.5" y="-208.68" font-family="Helvetica,sans-Serif" font-size="9.00">broad_quantifier_reminder</text>
</g>
<!-- qa_metacognition -->
<g id="node26" class="node">
<title>qa_metacognition</title>
<path fill="#ffe6f0" stroke="black" d="M1242,-360.38C1242,-360.38 1102,-360.38 1102,-360.38 1096,-360.38 1090,-354.38 1090,-348.38 1090,-348.38 1090,-309.38 1090,-309.38 1090,-303.38 1096,-297.38 1102,-297.38 1102,-297.38 1242,-297.38 1242,-297.38 1248,-297.38 1254,-303.38 1254,-309.38 1254,-309.38 1254,-348.38 1254,-348.38 1254,-354.38 1248,-360.38 1242,-360.38"/>
<text text-anchor="middle" x="1172" y="-348.38" font-family="Helvetica,sans-Serif" font-size="10.00">qa/metacognition.py</text>
<text text-anchor="middle" x="1172" y="-337.38" font-family="Helvetica,sans-Serif" font-size="10.00">QuestionState + 4 detectors</text>
<text text-anchor="middle" x="1172" y="-326.38" font-family="Helvetica,sans-Serif" font-size="10.00">(temporal · contradiction ·</text>
<text text-anchor="middle" x="1172" y="-315.38" font-family="Helvetica,sans-Serif" font-size="10.00"> false&#45;premise · out&#45;of&#45;corpus)</text>
<text text-anchor="middle" x="1172" y="-304.38" font-family="Helvetica,sans-Serif" font-size="10.00">(#000010)</text>
</g>
<!-- qa_query&#45;&gt;qa_metacognition -->
<g id="edge26" class="edge">
<title>qa_query&#45;&gt;qa_metacognition</title>
<path fill="none" stroke="black" d="M581.78,-374.74C659.59,-375.61 813.78,-375.45 944,-363.88 988.95,-359.89 1038.52,-352.58 1079.84,-345.68"/>
<polygon fill="black" stroke="black" points="1080.61,-349.1 1089.88,-343.98 1079.44,-342.2 1080.61,-349.1"/>
<text text-anchor="middle" x="842.5" y="-377.68" font-family="Helvetica,sans-Serif" font-size="9.00">preflight_question</text>
</g>
<!-- qa_warrant -->
<g id="node17" class="node">
<title>qa_warrant</title>
<path fill="#ffe6f0" stroke="black" d="M1190.5,-235.67C1190.5,-235.67 1068.5,-235.67 1068.5,-235.67 1062.5,-235.67 1056.5,-229.67 1056.5,-223.67 1056.5,-223.67 1056.5,-195.67 1056.5,-195.67 1056.5,-189.67 1062.5,-183.67 1068.5,-183.67 1068.5,-183.67 1190.5,-183.67 1190.5,-183.67 1196.5,-183.67 1202.5,-189.67 1202.5,-195.67 1202.5,-195.67 1202.5,-223.67 1202.5,-223.67 1202.5,-229.67 1196.5,-235.67 1190.5,-235.67"/>
<text text-anchor="middle" x="1129.5" y="-223.67" font-family="Helvetica,sans-Serif" font-size="10.00">qa/warrant.py</text>
<text text-anchor="middle" x="1129.5" y="-212.67" font-family="Helvetica,sans-Serif" font-size="10.00">5 anchor classes</text>
<text text-anchor="middle" x="1129.5" y="-201.67" font-family="Helvetica,sans-Serif" font-size="10.00">(proper&#45;noun · date · count</text>
<text text-anchor="middle" x="1129.5" y="-190.67" font-family="Helvetica,sans-Serif" font-size="10.00"> · entity&#45;list · cause)</text>
<path fill="#ffe6f0" stroke="black" d="M1233,-507.88C1233,-507.88 1111,-507.88 1111,-507.88 1105,-507.88 1099,-501.88 1099,-495.88 1099,-495.88 1099,-467.88 1099,-467.88 1099,-461.88 1105,-455.88 1111,-455.88 1111,-455.88 1233,-455.88 1233,-455.88 1239,-455.88 1245,-461.88 1245,-467.88 1245,-467.88 1245,-495.88 1245,-495.88 1245,-501.88 1239,-507.88 1233,-507.88"/>
<text text-anchor="middle" x="1172" y="-495.88" font-family="Helvetica,sans-Serif" font-size="10.00">qa/warrant.py</text>
<text text-anchor="middle" x="1172" y="-484.88" font-family="Helvetica,sans-Serif" font-size="10.00">5 anchor classes</text>
<text text-anchor="middle" x="1172" y="-473.88" font-family="Helvetica,sans-Serif" font-size="10.00">(proper&#45;noun · date · count</text>
<text text-anchor="middle" x="1172" y="-462.88" font-family="Helvetica,sans-Serif" font-size="10.00"> · entity&#45;list · cause)</text>
</g>
<!-- qa_verify&#45;&gt;qa_warrant -->
<g id="edge19" class="edge">
<title>qa_verify&#45;&gt;qa_warrant</title>
<path fill="none" stroke="black" d="M892.16,-180.87C939.69,-186.66 998.96,-193.88 1046.25,-199.65"/>
<polygon fill="black" stroke="black" points="1046.11,-203.16 1056.46,-200.89 1046.96,-196.21 1046.11,-203.16"/>
<path fill="none" stroke="black" d="M927.41,-465.52C977.06,-468.85 1039.67,-473.06 1088.98,-476.37"/>
<polygon fill="black" stroke="black" points="1088.76,-479.86 1098.97,-477.04 1089.23,-472.88 1088.76,-479.86"/>
</g>
<!-- qa_verify&#45;&gt;qa_evidence -->
<g id="edge20" class="edge">
<title>qa_verify&#45;&gt;qa_evidence</title>
<path fill="none" stroke="black" d="M892.16,-164.66C939.17,-161.28 997.67,-157.08 1044.7,-153.7"/>
<polygon fill="black" stroke="black" points="1045.14,-157.17 1054.86,-152.96 1044.64,-150.19 1045.14,-157.17"/>
<path fill="none" stroke="black" d="M927.41,-449.63C976.53,-443.63 1038.33,-436.09 1087.39,-430.09"/>
<polygon fill="black" stroke="black" points="1087.84,-433.56 1097.34,-428.88 1086.99,-426.62 1087.84,-433.56"/>
</g>
<!-- qa_runner -->
<g id="node19" class="node">
<title>qa_runner</title>
<path fill="#ffe6f0" stroke="black" d="M326,-361.67C326,-361.67 228,-361.67 228,-361.67 222,-361.67 216,-355.67 216,-349.67 216,-349.67 216,-337.67 216,-337.67 216,-331.67 222,-325.67 228,-325.67 228,-325.67 326,-325.67 326,-325.67 332,-325.67 338,-331.67 338,-337.67 338,-337.67 338,-349.67 338,-349.67 338,-355.67 332,-361.67 326,-361.67"/>
<text text-anchor="middle" x="277" y="-346.67" font-family="Helvetica,sans-Serif" font-size="10.00">qa/runner.py</text>
<text text-anchor="middle" x="277" y="-335.67" font-family="Helvetica,sans-Serif" font-size="10.00">ask(): single&#45;doc Q&amp;A</text>
<path fill="#ffe6f0" stroke="black" d="M326,-144.88C326,-144.88 228,-144.88 228,-144.88 222,-144.88 216,-138.88 216,-132.88 216,-132.88 216,-120.88 216,-120.88 216,-114.88 222,-108.88 228,-108.88 228,-108.88 326,-108.88 326,-108.88 332,-108.88 338,-114.88 338,-120.88 338,-120.88 338,-132.88 338,-132.88 338,-138.88 332,-144.88 326,-144.88"/>
<text text-anchor="middle" x="277" y="-129.88" font-family="Helvetica,sans-Serif" font-size="10.00">qa/runner.py</text>
<text text-anchor="middle" x="277" y="-118.88" font-family="Helvetica,sans-Serif" font-size="10.00">ask(): single&#45;doc Q&amp;A</text>
</g>
<!-- qa_runner&#45;&gt;qa_query -->
<g id="edge21" class="edge">
<title>qa_runner&#45;&gt;qa_query</title>
<path fill="none" stroke="black" d="M338.24,-329.54C378.03,-320.21 429.96,-308.02 469.66,-298.71"/>
<polygon fill="black" stroke="black" points="470.54,-302.1 479.48,-296.41 468.94,-295.28 470.54,-302.1"/>
<path fill="none" stroke="black" d="M296.49,-145.04C340.73,-188.49 452.76,-298.51 503.64,-348.49"/>
<polygon fill="black" stroke="black" points="501.39,-351.18 510.98,-355.69 506.3,-346.19 501.39,-351.18"/>
</g>
<!-- qa_runner&#45;&gt;qa_quantifier -->
<g id="edge27" class="edge">
<title>qa_runner&#45;&gt;qa_quantifier</title>
<path fill="none" stroke="black" d="M297.67,-108.85C316.99,-92.45 348.13,-69.41 380,-59.88 620.16,11.94 705.16,16.22 944,-59.88 1026.22,-86.08 1104.2,-154.08 1143.84,-192.81"/>
<polygon fill="black" stroke="black" points="1141.68,-195.59 1151.25,-200.14 1146.6,-190.62 1141.68,-195.59"/>
</g>
<!-- qa_runner&#45;&gt;qa_model_profiles -->
<g id="edge28" class="edge">
<title>qa_runner&#45;&gt;qa_model_profiles</title>
<path fill="none" stroke="black" d="M338.04,-124.54C437.69,-120.65 637.7,-112.84 753.38,-108.32"/>
<polygon fill="black" stroke="black" points="753.76,-111.81 763.62,-107.92 753.49,-104.81 753.76,-111.81"/>
</g>
<!-- qa_runner&#45;&gt;qa_quantifier_reminder -->
<g id="edge29" class="edge">
<title>qa_runner&#45;&gt;qa_quantifier_reminder</title>
<path fill="none" stroke="black" d="M338.2,-126.1C442.01,-125.04 650.52,-124.27 723,-133.88 735.66,-135.56 748.91,-138.11 761.78,-141.02"/>
<polygon fill="black" stroke="black" points="760.99,-144.43 771.53,-143.31 762.6,-137.62 760.99,-144.43"/>
</g>
<!-- qa_runner&#45;&gt;qa_metacognition -->
<g id="edge30" class="edge">
<title>qa_runner&#45;&gt;qa_metacognition</title>
<path fill="none" stroke="black" d="M338.06,-113.87C481.74,-84.05 841,-17.59 944,-74.88 957.26,-82.26 952.97,-91.69 962,-103.88 1013.37,-173.22 1030.62,-187.26 1090,-249.88 1102.65,-263.23 1116.89,-277.38 1129.85,-289.96"/>
<polygon fill="black" stroke="black" points="1127.69,-292.74 1137.32,-297.17 1132.55,-287.7 1127.69,-292.74"/>
</g>
<!-- qa_dag&#45;&gt;qa_quantifier -->
<g id="edge31" class="edge">
<title>qa_dag&#45;&gt;qa_quantifier</title>
<path fill="none" stroke="black" stroke-dasharray="1,5" d="M922.36,-302.87C976.17,-285.13 1046.89,-261.81 1099.14,-244.58"/>
<polygon fill="black" stroke="black" points="1100.27,-247.89 1108.68,-241.43 1098.08,-241.24 1100.27,-247.89"/>
<text text-anchor="middle" x="1017" y="-290.68" font-family="Helvetica,sans-Serif" font-size="9.00">preflight clause</text>
</g>
<!-- qa_dag&#45;&gt;qa_metacognition -->
<g id="edge32" class="edge">
<title>qa_dag&#45;&gt;qa_metacognition</title>
<path fill="none" stroke="black" stroke-dasharray="1,5" d="M930.4,-328.88C976.48,-328.88 1033.06,-328.88 1079.77,-328.88"/>
<polygon fill="black" stroke="black" points="1079.89,-332.38 1089.89,-328.88 1079.89,-325.38 1079.89,-332.38"/>
<text text-anchor="middle" x="1017" y="-331.68" font-family="Helvetica,sans-Serif" font-size="9.00">preflight clause</text>
</g>
<!-- qa_inspect -->
<g id="node22" class="node">
<title>qa_inspect</title>
<path fill="#ffe6f0" stroke="black" d="M317.5,-305.17C317.5,-305.17 236.5,-305.17 236.5,-305.17 230.5,-305.17 224.5,-299.17 224.5,-293.17 224.5,-293.17 224.5,-276.17 224.5,-276.17 224.5,-270.17 230.5,-264.17 236.5,-264.17 236.5,-264.17 317.5,-264.17 317.5,-264.17 323.5,-264.17 329.5,-270.17 329.5,-276.17 329.5,-276.17 329.5,-293.17 329.5,-293.17 329.5,-299.17 323.5,-305.17 317.5,-305.17"/>
<text text-anchor="middle" x="277" y="-293.17" font-family="Helvetica,sans-Serif" font-size="10.00">qa/inspect.py</text>
<text text-anchor="middle" x="277" y="-282.17" font-family="Helvetica,sans-Serif" font-size="10.00">sidecar diagnostic</text>
<text text-anchor="middle" x="277" y="-271.17" font-family="Helvetica,sans-Serif" font-size="10.00">(read&#45;only)</text>
<path fill="#ffe6f0" stroke="black" d="M317.5,-438.38C317.5,-438.38 236.5,-438.38 236.5,-438.38 230.5,-438.38 224.5,-432.38 224.5,-426.38 224.5,-426.38 224.5,-409.38 224.5,-409.38 224.5,-403.38 230.5,-397.38 236.5,-397.38 236.5,-397.38 317.5,-397.38 317.5,-397.38 323.5,-397.38 329.5,-403.38 329.5,-409.38 329.5,-409.38 329.5,-426.38 329.5,-426.38 329.5,-432.38 323.5,-438.38 317.5,-438.38"/>
<text text-anchor="middle" x="277" y="-426.38" font-family="Helvetica,sans-Serif" font-size="10.00">qa/inspect.py</text>
<text text-anchor="middle" x="277" y="-415.38" font-family="Helvetica,sans-Serif" font-size="10.00">sidecar diagnostic</text>
<text text-anchor="middle" x="277" y="-404.38" font-family="Helvetica,sans-Serif" font-size="10.00">(read&#45;only)</text>
</g>
<!-- qa_inspect&#45;&gt;qa_query -->
<g id="edge22" class="edge">
<title>qa_inspect&#45;&gt;qa_query</title>
<path fill="none" stroke="black" stroke-dasharray="5,2" d="M329.5,-284.67C369.99,-284.67 426.49,-284.67 469.11,-284.67"/>
<polygon fill="black" stroke="black" points="469.35,-288.17 479.35,-284.67 469.35,-281.17 469.35,-288.17"/>
<text text-anchor="middle" x="419.5" y="-287.47" font-family="Helvetica,sans-Serif" font-size="9.00">read&#45;only sidecar</text>
<path fill="none" stroke="black" stroke-dasharray="5,2" d="M329.5,-408.87C370.08,-401.77 426.73,-391.86 469.38,-384.4"/>
<polygon fill="black" stroke="black" points="470.11,-387.82 479.35,-382.65 468.9,-380.93 470.11,-387.82"/>
<text text-anchor="middle" x="419.5" y="-402.68" font-family="Helvetica,sans-Serif" font-size="9.00">read&#45;only sidecar</text>
</g>
<!-- distill -->
<g id="node23" class="node">
<g id="node27" class="node">
<title>distill</title>
<path fill="#fff0e0" stroke="black" d="M892.5,-679.67C892.5,-679.67 722.5,-679.67 722.5,-679.67 716.5,-679.67 710.5,-673.67 710.5,-667.67 710.5,-667.67 710.5,-655.67 710.5,-655.67 710.5,-649.67 716.5,-643.67 722.5,-643.67 722.5,-643.67 892.5,-643.67 892.5,-643.67 898.5,-643.67 904.5,-649.67 904.5,-655.67 904.5,-655.67 904.5,-667.67 904.5,-667.67 904.5,-673.67 898.5,-679.67 892.5,-679.67"/>
<text text-anchor="middle" x="807.5" y="-664.67" font-family="Helvetica,sans-Serif" font-size="10.00">distill/</text>
<text text-anchor="middle" x="807.5" y="-653.67" font-family="Helvetica,sans-Serif" font-size="10.00">Distiller ABC + tfidf + first_sentence</text>
<path fill="#fff0e0" stroke="black" d="M927.5,-865.88C927.5,-865.88 757.5,-865.88 757.5,-865.88 751.5,-865.88 745.5,-859.88 745.5,-853.88 745.5,-853.88 745.5,-841.88 745.5,-841.88 745.5,-835.88 751.5,-829.88 757.5,-829.88 757.5,-829.88 927.5,-829.88 927.5,-829.88 933.5,-829.88 939.5,-835.88 939.5,-841.88 939.5,-841.88 939.5,-853.88 939.5,-853.88 939.5,-859.88 933.5,-865.88 927.5,-865.88"/>
<text text-anchor="middle" x="842.5" y="-850.88" font-family="Helvetica,sans-Serif" font-size="10.00">distill/</text>
<text text-anchor="middle" x="842.5" y="-839.88" font-family="Helvetica,sans-Serif" font-size="10.00">Distiller ABC + tfidf + first_sentence</text>
</g>
<!-- distill&#45;&gt;document -->
<g id="edge26" class="edge">
<g id="edge36" class="edge">
<title>distill&#45;&gt;document</title>
<path fill="none" stroke="black" d="M904.87,-667.65C987.77,-670.16 1109.79,-667.5 1212,-639.67 1235.36,-633.31 1259.51,-621.14 1278.5,-610.07"/>
<polygon fill="black" stroke="black" points="1280.32,-613.06 1287.1,-604.92 1276.73,-607.05 1280.32,-613.06"/>
<path fill="none" stroke="black" d="M939.63,-854.2C1025.64,-857.2 1154.39,-855.07 1262,-825.88 1285.53,-819.5 1309.86,-807.2 1328.91,-796.06"/>
<polygon fill="black" stroke="black" points="1330.76,-799.03 1337.53,-790.88 1327.16,-793.03 1330.76,-799.03"/>
</g>
<!-- distill&#45;&gt;store -->
<g id="edge25" class="edge">
<g id="edge35" class="edge">
<title>distill&#45;&gt;store</title>
<path fill="none" stroke="black" d="M896.52,-643.63C900.76,-642.38 904.94,-641.06 909,-639.67 971.41,-618.37 1039.47,-584.28 1083,-560.98"/>
<polygon fill="black" stroke="black" points="1084.76,-564.01 1091.91,-556.18 1081.44,-557.85 1084.76,-564.01"/>
<path fill="none" stroke="black" d="M931.23,-829.85C935.57,-828.59 939.85,-827.27 944,-825.88 1008.23,-804.41 1078.61,-770.41 1123.71,-747.17"/>
<polygon fill="black" stroke="black" points="1125.4,-750.24 1132.66,-742.53 1122.17,-744.03 1125.4,-750.24"/>
</g>
<!-- mesh -->
<g id="node24" class="node">
<g id="node28" class="node">
<title>mesh</title>
<path fill="#f0e6ff" stroke="black" d="M350,-500.17C350,-500.17 204,-500.17 204,-500.17 198,-500.17 192,-494.17 192,-488.17 192,-488.17 192,-471.17 192,-471.17 192,-465.17 198,-459.17 204,-459.17 204,-459.17 350,-459.17 350,-459.17 356,-459.17 362,-465.17 362,-471.17 362,-471.17 362,-488.17 362,-488.17 362,-494.17 356,-500.17 350,-500.17"/>
<text text-anchor="middle" x="277" y="-488.17" font-family="Helvetica,sans-Serif" font-size="10.00">mesh/</text>
<text text-anchor="middle" x="277" y="-477.17" font-family="Helvetica,sans-Serif" font-size="10.00">federation: identity, roster,</text>
<text text-anchor="middle" x="277" y="-466.17" font-family="Helvetica,sans-Serif" font-size="10.00">AEAD epoch secret, gossip wire</text>
<path fill="#f0e6ff" stroke="black" d="M350,-675.38C350,-675.38 204,-675.38 204,-675.38 198,-675.38 192,-669.38 192,-663.38 192,-663.38 192,-646.38 192,-646.38 192,-640.38 198,-634.38 204,-634.38 204,-634.38 350,-634.38 350,-634.38 356,-634.38 362,-640.38 362,-646.38 362,-646.38 362,-663.38 362,-663.38 362,-669.38 356,-675.38 350,-675.38"/>
<text text-anchor="middle" x="277" y="-663.38" font-family="Helvetica,sans-Serif" font-size="10.00">mesh/</text>
<text text-anchor="middle" x="277" y="-652.38" font-family="Helvetica,sans-Serif" font-size="10.00">federation: identity, roster,</text>
<text text-anchor="middle" x="277" y="-641.38" font-family="Helvetica,sans-Serif" font-size="10.00">AEAD epoch secret, gossip wire</text>
</g>
<!-- mesh&#45;&gt;store -->
<g id="edge28" class="edge">
<g id="edge38" class="edge">
<title>mesh&#45;&gt;store</title>
<path fill="none" stroke="black" d="M362.11,-480.61C483.22,-482.53 713.65,-488.34 909,-505.67 958.48,-510.06 1013.9,-517.66 1056.67,-524.11"/>
<polygon fill="black" stroke="black" points="1056.29,-527.59 1066.71,-525.63 1057.35,-520.67 1056.29,-527.59"/>
<path fill="none" stroke="black" d="M362.26,-657.51C488.79,-661.92 735.31,-672.32 944,-691.88 996.14,-696.77 1054.73,-704.57 1099.33,-710.99"/>
<polygon fill="black" stroke="black" points="1099.08,-714.49 1109.48,-712.47 1100.09,-707.57 1099.08,-714.49"/>
</g>
<!-- cli -->
<g id="node25" class="node">
<g id="node29" class="node">
<title>cli</title>
<polygon fill="#dddddd" stroke="black" points="149,-475.17 0,-475.17 0,-434.17 155,-434.17 155,-469.17 149,-475.17"/>
<polyline fill="none" stroke="black" points="149,-475.17 149,-469.17 "/>
<polyline fill="none" stroke="black" points="155,-469.17 149,-469.17 "/>
<text text-anchor="middle" x="77.5" y="-463.17" font-family="Helvetica,sans-Serif" font-size="10.00">cli.py</text>
<text text-anchor="middle" x="77.5" y="-452.17" font-family="Helvetica,sans-Serif" font-size="10.00">argparse entrypoint</text>
<text text-anchor="middle" x="77.5" y="-441.17" font-family="Helvetica,sans-Serif" font-size="10.00">(make targets call into here)</text>
<polygon fill="#dddddd" stroke="black" points="149,-644.38 0,-644.38 0,-603.38 155,-603.38 155,-638.38 149,-644.38"/>
<polyline fill="none" stroke="black" points="149,-644.38 149,-638.38 "/>
<polyline fill="none" stroke="black" points="155,-638.38 149,-638.38 "/>
<text text-anchor="middle" x="77.5" y="-632.38" font-family="Helvetica,sans-Serif" font-size="10.00">cli.py</text>
<text text-anchor="middle" x="77.5" y="-621.38" font-family="Helvetica,sans-Serif" font-size="10.00">argparse entrypoint</text>
<text text-anchor="middle" x="77.5" y="-610.38" font-family="Helvetica,sans-Serif" font-size="10.00">(make targets call into here)</text>
</g>
<!-- cli&#45;&gt;ingest -->
<g id="edge29" class="edge">
<g id="edge39" class="edge">
<title>cli&#45;&gt;ingest</title>
<path fill="none" stroke="black" d="M99.43,-475.28C120.75,-494.85 155.76,-523.23 192,-536.67 281.45,-569.86 544.33,-581.07 695.71,-584.82"/>
<polygon fill="black" stroke="black" points="695.88,-588.33 705.96,-585.07 696.05,-581.33 695.88,-588.33"/>
<path fill="none" stroke="black" d="M98.47,-644.63C119.59,-665.11 154.93,-695.39 192,-709.88 240.82,-728.96 558.48,-753.38 730.77,-765.44"/>
<polygon fill="black" stroke="black" points="730.67,-768.95 740.89,-766.15 731.16,-761.96 730.67,-768.95"/>
</g>
<!-- cli&#45;&gt;evict -->
<g id="edge34" class="edge">
<g id="edge44" class="edge">
<title>cli&#45;&gt;evict</title>
<path fill="none" stroke="black" d="M111.87,-475.4C133.77,-487.84 163.53,-502.57 192,-509.67 394.76,-560.22 646.69,-546.92 754.08,-537.85"/>
<polygon fill="black" stroke="black" points="754.65,-541.32 764.31,-536.96 754.05,-534.34 754.65,-541.32"/>
<path fill="none" stroke="black" d="M108.24,-644.61C130.28,-658.74 161.62,-676.38 192,-684.88 303.83,-716.16 655.22,-719.12 789.04,-719.08"/>
<polygon fill="black" stroke="black" points="789.43,-722.58 799.43,-719.07 789.42,-715.58 789.43,-722.58"/>
</g>
<!-- cli&#45;&gt;concepts -->
<g id="edge36" class="edge">
<g id="edge46" class="edge">
<title>cli&#45;&gt;concepts</title>
<path fill="none" stroke="black" d="M155.03,-448.79C290.77,-438.34 572.94,-416.64 717.27,-405.54"/>
<polygon fill="black" stroke="black" points="717.72,-409.01 727.42,-404.76 717.18,-402.03 717.72,-409.01"/>
<path fill="none" stroke="black" d="M155.15,-618.86C297.29,-609.54 600.97,-589.64 752.15,-579.74"/>
<polygon fill="black" stroke="black" points="752.58,-583.22 762.33,-579.07 752.12,-576.23 752.58,-583.22"/>
</g>
<!-- cli&#45;&gt;qa_query -->
<g id="edge31" class="edge">
<g id="edge41" class="edge">
<title>cli&#45;&gt;qa_query</title>
<path fill="none" stroke="black" d="M124.1,-434.15C139.44,-427.71 156.79,-420.91 173,-415.67 255.16,-389.12 281.01,-400.61 362,-370.67 407.96,-353.68 457.53,-327.1 490.72,-307.99"/>
<polygon fill="black" stroke="black" points="492.75,-310.86 499.63,-302.81 489.23,-304.81 492.75,-310.86"/>
<path fill="none" stroke="black" d="M114.3,-603.2C131.93,-593.07 153.53,-580.75 173,-569.88 299.42,-499.29 332.47,-484.28 459,-413.88 468.79,-408.43 479.31,-402.5 489.16,-396.92"/>
<polygon fill="black" stroke="black" points="491.01,-399.9 497.98,-391.91 487.55,-393.81 491.01,-399.9"/>
</g>
<!-- cli&#45;&gt;qa_runner -->
<g id="edge30" class="edge">
<g id="edge40" class="edge">
<title>cli&#45;&gt;qa_runner</title>
<path fill="none" stroke="black" d="M98.93,-433.84C117,-416.44 144.81,-392.07 173,-376.67 183.36,-371.01 194.85,-366.14 206.29,-362.01"/>
<polygon fill="black" stroke="black" points="207.54,-365.28 215.85,-358.72 205.26,-358.66 207.54,-365.28"/>
<path fill="none" stroke="black" d="M86.73,-603.16C118.02,-524.44 229.5,-243.9 265.03,-154.48"/>
<polygon fill="black" stroke="black" points="268.35,-155.6 268.79,-145.01 261.85,-153.01 268.35,-155.6"/>
</g>
<!-- cli&#45;&gt;qa_inspect -->
<g id="edge32" class="edge">
<g id="edge42" class="edge">
<title>cli&#45;&gt;qa_inspect</title>
<path fill="none" stroke="black" d="M90.58,-434.02C108.97,-404.25 146.66,-349.26 192,-316.67 198.92,-311.7 206.71,-307.39 214.69,-303.69"/>
<polygon fill="black" stroke="black" points="216.31,-306.8 224.1,-299.62 213.53,-300.38 216.31,-306.8"/>
<path fill="none" stroke="black" d="M89.07,-602.97C104.55,-573.79 135.65,-520.35 173,-483.88 188.87,-468.39 208.92,-454.55 227.12,-443.6"/>
<polygon fill="black" stroke="black" points="229.02,-446.55 235.87,-438.46 225.47,-440.51 229.02,-446.55"/>
</g>
<!-- cli&#45;&gt;distill -->
<g id="edge33" class="edge">
<g id="edge43" class="edge">
<title>cli&#45;&gt;distill</title>
<path fill="none" stroke="black" d="M80.72,-475.38C89.61,-553.75 125.34,-830.42 192,-881.67 332.93,-990.04 422.6,-935.59 592,-881.67 690.58,-850.3 762.9,-740.21 792.17,-688.67"/>
<polygon fill="black" stroke="black" points="795.32,-690.2 797.13,-679.76 789.21,-686.79 795.32,-690.2"/>
<path fill="none" stroke="black" d="M80.65,-644.6C89.3,-723.69 124.48,-1004.78 192,-1056.88 380.37,-1202.23 537.3,-1137.62 723,-988.88 764.8,-955.4 802.62,-905.39 823.78,-874.79"/>
<polygon fill="black" stroke="black" points="826.81,-876.57 829.55,-866.34 821.02,-872.63 826.81,-876.57"/>
</g>
<!-- cli&#45;&gt;mesh -->
<g id="edge35" class="edge">
<g id="edge45" class="edge">
<title>cli&#45;&gt;mesh</title>
<path fill="none" stroke="black" d="M155.14,-464.37C163.89,-465.48 172.87,-466.62 181.81,-467.75"/>
<polygon fill="black" stroke="black" points="181.51,-471.24 191.87,-469.02 182.39,-464.29 181.51,-471.24"/>
<path fill="none" stroke="black" d="M155.14,-635.91C163.89,-637.28 172.87,-638.69 181.81,-640.1"/>
<polygon fill="black" stroke="black" points="181.45,-643.58 191.87,-641.68 182.53,-636.67 181.45,-643.58"/>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 34 KiB

After

Width:  |  Height:  |  Size: 43 KiB

Before After
Before After

View file

@ -17,6 +17,10 @@ digraph query_pipeline {
cache_check [label="cache lookup\nproperence_cache by 8-dim cache_key\n• equivalence_class fallback\n• ~0.3ms warm", fillcolor="#e6f0ff"]
cache_hit [label="CACHE HIT\nreplay answer + Merkle proof\n~100ms total", fillcolor="#d4edda", shape=note]
// Preflight (Tickets #000008 + #000010 — Merkle-bound via #000009)
preflight [label="PREFLIGHT (#000008 + #000010)\nclassifier (10-rung quantifier)\n+ metacognition QuestionState\n• temporal · contradiction\n• false-premise · out-of-corpus\n• broad-quantifier scope hint\n→ 5-clause CTI contract\n→ run-DAG `preflight` stage", fillcolor="#fff0e0"]
preflight_reject [label="REJECT-BROAD\n3-stage minimal DAG\nquestion → preflight → final_label\nno LLM call (~0ms)", fillcolor="#ffd4d4", shape=note]
// Retrieval
fts5 [label="FTS5 BM25 search\n• AND-mode first (strict)\n• OR-mode fallback (top-5 longest +\n synonym pool)\n• ~0.25s/shard", fillcolor="#ffe6f0"]
title_like [label="title-LIKE backup\n(skipped if >5 tokens)\n• ~0.5s/shard for short queries", fillcolor="#ffe6f0"]
@ -41,7 +45,7 @@ digraph query_pipeline {
warrant [label="warrant_check (5 anchor classes)\n• proper-noun (relation-gated)\n• date (year + month)\n• count (digit↔word)\n• entity-list\n• cause (why-shape)", fillcolor="#e7ffe7"]
// Render
render [label="render\n• spotlight excerpt (density rank)\n• [E5 | Title | chunk_prefix: \"...\"]\n• four-rung label ladder", fillcolor="#fff7e6"]
render [label="render\n• spotlight excerpt (density rank)\n• [E5 | Title | chunk_prefix: \"...\"]\n• four-rung label ladder\n• audit-line tails:\n · false premise · contradictory\n · stale risk · out of corpus\n · frame ambiguous\n · broad cap N · broad rejected", fillcolor="#fff7e6"]
// Persistence
cache_write [label="providence_cache write\n• 8-dim cache_key\n• run_dag_root + run_dag_blob\n• audit_event chained\n• context_root committed", fillcolor="#e6f0ff"]
@ -51,7 +55,9 @@ digraph query_pipeline {
// Edges
question -> cache_check
cache_check -> cache_hit [label="match"]
cache_check -> concepts_lookup [label="miss"]
cache_check -> preflight [label="miss"]
preflight -> preflight_reject [label="reject-broad\n(opt-in)", style=dashed, color="#cc4444"]
preflight -> concepts_lookup [label="continue"]
concepts_lookup -> fts5
concepts_lookup -> title_like
concepts_lookup -> phrase_route

View file

@ -4,287 +4,331 @@
<!-- Generated by graphviz version 2.43.0 (0)
-->
<!-- Title: query_pipeline Pages: 1 -->
<svg width="571pt" height="1347pt"
viewBox="0.00 0.00 571.00 1347.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 1343)">
<svg width="675pt" height="1554pt"
viewBox="0.00 0.00 675.00 1554.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 1550)">
<title>query_pipeline</title>
<polygon fill="white" stroke="transparent" points="-4,4 -4,-1343 567,-1343 567,4 -4,4"/>
<polygon fill="white" stroke="transparent" points="-4,4 -4,-1550 671,-1550 671,4 -4,4"/>
<!-- question -->
<g id="node1" class="node">
<title>question</title>
<polygon fill="#fff7e6" stroke="black" points="205,-1339 57,-1339 57,-1298 211,-1298 211,-1333 205,-1339"/>
<polyline fill="none" stroke="black" points="205,-1339 205,-1333 "/>
<polyline fill="none" stroke="black" points="211,-1333 205,-1333 "/>
<text text-anchor="middle" x="134" y="-1327" font-family="Helvetica,sans-Serif" font-size="10.00">QUESTION</text>
<text text-anchor="middle" x="134" y="-1316" font-family="Helvetica,sans-Serif" font-size="10.00">&quot;what tech can reconstruct</text>
<text text-anchor="middle" x="134" y="-1305" font-family="Helvetica,sans-Serif" font-size="10.00">another person&#39;s thoughts?&quot;</text>
<polygon fill="#fff7e6" stroke="black" points="178,-1546 30,-1546 30,-1505 184,-1505 184,-1540 178,-1546"/>
<polyline fill="none" stroke="black" points="178,-1546 178,-1540 "/>
<polyline fill="none" stroke="black" points="184,-1540 178,-1540 "/>
<text text-anchor="middle" x="107" y="-1534" font-family="Helvetica,sans-Serif" font-size="10.00">QUESTION</text>
<text text-anchor="middle" x="107" y="-1523" font-family="Helvetica,sans-Serif" font-size="10.00">&quot;what tech can reconstruct</text>
<text text-anchor="middle" x="107" y="-1512" font-family="Helvetica,sans-Serif" font-size="10.00">another person&#39;s thoughts?&quot;</text>
</g>
<!-- cache_check -->
<g id="node2" class="node">
<title>cache_check</title>
<path fill="#e6f0ff" stroke="black" d="M225,-1261C225,-1261 43,-1261 43,-1261 37,-1261 31,-1255 31,-1249 31,-1249 31,-1221 31,-1221 31,-1215 37,-1209 43,-1209 43,-1209 225,-1209 225,-1209 231,-1209 237,-1215 237,-1221 237,-1221 237,-1249 237,-1249 237,-1255 231,-1261 225,-1261"/>
<text text-anchor="middle" x="134" y="-1249" font-family="Helvetica,sans-Serif" font-size="10.00">cache lookup</text>
<text text-anchor="middle" x="134" y="-1238" font-family="Helvetica,sans-Serif" font-size="10.00">properence_cache by 8&#45;dim cache_key</text>
<text text-anchor="middle" x="134" y="-1227" font-family="Helvetica,sans-Serif" font-size="10.00">• equivalence_class fallback</text>
<text text-anchor="middle" x="134" y="-1216" font-family="Helvetica,sans-Serif" font-size="10.00">• ~0.3ms warm</text>
<path fill="#e6f0ff" stroke="black" d="M198,-1468C198,-1468 16,-1468 16,-1468 10,-1468 4,-1462 4,-1456 4,-1456 4,-1428 4,-1428 4,-1422 10,-1416 16,-1416 16,-1416 198,-1416 198,-1416 204,-1416 210,-1422 210,-1428 210,-1428 210,-1456 210,-1456 210,-1462 204,-1468 198,-1468"/>
<text text-anchor="middle" x="107" y="-1456" font-family="Helvetica,sans-Serif" font-size="10.00">cache lookup</text>
<text text-anchor="middle" x="107" y="-1445" font-family="Helvetica,sans-Serif" font-size="10.00">properence_cache by 8&#45;dim cache_key</text>
<text text-anchor="middle" x="107" y="-1434" font-family="Helvetica,sans-Serif" font-size="10.00">• equivalence_class fallback</text>
<text text-anchor="middle" x="107" y="-1423" font-family="Helvetica,sans-Serif" font-size="10.00">• ~0.3ms warm</text>
</g>
<!-- question&#45;&gt;cache_check -->
<g id="edge1" class="edge">
<title>question&#45;&gt;cache_check</title>
<path fill="none" stroke="black" d="M134,-1297.77C134,-1289.76 134,-1280.26 134,-1271.14"/>
<polygon fill="black" stroke="black" points="137.5,-1271.11 134,-1261.11 130.5,-1271.11 137.5,-1271.11"/>
<path fill="none" stroke="black" d="M107,-1504.77C107,-1496.76 107,-1487.26 107,-1478.14"/>
<polygon fill="black" stroke="black" points="110.5,-1478.11 107,-1468.11 103.5,-1478.11 110.5,-1478.11"/>
</g>
<!-- cache_hit -->
<g id="node3" class="node">
<title>cache_hit</title>
<polygon fill="#d4edda" stroke="black" points="183,-1157.5 27,-1157.5 27,-1116.5 189,-1116.5 189,-1151.5 183,-1157.5"/>
<polyline fill="none" stroke="black" points="183,-1157.5 183,-1151.5 "/>
<polyline fill="none" stroke="black" points="189,-1151.5 183,-1151.5 "/>
<text text-anchor="middle" x="108" y="-1145.5" font-family="Helvetica,sans-Serif" font-size="10.00">CACHE HIT</text>
<text text-anchor="middle" x="108" y="-1134.5" font-family="Helvetica,sans-Serif" font-size="10.00">replay answer + Merkle proof</text>
<text text-anchor="middle" x="108" y="-1123.5" font-family="Helvetica,sans-Serif" font-size="10.00">~100ms total</text>
<polygon fill="#d4edda" stroke="black" points="156,-1342.5 0,-1342.5 0,-1301.5 162,-1301.5 162,-1336.5 156,-1342.5"/>
<polyline fill="none" stroke="black" points="156,-1342.5 156,-1336.5 "/>
<polyline fill="none" stroke="black" points="162,-1336.5 156,-1336.5 "/>
<text text-anchor="middle" x="81" y="-1330.5" font-family="Helvetica,sans-Serif" font-size="10.00">CACHE HIT</text>
<text text-anchor="middle" x="81" y="-1319.5" font-family="Helvetica,sans-Serif" font-size="10.00">replay answer + Merkle proof</text>
<text text-anchor="middle" x="81" y="-1308.5" font-family="Helvetica,sans-Serif" font-size="10.00">~100ms total</text>
</g>
<!-- cache_check&#45;&gt;cache_hit -->
<g id="edge2" class="edge">
<title>cache_check&#45;&gt;cache_hit</title>
<path fill="none" stroke="black" d="M127.17,-1208.78C123.75,-1196.15 119.59,-1180.79 116.02,-1167.61"/>
<polygon fill="black" stroke="black" points="119.3,-1166.34 113.31,-1157.6 112.54,-1168.17 119.3,-1166.34"/>
<text text-anchor="middle" x="137" y="-1183.8" font-family="Helvetica,sans-Serif" font-size="9.00">match</text>
<path fill="none" stroke="black" d="M101.49,-1415.98C97.39,-1397.4 91.8,-1372 87.49,-1352.44"/>
<polygon fill="black" stroke="black" points="90.87,-1351.55 85.3,-1342.53 84.04,-1353.05 90.87,-1351.55"/>
<text text-anchor="middle" x="113" y="-1390.8" font-family="Helvetica,sans-Serif" font-size="9.00">match</text>
</g>
<!-- preflight -->
<g id="node4" class="node">
<title>preflight</title>
<path fill="#fff0e0" stroke="black" d="M352,-1370C352,-1370 192,-1370 192,-1370 186,-1370 180,-1364 180,-1358 180,-1358 180,-1286 180,-1286 180,-1280 186,-1274 192,-1274 192,-1274 352,-1274 352,-1274 358,-1274 364,-1280 364,-1286 364,-1286 364,-1358 364,-1358 364,-1364 358,-1370 352,-1370"/>
<text text-anchor="middle" x="272" y="-1358" font-family="Helvetica,sans-Serif" font-size="10.00">PREFLIGHT (#000008 + #000010)</text>
<text text-anchor="middle" x="272" y="-1347" font-family="Helvetica,sans-Serif" font-size="10.00">classifier (10&#45;rung quantifier)</text>
<text text-anchor="middle" x="272" y="-1336" font-family="Helvetica,sans-Serif" font-size="10.00">+ metacognition QuestionState</text>
<text text-anchor="middle" x="272" y="-1325" font-family="Helvetica,sans-Serif" font-size="10.00">• temporal · contradiction</text>
<text text-anchor="middle" x="272" y="-1314" font-family="Helvetica,sans-Serif" font-size="10.00">• false&#45;premise · out&#45;of&#45;corpus</text>
<text text-anchor="middle" x="272" y="-1303" font-family="Helvetica,sans-Serif" font-size="10.00">• broad&#45;quantifier scope hint</text>
<text text-anchor="middle" x="272" y="-1292" font-family="Helvetica,sans-Serif" font-size="10.00">→ 5&#45;clause CTI contract</text>
<text text-anchor="middle" x="272" y="-1281" font-family="Helvetica,sans-Serif" font-size="10.00">→ run&#45;DAG `preflight` stage</text>
</g>
<!-- cache_check&#45;&gt;preflight -->
<g id="edge3" class="edge">
<title>cache_check&#45;&gt;preflight</title>
<path fill="none" stroke="black" d="M141.99,-1415.98C158.3,-1404.31 178.36,-1389.97 197.8,-1376.06"/>
<polygon fill="black" stroke="black" points="199.99,-1378.8 206.08,-1370.14 195.91,-1373.11 199.99,-1378.8"/>
<text text-anchor="middle" x="190.5" y="-1390.8" font-family="Helvetica,sans-Serif" font-size="9.00">miss</text>
</g>
<!-- preflight_reject -->
<g id="node5" class="node">
<title>preflight_reject</title>
<polygon fill="#ffd4d4" stroke="black" points="287,-1218 115,-1218 115,-1166 293,-1166 293,-1212 287,-1218"/>
<polyline fill="none" stroke="black" points="287,-1218 287,-1212 "/>
<polyline fill="none" stroke="black" points="293,-1212 287,-1212 "/>
<text text-anchor="middle" x="204" y="-1206" font-family="Helvetica,sans-Serif" font-size="10.00">REJECT&#45;BROAD</text>
<text text-anchor="middle" x="204" y="-1195" font-family="Helvetica,sans-Serif" font-size="10.00">3&#45;stage minimal DAG</text>
<text text-anchor="middle" x="204" y="-1184" font-family="Helvetica,sans-Serif" font-size="10.00">question → preflight → final_label</text>
<text text-anchor="middle" x="204" y="-1173" font-family="Helvetica,sans-Serif" font-size="10.00">no LLM call (~0ms)</text>
</g>
<!-- preflight&#45;&gt;preflight_reject -->
<g id="edge4" class="edge">
<title>preflight&#45;&gt;preflight_reject</title>
<path fill="none" stroke="#cc4444" stroke-dasharray="5,2" d="M246.87,-1273.7C238.68,-1258.28 229.75,-1241.46 222.17,-1227.2"/>
<polygon fill="#cc4444" stroke="#cc4444" points="225.18,-1225.42 217.4,-1218.23 219,-1228.7 225.18,-1225.42"/>
<text text-anchor="middle" x="263.5" y="-1248.8" font-family="Helvetica,sans-Serif" font-size="9.00">reject&#45;broad</text>
<text text-anchor="middle" x="263.5" y="-1238.8" font-family="Helvetica,sans-Serif" font-size="9.00">(opt&#45;in)</text>
</g>
<!-- concepts_lookup -->
<g id="node7" class="node">
<g id="node9" class="node">
<title>concepts_lookup</title>
<path fill="#ffe6f0" stroke="black" d="M375,-1163C375,-1163 219,-1163 219,-1163 213,-1163 207,-1157 207,-1151 207,-1151 207,-1123 207,-1123 207,-1117 213,-1111 219,-1111 219,-1111 375,-1111 375,-1111 381,-1111 387,-1117 387,-1123 387,-1123 387,-1151 387,-1151 387,-1157 381,-1163 375,-1163"/>
<text text-anchor="middle" x="297" y="-1151" font-family="Helvetica,sans-Serif" font-size="10.00">concepts/ overlay</text>
<text text-anchor="middle" x="297" y="-1140" font-family="Helvetica,sans-Serif" font-size="10.00">• synonym_expand(qtokens)</text>
<text text-anchor="middle" x="297" y="-1129" font-family="Helvetica,sans-Serif" font-size="10.00">• rivalry_excluded()</text>
<text text-anchor="middle" x="297" y="-1118" font-family="Helvetica,sans-Serif" font-size="10.00">• per&#45;process cache, ~1ms warm</text>
<path fill="#ffe6f0" stroke="black" d="M479,-1218C479,-1218 323,-1218 323,-1218 317,-1218 311,-1212 311,-1206 311,-1206 311,-1178 311,-1178 311,-1172 317,-1166 323,-1166 323,-1166 479,-1166 479,-1166 485,-1166 491,-1172 491,-1178 491,-1178 491,-1206 491,-1206 491,-1212 485,-1218 479,-1218"/>
<text text-anchor="middle" x="401" y="-1206" font-family="Helvetica,sans-Serif" font-size="10.00">concepts/ overlay</text>
<text text-anchor="middle" x="401" y="-1195" font-family="Helvetica,sans-Serif" font-size="10.00">• synonym_expand(qtokens)</text>
<text text-anchor="middle" x="401" y="-1184" font-family="Helvetica,sans-Serif" font-size="10.00">• rivalry_excluded()</text>
<text text-anchor="middle" x="401" y="-1173" font-family="Helvetica,sans-Serif" font-size="10.00">• per&#45;process cache, ~1ms warm</text>
</g>
<!-- cache_check&#45;&gt;concepts_lookup -->
<g id="edge3" class="edge">
<title>cache_check&#45;&gt;concepts_lookup</title>
<path fill="none" stroke="black" d="M176.83,-1208.78C197.98,-1196.32 223.65,-1181.2 245.83,-1168.14"/>
<polygon fill="black" stroke="black" points="247.62,-1171.15 254.46,-1163.05 244.07,-1165.11 247.62,-1171.15"/>
<text text-anchor="middle" x="231.5" y="-1183.8" font-family="Helvetica,sans-Serif" font-size="9.00">miss</text>
<!-- preflight&#45;&gt;concepts_lookup -->
<g id="edge5" class="edge">
<title>preflight&#45;&gt;concepts_lookup</title>
<path fill="none" stroke="black" d="M319.67,-1273.7C335.8,-1257.69 353.45,-1240.18 368.17,-1225.58"/>
<polygon fill="black" stroke="black" points="370.94,-1227.75 375.58,-1218.23 366.01,-1222.79 370.94,-1227.75"/>
<text text-anchor="middle" x="376" y="-1243.8" font-family="Helvetica,sans-Serif" font-size="9.00">continue</text>
</g>
<!-- fts5 -->
<g id="node4" class="node">
<g id="node6" class="node">
<title>fts5</title>
<path fill="#ffe6f0" stroke="black" d="M184,-1074C184,-1074 12,-1074 12,-1074 6,-1074 0,-1068 0,-1062 0,-1062 0,-1023 0,-1023 0,-1017 6,-1011 12,-1011 12,-1011 184,-1011 184,-1011 190,-1011 196,-1017 196,-1023 196,-1023 196,-1062 196,-1062 196,-1068 190,-1074 184,-1074"/>
<text text-anchor="middle" x="98" y="-1062" font-family="Helvetica,sans-Serif" font-size="10.00">FTS5 BM25 search</text>
<text text-anchor="middle" x="98" y="-1051" font-family="Helvetica,sans-Serif" font-size="10.00">• AND&#45;mode first (strict)</text>
<text text-anchor="middle" x="98" y="-1040" font-family="Helvetica,sans-Serif" font-size="10.00">• OR&#45;mode fallback (top&#45;5 longest +</text>
<text text-anchor="middle" x="98" y="-1029" font-family="Helvetica,sans-Serif" font-size="10.00"> &#160;synonym pool)</text>
<text text-anchor="middle" x="98" y="-1018" font-family="Helvetica,sans-Serif" font-size="10.00">• ~0.25s/shard</text>
<path fill="#ffe6f0" stroke="black" d="M288,-1129C288,-1129 116,-1129 116,-1129 110,-1129 104,-1123 104,-1117 104,-1117 104,-1078 104,-1078 104,-1072 110,-1066 116,-1066 116,-1066 288,-1066 288,-1066 294,-1066 300,-1072 300,-1078 300,-1078 300,-1117 300,-1117 300,-1123 294,-1129 288,-1129"/>
<text text-anchor="middle" x="202" y="-1117" font-family="Helvetica,sans-Serif" font-size="10.00">FTS5 BM25 search</text>
<text text-anchor="middle" x="202" y="-1106" font-family="Helvetica,sans-Serif" font-size="10.00">• AND&#45;mode first (strict)</text>
<text text-anchor="middle" x="202" y="-1095" font-family="Helvetica,sans-Serif" font-size="10.00">• OR&#45;mode fallback (top&#45;5 longest +</text>
<text text-anchor="middle" x="202" y="-1084" font-family="Helvetica,sans-Serif" font-size="10.00"> &#160;synonym pool)</text>
<text text-anchor="middle" x="202" y="-1073" font-family="Helvetica,sans-Serif" font-size="10.00">• ~0.25s/shard</text>
</g>
<!-- filter -->
<g id="node8" class="node">
<g id="node10" class="node">
<title>filter</title>
<path fill="#ffe6f0" stroke="black" d="M344.5,-974C344.5,-974 249.5,-974 249.5,-974 243.5,-974 237.5,-968 237.5,-962 237.5,-962 237.5,-912 237.5,-912 237.5,-906 243.5,-900 249.5,-900 249.5,-900 344.5,-900 344.5,-900 350.5,-900 356.5,-906 356.5,-912 356.5,-912 356.5,-962 356.5,-962 356.5,-968 350.5,-974 344.5,-974"/>
<text text-anchor="middle" x="297" y="-962" font-family="Helvetica,sans-Serif" font-size="10.00">title&#45;relevance filter</text>
<text text-anchor="middle" x="297" y="-951" font-family="Helvetica,sans-Serif" font-size="10.00">4 accept paths:</text>
<text text-anchor="middle" x="297" y="-940" font-family="Helvetica,sans-Serif" font-size="10.00">1. title&#45;token overlap</text>
<text text-anchor="middle" x="297" y="-929" font-family="Helvetica,sans-Serif" font-size="10.00">2. TF&#45;IDF core match</text>
<text text-anchor="middle" x="297" y="-918" font-family="Helvetica,sans-Serif" font-size="10.00">3. body density</text>
<text text-anchor="middle" x="297" y="-907" font-family="Helvetica,sans-Serif" font-size="10.00">4. phrase match</text>
<path fill="#ffe6f0" stroke="black" d="M448.5,-1029C448.5,-1029 353.5,-1029 353.5,-1029 347.5,-1029 341.5,-1023 341.5,-1017 341.5,-1017 341.5,-967 341.5,-967 341.5,-961 347.5,-955 353.5,-955 353.5,-955 448.5,-955 448.5,-955 454.5,-955 460.5,-961 460.5,-967 460.5,-967 460.5,-1017 460.5,-1017 460.5,-1023 454.5,-1029 448.5,-1029"/>
<text text-anchor="middle" x="401" y="-1017" font-family="Helvetica,sans-Serif" font-size="10.00">title&#45;relevance filter</text>
<text text-anchor="middle" x="401" y="-1006" font-family="Helvetica,sans-Serif" font-size="10.00">4 accept paths:</text>
<text text-anchor="middle" x="401" y="-995" font-family="Helvetica,sans-Serif" font-size="10.00">1. title&#45;token overlap</text>
<text text-anchor="middle" x="401" y="-984" font-family="Helvetica,sans-Serif" font-size="10.00">2. TF&#45;IDF core match</text>
<text text-anchor="middle" x="401" y="-973" font-family="Helvetica,sans-Serif" font-size="10.00">3. body density</text>
<text text-anchor="middle" x="401" y="-962" font-family="Helvetica,sans-Serif" font-size="10.00">4. phrase match</text>
</g>
<!-- fts5&#45;&gt;filter -->
<g id="edge7" class="edge">
<g id="edge9" class="edge">
<title>fts5&#45;&gt;filter</title>
<path fill="none" stroke="black" d="M156.9,-1010.87C179.26,-999.24 204.92,-985.89 228.12,-973.82"/>
<polygon fill="black" stroke="black" points="229.96,-976.81 237.22,-969.09 226.73,-970.6 229.96,-976.81"/>
<path fill="none" stroke="black" d="M260.9,-1065.87C283.26,-1054.24 308.92,-1040.89 332.12,-1028.82"/>
<polygon fill="black" stroke="black" points="333.96,-1031.81 341.22,-1024.09 330.73,-1025.6 333.96,-1031.81"/>
</g>
<!-- title_like -->
<g id="node5" class="node">
<g id="node7" class="node">
<title>title_like</title>
<path fill="#ffe6f0" stroke="black" d="M368.5,-1063C368.5,-1063 225.5,-1063 225.5,-1063 219.5,-1063 213.5,-1057 213.5,-1051 213.5,-1051 213.5,-1034 213.5,-1034 213.5,-1028 219.5,-1022 225.5,-1022 225.5,-1022 368.5,-1022 368.5,-1022 374.5,-1022 380.5,-1028 380.5,-1034 380.5,-1034 380.5,-1051 380.5,-1051 380.5,-1057 374.5,-1063 368.5,-1063"/>
<text text-anchor="middle" x="297" y="-1051" font-family="Helvetica,sans-Serif" font-size="10.00">title&#45;LIKE backup</text>
<text text-anchor="middle" x="297" y="-1040" font-family="Helvetica,sans-Serif" font-size="10.00">(skipped if &gt;5 tokens)</text>
<text text-anchor="middle" x="297" y="-1029" font-family="Helvetica,sans-Serif" font-size="10.00">• ~0.5s/shard for short queries</text>
<path fill="#ffe6f0" stroke="black" d="M472.5,-1118C472.5,-1118 329.5,-1118 329.5,-1118 323.5,-1118 317.5,-1112 317.5,-1106 317.5,-1106 317.5,-1089 317.5,-1089 317.5,-1083 323.5,-1077 329.5,-1077 329.5,-1077 472.5,-1077 472.5,-1077 478.5,-1077 484.5,-1083 484.5,-1089 484.5,-1089 484.5,-1106 484.5,-1106 484.5,-1112 478.5,-1118 472.5,-1118"/>
<text text-anchor="middle" x="401" y="-1106" font-family="Helvetica,sans-Serif" font-size="10.00">title&#45;LIKE backup</text>
<text text-anchor="middle" x="401" y="-1095" font-family="Helvetica,sans-Serif" font-size="10.00">(skipped if &gt;5 tokens)</text>
<text text-anchor="middle" x="401" y="-1084" font-family="Helvetica,sans-Serif" font-size="10.00">• ~0.5s/shard for short queries</text>
</g>
<!-- title_like&#45;&gt;filter -->
<g id="edge8" class="edge">
<g id="edge10" class="edge">
<title>title_like&#45;&gt;filter</title>
<path fill="none" stroke="black" d="M297,-1021.54C297,-1010.98 297,-997.52 297,-984.51"/>
<polygon fill="black" stroke="black" points="300.5,-984.24 297,-974.24 293.5,-984.24 300.5,-984.24"/>
<path fill="none" stroke="black" d="M401,-1076.54C401,-1065.98 401,-1052.52 401,-1039.51"/>
<polygon fill="black" stroke="black" points="404.5,-1039.24 401,-1029.24 397.5,-1039.24 404.5,-1039.24"/>
</g>
<!-- phrase_route -->
<g id="node6" class="node">
<g id="node8" class="node">
<title>phrase_route</title>
<path fill="#ffe6f0" stroke="black" d="M551,-1063C551,-1063 411,-1063 411,-1063 405,-1063 399,-1057 399,-1051 399,-1051 399,-1034 399,-1034 399,-1028 405,-1022 411,-1022 411,-1022 551,-1022 551,-1022 557,-1022 563,-1028 563,-1034 563,-1034 563,-1051 563,-1051 563,-1057 557,-1063 551,-1063"/>
<text text-anchor="middle" x="481" y="-1051" font-family="Helvetica,sans-Serif" font-size="10.00">phrase&#45;pattern route</text>
<text text-anchor="middle" x="481" y="-1040" font-family="Helvetica,sans-Serif" font-size="10.00">4&#45;token sliding&#45;window match</text>
<text text-anchor="middle" x="481" y="-1029" font-family="Helvetica,sans-Serif" font-size="10.00">(closes allusion gap)</text>
<path fill="#ffe6f0" stroke="black" d="M655,-1118C655,-1118 515,-1118 515,-1118 509,-1118 503,-1112 503,-1106 503,-1106 503,-1089 503,-1089 503,-1083 509,-1077 515,-1077 515,-1077 655,-1077 655,-1077 661,-1077 667,-1083 667,-1089 667,-1089 667,-1106 667,-1106 667,-1112 661,-1118 655,-1118"/>
<text text-anchor="middle" x="585" y="-1106" font-family="Helvetica,sans-Serif" font-size="10.00">phrase&#45;pattern route</text>
<text text-anchor="middle" x="585" y="-1095" font-family="Helvetica,sans-Serif" font-size="10.00">4&#45;token sliding&#45;window match</text>
<text text-anchor="middle" x="585" y="-1084" font-family="Helvetica,sans-Serif" font-size="10.00">(closes allusion gap)</text>
</g>
<!-- phrase_route&#45;&gt;filter -->
<g id="edge9" class="edge">
<g id="edge11" class="edge">
<title>phrase_route&#45;&gt;filter</title>
<path fill="none" stroke="black" d="M445.96,-1021.79C423.19,-1008.98 392.75,-991.86 365.32,-976.43"/>
<polygon fill="black" stroke="black" points="366.96,-973.34 356.53,-971.49 363.53,-979.44 366.96,-973.34"/>
<path fill="none" stroke="black" d="M549.96,-1076.79C527.19,-1063.98 496.75,-1046.86 469.32,-1031.43"/>
<polygon fill="black" stroke="black" points="470.96,-1028.34 460.53,-1026.49 467.53,-1034.44 470.96,-1028.34"/>
</g>
<!-- concepts_lookup&#45;&gt;fts5 -->
<g id="edge4" class="edge">
<g id="edge6" class="edge">
<title>concepts_lookup&#45;&gt;fts5</title>
<path fill="none" stroke="black" d="M243.15,-1110.97C221.6,-1100.95 196.42,-1089.25 173.13,-1078.42"/>
<polygon fill="black" stroke="black" points="174.51,-1075.2 163.97,-1074.16 171.56,-1081.55 174.51,-1075.2"/>
<path fill="none" stroke="black" d="M347.15,-1165.97C325.6,-1155.95 300.42,-1144.25 277.13,-1133.42"/>
<polygon fill="black" stroke="black" points="278.51,-1130.2 267.97,-1129.16 275.56,-1136.55 278.51,-1130.2"/>
</g>
<!-- concepts_lookup&#45;&gt;title_like -->
<g id="edge5" class="edge">
<g id="edge7" class="edge">
<title>concepts_lookup&#45;&gt;title_like</title>
<path fill="none" stroke="black" d="M297,-1110.72C297,-1099.14 297,-1085.33 297,-1073.25"/>
<polygon fill="black" stroke="black" points="300.5,-1073.17 297,-1063.17 293.5,-1073.17 300.5,-1073.17"/>
<path fill="none" stroke="black" d="M401,-1165.72C401,-1154.14 401,-1140.33 401,-1128.25"/>
<polygon fill="black" stroke="black" points="404.5,-1128.17 401,-1118.17 397.5,-1128.17 404.5,-1128.17"/>
</g>
<!-- concepts_lookup&#45;&gt;phrase_route -->
<g id="edge6" class="edge">
<g id="edge8" class="edge">
<title>concepts_lookup&#45;&gt;phrase_route</title>
<path fill="none" stroke="black" d="M346.79,-1110.97C373.55,-1097.52 406.38,-1081.01 432.87,-1067.69"/>
<polygon fill="black" stroke="black" points="434.6,-1070.75 441.96,-1063.13 431.45,-1064.49 434.6,-1070.75"/>
<path fill="none" stroke="black" d="M450.79,-1165.97C477.55,-1152.52 510.38,-1136.01 536.87,-1122.69"/>
<polygon fill="black" stroke="black" points="538.6,-1125.75 545.96,-1118.13 535.45,-1119.49 538.6,-1125.75"/>
</g>
<!-- rerank -->
<g id="node9" class="node">
<g id="node11" class="node">
<title>rerank</title>
<path fill="#ffe6f0" stroke="black" d="M348.5,-863C348.5,-863 245.5,-863 245.5,-863 239.5,-863 233.5,-857 233.5,-851 233.5,-851 233.5,-812 233.5,-812 233.5,-806 239.5,-800 245.5,-800 245.5,-800 348.5,-800 348.5,-800 354.5,-800 360.5,-806 360.5,-812 360.5,-812 360.5,-851 360.5,-851 360.5,-857 354.5,-863 348.5,-863"/>
<text text-anchor="middle" x="297" y="-851" font-family="Helvetica,sans-Serif" font-size="10.00">rerank stack</text>
<text text-anchor="middle" x="297" y="-840" font-family="Helvetica,sans-Serif" font-size="10.00">• body coverage (sqrt)</text>
<text text-anchor="middle" x="297" y="-829" font-family="Helvetica,sans-Serif" font-size="10.00">• title token boost</text>
<text text-anchor="middle" x="297" y="-818" font-family="Helvetica,sans-Serif" font-size="10.00">• source role boost</text>
<text text-anchor="middle" x="297" y="-807" font-family="Helvetica,sans-Serif" font-size="10.00">• title purity</text>
<path fill="#ffe6f0" stroke="black" d="M452.5,-918C452.5,-918 349.5,-918 349.5,-918 343.5,-918 337.5,-912 337.5,-906 337.5,-906 337.5,-867 337.5,-867 337.5,-861 343.5,-855 349.5,-855 349.5,-855 452.5,-855 452.5,-855 458.5,-855 464.5,-861 464.5,-867 464.5,-867 464.5,-906 464.5,-906 464.5,-912 458.5,-918 452.5,-918"/>
<text text-anchor="middle" x="401" y="-906" font-family="Helvetica,sans-Serif" font-size="10.00">rerank stack</text>
<text text-anchor="middle" x="401" y="-895" font-family="Helvetica,sans-Serif" font-size="10.00">• body coverage (sqrt)</text>
<text text-anchor="middle" x="401" y="-884" font-family="Helvetica,sans-Serif" font-size="10.00">• title token boost</text>
<text text-anchor="middle" x="401" y="-873" font-family="Helvetica,sans-Serif" font-size="10.00">• source role boost</text>
<text text-anchor="middle" x="401" y="-862" font-family="Helvetica,sans-Serif" font-size="10.00">• title purity</text>
</g>
<!-- filter&#45;&gt;rerank -->
<g id="edge10" class="edge">
<g id="edge12" class="edge">
<title>filter&#45;&gt;rerank</title>
<path fill="none" stroke="black" d="M297,-899.8C297,-891.17 297,-881.9 297,-873.09"/>
<polygon fill="black" stroke="black" points="300.5,-873.02 297,-863.02 293.5,-873.02 300.5,-873.02"/>
<path fill="none" stroke="black" d="M401,-954.8C401,-946.17 401,-936.9 401,-928.09"/>
<polygon fill="black" stroke="black" points="404.5,-928.02 401,-918.02 397.5,-928.02 404.5,-928.02"/>
</g>
<!-- evidence_map -->
<g id="node10" class="node">
<g id="node12" class="node">
<title>evidence_map</title>
<path fill="#fff0e0" stroke="black" d="M379,-763C379,-763 215,-763 215,-763 209,-763 203,-757 203,-751 203,-751 203,-712 203,-712 203,-706 209,-700 215,-700 215,-700 379,-700 379,-700 385,-700 391,-706 391,-712 391,-712 391,-751 391,-751 391,-757 385,-763 379,-763"/>
<text text-anchor="middle" x="297" y="-751" font-family="Helvetica,sans-Serif" font-size="10.00">evidence map</text>
<text text-anchor="middle" x="297" y="-740" font-family="Helvetica,sans-Serif" font-size="10.00">(claim_lattice modes)</text>
<text text-anchor="middle" x="297" y="-729" font-family="Helvetica,sans-Serif" font-size="10.00">EvidenceObject per chunk</text>
<text text-anchor="middle" x="297" y="-718" font-family="Helvetica,sans-Serif" font-size="10.00">run&#45;stable evidence_id (sha256)</text>
<text text-anchor="middle" x="297" y="-707" font-family="Helvetica,sans-Serif" font-size="10.00">prompt&#45;facing pointer_id (E1, E2…)</text>
<path fill="#fff0e0" stroke="black" d="M483,-818C483,-818 319,-818 319,-818 313,-818 307,-812 307,-806 307,-806 307,-767 307,-767 307,-761 313,-755 319,-755 319,-755 483,-755 483,-755 489,-755 495,-761 495,-767 495,-767 495,-806 495,-806 495,-812 489,-818 483,-818"/>
<text text-anchor="middle" x="401" y="-806" font-family="Helvetica,sans-Serif" font-size="10.00">evidence map</text>
<text text-anchor="middle" x="401" y="-795" font-family="Helvetica,sans-Serif" font-size="10.00">(claim_lattice modes)</text>
<text text-anchor="middle" x="401" y="-784" font-family="Helvetica,sans-Serif" font-size="10.00">EvidenceObject per chunk</text>
<text text-anchor="middle" x="401" y="-773" font-family="Helvetica,sans-Serif" font-size="10.00">run&#45;stable evidence_id (sha256)</text>
<text text-anchor="middle" x="401" y="-762" font-family="Helvetica,sans-Serif" font-size="10.00">prompt&#45;facing pointer_id (E1, E2…)</text>
</g>
<!-- rerank&#45;&gt;evidence_map -->
<g id="edge11" class="edge">
<g id="edge13" class="edge">
<title>rerank&#45;&gt;evidence_map</title>
<path fill="none" stroke="black" d="M297,-799.76C297,-791.37 297,-782.14 297,-773.29"/>
<polygon fill="black" stroke="black" points="300.5,-773.13 297,-763.13 293.5,-773.13 300.5,-773.13"/>
<path fill="none" stroke="black" d="M401,-854.76C401,-846.37 401,-837.14 401,-828.29"/>
<polygon fill="black" stroke="black" points="404.5,-828.13 401,-818.13 397.5,-828.13 404.5,-828.13"/>
</g>
<!-- context -->
<g id="node11" class="node">
<g id="node13" class="node">
<title>context</title>
<path fill="#fff0e0" stroke="black" d="M370,-663C370,-663 224,-663 224,-663 218,-663 212,-657 212,-651 212,-651 212,-623 212,-623 212,-617 218,-611 224,-611 224,-611 370,-611 370,-611 376,-611 382,-617 382,-623 382,-623 382,-651 382,-651 382,-657 376,-663 370,-663"/>
<text text-anchor="middle" x="297" y="-651" font-family="Helvetica,sans-Serif" font-size="10.00">context assembly</text>
<text text-anchor="middle" x="297" y="-640" font-family="Helvetica,sans-Serif" font-size="10.00">• per&#45;source cap</text>
<text text-anchor="middle" x="297" y="-629" font-family="Helvetica,sans-Serif" font-size="10.00">• 60KB total budget</text>
<text text-anchor="middle" x="297" y="-618" font-family="Helvetica,sans-Serif" font-size="10.00">• wikitext.to_base() prose&#45;strip</text>
<path fill="#fff0e0" stroke="black" d="M474,-718C474,-718 328,-718 328,-718 322,-718 316,-712 316,-706 316,-706 316,-678 316,-678 316,-672 322,-666 328,-666 328,-666 474,-666 474,-666 480,-666 486,-672 486,-678 486,-678 486,-706 486,-706 486,-712 480,-718 474,-718"/>
<text text-anchor="middle" x="401" y="-706" font-family="Helvetica,sans-Serif" font-size="10.00">context assembly</text>
<text text-anchor="middle" x="401" y="-695" font-family="Helvetica,sans-Serif" font-size="10.00">• per&#45;source cap</text>
<text text-anchor="middle" x="401" y="-684" font-family="Helvetica,sans-Serif" font-size="10.00">• 60KB total budget</text>
<text text-anchor="middle" x="401" y="-673" font-family="Helvetica,sans-Serif" font-size="10.00">• wikitext.to_base() prose&#45;strip</text>
</g>
<!-- evidence_map&#45;&gt;context -->
<g id="edge12" class="edge">
<g id="edge14" class="edge">
<title>evidence_map&#45;&gt;context</title>
<path fill="none" stroke="black" d="M297,-699.96C297,-691.5 297,-682.25 297,-673.54"/>
<polygon fill="black" stroke="black" points="300.5,-673.27 297,-663.27 293.5,-673.27 300.5,-673.27"/>
<path fill="none" stroke="black" d="M401,-754.96C401,-746.5 401,-737.25 401,-728.54"/>
<polygon fill="black" stroke="black" points="404.5,-728.27 401,-718.27 397.5,-728.27 404.5,-728.27"/>
</g>
<!-- llm -->
<g id="node12" class="node">
<g id="node14" class="node">
<title>llm</title>
<path fill="#ffd4d4" stroke="black" d="M359.5,-574C359.5,-574 234.5,-574 234.5,-574 228.5,-574 222.5,-568 222.5,-562 222.5,-562 222.5,-534 222.5,-534 222.5,-528 228.5,-522 234.5,-522 234.5,-522 359.5,-522 359.5,-522 365.5,-522 371.5,-528 371.5,-534 371.5,-534 371.5,-562 371.5,-562 371.5,-568 365.5,-574 359.5,-574"/>
<text text-anchor="middle" x="297" y="-562" font-family="Helvetica,sans-Serif" font-size="10.00">LLM call (Hermes&#45;3 / vLLM)</text>
<text text-anchor="middle" x="297" y="-551" font-family="Helvetica,sans-Serif" font-size="10.00">68s — DOMINANT cost</text>
<text text-anchor="middle" x="297" y="-540" font-family="Helvetica,sans-Serif" font-size="10.00">claim_lattice_pointer or</text>
<text text-anchor="middle" x="297" y="-529" font-family="Helvetica,sans-Serif" font-size="10.00">claim_lattice (JSON)</text>
<path fill="#ffd4d4" stroke="black" d="M463.5,-629C463.5,-629 338.5,-629 338.5,-629 332.5,-629 326.5,-623 326.5,-617 326.5,-617 326.5,-589 326.5,-589 326.5,-583 332.5,-577 338.5,-577 338.5,-577 463.5,-577 463.5,-577 469.5,-577 475.5,-583 475.5,-589 475.5,-589 475.5,-617 475.5,-617 475.5,-623 469.5,-629 463.5,-629"/>
<text text-anchor="middle" x="401" y="-617" font-family="Helvetica,sans-Serif" font-size="10.00">LLM call (Hermes&#45;3 / vLLM)</text>
<text text-anchor="middle" x="401" y="-606" font-family="Helvetica,sans-Serif" font-size="10.00">68s — DOMINANT cost</text>
<text text-anchor="middle" x="401" y="-595" font-family="Helvetica,sans-Serif" font-size="10.00">claim_lattice_pointer or</text>
<text text-anchor="middle" x="401" y="-584" font-family="Helvetica,sans-Serif" font-size="10.00">claim_lattice (JSON)</text>
</g>
<!-- context&#45;&gt;llm -->
<g id="edge13" class="edge">
<g id="edge15" class="edge">
<title>context&#45;&gt;llm</title>
<path fill="none" stroke="black" d="M297,-610.84C297,-602.54 297,-593.15 297,-584.25"/>
<polygon fill="black" stroke="black" points="300.5,-584.11 297,-574.11 293.5,-584.11 300.5,-584.11"/>
<path fill="none" stroke="black" d="M401,-665.84C401,-657.54 401,-648.15 401,-639.25"/>
<polygon fill="black" stroke="black" points="404.5,-639.11 401,-629.11 397.5,-639.11 404.5,-639.11"/>
</g>
<!-- verify -->
<g id="node13" class="node">
<g id="node15" class="node">
<title>verify</title>
<path fill="#e7ffe7" stroke="black" d="M352,-485C352,-485 242,-485 242,-485 236,-485 230,-479 230,-473 230,-473 230,-390 230,-390 230,-384 236,-378 242,-378 242,-378 352,-378 352,-378 358,-378 364,-384 364,-390 364,-390 364,-473 364,-473 364,-479 358,-485 352,-485"/>
<text text-anchor="middle" x="297" y="-473" font-family="Helvetica,sans-Serif" font-size="10.00">verify_claim_lattice</text>
<text text-anchor="middle" x="297" y="-462" font-family="Helvetica,sans-Serif" font-size="10.00">7 hard checks:</text>
<text text-anchor="middle" x="297" y="-451" font-family="Helvetica,sans-Serif" font-size="10.00">1. parser succeeded</text>
<text text-anchor="middle" x="297" y="-440" font-family="Helvetica,sans-Serif" font-size="10.00">2. evidence_id resolves</text>
<text text-anchor="middle" x="297" y="-429" font-family="Helvetica,sans-Serif" font-size="10.00">3. source_role allowed</text>
<text text-anchor="middle" x="297" y="-418" font-family="Helvetica,sans-Serif" font-size="10.00">4. claim text non&#45;empty</text>
<text text-anchor="middle" x="297" y="-407" font-family="Helvetica,sans-Serif" font-size="10.00">5. citation coverage</text>
<text text-anchor="middle" x="297" y="-396" font-family="Helvetica,sans-Serif" font-size="10.00">6. pointer count cap</text>
<text text-anchor="middle" x="297" y="-385" font-family="Helvetica,sans-Serif" font-size="10.00">7. anchor&#45;class warrant</text>
<path fill="#e7ffe7" stroke="black" d="M456,-540C456,-540 346,-540 346,-540 340,-540 334,-534 334,-528 334,-528 334,-445 334,-445 334,-439 340,-433 346,-433 346,-433 456,-433 456,-433 462,-433 468,-439 468,-445 468,-445 468,-528 468,-528 468,-534 462,-540 456,-540"/>
<text text-anchor="middle" x="401" y="-528" font-family="Helvetica,sans-Serif" font-size="10.00">verify_claim_lattice</text>
<text text-anchor="middle" x="401" y="-517" font-family="Helvetica,sans-Serif" font-size="10.00">7 hard checks:</text>
<text text-anchor="middle" x="401" y="-506" font-family="Helvetica,sans-Serif" font-size="10.00">1. parser succeeded</text>
<text text-anchor="middle" x="401" y="-495" font-family="Helvetica,sans-Serif" font-size="10.00">2. evidence_id resolves</text>
<text text-anchor="middle" x="401" y="-484" font-family="Helvetica,sans-Serif" font-size="10.00">3. source_role allowed</text>
<text text-anchor="middle" x="401" y="-473" font-family="Helvetica,sans-Serif" font-size="10.00">4. claim text non&#45;empty</text>
<text text-anchor="middle" x="401" y="-462" font-family="Helvetica,sans-Serif" font-size="10.00">5. citation coverage</text>
<text text-anchor="middle" x="401" y="-451" font-family="Helvetica,sans-Serif" font-size="10.00">6. pointer count cap</text>
<text text-anchor="middle" x="401" y="-440" font-family="Helvetica,sans-Serif" font-size="10.00">7. anchor&#45;class warrant</text>
</g>
<!-- llm&#45;&gt;verify -->
<g id="edge14" class="edge">
<g id="edge16" class="edge">
<title>llm&#45;&gt;verify</title>
<path fill="none" stroke="black" d="M297,-521.87C297,-513.94 297,-504.8 297,-495.45"/>
<polygon fill="black" stroke="black" points="300.5,-495.28 297,-485.28 293.5,-495.28 300.5,-495.28"/>
<path fill="none" stroke="black" d="M401,-576.87C401,-568.94 401,-559.8 401,-550.45"/>
<polygon fill="black" stroke="black" points="404.5,-550.28 401,-540.28 397.5,-550.28 404.5,-550.28"/>
</g>
<!-- warrant -->
<g id="node14" class="node">
<g id="node16" class="node">
<title>warrant</title>
<path fill="#e7ffe7" stroke="black" d="M374.5,-341C374.5,-341 219.5,-341 219.5,-341 213.5,-341 207.5,-335 207.5,-329 207.5,-329 207.5,-279 207.5,-279 207.5,-273 213.5,-267 219.5,-267 219.5,-267 374.5,-267 374.5,-267 380.5,-267 386.5,-273 386.5,-279 386.5,-279 386.5,-329 386.5,-329 386.5,-335 380.5,-341 374.5,-341"/>
<text text-anchor="middle" x="297" y="-329" font-family="Helvetica,sans-Serif" font-size="10.00">warrant_check (5 anchor classes)</text>
<text text-anchor="middle" x="297" y="-318" font-family="Helvetica,sans-Serif" font-size="10.00">• proper&#45;noun (relation&#45;gated)</text>
<text text-anchor="middle" x="297" y="-307" font-family="Helvetica,sans-Serif" font-size="10.00">• date (year + month)</text>
<text text-anchor="middle" x="297" y="-296" font-family="Helvetica,sans-Serif" font-size="10.00">• count (digit↔word)</text>
<text text-anchor="middle" x="297" y="-285" font-family="Helvetica,sans-Serif" font-size="10.00">• entity&#45;list</text>
<text text-anchor="middle" x="297" y="-274" font-family="Helvetica,sans-Serif" font-size="10.00">• cause (why&#45;shape)</text>
<path fill="#e7ffe7" stroke="black" d="M478.5,-396C478.5,-396 323.5,-396 323.5,-396 317.5,-396 311.5,-390 311.5,-384 311.5,-384 311.5,-334 311.5,-334 311.5,-328 317.5,-322 323.5,-322 323.5,-322 478.5,-322 478.5,-322 484.5,-322 490.5,-328 490.5,-334 490.5,-334 490.5,-384 490.5,-384 490.5,-390 484.5,-396 478.5,-396"/>
<text text-anchor="middle" x="401" y="-384" font-family="Helvetica,sans-Serif" font-size="10.00">warrant_check (5 anchor classes)</text>
<text text-anchor="middle" x="401" y="-373" font-family="Helvetica,sans-Serif" font-size="10.00">• proper&#45;noun (relation&#45;gated)</text>
<text text-anchor="middle" x="401" y="-362" font-family="Helvetica,sans-Serif" font-size="10.00">• date (year + month)</text>
<text text-anchor="middle" x="401" y="-351" font-family="Helvetica,sans-Serif" font-size="10.00">• count (digit↔word)</text>
<text text-anchor="middle" x="401" y="-340" font-family="Helvetica,sans-Serif" font-size="10.00">• entity&#45;list</text>
<text text-anchor="middle" x="401" y="-329" font-family="Helvetica,sans-Serif" font-size="10.00">• cause (why&#45;shape)</text>
</g>
<!-- verify&#45;&gt;warrant -->
<g id="edge15" class="edge">
<g id="edge17" class="edge">
<title>verify&#45;&gt;warrant</title>
<path fill="none" stroke="black" d="M297,-377.64C297,-368.88 297,-359.85 297,-351.27"/>
<polygon fill="black" stroke="black" points="300.5,-351.06 297,-341.06 293.5,-351.06 300.5,-351.06"/>
<path fill="none" stroke="black" d="M401,-432.64C401,-423.88 401,-414.85 401,-406.27"/>
<polygon fill="black" stroke="black" points="404.5,-406.06 401,-396.06 397.5,-406.06 404.5,-406.06"/>
</g>
<!-- render -->
<g id="node15" class="node">
<g id="node17" class="node">
<title>render</title>
<path fill="#fff7e6" stroke="black" d="M374.5,-230C374.5,-230 219.5,-230 219.5,-230 213.5,-230 207.5,-224 207.5,-218 207.5,-218 207.5,-190 207.5,-190 207.5,-184 213.5,-178 219.5,-178 219.5,-178 374.5,-178 374.5,-178 380.5,-178 386.5,-184 386.5,-190 386.5,-190 386.5,-218 386.5,-218 386.5,-224 380.5,-230 374.5,-230"/>
<text text-anchor="middle" x="297" y="-218" font-family="Helvetica,sans-Serif" font-size="10.00">render</text>
<text text-anchor="middle" x="297" y="-207" font-family="Helvetica,sans-Serif" font-size="10.00">• spotlight excerpt (density rank)</text>
<text text-anchor="middle" x="297" y="-196" font-family="Helvetica,sans-Serif" font-size="10.00">• [E5 | Title | chunk_prefix: &quot;...&quot;]</text>
<text text-anchor="middle" x="297" y="-185" font-family="Helvetica,sans-Serif" font-size="10.00">• four&#45;rung label ladder</text>
<path fill="#fff7e6" stroke="black" d="M478.5,-285C478.5,-285 323.5,-285 323.5,-285 317.5,-285 311.5,-279 311.5,-273 311.5,-273 311.5,-190 311.5,-190 311.5,-184 317.5,-178 323.5,-178 323.5,-178 478.5,-178 478.5,-178 484.5,-178 490.5,-184 490.5,-190 490.5,-190 490.5,-273 490.5,-273 490.5,-279 484.5,-285 478.5,-285"/>
<text text-anchor="middle" x="401" y="-273" font-family="Helvetica,sans-Serif" font-size="10.00">render</text>
<text text-anchor="middle" x="401" y="-262" font-family="Helvetica,sans-Serif" font-size="10.00">• spotlight excerpt (density rank)</text>
<text text-anchor="middle" x="401" y="-251" font-family="Helvetica,sans-Serif" font-size="10.00">• [E5 | Title | chunk_prefix: &quot;...&quot;]</text>
<text text-anchor="middle" x="401" y="-240" font-family="Helvetica,sans-Serif" font-size="10.00">• four&#45;rung label ladder</text>
<text text-anchor="middle" x="401" y="-229" font-family="Helvetica,sans-Serif" font-size="10.00">• audit&#45;line tails:</text>
<text text-anchor="middle" x="401" y="-218" font-family="Helvetica,sans-Serif" font-size="10.00"> &#160;· false premise · contradictory</text>
<text text-anchor="middle" x="401" y="-207" font-family="Helvetica,sans-Serif" font-size="10.00"> &#160;· stale risk · out of corpus</text>
<text text-anchor="middle" x="401" y="-196" font-family="Helvetica,sans-Serif" font-size="10.00"> &#160;· frame ambiguous</text>
<text text-anchor="middle" x="401" y="-185" font-family="Helvetica,sans-Serif" font-size="10.00"> &#160;· broad cap N · broad rejected</text>
</g>
<!-- warrant&#45;&gt;render -->
<g id="edge16" class="edge">
<g id="edge18" class="edge">
<title>warrant&#45;&gt;render</title>
<path fill="none" stroke="black" d="M297,-266.79C297,-258.1 297,-248.84 297,-240.21"/>
<polygon fill="black" stroke="black" points="300.5,-240.06 297,-230.06 293.5,-240.06 300.5,-240.06"/>
<path fill="none" stroke="black" d="M401,-321.7C401,-313.39 401,-304.32 401,-295.25"/>
<polygon fill="black" stroke="black" points="404.5,-295.06 401,-285.06 397.5,-295.06 404.5,-295.06"/>
</g>
<!-- cache_write -->
<g id="node16" class="node">
<g id="node18" class="node">
<title>cache_write</title>
<path fill="#e6f0ff" stroke="black" d="M369.5,-141C369.5,-141 224.5,-141 224.5,-141 218.5,-141 212.5,-135 212.5,-129 212.5,-129 212.5,-90 212.5,-90 212.5,-84 218.5,-78 224.5,-78 224.5,-78 369.5,-78 369.5,-78 375.5,-78 381.5,-84 381.5,-90 381.5,-90 381.5,-129 381.5,-129 381.5,-135 375.5,-141 369.5,-141"/>
<text text-anchor="middle" x="297" y="-129" font-family="Helvetica,sans-Serif" font-size="10.00">providence_cache write</text>
<text text-anchor="middle" x="297" y="-118" font-family="Helvetica,sans-Serif" font-size="10.00">• 8&#45;dim cache_key</text>
<text text-anchor="middle" x="297" y="-107" font-family="Helvetica,sans-Serif" font-size="10.00">• run_dag_root + run_dag_blob</text>
<text text-anchor="middle" x="297" y="-96" font-family="Helvetica,sans-Serif" font-size="10.00">• audit_event chained</text>
<text text-anchor="middle" x="297" y="-85" font-family="Helvetica,sans-Serif" font-size="10.00">• context_root committed</text>
<path fill="#e6f0ff" stroke="black" d="M473.5,-141C473.5,-141 328.5,-141 328.5,-141 322.5,-141 316.5,-135 316.5,-129 316.5,-129 316.5,-90 316.5,-90 316.5,-84 322.5,-78 328.5,-78 328.5,-78 473.5,-78 473.5,-78 479.5,-78 485.5,-84 485.5,-90 485.5,-90 485.5,-129 485.5,-129 485.5,-135 479.5,-141 473.5,-141"/>
<text text-anchor="middle" x="401" y="-129" font-family="Helvetica,sans-Serif" font-size="10.00">providence_cache write</text>
<text text-anchor="middle" x="401" y="-118" font-family="Helvetica,sans-Serif" font-size="10.00">• 8&#45;dim cache_key</text>
<text text-anchor="middle" x="401" y="-107" font-family="Helvetica,sans-Serif" font-size="10.00">• run_dag_root + run_dag_blob</text>
<text text-anchor="middle" x="401" y="-96" font-family="Helvetica,sans-Serif" font-size="10.00">• audit_event chained</text>
<text text-anchor="middle" x="401" y="-85" font-family="Helvetica,sans-Serif" font-size="10.00">• context_root committed</text>
</g>
<!-- render&#45;&gt;cache_write -->
<g id="edge17" class="edge">
<g id="edge19" class="edge">
<title>render&#45;&gt;cache_write</title>
<path fill="none" stroke="black" d="M297,-177.72C297,-169.48 297,-160.12 297,-151.05"/>
<polygon fill="black" stroke="black" points="300.5,-151.01 297,-141.01 293.5,-151.01 300.5,-151.01"/>
<path fill="none" stroke="black" d="M401,-177.87C401,-168.91 401,-159.74 401,-151.15"/>
<polygon fill="black" stroke="black" points="404.5,-151.03 401,-141.03 397.5,-151.03 404.5,-151.03"/>
</g>
<!-- answer -->
<g id="node17" class="node">
<g id="node19" class="node">
<title>answer</title>
<polygon fill="#d4edda" stroke="black" points="380,-41 208,-41 208,0 386,0 386,-35 380,-41"/>
<polyline fill="none" stroke="black" points="380,-41 380,-35 "/>
<polyline fill="none" stroke="black" points="386,-35 380,-35 "/>
<text text-anchor="middle" x="297" y="-29" font-family="Helvetica,sans-Serif" font-size="10.00">ANSWER</text>
<text text-anchor="middle" x="297" y="-18" font-family="Helvetica,sans-Serif" font-size="10.00">label: POINTER&#45;LINKED&#45;PARTIAL ·</text>
<text text-anchor="middle" x="297" y="-7" font-family="Helvetica,sans-Serif" font-size="10.00">via claim_lattice · 2/2 · 11.6s</text>
<polygon fill="#d4edda" stroke="black" points="484,-41 312,-41 312,0 490,0 490,-35 484,-41"/>
<polyline fill="none" stroke="black" points="484,-41 484,-35 "/>
<polyline fill="none" stroke="black" points="490,-35 484,-35 "/>
<text text-anchor="middle" x="401" y="-29" font-family="Helvetica,sans-Serif" font-size="10.00">ANSWER</text>
<text text-anchor="middle" x="401" y="-18" font-family="Helvetica,sans-Serif" font-size="10.00">label: POINTER&#45;LINKED&#45;PARTIAL ·</text>
<text text-anchor="middle" x="401" y="-7" font-family="Helvetica,sans-Serif" font-size="10.00">via claim_lattice · 2/2 · 11.6s</text>
</g>
<!-- cache_write&#45;&gt;answer -->
<g id="edge18" class="edge">
<g id="edge20" class="edge">
<title>cache_write&#45;&gt;answer</title>
<path fill="none" stroke="black" d="M297,-77.58C297,-69.07 297,-59.84 297,-51.39"/>
<polygon fill="black" stroke="black" points="300.5,-51.19 297,-41.19 293.5,-51.19 300.5,-51.19"/>
<path fill="none" stroke="black" d="M401,-77.58C401,-69.07 401,-59.84 401,-51.39"/>
<polygon fill="black" stroke="black" points="404.5,-51.19 401,-41.19 397.5,-51.19 404.5,-51.19"/>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 26 KiB

Before After
Before After

View file

@ -18,7 +18,7 @@ digraph verifier_ladder {
// Decision tree
is_ungrounded [label="audit_mode == UNGROUNDED?", fillcolor="#dddddd", shape=diamond]
has_warrant_miss [label="WARRANT_MISSING or\nTITLE_MISMATCH in violations?", fillcolor="#dddddd", shape=diamond]
has_soft_demote [label="any soft-demote violation?\n(LAZY_ANCHOR_DEMOTED,\nPOINTER_OVERFLOW_TRIMMED,\nTOO_MANY_CLAIMS, …)", fillcolor="#dddddd", shape=diamond]
has_soft_demote [label="any soft-demote violation?\n(LAZY_ANCHOR_DEMOTED,\nPOINTER_OVERFLOW_TRIMMED,\nTOO_MANY_CLAIMS, BARE_NAME_CLAIM,\nFORMAT_COLLAPSED,\nBROAD_QUANTIFIER_RUNAWAY,\nBROAD_QUANTIFIER_CAP_APPLIED,\nBROAD_QUANTIFIER_SCOPE_UNBOUND, …)", fillcolor="#dddddd", shape=diamond]
is_hybrid [label="audit_mode == HYBRID?", fillcolor="#dddddd", shape=diamond]
// Rungs (top to bottom = strongest to weakest)
@ -30,6 +30,10 @@ digraph verifier_ladder {
// Suffix annotation
partial [label="HYBRID → add `-PARTIAL` suffix\non whichever rung applies", fillcolor="#fff0e0", shape=note]
// Audit-line tail tokens (#000008 + #000010 — pure render layer,
// composed onto the rung label after the suffix is applied).
tail_tokens [label="AUDIT-LINE TAILS\nappended to all rung labels:\n#000008 quantifier guard:\n · broad cap N · broad rejected\n · broad unbounded · broad runaway\n#000010 metacognition preflight:\n · false premise · contradictory\n · stale risk · out of corpus\n · frame ambiguous\nclassic verifier:\n · warrant missing · title mismatch\n · format collapsed", fillcolor="#fff0e0", shape=note]
// Decision flow
inputs -> is_ungrounded
is_ungrounded -> ungrounded [label="yes"]
@ -45,5 +49,11 @@ digraph verifier_ladder {
pointer_linked -> is_hybrid [style=dotted]
is_hybrid -> partial [label="yes" style=dotted]
// All four rungs can carry tail tokens.
evidence_warranted -> tail_tokens [style=dashed, color="#888888"]
anchor_warranted -> tail_tokens [style=dashed, color="#888888"]
pointer_linked -> tail_tokens [style=dashed, color="#888888"]
ungrounded -> tail_tokens [style=dashed, color="#888888"]
{rank=same; evidence_warranted; anchor_warranted; pointer_linked; ungrounded}
}

View file

@ -4,165 +4,212 @@
<!-- Generated by graphviz version 2.43.0 (0)
-->
<!-- Title: verifier_ladder Pages: 1 -->
<svg width="634pt" height="631pt"
viewBox="0.00 0.00 633.50 631.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 627)">
<svg width="619pt" height="823pt"
viewBox="0.00 0.00 619.00 823.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 819)">
<title>verifier_ladder</title>
<polygon fill="white" stroke="transparent" points="-4,4 -4,-627 629.5,-627 629.5,4 -4,4"/>
<polygon fill="white" stroke="transparent" points="-4,4 -4,-819 615,-819 615,4 -4,4"/>
<!-- inputs -->
<g id="node1" class="node">
<title>inputs</title>
<polygon fill="#fff7e6" stroke="black" points="602,-623 350,-623 350,-582 608,-582 608,-617 602,-623"/>
<polyline fill="none" stroke="black" points="602,-623 602,-617 "/>
<polyline fill="none" stroke="black" points="608,-617 602,-617 "/>
<text text-anchor="middle" x="479" y="-611" font-family="Helvetica,sans-Serif" font-size="10.00">VERIFIER OUTPUT</text>
<text text-anchor="middle" x="479" y="-600" font-family="Helvetica,sans-Serif" font-size="10.00">audit_mode ∈ {STRICT, HYBRID, UNGROUNDED}</text>
<text text-anchor="middle" x="479" y="-589" font-family="Helvetica,sans-Serif" font-size="10.00">violations: list[dict]</text>
<polygon fill="#fff7e6" stroke="black" points="566.5,-815 314.5,-815 314.5,-774 572.5,-774 572.5,-809 566.5,-815"/>
<polyline fill="none" stroke="black" points="566.5,-815 566.5,-809 "/>
<polyline fill="none" stroke="black" points="572.5,-809 566.5,-809 "/>
<text text-anchor="middle" x="443.5" y="-803" font-family="Helvetica,sans-Serif" font-size="10.00">VERIFIER OUTPUT</text>
<text text-anchor="middle" x="443.5" y="-792" font-family="Helvetica,sans-Serif" font-size="10.00">audit_mode ∈ {STRICT, HYBRID, UNGROUNDED}</text>
<text text-anchor="middle" x="443.5" y="-781" font-family="Helvetica,sans-Serif" font-size="10.00">violations: list[dict]</text>
</g>
<!-- is_ungrounded -->
<g id="node2" class="node">
<title>is_ungrounded</title>
<path fill="#dddddd" stroke="black" d="M467.09,-543.53C467.09,-543.53 345.04,-528.47 345.04,-528.47 339.08,-527.73 339.08,-526.27 345.04,-525.53 345.04,-525.53 467.09,-510.47 467.09,-510.47 473.05,-509.73 484.95,-509.73 490.91,-510.47 490.91,-510.47 612.96,-525.53 612.96,-525.53 618.92,-526.27 618.92,-527.73 612.96,-528.47 612.96,-528.47 490.91,-543.53 490.91,-543.53 484.95,-544.27 473.05,-544.27 467.09,-543.53"/>
<text text-anchor="middle" x="479" y="-524.5" font-family="Helvetica,sans-Serif" font-size="10.00">audit_mode == UNGROUNDED?</text>
<path fill="#dddddd" stroke="black" d="M431.59,-735.53C431.59,-735.53 309.54,-720.47 309.54,-720.47 303.58,-719.73 303.58,-718.27 309.54,-717.53 309.54,-717.53 431.59,-702.47 431.59,-702.47 437.55,-701.73 449.45,-701.73 455.41,-702.47 455.41,-702.47 577.46,-717.53 577.46,-717.53 583.42,-718.27 583.42,-719.73 577.46,-720.47 577.46,-720.47 455.41,-735.53 455.41,-735.53 449.45,-736.27 437.55,-736.27 431.59,-735.53"/>
<text text-anchor="middle" x="443.5" y="-716.5" font-family="Helvetica,sans-Serif" font-size="10.00">audit_mode == UNGROUNDED?</text>
</g>
<!-- inputs&#45;&gt;is_ungrounded -->
<g id="edge1" class="edge">
<title>inputs&#45;&gt;is_ungrounded</title>
<path fill="none" stroke="black" d="M479,-581.8C479,-573.7 479,-564.18 479,-555.41"/>
<polygon fill="black" stroke="black" points="482.5,-555.25 479,-545.25 475.5,-555.25 482.5,-555.25"/>
<path fill="none" stroke="black" d="M443.5,-773.8C443.5,-765.7 443.5,-756.18 443.5,-747.41"/>
<polygon fill="black" stroke="black" points="447,-747.25 443.5,-737.25 440,-747.25 447,-747.25"/>
</g>
<!-- has_warrant_miss -->
<g id="node3" class="node">
<title>has_warrant_miss</title>
<path fill="#dddddd" stroke="black" d="M369.18,-460.9C369.18,-460.9 223.82,-435.1 223.82,-435.1 217.91,-434.05 217.91,-431.95 223.82,-430.9 223.82,-430.9 369.18,-405.1 369.18,-405.1 375.09,-404.05 386.91,-404.05 392.82,-405.1 392.82,-405.1 538.18,-430.9 538.18,-430.9 544.09,-431.95 544.09,-434.05 538.18,-435.1 538.18,-435.1 392.82,-460.9 392.82,-460.9 386.91,-461.95 375.09,-461.95 369.18,-460.9"/>
<text text-anchor="middle" x="381" y="-436" font-family="Helvetica,sans-Serif" font-size="10.00">WARRANT_MISSING or</text>
<text text-anchor="middle" x="381" y="-425" font-family="Helvetica,sans-Serif" font-size="10.00">TITLE_MISMATCH in violations?</text>
<path fill="#dddddd" stroke="black" d="M302.68,-652.9C302.68,-652.9 157.32,-627.1 157.32,-627.1 151.41,-626.05 151.41,-623.95 157.32,-622.9 157.32,-622.9 302.68,-597.1 302.68,-597.1 308.59,-596.05 320.41,-596.05 326.32,-597.1 326.32,-597.1 471.68,-622.9 471.68,-622.9 477.59,-623.95 477.59,-626.05 471.68,-627.1 471.68,-627.1 326.32,-652.9 326.32,-652.9 320.41,-653.95 308.59,-653.95 302.68,-652.9"/>
<text text-anchor="middle" x="314.5" y="-628" font-family="Helvetica,sans-Serif" font-size="10.00">WARRANT_MISSING or</text>
<text text-anchor="middle" x="314.5" y="-617" font-family="Helvetica,sans-Serif" font-size="10.00">TITLE_MISMATCH in violations?</text>
</g>
<!-- is_ungrounded&#45;&gt;has_warrant_miss -->
<g id="edge3" class="edge">
<title>is_ungrounded&#45;&gt;has_warrant_miss</title>
<path fill="none" stroke="black" d="M462.82,-510.81C449.71,-498.5 430.81,-480.76 414.47,-465.42"/>
<polygon fill="black" stroke="black" points="416.86,-462.87 407.18,-458.57 412.07,-467.97 416.86,-462.87"/>
<text text-anchor="middle" x="448" y="-483.8" font-family="Helvetica,sans-Serif" font-size="9.00">no</text>
<path fill="none" stroke="black" d="M423.06,-703.42C404.98,-690.53 378.05,-671.32 355.54,-655.27"/>
<polygon fill="black" stroke="black" points="357.33,-652.25 347.16,-649.29 353.27,-657.95 357.33,-652.25"/>
<text text-anchor="middle" x="399.5" y="-675.8" font-family="Helvetica,sans-Serif" font-size="9.00">no</text>
</g>
<!-- ungrounded -->
<g id="node9" class="node">
<title>ungrounded</title>
<path fill="#dc3545" stroke="black" d="M613.5,-201.5C613.5,-201.5 542.5,-201.5 542.5,-201.5 536.5,-201.5 530.5,-195.5 530.5,-189.5 530.5,-189.5 530.5,-172.5 530.5,-172.5 530.5,-166.5 536.5,-160.5 542.5,-160.5 542.5,-160.5 613.5,-160.5 613.5,-160.5 619.5,-160.5 625.5,-166.5 625.5,-172.5 625.5,-172.5 625.5,-189.5 625.5,-189.5 625.5,-195.5 619.5,-201.5 613.5,-201.5"/>
<text text-anchor="middle" x="578" y="-189.5" font-family="Helvetica,sans-Serif" font-size="10.00" fill="white">UNGROUNDED</text>
<text text-anchor="middle" x="578" y="-178.5" font-family="Helvetica,sans-Serif" font-size="10.00" fill="white">no verified pairs</text>
<text text-anchor="middle" x="578" y="-167.5" font-family="Helvetica,sans-Serif" font-size="10.00" fill="white">at all</text>
<path fill="#dc3545" stroke="black" d="M599,-305.5C599,-305.5 528,-305.5 528,-305.5 522,-305.5 516,-299.5 516,-293.5 516,-293.5 516,-276.5 516,-276.5 516,-270.5 522,-264.5 528,-264.5 528,-264.5 599,-264.5 599,-264.5 605,-264.5 611,-270.5 611,-276.5 611,-276.5 611,-293.5 611,-293.5 611,-299.5 605,-305.5 599,-305.5"/>
<text text-anchor="middle" x="563.5" y="-293.5" font-family="Helvetica,sans-Serif" font-size="10.00" fill="white">UNGROUNDED</text>
<text text-anchor="middle" x="563.5" y="-282.5" font-family="Helvetica,sans-Serif" font-size="10.00" fill="white">no verified pairs</text>
<text text-anchor="middle" x="563.5" y="-271.5" font-family="Helvetica,sans-Serif" font-size="10.00" fill="white">at all</text>
</g>
<!-- is_ungrounded&#45;&gt;ungrounded -->
<g id="edge2" class="edge">
<title>is_ungrounded&#45;&gt;ungrounded</title>
<path fill="none" stroke="black" d="M506.67,-512.17C524.93,-501.44 547.53,-484.73 559,-463 602.45,-380.67 591.78,-265.38 583.46,-211.69"/>
<polygon fill="black" stroke="black" points="586.86,-210.81 581.79,-201.5 579.95,-211.94 586.86,-210.81"/>
<text text-anchor="middle" x="593" y="-377.8" font-family="Helvetica,sans-Serif" font-size="9.00">yes</text>
<path fill="none" stroke="black" d="M458.54,-702.43C484.34,-674.47 536.06,-612.73 554.5,-549 578.17,-467.23 572.15,-365.17 567.12,-315.67"/>
<polygon fill="black" stroke="black" points="570.59,-315.22 566.04,-305.65 563.63,-315.97 570.59,-315.22"/>
<text text-anchor="middle" x="555.5" y="-569.8" font-family="Helvetica,sans-Serif" font-size="9.00">yes</text>
</g>
<!-- has_soft_demote -->
<g id="node4" class="node">
<title>has_soft_demote</title>
<path fill="#dddddd" stroke="black" d="M182.49,-353.6C182.49,-353.6 29.51,-308.4 29.51,-308.4 23.75,-306.7 23.75,-303.3 29.51,-301.6 29.51,-301.6 182.49,-256.4 182.49,-256.4 188.25,-254.7 199.75,-254.7 205.51,-256.4 205.51,-256.4 358.49,-301.6 358.49,-301.6 364.25,-303.3 364.25,-306.7 358.49,-308.4 358.49,-308.4 205.51,-353.6 205.51,-353.6 199.75,-355.3 188.25,-355.3 182.49,-353.6"/>
<text text-anchor="middle" x="194" y="-319" font-family="Helvetica,sans-Serif" font-size="10.00">any soft&#45;demote violation?</text>
<text text-anchor="middle" x="194" y="-308" font-family="Helvetica,sans-Serif" font-size="10.00">(LAZY_ANCHOR_DEMOTED,</text>
<text text-anchor="middle" x="194" y="-297" font-family="Helvetica,sans-Serif" font-size="10.00">POINTER_OVERFLOW_TRIMMED,</text>
<text text-anchor="middle" x="194" y="-286" font-family="Helvetica,sans-Serif" font-size="10.00">TOO_MANY_CLAIMS, …)</text>
<path fill="#dddddd" stroke="black" d="M303.42,-544.39C303.42,-544.39 94.58,-457.61 94.58,-457.61 89.04,-455.3 89.04,-450.7 94.58,-448.39 94.58,-448.39 303.42,-361.61 303.42,-361.61 308.96,-359.3 320.04,-359.3 325.58,-361.61 325.58,-361.61 534.42,-448.39 534.42,-448.39 539.96,-450.7 539.96,-455.3 534.42,-457.61 534.42,-457.61 325.58,-544.39 325.58,-544.39 320.04,-546.7 308.96,-546.7 303.42,-544.39"/>
<text text-anchor="middle" x="314.5" y="-489" font-family="Helvetica,sans-Serif" font-size="10.00">any soft&#45;demote violation?</text>
<text text-anchor="middle" x="314.5" y="-478" font-family="Helvetica,sans-Serif" font-size="10.00">(LAZY_ANCHOR_DEMOTED,</text>
<text text-anchor="middle" x="314.5" y="-467" font-family="Helvetica,sans-Serif" font-size="10.00">POINTER_OVERFLOW_TRIMMED,</text>
<text text-anchor="middle" x="314.5" y="-456" font-family="Helvetica,sans-Serif" font-size="10.00">TOO_MANY_CLAIMS, BARE_NAME_CLAIM,</text>
<text text-anchor="middle" x="314.5" y="-445" font-family="Helvetica,sans-Serif" font-size="10.00">FORMAT_COLLAPSED,</text>
<text text-anchor="middle" x="314.5" y="-434" font-family="Helvetica,sans-Serif" font-size="10.00">BROAD_QUANTIFIER_RUNAWAY,</text>
<text text-anchor="middle" x="314.5" y="-423" font-family="Helvetica,sans-Serif" font-size="10.00">BROAD_QUANTIFIER_CAP_APPLIED,</text>
<text text-anchor="middle" x="314.5" y="-412" font-family="Helvetica,sans-Serif" font-size="10.00">BROAD_QUANTIFIER_SCOPE_UNBOUND, …)</text>
</g>
<!-- has_warrant_miss&#45;&gt;has_soft_demote -->
<g id="edge5" class="edge">
<title>has_warrant_miss&#45;&gt;has_soft_demote</title>
<path fill="none" stroke="black" d="M346.7,-408.89C321.16,-391.68 285.61,-367.73 255.23,-347.26"/>
<polygon fill="black" stroke="black" points="257.07,-344.27 246.82,-341.59 253.15,-350.08 257.07,-344.27"/>
<text text-anchor="middle" x="316" y="-377.8" font-family="Helvetica,sans-Serif" font-size="9.00">no</text>
<path fill="none" stroke="black" d="M314.5,-594.78C314.5,-584.41 314.5,-572.07 314.5,-559.06"/>
<polygon fill="black" stroke="black" points="318,-559 314.5,-549 311,-559 318,-559"/>
<text text-anchor="middle" x="320.5" y="-569.8" font-family="Helvetica,sans-Serif" font-size="9.00">no</text>
</g>
<!-- pointer_linked -->
<g id="node8" class="node">
<title>pointer_linked</title>
<path fill="#ffc107" stroke="black" d="M475.5,-207C475.5,-207 336.5,-207 336.5,-207 330.5,-207 324.5,-201 324.5,-195 324.5,-195 324.5,-167 324.5,-167 324.5,-161 330.5,-155 336.5,-155 336.5,-155 475.5,-155 475.5,-155 481.5,-155 487.5,-161 487.5,-167 487.5,-167 487.5,-195 487.5,-195 487.5,-201 481.5,-207 475.5,-207"/>
<text text-anchor="middle" x="406" y="-195" font-family="Helvetica,sans-Serif" font-size="10.00">POINTER&#45;LINKED</text>
<text text-anchor="middle" x="406" y="-184" font-family="Helvetica,sans-Serif" font-size="10.00">pointer/source/chunk verified;</text>
<text text-anchor="middle" x="406" y="-173" font-family="Helvetica,sans-Serif" font-size="10.00">warrant didn&#39;t apply OR failed</text>
<text text-anchor="middle" x="406" y="-162" font-family="Helvetica,sans-Serif" font-size="10.00">for at least one claim</text>
<path fill="#ffc107" stroke="black" d="M151,-311C151,-311 12,-311 12,-311 6,-311 0,-305 0,-299 0,-299 0,-271 0,-271 0,-265 6,-259 12,-259 12,-259 151,-259 151,-259 157,-259 163,-265 163,-271 163,-271 163,-299 163,-299 163,-305 157,-311 151,-311"/>
<text text-anchor="middle" x="81.5" y="-299" font-family="Helvetica,sans-Serif" font-size="10.00">POINTER&#45;LINKED</text>
<text text-anchor="middle" x="81.5" y="-288" font-family="Helvetica,sans-Serif" font-size="10.00">pointer/source/chunk verified;</text>
<text text-anchor="middle" x="81.5" y="-277" font-family="Helvetica,sans-Serif" font-size="10.00">warrant didn&#39;t apply OR failed</text>
<text text-anchor="middle" x="81.5" y="-266" font-family="Helvetica,sans-Serif" font-size="10.00">for at least one claim</text>
</g>
<!-- has_warrant_miss&#45;&gt;pointer_linked -->
<g id="edge4" class="edge">
<title>has_warrant_miss&#45;&gt;pointer_linked</title>
<path fill="none" stroke="black" d="M383.87,-403.32C388.47,-357.34 397.48,-267.24 402.46,-217.35"/>
<polygon fill="black" stroke="black" points="405.95,-217.65 403.47,-207.35 398.99,-216.95 405.95,-217.65"/>
<text text-anchor="middle" x="407" y="-302.8" font-family="Helvetica,sans-Serif" font-size="9.00">yes</text>
<path fill="none" stroke="black" d="M228.89,-610.18C162.79,-597.56 79.22,-576.66 58.5,-549 7.82,-481.35 42.1,-374.67 65.23,-320.31"/>
<polygon fill="black" stroke="black" points="68.45,-321.67 69.25,-311.11 62.04,-318.87 68.45,-321.67"/>
<text text-anchor="middle" x="66.5" y="-450.8" font-family="Helvetica,sans-Serif" font-size="9.00">yes</text>
</g>
<!-- evidence_warranted -->
<g id="node6" class="node">
<title>evidence_warranted</title>
<path fill="#28a745" stroke="black" d="M120,-207C120,-207 12,-207 12,-207 6,-207 0,-201 0,-195 0,-195 0,-167 0,-167 0,-161 6,-155 12,-155 12,-155 120,-155 120,-155 126,-155 132,-161 132,-167 132,-167 132,-195 132,-195 132,-201 126,-207 120,-207"/>
<text text-anchor="middle" x="66" y="-195" font-family="Helvetica,sans-Serif" font-size="10.00" fill="white">EVIDENCE&#45;WARRANTED</text>
<text text-anchor="middle" x="66" y="-184" font-family="Helvetica,sans-Serif" font-size="10.00" fill="white">pointer verified +</text>
<text text-anchor="middle" x="66" y="-173" font-family="Helvetica,sans-Serif" font-size="10.00" fill="white">warrant ran &amp; passed +</text>
<text text-anchor="middle" x="66" y="-162" font-family="Helvetica,sans-Serif" font-size="10.00" fill="white">NO soft demotes</text>
<path fill="#28a745" stroke="black" d="M475.5,-311C475.5,-311 367.5,-311 367.5,-311 361.5,-311 355.5,-305 355.5,-299 355.5,-299 355.5,-271 355.5,-271 355.5,-265 361.5,-259 367.5,-259 367.5,-259 475.5,-259 475.5,-259 481.5,-259 487.5,-265 487.5,-271 487.5,-271 487.5,-299 487.5,-299 487.5,-305 481.5,-311 475.5,-311"/>
<text text-anchor="middle" x="421.5" y="-299" font-family="Helvetica,sans-Serif" font-size="10.00" fill="white">EVIDENCE&#45;WARRANTED</text>
<text text-anchor="middle" x="421.5" y="-288" font-family="Helvetica,sans-Serif" font-size="10.00" fill="white">pointer verified +</text>
<text text-anchor="middle" x="421.5" y="-277" font-family="Helvetica,sans-Serif" font-size="10.00" fill="white">warrant ran &amp; passed +</text>
<text text-anchor="middle" x="421.5" y="-266" font-family="Helvetica,sans-Serif" font-size="10.00" fill="white">NO soft demotes</text>
</g>
<!-- has_soft_demote&#45;&gt;evidence_warranted -->
<g id="edge7" class="edge">
<title>has_soft_demote&#45;&gt;evidence_warranted</title>
<path fill="none" stroke="black" d="M153.15,-265.06C135.89,-248.61 116.04,-229.69 99.64,-214.07"/>
<polygon fill="black" stroke="black" points="102.03,-211.51 92.38,-207.14 97.2,-216.57 102.03,-211.51"/>
<text text-anchor="middle" x="125" y="-227.8" font-family="Helvetica,sans-Serif" font-size="9.00">no</text>
<path fill="none" stroke="black" d="M362.99,-376.77C375.77,-356.94 388.94,-336.51 399.54,-320.07"/>
<polygon fill="black" stroke="black" points="402.67,-321.67 405.15,-311.37 396.79,-317.88 402.67,-321.67"/>
<text text-anchor="middle" x="398.5" y="-331.8" font-family="Helvetica,sans-Serif" font-size="9.00">no</text>
</g>
<!-- anchor_warranted -->
<g id="node7" class="node">
<title>anchor_warranted</title>
<path fill="#7cc66e" stroke="black" d="M294,-207C294,-207 162,-207 162,-207 156,-207 150,-201 150,-195 150,-195 150,-167 150,-167 150,-161 156,-155 162,-155 162,-155 294,-155 294,-155 300,-155 306,-161 306,-167 306,-167 306,-195 306,-195 306,-201 300,-207 294,-207"/>
<text text-anchor="middle" x="228" y="-195" font-family="Helvetica,sans-Serif" font-size="10.00">ANCHOR&#45;WARRANTED</text>
<text text-anchor="middle" x="228" y="-184" font-family="Helvetica,sans-Serif" font-size="10.00">pointer&#45;linked +</text>
<text text-anchor="middle" x="228" y="-173" font-family="Helvetica,sans-Serif" font-size="10.00">warrant passed where it ran;</text>
<text text-anchor="middle" x="228" y="-162" font-family="Helvetica,sans-Serif" font-size="10.00">soft demotes present</text>
<path fill="#7cc66e" stroke="black" d="M325.5,-311C325.5,-311 193.5,-311 193.5,-311 187.5,-311 181.5,-305 181.5,-299 181.5,-299 181.5,-271 181.5,-271 181.5,-265 187.5,-259 193.5,-259 193.5,-259 325.5,-259 325.5,-259 331.5,-259 337.5,-265 337.5,-271 337.5,-271 337.5,-299 337.5,-299 337.5,-305 331.5,-311 325.5,-311"/>
<text text-anchor="middle" x="259.5" y="-299" font-family="Helvetica,sans-Serif" font-size="10.00">ANCHOR&#45;WARRANTED</text>
<text text-anchor="middle" x="259.5" y="-288" font-family="Helvetica,sans-Serif" font-size="10.00">pointer&#45;linked +</text>
<text text-anchor="middle" x="259.5" y="-277" font-family="Helvetica,sans-Serif" font-size="10.00">warrant passed where it ran;</text>
<text text-anchor="middle" x="259.5" y="-266" font-family="Helvetica,sans-Serif" font-size="10.00">soft demotes present</text>
</g>
<!-- has_soft_demote&#45;&gt;anchor_warranted -->
<g id="edge6" class="edge">
<title>has_soft_demote&#45;&gt;anchor_warranted</title>
<path fill="none" stroke="black" d="M207.15,-256.83C210.82,-243.63 214.76,-229.52 218.21,-217.15"/>
<polygon fill="black" stroke="black" points="221.66,-217.79 220.97,-207.22 214.92,-215.91 221.66,-217.79"/>
<text text-anchor="middle" x="224" y="-227.8" font-family="Helvetica,sans-Serif" font-size="9.00">yes</text>
<path fill="none" stroke="black" d="M286.68,-368.03C281.15,-351.33 275.63,-334.69 271.03,-320.8"/>
<polygon fill="black" stroke="black" points="274.32,-319.61 267.85,-311.21 267.68,-321.81 274.32,-319.61"/>
<text text-anchor="middle" x="283.5" y="-331.8" font-family="Helvetica,sans-Serif" font-size="9.00">yes</text>
</g>
<!-- is_hybrid -->
<g id="node5" class="node">
<title>is_hybrid</title>
<path fill="#dddddd" stroke="black" d="M216.14,-116.17C216.14,-116.17 123.26,-101.83 123.26,-101.83 117.33,-100.92 117.33,-99.08 123.26,-98.17 123.26,-98.17 216.14,-83.83 216.14,-83.83 222.07,-82.92 233.93,-82.92 239.86,-83.83 239.86,-83.83 332.74,-98.17 332.74,-98.17 338.67,-99.08 338.67,-100.92 332.74,-101.83 332.74,-101.83 239.86,-116.17 239.86,-116.17 233.93,-117.08 222.07,-117.08 216.14,-116.17"/>
<text text-anchor="middle" x="228" y="-97.5" font-family="Helvetica,sans-Serif" font-size="10.00">audit_mode == HYBRID?</text>
<path fill="#dddddd" stroke="black" d="M177.64,-168.17C177.64,-168.17 84.76,-153.83 84.76,-153.83 78.83,-152.92 78.83,-151.08 84.76,-150.17 84.76,-150.17 177.64,-135.83 177.64,-135.83 183.57,-134.92 195.43,-134.92 201.36,-135.83 201.36,-135.83 294.24,-150.17 294.24,-150.17 300.17,-151.08 300.17,-152.92 294.24,-153.83 294.24,-153.83 201.36,-168.17 201.36,-168.17 195.43,-169.08 183.57,-169.08 177.64,-168.17"/>
<text text-anchor="middle" x="189.5" y="-149.5" font-family="Helvetica,sans-Serif" font-size="10.00">audit_mode == HYBRID?</text>
</g>
<!-- partial -->
<g id="node10" class="node">
<title>partial</title>
<polygon fill="#fff0e0" stroke="black" points="308.5,-36 141.5,-36 141.5,0 314.5,0 314.5,-30 308.5,-36"/>
<polyline fill="none" stroke="black" points="308.5,-36 308.5,-30 "/>
<polyline fill="none" stroke="black" points="314.5,-30 308.5,-30 "/>
<text text-anchor="middle" x="228" y="-21" font-family="Helvetica,sans-Serif" font-size="10.00">HYBRID → add `&#45;PARTIAL` suffix</text>
<text text-anchor="middle" x="228" y="-10" font-family="Helvetica,sans-Serif" font-size="10.00">on whichever rung applies</text>
<polygon fill="#fff0e0" stroke="black" points="270,-36 103,-36 103,0 276,0 276,-30 270,-36"/>
<polyline fill="none" stroke="black" points="270,-36 270,-30 "/>
<polyline fill="none" stroke="black" points="276,-30 270,-30 "/>
<text text-anchor="middle" x="189.5" y="-21" font-family="Helvetica,sans-Serif" font-size="10.00">HYBRID → add `&#45;PARTIAL` suffix</text>
<text text-anchor="middle" x="189.5" y="-10" font-family="Helvetica,sans-Serif" font-size="10.00">on whichever rung applies</text>
</g>
<!-- is_hybrid&#45;&gt;partial -->
<g id="edge11" class="edge">
<title>is_hybrid&#45;&gt;partial</title>
<path fill="none" stroke="black" stroke-dasharray="1,5" d="M228,-81.64C228,-71.3 228,-57.94 228,-46.22"/>
<polygon fill="black" stroke="black" points="231.5,-46.05 228,-36.05 224.5,-46.05 231.5,-46.05"/>
<text text-anchor="middle" x="236" y="-56.8" font-family="Helvetica,sans-Serif" font-size="9.00">yes</text>
<path fill="none" stroke="black" stroke-dasharray="1,5" d="M189.5,-133.74C189.5,-111.51 189.5,-72.6 189.5,-46.32"/>
<polygon fill="black" stroke="black" points="193,-46.26 189.5,-36.26 186,-46.26 193,-46.26"/>
<text text-anchor="middle" x="197.5" y="-56.8" font-family="Helvetica,sans-Serif" font-size="9.00">yes</text>
</g>
<!-- evidence_warranted&#45;&gt;is_hybrid -->
<g id="edge8" class="edge">
<title>evidence_warranted&#45;&gt;is_hybrid</title>
<path fill="none" stroke="black" stroke-dasharray="1,5" d="M117.7,-154.79C141.9,-142.99 170.13,-129.22 191.97,-118.57"/>
<polygon fill="black" stroke="black" points="193.76,-121.59 201.22,-114.06 190.7,-115.3 193.76,-121.59"/>
<path fill="none" stroke="black" stroke-dasharray="1,5" d="M377.04,-258.9C331.76,-233.33 262.6,-194.28 222.14,-171.43"/>
<polygon fill="black" stroke="black" points="223.66,-168.27 213.23,-166.4 220.22,-174.36 223.66,-168.27"/>
</g>
<!-- tail_tokens -->
<g id="node11" class="node">
<title>tail_tokens</title>
<polygon fill="#fff0e0" stroke="black" points="513,-222 324,-222 324,-82 519,-82 519,-216 513,-222"/>
<polyline fill="none" stroke="black" points="513,-222 513,-216 "/>
<polyline fill="none" stroke="black" points="519,-216 513,-216 "/>
<text text-anchor="middle" x="421.5" y="-210" font-family="Helvetica,sans-Serif" font-size="10.00">AUDIT&#45;LINE TAILS</text>
<text text-anchor="middle" x="421.5" y="-199" font-family="Helvetica,sans-Serif" font-size="10.00">appended to all rung labels:</text>
<text text-anchor="middle" x="421.5" y="-188" font-family="Helvetica,sans-Serif" font-size="10.00">#000008 quantifier guard:</text>
<text text-anchor="middle" x="421.5" y="-177" font-family="Helvetica,sans-Serif" font-size="10.00"> &#160;· broad cap N · broad rejected</text>
<text text-anchor="middle" x="421.5" y="-166" font-family="Helvetica,sans-Serif" font-size="10.00"> &#160;· broad unbounded · broad runaway</text>
<text text-anchor="middle" x="421.5" y="-155" font-family="Helvetica,sans-Serif" font-size="10.00">#000010 metacognition preflight:</text>
<text text-anchor="middle" x="421.5" y="-144" font-family="Helvetica,sans-Serif" font-size="10.00"> &#160;· false premise · contradictory</text>
<text text-anchor="middle" x="421.5" y="-133" font-family="Helvetica,sans-Serif" font-size="10.00"> &#160;· stale risk · out of corpus</text>
<text text-anchor="middle" x="421.5" y="-122" font-family="Helvetica,sans-Serif" font-size="10.00"> &#160;· frame ambiguous</text>
<text text-anchor="middle" x="421.5" y="-111" font-family="Helvetica,sans-Serif" font-size="10.00">classic verifier:</text>
<text text-anchor="middle" x="421.5" y="-100" font-family="Helvetica,sans-Serif" font-size="10.00"> &#160;· warrant missing · title mismatch</text>
<text text-anchor="middle" x="421.5" y="-89" font-family="Helvetica,sans-Serif" font-size="10.00"> &#160;· format collapsed</text>
</g>
<!-- evidence_warranted&#45;&gt;tail_tokens -->
<g id="edge12" class="edge">
<title>evidence_warranted&#45;&gt;tail_tokens</title>
<path fill="none" stroke="#888888" stroke-dasharray="5,2" d="M421.5,-258.74C421.5,-250.85 421.5,-241.69 421.5,-232.12"/>
<polygon fill="#888888" stroke="#888888" points="425,-232.04 421.5,-222.04 418,-232.04 425,-232.04"/>
</g>
<!-- anchor_warranted&#45;&gt;is_hybrid -->
<g id="edge9" class="edge">
<title>anchor_warranted&#45;&gt;is_hybrid</title>
<path fill="none" stroke="black" stroke-dasharray="1,5" d="M228,-154.57C228,-146.2 228,-136.85 228,-128.34"/>
<polygon fill="black" stroke="black" points="231.5,-128.15 228,-118.15 224.5,-128.15 231.5,-128.15"/>
<path fill="none" stroke="black" stroke-dasharray="1,5" d="M246,-258.74C233.5,-235.35 215.03,-200.77 202.64,-177.59"/>
<polygon fill="black" stroke="black" points="205.7,-175.89 197.9,-168.72 199.53,-179.19 205.7,-175.89"/>
</g>
<!-- anchor_warranted&#45;&gt;tail_tokens -->
<g id="edge13" class="edge">
<title>anchor_warranted&#45;&gt;tail_tokens</title>
<path fill="none" stroke="#888888" stroke-dasharray="5,2" d="M290.74,-258.74C301.73,-249.85 314.71,-239.35 328.16,-228.48"/>
<polygon fill="#888888" stroke="#888888" points="330.55,-231.05 336.13,-222.04 326.15,-225.6 330.55,-231.05"/>
</g>
<!-- pointer_linked&#45;&gt;is_hybrid -->
<g id="edge10" class="edge">
<title>pointer_linked&#45;&gt;is_hybrid</title>
<path fill="none" stroke="black" stroke-dasharray="1,5" d="M349.19,-154.79C321.88,-142.67 289.91,-128.48 265.66,-117.71"/>
<polygon fill="black" stroke="black" points="267,-114.48 256.44,-113.62 264.16,-120.88 267,-114.48"/>
<path fill="none" stroke="black" stroke-dasharray="1,5" d="M102.32,-258.74C121.98,-234.9 151.2,-199.45 170.3,-176.28"/>
<polygon fill="black" stroke="black" points="173.19,-178.29 176.85,-168.35 167.78,-173.84 173.19,-178.29"/>
</g>
<!-- pointer_linked&#45;&gt;tail_tokens -->
<g id="edge14" class="edge">
<title>pointer_linked&#45;&gt;tail_tokens</title>
<path fill="none" stroke="#888888" stroke-dasharray="5,2" d="M163.34,-261.46C166.43,-260.62 169.49,-259.8 172.5,-259 232.96,-242.87 253.5,-247.93 314.63,-222.12"/>
<polygon fill="#888888" stroke="#888888" points="316.17,-225.27 323.96,-218.08 313.39,-218.84 316.17,-225.27"/>
</g>
<!-- ungrounded&#45;&gt;tail_tokens -->
<g id="edge15" class="edge">
<title>ungrounded&#45;&gt;tail_tokens</title>
<path fill="none" stroke="#888888" stroke-dasharray="5,2" d="M542.24,-264.39C531.63,-254.6 518.05,-242.07 503.84,-228.96"/>
<polygon fill="#888888" stroke="#888888" points="506.09,-226.28 496.37,-222.07 501.35,-231.42 506.09,-226.28"/>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 17 KiB

Before After
Before After

View file

@ -75,7 +75,11 @@ make docs # runs `dot -Tsvg` and `-Tpng` on every docs/diagrams/*.dot
| [`qa/warrant.py`](../aborist/qa/warrant.py) | 5 anchor classes (proper-noun · date · count · entity-list · cause) | [](#qa-py) |
| [`qa/evidence.py`](../aborist/qa/evidence.py) | `EvidenceObject` + spotlight excerpt (density rank) | [](#qa-py) |
| [`qa/parse_claims.py`](../aborist/qa/parse_claims.py) | pointer-line parser (`claim. [E1,E2]`) | [](#qa-py) |
| [`qa/dag.py`](../aborist/qa/dag.py) | per-run Merkle-DAG (7-stage quote / 9-stage CTI) | [](#qa-py) |
| [`qa/quantifier.py`](../aborist/qa/quantifier.py) | 10-rung broad-quantifier intensity classifier (#000008) | [](#qa-py) |
| [`qa/model_profiles.py`](../aborist/qa/model_profiles.py) | per-model claim-cap profiles keyed on (intensity, model) | [](#qa-py) |
| [`qa/quantifier_reminder.py`](../aborist/qa/quantifier_reminder.py) | broad-query user-turn reminder text generator | [](#qa-py) |
| [`qa/metacognition.py`](../aborist/qa/metacognition.py) | `QuestionState` + 4 preflight detectors (#000010) | [](#qa-py) |
| [`qa/dag.py`](../aborist/qa/dag.py) | per-run Merkle-DAG (7/8 quote · 9/10 CTI · 3 reject) | [](#qa-py) |
| [`qa/inspect.py`](../aborist/qa/inspect.py) | sidecar diagnostic (read-only span classifier) | [](#qa-py) |
### Distillation
@ -993,21 +997,104 @@ so unsourced prose can't smuggle past the verifier.
#### `qa.dag` — per-run Merkle DAG
Commits each provenance step independently as a stage hash. Two
shapes:
Commits each provenance step independently as a stage hash. Five
shapes (post-#000009 preflight binding):
- **7-stage (quote mode):** question / retrieval / context /
prompt / answer / verify / final_label
- **9-stage (claim-lattice / CTI):** question / retrieval /
evidence_map / prompt / raw_answer / parsed_claim_lattice /
- **7-stage (quote mode, legacy):** question / retrieval /
context / prompt / answer / verify / final_label
- **8-stage (quote mode, post-#000009):** question / **preflight**
/ retrieval / context / prompt / answer / verify / final_label
- **9-stage (claim-lattice / CTI, legacy):** question / retrieval
/ evidence_map / prompt / raw_answer / parsed_claim_lattice /
verify / render / final_label
- **10-stage (claim-lattice / CTI, post-#000009):** question /
**preflight** / retrieval / evidence_map / prompt / raw_answer
/ parsed_claim_lattice / verify / render / final_label
- **3-stage (reject-broad early-return, post-#000009 §8):**
question / preflight / final_label. Built by
`build_reject_run_dag()` when the broad-quantifier guard
rejects before the LLM call. Audit replay can identify reject
rows by stage count alone.
The `preflight` stage payload (5 nested CTI clauses): `classifier`
(quantifier output), `answer_contract` (guard / cap / reject
state), `prompt_contract` (reminder enabled / injected / template
id), `evidence_contract` (exposure budget), `policy_refs`
(`governance_policy_hash`, `model_profile_hash`, `answer_mode`).
Plus `question_state` for the metacognition QuestionState
(#000010). Versioned via `PREFLIGHT_NODE_VERSION =
"preflight-node-v1"`.
The `run_dag_root` is persisted alongside every providence record;
`run_dag_blob` carries the full `{root, nodes}` JSON so an auditor
can recompute & verify any step.
can recompute & verify any step. Two cache rows that share the
same question + same model output + same verifier verdict but
different preflight policy state now produce **different**
`run_dag_root` values.
[`aborist/qa/dag.py`](../aborist/qa/dag.py)
#### `qa.quantifier` — broad-quantifier classifier (#000008)
Pure 10-rung intensity classifier mapping a question string onto
`{ABSENT, SINGULAR, FEW, MANY, ALL, COMPREHENSIVE, OPEN_REQUEST,
SMALL_NUM_EXPLICIT, COMPARATIVE_BOUND, PROPORTIONAL}`. Returns
`scope_bound_hint ∈ {bounded, unbounded, unknown}` so the
preflight stage can distinguish bounded universals (`name all
members of the Beatles`, naturally finite) from unbounded
(`winners of all major sports?`, undefined scope). Feeds the
preflight stage's `classifier` clause and the `answer_contract`
clause's `claim_cap_resolved` lookup. No I/O; no LLM.
[`aborist/qa/quantifier.py`](../aborist/qa/quantifier.py)
#### `qa.model_profiles` — per-model claim-cap profiles (#000008)
`PROFILES` dict mapping `(quantifier_intensity, model_id)`
`claim_count_cap`. `cap_for_intensity()` performs the lookup at
infer time; the resolved cap (and whether it actually applied)
gets stored in the run-DAG `answer_contract` clause for audit.
Six-level disable hierarchy: per-test override → per-call CLI
flag → per-phase policy → per-mode allowlist → per-model profile
→ master kill via `governance_policy_hash`.
[`aborist/qa/model_profiles.py`](../aborist/qa/model_profiles.py)
#### `qa.quantifier_reminder` — broad-query user-turn reminder (#000008)
`broad_quantifier_reminder()` synthesizes a one-line reminder for
broad questions when `quantifier_reminder_enabled=True` (default
for lattice modes). Two templates: `broad-quantifier-bounded-v1`
(when scope is corpus-known finite) and
`broad-quantifier-unbounded-v1` (under-specified scope; adds
"do not enumerate from training prior"). The reminder template
id lands in the run-DAG `prompt_contract` clause.
[`aborist/qa/quantifier_reminder.py`](../aborist/qa/quantifier_reminder.py)
#### `qa.metacognition` — meta-cognition preflight guard (#000010)
`QuestionState` dataclass + `preflight_question()` pure function
with four deterministic detectors (no LLM):
- `detect_temporal_sensitivity()``current` / `latest` /
`today` / `CEO` / etc. → high (stale-risk).
- `detect_contradiction()` — lexical pairs (unmarried+spouse,
always+never, alive+dead).
- `detect_false_premise()` — presupposition patterns
(`when did X stop Y?`, `how did X become Y?`).
- `detect_out_of_corpus()` — private/uploaded-document references.
8 LogicalStatus values, 3 PreflightResult values
(`PREFLIGHT_OK` / `_PARTIAL` / `_BLOCKED`). 6 policy fields all
default-on except `metacognition_block_on_contradiction`. Audit-
line tail tokens: `· false premise`, `· contradictory`, `· stale
risk`, `· out of corpus`, `· frame ambiguous`. CLI flags
`--no-preflight`, `--block-on-contradiction`. Feeds the preflight
stage's `question_state` clause.
[`aborist/qa/metacognition.py`](../aborist/qa/metacognition.py)
#### `qa.inspect` — read-only sidecar
Pulls source chunks for a given cache_key & classifies each

View file

@ -61,39 +61,61 @@ multiple frames acknowledged in the answer (literal vs
fictional-actual vs in-universe-propaganda) rather than picking one
frame and discarding the others.
- **Status**: ½ — phrase-route closed the **retrieval** side
(commit `1b8677d`); answer-side compilation pending.
- **Code anchors**: today, none. Future:
`aborist/qa/frame.py:detect_frame`, runtime-side polarity contract
emission.
- **Pinning tests**: today, only the phrase-route tests in
`test_query.py::test_phrase_match_surfaces_topical_doc`. Future:
per-shape frame-detector tests + multi-frame answer-shape live
fixtures.
- **Status**: ¾ — phrase-route closed the retrieval side
(commit `1b8677d`); pre-answer preflight contract (#000008
quantifier classifier + #000010 metacognition QuestionState)
landed 2026-05-03. Answer-side multi-frame compilation still
pending.
- **Code anchors**: `aborist/qa/quantifier.py:classify_question_quantifier`
(#000008), `aborist/qa/metacognition.py:preflight_question`
(#000010), `aborist/qa/dag.py:preflight_node_hash` /
`build_preflight_node_payload` (#000009 — five nested CTI
clauses bind into the run-DAG `preflight` stage). Future:
runtime-side polarity contract emission for multi-frame answers.
- **Pinning tests**: `tests/test_quantifier_classifier.py`
(10-rung intensity ladder, 70 tests), `tests/test_metacognition.py`
(4 detectors + governance + audit-line tails, 68 tests),
`tests/test_dag.py::test_preflight_*` (DAG binding, 9 tests).
Future: per-shape frame-detector tests + multi-frame answer-shape
live fixtures.
- **Open ticket**:
[#000002 Reference-Frame Polarity Contract](ticket-000002-reference-frame-polarity-contract.md).
- **Bench signal**: today, `phrase_match_surfaced` flag on bench rows
(true when phrase route fired). Once Module L lands, additionally
`frame_kind ∈ {literal, reference, ambiguous}`.
- **Bench signal**: lattice-mode bench rows now carry
`quantifier_intensity`, `quantifier_matched_token`,
`scope_bound_hint`, `preflight_logical_statuses`,
`preflight_question_shape`, `preflight_result`. Audit-line tails
surface five metacog kinds: `· false premise`, `· contradictory`,
`· stale risk`, `· out of corpus`, `· frame ambiguous`.
### D4 — Bind the retrieval map AND the evidence map
Provenance binding covers both *what got retrieved* (sources) and
*how retrieval got there* (the operator-influenceable inputs:
keywords, top_k, over_fetch, max_context_chars, shard set).
keywords, top_k, over_fetch, max_context_chars, shard set). Plus
the **preflight contract** governing the run (#000009 — guard /
cap / reminder / reject decisions hash-bound).
- **Status**: ½ — `evidence_map_root` lives in the 9-stage run-DAG
(`aborist/qa/dag.py`); retrieval-plan binding (the input side) is
the open work.
- **Code anchors**: `aborist/qa/dag.py:build_run_dag`,
`aborist/qa/evidence.py:evidence_map_root`.
- **Pinning tests**: `tests/test_qa_dag.py`,
`tests/test_evidence.py`.
- **Open ticket**:
[#000001 Retrieval-keywords audit gap](ticket-000001-retrieval-keywords-audit-gap.md).
- **Status**: ¾ — `evidence_map_root` lives in the run-DAG
(`aborist/qa/dag.py`); `retrieval_plan_hash` landed via #000001.
Preflight stage (#000009) added the upstream control commitment:
classifier output + answer/prompt/evidence contracts +
`governance_policy_hash` / `model_profile_hash` references all
fold into a single `preflight` Merkle leaf. Quote mode now 7→8
stages; pointer-mode CTI 9→10 stages; reject-broad path emits a
3-stage minimal DAG (`question → preflight → final_label`).
- **Code anchors**: `aborist/qa/dag.py:build_run_dag` (legacy +
preflight-extended shapes), `build_reject_run_dag` (3-stage),
`preflight_node_hash` / `build_preflight_node_payload` (5-clause
payload), `aborist/qa/evidence.py:evidence_map_root`.
- **Pinning tests**: `tests/test_dag.py` (24 tests including
preflight stage + reject path), `tests/test_evidence.py`.
- **Open ticket**: [#000001 Retrieval-keywords audit gap](ticket-000001-retrieval-keywords-audit-gap.md)
closed; future retrieval-side refinement still possible.
- **Bench signal**: every lattice-mode row has `run_dag_root`
populated; future bench column will report on `retrieval_plan_hash`
presence once #000001 lands.
populated. Two cache rows that share the same question + same
model output + same verifier verdict but different preflight
policy state now produce different `run_dag_root` values —
audit replay can pin the policy decision per row.
### D5 — Verify pointers deterministically
@ -197,16 +219,16 @@ gets layered on top.
## Status snapshot at landing
| # | Directive | Status | Tickets |
|---|----------------------------------------------|------------|-----------------|
| 1 | Stop making Hermes prove things | ✓ | |
| 2 | Hermes emits pointer clauses | ✓ | |
| 3 | Build CTI internally | ✓ | #000002 (closed)|
| 4 | Bind retrieval map AND evidence map | ✓ | #000001 (closed)|
| 5 | Verify pointers deterministically | ✓ | |
| 6 | Anchor-class warrant before NLI | ✓ | #000003 (closed)|
| 7 | Rename labels honestly | ✓ | #000005 (closed)|
| 8 | Automate only after test-pinning | discipline | #000004 (closed)|
| # | Directive | Status | Tickets |
|---|----------------------------------------------|------------|-------------------------------|
| 1 | Stop making Hermes prove things | ✓ | #000010 (closed) |
| 2 | Hermes emits pointer clauses | ✓ | |
| 3 | Build CTI internally | ✓ | #000002, #000008, #000010 (closed) |
| 4 | Bind retrieval map AND evidence map | ✓ | #000001, #000009 (closed) |
| 5 | Verify pointers deterministically | ✓ | |
| 6 | Anchor-class warrant before NLI | ✓ | #000003 (closed) |
| 7 | Rename labels honestly | ✓ | #000005 (closed) |
| 8 | Automate only after test-pinning | discipline | #000004 (closed) |
All seven structural directives now ✓:
@ -224,7 +246,43 @@ All seven structural directives now ✓:
D8 is the meta-discipline that gates how all of the above land;
the bench coverage substrate (#000004) is closed. Tests: 734
passed.
passed at the original snapshot.
### Post-landing addendum (2026-05-03 / 2026-05-04)
Three additional tickets landed extending D1, D3, and D4:
- **#000008** (closed `4f2b5a6`, 2026-05-03) — Broad-quantifier
preflight guard. New modules `aborist/qa/quantifier.py`,
`model_profiles.py`, `quantifier_reminder.py`. Seven new
policy fields fold into `governance_policy_hash`; six-level
disable hierarchy. Defaults flipped (after n=5 verification):
reminder default-on for lattice modes, cap default operator-
opt-in with JSON-only allowlist.
- **#000010** (closed, 2026-05-03) — Meta-Cognition Preflight
Guard. New module `aborist/qa/metacognition.py` with
`QuestionState` dataclass + four pure detectors (temporal,
contradiction, false-premise-lite, out-of-corpus). Six new
policy fields, all default-on except
`metacognition_block_on_contradiction`. Audit-line tail
tokens: `· false premise`, `· contradictory`, `· stale risk`,
`· out of corpus`, `· frame ambiguous`. Closes D1 by giving
the runtime explicit epistemic state to refuse from instead
of asking Hermes to self-regulate.
- **#000009** (closed `111dda6`, 2026-05-04) — Preflight run-DAG
node binding. Inserts `preflight` stage between `question` and
`retrieval`. Quote mode 7→8 stages; pointer-mode CTI 9→10
stages. Reject-broad early-return path emits a 3-stage minimal
DAG (`question → preflight → final_label`). Five nested CTI
clauses (classifier / answer_contract / prompt_contract /
evidence_contract / policy_refs) inside a single hashable
leaf. Closes D4 by Merkle-binding the upstream control
decisions that previously only appeared on result dicts.
Test count after these landings: **993 passing** (up from 734;
259 new across the three tickets). All seven directives remain ✓.
## Anti-regression test layer