arborist/docs/_source/_build/html/api/qa.html
russell@unturf.com 49607a5997
docs: add Sphinx API reference generation from docstrings
Implements Read the Docs infrastructure to generate API documentation
directly from code docstrings. Replaces static modules.md (1200+ lines).

New structure:
- docs/_source/conf.py — Sphinx configuration (furo theme)
- docs/_source/index.rst — Main TOC
- docs/_source/api/*.rst — Module groups (substrate, storage, retrieval,
  qa, distill, mesh, cli)
- docs/_source/Makefile — Local build targets
- docs/_source/README.md — Documentation on building and extending

Makefile integration:
- make docs-api — generate HTML (output: docs/_source/_build/html/)
- make docs-api-clean — remove build artifacts

Build output (40 HTML files):
- API module reference with docstrings
- Source code links (:viewcode: extension)
- Full-text search index
- Module index (genindex, py-modindex)

Sphinx installed in venv as dev dependency. HTML is browseable at
docs/_source/_build/html/index.html (open in browser after build).

This justifies the deletion of modules.md: code docstrings + Sphinx
autodoc = automatically-generated, always-current API reference.
2026-05-04 07:55:34 -04:00

2242 lines
No EOL
236 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!doctype html>
<html class="no-js" lang="en" data-content_root="../">
<head><meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="color-scheme" content="light dark"><meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="index" title="Index" href="../genindex.html"><link rel="search" title="Search" href="../search.html"><link rel="next" title="Distillation: surface → core compression" href="distill.html"><link rel="prev" title="Retrieval: FTS5 search and concepts" href="retrieval.html">
<!-- Generated with Sphinx 9.1.0 and Furo 2025.12.19 -->
<title>Q&amp;A Pipeline: question → answer → verify → cache - Aborist API Reference</title>
<link rel="stylesheet" type="text/css" href="../_static/pygments.css?v=d111a655" />
<link rel="stylesheet" type="text/css" href="../_static/styles/furo.css?v=7bdb33bb" />
<link rel="stylesheet" type="text/css" href="../_static/styles/furo-extensions.css?v=8dab3a3b" />
<style>
body {
--color-code-background: #f2f2f2;
--color-code-foreground: #1e1e1e;
}
@media not print {
body[data-theme="dark"] {
--color-code-background: #202020;
--color-code-foreground: #d0d0d0;
}
@media (prefers-color-scheme: dark) {
body:not([data-theme="light"]) {
--color-code-background: #202020;
--color-code-foreground: #d0d0d0;
}
}
}
</style></head>
<body>
<script>
document.body.dataset.theme = localStorage.getItem("theme") || "auto";
</script>
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
<symbol id="svg-toc" viewBox="0 0 24 24">
<title>Contents</title>
<svg stroke="currentColor" fill="currentColor" stroke-width="0" viewBox="0 0 1024 1024">
<path d="M408 442h480c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8H408c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8zm-8 204c0 4.4 3.6 8 8 8h480c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8H408c-4.4 0-8 3.6-8 8v56zm504-486H120c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h784c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zm0 632H120c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h784c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zM115.4 518.9L271.7 642c5.8 4.6 14.4.5 14.4-6.9V388.9c0-7.4-8.5-11.5-14.4-6.9L115.4 505.1a8.74 8.74 0 0 0 0 13.8z"/>
</svg>
</symbol>
<symbol id="svg-menu" viewBox="0 0 24 24">
<title>Menu</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor"
stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather-menu">
<line x1="3" y1="12" x2="21" y2="12"></line>
<line x1="3" y1="6" x2="21" y2="6"></line>
<line x1="3" y1="18" x2="21" y2="18"></line>
</svg>
</symbol>
<symbol id="svg-arrow-right" viewBox="0 0 24 24">
<title>Expand</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor"
stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather-chevron-right">
<polyline points="9 18 15 12 9 6"></polyline>
</svg>
</symbol>
<symbol id="svg-sun" viewBox="0 0 24 24">
<title>Light mode</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor"
stroke-width="1" stroke-linecap="round" stroke-linejoin="round" class="feather-sun">
<circle cx="12" cy="12" r="5"></circle>
<line x1="12" y1="1" x2="12" y2="3"></line>
<line x1="12" y1="21" x2="12" y2="23"></line>
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
<line x1="1" y1="12" x2="3" y2="12"></line>
<line x1="21" y1="12" x2="23" y2="12"></line>
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
</svg>
</symbol>
<symbol id="svg-moon" viewBox="0 0 24 24">
<title>Dark mode</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor"
stroke-width="1" stroke-linecap="round" stroke-linejoin="round" class="icon-tabler-moon">
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
<path d="M12 3c.132 0 .263 0 .393 0a7.5 7.5 0 0 0 7.92 12.446a9 9 0 1 1 -8.313 -12.454z" />
</svg>
</symbol>
<symbol id="svg-sun-with-moon" viewBox="0 0 24 24">
<title>Auto light/dark, in light mode</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor"
stroke-width="1" stroke-linecap="round" stroke-linejoin="round"
class="icon-custom-derived-from-feather-sun-and-tabler-moon">
<path style="opacity: 50%" d="M 5.411 14.504 C 5.471 14.504 5.532 14.504 5.591 14.504 C 3.639 16.319 4.383 19.569 6.931 20.352 C 7.693 20.586 8.512 20.551 9.25 20.252 C 8.023 23.207 4.056 23.725 2.11 21.184 C 0.166 18.642 1.702 14.949 4.874 14.536 C 5.051 14.512 5.231 14.5 5.411 14.5 L 5.411 14.504 Z"/>
<line x1="14.5" y1="3.25" x2="14.5" y2="1.25"/>
<line x1="14.5" y1="15.85" x2="14.5" y2="17.85"/>
<line x1="10.044" y1="5.094" x2="8.63" y2="3.68"/>
<line x1="19" y1="14.05" x2="20.414" y2="15.464"/>
<line x1="8.2" y1="9.55" x2="6.2" y2="9.55"/>
<line x1="20.8" y1="9.55" x2="22.8" y2="9.55"/>
<line x1="10.044" y1="14.006" x2="8.63" y2="15.42"/>
<line x1="19" y1="5.05" x2="20.414" y2="3.636"/>
<circle cx="14.5" cy="9.55" r="3.6"/>
</svg>
</symbol>
<symbol id="svg-moon-with-sun" viewBox="0 0 24 24">
<title>Auto light/dark, in dark mode</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor"
stroke-width="1" stroke-linecap="round" stroke-linejoin="round"
class="icon-custom-derived-from-feather-sun-and-tabler-moon">
<path d="M 8.282 7.007 C 8.385 7.007 8.494 7.007 8.595 7.007 C 5.18 10.184 6.481 15.869 10.942 17.24 C 12.275 17.648 13.706 17.589 15 17.066 C 12.851 22.236 5.91 23.143 2.505 18.696 C -0.897 14.249 1.791 7.786 7.342 7.063 C 7.652 7.021 7.965 7 8.282 7 L 8.282 7.007 Z"/>
<line style="opacity: 50%" x1="18" y1="3.705" x2="18" y2="2.5"/>
<line style="opacity: 50%" x1="18" y1="11.295" x2="18" y2="12.5"/>
<line style="opacity: 50%" x1="15.316" y1="4.816" x2="14.464" y2="3.964"/>
<line style="opacity: 50%" x1="20.711" y1="10.212" x2="21.563" y2="11.063"/>
<line style="opacity: 50%" x1="14.205" y1="7.5" x2="13.001" y2="7.5"/>
<line style="opacity: 50%" x1="21.795" y1="7.5" x2="23" y2="7.5"/>
<line style="opacity: 50%" x1="15.316" y1="10.184" x2="14.464" y2="11.036"/>
<line style="opacity: 50%" x1="20.711" y1="4.789" x2="21.563" y2="3.937"/>
<circle style="opacity: 50%" cx="18" cy="7.5" r="2.169"/>
</svg>
</symbol>
<symbol id="svg-pencil" viewBox="0 0 24 24">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor"
stroke-width="1" stroke-linecap="round" stroke-linejoin="round" class="icon-tabler-pencil-code">
<path d="M4 20h4l10.5 -10.5a2.828 2.828 0 1 0 -4 -4l-10.5 10.5v4" />
<path d="M13.5 6.5l4 4" />
<path d="M20 21l2 -2l-2 -2" />
<path d="M17 17l-2 2l2 2" />
</svg>
</symbol>
<symbol id="svg-eye" viewBox="0 0 24 24">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor"
stroke-width="1" stroke-linecap="round" stroke-linejoin="round" class="icon-tabler-eye-code">
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
<path d="M10 12a2 2 0 1 0 4 0a2 2 0 0 0 -4 0" />
<path
d="M11.11 17.958c-3.209 -.307 -5.91 -2.293 -8.11 -5.958c2.4 -4 5.4 -6 9 -6c3.6 0 6.6 2 9 6c-.21 .352 -.427 .688 -.647 1.008" />
<path d="M20 21l2 -2l-2 -2" />
<path d="M17 17l-2 2l2 2" />
</svg>
</symbol>
</svg>
<input type="checkbox" class="sidebar-toggle" name="__navigation" id="__navigation" aria-label="Toggle site navigation sidebar">
<input type="checkbox" class="sidebar-toggle" name="__toc" id="__toc" aria-label="Toggle table of contents sidebar">
<label class="overlay sidebar-overlay" for="__navigation"></label>
<label class="overlay toc-overlay" for="__toc"></label>
<a class="skip-to-content muted-link" href="#furo-main-content">Skip to content</a>
<div class="page">
<header class="mobile-header">
<div class="header-left">
<label class="nav-overlay-icon" for="__navigation">
<span class="icon"><svg><use href="#svg-menu"></use></svg></span>
</label>
</div>
<div class="header-center">
<a href="../index.html"><div class="brand">Aborist API Reference</div></a>
</div>
<div class="header-right">
<div class="theme-toggle-container theme-toggle-header">
<button class="theme-toggle" aria-label="Toggle Light / Dark / Auto color theme">
<svg class="theme-icon-when-auto-light"><use href="#svg-sun-with-moon"></use></svg>
<svg class="theme-icon-when-auto-dark"><use href="#svg-moon-with-sun"></use></svg>
<svg class="theme-icon-when-dark"><use href="#svg-moon"></use></svg>
<svg class="theme-icon-when-light"><use href="#svg-sun"></use></svg>
</button>
</div>
<label class="toc-overlay-icon toc-header-icon" for="__toc">
<span class="icon"><svg><use href="#svg-toc"></use></svg></span>
</label>
</div>
</header>
<aside class="sidebar-drawer">
<div class="sidebar-container">
<div class="sidebar-sticky"><div class="sidebar-tree">
<p class="caption" role="heading"><span class="caption-text">API Modules</span></p>
<ul class="current">
<li class="toctree-l1"><a class="reference internal" href="substrate.html">Substrate: Core data structures</a></li>
<li class="toctree-l1"><a class="reference internal" href="storage.html">Storage: SQLite schema and audit</a></li>
<li class="toctree-l1"><a class="reference internal" href="retrieval.html">Retrieval: FTS5 search and concepts</a></li>
<li class="toctree-l1 current current-page"><a class="current reference internal" href="#">Q&amp;A Pipeline: question → answer → verify → cache</a></li>
<li class="toctree-l1"><a class="reference internal" href="distill.html">Distillation: surface → core compression</a></li>
<li class="toctree-l1"><a class="reference internal" href="mesh.html">Federation: multiplayer aborist</a></li>
<li class="toctree-l1"><a class="reference internal" href="cli.html">CLI: Command-line interface</a></li>
</ul>
</div>
</div>
</div>
</aside>
<div class="main">
<div class="content">
<div class="article-container">
<a href="#" class="back-to-top muted-link">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
<path d="M13 20h-2V8l-5.5 5.5-1.42-1.42L12 4.16l7.92 7.92-1.42 1.42L13 8v12z"></path>
</svg>
<span>Back to top</span>
</a>
<div class="content-icon-container">
<div class="view-this-page">
<a class="muted-link" href="../_sources/api/qa.rst.txt" title="View this page">
<svg><use href="#svg-eye"></use></svg>
<span class="visually-hidden">View this page</span>
</a>
</div>
<div class="theme-toggle-container theme-toggle-content">
<button class="theme-toggle" aria-label="Toggle Light / Dark / Auto color theme">
<svg class="theme-icon-when-auto-light"><use href="#svg-sun-with-moon"></use></svg>
<svg class="theme-icon-when-auto-dark"><use href="#svg-moon-with-sun"></use></svg>
<svg class="theme-icon-when-dark"><use href="#svg-moon"></use></svg>
<svg class="theme-icon-when-light"><use href="#svg-sun"></use></svg>
</button>
</div>
<label class="toc-overlay-icon toc-content-icon" for="__toc">
<span class="icon"><svg><use href="#svg-toc"></use></svg></span>
</label>
</div>
<article role="main" id="furo-main-content">
<section id="q-a-pipeline-question-answer-verify-cache">
<h1>Q&amp;A Pipeline: question → answer → verify → cache<a class="headerlink" href="#q-a-pipeline-question-answer-verify-cache" title="Link to this heading"></a></h1>
<p>Question answering, caching, verification, evidence mapping.</p>
<section id="module-aborist.qa.keys">
<span id="keys"></span><h2>keys<a class="headerlink" href="#module-aborist.qa.keys" title="Link to this heading"></a></h2>
<p>The 8-dim Merkle-AGI v9.8 cache_key.</p>
<p>v9.8 invariant: no answer is reused unless all eight match and the
record is live (not failed/stale/quarantined):</p>
<blockquote>
<div><ol class="arabic simple">
<li><p>source_root — content fingerprint of the document</p></li>
<li><p>question_hash — SHA-256 of normalized question text</p></li>
<li><p>model_profile_hash — model_id + revision + quantization</p></li>
<li><p>conversation_hash — full canonical OpenAI messages array</p></li>
<li><p>governance_policy_hash — sampling/policy parameters dict</p></li>
<li><p>schema_version — aborist DB schema version</p></li>
<li><p>canonicalization_version — text normalization rules</p></li>
<li><p>chunking_version — chunker name &amp; parameters</p></li>
</ol>
</div></blockquote>
<p>Bumping ANY of these eight dimensions yields a distinct cache_key, so
prior records cannot be served. This is the runtime drift detection
the providence whitepaper compresses into “cache_key = source_root +
: + question_hash” — thats a simplification; the rigorous form is
all eight dimensions hashed together.</p>
<dl class="py function">
<dt class="sig sig-object py" id="aborist.qa.keys.canonical_question">
<span class="sig-prename descclassname"><span class="pre">aborist.qa.keys.</span></span><span class="sig-name descname"><span class="pre">canonical_question</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">question</span></span></em>, <em class="sig-param"><span class="keyword-only-separator o"><abbr title="Keyword-only parameters separator (PEP 3102)"><span class="pre">*</span></abbr></span></em>, <em class="sig-param"><span class="n"><span class="pre">mode</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">'equivalence_class'</span></span></em><span class="sig-paren">)</span><a class="reference internal" href="../_modules/aborist/qa/keys.html#canonical_question"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#aborist.qa.keys.canonical_question" title="Link to this definition"></a></dt>
<dd><p>Canonical form of <cite>question</cite> for the given dedup <code class="docutils literal notranslate"><span class="pre">mode</span></code>.</p>
<p>Two modes:</p>
<ul class="simple">
<li><p><code class="docutils literal notranslate"><span class="pre">&quot;equivalence_class&quot;</span></code> (default): four-step canonicalization —
<code class="docutils literal notranslate"><span class="pre">canonicalize()</span></code> (NFC + ws-collapse + strip ends), then
lowercase, then trailing-punctuation strip, then standalone-article
filter (<code class="docutils literal notranslate"><span class="pre">the</span></code>, <code class="docutils literal notranslate"><span class="pre">a</span></code>, <code class="docutils literal notranslate"><span class="pre">an</span></code>). All variants of “Who is THE
Batman?” / “who is batman” / “who is X.” collapse to one form.
The default for chat-style agents that prefer fast cache hits.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">&quot;strict&quot;</span></code>: only <code class="docutils literal notranslate"><span class="pre">canonicalize()</span></code> — NFC + ws-collapse + strip
ends. Case-sensitive, punctuation-sensitive, article-sensitive.
Maximum granularity. The choice for audit-grade agents that want
every distinct phrasing to get its own answer.</p></li>
</ul>
<p>Exposed as a function so callers can dedup BEFORE hashing — e.g.
inject the canonical form into the user message used for
<code class="docutils literal notranslate"><span class="pre">conversation_hash</span></code>, while still sending the verbatim question to
the LLM. Without this split <code class="docutils literal notranslate"><span class="pre">&quot;who</span> <span class="pre">is</span> <span class="pre">batman&quot;</span></code>, <code class="docutils literal notranslate"><span class="pre">&quot;who</span> <span class="pre">is</span>
<span class="pre">batman?&quot;</span></code>, and <code class="docutils literal notranslate"><span class="pre">&quot;who</span> <span class="pre">is</span> <span class="pre">the</span> <span class="pre">batman?&quot;</span></code> collapse on
<code class="docutils literal notranslate"><span class="pre">question_hash</span></code> (under equivalence_class) but each hits
<code class="docutils literal notranslate"><span class="pre">conversation_hash</span></code> differently, missing cache.</p>
<p>The choice of mode flows through <code class="docutils literal notranslate"><span class="pre">policy[&quot;question_dedup&quot;]</span></code> into
<code class="docutils literal notranslate"><span class="pre">governance_policy_hash</span></code> so two agents under different modes
write records under different <a href="#id1"><span class="problematic" id="id2">``</span></a>cache_key``s — they coexist in
parallel namespaces, never collide.</p>
<dl class="field-list simple">
<dt class="field-odd">Parameters<span class="colon">:</span></dt>
<dd class="field-odd"><ul class="simple">
<li><p><strong>question</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.14)"><em>str</em></a>)</p></li>
<li><p><strong>mode</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.14)"><em>str</em></a>)</p></li>
</ul>
</dd>
<dt class="field-even">Return type<span class="colon">:</span></dt>
<dd class="field-even"><p><a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.14)">str</a></p>
</dd>
</dl>
</dd></dl>
<dl class="py function">
<dt class="sig sig-object py" id="aborist.qa.keys.question_hash">
<span class="sig-prename descclassname"><span class="pre">aborist.qa.keys.</span></span><span class="sig-name descname"><span class="pre">question_hash</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">question</span></span></em>, <em class="sig-param"><span class="keyword-only-separator o"><abbr title="Keyword-only parameters separator (PEP 3102)"><span class="pre">*</span></abbr></span></em>, <em class="sig-param"><span class="n"><span class="pre">mode</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">'equivalence_class'</span></span></em><span class="sig-paren">)</span><a class="reference internal" href="../_modules/aborist/qa/keys.html#question_hash"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#aborist.qa.keys.question_hash" title="Link to this definition"></a></dt>
<dd><p>SHA-256 of the dedup-mode-canonicalized question.</p>
<p>See <code class="docutils literal notranslate"><span class="pre">canonical_question</span></code> for what each mode does. The hash is the
SHA-256 of the canonical form. Bumping
<code class="docutils literal notranslate"><span class="pre">_QUESTION_TRAILING_STRIP</span></code> or <code class="docutils literal notranslate"><span class="pre">_QUESTION_ARTICLE_STRIP</span></code> (the
equivalence-class strip sets) orphans prior cache records whose
canonical question contained newly-stripped tokens; they live as
history but wont be re-hit on lookup.</p>
<p>Equivalence class examples (mode=”equivalence_class”):</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="s2">&quot;who is X&quot;</span> <span class="o">|</span>
<span class="s2">&quot;who is X?&quot;</span> <span class="o">|</span>
<span class="s2">&quot;Who Is X.&quot;</span> <span class="o">|</span> <span class="o">-&gt;</span> <span class="n">same</span> <span class="n">question_hash</span>
<span class="s2">&quot;who is the X&quot;</span> <span class="o">|</span>
<span class="s2">&quot;who is a X&quot;</span> <span class="o">|</span>
<span class="s2">&quot;who is an X&quot;</span> <span class="o">|</span> <span class="p">(</span><span class="n">CJK</span> <span class="n">question</span> <span class="n">mark</span><span class="p">)</span>
</pre></div>
</div>
<p>Strict mode (mode=”strict”) distinguishes all of those.</p>
<p>Whats IN the trailing-strip set: <code class="docutils literal notranslate"><span class="pre">.?!,;:</span></code> (ASCII), <code class="docutils literal notranslate"><span class="pre">?!。、</span></code>
(CJK full-width), <code class="docutils literal notranslate"><span class="pre"></span></code> (ellipsis). Pairs like <code class="docutils literal notranslate"><span class="pre">&quot;</span></code> <code class="docutils literal notranslate"><span class="pre">'</span></code> <code class="docutils literal notranslate"><span class="pre">)</span></code>
<code class="docutils literal notranslate"><span class="pre">]</span></code> <code class="docutils literal notranslate"><span class="pre">}</span></code> are NOT — naive one-sided stripping breaks balance.
Apostrophes arent either — <code class="docutils literal notranslate"><span class="pre">X's</span></code> is a different question from
<code class="docutils literal notranslate"><span class="pre">X</span></code>.</p>
<dl class="field-list simple">
<dt class="field-odd">Parameters<span class="colon">:</span></dt>
<dd class="field-odd"><ul class="simple">
<li><p><strong>question</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.14)"><em>str</em></a>)</p></li>
<li><p><strong>mode</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.14)"><em>str</em></a>)</p></li>
</ul>
</dd>
<dt class="field-even">Return type<span class="colon">:</span></dt>
<dd class="field-even"><p><a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.14)">str</a></p>
</dd>
</dl>
</dd></dl>
<dl class="py function">
<dt class="sig sig-object py" id="aborist.qa.keys.model_profile_hash">
<span class="sig-prename descclassname"><span class="pre">aborist.qa.keys.</span></span><span class="sig-name descname"><span class="pre">model_profile_hash</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">model_id</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">revision</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">''</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">quantization</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">''</span></span></em><span class="sig-paren">)</span><a class="reference internal" href="../_modules/aborist/qa/keys.html#model_profile_hash"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#aborist.qa.keys.model_profile_hash" title="Link to this definition"></a></dt>
<dd><p>SHA-256 of model identity. Bumping any field bumps the cache key.</p>
<dl class="field-list simple">
<dt class="field-odd">Parameters<span class="colon">:</span></dt>
<dd class="field-odd"><ul class="simple">
<li><p><strong>model_id</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.14)"><em>str</em></a>)</p></li>
<li><p><strong>revision</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.14)"><em>str</em></a>)</p></li>
<li><p><strong>quantization</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.14)"><em>str</em></a>)</p></li>
</ul>
</dd>
<dt class="field-even">Return type<span class="colon">:</span></dt>
<dd class="field-even"><p><a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.14)">str</a></p>
</dd>
</dl>
</dd></dl>
<dl class="py function">
<dt class="sig sig-object py" id="aborist.qa.keys.conversation_hash">
<span class="sig-prename descclassname"><span class="pre">aborist.qa.keys.</span></span><span class="sig-name descname"><span class="pre">conversation_hash</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">messages</span></span></em><span class="sig-paren">)</span><a class="reference internal" href="../_modules/aborist/qa/keys.html#conversation_hash"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#aborist.qa.keys.conversation_hash" title="Link to this definition"></a></dt>
<dd><p>SHA-256 of canonical JSON of the full OpenAI messages array.</p>
<p>Order matters: a 6-turn dialogue arriving at the same final question
produces a different hash than a single-turn ask.</p>
<dl class="field-list simple">
<dt class="field-odd">Parameters<span class="colon">:</span></dt>
<dd class="field-odd"><p><strong>messages</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#list" title="(in Python v3.14)"><em>list</em></a><em>[</em><a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#dict" title="(in Python v3.14)"><em>dict</em></a><em>]</em>)</p>
</dd>
<dt class="field-even">Return type<span class="colon">:</span></dt>
<dd class="field-even"><p><a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.14)">str</a></p>
</dd>
</dl>
</dd></dl>
<dl class="py function">
<dt class="sig sig-object py" id="aborist.qa.keys.governance_policy_hash">
<span class="sig-prename descclassname"><span class="pre">aborist.qa.keys.</span></span><span class="sig-name descname"><span class="pre">governance_policy_hash</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">policy</span></span></em><span class="sig-paren">)</span><a class="reference internal" href="../_modules/aborist/qa/keys.html#governance_policy_hash"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#aborist.qa.keys.governance_policy_hash" title="Link to this definition"></a></dt>
<dd><p>SHA-256 of canonical JSON of the sampling/policy dict.</p>
<p>Includes temperature, top_p, max_tokens, and the system prompt — any
of those changing means the answer is governed differently and the
cache must miss.</p>
<dl class="field-list simple">
<dt class="field-odd">Parameters<span class="colon">:</span></dt>
<dd class="field-odd"><p><strong>policy</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#dict" title="(in Python v3.14)"><em>dict</em></a>)</p>
</dd>
<dt class="field-even">Return type<span class="colon">:</span></dt>
<dd class="field-even"><p><a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.14)">str</a></p>
</dd>
</dl>
</dd></dl>
<dl class="py function">
<dt class="sig sig-object py" id="aborist.qa.keys.verifier_policy_hash">
<span class="sig-prename descclassname"><span class="pre">aborist.qa.keys.</span></span><span class="sig-name descname"><span class="pre">verifier_policy_hash</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">policy</span></span></em><span class="sig-paren">)</span><a class="reference internal" href="../_modules/aborist/qa/keys.html#verifier_policy_hash"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#aborist.qa.keys.verifier_policy_hash" title="Link to this definition"></a></dt>
<dd><p>SHA-256 of canonical JSON of the verifier-relevant subset of policy.</p>
<p>Pulls <cite>_VERIFIER_POLICY_FIELDS</cite> out of <cite>policy</cite> and hashes only
those. Empty dict → constant hash (<cite>sha256(“{}”)</cite>). Folded into
<cite>cache_key</cite> as a 9th dimension so a verifier-policy change is
observable from the cache_key alone, separate from
<cite>governance_policy_hash</cite> which folds in temperature / top_p /
prompts.</p>
<p>The two hashes overlap (verifier fields ARE in the broader policy
dict and so contribute to governance_policy_hash too). Thats
intentional — bumping a verifier rule bumps BOTH dimensions.
Bumping a non-verifier field (e.g. temperature) bumps ONLY
governance_policy_hash. The asymmetry is what makes the audit
legible: which dimension changed answers a question that scanning
the whole policy dict cannot.</p>
<dl class="field-list simple">
<dt class="field-odd">Parameters<span class="colon">:</span></dt>
<dd class="field-odd"><p><strong>policy</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#dict" title="(in Python v3.14)"><em>dict</em></a>)</p>
</dd>
<dt class="field-even">Return type<span class="colon">:</span></dt>
<dd class="field-even"><p><a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.14)">str</a></p>
</dd>
</dl>
</dd></dl>
<dl class="py function">
<dt class="sig sig-object py" id="aborist.qa.keys.cache_key">
<span class="sig-prename descclassname"><span class="pre">aborist.qa.keys.</span></span><span class="sig-name descname"><span class="pre">cache_key</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">source_root</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">question_hash_value</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">model_profile_hash_value</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">conversation_hash_value</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">governance_policy_hash_value</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">schema_version</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">canonicalization_version</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">chunking_version</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">verifier_policy_hash_value</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em><span class="sig-paren">)</span><a class="reference internal" href="../_modules/aborist/qa/keys.html#cache_key"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#aborist.qa.keys.cache_key" title="Link to this definition"></a></dt>
<dd><p>SHA-256 of the cache-identity dimensions joined with |.</p>
<p>8-dim form (legacy): omit <cite>verifier_policy_hash_value</cite> (or pass
None). The result matches pre-2026-05-01 cache identity and
keeps backward compatibility with cached records written before
the 9th dimension landed.</p>
<p>9-dim form: pass <cite>verifier_policy_hash_value</cite> explicitly. Records
written under the 9-dim form bind to the verifier-policy
identity; lookups with a different verifier_policy_hash miss.
The 9th dimension is the explicit “did the verifier rules
change?” gate.</p>
<p>Any drift in any dimension produces a distinct cache_key.</p>
<dl class="field-list simple">
<dt class="field-odd">Parameters<span class="colon">:</span></dt>
<dd class="field-odd"><ul class="simple">
<li><p><strong>source_root</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.14)"><em>str</em></a>)</p></li>
<li><p><strong>question_hash_value</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.14)"><em>str</em></a>)</p></li>
<li><p><strong>model_profile_hash_value</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.14)"><em>str</em></a>)</p></li>
<li><p><strong>conversation_hash_value</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.14)"><em>str</em></a>)</p></li>
<li><p><strong>governance_policy_hash_value</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.14)"><em>str</em></a>)</p></li>
<li><p><strong>schema_version</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.14)"><em>str</em></a>)</p></li>
<li><p><strong>canonicalization_version</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.14)"><em>str</em></a>)</p></li>
<li><p><strong>chunking_version</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.14)"><em>str</em></a>)</p></li>
<li><p><strong>verifier_policy_hash_value</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.14)"><em>str</em></a><em> | </em><em>None</em>)</p></li>
</ul>
</dd>
<dt class="field-even">Return type<span class="colon">:</span></dt>
<dd class="field-even"><p><a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.14)">str</a></p>
</dd>
</dl>
</dd></dl>
</section>
<section id="module-aborist.qa.runner">
<span id="runner"></span><h2>runner<a class="headerlink" href="#module-aborist.qa.runner" title="Link to this heading"></a></h2>
<p>Q&amp;A runner: cache-first lookup -&gt; inference fallback -&gt; provable record.</p>
<dl class="simple">
<dt>Implements the v9.8 admissibility invariant:</dt><dd><p>No record reused unless all 8 cache_key dimensions match AND state
is live (not failed/stale/quarantined).</p>
</dd>
</dl>
<p>Cache hit -&gt; persisted audit_mode (STRICT/HYBRID/UNGROUNDED).
Cache miss -&gt; call ChatClient, run faithfulness check, classify, store</p>
<blockquote>
<div><p>record, audit event.</p>
</div></blockquote>
<dl class="py function">
<dt class="sig sig-object py" id="aborist.qa.runner.ask">
<span class="sig-prename descclassname"><span class="pre">aborist.qa.runner.</span></span><span class="sig-name descname"><span class="pre">ask</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">conn</span></span></em>, <em class="sig-param"><span class="keyword-only-separator o"><abbr title="Keyword-only parameters separator (PEP 3102)"><span class="pre">*</span></abbr></span></em>, <em class="sig-param"><span class="n"><span class="pre">document_root</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">question</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">client</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">model_id</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">revision</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">''</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">quantization</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">''</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">policy</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">chain</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">'private'</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">fidelity</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em><span class="sig-paren">)</span><a class="reference internal" href="../_modules/aborist/qa/runner.html#ask"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#aborist.qa.runner.ask" title="Link to this definition"></a></dt>
<dd><p>Look up cached answer or run inference. Returns a result dict.</p>
<p>See <code class="docutils literal notranslate"><span class="pre">aborist.qa.query.query</span></code> for <cite>fidelity</cite> semantics — it
controls lookup tolerance: <code class="docutils literal notranslate"><span class="pre">&quot;strict&quot;</span></code> only checks the cache_key
matching the calls <code class="docutils literal notranslate"><span class="pre">policy[&quot;question_dedup&quot;]</span></code>; the default
<code class="docutils literal notranslate"><span class="pre">&quot;equivalence_class&quot;</span></code> falls back to the alternate dedup modes
cache_key on miss so a fast-cache agent can reuse records written
under either mode. Result includes <code class="docutils literal notranslate"><span class="pre">lookup_path</span></code>.</p>
<dl class="field-list simple">
<dt class="field-odd">Parameters<span class="colon">:</span></dt>
<dd class="field-odd"><ul class="simple">
<li><p><strong>conn</strong> (<a class="reference external" href="https://docs.python.org/3/library/sqlite3.html#sqlite3.Connection" title="(in Python v3.14)"><em>Connection</em></a>)</p></li>
<li><p><strong>document_root</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.14)"><em>str</em></a>)</p></li>
<li><p><strong>question</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.14)"><em>str</em></a>)</p></li>
<li><p><strong>client</strong> (<a class="reference internal" href="#aborist.qa.client.ChatClient" title="aborist.qa.client.ChatClient"><em>ChatClient</em></a>)</p></li>
<li><p><strong>model_id</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.14)"><em>str</em></a>)</p></li>
<li><p><strong>revision</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.14)"><em>str</em></a>)</p></li>
<li><p><strong>quantization</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.14)"><em>str</em></a>)</p></li>
<li><p><strong>policy</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#dict" title="(in Python v3.14)"><em>dict</em></a><em> | </em><em>None</em>)</p></li>
<li><p><strong>chain</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.14)"><em>str</em></a>)</p></li>
<li><p><strong>fidelity</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.14)"><em>str</em></a><em> | </em><em>None</em>)</p></li>
</ul>
</dd>
<dt class="field-even">Return type<span class="colon">:</span></dt>
<dd class="field-even"><p><a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#dict" title="(in Python v3.14)">dict</a></p>
</dd>
</dl>
</dd></dl>
</section>
<section id="module-aborist.qa.query">
<span id="query"></span><h2>query<a class="headerlink" href="#module-aborist.qa.query" title="Link to this heading"></a></h2>
<p>Multi-source corpus Q&amp;A.</p>
<p>Pose a question, the tree finds related cached docs, assembles them as context,
asks Hermes, caches the answer.</p>
<dl>
<dt>The flow:</dt><dd><ol class="arabic">
<li><p>FTS5 search across all shards (chunks_fts cant be UNIONd in views,
so we query each shards index independently and merge by score).</p></li>
<li><p>Title-boost rerank: hits whose title contains query tokens get a
score bump. Title is a strong topical signal that BM25 alone misses
(BM25 favors short docs with rare body tokens — Tell_(poker) outranks
Back_to_the_Future without a title boost).</p></li>
<li><p>Pick top-K distinct documents within a character budget.</p></li>
<li><p>Compute <cite>context_root</cite> = Merkle root over the sorted source
document_roots — thats the “source” dimension of v9.8s 8-dim
cache_key for this multi-source answer.</p></li>
<li><p>Cache lookup; hit returns the persisted audit_mode.</p></li>
<li><p>Miss calls Hermes via the OpenAI-compatible client, then runs the
faithfulness check (<cite>verify_quotes</cite>) — every double-quoted span in
the answer is verbatim-matched against the assembled context.
Result classifies the answer:</p>
<blockquote>
<div><p>STRICT every quote (&gt;=1) verified against context
HYBRID some claims sourced, some emergent (training-derived)
UNGROUNDED no quotes verify — purely emergent</p>
</div></blockquote>
</li>
<li><p>Persist record with merkle_proof = {context_root, sources: […]},
audit_mode, and unverified_quotes (the spans the model produced
that didnt appear in any source — corpus-growth signal).</p></li>
</ol>
</dd>
</dl>
<p>Per-source proofs are not bundled here (the source roots themselves are
already content-addressed). A verifier asks the shards for any specific
chunks proof on demand.</p>
<dl class="py function">
<dt class="sig sig-object py" id="aborist.qa.query.query">
<span class="sig-prename descclassname"><span class="pre">aborist.qa.query.</span></span><span class="sig-name descname"><span class="pre">query</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="keyword-only-separator o"><abbr title="Keyword-only parameters separator (PEP 3102)"><span class="pre">*</span></abbr></span></em>, <em class="sig-param"><span class="n"><span class="pre">question</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">qa_db</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">chat_client</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">model_id</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">revision</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">''</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">quantization</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">''</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">shards_dir</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">single_db</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">top_k</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">8</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">over_fetch</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">32</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">max_context_chars</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">policy</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">chain</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">'private'</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">fidelity</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">burn_existing</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">False</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">retrieval_keywords</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em><span class="sig-paren">)</span><a class="reference internal" href="../_modules/aborist/qa/query.html#query"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#aborist.qa.query.query" title="Link to this definition"></a></dt>
<dd><p>Answer <cite>question</cite> using the corpus. Cache to qa_db. Returns a result dict.</p>
<p><cite>fidelity</cite> controls lookup tolerance — see <code class="docutils literal notranslate"><span class="pre">FIDELITY_MODES</span></code> in
<code class="docutils literal notranslate"><span class="pre">aborist.qa.keys</span></code>. <code class="docutils literal notranslate"><span class="pre">&quot;strict&quot;</span></code> checks only the cache_key
matching this calls <code class="docutils literal notranslate"><span class="pre">policy[&quot;question_dedup&quot;]</span></code>. <code class="docutils literal notranslate"><span class="pre">&quot;equivalence_class&quot;</span></code>
(default) tries the primary cache_key first, then the alternate
dedup-mode cache_key as a fallback so a fast-cache agent can reuse
a record written under either mode. Result includes <code class="docutils literal notranslate"><span class="pre">lookup_path</span></code>
naming which key matched (or <code class="docutils literal notranslate"><span class="pre">&quot;miss&quot;</span></code> when the LLM ran).</p>
<p><cite>burn_existing=True</cite> deletes the matching live providence_cache row
(under the primary dedup-mode cache_key) BEFORE the cache lookup,
forcing a fresh inference. Each burn writes a <code class="docutils literal notranslate"><span class="pre">providence_burn</span></code>
audit event. Test-ergonomic: run <cite>make query Q=… BURN=1</cite> after
tweaking a knob to see the new behavior without finding cache_keys
by hand. Result includes <code class="docutils literal notranslate"><span class="pre">burned_existing</span></code> reporting how many
rows were deleted (0 or 1 for the primary key; the equivalence-
class fallback key is left alone so prior alt-mode records stay
historic).</p>
<p><cite>retrieval_keywords</cite> augments the FTS5 search and title-filter
token set with operator-supplied keywords WITHOUT changing what
the LLM sees as its question or what the verifier checks.
Empirically observed 2026-05-01: long discursive questions like
what technology is currently or soon available which may enable
one person to reconstruct another persons thoughts… under-
retrieve because their content tokens get diluted by template
phrasing. Appending domain keywords (transcranial knowledge
acquisition) narrows OR-mode FTS5 to the topical article
(Neurotechnology) and lifts the verdict from HYBRID to STRICT.</p>
<p>Keywords do NOT enter <code class="docutils literal notranslate"><span class="pre">question_hash</span></code> directly, but they DO
change which sources get chosen — and that re-routes the
<code class="docutils literal notranslate"><span class="pre">context_root</span></code> and <code class="docutils literal notranslate"><span class="pre">conversation_hash</span></code> components of
<code class="docutils literal notranslate"><span class="pre">cache_key</span></code>. Two calls with the same question and different
keywords therefore land under different cache_keys (different
contexts, different cached records — correctly so). Pair with
<code class="docutils literal notranslate"><span class="pre">burn_existing=True</span></code> to force fresh inference when iterating
on keyword sets.</p>
<dl class="field-list simple">
<dt class="field-odd">Parameters<span class="colon">:</span></dt>
<dd class="field-odd"><ul class="simple">
<li><p><strong>question</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.14)"><em>str</em></a>)</p></li>
<li><p><strong>qa_db</strong> (<a class="reference external" href="https://docs.python.org/3/library/pathlib.html#pathlib.Path" title="(in Python v3.14)"><em>Path</em></a>)</p></li>
<li><p><strong>chat_client</strong> (<a class="reference internal" href="#aborist.qa.client.ChatClient" title="aborist.qa.client.ChatClient"><em>ChatClient</em></a>)</p></li>
<li><p><strong>model_id</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.14)"><em>str</em></a>)</p></li>
<li><p><strong>revision</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.14)"><em>str</em></a>)</p></li>
<li><p><strong>quantization</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.14)"><em>str</em></a>)</p></li>
<li><p><strong>shards_dir</strong> (<a class="reference external" href="https://docs.python.org/3/library/pathlib.html#pathlib.Path" title="(in Python v3.14)"><em>Path</em></a><em> | </em><em>None</em>)</p></li>
<li><p><strong>single_db</strong> (<a class="reference external" href="https://docs.python.org/3/library/pathlib.html#pathlib.Path" title="(in Python v3.14)"><em>Path</em></a><em> | </em><em>None</em>)</p></li>
<li><p><strong>top_k</strong> (<a class="reference external" href="https://docs.python.org/3/library/functions.html#int" title="(in Python v3.14)"><em>int</em></a>)</p></li>
<li><p><strong>over_fetch</strong> (<a class="reference external" href="https://docs.python.org/3/library/functions.html#int" title="(in Python v3.14)"><em>int</em></a>)</p></li>
<li><p><strong>max_context_chars</strong> (<a class="reference external" href="https://docs.python.org/3/library/functions.html#int" title="(in Python v3.14)"><em>int</em></a><em> | </em><em>None</em>)</p></li>
<li><p><strong>policy</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#dict" title="(in Python v3.14)"><em>dict</em></a><em> | </em><em>None</em>)</p></li>
<li><p><strong>chain</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.14)"><em>str</em></a>)</p></li>
<li><p><strong>fidelity</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.14)"><em>str</em></a><em> | </em><em>None</em>)</p></li>
<li><p><strong>burn_existing</strong> (<a class="reference external" href="https://docs.python.org/3/library/functions.html#bool" title="(in Python v3.14)"><em>bool</em></a>)</p></li>
<li><p><strong>retrieval_keywords</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.14)"><em>str</em></a><em> | </em><em>None</em>)</p></li>
</ul>
</dd>
<dt class="field-even">Return type<span class="colon">:</span></dt>
<dd class="field-even"><p><a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#dict" title="(in Python v3.14)">dict</a></p>
</dd>
</dl>
</dd></dl>
</section>
<section id="module-aborist.qa.verify">
<span id="verify"></span><h2>verify<a class="headerlink" href="#module-aborist.qa.verify" title="Link to this heading"></a></h2>
<p>Post-LLM faithfulness check: did the answer ground its claims in context?</p>
<p>Three layered strategies, tried in order. The first one that finds evidence
classifies the answer. <cite>verifier_method</cite> on the result records which path
fired so the audit chain stays diagnostic.</p>
<blockquote>
<div><ol class="arabic simple">
<li><dl class="simple">
<dt>quote model wrapped claims in double quotes per system prompt.</dt><dd><p>Strongest signal — explicit, verbatim, model-asserted.</p>
</dd>
</dl>
</li>
<li><dl class="simple">
<dt>span no quotes, but bullet/sentence-level lines from the answer</dt><dd><p>appear verbatim in context. Catches models that quote
inline without “…” marks.</p>
</dd>
</dl>
</li>
<li><dl class="simple">
<dt>entity no quotes and no span match, but multi-word proper-noun</dt><dd><p>phrases from the answer appear verbatim in context.
Catches the Wikipedia-infobox-to-prose case: the model
paraphrases structure so spans diverge, but every named
entity is intact and grounded.</p>
</dd>
</dl>
</li>
</ol>
</div></blockquote>
<p>Each strategy classifies into v9.8s audit-mode trichotomy (RAG-adapted
vocabulary; substrate calls UNGROUNDED “VISUAL”):</p>
<blockquote>
<div><p>STRICT every evidence unit (&gt;=1) verifies verbatim against context
HYBRID some verify, others do not (mixed source / emergent)
UNGROUNDED no evidence, or none verify (purely emergent)</p>
</div></blockquote>
<p><cite>unverified_quotes</cite> (kept under that name for schema continuity) collects
spans the model produced that dont appear in any source — the
corpus-growth signal mined by <cite>aborist emergent</cite>.</p>
<p>Hard rule (CLAUDE.md “soft hash vs hard hash”): every check is a lexical
substring test under norm-v1 + lowercase canonicalization. No embeddings,
no semantic similarity, no fuzzy alignment. The contract is “this token
sequence either is or isnt in the context.”</p>
<p>Wikitext context is run through <code class="docutils literal notranslate"><span class="pre">aborist.wikitext.to_base</span></code> before the
substring test. The corpus stores raw wikitext (so the link graph is
recoverable from any page), but the LLM produces clean prose. Without
the strip, every wikilink-carrying source paragraph compares as
“different surface form” and the verifier wrongly reports UNGROUNDED on
genuine source-grounded quotes. With the strip, paraphrases of <em>markup</em>
(<code class="docutils literal notranslate"><span class="pre">[[Cloud]]</span></code> vs <code class="docutils literal notranslate"><span class="pre">Cloud</span></code>) verify, while paraphrases of <em>prose</em> still
flag honestly. mwparserfromhell is an optional dep; if absent, the
strip is a no-op and verification falls back to todays behavior.</p>
<dl class="py function">
<dt class="sig sig-object py" id="aborist.qa.verify.extract_quotes">
<span class="sig-prename descclassname"><span class="pre">aborist.qa.verify.</span></span><span class="sig-name descname"><span class="pre">extract_quotes</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">answer_text</span></span></em><span class="sig-paren">)</span><a class="reference internal" href="../_modules/aborist/qa/verify.html#extract_quotes"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#aborist.qa.verify.extract_quotes" title="Link to this definition"></a></dt>
<dd><p>Pull double-quoted spans of length &gt;= MIN_QUOTE_CHARS from <cite>answer_text</cite>.</p>
<p>Sequential pairing: locate every double-quote character, then pair
them as (1st, 2nd), (3rd, 4th), …. Each pair brackets one quoted
span; text between consecutive pairs is the models own framing
prose (not captured). This is the correct model for adjacent quote
pairs like <cite>“title” prose “quote”</cite> — naive regex matching paired
the close of “title” with the open of “quote” and captured <cite>prose</cite>
as a phantom quote, dragging classifications down to HYBRID
incorrectly.</p>
<dl class="field-list simple">
<dt class="field-odd">Parameters<span class="colon">:</span></dt>
<dd class="field-odd"><p><strong>answer_text</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.14)"><em>str</em></a>)</p>
</dd>
<dt class="field-even">Return type<span class="colon">:</span></dt>
<dd class="field-even"><p><a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#list" title="(in Python v3.14)">list</a>[<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.14)">str</a>]</p>
</dd>
</dl>
</dd></dl>
<dl class="py function">
<dt class="sig sig-object py" id="aborist.qa.verify.extract_claim_spans">
<span class="sig-prename descclassname"><span class="pre">aborist.qa.verify.</span></span><span class="sig-name descname"><span class="pre">extract_claim_spans</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">answer_text</span></span></em><span class="sig-paren">)</span><a class="reference internal" href="../_modules/aborist/qa/verify.html#extract_claim_spans"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#aborist.qa.verify.extract_claim_spans" title="Link to this definition"></a></dt>
<dd><p>Strip bullet markers, split into sentences, drop framing prefixes.</p>
<p>Returns each non-empty span of length &gt;= MIN_SPAN_CHARS. These are the
“claim units” the model wrote — each one well substring-test against
context.</p>
<dl class="field-list simple">
<dt class="field-odd">Parameters<span class="colon">:</span></dt>
<dd class="field-odd"><p><strong>answer_text</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.14)"><em>str</em></a>)</p>
</dd>
<dt class="field-even">Return type<span class="colon">:</span></dt>
<dd class="field-even"><p><a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#list" title="(in Python v3.14)">list</a>[<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.14)">str</a>]</p>
</dd>
</dl>
</dd></dl>
<dl class="py function">
<dt class="sig sig-object py" id="aborist.qa.verify.extract_proper_nouns">
<span class="sig-prename descclassname"><span class="pre">aborist.qa.verify.</span></span><span class="sig-name descname"><span class="pre">extract_proper_nouns</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">answer_text</span></span></em><span class="sig-paren">)</span><a class="reference internal" href="../_modules/aborist/qa/verify.html#extract_proper_nouns"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#aborist.qa.verify.extract_proper_nouns" title="Link to this definition"></a></dt>
<dd><p>Pull multi-word capitalized phrases. Deduplicated, order preserved.</p>
<p>Multi-word only — single capitalized words at sentence start are too
noisy (“Based”, “Now”, “However”). Multi-word phrases like
“Keanu Reeves” or “Thomas A. Anderson” are reliable proper-noun
candidates and substring-test cleanly against source prose or
structured wikitext.</p>
<dl class="field-list simple">
<dt class="field-odd">Parameters<span class="colon">:</span></dt>
<dd class="field-odd"><p><strong>answer_text</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.14)"><em>str</em></a>)</p>
</dd>
<dt class="field-even">Return type<span class="colon">:</span></dt>
<dd class="field-even"><p><a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#list" title="(in Python v3.14)">list</a>[<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.14)">str</a>]</p>
</dd>
</dl>
</dd></dl>
<dl class="py function">
<dt class="sig sig-object py" id="aborist.qa.verify.verify_quotes">
<span class="sig-prename descclassname"><span class="pre">aborist.qa.verify.</span></span><span class="sig-name descname"><span class="pre">verify_quotes</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">answer_text</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">context</span></span></em>, <em class="sig-param"><span class="keyword-only-separator o"><abbr title="Keyword-only parameters separator (PEP 3102)"><span class="pre">*</span></abbr></span></em>, <em class="sig-param"><span class="n"><span class="pre">entity_policy</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">'proximity'</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">proximity_n</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">3</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">proximity_window</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">300</span></span></em><span class="sig-paren">)</span><a class="reference internal" href="../_modules/aborist/qa/verify.html#verify_quotes"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#aborist.qa.verify.verify_quotes" title="Link to this definition"></a></dt>
<dd><p>Classify an answers grounding against its retrieved context.</p>
<p>Tries quote → span → entity verification in sequence. The first
strategy that finds evidence classifies the answer; later strategies
dont run.</p>
<p><cite>entity_policy</cite> controls how the entity path classifies — see
ENTITY_POLICIES. The quote and span paths are unaffected; they are
explicit-claim evidence and always classify per the trichotomy.</p>
<dl>
<dt>Returns:</dt><dd><dl class="simple">
<dt>{</dt><dd><p>“n_quotes”: int, # evidence units extracted (any path)
“n_verified”: int, # of those, how many appear verbatim
“audit_mode”: str, # STRICT | HYBRID | UNGROUNDED
“unverified_quotes”: [str], # spans we couldnt ground in context
“verifier_method”: str, # quote | span | entity | none</p>
</dd>
</dl>
<p>}</p>
</dd>
</dl>
<dl class="field-list simple">
<dt class="field-odd">Parameters<span class="colon">:</span></dt>
<dd class="field-odd"><ul class="simple">
<li><p><strong>answer_text</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.14)"><em>str</em></a>)</p></li>
<li><p><strong>context</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.14)"><em>str</em></a>)</p></li>
<li><p><strong>entity_policy</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.14)"><em>str</em></a>)</p></li>
<li><p><strong>proximity_n</strong> (<a class="reference external" href="https://docs.python.org/3/library/functions.html#int" title="(in Python v3.14)"><em>int</em></a>)</p></li>
<li><p><strong>proximity_window</strong> (<a class="reference external" href="https://docs.python.org/3/library/functions.html#int" title="(in Python v3.14)"><em>int</em></a>)</p></li>
</ul>
</dd>
<dt class="field-even">Return type<span class="colon">:</span></dt>
<dd class="field-even"><p><a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#dict" title="(in Python v3.14)">dict</a></p>
</dd>
</dl>
</dd></dl>
<dl class="py function">
<dt class="sig sig-object py" id="aborist.qa.verify.verify_claim_lattice">
<span class="sig-prename descclassname"><span class="pre">aborist.qa.verify.</span></span><span class="sig-name descname"><span class="pre">verify_claim_lattice</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">answer_text</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">evidence_map</span></span></em>, <em class="sig-param"><span class="keyword-only-separator o"><abbr title="Keyword-only parameters separator (PEP 3102)"><span class="pre">*</span></abbr></span></em>, <em class="sig-param"><span class="n"><span class="pre">allowed_source_roles</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">('primary_answer_source',</span> <span class="pre">'secondary_context_source',</span> <span class="pre">'background_source',</span> <span class="pre">'unclassified')</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">max_pointers_per_claim</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">2</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">min_citation_coverage</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">0.3</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">min_claim_content_tokens</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">2</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">lazy_anchor_demote_threshold</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">0.5</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">lazy_anchor_demote_min_pairs</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">3</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">max_claims_per_answer</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">12</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">subject_tokens_absent_threshold</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">3</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">question</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">warrant_check_enabled</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">True</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">deflection_check_enabled</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">True</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">format_collapse_check_enabled</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">True</span></span></em><span class="sig-paren">)</span><a class="reference internal" href="../_modules/aborist/qa/verify.html#verify_claim_lattice"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#aborist.qa.verify.verify_claim_lattice" title="Link to this definition"></a></dt>
<dd><p>Deterministic verifier for <code class="docutils literal notranslate"><span class="pre">answer_mode=&quot;claim_lattice_pointer&quot;</span></code>.</p>
<p>The model wrote pointer-line prose (<code class="docutils literal notranslate"><span class="pre">Claim</span> <span class="pre">text.</span> <span class="pre">[E12]</span></code>); the
parser pulled (claim_text, [pointer_ids]) pairs from each non-empty
line. This verifier maps each pointer id back to its
content-addressed evidence object and runs six hard checks:</p>
<ol class="arabic simple">
<li><p>Parser succeeded — <code class="docutils literal notranslate"><span class="pre">parse_status</span> <span class="pre">==</span> <span class="pre">&quot;PARSED&quot;</span></code> (line had a
bracket tag). NO_EVIDENCE_POINTER claims (prose without tag)
count toward the denominator and downgrade the verdict.</p></li>
<li><p>Pointer id resolves to an entry in the runtime-built evidence
map. No model-invented ids.</p></li>
<li><p>Resolved entrys <code class="docutils literal notranslate"><span class="pre">source_role</span></code> is in <code class="docutils literal notranslate"><span class="pre">allowed_source_roles</span></code>.</p></li>
<li><p>Claim text non-empty after tag strip.</p></li>
<li><p>Claims content tokens textually overlap the cited evidence
span at coverage ≥ <code class="docutils literal notranslate"><span class="pre">min_citation_coverage</span></code> (per-pair, lexical
only — see <code class="docutils literal notranslate"><span class="pre">_claim_textually_overlaps_evidence</span></code>). Catches the
magnet-chunk lazy-anchor where the model cites an evidence
pointer whose text contains few claim-content tokens.</p></li>
<li><p>Pointer count per claim does not exceed <code class="docutils literal notranslate"><span class="pre">max_pointers_per_claim</span></code>
(default 2 — matches the prompts “1 or 2 pointers per claim”
rule). When exceeded, the claim is TRIMMED to the first N
pointers and verification proceeds normally; a
<code class="docutils literal notranslate"><span class="pre">POINTER_OVERFLOW_TRIMMED</span></code> violation is recorded so STRICT is
no longer reachable (audit_mode caps at HYBRID for the run).
Trim-and-verify (vs hard fail) protects correct claims that
were over-cited (e.g. “Leonardo painted the Mona Lisa.
[E2,…,E14]”) while keeping the over-citation pattern
surfaced. The dropped pointers count toward <code class="docutils literal notranslate"><span class="pre">n_quotes</span></code> so
the denominator reflects what the model emitted.</p></li>
</ol>
<p>Removed 2026-04-30: the strict no-double-quote rule. The model
routinely paraphrases source prose but copies named-quoted phrases
verbatim (e.g. <code class="docutils literal notranslate"><span class="pre">&quot;Constitution</span> <span class="pre">State&quot;</span></code> from a Connecticut span).
Hard-rejecting claims that contained any <code class="docutils literal notranslate"><span class="pre">&quot;</span></code> char was rejecting
factually correct, source-grounded claims for cosmetic punctuation.
The coverage threshold (Rule 5) and pointer cap (Rule 6) carry the
weight of catching synthetic-quote / mega-claim failures the old
rule was meant to catch. <code class="docutils literal notranslate"><span class="pre">_has_manual_quote</span></code> is still defined and
used by <code class="docutils literal notranslate"><span class="pre">verify_claim_lattice_json</span></code>.</p>
<p>Returns a verdict in the same shape as <code class="docutils literal notranslate"><span class="pre">verify_quotes</span></code> + extras:</p>
<blockquote>
<div><p>n_quotes total claim-pointer pairs (denominator)
n_verified pairs where pointer resolved AND</p>
<blockquote>
<div><p>source_role allowed AND coverage met
AND claim text non-empty</p>
</div></blockquote>
<p>audit_mode STRICT / HYBRID / UNGROUNDED
unverified_quotes claim texts that didnt reach</p>
<blockquote>
<div><p>EVIDENCE_LINKED — kept under that name
for schema continuity with verify_quotes</p>
</div></blockquote>
<p>verifier_method “claim_lattice”
claim_statuses per-claim {text, evidence_ids,</p>
<blockquote>
<div><p>pointer_ids, status, reasons[]}; status ∈
{EVIDENCE_LINKED, EVIDENCE_LINKED_PARTIAL,</p>
<blockquote>
<div><p>UNKNOWN_EVIDENCE_ID,
SOURCE_ROLE_BLOCKED,
CITATION_MISMATCH,
NO_EVIDENCE_POINTER, SCHEMA_INVALID}</p>
</div></blockquote>
</div></blockquote>
<dl class="simple">
<dt>violations structured violation records for the</dt><dd><p>run-DAG / sidecar</p>
</dd>
<dt>rendered_text human-readable prose with literal spans</dt><dd><p>interpolated; what the runner persists
as <code class="docutils literal notranslate"><span class="pre">answer_text</span></code></p>
</dd>
<dt>evidence_id_pairs per-claim list of resolved</dt><dd><p>content-addressed evidence_ids (run-stable
form). Used to thread the parsed lattice
into the run-DAG.</p>
</dd>
</dl>
</div></blockquote>
<dl class="field-list simple">
<dt class="field-odd">Parameters<span class="colon">:</span></dt>
<dd class="field-odd"><ul class="simple">
<li><p><strong>answer_text</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.14)"><em>str</em></a>)</p></li>
<li><p><strong>allowed_source_roles</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#tuple" title="(in Python v3.14)"><em>tuple</em></a><em>[</em><a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.14)"><em>str</em></a><em>, </em><em>...</em><em>]</em>)</p></li>
<li><p><strong>max_pointers_per_claim</strong> (<a class="reference external" href="https://docs.python.org/3/library/functions.html#int" title="(in Python v3.14)"><em>int</em></a>)</p></li>
<li><p><strong>min_citation_coverage</strong> (<a class="reference external" href="https://docs.python.org/3/library/functions.html#float" title="(in Python v3.14)"><em>float</em></a>)</p></li>
<li><p><strong>min_claim_content_tokens</strong> (<a class="reference external" href="https://docs.python.org/3/library/functions.html#int" title="(in Python v3.14)"><em>int</em></a>)</p></li>
<li><p><strong>lazy_anchor_demote_threshold</strong> (<a class="reference external" href="https://docs.python.org/3/library/functions.html#float" title="(in Python v3.14)"><em>float</em></a>)</p></li>
<li><p><strong>lazy_anchor_demote_min_pairs</strong> (<a class="reference external" href="https://docs.python.org/3/library/functions.html#int" title="(in Python v3.14)"><em>int</em></a>)</p></li>
<li><p><strong>max_claims_per_answer</strong> (<a class="reference external" href="https://docs.python.org/3/library/functions.html#int" title="(in Python v3.14)"><em>int</em></a>)</p></li>
<li><p><strong>subject_tokens_absent_threshold</strong> (<a class="reference external" href="https://docs.python.org/3/library/functions.html#int" title="(in Python v3.14)"><em>int</em></a>)</p></li>
<li><p><strong>question</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.14)"><em>str</em></a><em> | </em><em>None</em>)</p></li>
<li><p><strong>warrant_check_enabled</strong> (<a class="reference external" href="https://docs.python.org/3/library/functions.html#bool" title="(in Python v3.14)"><em>bool</em></a>)</p></li>
<li><p><strong>deflection_check_enabled</strong> (<a class="reference external" href="https://docs.python.org/3/library/functions.html#bool" title="(in Python v3.14)"><em>bool</em></a>)</p></li>
<li><p><strong>format_collapse_check_enabled</strong> (<a class="reference external" href="https://docs.python.org/3/library/functions.html#bool" title="(in Python v3.14)"><em>bool</em></a>)</p></li>
</ul>
</dd>
<dt class="field-even">Return type<span class="colon">:</span></dt>
<dd class="field-even"><p><a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#dict" title="(in Python v3.14)">dict</a></p>
</dd>
</dl>
</dd></dl>
<dl class="py function">
<dt class="sig sig-object py" id="aborist.qa.verify.evidence_map_by_evidence_id_local">
<span class="sig-prename descclassname"><span class="pre">aborist.qa.verify.</span></span><span class="sig-name descname"><span class="pre">evidence_map_by_evidence_id_local</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">evidence_map</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">eid</span></span></em><span class="sig-paren">)</span><a class="reference internal" href="../_modules/aborist/qa/verify.html#evidence_map_by_evidence_id_local"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#aborist.qa.verify.evidence_map_by_evidence_id_local" title="Link to this definition"></a></dt>
<dd><p>Local helper — returns the EvidenceObject whose <code class="docutils literal notranslate"><span class="pre">evidence_id</span></code>
matches <code class="docutils literal notranslate"><span class="pre">eid</span></code>, or None. Avoids the import-cycle risk of pulling
<cite>evidence_map_by_evidence_id</cite> into this modules hot path; the
O(N) walk is fine since evidence maps are &lt;30 entries.</p>
<dl class="field-list simple">
<dt class="field-odd">Parameters<span class="colon">:</span></dt>
<dd class="field-odd"><p><strong>eid</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.14)"><em>str</em></a>)</p>
</dd>
</dl>
</dd></dl>
<dl class="py function">
<dt class="sig sig-object py" id="aborist.qa.verify.verify_claim_lattice_json">
<span class="sig-prename descclassname"><span class="pre">aborist.qa.verify.</span></span><span class="sig-name descname"><span class="pre">verify_claim_lattice_json</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">answer_json_text</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">evidence_map</span></span></em>, <em class="sig-param"><span class="keyword-only-separator o"><abbr title="Keyword-only parameters separator (PEP 3102)"><span class="pre">*</span></abbr></span></em>, <em class="sig-param"><span class="n"><span class="pre">allowed_source_roles</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">('primary_answer_source',</span> <span class="pre">'secondary_context_source',</span> <span class="pre">'background_source',</span> <span class="pre">'unclassified')</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">max_evidence_per_claim</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">2</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">min_citation_coverage</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">0.3</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">max_claims_per_answer</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">12</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">subject_tokens_absent_threshold</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">3</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">question</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">warrant_check_enabled</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">True</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">deflection_check_enabled</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">True</span></span></em><span class="sig-paren">)</span><a class="reference internal" href="../_modules/aborist/qa/verify.html#verify_claim_lattice_json"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#aborist.qa.verify.verify_claim_lattice_json" title="Link to this definition"></a></dt>
<dd><p>Deterministic verifier for <code class="docutils literal notranslate"><span class="pre">answer_mode=&quot;claim_lattice&quot;</span></code> (JSON).</p>
<p>Parses the models JSON output (lenient pre-parser handles markdown
fences / preamble / curly quotes / trailing commas), validates the
schema, then runs the same hard checks as <code class="docutils literal notranslate"><span class="pre">verify_claim_lattice</span></code>
but reading <code class="docutils literal notranslate"><span class="pre">evidence_ids</span></code> from the JSON claim objects.</p>
<p>2026-04-30: switched from content-addressed evidence_ids
(<code class="docutils literal notranslate"><span class="pre">Eed1b6e396</span></code>) to pointer_ids (<code class="docutils literal notranslate"><span class="pre">E1</span></code>, <code class="docutils literal notranslate"><span class="pre">E2</span></code>, …) in the prompt
&amp; JSON output. Hermes-3-8B was fabricating plausible content-
addressed IDs (<code class="docutils literal notranslate"><span class="pre">E1b6e396</span></code>-style near-misses) on cross-document
relationship questions; the verifier correctly rejected them as
UNKNOWN_EVIDENCE_ID but the answer text was often factually
correct, leaving us with honest UNGROUNDED on right answers.
Pointer IDs are short, enumerable, and fabrication-obvious. The
runtime still resolves each pointer_id to its content-addressed
evidence_id internally and stores that in <code class="docutils literal notranslate"><span class="pre">evidence_id_pairs</span></code>
(cache/run-DAG continuity); only the prompt-facing surface
changes.</p>
<ol class="arabic simple">
<li><p>JSON parses (lenient). Failure → SCHEMA_INVALID, UNGROUNDED.</p></li>
<li><p>Top-level is <code class="docutils literal notranslate"><span class="pre">{&quot;claims&quot;:</span> <span class="pre">[...]}</span></code>.</p></li>
<li><p>Each claim is <code class="docutils literal notranslate"><span class="pre">{&quot;text&quot;:</span> <span class="pre">str,</span> <span class="pre">&quot;evidence_ids&quot;:</span> <span class="pre">[str,</span> <span class="pre">...]}</span></code>.</p></li>
<li><p>Each evidence_id resolves in the runtime-built evidence map
(no model-invented IDs).</p></li>
<li><p>Resolved entrys <code class="docutils literal notranslate"><span class="pre">source_role</span></code> is in <code class="docutils literal notranslate"><span class="pre">allowed_source_roles</span></code>.</p></li>
<li><p>Claim text contains no double-quote characters anywhere.</p></li>
<li><p>Claim text non-empty.</p></li>
<li><p>Claims content tokens textually overlap the cited evidence span.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">len(evidence_ids)</span> <span class="pre">&lt;=</span> <span class="pre">max_evidence_per_claim</span></code>.</p></li>
</ol>
<p>Returns a verdict in the same shape as <code class="docutils literal notranslate"><span class="pre">verify_claim_lattice</span></code> plus
a <code class="docutils literal notranslate"><span class="pre">json_fixups</span></code> field naming any drift the lenient parser had to
peel (<code class="docutils literal notranslate"><span class="pre">&quot;fence&quot;</span></code> / <code class="docutils literal notranslate"><span class="pre">&quot;prose_trim&quot;</span></code> / <code class="docutils literal notranslate"><span class="pre">&quot;curly_quotes&quot;</span></code> /
<code class="docutils literal notranslate"><span class="pre">&quot;trailing_comma&quot;</span></code>). Empty list = strict JSON parse on first try.</p>
<dl class="field-list simple">
<dt class="field-odd">Parameters<span class="colon">:</span></dt>
<dd class="field-odd"><ul class="simple">
<li><p><strong>answer_json_text</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.14)"><em>str</em></a>)</p></li>
<li><p><strong>allowed_source_roles</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#tuple" title="(in Python v3.14)"><em>tuple</em></a><em>[</em><a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.14)"><em>str</em></a><em>, </em><em>...</em><em>]</em>)</p></li>
<li><p><strong>max_evidence_per_claim</strong> (<a class="reference external" href="https://docs.python.org/3/library/functions.html#int" title="(in Python v3.14)"><em>int</em></a>)</p></li>
<li><p><strong>min_citation_coverage</strong> (<a class="reference external" href="https://docs.python.org/3/library/functions.html#float" title="(in Python v3.14)"><em>float</em></a>)</p></li>
<li><p><strong>max_claims_per_answer</strong> (<a class="reference external" href="https://docs.python.org/3/library/functions.html#int" title="(in Python v3.14)"><em>int</em></a>)</p></li>
<li><p><strong>subject_tokens_absent_threshold</strong> (<a class="reference external" href="https://docs.python.org/3/library/functions.html#int" title="(in Python v3.14)"><em>int</em></a>)</p></li>
<li><p><strong>question</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.14)"><em>str</em></a><em> | </em><em>None</em>)</p></li>
<li><p><strong>warrant_check_enabled</strong> (<a class="reference external" href="https://docs.python.org/3/library/functions.html#bool" title="(in Python v3.14)"><em>bool</em></a>)</p></li>
<li><p><strong>deflection_check_enabled</strong> (<a class="reference external" href="https://docs.python.org/3/library/functions.html#bool" title="(in Python v3.14)"><em>bool</em></a>)</p></li>
</ul>
</dd>
<dt class="field-even">Return type<span class="colon">:</span></dt>
<dd class="field-even"><p><a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#dict" title="(in Python v3.14)">dict</a></p>
</dd>
</dl>
</dd></dl>
</section>
<section id="module-aborist.qa.evidence">
<span id="evidence"></span><h2>evidence<a class="headerlink" href="#module-aborist.qa.evidence" title="Link to this heading"></a></h2>
<p>Evidence map for claim-lattice-pointer (quote-by-pointer) answer mode.</p>
<p>Builds a deterministic table of evidence objects from already-retrieved
chunks. The model references each object by a short <code class="docutils literal notranslate"><span class="pre">pointer_id</span></code>
(“E1”, “E2”, …) which the runtime maps back to a content-addressed
<code class="docutils literal notranslate"><span class="pre">evidence_id</span></code> for the cache, run-DAG, and audit chain.</p>
<p>Design pinned by G0 ticket (2026-04-29) and the CTI / Clause Lattice
Intelligence reframe:</p>
<blockquote>
<div><p>Models should not generate verbatim quotes.
They should point to evidence IDs extracted by deterministic code.</p>
</div></blockquote>
<p>This kills the synthetic-elision class by construction — the model
never types the quote string, so it cant drop characters from one.</p>
<p>Two-layer id scheme:</p>
<ul class="simple">
<li><dl class="simple">
<dt><code class="docutils literal notranslate"><span class="pre">pointer_id</span></code> short numeric tag the model sees in the prompt and</dt><dd><p>writes back in pointer-line answers. <code class="docutils literal notranslate"><span class="pre">E</span></code> + the
1-based position of the evidence object in the map
(<code class="docutils literal notranslate"><span class="pre">E1</span></code>, <code class="docutils literal notranslate"><span class="pre">E2</span></code>, …, <code class="docutils literal notranslate"><span class="pre">E37</span></code>). One BPE token per id
in standard tokenizers. Stays in the models
in-distribution citation style.</p>
</dd>
</dl>
</li>
<li><dl class="simple">
<dt><code class="docutils literal notranslate"><span class="pre">evidence_id</span></code> content-addressed handle. <code class="docutils literal notranslate"><span class="pre">E</span></code> + first 8 hex of</dt><dd><p><code class="docutils literal notranslate"><span class="pre">sha256(chunk_root:offset_start:offset_end)</span></code>.
Same chunk + same offsets in two runs → same id,
forever. The cache_key, run-DAG, and audit chain
all use this form so provenance is run-stable.</p>
</dd>
</dl>
</li>
</ul>
<p>The verifier (<code class="docutils literal notranslate"><span class="pre">verify_claim_lattice</span></code>) maps each pointer_id the model
writes back to its content-addressed evidence_id before persistence.
The models literal output is run-dependent (run #1s <code class="docutils literal notranslate"><span class="pre">E1</span></code> and run
#2s <code class="docutils literal notranslate"><span class="pre">E1</span></code> likely point at different chunks); the content-addressed
layer is what stays stable.</p>
<p>For the first cut every chunk produces exactly one evidence object
covering <code class="docutils literal notranslate"><span class="pre">offset_start=0</span> <span class="pre">..</span> <span class="pre">offset_end=len(span)</span></code>. Sub-chunk
extraction (paragraph-level, sentence-level) is a future refinement;
the schema already accepts arbitrary offsets so adding finer-grained
splits later doesnt break the contract.</p>
<dl class="py class">
<dt class="sig sig-object py" id="aborist.qa.evidence.EvidenceObject">
<span class="property"><span class="k"><span class="pre">class</span></span><span class="w"> </span></span><span class="sig-prename descclassname"><span class="pre">aborist.qa.evidence.</span></span><span class="sig-name descname"><span class="pre">EvidenceObject</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">pointer_id</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">evidence_id</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">source_root</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">document_uri</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">title</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">chunk_idx</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">chunk_root</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">offset_start</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">offset_end</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">source_role</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">text_hash</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">span</span></span></em><span class="sig-paren">)</span><a class="reference internal" href="../_modules/aborist/qa/evidence.html#EvidenceObject"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#aborist.qa.evidence.EvidenceObject" title="Link to this definition"></a></dt>
<dd><p>One pinned span the model may reference by <code class="docutils literal notranslate"><span class="pre">pointer_id</span></code>.</p>
<p>All fields are deterministic from inputs; same chunk + offsets yields
the same object byte-for-byte.</p>
<ul class="simple">
<li><dl class="simple">
<dt><code class="docutils literal notranslate"><span class="pre">pointer_id</span></code> prompt-facing id (“E1”, “E2”, …) — what the</dt><dd><p>model sees &amp; writes back. Position-derived;
run-dependent on purpose.</p>
</dd>
</dl>
</li>
<li><dl class="simple">
<dt><code class="docutils literal notranslate"><span class="pre">evidence_id</span></code> content-addressed handle (“E” + 8 hex of</dt><dd><p>sha256(chunk_root:start:end)) — what the
cache, run-DAG, and audit chain use.
Run-stable.</p>
</dd>
</dl>
</li>
<li><p><code class="docutils literal notranslate"><span class="pre">source_root</span></code> document_root the chunk belongs to</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">document_uri</span></code> human-readable URI (for the renderer)</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">title</span></code> doc title (for the renderer &amp; prompt)</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">chunk_idx</span></code> chunk index within the document</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">chunk_root</span></code> leaf hash of the chunk</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">offset_start</span></code> byte offset within the chunk (0 for whole-chunk)</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">offset_end</span></code> end offset (exclusive)</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">source_role</span></code> role classification (primary_answer_source / …)</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">text_hash</span></code> sha256 of the span (for tamper detection)</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">span</span></code> the literal text (what the renderer interpolates)</p></li>
</ul>
<dl class="field-list simple">
<dt class="field-odd">Parameters<span class="colon">:</span></dt>
<dd class="field-odd"><ul class="simple">
<li><p><strong>pointer_id</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.14)"><em>str</em></a>)</p></li>
<li><p><strong>evidence_id</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.14)"><em>str</em></a>)</p></li>
<li><p><strong>source_root</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.14)"><em>str</em></a>)</p></li>
<li><p><strong>document_uri</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.14)"><em>str</em></a>)</p></li>
<li><p><strong>title</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.14)"><em>str</em></a><em> | </em><em>None</em>)</p></li>
<li><p><strong>chunk_idx</strong> (<a class="reference external" href="https://docs.python.org/3/library/functions.html#int" title="(in Python v3.14)"><em>int</em></a>)</p></li>
<li><p><strong>chunk_root</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.14)"><em>str</em></a>)</p></li>
<li><p><strong>offset_start</strong> (<a class="reference external" href="https://docs.python.org/3/library/functions.html#int" title="(in Python v3.14)"><em>int</em></a>)</p></li>
<li><p><strong>offset_end</strong> (<a class="reference external" href="https://docs.python.org/3/library/functions.html#int" title="(in Python v3.14)"><em>int</em></a>)</p></li>
<li><p><strong>source_role</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.14)"><em>str</em></a>)</p></li>
<li><p><strong>text_hash</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.14)"><em>str</em></a>)</p></li>
<li><p><strong>span</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.14)"><em>str</em></a>)</p></li>
</ul>
</dd>
</dl>
<dl class="py attribute">
<dt class="sig sig-object py" id="aborist.qa.evidence.EvidenceObject.pointer_id">
<span class="sig-name descname"><span class="pre">pointer_id</span></span><span class="property"><span class="p"><span class="pre">:</span></span><span class="w"> </span><a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.14)"><span class="pre">str</span></a></span><a class="headerlink" href="#aborist.qa.evidence.EvidenceObject.pointer_id" title="Link to this definition"></a></dt>
<dd></dd></dl>
<dl class="py attribute">
<dt class="sig sig-object py" id="aborist.qa.evidence.EvidenceObject.evidence_id">
<span class="sig-name descname"><span class="pre">evidence_id</span></span><span class="property"><span class="p"><span class="pre">:</span></span><span class="w"> </span><a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.14)"><span class="pre">str</span></a></span><a class="headerlink" href="#aborist.qa.evidence.EvidenceObject.evidence_id" title="Link to this definition"></a></dt>
<dd></dd></dl>
<dl class="py attribute">
<dt class="sig sig-object py" id="aborist.qa.evidence.EvidenceObject.source_root">
<span class="sig-name descname"><span class="pre">source_root</span></span><span class="property"><span class="p"><span class="pre">:</span></span><span class="w"> </span><a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.14)"><span class="pre">str</span></a></span><a class="headerlink" href="#aborist.qa.evidence.EvidenceObject.source_root" title="Link to this definition"></a></dt>
<dd></dd></dl>
<dl class="py attribute">
<dt class="sig sig-object py" id="aborist.qa.evidence.EvidenceObject.document_uri">
<span class="sig-name descname"><span class="pre">document_uri</span></span><span class="property"><span class="p"><span class="pre">:</span></span><span class="w"> </span><a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.14)"><span class="pre">str</span></a></span><a class="headerlink" href="#aborist.qa.evidence.EvidenceObject.document_uri" title="Link to this definition"></a></dt>
<dd></dd></dl>
<dl class="py attribute">
<dt class="sig sig-object py" id="aborist.qa.evidence.EvidenceObject.title">
<span class="sig-name descname"><span class="pre">title</span></span><span class="property"><span class="p"><span class="pre">:</span></span><span class="w"> </span><a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.14)"><span class="pre">str</span></a><span class="w"> </span><span class="p"><span class="pre">|</span></span><span class="w"> </span><a class="reference external" href="https://docs.python.org/3/library/constants.html#None" title="(in Python v3.14)"><span class="pre">None</span></a></span><a class="headerlink" href="#aborist.qa.evidence.EvidenceObject.title" title="Link to this definition"></a></dt>
<dd></dd></dl>
<dl class="py attribute">
<dt class="sig sig-object py" id="aborist.qa.evidence.EvidenceObject.chunk_idx">
<span class="sig-name descname"><span class="pre">chunk_idx</span></span><span class="property"><span class="p"><span class="pre">:</span></span><span class="w"> </span><a class="reference external" href="https://docs.python.org/3/library/functions.html#int" title="(in Python v3.14)"><span class="pre">int</span></a></span><a class="headerlink" href="#aborist.qa.evidence.EvidenceObject.chunk_idx" title="Link to this definition"></a></dt>
<dd></dd></dl>
<dl class="py attribute">
<dt class="sig sig-object py" id="aborist.qa.evidence.EvidenceObject.chunk_root">
<span class="sig-name descname"><span class="pre">chunk_root</span></span><span class="property"><span class="p"><span class="pre">:</span></span><span class="w"> </span><a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.14)"><span class="pre">str</span></a></span><a class="headerlink" href="#aborist.qa.evidence.EvidenceObject.chunk_root" title="Link to this definition"></a></dt>
<dd></dd></dl>
<dl class="py attribute">
<dt class="sig sig-object py" id="aborist.qa.evidence.EvidenceObject.offset_start">
<span class="sig-name descname"><span class="pre">offset_start</span></span><span class="property"><span class="p"><span class="pre">:</span></span><span class="w"> </span><a class="reference external" href="https://docs.python.org/3/library/functions.html#int" title="(in Python v3.14)"><span class="pre">int</span></a></span><a class="headerlink" href="#aborist.qa.evidence.EvidenceObject.offset_start" title="Link to this definition"></a></dt>
<dd></dd></dl>
<dl class="py attribute">
<dt class="sig sig-object py" id="aborist.qa.evidence.EvidenceObject.offset_end">
<span class="sig-name descname"><span class="pre">offset_end</span></span><span class="property"><span class="p"><span class="pre">:</span></span><span class="w"> </span><a class="reference external" href="https://docs.python.org/3/library/functions.html#int" title="(in Python v3.14)"><span class="pre">int</span></a></span><a class="headerlink" href="#aborist.qa.evidence.EvidenceObject.offset_end" title="Link to this definition"></a></dt>
<dd></dd></dl>
<dl class="py attribute">
<dt class="sig sig-object py" id="aborist.qa.evidence.EvidenceObject.source_role">
<span class="sig-name descname"><span class="pre">source_role</span></span><span class="property"><span class="p"><span class="pre">:</span></span><span class="w"> </span><a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.14)"><span class="pre">str</span></a></span><a class="headerlink" href="#aborist.qa.evidence.EvidenceObject.source_role" title="Link to this definition"></a></dt>
<dd></dd></dl>
<dl class="py attribute">
<dt class="sig sig-object py" id="aborist.qa.evidence.EvidenceObject.text_hash">
<span class="sig-name descname"><span class="pre">text_hash</span></span><span class="property"><span class="p"><span class="pre">:</span></span><span class="w"> </span><a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.14)"><span class="pre">str</span></a></span><a class="headerlink" href="#aborist.qa.evidence.EvidenceObject.text_hash" title="Link to this definition"></a></dt>
<dd></dd></dl>
<dl class="py attribute">
<dt class="sig sig-object py" id="aborist.qa.evidence.EvidenceObject.span">
<span class="sig-name descname"><span class="pre">span</span></span><span class="property"><span class="p"><span class="pre">:</span></span><span class="w"> </span><a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.14)"><span class="pre">str</span></a></span><a class="headerlink" href="#aborist.qa.evidence.EvidenceObject.span" title="Link to this definition"></a></dt>
<dd></dd></dl>
<dl class="py method">
<dt class="sig sig-object py" id="aborist.qa.evidence.EvidenceObject.to_dict">
<span class="sig-name descname"><span class="pre">to_dict</span></span><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="reference internal" href="../_modules/aborist/qa/evidence.html#EvidenceObject.to_dict"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#aborist.qa.evidence.EvidenceObject.to_dict" title="Link to this definition"></a></dt>
<dd><dl class="field-list simple">
<dt class="field-odd">Return type<span class="colon">:</span></dt>
<dd class="field-odd"><p><a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#dict" title="(in Python v3.14)">dict</a></p>
</dd>
</dl>
</dd></dl>
</dd></dl>
<dl class="py function">
<dt class="sig sig-object py" id="aborist.qa.evidence.build_evidence_map">
<span class="sig-prename descclassname"><span class="pre">aborist.qa.evidence.</span></span><span class="sig-name descname"><span class="pre">build_evidence_map</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">chunks</span></span></em><span class="sig-paren">)</span><a class="reference internal" href="../_modules/aborist/qa/evidence.html#build_evidence_map"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#aborist.qa.evidence.build_evidence_map" title="Link to this definition"></a></dt>
<dd><p>Build the evidence table from retrieved chunks.</p>
<dl class="simple">
<dt><code class="docutils literal notranslate"><span class="pre">chunks</span></code> is a list of dicts with keys:</dt><dd><p>source_root, document_uri, title (optional), chunk_idx,
chunk_root, span, source_role (optional, default unclassified)</p>
</dd>
</dl>
<p>Returns a list of <code class="docutils literal notranslate"><span class="pre">EvidenceObject``s,</span> <span class="pre">one</span> <span class="pre">per</span> <span class="pre">chunk,</span> <span class="pre">in</span> <span class="pre">input</span> <span class="pre">order.</span>
<span class="pre">The</span> <span class="pre">1-based</span> <span class="pre">position</span> <span class="pre">drives</span> <span class="pre">``pointer_id</span></code> (E1, E2, …); the chunks
content drives <code class="docutils literal notranslate"><span class="pre">evidence_id</span></code> (sha256-derived). For the first cut
each chunk = one whole-span evidence object (offset 0 .. len(span)).
Sub-chunk splitting is a future refinement.</p>
<dl class="field-list simple">
<dt class="field-odd">Parameters<span class="colon">:</span></dt>
<dd class="field-odd"><p><strong>chunks</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#list" title="(in Python v3.14)"><em>list</em></a><em>[</em><a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#dict" title="(in Python v3.14)"><em>dict</em></a><em>]</em>)</p>
</dd>
<dt class="field-even">Return type<span class="colon">:</span></dt>
<dd class="field-even"><p><a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#list" title="(in Python v3.14)">list</a>[<a class="reference internal" href="#aborist.qa.evidence.EvidenceObject" title="aborist.qa.evidence.EvidenceObject"><em>EvidenceObject</em></a>]</p>
</dd>
</dl>
</dd></dl>
<dl class="py function">
<dt class="sig sig-object py" id="aborist.qa.evidence.evidence_map_root">
<span class="sig-prename descclassname"><span class="pre">aborist.qa.evidence.</span></span><span class="sig-name descname"><span class="pre">evidence_map_root</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">evidence</span></span></em><span class="sig-paren">)</span><a class="reference internal" href="../_modules/aborist/qa/evidence.html#evidence_map_root"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#aborist.qa.evidence.evidence_map_root" title="Link to this definition"></a></dt>
<dd><p>Merkle root over the sorted evidence_id leaves.</p>
<p>Sorting makes the root order-independent — two retrieval runs that
return the same chunks in different orders produce the same root.
Use as the <code class="docutils literal notranslate"><span class="pre">evidence_map</span></code> stage hash in the run-DAG.</p>
<dl class="field-list simple">
<dt class="field-odd">Parameters<span class="colon">:</span></dt>
<dd class="field-odd"><p><strong>evidence</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#list" title="(in Python v3.14)"><em>list</em></a><em>[</em><a class="reference internal" href="#aborist.qa.evidence.EvidenceObject" title="aborist.qa.evidence.EvidenceObject"><em>EvidenceObject</em></a><em>]</em>)</p>
</dd>
<dt class="field-even">Return type<span class="colon">:</span></dt>
<dd class="field-even"><p><a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.14)">str</a></p>
</dd>
</dl>
</dd></dl>
<dl class="py function">
<dt class="sig sig-object py" id="aborist.qa.evidence.render_evidence_block">
<span class="sig-prename descclassname"><span class="pre">aborist.qa.evidence.</span></span><span class="sig-name descname"><span class="pre">render_evidence_block</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">e</span></span></em><span class="sig-paren">)</span><a class="reference internal" href="../_modules/aborist/qa/evidence.html#render_evidence_block"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#aborist.qa.evidence.render_evidence_block" title="Link to this definition"></a></dt>
<dd><p>Format one evidence object for the LLM prompt.</p>
<p>Header carries the prompt-facing pointer_id, title (or URI tail),
and source role so the model has everything it needs to cite
without typing the span:</p>
<blockquote>
<div><p>=== E1 (Jurassic_Park_(film) | primary_answer_source) ===
&lt;literal span text&gt;</p>
</div></blockquote>
<p>The runtime maps E1 back to the content-addressed evidence_id
before persistence; the model never sees the hex form.</p>
<dl class="field-list simple">
<dt class="field-odd">Parameters<span class="colon">:</span></dt>
<dd class="field-odd"><p><strong>e</strong> (<a class="reference internal" href="#aborist.qa.evidence.EvidenceObject" title="aborist.qa.evidence.EvidenceObject"><em>EvidenceObject</em></a>)</p>
</dd>
<dt class="field-even">Return type<span class="colon">:</span></dt>
<dd class="field-even"><p><a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.14)">str</a></p>
</dd>
</dl>
</dd></dl>
<dl class="py function">
<dt class="sig sig-object py" id="aborist.qa.evidence.render_evidence_map">
<span class="sig-prename descclassname"><span class="pre">aborist.qa.evidence.</span></span><span class="sig-name descname"><span class="pre">render_evidence_map</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">evidence</span></span></em><span class="sig-paren">)</span><a class="reference internal" href="../_modules/aborist/qa/evidence.html#render_evidence_map"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#aborist.qa.evidence.render_evidence_map" title="Link to this definition"></a></dt>
<dd><p>Concatenated evidence blocks, ready to drop into the prompt.</p>
<dl class="field-list simple">
<dt class="field-odd">Parameters<span class="colon">:</span></dt>
<dd class="field-odd"><p><strong>evidence</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#list" title="(in Python v3.14)"><em>list</em></a><em>[</em><a class="reference internal" href="#aborist.qa.evidence.EvidenceObject" title="aborist.qa.evidence.EvidenceObject"><em>EvidenceObject</em></a><em>]</em>)</p>
</dd>
<dt class="field-even">Return type<span class="colon">:</span></dt>
<dd class="field-even"><p><a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.14)">str</a></p>
</dd>
</dl>
</dd></dl>
<dl class="py function">
<dt class="sig sig-object py" id="aborist.qa.evidence.render_evidence_block_for_json">
<span class="sig-prename descclassname"><span class="pre">aborist.qa.evidence.</span></span><span class="sig-name descname"><span class="pre">render_evidence_block_for_json</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">e</span></span></em><span class="sig-paren">)</span><a class="reference internal" href="../_modules/aborist/qa/evidence.html#render_evidence_block_for_json"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#aborist.qa.evidence.render_evidence_block_for_json" title="Link to this definition"></a></dt>
<dd><p>Format one evidence object for the JSON-mode LLM prompt.</p>
<p>2026-04-30: header uses the prompt-facing <code class="docutils literal notranslate"><span class="pre">pointer_id</span></code> (E1, E2,
…) — same as claim_lattice_pointer mode — instead of the
content-addressed <code class="docutils literal notranslate"><span class="pre">evidence_id</span></code> (long hex). The change closes a
real failure mode: small models (Hermes-3-8B observed) were
fabricating plausible-looking content-addressed IDs (e.g.
<code class="docutils literal notranslate"><span class="pre">E1b6e396</span></code> when the runtime had <code class="docutils literal notranslate"><span class="pre">Eed1b6e396</span></code>) → <a href="#id3"><span class="problematic" id="id4">UNKNOWN_</span></a>
EVIDENCE_ID → UNGROUNDED, even when the answer text was correct.
Pointer IDs (<code class="docutils literal notranslate"><span class="pre">E1</span></code>-<code class="docutils literal notranslate"><span class="pre">E10</span></code>) are short, enumerable, and fabrication-
obvious — the model cant invent <code class="docutils literal notranslate"><span class="pre">E27</span></code> if only <code class="docutils literal notranslate"><span class="pre">E1</span></code>-<code class="docutils literal notranslate"><span class="pre">E10</span></code> were
shown.</p>
<p>The runtime still stores content-addressed <code class="docutils literal notranslate"><span class="pre">evidence_id</span></code> in the
cache &amp; run-DAG (resolved on-the-fly in <code class="docutils literal notranslate"><span class="pre">verify_claim_lattice_json</span></code>);
only the prompt-facing string changes:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">===</span> <span class="n">E1</span> <span class="p">(</span><span class="n">Jurassic_Park_</span><span class="p">(</span><span class="n">film</span><span class="p">)</span> <span class="o">|</span> <span class="n">primary_answer_source</span><span class="p">)</span> <span class="o">===</span>
<span class="o">&lt;</span><span class="n">literal</span> <span class="n">span</span> <span class="n">text</span><span class="o">&gt;</span>
</pre></div>
</div>
<dl class="field-list simple">
<dt class="field-odd">Parameters<span class="colon">:</span></dt>
<dd class="field-odd"><p><strong>e</strong> (<a class="reference internal" href="#aborist.qa.evidence.EvidenceObject" title="aborist.qa.evidence.EvidenceObject"><em>EvidenceObject</em></a>)</p>
</dd>
<dt class="field-even">Return type<span class="colon">:</span></dt>
<dd class="field-even"><p><a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.14)">str</a></p>
</dd>
</dl>
</dd></dl>
<dl class="py function">
<dt class="sig sig-object py" id="aborist.qa.evidence.render_evidence_map_for_json">
<span class="sig-prename descclassname"><span class="pre">aborist.qa.evidence.</span></span><span class="sig-name descname"><span class="pre">render_evidence_map_for_json</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">evidence</span></span></em><span class="sig-paren">)</span><a class="reference internal" href="../_modules/aborist/qa/evidence.html#render_evidence_map_for_json"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#aborist.qa.evidence.render_evidence_map_for_json" title="Link to this definition"></a></dt>
<dd><p>Concatenated evidence blocks for JSON mode.</p>
<dl class="field-list simple">
<dt class="field-odd">Parameters<span class="colon">:</span></dt>
<dd class="field-odd"><p><strong>evidence</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#list" title="(in Python v3.14)"><em>list</em></a><em>[</em><a class="reference internal" href="#aborist.qa.evidence.EvidenceObject" title="aborist.qa.evidence.EvidenceObject"><em>EvidenceObject</em></a><em>]</em>)</p>
</dd>
<dt class="field-even">Return type<span class="colon">:</span></dt>
<dd class="field-even"><p><a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.14)">str</a></p>
</dd>
</dl>
</dd></dl>
<dl class="py function">
<dt class="sig sig-object py" id="aborist.qa.evidence.evidence_map_by_pointer_id">
<span class="sig-prename descclassname"><span class="pre">aborist.qa.evidence.</span></span><span class="sig-name descname"><span class="pre">evidence_map_by_pointer_id</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">evidence</span></span></em><span class="sig-paren">)</span><a class="reference internal" href="../_modules/aborist/qa/evidence.html#evidence_map_by_pointer_id"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#aborist.qa.evidence.evidence_map_by_pointer_id" title="Link to this definition"></a></dt>
<dd><p>Index by prompt-facing pointer_id (E1, E2, …).</p>
<dl class="field-list simple">
<dt class="field-odd">Parameters<span class="colon">:</span></dt>
<dd class="field-odd"><p><strong>evidence</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#list" title="(in Python v3.14)"><em>list</em></a><em>[</em><a class="reference internal" href="#aborist.qa.evidence.EvidenceObject" title="aborist.qa.evidence.EvidenceObject"><em>EvidenceObject</em></a><em>]</em>)</p>
</dd>
<dt class="field-even">Return type<span class="colon">:</span></dt>
<dd class="field-even"><p><a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#dict" title="(in Python v3.14)">dict</a>[<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.14)">str</a>, <a class="reference internal" href="#aborist.qa.evidence.EvidenceObject" title="aborist.qa.evidence.EvidenceObject"><em>EvidenceObject</em></a>]</p>
</dd>
</dl>
</dd></dl>
<dl class="py function">
<dt class="sig sig-object py" id="aborist.qa.evidence.evidence_map_by_evidence_id">
<span class="sig-prename descclassname"><span class="pre">aborist.qa.evidence.</span></span><span class="sig-name descname"><span class="pre">evidence_map_by_evidence_id</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">evidence</span></span></em><span class="sig-paren">)</span><a class="reference internal" href="../_modules/aborist/qa/evidence.html#evidence_map_by_evidence_id"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#aborist.qa.evidence.evidence_map_by_evidence_id" title="Link to this definition"></a></dt>
<dd><p>Index by content-addressed evidence_id (E1f8e4c2a, …).</p>
<dl class="field-list simple">
<dt class="field-odd">Parameters<span class="colon">:</span></dt>
<dd class="field-odd"><p><strong>evidence</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#list" title="(in Python v3.14)"><em>list</em></a><em>[</em><a class="reference internal" href="#aborist.qa.evidence.EvidenceObject" title="aborist.qa.evidence.EvidenceObject"><em>EvidenceObject</em></a><em>]</em>)</p>
</dd>
<dt class="field-even">Return type<span class="colon">:</span></dt>
<dd class="field-even"><p><a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#dict" title="(in Python v3.14)">dict</a>[<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.14)">str</a>, <a class="reference internal" href="#aborist.qa.evidence.EvidenceObject" title="aborist.qa.evidence.EvidenceObject"><em>EvidenceObject</em></a>]</p>
</dd>
</dl>
</dd></dl>
<dl class="py function">
<dt class="sig sig-object py" id="aborist.qa.evidence.render_claim_lattice">
<span class="sig-prename descclassname"><span class="pre">aborist.qa.evidence.</span></span><span class="sig-name descname"><span class="pre">render_claim_lattice</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">claims</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">by_id</span></span></em>, <em class="sig-param"><span class="keyword-only-separator o"><abbr title="Keyword-only parameters separator (PEP 3102)"><span class="pre">*</span></abbr></span></em>, <em class="sig-param"><span class="n"><span class="pre">window</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">200</span></span></em><span class="sig-paren">)</span><a class="reference internal" href="../_modules/aborist/qa/evidence.html#render_claim_lattice"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#aborist.qa.evidence.render_claim_lattice" title="Link to this definition"></a></dt>
<dd><p>Convert structured claims to human-readable prose with literal spans.</p>
<p>Each claim becomes one bullet line followed by inlined evidence
excerpts. The models claim text is rendered verbatim; each cited
pointer_id is followed by a <strong>spotlight excerpt</strong> of the literal
source span — a window of <code class="docutils literal notranslate"><span class="pre">window</span></code> chars centered on the first
content token from the claim that appears in the span. Falls back
to the leading window when no claim token matches.</p>
<p>Why spotlight over leading-N truncation: when the cited evidence is
a whole article and the model lazy-anchors every claim at the same
pointer, the leading-N strategy displayed the same article-intro
sentence under every claim. The spotlight finds the part of the
span the claim is <em>about</em> — “Brachiosaurus appears in the film” +
a 15 KB article span gets a window centered on the first
“brachiosaurus” mention, not the production-history opener. Same
cited evidence id, but the displayed text actually supports
different claims differently.</p>
<p><code class="docutils literal notranslate"><span class="pre">by_id</span></code> is the pointer_id → EvidenceObject index — what
<code class="docutils literal notranslate"><span class="pre">evidence_map_by_pointer_id</span></code> returns. Determinism: same
(claims, by_id, window) → same prose, byte-for-byte. Unknown ids
render as <code class="docutils literal notranslate"><span class="pre">[&lt;id&gt;:</span> <span class="pre">?]</span></code> so violations are visible at a glance.</p>
<dl class="field-list simple">
<dt class="field-odd">Parameters<span class="colon">:</span></dt>
<dd class="field-odd"><ul class="simple">
<li><p><strong>claims</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#list" title="(in Python v3.14)"><em>list</em></a><em>[</em><a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#dict" title="(in Python v3.14)"><em>dict</em></a><em>]</em>)</p></li>
<li><p><strong>by_id</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#dict" title="(in Python v3.14)"><em>dict</em></a><em>[</em><a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.14)"><em>str</em></a><em>, </em><a class="reference internal" href="#aborist.qa.evidence.EvidenceObject" title="aborist.qa.evidence.EvidenceObject"><em>EvidenceObject</em></a><em>]</em>)</p></li>
<li><p><strong>window</strong> (<a class="reference external" href="https://docs.python.org/3/library/functions.html#int" title="(in Python v3.14)"><em>int</em></a>)</p></li>
</ul>
</dd>
<dt class="field-even">Return type<span class="colon">:</span></dt>
<dd class="field-even"><p><a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.14)">str</a></p>
</dd>
</dl>
</dd></dl>
</section>
<section id="module-aborist.qa.quantifier">
<span id="quantifier"></span><h2>quantifier<a class="headerlink" href="#module-aborist.qa.quantifier" title="Link to this heading"></a></h2>
<p>Pure quantifier preflight classifier — Ticket #000008 Phase 1.</p>
<p>Maps a question string onto the ten-rung intensity ladder defined in
<code class="docutils literal notranslate"><span class="pre">docs/tickets/ticket-000008-broad-quantifier-preflight-guard.md</span></code> §2.
The classifier exists to estimate <strong>expected number of claims in the
answer</strong> and <strong>format-discipline risk on small models</strong>. It is not
formal-semantics quantifier theory; the operational axis is what
matters.</p>
<p>Pure function. No I/O. No model call. No retrieval call. Folds into
<code class="docutils literal notranslate"><span class="pre">governance_policy_hash</span></code> via <code class="docutils literal notranslate"><span class="pre">classifier_version</span></code> (added to
<code class="docutils literal notranslate"><span class="pre">aborist.qa.keys._VERIFIER_POLICY_FIELDS</span></code> in Phase 2).</p>
<p>Intensity rungs (highest wins for multi-quantifier questions):</p>
<blockquote>
<div><ol class="arabic simple">
<li><p>ABSENT universal-negation, single-claim shape</p></li>
<li><p>SINGULAR one-fact wh / definite reference</p></li>
<li><p>PROPORTIONAL descriptive fraction (<cite>most</cite>, <cite>half</cite>)</p></li>
<li><p>SMALL_NUM_EXPLICIT bounded by digit/word (<cite>top 3</cite>, <cite>seven X</cite>)</p></li>
<li><p>COMPARATIVE_BOUND bounded by inequality (<cite>at least 5</cite>)</p></li>
<li><p>FEW small set, vague (<cite>some</cite>, <cite>a few</cite>)</p></li>
<li><p>MANY medium set, vague (<cite>many</cite>, <cite>numerous</cite>)</p></li>
<li><p>ALL universal quantifier (<cite>all</cite>, <cite>every</cite>)</p></li>
<li><dl class="simple">
<dt>COMPREHENSIVE exhaustive request (<cite>complete list of</cite>,</dt><dd><p><cite>tell me everything</cite>)</p>
</dd>
</dl>
</li>
<li><dl class="simple">
<dt>OPEN_REQUEST verb-driven enumeration (<cite>tell me about</cite>,</dt><dd><p><cite>describe</cite>, <cite>explain</cite>)</p>
</dd>
</dl>
</li>
</ol>
</div></blockquote>
<p>Returns a dict with:</p>
<blockquote>
<div><p>intensity one of the ten rungs (or “SINGULAR” by default)
matched_token the lexical surface form that triggered the rung
explicit_count int when SMALL_NUM_EXPLICIT or COMPARATIVE_BOUND;</p>
<blockquote>
<div><p>None otherwise</p>
</div></blockquote>
<p>is_broad True for ALL / COMPREHENSIVE / OPEN_REQUEST
operational_shape mnemonic for downstream policy (e.g.</p>
<blockquote>
<div><p>“universal_enumeration”, “exhaustive_request”)</p>
</div></blockquote>
<dl class="simple">
<dt>scope_bound_hint “bounded” | “unbounded” | “unknown”</dt><dd><dl class="simple">
<dt>(see ticket §10.1 — bounded ≠ unbounded</dt><dd><p>universals; classifier defaults to “unknown”
when intensity is broad and no domain anchor
is present)</p>
</dd>
</dl>
</dd>
</dl>
</div></blockquote>
<p>Highest-intensity-wins arbitration: when a question contains
overlapping markers (e.g. “tell me about all the planets”), pick the
rung farther from SINGULAR. The order in <code class="docutils literal notranslate"><span class="pre">_RUNG_PRIORITY</span></code> codifies
this — later rungs win.</p>
<dl class="py function">
<dt class="sig sig-object py" id="aborist.qa.quantifier.classify_question_quantifier">
<span class="sig-prename descclassname"><span class="pre">aborist.qa.quantifier.</span></span><span class="sig-name descname"><span class="pre">classify_question_quantifier</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">question</span></span></em><span class="sig-paren">)</span><a class="reference internal" href="../_modules/aborist/qa/quantifier.html#classify_question_quantifier"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#aborist.qa.quantifier.classify_question_quantifier" title="Link to this definition"></a></dt>
<dd><p>Classify <code class="docutils literal notranslate"><span class="pre">question</span></code> onto the ten-rung intensity ladder.</p>
<p>Highest-intensity-wins arbitration: when multiple rungs match,
pick the one farther from SINGULAR. Operationally that means
“tell me about all the planets” classifies OPEN_REQUEST (later
in the priority order than ALL), even though ALL also matched.
The downstream cap is the broader rungs cap, which is what we
want under enumeration pressure.</p>
<p>Returns a dict; see module docstring for fields.</p>
<p>Empty / whitespace-only questions classify SINGULAR (no quantifier
pressure) with no matched_token.</p>
<dl class="field-list simple">
<dt class="field-odd">Parameters<span class="colon">:</span></dt>
<dd class="field-odd"><p><strong>question</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.14)"><em>str</em></a>)</p>
</dd>
<dt class="field-even">Return type<span class="colon">:</span></dt>
<dd class="field-even"><p><a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#dict" title="(in Python v3.14)">dict</a></p>
</dd>
</dl>
</dd></dl>
</section>
<section id="module-aborist.qa.metacognition">
<span id="metacognition"></span><h2>metacognition<a class="headerlink" href="#module-aborist.qa.metacognition" title="Link to this heading"></a></h2>
<p>Meta-Cognition Preflight Guard — Ticket #000010 Phase 1.</p>
<p>Runtime epistemic control layer that classifies a questions shape
BEFORE generation, so the model never answers from the surface form
alone when the question is ill-posed (false-premise, contradictory,
under-specified, broad-quantifier, time-sensitive, out-of-corpus,
reference-frame ambiguous).</p>
<p>Pure and deterministic. No I/O, no model call, no retrieval call.
Reuses <code class="docutils literal notranslate"><span class="pre">aborist.qa.quantifier.classify_question_quantifier</span></code> for
the broad-quantifier rung; adds four new lightweight detectors:</p>
<blockquote>
<div><ul class="simple">
<li><p>temporal sensitivity (current/latest/today/CEO/etc.)</p></li>
<li><p>contradiction (lexical) (unmarried+spouse, always+sometimes-not)</p></li>
<li><p>false-premise (lite) (presupposition patterns)</p></li>
<li><p>out-of-corpus (my-uploaded-X / my-file shapes)</p></li>
</ul>
</div></blockquote>
<p>Reference-frame detection lives in <code class="docutils literal notranslate"><span class="pre">aborist.qa.query._detect_frame</span></code>
(ticket #000002) and is called from the surrounding runtime, not
from this module — keeps detection pure-on-question (no corpus
lookup needed here).</p>
<p>The output is a <code class="docutils literal notranslate"><span class="pre">QuestionState</span></code> dataclass that becomes a CTI root
node. First pass surfaces it on the <code class="docutils literal notranslate"><span class="pre">query()</span></code> result dict only;
run-DAG node binding deferred to the same Phase 5 work tracked in
ticket #000009 (both nodes can land together).</p>
<p>Hard rule (D1): No LLM in this hard path. Model-assisted preflight,
if added later, labels itself <code class="docutils literal notranslate"><span class="pre">SOFT_PREFLIGHT_HINT</span></code> and never
produces a <code class="docutils literal notranslate"><span class="pre">PREFLIGHT_OK</span></code> / <code class="docutils literal notranslate"><span class="pre">PREFLIGHT_BLOCKED</span></code> without
deterministic support.</p>
<dl class="py class">
<dt class="sig sig-object py" id="aborist.qa.metacognition.QuestionState">
<span class="property"><span class="k"><span class="pre">class</span></span><span class="w"> </span></span><span class="sig-prename descclassname"><span class="pre">aborist.qa.metacognition.</span></span><span class="sig-name descname"><span class="pre">QuestionState</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">raw_question</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">question_hash</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">logical_statuses</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">question_shape</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">quantifier_intensity</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">quantifier_matched_token</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">scope_bound_hint</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">reference_frames</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">temporal_sensitivity</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">temporal_matched_tokens</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">contradiction_pairs</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">false_premise_hints</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">corpus_requirement</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">known_boundaries</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">answer_constraints</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">preflight_result</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">preflight_policy_hash</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">classifier_version</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">'metacognition-v0.1'</span></span></em><span class="sig-paren">)</span><a class="reference internal" href="../_modules/aborist/qa/metacognition.html#QuestionState"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#aborist.qa.metacognition.QuestionState" title="Link to this definition"></a></dt>
<dd><p>Runtime epistemic state for one question.</p>
<p>All fields are deterministic from the question + per-call
<cite>model_profile</cite> / <cite>corpus_profile</cite> / <cite>policy</cite> inputs. No
randomness, no LLM. Hashable via <cite>preflight_policy_hash</cite> so
the run-DAG (Phase 5) can bind the decision into the audit
chain.</p>
<dl class="field-list simple">
<dt class="field-odd">Parameters<span class="colon">:</span></dt>
<dd class="field-odd"><ul class="simple">
<li><p><strong>raw_question</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.14)"><em>str</em></a>)</p></li>
<li><p><strong>question_hash</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.14)"><em>str</em></a>)</p></li>
<li><p><strong>logical_statuses</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#tuple" title="(in Python v3.14)"><em>tuple</em></a><em>[</em><a class="reference external" href="https://docs.python.org/3/library/typing.html#typing.Literal" title="(in Python v3.14)"><em>Literal</em></a><em>[</em><em>'well_formed'</em><em>, </em><em>'under_specified'</em><em>, </em><em>'false_premise_suspected'</em><em>, </em><em>'contradictory_question'</em><em>, </em><em>'out_of_corpus_risk'</em><em>, </em><em>'stale_risk'</em><em>, </em><em>'reference_frame_ambiguous'</em><em>, </em><em>'broad_quantifier_unbounded'</em><em>]</em><em>, </em><em>...</em><em>]</em>)</p></li>
<li><p><strong>question_shape</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.14)"><em>str</em></a>)</p></li>
<li><p><strong>quantifier_intensity</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.14)"><em>str</em></a><em> | </em><em>None</em>)</p></li>
<li><p><strong>quantifier_matched_token</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.14)"><em>str</em></a><em> | </em><em>None</em>)</p></li>
<li><p><strong>scope_bound_hint</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.14)"><em>str</em></a>)</p></li>
<li><p><strong>reference_frames</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#tuple" title="(in Python v3.14)"><em>tuple</em></a><em>[</em><a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.14)"><em>str</em></a><em>, </em><em>...</em><em>]</em>)</p></li>
<li><p><strong>temporal_sensitivity</strong> (<a class="reference external" href="https://docs.python.org/3/library/typing.html#typing.Literal" title="(in Python v3.14)"><em>Literal</em></a><em>[</em><em>'high'</em><em>, </em><em>'medium'</em><em>, </em><em>'low'</em><em>]</em>)</p></li>
<li><p><strong>temporal_matched_tokens</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#tuple" title="(in Python v3.14)"><em>tuple</em></a><em>[</em><a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.14)"><em>str</em></a><em>, </em><em>...</em><em>]</em>)</p></li>
<li><p><strong>contradiction_pairs</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#tuple" title="(in Python v3.14)"><em>tuple</em></a><em>[</em><a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#tuple" title="(in Python v3.14)"><em>tuple</em></a><em>[</em><a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.14)"><em>str</em></a><em>, </em><a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.14)"><em>str</em></a><em>]</em><em>, </em><em>...</em><em>]</em>)</p></li>
<li><p><strong>false_premise_hints</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#tuple" title="(in Python v3.14)"><em>tuple</em></a><em>[</em><a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#dict" title="(in Python v3.14)"><em>dict</em></a><em>, </em><em>...</em><em>]</em>)</p></li>
<li><p><strong>corpus_requirement</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.14)"><em>str</em></a>)</p></li>
<li><p><strong>known_boundaries</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#tuple" title="(in Python v3.14)"><em>tuple</em></a><em>[</em><a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.14)"><em>str</em></a><em>, </em><em>...</em><em>]</em>)</p></li>
<li><p><strong>answer_constraints</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#dict" title="(in Python v3.14)"><em>dict</em></a>)</p></li>
<li><p><strong>preflight_result</strong> (<a class="reference external" href="https://docs.python.org/3/library/typing.html#typing.Literal" title="(in Python v3.14)"><em>Literal</em></a><em>[</em><em>'PREFLIGHT_OK'</em><em>, </em><em>'PREFLIGHT_PARTIAL'</em><em>, </em><em>'PREFLIGHT_BLOCKED'</em><em>]</em>)</p></li>
<li><p><strong>preflight_policy_hash</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.14)"><em>str</em></a>)</p></li>
<li><p><strong>classifier_version</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.14)"><em>str</em></a>)</p></li>
</ul>
</dd>
</dl>
<dl class="py attribute">
<dt class="sig sig-object py" id="aborist.qa.metacognition.QuestionState.raw_question">
<span class="sig-name descname"><span class="pre">raw_question</span></span><span class="property"><span class="p"><span class="pre">:</span></span><span class="w"> </span><a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.14)"><span class="pre">str</span></a></span><a class="headerlink" href="#aborist.qa.metacognition.QuestionState.raw_question" title="Link to this definition"></a></dt>
<dd></dd></dl>
<dl class="py attribute">
<dt class="sig sig-object py" id="aborist.qa.metacognition.QuestionState.question_hash">
<span class="sig-name descname"><span class="pre">question_hash</span></span><span class="property"><span class="p"><span class="pre">:</span></span><span class="w"> </span><a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.14)"><span class="pre">str</span></a></span><a class="headerlink" href="#aborist.qa.metacognition.QuestionState.question_hash" title="Link to this definition"></a></dt>
<dd></dd></dl>
<dl class="py attribute">
<dt class="sig sig-object py" id="aborist.qa.metacognition.QuestionState.logical_statuses">
<span class="sig-name descname"><span class="pre">logical_statuses</span></span><span class="property"><span class="p"><span class="pre">:</span></span><span class="w"> </span><a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#tuple" title="(in Python v3.14)"><span class="pre">tuple</span></a><span class="p"><span class="pre">[</span></span><a class="reference external" href="https://docs.python.org/3/library/typing.html#typing.Literal" title="(in Python v3.14)"><span class="pre">Literal</span></a><span class="p"><span class="pre">[</span></span><span class="s"><span class="pre">'well_formed'</span></span><span class="p"><span class="pre">,</span></span><span class="w"> </span><span class="s"><span class="pre">'under_specified'</span></span><span class="p"><span class="pre">,</span></span><span class="w"> </span><span class="s"><span class="pre">'false_premise_suspected'</span></span><span class="p"><span class="pre">,</span></span><span class="w"> </span><span class="s"><span class="pre">'contradictory_question'</span></span><span class="p"><span class="pre">,</span></span><span class="w"> </span><span class="s"><span class="pre">'out_of_corpus_risk'</span></span><span class="p"><span class="pre">,</span></span><span class="w"> </span><span class="s"><span class="pre">'stale_risk'</span></span><span class="p"><span class="pre">,</span></span><span class="w"> </span><span class="s"><span class="pre">'reference_frame_ambiguous'</span></span><span class="p"><span class="pre">,</span></span><span class="w"> </span><span class="s"><span class="pre">'broad_quantifier_unbounded'</span></span><span class="p"><span class="pre">]</span></span><span class="p"><span class="pre">,</span></span><span class="w"> </span><span class="p"><span class="pre">...</span></span><span class="p"><span class="pre">]</span></span></span><a class="headerlink" href="#aborist.qa.metacognition.QuestionState.logical_statuses" title="Link to this definition"></a></dt>
<dd></dd></dl>
<dl class="py attribute">
<dt class="sig sig-object py" id="aborist.qa.metacognition.QuestionState.question_shape">
<span class="sig-name descname"><span class="pre">question_shape</span></span><span class="property"><span class="p"><span class="pre">:</span></span><span class="w"> </span><a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.14)"><span class="pre">str</span></a></span><a class="headerlink" href="#aborist.qa.metacognition.QuestionState.question_shape" title="Link to this definition"></a></dt>
<dd></dd></dl>
<dl class="py attribute">
<dt class="sig sig-object py" id="aborist.qa.metacognition.QuestionState.quantifier_intensity">
<span class="sig-name descname"><span class="pre">quantifier_intensity</span></span><span class="property"><span class="p"><span class="pre">:</span></span><span class="w"> </span><a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.14)"><span class="pre">str</span></a><span class="w"> </span><span class="p"><span class="pre">|</span></span><span class="w"> </span><a class="reference external" href="https://docs.python.org/3/library/constants.html#None" title="(in Python v3.14)"><span class="pre">None</span></a></span><a class="headerlink" href="#aborist.qa.metacognition.QuestionState.quantifier_intensity" title="Link to this definition"></a></dt>
<dd></dd></dl>
<dl class="py attribute">
<dt class="sig sig-object py" id="aborist.qa.metacognition.QuestionState.quantifier_matched_token">
<span class="sig-name descname"><span class="pre">quantifier_matched_token</span></span><span class="property"><span class="p"><span class="pre">:</span></span><span class="w"> </span><a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.14)"><span class="pre">str</span></a><span class="w"> </span><span class="p"><span class="pre">|</span></span><span class="w"> </span><a class="reference external" href="https://docs.python.org/3/library/constants.html#None" title="(in Python v3.14)"><span class="pre">None</span></a></span><a class="headerlink" href="#aborist.qa.metacognition.QuestionState.quantifier_matched_token" title="Link to this definition"></a></dt>
<dd></dd></dl>
<dl class="py attribute">
<dt class="sig sig-object py" id="aborist.qa.metacognition.QuestionState.scope_bound_hint">
<span class="sig-name descname"><span class="pre">scope_bound_hint</span></span><span class="property"><span class="p"><span class="pre">:</span></span><span class="w"> </span><a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.14)"><span class="pre">str</span></a></span><a class="headerlink" href="#aborist.qa.metacognition.QuestionState.scope_bound_hint" title="Link to this definition"></a></dt>
<dd></dd></dl>
<dl class="py attribute">
<dt class="sig sig-object py" id="aborist.qa.metacognition.QuestionState.reference_frames">
<span class="sig-name descname"><span class="pre">reference_frames</span></span><span class="property"><span class="p"><span class="pre">:</span></span><span class="w"> </span><a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#tuple" title="(in Python v3.14)"><span class="pre">tuple</span></a><span class="p"><span class="pre">[</span></span><a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.14)"><span class="pre">str</span></a><span class="p"><span class="pre">,</span></span><span class="w"> </span><span class="p"><span class="pre">...</span></span><span class="p"><span class="pre">]</span></span></span><a class="headerlink" href="#aborist.qa.metacognition.QuestionState.reference_frames" title="Link to this definition"></a></dt>
<dd></dd></dl>
<dl class="py attribute">
<dt class="sig sig-object py" id="aborist.qa.metacognition.QuestionState.temporal_sensitivity">
<span class="sig-name descname"><span class="pre">temporal_sensitivity</span></span><span class="property"><span class="p"><span class="pre">:</span></span><span class="w"> </span><a class="reference external" href="https://docs.python.org/3/library/typing.html#typing.Literal" title="(in Python v3.14)"><span class="pre">Literal</span></a><span class="p"><span class="pre">[</span></span><span class="s"><span class="pre">'high'</span></span><span class="p"><span class="pre">,</span></span><span class="w"> </span><span class="s"><span class="pre">'medium'</span></span><span class="p"><span class="pre">,</span></span><span class="w"> </span><span class="s"><span class="pre">'low'</span></span><span class="p"><span class="pre">]</span></span></span><a class="headerlink" href="#aborist.qa.metacognition.QuestionState.temporal_sensitivity" title="Link to this definition"></a></dt>
<dd></dd></dl>
<dl class="py attribute">
<dt class="sig sig-object py" id="aborist.qa.metacognition.QuestionState.temporal_matched_tokens">
<span class="sig-name descname"><span class="pre">temporal_matched_tokens</span></span><span class="property"><span class="p"><span class="pre">:</span></span><span class="w"> </span><a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#tuple" title="(in Python v3.14)"><span class="pre">tuple</span></a><span class="p"><span class="pre">[</span></span><a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.14)"><span class="pre">str</span></a><span class="p"><span class="pre">,</span></span><span class="w"> </span><span class="p"><span class="pre">...</span></span><span class="p"><span class="pre">]</span></span></span><a class="headerlink" href="#aborist.qa.metacognition.QuestionState.temporal_matched_tokens" title="Link to this definition"></a></dt>
<dd></dd></dl>
<dl class="py attribute">
<dt class="sig sig-object py" id="aborist.qa.metacognition.QuestionState.contradiction_pairs">
<span class="sig-name descname"><span class="pre">contradiction_pairs</span></span><span class="property"><span class="p"><span class="pre">:</span></span><span class="w"> </span><a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#tuple" title="(in Python v3.14)"><span class="pre">tuple</span></a><span class="p"><span class="pre">[</span></span><a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#tuple" title="(in Python v3.14)"><span class="pre">tuple</span></a><span class="p"><span class="pre">[</span></span><a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.14)"><span class="pre">str</span></a><span class="p"><span class="pre">,</span></span><span class="w"> </span><a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.14)"><span class="pre">str</span></a><span class="p"><span class="pre">]</span></span><span class="p"><span class="pre">,</span></span><span class="w"> </span><span class="p"><span class="pre">...</span></span><span class="p"><span class="pre">]</span></span></span><a class="headerlink" href="#aborist.qa.metacognition.QuestionState.contradiction_pairs" title="Link to this definition"></a></dt>
<dd></dd></dl>
<dl class="py attribute">
<dt class="sig sig-object py" id="aborist.qa.metacognition.QuestionState.false_premise_hints">
<span class="sig-name descname"><span class="pre">false_premise_hints</span></span><span class="property"><span class="p"><span class="pre">:</span></span><span class="w"> </span><a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#tuple" title="(in Python v3.14)"><span class="pre">tuple</span></a><span class="p"><span class="pre">[</span></span><a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#dict" title="(in Python v3.14)"><span class="pre">dict</span></a><span class="p"><span class="pre">,</span></span><span class="w"> </span><span class="p"><span class="pre">...</span></span><span class="p"><span class="pre">]</span></span></span><a class="headerlink" href="#aborist.qa.metacognition.QuestionState.false_premise_hints" title="Link to this definition"></a></dt>
<dd></dd></dl>
<dl class="py attribute">
<dt class="sig sig-object py" id="aborist.qa.metacognition.QuestionState.corpus_requirement">
<span class="sig-name descname"><span class="pre">corpus_requirement</span></span><span class="property"><span class="p"><span class="pre">:</span></span><span class="w"> </span><a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.14)"><span class="pre">str</span></a></span><a class="headerlink" href="#aborist.qa.metacognition.QuestionState.corpus_requirement" title="Link to this definition"></a></dt>
<dd></dd></dl>
<dl class="py attribute">
<dt class="sig sig-object py" id="aborist.qa.metacognition.QuestionState.known_boundaries">
<span class="sig-name descname"><span class="pre">known_boundaries</span></span><span class="property"><span class="p"><span class="pre">:</span></span><span class="w"> </span><a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#tuple" title="(in Python v3.14)"><span class="pre">tuple</span></a><span class="p"><span class="pre">[</span></span><a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.14)"><span class="pre">str</span></a><span class="p"><span class="pre">,</span></span><span class="w"> </span><span class="p"><span class="pre">...</span></span><span class="p"><span class="pre">]</span></span></span><a class="headerlink" href="#aborist.qa.metacognition.QuestionState.known_boundaries" title="Link to this definition"></a></dt>
<dd></dd></dl>
<dl class="py attribute">
<dt class="sig sig-object py" id="aborist.qa.metacognition.QuestionState.answer_constraints">
<span class="sig-name descname"><span class="pre">answer_constraints</span></span><span class="property"><span class="p"><span class="pre">:</span></span><span class="w"> </span><a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#dict" title="(in Python v3.14)"><span class="pre">dict</span></a></span><a class="headerlink" href="#aborist.qa.metacognition.QuestionState.answer_constraints" title="Link to this definition"></a></dt>
<dd></dd></dl>
<dl class="py attribute">
<dt class="sig sig-object py" id="aborist.qa.metacognition.QuestionState.preflight_result">
<span class="sig-name descname"><span class="pre">preflight_result</span></span><span class="property"><span class="p"><span class="pre">:</span></span><span class="w"> </span><a class="reference external" href="https://docs.python.org/3/library/typing.html#typing.Literal" title="(in Python v3.14)"><span class="pre">Literal</span></a><span class="p"><span class="pre">[</span></span><span class="s"><span class="pre">'PREFLIGHT_OK'</span></span><span class="p"><span class="pre">,</span></span><span class="w"> </span><span class="s"><span class="pre">'PREFLIGHT_PARTIAL'</span></span><span class="p"><span class="pre">,</span></span><span class="w"> </span><span class="s"><span class="pre">'PREFLIGHT_BLOCKED'</span></span><span class="p"><span class="pre">]</span></span></span><a class="headerlink" href="#aborist.qa.metacognition.QuestionState.preflight_result" title="Link to this definition"></a></dt>
<dd></dd></dl>
<dl class="py attribute">
<dt class="sig sig-object py" id="aborist.qa.metacognition.QuestionState.preflight_policy_hash">
<span class="sig-name descname"><span class="pre">preflight_policy_hash</span></span><span class="property"><span class="p"><span class="pre">:</span></span><span class="w"> </span><a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.14)"><span class="pre">str</span></a></span><a class="headerlink" href="#aborist.qa.metacognition.QuestionState.preflight_policy_hash" title="Link to this definition"></a></dt>
<dd></dd></dl>
<dl class="py attribute">
<dt class="sig sig-object py" id="aborist.qa.metacognition.QuestionState.classifier_version">
<span class="sig-name descname"><span class="pre">classifier_version</span></span><span class="property"><span class="p"><span class="pre">:</span></span><span class="w"> </span><a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.14)"><span class="pre">str</span></a></span><span class="property"><span class="w"> </span><span class="p"><span class="pre">=</span></span><span class="w"> </span><span class="pre">'metacognition-v0.1'</span></span><a class="headerlink" href="#aborist.qa.metacognition.QuestionState.classifier_version" title="Link to this definition"></a></dt>
<dd></dd></dl>
<dl class="py method">
<dt class="sig sig-object py" id="aborist.qa.metacognition.QuestionState.to_dict">
<span class="sig-name descname"><span class="pre">to_dict</span></span><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="reference internal" href="../_modules/aborist/qa/metacognition.html#QuestionState.to_dict"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#aborist.qa.metacognition.QuestionState.to_dict" title="Link to this definition"></a></dt>
<dd><p>Convert to JSON-serializable dict for run-DAG / bench.</p>
<dl class="field-list simple">
<dt class="field-odd">Return type<span class="colon">:</span></dt>
<dd class="field-odd"><p><a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#dict" title="(in Python v3.14)">dict</a></p>
</dd>
</dl>
</dd></dl>
</dd></dl>
<dl class="py function">
<dt class="sig sig-object py" id="aborist.qa.metacognition.detect_temporal_sensitivity">
<span class="sig-prename descclassname"><span class="pre">aborist.qa.metacognition.</span></span><span class="sig-name descname"><span class="pre">detect_temporal_sensitivity</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">question</span></span></em><span class="sig-paren">)</span><a class="reference internal" href="../_modules/aborist/qa/metacognition.html#detect_temporal_sensitivity"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#aborist.qa.metacognition.detect_temporal_sensitivity" title="Link to this definition"></a></dt>
<dd><p>Return <code class="docutils literal notranslate"><span class="pre">(sensitivity,</span> <span class="pre">matched_tokens)</span></code>.</p>
<p><cite>high</cite> = explicit temporal anchor (<cite>current</cite>, <cite>latest</cite>, etc.)
OR rapid-turnover role pattern. <cite>medium</cite> reserved for future
weekly/monthly cadence detection (not implemented in this
pass). <cite>low</cite> = no temporal markers detected (the default).</p>
<dl class="field-list simple">
<dt class="field-odd">Parameters<span class="colon">:</span></dt>
<dd class="field-odd"><p><strong>question</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.14)"><em>str</em></a>)</p>
</dd>
<dt class="field-even">Return type<span class="colon">:</span></dt>
<dd class="field-even"><p><a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#tuple" title="(in Python v3.14)">tuple</a>[<a class="reference external" href="https://docs.python.org/3/library/typing.html#typing.Literal" title="(in Python v3.14)"><em>Literal</em></a>[high, medium, low], tuple[str, …]]</p>
</dd>
</dl>
</dd></dl>
<dl class="py function">
<dt class="sig sig-object py" id="aborist.qa.metacognition.detect_contradiction">
<span class="sig-prename descclassname"><span class="pre">aborist.qa.metacognition.</span></span><span class="sig-name descname"><span class="pre">detect_contradiction</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">question</span></span></em><span class="sig-paren">)</span><a class="reference internal" href="../_modules/aborist/qa/metacognition.html#detect_contradiction"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#aborist.qa.metacognition.detect_contradiction" title="Link to this definition"></a></dt>
<dd><p>Return tuple of (token_a, token_b) pairs whose BOTH members
appear in <code class="docutils literal notranslate"><span class="pre">question</span></code> (case-insensitive whole-word match).</p>
<p>Returns empty tuple when no contradiction detected. The caller
decides whether to label-only or block — by default this
surfaces in the audit-line tail, NOT a hard block, since false
positives on contradiction would refuse legitimate questions.</p>
<dl class="field-list simple">
<dt class="field-odd">Parameters<span class="colon">:</span></dt>
<dd class="field-odd"><p><strong>question</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.14)"><em>str</em></a>)</p>
</dd>
<dt class="field-even">Return type<span class="colon">:</span></dt>
<dd class="field-even"><p><a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#tuple" title="(in Python v3.14)">tuple</a>[<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#tuple" title="(in Python v3.14)">tuple</a>[<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.14)">str</a>, <a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.14)">str</a>], …]</p>
</dd>
</dl>
</dd></dl>
<dl class="py function">
<dt class="sig sig-object py" id="aborist.qa.metacognition.detect_false_premise">
<span class="sig-prename descclassname"><span class="pre">aborist.qa.metacognition.</span></span><span class="sig-name descname"><span class="pre">detect_false_premise</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">question</span></span></em><span class="sig-paren">)</span><a class="reference internal" href="../_modules/aborist/qa/metacognition.html#detect_false_premise"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#aborist.qa.metacognition.detect_false_premise" title="Link to this definition"></a></dt>
<dd><p>Return tuple of presupposition dicts surfacing the implied
relation. Each dict carries:</p>
<blockquote>
<div><p>kind — pattern label (stopped_doing, caused, …)
presupposition — natural-language statement of the</p>
<blockquote>
<div><p>presupposition</p>
</div></blockquote>
<p>subject — extracted subject token-span
predicate — extracted predicate token-span</p>
</div></blockquote>
<p>First-pass detection only. The verifier uses these as soft
hints; downstream the audit-line tail surfaces “false premise
suspected” so the operator can read the audit log and check
whether the cited evidence supports the presupposition.</p>
<p>Returns empty tuple when no pattern fires.</p>
<dl class="field-list simple">
<dt class="field-odd">Parameters<span class="colon">:</span></dt>
<dd class="field-odd"><p><strong>question</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.14)"><em>str</em></a>)</p>
</dd>
<dt class="field-even">Return type<span class="colon">:</span></dt>
<dd class="field-even"><p><a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#tuple" title="(in Python v3.14)">tuple</a>[<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#dict" title="(in Python v3.14)">dict</a>, …]</p>
</dd>
</dl>
</dd></dl>
<dl class="py function">
<dt class="sig sig-object py" id="aborist.qa.metacognition.detect_out_of_corpus">
<span class="sig-prename descclassname"><span class="pre">aborist.qa.metacognition.</span></span><span class="sig-name descname"><span class="pre">detect_out_of_corpus</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">question</span></span></em><span class="sig-paren">)</span><a class="reference internal" href="../_modules/aborist/qa/metacognition.html#detect_out_of_corpus"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#aborist.qa.metacognition.detect_out_of_corpus" title="Link to this definition"></a></dt>
<dd><p>Return True iff the question references a private / uploaded
document that the encyclopedic corpus cannot have.</p>
<dl class="field-list simple">
<dt class="field-odd">Parameters<span class="colon">:</span></dt>
<dd class="field-odd"><p><strong>question</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.14)"><em>str</em></a>)</p>
</dd>
<dt class="field-even">Return type<span class="colon">:</span></dt>
<dd class="field-even"><p><a class="reference external" href="https://docs.python.org/3/library/functions.html#bool" title="(in Python v3.14)">bool</a></p>
</dd>
</dl>
</dd></dl>
<dl class="py function">
<dt class="sig sig-object py" id="aborist.qa.metacognition.preflight_question">
<span class="sig-prename descclassname"><span class="pre">aborist.qa.metacognition.</span></span><span class="sig-name descname"><span class="pre">preflight_question</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">question</span></span></em>, <em class="sig-param"><span class="keyword-only-separator o"><abbr title="Keyword-only parameters separator (PEP 3102)"><span class="pre">*</span></abbr></span></em>, <em class="sig-param"><span class="n"><span class="pre">model_profile_id</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">corpus_profile</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">reference_frames</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">()</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">policy</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em><span class="sig-paren">)</span><a class="reference internal" href="../_modules/aborist/qa/metacognition.html#preflight_question"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#aborist.qa.metacognition.preflight_question" title="Link to this definition"></a></dt>
<dd><p>Classify <code class="docutils literal notranslate"><span class="pre">question</span></code> deterministically into a QuestionState.</p>
<p>Pure function. Reuses the Phase 1 quantifier classifier
(#000008) plus four new lightweight detectors (temporal,
contradiction, false-premise-lite, out-of-corpus).</p>
<p><cite>corpus_profile</cite> is an optional dict carrying corpus boundary
metadata (e.g. <code class="docutils literal notranslate"><span class="pre">{&quot;corpus_latest_timestamp&quot;:</span> <span class="pre">&quot;2003-05-16&quot;}</span></code>);
when present, the temporal detector cross-checks against it.
First-pass implementation just records <cite>corpus_requirement</cite>
based on the temporal sensitivity — full cutoff arithmetic
deferred to a future amend.</p>
<p><cite>reference_frames</cite> is passed in by the caller because frame
detection requires retrieved sources (lives in
<cite>aborist.qa.query._detect_frame</cite>). Empty tuple is the default
for “no frame routing happened”.</p>
<p><cite>policy</cite> overrides for the per-detector enables. Defaults are
permissive (all checks on) per ticket #000010 §7.3.</p>
<dl class="field-list simple">
<dt class="field-odd">Parameters<span class="colon">:</span></dt>
<dd class="field-odd"><ul class="simple">
<li><p><strong>question</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.14)"><em>str</em></a>)</p></li>
<li><p><strong>model_profile_id</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.14)"><em>str</em></a><em> | </em><em>None</em>)</p></li>
<li><p><strong>corpus_profile</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#dict" title="(in Python v3.14)"><em>dict</em></a><em> | </em><em>None</em>)</p></li>
<li><p><strong>reference_frames</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#tuple" title="(in Python v3.14)"><em>tuple</em></a><em>[</em><a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.14)"><em>str</em></a><em>, </em><em>...</em><em>]</em>)</p></li>
<li><p><strong>policy</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#dict" title="(in Python v3.14)"><em>dict</em></a><em> | </em><em>None</em>)</p></li>
</ul>
</dd>
<dt class="field-even">Return type<span class="colon">:</span></dt>
<dd class="field-even"><p><a class="reference internal" href="#aborist.qa.metacognition.QuestionState" title="aborist.qa.metacognition.QuestionState"><em>QuestionState</em></a></p>
</dd>
</dl>
</dd></dl>
</section>
<section id="module-aborist.qa.dag">
<span id="dag"></span><h2>dag<a class="headerlink" href="#module-aborist.qa.dag" title="Link to this heading"></a></h2>
<p>Per-run Merkle-DAG provenance for providence records.</p>
<p>Each query/ask call passes through several stages:</p>
<blockquote>
<div><p>question → retrieval → context → prompt → answer → verify → final_label</p>
</div></blockquote>
<p>Each stage emits a hash; the runs identity is the Merkle root over the
ordered sequence of stage hashes. Stored on the providence record as
<code class="docutils literal notranslate"><span class="pre">run_dag_root</span></code> (alongside <code class="docutils literal notranslate"><span class="pre">cache_key</span></code>). The DAG is verifiable: given
the persisted node list &amp; the same Merkle conventions aborist uses
elsewhere (non-commutative HashCombine, prefix 0x03, leaf prefix 0x00,
self-duplicate odd rule), an auditor can recompute the root from the
nodes &amp; confirm the run was constructed as recorded.</p>
<p>Distinct from the linear <code class="docutils literal notranslate"><span class="pre">audit_events</span></code> chain — that chain tracks
state-changing operations across the DB. This DAG tracks the
computation provenance of one specific answer. Both coexist; the
records <code class="docutils literal notranslate"><span class="pre">audit_event_hash</span></code> links to the chain, <code class="docutils literal notranslate"><span class="pre">run_dag_root</span></code> &amp;
<code class="docutils literal notranslate"><span class="pre">run_dag_blob</span></code> carry the per-run computation graph.</p>
<p>Stages chosen to mirror the toy-Hermes design (fox 2026-04-30):</p>
<blockquote>
<div><p>question hash of question_hash (8-dim cache_key dim)
retrieval hash of sources summary (document_roots + roles +</p>
<blockquote>
<div><p>scores) — captures which docs ranked &amp; how</p>
</div></blockquote>
<dl class="simple">
<dt>context context_root (Merkle root over sorted source roots,</dt><dd><p>the “source” dim of the cache_key)</p>
</dd>
</dl>
<p>prompt conversation_hash (the assembled messages)
answer sha256(answer_text)
verify hash of verdict summary (audit_mode, verifier_method,</p>
<blockquote>
<div><p>n_quotes, n_verified, claim_statuses)</p>
</div></blockquote>
<p>final_label hash of (audit_mode, verifier_method, lookup_path)</p>
</div></blockquote>
<p>The DAG is NOT part of cache_key. cache_key inputs (the 8 dims)
determine the answer; the answer determines the DAG. Folding the DAG
back into cache_key would create a circular dependency.</p>
<dl class="py function">
<dt class="sig sig-object py" id="aborist.qa.dag.localize_failure">
<span class="sig-prename descclassname"><span class="pre">aborist.qa.dag.</span></span><span class="sig-name descname"><span class="pre">localize_failure</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="keyword-only-separator o"><abbr title="Keyword-only parameters separator (PEP 3102)"><span class="pre">*</span></abbr></span></em>, <em class="sig-param"><span class="n"><span class="pre">audit_mode</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">n_sources</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">n_quotes</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">n_verified</span></span></em><span class="sig-paren">)</span><a class="reference internal" href="../_modules/aborist/qa/dag.html#localize_failure"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#aborist.qa.dag.localize_failure" title="Link to this definition"></a></dt>
<dd><p>Map a non-STRICT verdict to the pipeline stage that introduced
the failure. Returns <code class="docutils literal notranslate"><span class="pre">None</span></code> for STRICT outcomes.</p>
<p>Stage labels (in pipeline order):</p>
<ul class="simple">
<li><p><code class="docutils literal notranslate"><span class="pre">retrieval</span></code> — no admitted sources. Title/body gates rejected
everything, or the corpus genuinely lacks the topic. Repair path:
ingest more sources or relax the breadth threshold.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">context</span></code> — sources admitted but no quotes extracted. Could be
a context-truncation issue (per-source cap dropped the relevant
paragraph) or a model that declined to cite anything. Repair path:
raise per-source cap; tighten prompt.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">answer</span></code> — sources retrieved &amp; quotes extracted but they dont
verify. The model either fabricated content, paraphrased inside
quotes, or appended citation tails. Repair path: the
<code class="docutils literal notranslate"><span class="pre">mechanical_repair</span></code> pass + (when wired) the re-prompt feedback
loop.</p></li>
</ul>
<p>The toy-Hermes design pass calls this “chain-segment failure
localization” — debugging becomes typed instead of vague. An
operator reading <code class="docutils literal notranslate"><span class="pre">failure_stage='answer'</span></code> knows retrieval &amp;
context were fine; the model is what to fix. <code class="docutils literal notranslate"><span class="pre">failure_stage='retrieval'</span></code>
means stop tuning the verifier &amp; go ingest a relevant source.</p>
<dl class="field-list simple">
<dt class="field-odd">Parameters<span class="colon">:</span></dt>
<dd class="field-odd"><ul class="simple">
<li><p><strong>audit_mode</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.14)"><em>str</em></a>)</p></li>
<li><p><strong>n_sources</strong> (<a class="reference external" href="https://docs.python.org/3/library/functions.html#int" title="(in Python v3.14)"><em>int</em></a>)</p></li>
<li><p><strong>n_quotes</strong> (<a class="reference external" href="https://docs.python.org/3/library/functions.html#int" title="(in Python v3.14)"><em>int</em></a>)</p></li>
<li><p><strong>n_verified</strong> (<a class="reference external" href="https://docs.python.org/3/library/functions.html#int" title="(in Python v3.14)"><em>int</em></a>)</p></li>
</ul>
</dd>
<dt class="field-even">Return type<span class="colon">:</span></dt>
<dd class="field-even"><p><a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.14)">str</a> | None</p>
</dd>
</dl>
</dd></dl>
<dl class="py function">
<dt class="sig sig-object py" id="aborist.qa.dag.build_preflight_node_payload">
<span class="sig-prename descclassname"><span class="pre">aborist.qa.dag.</span></span><span class="sig-name descname"><span class="pre">build_preflight_node_payload</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="keyword-only-separator o"><abbr title="Keyword-only parameters separator (PEP 3102)"><span class="pre">*</span></abbr></span></em>, <em class="sig-param"><span class="n"><span class="pre">question_state</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">quantifier</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">answer_contract</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">prompt_contract</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">evidence_contract</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">policy_refs</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em><span class="sig-paren">)</span><a class="reference internal" href="../_modules/aborist/qa/dag.html#build_preflight_node_payload"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#aborist.qa.dag.build_preflight_node_payload" title="Link to this definition"></a></dt>
<dd><p>Build the canonical nested-clause payload for the preflight
DAG stage. Returns a JSON-ready dict; pair with
<a class="reference internal" href="#aborist.qa.dag.preflight_node_hash" title="aborist.qa.dag.preflight_node_hash"><code class="xref py py-func docutils literal notranslate"><span class="pre">preflight_node_hash()</span></code></a> to get the SHA-256 hex.</p>
<p>Five-clause structure per ticket #000009 §8.2 / feedback §3:</p>
<ul class="simple">
<li><p><code class="docutils literal notranslate"><span class="pre">classifier</span></code> — quantifier classifier output (#000008):
intensity, matched_token, explicit_count, scope_bound_hint,
is_broad, classifier_version, operational_shape.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">answer_contract</span></code> — guard / cap / reject decisions taken
on this run.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">prompt_contract</span></code> — reminder enabled / injected /
template_id (#000008 §10.5).</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">evidence_contract</span></code> — exposure budget, one-claim-per-line
discipline (#000010 §10.4).</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">policy_refs</span></code> — governance_policy_hash + model_profile_hash
+ answer_mode. Reference-by-hash rather than raw policy
bundles (feedback §4: avoid double-committing
already-hashed state).</p></li>
</ul>
<p>Plus the metacog <code class="docutils literal notranslate"><span class="pre">question_state</span></code> from #000010 — thats its
own clause for now (logical_statuses, false_premise_hints,
contradiction_pairs). Its hashed separately by
<cite>metacognition.preflight_policy_hash</cite> already.</p>
<p>Any clause may be None / empty — the resulting payload is
still stable. Includes <code class="docutils literal notranslate"><span class="pre">node_version</span></code> so legacy runs without
the node can be unambiguously labeled <cite>unavailable_legacy_run</cite>
by audit tools.</p>
<dl class="field-list simple">
<dt class="field-odd">Parameters<span class="colon">:</span></dt>
<dd class="field-odd"><ul class="simple">
<li><p><strong>question_state</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#dict" title="(in Python v3.14)"><em>dict</em></a><em> | </em><em>None</em>)</p></li>
<li><p><strong>quantifier</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#dict" title="(in Python v3.14)"><em>dict</em></a><em> | </em><em>None</em>)</p></li>
<li><p><strong>answer_contract</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#dict" title="(in Python v3.14)"><em>dict</em></a><em> | </em><em>None</em>)</p></li>
<li><p><strong>prompt_contract</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#dict" title="(in Python v3.14)"><em>dict</em></a><em> | </em><em>None</em>)</p></li>
<li><p><strong>evidence_contract</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#dict" title="(in Python v3.14)"><em>dict</em></a><em> | </em><em>None</em>)</p></li>
<li><p><strong>policy_refs</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#dict" title="(in Python v3.14)"><em>dict</em></a><em> | </em><em>None</em>)</p></li>
</ul>
</dd>
<dt class="field-even">Return type<span class="colon">:</span></dt>
<dd class="field-even"><p><a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#dict" title="(in Python v3.14)">dict</a></p>
</dd>
</dl>
</dd></dl>
<dl class="py function">
<dt class="sig sig-object py" id="aborist.qa.dag.preflight_node_hash">
<span class="sig-prename descclassname"><span class="pre">aborist.qa.dag.</span></span><span class="sig-name descname"><span class="pre">preflight_node_hash</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="keyword-only-separator o"><abbr title="Keyword-only parameters separator (PEP 3102)"><span class="pre">*</span></abbr></span></em>, <em class="sig-param"><span class="n"><span class="pre">question_state</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">quantifier</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">answer_contract</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">prompt_contract</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">evidence_contract</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">policy_refs</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em><span class="sig-paren">)</span><a class="reference internal" href="../_modules/aborist/qa/dag.html#preflight_node_hash"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#aborist.qa.dag.preflight_node_hash" title="Link to this definition"></a></dt>
<dd><p>Hash the preflight decision into a stable SHA-256 hex string.</p>
<p>Returns the hash of the nested-clause payload built by
<a class="reference internal" href="#aborist.qa.dag.build_preflight_node_payload" title="aborist.qa.dag.build_preflight_node_payload"><code class="xref py py-func docutils literal notranslate"><span class="pre">build_preflight_node_payload()</span></code></a>. See that function for the
five-clause structure.</p>
<p>Audit-replay payoff: two cache rows that share the same
question + same model output + same verifier verdict but
different preflight policy state produce different hashes
here, which propagate to <code class="docutils literal notranslate"><span class="pre">run_dag_root</span></code> via
<a class="reference internal" href="#aborist.qa.dag.build_run_dag" title="aborist.qa.dag.build_run_dag"><code class="xref py py-func docutils literal notranslate"><span class="pre">build_run_dag()</span></code></a>.</p>
<p>Backward compatibility note: Pre-2026-05-04 (<cite>c36e85c</cite>) callers
used a flat 3-key payload (<cite>question_state</cite> / <cite>quantifier</cite> /
<cite>policy_state</cite>). Hashes computed with that callsite will NOT
match this restructured callsite — <cite>run_dag_root</cite> values for
rows written between <cite>c36e85c</cite> and the current commit are
treated as a discrete generation; theyre still verifiable by
re-reading <cite>run_dag_blob</cite> (the persisted blob captures the
payload that was actually hashed).</p>
<dl class="field-list simple">
<dt class="field-odd">Parameters<span class="colon">:</span></dt>
<dd class="field-odd"><ul class="simple">
<li><p><strong>question_state</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#dict" title="(in Python v3.14)"><em>dict</em></a><em> | </em><em>None</em>)</p></li>
<li><p><strong>quantifier</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#dict" title="(in Python v3.14)"><em>dict</em></a><em> | </em><em>None</em>)</p></li>
<li><p><strong>answer_contract</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#dict" title="(in Python v3.14)"><em>dict</em></a><em> | </em><em>None</em>)</p></li>
<li><p><strong>prompt_contract</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#dict" title="(in Python v3.14)"><em>dict</em></a><em> | </em><em>None</em>)</p></li>
<li><p><strong>evidence_contract</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#dict" title="(in Python v3.14)"><em>dict</em></a><em> | </em><em>None</em>)</p></li>
<li><p><strong>policy_refs</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#dict" title="(in Python v3.14)"><em>dict</em></a><em> | </em><em>None</em>)</p></li>
</ul>
</dd>
<dt class="field-even">Return type<span class="colon">:</span></dt>
<dd class="field-even"><p><a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.14)">str</a></p>
</dd>
</dl>
</dd></dl>
<dl class="py function">
<dt class="sig sig-object py" id="aborist.qa.dag.build_run_dag">
<span class="sig-prename descclassname"><span class="pre">aborist.qa.dag.</span></span><span class="sig-name descname"><span class="pre">build_run_dag</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="keyword-only-separator o"><abbr title="Keyword-only parameters separator (PEP 3102)"><span class="pre">*</span></abbr></span></em>, <em class="sig-param"><span class="n"><span class="pre">question_hash</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">sources</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">context_root</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">conversation_hash</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">answer_text</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">audit_mode</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">verifier_method</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">n_quotes</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">n_verified</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">claim_statuses</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">lookup_path</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">evidence_map_root</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">answer_mode</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">violations</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">raw_answer_text</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">parsed_lattice</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">rendered_text</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">retrieval_plan_hash</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">preflight_hash</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">preflight_payload</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em><span class="sig-paren">)</span><a class="reference internal" href="../_modules/aborist/qa/dag.html#build_run_dag"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#aborist.qa.dag.build_run_dag" title="Link to this definition"></a></dt>
<dd><p>Return <code class="docutils literal notranslate"><span class="pre">{&quot;root&quot;:</span> <span class="pre">&lt;hex&gt;,</span> <span class="pre">&quot;nodes&quot;:</span> <span class="pre">[&lt;stage&gt;,</span> <span class="pre">&lt;hash&gt;],</span> <span class="pre">...}</span></code>.</p>
<p>All inputs are already-computed hashes or text; no I/O. Idempotent &amp;
deterministic — same inputs always produce the same root, byte-for-
byte across machines (as long as the Merkle conventions stay pinned;
they do, via <code class="docutils literal notranslate"><span class="pre">aborist.merkle</span></code>).</p>
<p>Two base DAG shapes; both gain an optional <code class="docutils literal notranslate"><span class="pre">preflight</span></code> stage
when <code class="docutils literal notranslate"><span class="pre">preflight_hash</span></code> is supplied (Ticket #000009):</p>
<ul class="simple">
<li><p><strong>Quote mode (default).</strong> 7 stages —
<code class="docutils literal notranslate"><span class="pre">question</span> <span class="pre">/</span> <span class="pre">retrieval</span> <span class="pre">/</span> <span class="pre">context</span> <span class="pre">/</span> <span class="pre">prompt</span> <span class="pre">/</span> <span class="pre">answer</span> <span class="pre">/</span> <span class="pre">verify</span> <span class="pre">/</span>
<span class="pre">final_label</span></code>. Triggered when <code class="docutils literal notranslate"><span class="pre">evidence_map_root</span></code> is None.
Backward-compatible with all run_dag_root values written by code
that pre-dates G0. With <code class="docutils literal notranslate"><span class="pre">preflight_hash</span></code>, becomes 8 stages —
<code class="docutils literal notranslate"><span class="pre">question</span> <span class="pre">/</span> <span class="pre">preflight</span> <span class="pre">/</span> <span class="pre">retrieval</span> <span class="pre">/</span> <span class="pre">...</span></code>.</p></li>
<li><p><strong>Claim-lattice-pointer mode (G0 / CTI).</strong> 9 stages —
<code class="docutils literal notranslate"><span class="pre">question</span> <span class="pre">/</span> <span class="pre">retrieval</span> <span class="pre">/</span> <span class="pre">evidence_map</span> <span class="pre">/</span> <span class="pre">prompt</span> <span class="pre">/</span> <span class="pre">raw_answer</span> <span class="pre">/</span>
<span class="pre">parsed_claim_lattice</span> <span class="pre">/</span> <span class="pre">verify</span> <span class="pre">/</span> <span class="pre">render</span> <span class="pre">/</span> <span class="pre">final_label</span></code>. Triggered
when <code class="docutils literal notranslate"><span class="pre">evidence_map_root</span></code> is non-None. Splits the single
<code class="docutils literal notranslate"><span class="pre">answer</span></code> node into three: the models raw output, the parsed
claim-lattice, and the rendered prose with literal spans
interpolated. <code class="docutils literal notranslate"><span class="pre">context</span></code> drops out (the context IS the evidence
map). All three of <code class="docutils literal notranslate"><span class="pre">raw_answer_text</span></code> / <code class="docutils literal notranslate"><span class="pre">parsed_lattice</span></code> /
<code class="docutils literal notranslate"><span class="pre">rendered_text</span></code> should be supplied; missing args fall back to
<code class="docutils literal notranslate"><span class="pre">answer_text</span></code> for the raw_answer &amp; render hashes and <code class="docutils literal notranslate"><span class="pre">[]</span></code> for
the parsed_lattice hash. With <code class="docutils literal notranslate"><span class="pre">preflight_hash</span></code>, becomes 10
stages.</p></li>
</ul>
<p><code class="docutils literal notranslate"><span class="pre">answer_mode</span></code> &amp; <code class="docutils literal notranslate"><span class="pre">violations</span></code> fold into the verify &amp; final_label
payloads when provided. <code class="docutils literal notranslate"><span class="pre">preflight_hash</span></code> (Ticket #000009) is
optional; when None, the DAG shape remains 7/9 stages exactly so
pre-#000009 records can be re-validated. When supplied, the
preflight stage inserts at position 1 (between <code class="docutils literal notranslate"><span class="pre">question</span></code> and
<code class="docutils literal notranslate"><span class="pre">retrieval</span></code>) per ticket #000009 §3.1.</p>
<dl class="field-list simple">
<dt class="field-odd">Parameters<span class="colon">:</span></dt>
<dd class="field-odd"><ul class="simple">
<li><p><strong>question_hash</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.14)"><em>str</em></a>)</p></li>
<li><p><strong>sources</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#list" title="(in Python v3.14)"><em>list</em></a><em>[</em><a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#dict" title="(in Python v3.14)"><em>dict</em></a><em>]</em>)</p></li>
<li><p><strong>context_root</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.14)"><em>str</em></a>)</p></li>
<li><p><strong>conversation_hash</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.14)"><em>str</em></a>)</p></li>
<li><p><strong>answer_text</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.14)"><em>str</em></a>)</p></li>
<li><p><strong>audit_mode</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.14)"><em>str</em></a>)</p></li>
<li><p><strong>verifier_method</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.14)"><em>str</em></a>)</p></li>
<li><p><strong>n_quotes</strong> (<a class="reference external" href="https://docs.python.org/3/library/functions.html#int" title="(in Python v3.14)"><em>int</em></a>)</p></li>
<li><p><strong>n_verified</strong> (<a class="reference external" href="https://docs.python.org/3/library/functions.html#int" title="(in Python v3.14)"><em>int</em></a>)</p></li>
<li><p><strong>claim_statuses</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#list" title="(in Python v3.14)"><em>list</em></a><em>[</em><a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#dict" title="(in Python v3.14)"><em>dict</em></a><em>] </em><em>| </em><em>None</em>)</p></li>
<li><p><strong>lookup_path</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.14)"><em>str</em></a><em> | </em><em>None</em>)</p></li>
<li><p><strong>evidence_map_root</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.14)"><em>str</em></a><em> | </em><em>None</em>)</p></li>
<li><p><strong>answer_mode</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.14)"><em>str</em></a><em> | </em><em>None</em>)</p></li>
<li><p><strong>violations</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#list" title="(in Python v3.14)"><em>list</em></a><em>[</em><a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#dict" title="(in Python v3.14)"><em>dict</em></a><em>] </em><em>| </em><em>None</em>)</p></li>
<li><p><strong>raw_answer_text</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.14)"><em>str</em></a><em> | </em><em>None</em>)</p></li>
<li><p><strong>parsed_lattice</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#list" title="(in Python v3.14)"><em>list</em></a><em> | </em><em>None</em>)</p></li>
<li><p><strong>rendered_text</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.14)"><em>str</em></a><em> | </em><em>None</em>)</p></li>
<li><p><strong>retrieval_plan_hash</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.14)"><em>str</em></a><em> | </em><em>None</em>)</p></li>
<li><p><strong>preflight_hash</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.14)"><em>str</em></a><em> | </em><em>None</em>)</p></li>
<li><p><strong>preflight_payload</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#dict" title="(in Python v3.14)"><em>dict</em></a><em> | </em><em>None</em>)</p></li>
</ul>
</dd>
<dt class="field-even">Return type<span class="colon">:</span></dt>
<dd class="field-even"><p><a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#dict" title="(in Python v3.14)">dict</a></p>
</dd>
</dl>
</dd></dl>
<dl class="py function">
<dt class="sig sig-object py" id="aborist.qa.dag.build_reject_run_dag">
<span class="sig-prename descclassname"><span class="pre">aborist.qa.dag.</span></span><span class="sig-name descname"><span class="pre">build_reject_run_dag</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="keyword-only-separator o"><abbr title="Keyword-only parameters separator (PEP 3102)"><span class="pre">*</span></abbr></span></em>, <em class="sig-param"><span class="n"><span class="pre">question_hash</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">preflight_hash</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">rejection_reason</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">answer_text</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">audit_mode</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">'UNGROUNDED'</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">verifier_method</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">'claim_lattice_pointer'</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">violations</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">preflight_payload</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em><span class="sig-paren">)</span><a class="reference internal" href="../_modules/aborist/qa/dag.html#build_reject_run_dag"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#aborist.qa.dag.build_reject_run_dag" title="Link to this definition"></a></dt>
<dd><p>3-stage reject-broad run-DAG: <code class="docutils literal notranslate"><span class="pre">question</span> <span class="pre"></span> <span class="pre">preflight</span> <span class="pre"></span>
<span class="pre">final_label</span></code>.</p>
<p>Ticket #000009 §8.2 / 2026-05-04 feedback §6.2: preflight
rejection currently early-returns from <code class="docutils literal notranslate"><span class="pre">query()</span></code> before the
standard <code class="docutils literal notranslate"><span class="pre">build_run_dag()</span></code> runs, so reject rows have no
auditable Merkle commitment. This builder fills that gap with
a minimal DAG shape that captures the rejection without
pretending retrieval / prompt / raw_model_output happened.</p>
<p>The returned shape is INTENTIONALLY shorter than the standard
7/9/8/10-stage shapes — <cite>audit replay can read the stage
list</cite> and tell instantly that this row is a preflight
rejection: 3 stages always means reject path.</p>
<p><cite>final_label</cite> carries the rejection_reason + answer_text hash
so two rejections that differ only in their (rendered)
rationale string still produce different roots. The
rejection_reason is the canonical string from the violation
(<cite>“preflight rejection — broad-quantifier query with
unbounded scope. …”</cite>), NOT the operator-facing rendered
answer_text — that lets policy template changes invalidate
the hash even if the operator-visible text is unchanged.</p>
<dl class="field-list simple">
<dt class="field-odd">Parameters<span class="colon">:</span></dt>
<dd class="field-odd"><ul class="simple">
<li><p><strong>question_hash</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.14)"><em>str</em></a>)</p></li>
<li><p><strong>preflight_hash</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.14)"><em>str</em></a>)</p></li>
<li><p><strong>rejection_reason</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.14)"><em>str</em></a>)</p></li>
<li><p><strong>answer_text</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.14)"><em>str</em></a>)</p></li>
<li><p><strong>audit_mode</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.14)"><em>str</em></a>)</p></li>
<li><p><strong>verifier_method</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.14)"><em>str</em></a>)</p></li>
<li><p><strong>violations</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#list" title="(in Python v3.14)"><em>list</em></a><em>[</em><a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#dict" title="(in Python v3.14)"><em>dict</em></a><em>] </em><em>| </em><em>None</em>)</p></li>
<li><p><strong>preflight_payload</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#dict" title="(in Python v3.14)"><em>dict</em></a><em> | </em><em>None</em>)</p></li>
</ul>
</dd>
<dt class="field-even">Return type<span class="colon">:</span></dt>
<dd class="field-even"><p><a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#dict" title="(in Python v3.14)">dict</a></p>
</dd>
</dl>
</dd></dl>
<dl class="py function">
<dt class="sig sig-object py" id="aborist.qa.dag.verify_run_dag">
<span class="sig-prename descclassname"><span class="pre">aborist.qa.dag.</span></span><span class="sig-name descname"><span class="pre">verify_run_dag</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">blob</span></span></em><span class="sig-paren">)</span><a class="reference internal" href="../_modules/aborist/qa/dag.html#verify_run_dag"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#aborist.qa.dag.verify_run_dag" title="Link to this definition"></a></dt>
<dd><p>Recompute the Merkle root from <code class="docutils literal notranslate"><span class="pre">blob</span></code> and check it matches.</p>
<p>Used by audit tooling. Accepts either a parsed dict or the JSON
string we persist in <code class="docutils literal notranslate"><span class="pre">providence_cache.run_dag_blob</span></code>.</p>
<dl class="field-list simple">
<dt class="field-odd">Parameters<span class="colon">:</span></dt>
<dd class="field-odd"><p><strong>blob</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.14)"><em>str</em></a><em> | </em><a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#dict" title="(in Python v3.14)"><em>dict</em></a>)</p>
</dd>
<dt class="field-even">Return type<span class="colon">:</span></dt>
<dd class="field-even"><p><a class="reference external" href="https://docs.python.org/3/library/functions.html#bool" title="(in Python v3.14)">bool</a></p>
</dd>
</dl>
</dd></dl>
</section>
<section id="module-aborist.qa.client">
<span id="client"></span><h2>client<a class="headerlink" href="#module-aborist.qa.client" title="Link to this heading"></a></h2>
<p>Chat-completion clients.</p>
<p>ChatClient is a Protocol — any object with a <cite>chat_completion</cite> method
plugs in. We ship two concrete clients:</p>
<ul class="simple">
<li><p>OpenAICompatibleClient — talks to any OpenAI-compatible /v1/chat/completions
endpoint (vllm, llama.cpp server, ollama, TGI, hosted services).</p></li>
<li><p>StubClient — offline canned responses for tests and dry-runs. No
network. Operation Voyeur safe.</p></li>
</ul>
<dl class="py class">
<dt class="sig sig-object py" id="aborist.qa.client.ChatClient">
<span class="property"><span class="k"><span class="pre">class</span></span><span class="w"> </span></span><span class="sig-prename descclassname"><span class="pre">aborist.qa.client.</span></span><span class="sig-name descname"><span class="pre">ChatClient</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="o"><span class="pre">*</span></span><span class="n"><span class="pre">args</span></span></em>, <em class="sig-param"><span class="o"><span class="pre">**</span></span><span class="n"><span class="pre">kwargs</span></span></em><span class="sig-paren">)</span><a class="reference internal" href="../_modules/aborist/qa/client.html#ChatClient"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#aborist.qa.client.ChatClient" title="Link to this definition"></a></dt>
<dd><dl class="py method">
<dt class="sig sig-object py" id="aborist.qa.client.ChatClient.chat_completion">
<span class="sig-name descname"><span class="pre">chat_completion</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">messages</span></span></em>, <em class="sig-param"><span class="keyword-only-separator o"><abbr title="Keyword-only parameters separator (PEP 3102)"><span class="pre">*</span></abbr></span></em>, <em class="sig-param"><span class="n"><span class="pre">model</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">temperature</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">0.1</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">max_tokens</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">512</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">top_p</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">1.0</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">extra_body</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em><span class="sig-paren">)</span><a class="reference internal" href="../_modules/aborist/qa/client.html#ChatClient.chat_completion"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#aborist.qa.client.ChatClient.chat_completion" title="Link to this definition"></a></dt>
<dd><p>Return the assistants text response.</p>
<p><code class="docutils literal notranslate"><span class="pre">extra_body</span></code> is forwarded as additional fields in the JSON
request payload — used for vLLM-specific knobs like
<code class="docutils literal notranslate"><span class="pre">guided_json</span></code> (constrain output to a JSON Schema at sampling
time, eliminating SCHEMA_INVALID failures from prompt drift).
Endpoints that dont recognize the field ignore it; the client
passes it through opaque-ly.</p>
<dl class="field-list simple">
<dt class="field-odd">Parameters<span class="colon">:</span></dt>
<dd class="field-odd"><ul class="simple">
<li><p><strong>messages</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#list" title="(in Python v3.14)"><em>list</em></a><em>[</em><a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#dict" title="(in Python v3.14)"><em>dict</em></a><em>]</em>)</p></li>
<li><p><strong>model</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.14)"><em>str</em></a>)</p></li>
<li><p><strong>temperature</strong> (<a class="reference external" href="https://docs.python.org/3/library/functions.html#float" title="(in Python v3.14)"><em>float</em></a>)</p></li>
<li><p><strong>max_tokens</strong> (<a class="reference external" href="https://docs.python.org/3/library/functions.html#int" title="(in Python v3.14)"><em>int</em></a>)</p></li>
<li><p><strong>top_p</strong> (<a class="reference external" href="https://docs.python.org/3/library/functions.html#float" title="(in Python v3.14)"><em>float</em></a>)</p></li>
<li><p><strong>extra_body</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#dict" title="(in Python v3.14)"><em>dict</em></a><em> | </em><em>None</em>)</p></li>
</ul>
</dd>
<dt class="field-even">Return type<span class="colon">:</span></dt>
<dd class="field-even"><p><a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.14)">str</a></p>
</dd>
</dl>
</dd></dl>
</dd></dl>
<dl class="py class">
<dt class="sig sig-object py" id="aborist.qa.client.StubClient">
<span class="property"><span class="k"><span class="pre">class</span></span><span class="w"> </span></span><span class="sig-prename descclassname"><span class="pre">aborist.qa.client.</span></span><span class="sig-name descname"><span class="pre">StubClient</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">answer</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">'[STUB]</span> <span class="pre">dry-run</span> <span class="pre">answer;</span> <span class="pre">no</span> <span class="pre">LLM</span> <span class="pre">was</span> <span class="pre">called.'</span></span></em><span class="sig-paren">)</span><a class="reference internal" href="../_modules/aborist/qa/client.html#StubClient"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#aborist.qa.client.StubClient" title="Link to this definition"></a></dt>
<dd><p>Offline client for tests / dry-run.</p>
<p>Pass <cite>answer=callable(messages, **kw) -&gt; str</cite> for dynamic stubbing.</p>
<dl class="py method">
<dt class="sig sig-object py" id="aborist.qa.client.StubClient.chat_completion">
<span class="sig-name descname"><span class="pre">chat_completion</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">messages</span></span></em>, <em class="sig-param"><span class="o"><span class="pre">**</span></span><span class="n"><span class="pre">kwargs</span></span></em><span class="sig-paren">)</span><a class="reference internal" href="../_modules/aborist/qa/client.html#StubClient.chat_completion"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#aborist.qa.client.StubClient.chat_completion" title="Link to this definition"></a></dt>
<dd><dl class="field-list simple">
<dt class="field-odd">Return type<span class="colon">:</span></dt>
<dd class="field-odd"><p><a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.14)">str</a></p>
</dd>
</dl>
</dd></dl>
</dd></dl>
<dl class="py class">
<dt class="sig sig-object py" id="aborist.qa.client.OpenAICompatibleClient">
<span class="property"><span class="k"><span class="pre">class</span></span><span class="w"> </span></span><span class="sig-prename descclassname"><span class="pre">aborist.qa.client.</span></span><span class="sig-name descname"><span class="pre">OpenAICompatibleClient</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">base_url</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">api_key</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">timeout</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">60.0</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">max_retries</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">3</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">retry_backoff_base_s</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">0.5</span></span></em><span class="sig-paren">)</span><a class="reference internal" href="../_modules/aborist/qa/client.html#OpenAICompatibleClient"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#aborist.qa.client.OpenAICompatibleClient" title="Link to this definition"></a></dt>
<dd><p>OpenAI-compatible chat completion over HTTP.</p>
<p>Default endpoint is configurable via env. Pass api_key only if the
target requires it; uncloseais free endpoint does not.</p>
<p>Retries on transient upstream failures (HTTP 502/503/504) with
exponential backoff. The 2026-04-30 QA-modes bench saw 19 of 66
JSON-mode runs error out with 502 from vLLM — clustered, plausibly
correlated with <cite>guided_json</cite> stressing the grammar engine. Retry
smooths over the cluster without changing semantics: a 502 still
fails the bench cell if all attempts exhaust, but transient bursts
no longer dominate the error column.</p>
<dl class="field-list simple">
<dt class="field-odd">Parameters<span class="colon">:</span></dt>
<dd class="field-odd"><ul class="simple">
<li><p><strong>base_url</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.14)"><em>str</em></a>)</p></li>
<li><p><strong>api_key</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.14)"><em>str</em></a><em> | </em><em>None</em>)</p></li>
<li><p><strong>timeout</strong> (<a class="reference external" href="https://docs.python.org/3/library/functions.html#float" title="(in Python v3.14)"><em>float</em></a>)</p></li>
<li><p><strong>max_retries</strong> (<a class="reference external" href="https://docs.python.org/3/library/functions.html#int" title="(in Python v3.14)"><em>int</em></a>)</p></li>
<li><p><strong>retry_backoff_base_s</strong> (<a class="reference external" href="https://docs.python.org/3/library/functions.html#float" title="(in Python v3.14)"><em>float</em></a>)</p></li>
</ul>
</dd>
</dl>
<dl class="py method">
<dt class="sig sig-object py" id="aborist.qa.client.OpenAICompatibleClient.close">
<span class="sig-name descname"><span class="pre">close</span></span><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="reference internal" href="../_modules/aborist/qa/client.html#OpenAICompatibleClient.close"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#aborist.qa.client.OpenAICompatibleClient.close" title="Link to this definition"></a></dt>
<dd><p>Release the underlying connection pool.</p>
<dl class="field-list simple">
<dt class="field-odd">Return type<span class="colon">:</span></dt>
<dd class="field-odd"><p>None</p>
</dd>
</dl>
</dd></dl>
<dl class="py method">
<dt class="sig sig-object py" id="aborist.qa.client.OpenAICompatibleClient.chat_completion">
<span class="sig-name descname"><span class="pre">chat_completion</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">messages</span></span></em>, <em class="sig-param"><span class="keyword-only-separator o"><abbr title="Keyword-only parameters separator (PEP 3102)"><span class="pre">*</span></abbr></span></em>, <em class="sig-param"><span class="n"><span class="pre">model</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">temperature</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">0.1</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">max_tokens</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">512</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">top_p</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">1.0</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">extra_body</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">stop</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em><span class="sig-paren">)</span><a class="reference internal" href="../_modules/aborist/qa/client.html#OpenAICompatibleClient.chat_completion"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#aborist.qa.client.OpenAICompatibleClient.chat_completion" title="Link to this definition"></a></dt>
<dd><dl class="field-list simple">
<dt class="field-odd">Parameters<span class="colon">:</span></dt>
<dd class="field-odd"><ul class="simple">
<li><p><strong>messages</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#list" title="(in Python v3.14)"><em>list</em></a><em>[</em><a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#dict" title="(in Python v3.14)"><em>dict</em></a><em>]</em>)</p></li>
<li><p><strong>model</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.14)"><em>str</em></a>)</p></li>
<li><p><strong>temperature</strong> (<a class="reference external" href="https://docs.python.org/3/library/functions.html#float" title="(in Python v3.14)"><em>float</em></a>)</p></li>
<li><p><strong>max_tokens</strong> (<a class="reference external" href="https://docs.python.org/3/library/functions.html#int" title="(in Python v3.14)"><em>int</em></a>)</p></li>
<li><p><strong>top_p</strong> (<a class="reference external" href="https://docs.python.org/3/library/functions.html#float" title="(in Python v3.14)"><em>float</em></a>)</p></li>
<li><p><strong>extra_body</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#dict" title="(in Python v3.14)"><em>dict</em></a><em> | </em><em>None</em>)</p></li>
<li><p><strong>stop</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#list" title="(in Python v3.14)"><em>list</em></a><em>[</em><a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.14)"><em>str</em></a><em>] </em><em>| </em><em>None</em>)</p></li>
</ul>
</dd>
<dt class="field-even">Return type<span class="colon">:</span></dt>
<dd class="field-even"><p><a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.14)">str</a></p>
</dd>
</dl>
</dd></dl>
</dd></dl>
</section>
</section>
</article>
</div>
<footer>
<div class="related-pages">
<a class="next-page" href="distill.html">
<div class="page-info">
<div class="context">
<span>Next</span>
</div>
<div class="title">Distillation: surface → core compression</div>
</div>
<svg class="furo-related-icon"><use href="#svg-arrow-right"></use></svg>
</a>
<a class="prev-page" href="retrieval.html">
<svg class="furo-related-icon"><use href="#svg-arrow-right"></use></svg>
<div class="page-info">
<div class="context">
<span>Previous</span>
</div>
<div class="title">Retrieval: FTS5 search and concepts</div>
</div>
</a>
</div>
<div class="bottom-of-page">
<div class="left-details">
<div class="copyright">
Copyright &#169; 2026, agent blackops
</div>
Made with <a href="https://www.sphinx-doc.org/">Sphinx</a> and <a class="muted-link" href="https://pradyunsg.me">@pradyunsg</a>'s
<a href="https://github.com/pradyunsg/furo">Furo</a>
</div>
<div class="right-details">
</div>
</div>
</footer>
</div>
<aside class="toc-drawer">
<div class="toc-sticky toc-scroll">
<div class="toc-title-container">
<span class="toc-title">
On this page
</span>
</div>
<div class="toc-tree-container">
<div class="toc-tree">
<ul>
<li><a class="reference internal" href="#">Q&amp;A Pipeline: question → answer → verify → cache</a><ul>
<li><a class="reference internal" href="#module-aborist.qa.keys">keys</a><ul>
<li><a class="reference internal" href="#aborist.qa.keys.canonical_question"><code class="docutils literal notranslate"><span class="pre">canonical_question()</span></code></a></li>
<li><a class="reference internal" href="#aborist.qa.keys.question_hash"><code class="docutils literal notranslate"><span class="pre">question_hash()</span></code></a></li>
<li><a class="reference internal" href="#aborist.qa.keys.model_profile_hash"><code class="docutils literal notranslate"><span class="pre">model_profile_hash()</span></code></a></li>
<li><a class="reference internal" href="#aborist.qa.keys.conversation_hash"><code class="docutils literal notranslate"><span class="pre">conversation_hash()</span></code></a></li>
<li><a class="reference internal" href="#aborist.qa.keys.governance_policy_hash"><code class="docutils literal notranslate"><span class="pre">governance_policy_hash()</span></code></a></li>
<li><a class="reference internal" href="#aborist.qa.keys.verifier_policy_hash"><code class="docutils literal notranslate"><span class="pre">verifier_policy_hash()</span></code></a></li>
<li><a class="reference internal" href="#aborist.qa.keys.cache_key"><code class="docutils literal notranslate"><span class="pre">cache_key()</span></code></a></li>
</ul>
</li>
<li><a class="reference internal" href="#module-aborist.qa.runner">runner</a><ul>
<li><a class="reference internal" href="#aborist.qa.runner.ask"><code class="docutils literal notranslate"><span class="pre">ask()</span></code></a></li>
</ul>
</li>
<li><a class="reference internal" href="#module-aborist.qa.query">query</a><ul>
<li><a class="reference internal" href="#aborist.qa.query.query"><code class="docutils literal notranslate"><span class="pre">query()</span></code></a></li>
</ul>
</li>
<li><a class="reference internal" href="#module-aborist.qa.verify">verify</a><ul>
<li><a class="reference internal" href="#aborist.qa.verify.extract_quotes"><code class="docutils literal notranslate"><span class="pre">extract_quotes()</span></code></a></li>
<li><a class="reference internal" href="#aborist.qa.verify.extract_claim_spans"><code class="docutils literal notranslate"><span class="pre">extract_claim_spans()</span></code></a></li>
<li><a class="reference internal" href="#aborist.qa.verify.extract_proper_nouns"><code class="docutils literal notranslate"><span class="pre">extract_proper_nouns()</span></code></a></li>
<li><a class="reference internal" href="#aborist.qa.verify.verify_quotes"><code class="docutils literal notranslate"><span class="pre">verify_quotes()</span></code></a></li>
<li><a class="reference internal" href="#aborist.qa.verify.verify_claim_lattice"><code class="docutils literal notranslate"><span class="pre">verify_claim_lattice()</span></code></a></li>
<li><a class="reference internal" href="#aborist.qa.verify.evidence_map_by_evidence_id_local"><code class="docutils literal notranslate"><span class="pre">evidence_map_by_evidence_id_local()</span></code></a></li>
<li><a class="reference internal" href="#aborist.qa.verify.verify_claim_lattice_json"><code class="docutils literal notranslate"><span class="pre">verify_claim_lattice_json()</span></code></a></li>
</ul>
</li>
<li><a class="reference internal" href="#module-aborist.qa.evidence">evidence</a><ul>
<li><a class="reference internal" href="#aborist.qa.evidence.EvidenceObject"><code class="docutils literal notranslate"><span class="pre">EvidenceObject</span></code></a><ul>
<li><a class="reference internal" href="#aborist.qa.evidence.EvidenceObject.pointer_id"><code class="docutils literal notranslate"><span class="pre">EvidenceObject.pointer_id</span></code></a></li>
<li><a class="reference internal" href="#aborist.qa.evidence.EvidenceObject.evidence_id"><code class="docutils literal notranslate"><span class="pre">EvidenceObject.evidence_id</span></code></a></li>
<li><a class="reference internal" href="#aborist.qa.evidence.EvidenceObject.source_root"><code class="docutils literal notranslate"><span class="pre">EvidenceObject.source_root</span></code></a></li>
<li><a class="reference internal" href="#aborist.qa.evidence.EvidenceObject.document_uri"><code class="docutils literal notranslate"><span class="pre">EvidenceObject.document_uri</span></code></a></li>
<li><a class="reference internal" href="#aborist.qa.evidence.EvidenceObject.title"><code class="docutils literal notranslate"><span class="pre">EvidenceObject.title</span></code></a></li>
<li><a class="reference internal" href="#aborist.qa.evidence.EvidenceObject.chunk_idx"><code class="docutils literal notranslate"><span class="pre">EvidenceObject.chunk_idx</span></code></a></li>
<li><a class="reference internal" href="#aborist.qa.evidence.EvidenceObject.chunk_root"><code class="docutils literal notranslate"><span class="pre">EvidenceObject.chunk_root</span></code></a></li>
<li><a class="reference internal" href="#aborist.qa.evidence.EvidenceObject.offset_start"><code class="docutils literal notranslate"><span class="pre">EvidenceObject.offset_start</span></code></a></li>
<li><a class="reference internal" href="#aborist.qa.evidence.EvidenceObject.offset_end"><code class="docutils literal notranslate"><span class="pre">EvidenceObject.offset_end</span></code></a></li>
<li><a class="reference internal" href="#aborist.qa.evidence.EvidenceObject.source_role"><code class="docutils literal notranslate"><span class="pre">EvidenceObject.source_role</span></code></a></li>
<li><a class="reference internal" href="#aborist.qa.evidence.EvidenceObject.text_hash"><code class="docutils literal notranslate"><span class="pre">EvidenceObject.text_hash</span></code></a></li>
<li><a class="reference internal" href="#aborist.qa.evidence.EvidenceObject.span"><code class="docutils literal notranslate"><span class="pre">EvidenceObject.span</span></code></a></li>
<li><a class="reference internal" href="#aborist.qa.evidence.EvidenceObject.to_dict"><code class="docutils literal notranslate"><span class="pre">EvidenceObject.to_dict()</span></code></a></li>
</ul>
</li>
<li><a class="reference internal" href="#aborist.qa.evidence.build_evidence_map"><code class="docutils literal notranslate"><span class="pre">build_evidence_map()</span></code></a></li>
<li><a class="reference internal" href="#aborist.qa.evidence.evidence_map_root"><code class="docutils literal notranslate"><span class="pre">evidence_map_root()</span></code></a></li>
<li><a class="reference internal" href="#aborist.qa.evidence.render_evidence_block"><code class="docutils literal notranslate"><span class="pre">render_evidence_block()</span></code></a></li>
<li><a class="reference internal" href="#aborist.qa.evidence.render_evidence_map"><code class="docutils literal notranslate"><span class="pre">render_evidence_map()</span></code></a></li>
<li><a class="reference internal" href="#aborist.qa.evidence.render_evidence_block_for_json"><code class="docutils literal notranslate"><span class="pre">render_evidence_block_for_json()</span></code></a></li>
<li><a class="reference internal" href="#aborist.qa.evidence.render_evidence_map_for_json"><code class="docutils literal notranslate"><span class="pre">render_evidence_map_for_json()</span></code></a></li>
<li><a class="reference internal" href="#aborist.qa.evidence.evidence_map_by_pointer_id"><code class="docutils literal notranslate"><span class="pre">evidence_map_by_pointer_id()</span></code></a></li>
<li><a class="reference internal" href="#aborist.qa.evidence.evidence_map_by_evidence_id"><code class="docutils literal notranslate"><span class="pre">evidence_map_by_evidence_id()</span></code></a></li>
<li><a class="reference internal" href="#aborist.qa.evidence.render_claim_lattice"><code class="docutils literal notranslate"><span class="pre">render_claim_lattice()</span></code></a></li>
</ul>
</li>
<li><a class="reference internal" href="#module-aborist.qa.quantifier">quantifier</a><ul>
<li><a class="reference internal" href="#aborist.qa.quantifier.classify_question_quantifier"><code class="docutils literal notranslate"><span class="pre">classify_question_quantifier()</span></code></a></li>
</ul>
</li>
<li><a class="reference internal" href="#module-aborist.qa.metacognition">metacognition</a><ul>
<li><a class="reference internal" href="#aborist.qa.metacognition.QuestionState"><code class="docutils literal notranslate"><span class="pre">QuestionState</span></code></a><ul>
<li><a class="reference internal" href="#aborist.qa.metacognition.QuestionState.raw_question"><code class="docutils literal notranslate"><span class="pre">QuestionState.raw_question</span></code></a></li>
<li><a class="reference internal" href="#aborist.qa.metacognition.QuestionState.question_hash"><code class="docutils literal notranslate"><span class="pre">QuestionState.question_hash</span></code></a></li>
<li><a class="reference internal" href="#aborist.qa.metacognition.QuestionState.logical_statuses"><code class="docutils literal notranslate"><span class="pre">QuestionState.logical_statuses</span></code></a></li>
<li><a class="reference internal" href="#aborist.qa.metacognition.QuestionState.question_shape"><code class="docutils literal notranslate"><span class="pre">QuestionState.question_shape</span></code></a></li>
<li><a class="reference internal" href="#aborist.qa.metacognition.QuestionState.quantifier_intensity"><code class="docutils literal notranslate"><span class="pre">QuestionState.quantifier_intensity</span></code></a></li>
<li><a class="reference internal" href="#aborist.qa.metacognition.QuestionState.quantifier_matched_token"><code class="docutils literal notranslate"><span class="pre">QuestionState.quantifier_matched_token</span></code></a></li>
<li><a class="reference internal" href="#aborist.qa.metacognition.QuestionState.scope_bound_hint"><code class="docutils literal notranslate"><span class="pre">QuestionState.scope_bound_hint</span></code></a></li>
<li><a class="reference internal" href="#aborist.qa.metacognition.QuestionState.reference_frames"><code class="docutils literal notranslate"><span class="pre">QuestionState.reference_frames</span></code></a></li>
<li><a class="reference internal" href="#aborist.qa.metacognition.QuestionState.temporal_sensitivity"><code class="docutils literal notranslate"><span class="pre">QuestionState.temporal_sensitivity</span></code></a></li>
<li><a class="reference internal" href="#aborist.qa.metacognition.QuestionState.temporal_matched_tokens"><code class="docutils literal notranslate"><span class="pre">QuestionState.temporal_matched_tokens</span></code></a></li>
<li><a class="reference internal" href="#aborist.qa.metacognition.QuestionState.contradiction_pairs"><code class="docutils literal notranslate"><span class="pre">QuestionState.contradiction_pairs</span></code></a></li>
<li><a class="reference internal" href="#aborist.qa.metacognition.QuestionState.false_premise_hints"><code class="docutils literal notranslate"><span class="pre">QuestionState.false_premise_hints</span></code></a></li>
<li><a class="reference internal" href="#aborist.qa.metacognition.QuestionState.corpus_requirement"><code class="docutils literal notranslate"><span class="pre">QuestionState.corpus_requirement</span></code></a></li>
<li><a class="reference internal" href="#aborist.qa.metacognition.QuestionState.known_boundaries"><code class="docutils literal notranslate"><span class="pre">QuestionState.known_boundaries</span></code></a></li>
<li><a class="reference internal" href="#aborist.qa.metacognition.QuestionState.answer_constraints"><code class="docutils literal notranslate"><span class="pre">QuestionState.answer_constraints</span></code></a></li>
<li><a class="reference internal" href="#aborist.qa.metacognition.QuestionState.preflight_result"><code class="docutils literal notranslate"><span class="pre">QuestionState.preflight_result</span></code></a></li>
<li><a class="reference internal" href="#aborist.qa.metacognition.QuestionState.preflight_policy_hash"><code class="docutils literal notranslate"><span class="pre">QuestionState.preflight_policy_hash</span></code></a></li>
<li><a class="reference internal" href="#aborist.qa.metacognition.QuestionState.classifier_version"><code class="docutils literal notranslate"><span class="pre">QuestionState.classifier_version</span></code></a></li>
<li><a class="reference internal" href="#aborist.qa.metacognition.QuestionState.to_dict"><code class="docutils literal notranslate"><span class="pre">QuestionState.to_dict()</span></code></a></li>
</ul>
</li>
<li><a class="reference internal" href="#aborist.qa.metacognition.detect_temporal_sensitivity"><code class="docutils literal notranslate"><span class="pre">detect_temporal_sensitivity()</span></code></a></li>
<li><a class="reference internal" href="#aborist.qa.metacognition.detect_contradiction"><code class="docutils literal notranslate"><span class="pre">detect_contradiction()</span></code></a></li>
<li><a class="reference internal" href="#aborist.qa.metacognition.detect_false_premise"><code class="docutils literal notranslate"><span class="pre">detect_false_premise()</span></code></a></li>
<li><a class="reference internal" href="#aborist.qa.metacognition.detect_out_of_corpus"><code class="docutils literal notranslate"><span class="pre">detect_out_of_corpus()</span></code></a></li>
<li><a class="reference internal" href="#aborist.qa.metacognition.preflight_question"><code class="docutils literal notranslate"><span class="pre">preflight_question()</span></code></a></li>
</ul>
</li>
<li><a class="reference internal" href="#module-aborist.qa.dag">dag</a><ul>
<li><a class="reference internal" href="#aborist.qa.dag.localize_failure"><code class="docutils literal notranslate"><span class="pre">localize_failure()</span></code></a></li>
<li><a class="reference internal" href="#aborist.qa.dag.build_preflight_node_payload"><code class="docutils literal notranslate"><span class="pre">build_preflight_node_payload()</span></code></a></li>
<li><a class="reference internal" href="#aborist.qa.dag.preflight_node_hash"><code class="docutils literal notranslate"><span class="pre">preflight_node_hash()</span></code></a></li>
<li><a class="reference internal" href="#aborist.qa.dag.build_run_dag"><code class="docutils literal notranslate"><span class="pre">build_run_dag()</span></code></a></li>
<li><a class="reference internal" href="#aborist.qa.dag.build_reject_run_dag"><code class="docutils literal notranslate"><span class="pre">build_reject_run_dag()</span></code></a></li>
<li><a class="reference internal" href="#aborist.qa.dag.verify_run_dag"><code class="docutils literal notranslate"><span class="pre">verify_run_dag()</span></code></a></li>
</ul>
</li>
<li><a class="reference internal" href="#module-aborist.qa.client">client</a><ul>
<li><a class="reference internal" href="#aborist.qa.client.ChatClient"><code class="docutils literal notranslate"><span class="pre">ChatClient</span></code></a><ul>
<li><a class="reference internal" href="#aborist.qa.client.ChatClient.chat_completion"><code class="docutils literal notranslate"><span class="pre">ChatClient.chat_completion()</span></code></a></li>
</ul>
</li>
<li><a class="reference internal" href="#aborist.qa.client.StubClient"><code class="docutils literal notranslate"><span class="pre">StubClient</span></code></a><ul>
<li><a class="reference internal" href="#aborist.qa.client.StubClient.chat_completion"><code class="docutils literal notranslate"><span class="pre">StubClient.chat_completion()</span></code></a></li>
</ul>
</li>
<li><a class="reference internal" href="#aborist.qa.client.OpenAICompatibleClient"><code class="docutils literal notranslate"><span class="pre">OpenAICompatibleClient</span></code></a><ul>
<li><a class="reference internal" href="#aborist.qa.client.OpenAICompatibleClient.close"><code class="docutils literal notranslate"><span class="pre">OpenAICompatibleClient.close()</span></code></a></li>
<li><a class="reference internal" href="#aborist.qa.client.OpenAICompatibleClient.chat_completion"><code class="docutils literal notranslate"><span class="pre">OpenAICompatibleClient.chat_completion()</span></code></a></li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</div>
</div>
</div>
</aside>
</div>
</div><script src="../_static/documentation_options.js?v=335b8a46"></script>
<script src="../_static/doctools.js?v=fd6eb6e6"></script>
<script src="../_static/sphinx_highlight.js?v=6ffebe34"></script>
<script src="../_static/scripts/furo.js?v=46bd48cc"></script>
</body>
</html>