From 49607a5997be4e0cbad5744295fed3991aff4e48 Mon Sep 17 00:00:00 2001 From: "russell@unturf.com" Date: Mon, 4 May 2026 07:55:34 -0400 Subject: [PATCH] docs: add Sphinx API reference generation from docstrings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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. --- Makefile | 9 +- docs/_source/Makefile | 18 + docs/_source/README.md | 60 + docs/_source/_build/html/.buildinfo | 4 + .../__intersphinx_cache__/python_objects.inv | Bin 0 -> 153230 bytes .../_build/html/.doctrees/api/cli.doctree | Bin 0 -> 8981 bytes .../_build/html/.doctrees/api/distill.doctree | Bin 0 -> 37755 bytes .../_build/html/.doctrees/api/mesh.doctree | Bin 0 -> 85047 bytes .../_build/html/.doctrees/api/qa.doctree | Bin 0 -> 558616 bytes .../html/.doctrees/api/retrieval.doctree | Bin 0 -> 159850 bytes .../_build/html/.doctrees/api/storage.doctree | Bin 0 -> 113042 bytes .../html/.doctrees/api/substrate.doctree | Bin 0 -> 134059 bytes .../_build/html/.doctrees/environment.pickle | Bin 0 -> 3409014 bytes .../_build/html/.doctrees/index.doctree | Bin 0 -> 4856 bytes .../_build/html/_modules/aborist/cli.html | 4456 +++++++++++++++++ .../html/_modules/aborist/concepts/query.html | 573 +++ .../html/_modules/aborist/concepts/store.html | 394 ++ .../html/_modules/aborist/distill/base.html | 312 ++ .../aborist/distill/first_sentence.html | 330 ++ .../html/_modules/aborist/distill/tfidf.html | 363 ++ .../html/_modules/aborist/document.html | 392 ++ .../_build/html/_modules/aborist/evict.html | 496 ++ .../_build/html/_modules/aborist/ingest.html | 696 +++ .../_build/html/_modules/aborist/merkle.html | 461 ++ .../html/_modules/aborist/mesh/crypto.html | 387 ++ .../html/_modules/aborist/mesh/state.html | 685 +++ .../html/_modules/aborist/qa/client.html | 493 ++ .../_build/html/_modules/aborist/qa/dag.html | 731 +++ .../html/_modules/aborist/qa/evidence.html | 777 +++ .../_build/html/_modules/aborist/qa/keys.html | 598 +++ .../_modules/aborist/qa/metacognition.html | 880 ++++ .../html/_modules/aborist/qa/quantifier.html | 703 +++ .../html/_modules/aborist/qa/query.html | 3431 +++++++++++++ .../html/_modules/aborist/qa/runner.html | 1348 +++++ .../html/_modules/aborist/qa/verify.html | 2434 +++++++++ .../html/_modules/aborist/search/base.html | 325 ++ .../html/_modules/aborist/search/fts5.html | 508 ++ .../_build/html/_modules/aborist/source.html | 291 ++ .../_modules/aborist/sources/html_page.html | 419 ++ .../_modules/aborist/sources/wikipedia.html | 676 +++ .../_build/html/_modules/aborist/store.html | 1293 +++++ .../html/_modules/aborist/wikitext.html | 406 ++ docs/_source/_build/html/_modules/index.html | 289 ++ .../_build/html/_sources/api/cli.rst.txt | 8 + .../_build/html/_sources/api/distill.rst.txt | 9 + .../_build/html/_sources/api/mesh.rst.txt | 9 + .../_build/html/_sources/api/qa.rst.txt | 67 + .../html/_sources/api/retrieval.rst.txt | 35 + .../_build/html/_sources/api/storage.rst.txt | 27 + .../html/_sources/api/substrate.rst.txt | 27 + .../_build/html/_sources/index.rst.txt | 26 + .../_build/html/_static/base-stemmer.js | 476 ++ docs/_source/_build/html/_static/basic.css | 906 ++++ docs/_source/_build/html/_static/debug.css | 69 + docs/_source/_build/html/_static/doctools.js | 150 + .../html/_static/documentation_options.js | 13 + .../_build/html/_static/english-stemmer.js | 1066 ++++ docs/_source/_build/html/_static/file.png | Bin 0 -> 286 bytes .../_build/html/_static/language_data.js | 13 + docs/_source/_build/html/_static/minus.png | Bin 0 -> 90 bytes docs/_source/_build/html/_static/plus.png | Bin 0 -> 90 bytes docs/_source/_build/html/_static/pygments.css | 250 + .../html/_static/scripts/furo-extensions.js | 0 .../_build/html/_static/scripts/furo.js | 3 + .../html/_static/scripts/furo.js.LICENSE.txt | 7 + .../_build/html/_static/scripts/furo.js.map | 1 + .../_build/html/_static/searchtools.js | 693 +++ docs/_source/_build/html/_static/skeleton.css | 296 ++ .../_build/html/_static/sphinx_highlight.js | 159 + .../html/_static/styles/furo-extensions.css | 2 + .../_static/styles/furo-extensions.css.map | 1 + .../_build/html/_static/styles/furo.css | 2 + .../_build/html/_static/styles/furo.css.map | 1 + docs/_source/_build/html/api/cli.html | 325 ++ docs/_source/_build/html/api/distill.html | 450 ++ docs/_source/_build/html/api/mesh.html | 639 +++ docs/_source/_build/html/api/qa.html | 2242 +++++++++ docs/_source/_build/html/api/retrieval.html | 882 ++++ docs/_source/_build/html/api/storage.html | 703 +++ docs/_source/_build/html/api/substrate.html | 866 ++++ docs/_source/_build/html/genindex.html | 1162 +++++ docs/_source/_build/html/index.html | 512 ++ docs/_source/_build/html/objects.inv | Bin 0 -> 2640 bytes docs/_source/_build/html/py-modindex.html | 417 ++ docs/_source/_build/html/search.html | 275 + docs/_source/_build/html/searchindex.js | 1 + docs/_source/api/cli.rst | 8 + docs/_source/api/distill.rst | 9 + docs/_source/api/mesh.rst | 9 + docs/_source/api/qa.rst | 67 + docs/_source/api/retrieval.rst | 35 + docs/_source/api/storage.rst | 27 + docs/_source/api/substrate.rst | 27 + docs/_source/conf.py | 52 + docs/_source/index.rst | 26 + 95 files changed, 38287 insertions(+), 1 deletion(-) create mode 100644 docs/_source/Makefile create mode 100644 docs/_source/README.md create mode 100644 docs/_source/_build/html/.buildinfo create mode 100644 docs/_source/_build/html/.doctrees/__intersphinx_cache__/python_objects.inv create mode 100644 docs/_source/_build/html/.doctrees/api/cli.doctree create mode 100644 docs/_source/_build/html/.doctrees/api/distill.doctree create mode 100644 docs/_source/_build/html/.doctrees/api/mesh.doctree create mode 100644 docs/_source/_build/html/.doctrees/api/qa.doctree create mode 100644 docs/_source/_build/html/.doctrees/api/retrieval.doctree create mode 100644 docs/_source/_build/html/.doctrees/api/storage.doctree create mode 100644 docs/_source/_build/html/.doctrees/api/substrate.doctree create mode 100644 docs/_source/_build/html/.doctrees/environment.pickle create mode 100644 docs/_source/_build/html/.doctrees/index.doctree create mode 100644 docs/_source/_build/html/_modules/aborist/cli.html create mode 100644 docs/_source/_build/html/_modules/aborist/concepts/query.html create mode 100644 docs/_source/_build/html/_modules/aborist/concepts/store.html create mode 100644 docs/_source/_build/html/_modules/aborist/distill/base.html create mode 100644 docs/_source/_build/html/_modules/aborist/distill/first_sentence.html create mode 100644 docs/_source/_build/html/_modules/aborist/distill/tfidf.html create mode 100644 docs/_source/_build/html/_modules/aborist/document.html create mode 100644 docs/_source/_build/html/_modules/aborist/evict.html create mode 100644 docs/_source/_build/html/_modules/aborist/ingest.html create mode 100644 docs/_source/_build/html/_modules/aborist/merkle.html create mode 100644 docs/_source/_build/html/_modules/aborist/mesh/crypto.html create mode 100644 docs/_source/_build/html/_modules/aborist/mesh/state.html create mode 100644 docs/_source/_build/html/_modules/aborist/qa/client.html create mode 100644 docs/_source/_build/html/_modules/aborist/qa/dag.html create mode 100644 docs/_source/_build/html/_modules/aborist/qa/evidence.html create mode 100644 docs/_source/_build/html/_modules/aborist/qa/keys.html create mode 100644 docs/_source/_build/html/_modules/aborist/qa/metacognition.html create mode 100644 docs/_source/_build/html/_modules/aborist/qa/quantifier.html create mode 100644 docs/_source/_build/html/_modules/aborist/qa/query.html create mode 100644 docs/_source/_build/html/_modules/aborist/qa/runner.html create mode 100644 docs/_source/_build/html/_modules/aborist/qa/verify.html create mode 100644 docs/_source/_build/html/_modules/aborist/search/base.html create mode 100644 docs/_source/_build/html/_modules/aborist/search/fts5.html create mode 100644 docs/_source/_build/html/_modules/aborist/source.html create mode 100644 docs/_source/_build/html/_modules/aborist/sources/html_page.html create mode 100644 docs/_source/_build/html/_modules/aborist/sources/wikipedia.html create mode 100644 docs/_source/_build/html/_modules/aborist/store.html create mode 100644 docs/_source/_build/html/_modules/aborist/wikitext.html create mode 100644 docs/_source/_build/html/_modules/index.html create mode 100644 docs/_source/_build/html/_sources/api/cli.rst.txt create mode 100644 docs/_source/_build/html/_sources/api/distill.rst.txt create mode 100644 docs/_source/_build/html/_sources/api/mesh.rst.txt create mode 100644 docs/_source/_build/html/_sources/api/qa.rst.txt create mode 100644 docs/_source/_build/html/_sources/api/retrieval.rst.txt create mode 100644 docs/_source/_build/html/_sources/api/storage.rst.txt create mode 100644 docs/_source/_build/html/_sources/api/substrate.rst.txt create mode 100644 docs/_source/_build/html/_sources/index.rst.txt create mode 100644 docs/_source/_build/html/_static/base-stemmer.js create mode 100644 docs/_source/_build/html/_static/basic.css create mode 100644 docs/_source/_build/html/_static/debug.css create mode 100644 docs/_source/_build/html/_static/doctools.js create mode 100644 docs/_source/_build/html/_static/documentation_options.js create mode 100644 docs/_source/_build/html/_static/english-stemmer.js create mode 100644 docs/_source/_build/html/_static/file.png create mode 100644 docs/_source/_build/html/_static/language_data.js create mode 100644 docs/_source/_build/html/_static/minus.png create mode 100644 docs/_source/_build/html/_static/plus.png create mode 100644 docs/_source/_build/html/_static/pygments.css create mode 100644 docs/_source/_build/html/_static/scripts/furo-extensions.js create mode 100644 docs/_source/_build/html/_static/scripts/furo.js create mode 100644 docs/_source/_build/html/_static/scripts/furo.js.LICENSE.txt create mode 100644 docs/_source/_build/html/_static/scripts/furo.js.map create mode 100644 docs/_source/_build/html/_static/searchtools.js create mode 100644 docs/_source/_build/html/_static/skeleton.css create mode 100644 docs/_source/_build/html/_static/sphinx_highlight.js create mode 100644 docs/_source/_build/html/_static/styles/furo-extensions.css create mode 100644 docs/_source/_build/html/_static/styles/furo-extensions.css.map create mode 100644 docs/_source/_build/html/_static/styles/furo.css create mode 100644 docs/_source/_build/html/_static/styles/furo.css.map create mode 100644 docs/_source/_build/html/api/cli.html create mode 100644 docs/_source/_build/html/api/distill.html create mode 100644 docs/_source/_build/html/api/mesh.html create mode 100644 docs/_source/_build/html/api/qa.html create mode 100644 docs/_source/_build/html/api/retrieval.html create mode 100644 docs/_source/_build/html/api/storage.html create mode 100644 docs/_source/_build/html/api/substrate.html create mode 100644 docs/_source/_build/html/genindex.html create mode 100644 docs/_source/_build/html/index.html create mode 100644 docs/_source/_build/html/objects.inv create mode 100644 docs/_source/_build/html/py-modindex.html create mode 100644 docs/_source/_build/html/search.html create mode 100644 docs/_source/_build/html/searchindex.js create mode 100644 docs/_source/api/cli.rst create mode 100644 docs/_source/api/distill.rst create mode 100644 docs/_source/api/mesh.rst create mode 100644 docs/_source/api/qa.rst create mode 100644 docs/_source/api/retrieval.rst create mode 100644 docs/_source/api/storage.rst create mode 100644 docs/_source/api/substrate.rst create mode 100644 docs/_source/conf.py create mode 100644 docs/_source/index.rst diff --git a/Makefile b/Makefile index 9b21b1f..8ac1253 100644 --- a/Makefile +++ b/Makefile @@ -30,7 +30,8 @@ SEARCH_Q ?= computer ingest-xml-attached ingest-abstract \ ingest-grok ingest-grok-media \ ingest-self ingest-self-providence ingest-git ingest-hg \ - verify search stats test test-live docs chain-check chain-check-shards \ + verify search stats test test-live docs docs-api docs-api-clean \ + chain-check chain-check-shards \ falsify burn burn-kindergarten inspect bootstrap-crawler test-crawler crawl-ingest \ recrawl-check bench-qa clean clean-db clean-data help @@ -499,6 +500,12 @@ docs/diagrams/%.svg: docs/diagrams/%.dot docs: $(DOT_PNGS) $(DOT_SVGS) ## render docs/diagrams/*.dot -> .png + .svg via graphviz +docs-api: ## generate Sphinx API reference from docstrings (output: docs/_source/_build/html/) + $(PY) -m sphinx.cmd.build -b html docs/_source docs/_source/_build/html + +docs-api-clean: ## remove Sphinx build artifacts + rm -rf docs/_source/_build/ + # Reproducible micro-benchmark over a fixed slice of cur. Lets you compare # ETL throughput across configs and catches regressions on optimization # work. Override BENCH_DOCS=N (default 5000). diff --git a/docs/_source/Makefile b/docs/_source/Makefile new file mode 100644 index 0000000..4d877a5 --- /dev/null +++ b/docs/_source/Makefile @@ -0,0 +1,18 @@ +# Sphinx documentation build Makefile + +.PHONY: help clean html text + +help: + @echo "Sphinx documentation build targets:" + @echo " make html - build HTML documentation" + @echo " make text - build text documentation" + @echo " make clean - remove build artifacts" + +html: + sphinx-build -b html . _build/html + +text: + sphinx-build -b text . _build/text + +clean: + rm -rf _build/ diff --git a/docs/_source/README.md b/docs/_source/README.md new file mode 100644 index 0000000..dda2711 --- /dev/null +++ b/docs/_source/README.md @@ -0,0 +1,60 @@ +# Aborist API Reference (Sphinx) + +This directory contains Sphinx configuration to generate API documentation from docstrings. + +## Build + +```bash +cd docs/_source +make html # Generate HTML (output: _build/html/) +make text # Generate text (output: _build/text/) +make clean # Remove build artifacts +``` + +Or directly: + +```bash +sphinx-build -b html . _build/html +``` + +## View + +After building, open `_build/html/index.html` in a browser. + +## Structure + +- `conf.py` — Sphinx configuration +- `index.rst` — Main table of contents +- `api/` — Module documentation (one .rst per module category) + - `substrate.rst` — Core data structures (merkle, document, wikitext) + - `storage.rst` — SQLite schema (store, ingest, evict) + - `retrieval.rst` — FTS5 search (search, sources, concepts) + - `qa.rst` — Q&A pipeline (runner, query, verify, evidence, etc.) + - `distill.rst` — Distillation (surface→core) + - `mesh.rst` — Federation (gossip-based sync) + - `cli.rst` — Command-line interface + +## What it replaces + +This generated documentation **replaces `docs/modules.md`** (1200+ lines of static API reference). The docstrings in code are the source of truth; Sphinx extracts them automatically. + +## Adding new modules + +1. Add a docstring to the module (module-level docstring at the top of `module.py`) +2. Add an `.rst` file in `api/` that includes the module with `automodule` directive +3. Reference it in `index.rst` +4. Rebuild with `make html` + +## Theme + +Uses **furo** theme (modern, responsive, search-enabled). + +## Autodoc directives + +The `.rst` files use Sphinx `automodule` to extract: +- Module docstrings +- Class docstrings + members +- Function signatures + docstrings +- Source code links (`:viewcode:` extension) + +See [Sphinx autodoc docs](https://www.sphinx-doc.org/en/master/usage/extensions/autodoc.html). diff --git a/docs/_source/_build/html/.buildinfo b/docs/_source/_build/html/.buildinfo new file mode 100644 index 0000000..9377929 --- /dev/null +++ b/docs/_source/_build/html/.buildinfo @@ -0,0 +1,4 @@ +# Sphinx build info version 1 +# This file records the configuration used when building these files. When it is not found, a full rebuild will be done. +config: 72d8748569a4fd9a0c87ddba8f0e6a2d +tags: 645f666f9bcd5a90fca523b33c5a78b7 diff --git a/docs/_source/_build/html/.doctrees/__intersphinx_cache__/python_objects.inv b/docs/_source/_build/html/.doctrees/__intersphinx_cache__/python_objects.inv new file mode 100644 index 0000000000000000000000000000000000000000..2d66073f65f7a9bd56771e870e07e69da9536a0d GIT binary patch literal 153230 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 literal 0 HcmV?d00001 diff --git a/docs/_source/_build/html/.doctrees/api/cli.doctree b/docs/_source/_build/html/.doctrees/api/cli.doctree new file mode 100644 index 0000000000000000000000000000000000000000..6dee2a00342d49fc717c1d7c6875e012330b204f GIT binary patch literal 8981 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 literal 0 HcmV?d00001 diff --git a/docs/_source/_build/html/.doctrees/api/distill.doctree b/docs/_source/_build/html/.doctrees/api/distill.doctree new file mode 100644 index 0000000000000000000000000000000000000000..965dee2566ea039a53306d22b9ecaa3c9779c363 GIT binary patch literal 37755 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 Dl9`m$ literal 0 HcmV?d00001 diff --git a/docs/_source/_build/html/.doctrees/api/mesh.doctree b/docs/_source/_build/html/.doctrees/api/mesh.doctree new file mode 100644 index 0000000000000000000000000000000000000000..5abdba38df1c627d0fadf1b1106c12544c776cb0 GIT binary patch literal 85047 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 literal 0 HcmV?d00001 diff --git a/docs/_source/_build/html/.doctrees/api/qa.doctree b/docs/_source/_build/html/.doctrees/api/qa.doctree new file mode 100644 index 0000000000000000000000000000000000000000..d03fd84b6c249b1f194bf65bfc19306ee7c00012 GIT binary patch literal 558616 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 b$>YJidX{{^M#!VDJ4-H*+~dzX^c?tqFF2lI literal 0 HcmV?d00001 diff --git a/docs/_source/_build/html/.doctrees/api/retrieval.doctree b/docs/_source/_build/html/.doctrees/api/retrieval.doctree new file mode 100644 index 0000000000000000000000000000000000000000..08bb7c905851d2df4e64d977c68abd746076382f GIT binary patch literal 159850 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 z z3sdZ1cKi_CpBauHK18b735>Y0hM2`tS-i|UG2QnayjZjo#|dPb zeCGQOl2GP6&n7-Ig{tmL5G1yVB%J31IfhKaA?Y^c!ky^70FCD1{5gDzlgAullcD@( zgbX4BlUvK;c_HKEZ_^zKA7(gnt>jc= zEU55@^^Sz^W=5YK{Qq}okj0uy2@U1DBLSxey(7Vh6a5>(2JL?Jjsz@CvuO0|B*Y~H z+!z-HQiYCe)}cCuk>8Q91R7)^RrKG0Z}u=x);kh15KX-!!6cf~PJy|$Df&7gyqg5f zNI_xGV5IzG3N&V<@L4UUPnJstxZZO&Do_SE?npr9(3=MK13&2{TjbMEA+~o<^fU7J z=j87%$lw1Ue}75-{tEx1CO$^wktM$H*`Eb{o_xtwpw5;84F}opNWkbJ#r!&fIr%gY z=0o0*(2nKd*DHGMSw8&AAR6|cJpB3_$?OzJq#1k%g=xZ?u!FWDjMm#J#E&vPbb`B29K40{b@35=|JGldp#-b2A z>OfEaAeXRy3MQ_@vKCC_F5ps3no&}Sa|thTa13|g^=;lkSq`rJF*I|gba%F-t#O2XVCG^aU2&F`_;6r(_{UF66^$6!D{eY7vJSbrOgoopp&6m8e^PcFS z9s6gemHu;mbnr*sVOk{Vdl`B2fBb-xyrF<~-lU%hWOA2YQHtZp7N1d@m$MY@tekb% zvz^sR>YzFIAw;hNzB$k8NQ4q@f~P>cA>9Q0{&GZt`UoxnRuPQ&Ssnbz+~wa6WoT-q z?(%n9&+6FjV-m-5*!^|J@gCQmOk+wM<6^Ir@s%0Jg7@h@6~{pL@fWd%Fq}d5@oJ_i zn;dG9oCeosMUd~}uf_%fRaj0eyZDDC|1``z5*8IGK?6(vDHf;gp|d8#%^0xU+eQ{L zI!17^S5u<`DNcq&{^`>Jt{N2}Q;OuDvbn_bPbpEfB!$?MfBMqA17z@1qqM&K(>LVp z^z|938pTjCyFVg&6I9PZRWnL!N}7FHpvnObUwH-rb$Ht85mL>cb~=kGhJO#;sk6l{ zx`-c}bss1AC1P<{til;4Q2R9lmK!HF>%L5IvR6}QU0(V4I>5~&AA%@aEY75fUp_wO z8AML`n5`7Uku!9r+9|9E$6{z;QOQ`GPdMCx+A|DTZk(8KoKA4ER~tq+0)U%II0R8N z;V^097mfv06C_Pl zc82CjIunnPxt;Dze7+xW(wRsB+qD6A7ojt;EdbA@Gx1*0OFn0!1v{HFQHY)COyobv zJ=0rKFmX8(EtouVoQWUw4$9&J`T#V@;!J!WsW;2c#QXDN`wtY0RA=H>{eY7WD+*Y5 zSUH@D-}S=I>vEzU`)4OQ6BG2GYiHv8GrbBdc~{?mXXMRlKj0*9C}5p8={~{%oQa#g znC0axMLR2J-SuqF#H0?IduQTXfxk{?qC_a+Osqq@S#l;K3e=f+09X~_SME&2&tL*; zDML*t!!=dS%gcIW};l z)aCdD)^M&}j<;t;kh>h8f(iFuWNKyb2GQ)gXX`S=OI%_JX!D4JKvq={cXKJOVs zPWhNEm*eI@XR4jTig26?4J;}di}MMGTP5!?V7YN(!ZAv4vR4~MIL-&SnS?_SMH3E_ zCVt`A;2A_hIGmuk%P~q3HRf_eQz3)P@zxY*%;m@}B4K=FaXE6^(cP#(C$-(>i0c7$ zIku2n#N|jn4dZg8rqf_9N6#Bi)$Vk?*eXqh?l+!fm0{m_5|C2wo)k6vRrDc7*TFTO z{Nh3IP@#k8jA!->)c`(hh5z{t`}}RE=oV-YJqzU*7LhCuJFUI?rt7bRyV9okt!%=y zxBMba^%p`Hs*;g2p7c)kJ{&thh2#j_g>9(8&a*tD3g8RxE=|&Z5b@}4_@h6+^t!9U zE4{x+l6psn>17>r1sVT+%j!50$iQExfd{2Dix- zI%W9Q-QDTV)WhA4(y`qmlTCOXvc0<+mMUQzE;NN}Gux#yJOzZ$E(H_K$_%+mGdNei zr!;~R0bek zgaPx^TpknKOcY-XW;CCt0P@-_dT0sUc-w}%8vD0{l4{52ldBYqNNRjl8YUNgPmeQU zj9+>z^d3B%WIQh2852K_NpS8!PbJ%_K?Uf{Uc7t~@P=z6o0D$bwC>YFJUb+=gHZ@HIYYritxB-h_5eA*TuU@o+M_8D;J)`i$6*gInlo3m7YS?_2SRBL^}}`k#Prl zJtpBP$3`uZz5hZ$u}3{zu?9=;GS;xgOG|=~nwh)+s#7dw(yuJr5R=am|VPWA5owV@}~o;<)Q}jPP1Hi8Cqfd6fnN;(8 zaz{{uxJALc{Qdyot4y?06cJ*=@Ew9s!gY(qDx7rJty>u8Z`EPBabn)NUlW|{)l^}K zJ_i+Zxb_zUBB{b42%-stNe{m;eA_dCoWihHv0&UXq1iMnysni=g*=*>8%#oWKm&`q zz~b4Gko^WMJL{2hOhPUrIN7TWBOzA++*An>1kohKq=#QZws{7SkPs&*?z??sio7x3 zEiPOce77$l)zVkk<%hyQtn|a?TGDV|}iN9XQq4@Pc@+4hj8V;I@Y+$=hM46_&e2>bl=|Q@e++R@J6M z*evb4V9(f|N6ftl4*{3e>1#~HWGeIbiIk_OGXJ+9a59yd0=CZ!?lHhr<_85};k26r zm*SeUeROfV6fM|Em*Og2Uigw{7E3j`B?SwYYte#*bS>`8E~a!9RNZ;lmf|gaWD8{> zXnOKR4&i+75G+Z{W6&Urt8pi(CvlUHcMFG_D2je|ii|IcQdpO?SH7RX{o$(B`mB_VA_v1C=~ zAAiy-Tq5|Vzu?{W15P?HDPY}!xe&D|9|Zj(QGd3#hrG^9+Pz;DS^2U;)$s|2EMdR$ zL5S~i9Ix_@!!lc5o{ujpm_!1>Gx(?5L zVr-EnFic`P14bM1Jv?+Pmj^1M*KJ{8Ms6GhuC0tpDSCBc0f=dvM~VS-++vOD*2^w7h6>~UxuZHS_5;UF% z32W@Z5cLwvr{*0Tr6*dc>Pu)?s*19G?L%#j`QeM8w#%AEvz0{^=96mvsKN%_a106) z&1T&?rE^=J&oahjpCO1Zb1C0R@CDN7ucTqIN}JSaz7WU2xkbOo>HTs8nj0(TRQ^4J zmA#rez4J7nNHZoM|48t%R~tq?J_B$w$%i0}CLbnU z{POXqo)Y`dY}u*&?M^D_+fKr*D}ZjuRzXut4uu*2?{R;$^Lwy)+rNAE8+qFNK0~z0~RS z$rcpJ!m=nR_I8!Q-C^hf_HvLXwxRG8(n%cp$&e&*iSW*lj(tKp_9@cQ_QG~b2kjvp z^=Es*Tcm>l-Vk#dNol~J)TMC{Cdf9?dH^@1*MbNKd5R+TDG=(=_Ca(<+rirDg!X)6H$6`U0_fEmr_=MW~fYf&C1VJBPp~ z!;PPU23eNMfAs@S>TwEK>MZr3kGk0Wy#OrC1!=A<6D;84R!Zcke=K0w%mlZoV(D9k z@mA?fCkUuV0v6)$6fGGOQVJndM`}nkmu%A)0Yfz;<39_afy;R3G{iW`uPGD1AS7lf z7gdI}h}gyRckbk*#E%lWEq>&Z0gTfKa#cC@#dLOX@cgUnVyC~0>Q{2cbx9w@zz~`=4Y?ie+$w}TPWVYQ1pRHaPuU_b7#*g`5 z?tlgsCp;FbMy6$-qIst2hJx(^jqS@l1}sBYDKulgm*)|j?A27?OJ3LeivX_bdqL@> z&p{ckcS;mvfWQ;3kBq#!H{=~4gP-PoUx+fm`=no_27FK6PTvU)Tq}S|)#!ClF}wdA z543cv_1eT3!8QkdO>em=b9N<++5o-f4bO0JqsqKdIR7$uqmGbj>2WMpb!wwFfx|e z>hEWgzwdj{R&tm3wx|s3MYGoG`tM!s6*TQ;5`qP>d5#&>M z#)9j6kYF?s29*#d_H?ZQ`9`&Juq~)n!s!;=cGBnyH``D!{mTh9Xn3mcyke=U=F&;UX)8!23M8ri z%z)|?M*hz0`w4RPYMSx%4yc&JKtGMIiIrx#H;vOyV5?e78HlE)$e2XaEf3wFy(#)V z&)CoeX4X0idj@Oj87a_M?3mALF?|y5a0N~7L+5(W-KY=|1~{xL{Eb>wKg3VOsv@6; zu&S7<%7Q*m1?4JGXA8vdASEES-<5_xQOtiOFeje|!d!jlRU%P{9=#qASVE&S9f&@# zE5l?_sk-fU;`3Qn-Bevp=Vf&VDC*VVrx@XWNm!>y)NnN~h?ka|jdIxPvNI1Glma;^ zmlX7=Zl7(qLac&4=0Z`MAaDjCkl(VsB|en~RWA|O_y|nnjr6BcK1IbZ`u%Pak@!Zx zJ<0*>E*4?M?G}s9``vg=daawXgj{z;v)$@-M&Tl|+A#>3v5Ig~st)&=H5;A1L1(7X zY|Ko<393?~%RWKnQXMZ^+68w`bi=78eikeI>;jbx-6~jQ^Vci$n}pTQ!rFAn=OhK5 zo-1VN^@qY%9pWgRpj!=tD&#_smV2;W%7#db-vP%8x$p;`2-4j`b?xNJb?yrV`}93uzj>1j#Ak`Q7e=AHx}I5 zhAkb4TN7lA^-~o6jE@Hg58QI#P*9qj1bcgAe4H=uaFnsx9UtF?t*X7oQSrUm#v;h+ z4>7U`03NujA54_WM`;K;Y5;eO?af#dUSQ{9`{=<~s`PCROrMV%tjy;_TAL6I1#mU< zpx9g#gIc8vmjcs|?AnAFazs~Z;;8_f85qg=yVMLUKVqx&$-uE1kuyX=>4gKMv}hMf zy#mUQ)kA=_K zzl8>5ZN6%j1|)fcpw&%xCV^NDJozxe$*rI7TLgf`0*)>Inso)flaIrXVyU=se4Jgg z%Xo$yJ3ueqg;~7+@+;uF-F7$y>vVhOk^opYO7|`Nc3!;lw^i>=p&3{O)6L}9H?iX+ zzd#qM{c?_t$U=o@-!bUq9yrtC-zM~d#r1M3fE3mzC#j$(Xj9bf~0hwXz`3zGBq(H`sDr8*+fYELpI>+^7%dZOXEe7!H zXfFWbDuDc0p6X}AhIqY=OA7e0!SKwaTh@Z)Eh5}-k6xEmY~hmC8-O8USP`O1R)ZTF z;V7Q738rgPu&ac{>vFYL6@o=d;xp-cR4eb3a zdvefwpcPwin+@Crinq`Q9kQJyE(@-@pwiJWYz25FC~VVqP+JPOW{(~W6@?#7gC7Zv zWks4xT8f+DxB=WfXPKf!Y>1*g%}JKbxMyAtUNA70t4+ShmDr@KT?BcQi#amZgVZV_ z2l0c6db51Act;N+aq9m0&1|J8h9_F!|Dua1y()<;vYle3*4`0}UKW5aj2smop-OuO zT9oU(O6X_+$<0lTh(?6?-$s2RjJ+yby(p0Dw_2QAg$mkX*Nhzc??t-#_?|t z(m1s?I!LU@-*IGg~d^U0eM3d5XN%8Yb#YMFxN=XMEDi$Zz8Z-a9kli zhih$KHf953h|r;mH^tHTM-f)a z3fvKgy9@Y-oT!5bTaH0q1JIKF3Ls!UVZpxh#`f%jBnZ%wVWo(P&HM1yN?BCuk^+7d zMBb3LHbH8>I9h&@68ID6q(PB#--q@?(N1LT$m0|1ZG__J*ngB5owQT8%yc1l=Mh;j zl6geEhlNXI$lBQrM1vASo?lof3*qbr`68*Y!AlLx#Zhaafh&hXJ-e}z)SJy~)<*rP z@{_0DYu0vJuyWyJriBEbVJO(N%XpT(Q6Hg-ePvZ8NF`mc_OtK4%M=+ z62lkf#qfE9Vz^RUC`>}yeg(ekZ6w-n$cy&t21R=nC^2P0BX}1S3XjO&>6kXeYLP_w zPxGSuUV?J^&4nNJ15Tbgqk#2m^A^Bj&G9FnCE}mc2?cAbGh9R%+n zrKTX0&H*o)+D07kJ4A-sZ|?x40x5ZCAvdJCYw)|s+b!4516RV+SVK@I(yR6tH{li+ z5}6?FhsbmV=n0RKLeLsmHwF9I2JzmPF<-3(SI&j)V>GG(u5XewG(!B$EG4P}7tK^c zcmlOO4Jku+lA7>jRc`{qtC%8GZ#IwiT5#)t5?1Bx4(cFm{o~*f~BKeRoz2`N4)~ zVS~*P6GB+VEC(A>vo2^Fup+aV57h_?SHNG$4ndzWU5=wqtC4^2{`|F>N5alfzZx14 zAE|!BAr`CgDBH1uZ>d;~NUVjOpcF}Ic((yr_opb+oZn{m4uYY*ntHS#f4{1wlyTSg4`4BNFBrE(UZzDwt? zo!E#glar0mz@lfcc(&wZw*kwI6O)r&1Sfm7VdUgIfSW2Of*_ilnDp?=$$HNKa>~ha z;u~|zM~av1DVb@{AdO~kt@odRM!+>RHw4yhT5}fSShLMLBz)h70K@d$IOnUg` z;jm`_IptvmT_)WE!Tpd-Q}C}+MckX2{7fWXNw80d1QyShNW9a4W#_db5^pCs*{cmB z67L4MsUjf=qKSk_55Gvf+%tfjB5|_j$#qMH;qm25iPl<)u75EzPnev1mJBH&Cs;gN za`HU`mR$f8IeC!aWUn@iocsXbrpk#Rh$bf{J^XTVzh?kB;s2oq1Nd7=AIhv;d)v&R~GUQX66W+cOM`FO3XVf&NuI1 z1l;Mg06$Az@F@e9eL^Yo?vn&3d$nQa-TeSJb>2~eWS)25%sV&+f2eu)v%H=Dc#bIg zi|iCN=bb5G{(1K&o&hB0of8y)iQ*+Gz8!X(2zr<^+$QpLQf*f6{yTR}pMLhafCFcD z{}r%7iZfjCa?7`HEKX%q^dw1IPT|L8!e@xN$$CtkotFS2u2eQ42f5ktVt*ZeR}7LY zGk4u0#qNsX0WiUYESIhD;HbM%f%-?CZ#bj(l-{{ghvCrMV#ud~?pz^hwp@x}00Z1s z(vJ7S)&t|%A|<$kC+3R8x0RY5yvqzo^BXa2(A-JF?Kw&k_6&_(gW`EY`f;AtEM=Gw zi9IW=xQu5vzxTNyDeBs;D;IZu?_HvuCBOG{&)~RS;H@K-&C5hTwkuiO*}fM1WVY{C zzz?&nY0@=$x7#Ez4fM(MSC)87?5&Kcxo`2JZb`s-6Etw?Gc}Ft4@f-)H`Ny`kyA@8 zd6a*d7rj3l5IuPyL!=goqHGT|f7Xv`rp)2{E!aCVhyT%1nMXpsoLHwtcgR#_k|g0Hl*rnq*brgL@K zrPg?EluwXOaJ<@tRG;y2qK4t@C_jr@F!OVEjE!6~iKp(>$SE{{R34Hyv@3u+hv244 zyxfRfr-f%~)W3#cXs@Pj zG-o^Ih-gSN;h zm$Z1C^ItY#*%^;?V)F4Nf|I?PDj(6ipkj^$qpw1B)eT{l2SE@`9!z@p<>AAg0pyg2 zP1*vG8p$!%g*0n)$sV1}cA6u~Ok5T~1B-IO;@J|H(+yZ|oS3+rN^r7Q8%A8V0Nhk@ zp#;%2CwT*gk=}R@=DfUvWAKOaDeuqQ>1A_7(JQi3)buHv66T+PCwT^tn1D`D+^2kJ z%5-KvWi%l&cpaxmwOREkAJ5ESX6@QLa8%+*rB?2`Z;VIRGFDTJ+ZSa* zYltbzdQ6?9&nM!5BBkE#j-@F|3kQY6RtEJ3qt&eI9oA!xL8*7In}c!+H}R)Gmk`E2 z1e_;KvQbE32g zfBFU1D{bH!rq2 zuQU~kqjZBbmBRH{zi`P%AjuWHU&rxKZ_=Y#!#VdRU6&O@9<#p&8*Gjkt}qiU-Xz7o zS|!L`fCG=#6g@dB*~UT^NJ@@p#*=O5o(c^t+c_*wv5brz51`HUo^iaWYrry8hvY8b z{og@wvR6}W#hl)u=or9NjVdyuOmC1Nh_?GT>ESeSh*9-q&j1vo3S}gNQFRrmHmlo( zHv&kNy>?n7s%*RP2iPFHIOk14d4DE+RNhC=hbGxQKb8~}EBF5wKy|HJKn}v)clqmZ zlNm{tnY&JT;wCfKbb<+4OlGe6-Hi&Aj!u&qsZ34g2k;Ylu!wvb#$={SaZrAH|56K_o`nBYIKPI27{zJ$kZ#+i)Avnoy!9<$GnIDx*LYZT`av2QQX;(^Y5_aW} zfbhfFmDn@2E64B?e&u$hP0&#HsSiN@gmFIAru@q*+fBH(0RqMJ{TF=drUq{)jRjX= zVQCWMyrqCVfzU=16P`fo1dZ@Gz1g~ersy=e=mG9EE+2)vhlO?$Dqm6A4Zl^RIj>5&MfDS~j@ezh| z5lR4WRzt0Zy#3?1dk{FgUb&}r68Z0$aL41O=t5w(d&2VxMi;!z(T|bY)ZjjkHMAPs zvudI|AuEd9M7a_h2xMXD^;_KX@+eCj6uo}NeNsm<;iH-;In7hnqiUd%sc9Ohw*n$* zCdy6zI^0A-l4USa_NPE&S+ZO<1QW8DC|r@a8x^7|^dCD-6#SK%DEHteVxo{w!gj7VMqbvfs5-<~D(sL$iJTFXyI5Vw2ePyc*gKx9P#2 z>89rfU{8c!`KISoyC%1|(|;dY;X;zS^*MHB2v^;OaQQntOGPg=taWkM60+;@;H59s zJb(7(_1k&hDPvB-|l5CY=12hfKhbnopL0bPx zO#5a-T=isG$U-$R+f#y8+PcVPwg(hyig#uQsTV8Ot>$y*QGtbL@?Qaom=X z6_Oq%f$ejY@3`(o8KXO{Lkvlvjl6vE4L1S*;UF%&6A1TL!plE^f&@u_lLa?2r(9Cg`^;`Mg_VUI-?Z0RMIHLPhdDSNLI6w0oB)H@)H_jm_1aM``8m-QS{Pevw$KVLeYMNu{v{{cU$nOyvr zTd;S!_#bDfY;*COLycFS&Q;BJ z5SAeKjS&oT)oSgauzy!@`HsE#Ko)<4>4t*`f)2i@RDzecN^N{h3nNeL&87VZuY{+T zY$rO%!&?wgfLuEEVmk>~-Eh;@2M!T{+dCt4r5y|45|;_^`IBOJ2#R#HD*z1HLtOv{ za{D?*Ay@#H!~ylG9>NnOyGEdU(m@AeT>+-~%|O=>(SX1Lz?8Xn-+TCnjDd;Y(4eK@ ze0vbVSpdF&DL8ZN`~Ou|40(p$FR;PphzU8ETC?N(r{V|~BZS=}a0=yi>**P89<)=N5}|dgDTQxh{-Bv0w`ZEPZpJ;>5gh=MbFi)zm$I z&eX(cC%{#={6vA99)3y?%^Mf(IvJ>e&+Qr~uOF9pWDIzkE6(EvKbW`6Ycmovx&$ib zaD(3n)dwQx(;g*>sh;?*C62`zr%8Ui5C_6> zqhF-5xz~W^#)?hsR}rl2)zpcdQx@YDkn3Kp*CxgYwy9D{iK7qH<8XgZ-eEHML(KBO z$=l^$%?)Lvj{w}+rswDL4lW}-WiC9(y_xv_t-PInV~!~L@7XD8sy1`>`c>PrJOjw7 z+BTY7@1TIUZ(B{2HgreV8LIaE0g2nmt8@WZCVQ5|{evSdn zjTO^xTM1V7YD4I^Xgk17orQuVTF}d+h+k$#JOfC`j1v?OdM!zjKo;~ugE~WG$=#?x?JQ@s4|fDK+V_4K4vqGaPs2p}=)QT-Xy0gOrqOK7Oc&uqB&2hu zo<%w{aTZAj;EeQ9KUdXrSN>rgk~jP|T{=;0gte*aM6=x~wnFySz`l!j!5zCN;NgL8 zslM-`J+pR9=#$&%$`Ss+J3>o%;XBa4wck{uB;O+SB!(gqCj&>KC|huD z@x{94wyUssIUY4GHOR~L{b<2PKo_*yPfvlyo1z5(!^GYhoIA-0m~F75#vd{Gxz$e$Bg>4+TC+r0ZVTc{xQp9)MFT)P*F$oMqxyJ_e;k zj^%f}W3e#c*%=w|Qa|7%11Mmf0rM}~!?DMY67AP}q32}*?K&$9-1TgM(&W-M$AQv+ zfrZ2wD3#bG0;L~?cEbfqv1b}6y${$E;a46gU87qPmN4nxLT%hiJkNN?}p zQ1Hx9y>>LL&j5&4tz4?_g1BQBf@$z&v{Z>o<*-qnfwEdhUMBYl#7xeZPkLtzU#4N{ zhfUAsIGpwK`1JZ9T@2tH{~vr|3&qd&{+p^g)~yuMXjqW7sZ1T)0T? z7Jfy4$K8Fr#AFfJ*$`MNXrYDMj?6phr15dbdI|^G9=NMdg&8hI$^+iEOu^FYmK8LQ|(f#dI{~RQfo|M z^nE(0^rnG-ZP>TLTfS^2jh5>@a+?jEJR^r&0BRCYYQVKNI4L2|p%!+6!d7(gBWl6c zE}Te3kN*tEtuqa`@Qh40%NX(()4$qmRyuS(w@Pp~4&ZK)3O2Hvr4$ZW=vs*X!s+df=|t?;3$`d@{lJ zN62&nr09e~6oC@26O&5fm~UDs_85{`^%B}`B(}P6t+@oW=JyDH>|0aZhu*gc0B=@X zJjl8NL*e7_BUh{OC#ZxG&kEC+aIU;fukdQ&-C5Lw1o{H}uaNw6XE+vIj-~)n6eEY9 zbR8TuE`dS;?b(B;k1NgN4G8CkrRlNYhIVbL24~yxdRaIW&$K6+38nh+(oAQBq-(X| z9Q!3CiwNC2!DXm?z;F=83D)m4+n6j=s<*18iLi^dMSW&uThMLy8gM-rKM1e*l>grv zn4uR|YFy)*z`9l0_*h-W+(N^S=AR4=NXY1eWa9spN`o{_a6Gvu*(#W1s|g|8^wK98 zwvdy|K9l36Xy9~bT46t4TxyplYGwEUlVGxT0z9no;!bZ8KgRRM`Z$fhjgwZJ#?t1S z<8-gf4XU}xz(PKc!v>qHJHW03@p&ZWdObDsP*_sPZG`aYmB5G< z^NAYKtCj)FOenk)Gbz$ynY_&z&QR?#WJ3Q?(%-)YEJ>gQq8a0wm95Q z_?S=En(^h_s52A6`Mb1bpPZRvOy}K9IF`_PSgcYlRp*Ig=>W<&gFbD*N}ZPx!O322 zn0eU*xT*6}5JX!bO?vpH=#XasIi+Z|h&Q?AM%mUeNl{9qY`i8jADC?P$uJVKfyJ{W z8}Be+*_p2B?6(n|?A3;mjduauRM`*&(PYD~mKwoUvRHt=l|73*=3w7{QdLTCt4 zN~Q%`?WrFVIl$FQO$)@*l(~fp7GKwqG+us*-e}fmM=~uiWk_mTpgAO`Op~<09}=?I zM}X6V2{cMcW`TD0$kPJ3(}bVObT`-r?r!ko@TjW2L4lg$&U8TBG}3gyOM!DV9gut) zA|23-I~Sre3$Qg^3K6Sv*y?urVRb8ei{|vNr;<(KU>t^8(?*C3uAS1^Py5*>3MmsvJCb&^|Egm4)|pgSE51ICMppSpkTN%07;6IS4B4@WsKURCb3+YkyX zGFS)W6}$w(ZDIdlj4GuIfwoRRUJD0+d)->SGX~d>lgl;17k5jk4iD<}dE7BxPH(6z zVi>J|u)6ACyle_%fhD+W6TmI2fbY4}Els!J%kp-!*#&&LH*Yz`0wS4>qwwOLg&e zQM@)hQ3FDDOWj_FS6UP=s)TUkD8O5Fywq+0A)yBP`k`bQUO^fn)`%a;Bq&0-zlm|p ze!Q&LogBS*v{Qr6oAn=yVY}UI7a(_T$xz_!7z@0;L~sF@7;XL_L^z z@hS>8*?P17gV8u%gJS^k>r{b6br@4WUdf-p1BzGR`~0xck57hZZnIq}R>BtE%-SeJ z{Iwsi5@JP!3kt5}zt3EU@8t^FS~yv&qfF9gbYZ4W#EW4DO#+F4nzf1|N~=n}ZnG$h z;`y}-V1%-R(|2zZK;r9^_nv1&yeW~UFD2}wha<1;b7 z2S(5=*BX<62b1e{DCnKugkJ3w1OeE=33I$G8N>?FsDPX;Z3gx5c?70wlvZ_5z?_&a3gsXMQ0%l&Lhp$&SEvg)(pAXD zsl)#;e-=U>08FO_TxPDgli^$U=hR0ra3GL=O@b+f=GzA_Nl=XrWAs5ZX%6VDwD%|FyVIFB^SaZ0unibl2EGLu z@x& zhL|P35nIHPANWX|sszpwFNs%#5dd0<1>zY|Rt5NoDI!Y@1c5=~<}Tniu}*v?u7rTA zMAL5IAaP_5aEw?cR*0Fsz#O5JTTfkg5Jl9ZI_y+KLXlcYa*cvVh-G4xxKs=D5i}3! zBOVh^hzIq2OAIss*NIdkFip^g>{YV71Gg&a!~^_5w?d#1ry@+bf%2~6vaeL0T3ur92B>j zoCltiK5%T_NvIfy($lp?7}Lr>@fdomDd6!aeEX@)}AQGJQ^3;?=iH z{e4}%u}JJ3XEmmB(f!C1bjB!6P#!&Eg(p@g&mjSKASp;*5KF`=4i8LmJ^m<3kKYUR$g6VcQ8v*98hp$f5MF*gd0T&A4(*AXpyk$R#=srHADF^QBC_HYyhX% z4$7twA3{u@?0!0qA|s&>g&Ubz_cn6-tn ztRq;@Ah}ZoG|Yg5Ba^9=j+4kJ{ij)2gZ8J0buy2yG3rgFA%tA5>& zUL-xh#DvWv7XrA$l0XtNBn*T#K*%yAp7=`w3=B+|Ng#wJ=1Z6#Uy>QVA;bIvANl^L zmRnV~>sHt8?gyFQ#6NiIuCC>rQ|FwjvsBe%D}Ld;^Ol@P|HT_B&2qO>tGA~c%}Utr z#jB}cE^KsqPxN-bviE4O5U**K&a|7|Rypj&=b=WqTB}!DVWam*uXm#g7iDJV56L8)7*b$Zkm zO_$#no+ThWTD+#m0bMy?0$Au_Q@o~_;89%`uN2@PiBg%%rIYlnSKUzER$W`&UR_q*5nsEf z+MEmb%r?*NIa%xMDa|xnwRUF@AZhO@auD{E=4*S}oCMRYHekK<@Y3!K@LdDoOD9{U z`KnH?=bpZC`UaC!lblXLxmv0<@CAe`x0>ztRJ&SgRf5yC@JxG}Q*lc?bbCQlU^mIJ zJ664v$X2}!w5kS}qRa9BEAjuU9_e+fh3eJS9o5~yX1OE?u$tf;q&Q-uEQnVS5kNnh z>@D(}8uVtrL5cb|@~Uj`Ro$6*V|%_@Yn+`fRVsp~SJWDn@T^8w&Y)IQ;#J_FR*g-1 zAznUTsf|p37Fu@9z zbN6yNuFcKYL((7Zpi>Qlqhae*J)Aml=OGSWsWMky0s<&&im^wD= z?M?}c>C=xt9=xnxI~`62vn5DGWfBUZRL9qsbg{fNI#~TGkESNF`c|QZN9j^g?d|!f zwhF}Pxv2IQK{cxQ^VBz}_C%rspU*Z8#qcy!Ii>meuu++6HtGv}eGCfh7smX&q>UA_ z1Wgm3=8f1-Y2L2>rXb0w}+U_SD!2G;NMArDpTCl4(rY&+MUhAdY&gS5M?*-{xy zQN|MdXfWGs1@+QG*uol8Zq9);(9qb>F%l%=UVTz>$p~F4GW=0KGOPi1f8av~s@PA4 z8<{d|Pj_lzi_@S=i^-W%YmTT;uW%}WDM&BQ)WaY=UE|x@6czr9puz|}DkA(vJ|av2 zw=ek+fhzVB;nqsns-0%)0*iBru$%!;v>6)&wC@OLClPd-0bgVX3UWx7{n-*muBgjIY4XrUCo1usbM#6nwjF?uvI~dv5H%r$w8dbsx^n znChW;In3R%wxCL*^$=`g{8DV!VBvMTuu-HTTwM|0B;l#d6z5Bw>i)Z%?b_M9@u{#& z?eC}Mre4BTnc20QFEIs-ypHux<_TGlTJIZVeRC6^E>`n0<(!v7ycS4IL7%gM;`KBx zGj7@UP+D*CnzM8DeeHQH39#--{fDj7A@Ol^4Gpj@+Leq0D!~H43VbMD!_Y|MuqvTG zx9pPd3hL)2z1eKaLcE%w<{+=8F-&Nqo6$Vlk3R(9E!0;Afafy+$*i6WJ7FuezlyKT zKZjgpNe)SR*5`28UWqZ-1QFvE`=}~ll{#~k{I00_h?A=El18s2C!7fP5GUM=h>kRy zn;Efa?B;yfD#19{v0AcUj*L%g%(($$Hq9|l8DpLoudFqgJ4O?MtNjH^LX@Y80{u}p z=$MMxQn%hIo-Wn9p+Y0RpxvFHZ?-zc_FSpeVWwEScaA9fG95enI$`qe{k*|F_$O-> zQVrru<^WC&Rzd?7o#bh5G@LVj?6k1+C%X-Mxw%sBaf0nGK2*OP10U`!fwOIzTt{UX z)V+A4{8)qqSv7dUrNq~?!r4x#bu#Sq;){x0TelNGm~fh`K&4ux7u^P!;+6PUl>RWUed}VWZ1XqeN~f`0l{Cy?BBYM{_2^g3(jjZ6$}J7q2(eE1Y{w7h;)+ zSI@!(V=~8~nkaUfWukJY-HSegVOa5NdvGh#4_r5`k!!(j2JcRScL&#x&`6ilS8l9G zjgR^ra!)FDmursN8r*po449x4oN3kg4owU~wmRH=A$D)@43TFA(4n)SQfmd*NGED- zHfV%lC9EWSg0c0dBRZz>CgGsoQBzsd7w9htd8O&)U0p zZ!k-%b9=X7*knSZuh2+*3o$~c3eT?&gC`s{(O;lpmU@P2t-`4z$wJjN?tG&pixhL^ zwYY(~H?h>eG~7S+oM%7#y5|J@gXdfy9K8*4eKHKV_p<&O{f}X&v=V6lw*gdw6Gu{ss{frB$8hD`1P|AIk!gheM-Lvo>-bN>{~MCjp`076 zZ4%bw2aW~>SVDU`D28F*YV@>Dv7;um=fxAV zwXj~vcE_$@zgt%Eq-lEhK5@6)ueIf-RWDM+y49Ch(SEAAE!s!_@VFao;}ZyGnw5n< z2(@U_=;q|RLgGcb03^1}$sYo)639>F+&`DDlERv7codQ`qYZ`}jWg7;W^c95_zWsDW>C5sH^# znkDw^vqJv$)XGP2dN>!K*^BwSq=G%d53%(8f2+ao!-&UqM|>&qj#cu z^g8@`JbIiyvhDskeCnqsSaiv54Tm&`+BFa9o2wzK$IxdM0yK3;@VgM{?o4J^(G9%X zvsrJ^jrd2-u-Ilqw`gVY+T$UdSlHnbw+W#&%G8wn3H9v71w#8gMGX?|6CKsY6%v`O zGx5aj+><8*3sFDsKz*&Y$!)qRra>=K2z#+!$-S?xM>11ibYQ5t;N4L(WRI%WIX8x**N!sc%92#aQ_ z3!TYptb!@emE`%$AkxeisDE!Xr+8uq^l1Yo2jzI2i#N#PDVWEt1(d84Kg#c$Q3K{6 z+2ZY_(#A$pmdSe56O9KOk*sd+09C3-kWp-oyC0H(XBdM8&h~lCE8c6 zAUlwBX)_fH(P4t@NH%1`scnJmZXL1-MNtM+^nml%hh4vtPSv_oxIEy*C90xRn_u}j znq_HLa~gyf^q5zJ=&cyWb^w{UETi{g2x6pn z;9qDx1w@~x@@ll>p33MqQ91em{wS{eFutXolWbpDT^aorRi|O2kI|=B&?ox(+FtYt zYPLDWodv5iatbX-R3Nv%gH|cI)$D>h4>pi30QW!gGFdj^9k&IPS;g$`6N*7jOb2{l zfoLV1;qb9hbcHh3X!k0t%mSEdhpR(vEA?stVWLvci#M{|(IRb}S*%mv%CFO5krHWV z;5Vjvw(rmnZ|qY;W*de7ly}JQdr~&~8&u3;6#fv^J?WV?3e&viQU%+hPdX4Fog|Dx5=M^= z{d-uo!CJ#G0NqC6Rm)A$v2!tjD)hz`)WBbFOwhvd5cxWg2o8UL!6KU=G4l2iQBmq_ zpBGrVaOGqHG2%cbcn$zz8fVEv8hBJXNa1{4SBXxAb3D~s_8bVi_AUmLz1k==F?~}x zX!D4JHf{mA&Vh<1AjEav0+KmmBrIOJDkpplizmC0uzKYtE4xvF^Pt7@jkb`&Ate=E zM1Rf!ooH+F>0*337hS^sZexG9v%fpo-%Huw%jhpr#I#VwW&;QeYo+dnT}(Mx$U6^P z3vL^AyJ@2uEi)|CyGFNAQ^WY#r;|pjf=mWF)@&d#R_#XiQ^9x))^}r4b){g+r?nT_N|B z6S++5^$*bu8{WERE5#WpP+xS9a28z{_OZx;5+l4^A7MGMnw&5GMPc$a_c)L1;|xwx z;=|ijn$Y0Gq^C?NVADQ`o&5gaKrEO(?l7n2mxSLsOEXlPBl z8|4>K-^-11P-JmYe4gcTPqjM>NVgYbAO?agA*8{G{Q7oq;0Q8|$l-$Qn05d)5ZrNF zlEXEo-jpuc@8r-_23PbB!kT+4_KAkrOeB$=2PdF<4$TI-M}}pwhd5wC=P4F~6IV}H zW=>G*26Cp5;C|q~`wrax0yvH6?CSl;4&8N(5rCasoj_U}PjtiYwdD5RnBQpzSV`^Hwp~-p&=?QI!|a|x@X{$Ozx3rZ_QvYZHUg$l(=(DJgNcX#&@m8%@RW`qg5%3*9?u* zHiwj`{?lOES1uSf%ylZ15hWnnlu>-tqKWvHzQy9;(62Z|gFMl?5@)f`gjCZ>I64A_ z@ZcOA*_p!pODUQREzJKW)zLsBq$Opwq(^1>#m?Bp+6ryn00 z>dpNmR-BNA)r%7-_e*iYB0JH)=#98=hJBtI?2t<+*%X!}iR?VlzATFEVm5RaJJNb| z8`bc%Cniz0iS!+BoP>}4Z_$9UpqZ{k#kzHC@#C3(V5iILN2%Vj1w;7Qf54!!SJPcy zhQ5&w9+J+9e(oa2sB0iBly^_$~)v0Xpj}k)hQcoM#UUH_5!Nw zF2r%r^X9zBdD7EqnjgtK=pi&%42mA}r)WBAk(OSU?%fuB%OPyEQojXC`J1ecI;r2M z%Pv#y17CIK?M*o2Jtab^wb_(_DyCAS;_)f9pG);NP}(17P}!@EAbQB7)pJY-3Lz(s zw^IAHyl9I4M^I|Nm3PPwFAim+kE7pl)AQ4Lk@KXdQ>lG9@1Xx>ktq6?{uE6swY2oQ zmD;=m0aK}E_wxoQzOT8JqYUZN*3cDI5_!I#W!1(S(%rDiRBCqpLYoe;i(N|%2JK=K zhmet+OZ!gSPS6N`>e;-~NqoCX7giR+PH)IXAoOxHScH{!V1lo8FLRj#7-BF=65sBw zBbkS0#G83C*;R%+rTvu5u}`>DIzzJ?75I)YGu%o0MIP>a5a{r5C;K!?xRW~wMhJKA z!ujb&yTnqH-NDXF%wVV1E+f==bo5ZCF^FHFbF6v?zeWJEHT6Ac+CX2PvjZiFdSIo2osMZx?QC(M}v$~U4} zmR_^Q?_TfKAR{Vdp~#{{g?KQS>&d(IMa8At5W)XLn;u-(%)9SG5WR%BBW^LXr@KF_L+b?d!*wK@5A z+G|_ytEhoLpI>;04({Ueo`)2xXXjN$#x8udY%7;pRiISK^SludJMjHzkhN0jJQi(0 z#Z2#EybNc-aQzA$n-%xVY{bzlgny?KsCBd3%3(J$P{>HsQ#Gk{kUSc6@|MS9s^{#< z7PNYp0cfx0PpkeT#Y4%XqL!Y#nWmOo9-retNRvlma&LLe98p>`a?wh}#>bkG%XoI9 z0_V_7YlirjTQhH^Pb_(peHz7@;p^K7*36Z-i>Zj~&q{7n<|5OSk&QC!m=}(2$EXqf zjF<~#17^WY(#6nn37^z+=+egpg*zc#tQ6XZFj>0zo6_fP#=Jl2#%{)}mhdOaH7QWA z{C?8ONCu1r7Q=vHVSYwJ225cLX3Q6zkY}1PpF^{(#ldREe3~^d0bT}P;O3ZNb|uA7 z`0TTy^WP2!?bE|SYgbqby$qwvGK-61bbSg~Wg1-yh(4q1J!m(A(M7{@qie$&e4?+? z=$eqCVYj&6i>h80*Nv3d1zU<;;m0q?VHc<2HZUA(B&EpH$!=ot^Pn~xu)FE8r;tKA zLJx}DE(Ctr8b;feGwbU&2s>_lZ59n-+$^s3waXVmX?q!c?4#LzZP9czkQB zFZ*QER#}+rPcWG5)pVYSs;HQ0PW71x(c4j7H=wLMkPyV+fiykbJn%9H0wxb+_d`*( z>)riGQ=c@IhiUOlR&A`N{^!u8&L;Lbqp1~9w$D(5K}uD*v?jn+BK1pbW-3S+s0Zh6-H+`26Kha3Pa-;b234CHk zG5a)%QOvg;qZq}w(I>xAEE_GJQLIMrGm5v#2FfU&duFz=prp{P#=$ogCx{G_Q?Bts)^hh4%)^zpk2Z5TxY2x27R?3Kw$ArQTXxUV1D&*Fxyq`K(pS$ zfQw?*9|BgHX1xNU&#d2zb|aYeG%PpkKSH1AYhu<*skWQ-*P$vY8yJ)BJBn_-e;yB1 z(9x>`OaZCzaFPgjZBTkiKjRCb+>QPTHP{geSfPS`@+SVbym1f)+&9p`V&YS=zN}gHm}ai4cf{xW zsh-UR(_-R(k3nd!rf*lrZQ?WGOq=)#xeW6zO)b0LBh!sGw}0h8NSb$FVRaV6#J_T_ zIkR@c(k5GQNPq?w4x!>)9O5wXZ%Fl(4U;hOpUq&hSJQbSnn1-ICjLHD*9{me4s95i3pssLm z!kJWG*)R!C=rEY<)kfij1@t?R6B2?LoRFr6n-d;(AYgJrc0c6o`E$2cktQ>(Sso_y zQ>@xpojo7)o?7ATc|SE6w7e>3k4n|IFrdXD^6$Oi8G(m{3uYh}eQE#)(31^&0`3L&M93t$~C=L<6NgKf-GF8Wo zpLkBoehYxiwB;2LeYX4$p<+g`XPsgK04A4^|Kd>#Pa`WDa>Zq2A; z@%tYU#@x8SS2P6ji)-B1d?A#^{VX-u5eZl!F*f5~?LNj3o`2LEL}8gNpn=6QqhftB zEZdXUD$J%K8A+5e6j`1AR2A=NK=L8Ws<^d2~_>uXheEopdEF??YOzFi|1P?(^<2j*g(u$!r9VNr(C6* z7w5aUYxC{}JQUhUjHlr{P+a$ffYvV@x|3>ii|I`Xn(BVh`0WQv0GHu{*RIPQ_QZ92 zUvPq>M=x}pm<&$Plb0ug0@c`!uWgWuE-i00n;jG*jPP=HOB#Oav{8U?@$Tsf`G`%S z)jZQK;`+a0cs4A9et1Y4p=El;S<~&ir-MTc7JH`GRrhi21G(Fp0il-H_Nyt9q;Cw= zaFLpKLX~M9{o7PW=8B+Mqw@Ms8krkXlX{|^8=#e(oD!7f>^)I6!M{5+5Nnbd(r|La zvca573DY`#hPBQC$SPqVdLlr1#9PGN9f->|% zk&sEcW>b?%_0IRNYhqHk{Lry`4<5fSICSj3y8?X&I1%Xo6*xcRS=Q<#o@lr2nu;XM zxP4!f-AS{PfH-k7!2T+D;J}gl58fLTZk-H_|LwkfG9Yo@J;5ghFG*Fx*;=F4!M)4& zXMOSVmR`ES zwIkK_&v{fcVI_KI`G;H;;gw=VY>mX&o6>DT{}Z+3#mJ)Q2U<~F8J5KPDI6^U4ic95 zxkC;tsXcUiCB@r^q&__?z7=gDSerDIIC-_T_L>|tl4wnNw0ZimcL|}?Sm_#HWOS88 z_q`SvCfO_BM(Q}>JZiyl&(wL*KarwNS`f7^95BW|_O;kNpoIw)jlt!?7b=pV?_<;~ zdx9JtCREhoyY3d%u0ortYuaAJ$PkIOFv zbbI#TvrJ98O7pAbzixfhR3~;6wdxvqk+ZQPsRFl zT0EDgv)_??^UhRX+1f)S-@JptWUr>XJ#)JEqhCh9dfEgt3e)aYk4Jxu>Yfw@8b*L5&0(3km<32)=|F&X z&UAk96|9aUx$y#~2=QD6d-#sb)kmbS&`5BT&Kxo0@~e`vf51q(bl6#yRs|tt-{GL8 zQ{1Rn?`NQt@wfN{TCo- zF3yXX=zE}y5evu>m$NTwjthAQ-H8TS8-!7)dG*lL#fugn145P4li> ze!uNtHB)}G`=NBim%00qfl^w!J;F^@R&A_-(o^2l6@k(!H5jzZP#eO_I^Fqt_z=@z z?BgRa+LPm`*%wZM3s$iDnicRfUa*e9yK=~Z%HU;ygzZ8Mxu?X8=5)cd5pRI9P; zH_Q8^)}2H@QpCW3u03N>^tK6l-=d=;cp}FH>8d0>LBL_D;p$9Ru;b14j!N_X(V}C` z2K2`{wdM0eif`Z)R)4YRSoKHs2e74_%7iVmbuT3gp9Kb43molrM3M?AG;iITIid{p zORG3hkv^e*8MDc5RN#A>%uqk=gL$Zb^(K5`$-?Z@D4~At+8rU(UntGbhm8u4^}F+g zx0!judc%zH{;|=+`{pQqf&J&{jl^kc6@Hl%UT57e&EAD2NAwsUhz&5y`ch*q8s5?V z9Z5HE4XXONHM z^0M2UC}zg?Z$YyxO{8Mp%>DxPp}O|524-wu5Au=KVaE5eesHHHH?8VA6e`*=#Ql98Tn#utS}Xcj8^zj`=y9%JZuy)*n~_Xt_9 z*NPEduFJpEtMkk5adN(1%ZInGuii4UN+?;|EK$5w%#9g({e&BjtoMXJ>OUiYB z`YKa$CgDgXbS$J1+JvFx!;`xaxose6%AG^onh#+iJAg4~_7Q zp8Zp(hG%ytv6pdmr_|q%1SWoQmy4-3Px$#kLIN!a`Fh-4jnf~suu%@#B@PrmqNh1= z;A5&eJIgU^PY1Vk>!*;%L>W1FuD9Ck)+<4`9ZuM?s)B3qVsMh$gKaBy_=;!kJqvoV z=Y5eig#nQA(>fXQ6sb@hDfyQKk|O)s&942T7K>*AR6%yi=}=@}GybYYazMZt%uI_}Q;V14}fEiuK*S#SLLPqP?%3IFjnwv>P-&kVjVzF$nF| zbWdB(*w(;jk(icD$GQ@78J^uVwd@NJd2Pun@GJ*H(z83w>Np}Zo0P@JqN3KYjK2RC z8xOrm3Fm_MqzJa@a`@8W87j`jHjW_Z8&ZAQIe<(S5uABFgUMb^XOyUjiaA1dKac9V z>&wa*2|*0TNYlg37%c|^-i)!9j2Dr(D6LK{2rrBq!3}9k=XU^sK7V#%63qo4e4K$y zUd*7NSxi){_cKs^@K}{8mN>s{p1w8Ccb0Jv|GMe{E78U1{EI=$7VHtf^(mtQ+YoKJ! zF_`StMv<%*`W+})oFLwk_1e71iT+2DtheSJ^od2H=-d4%nwG3Ihq)!|eg^{Pik96E zr88XPmQWc|Bh$chDlkAjQHrCqsK=@_kMxVwH$nk z&Pj84v=hxcF*o`mYOZMBG0tZu-PmKCD+HDZsX>CpHzmW@Ce25RYFeN$qMGW8BQxr! zl^Zc9RSux}7X|a3PM9;pl((Z<)|T8Fg1ObJL59QMLXkyr_+JkoGadd4h(3q^cC;J8 z;ZMVIhkuhk(O2p4U&SS5caO}WofPri!C4a;@iNpSrXT3(-+E8CRz3wMbfeNPm*&Hu z70x$Xoy2vY`MYA1t{BVD7k??$=Dzrr0&;P$D|*})Lg^HK4K>&i30T3+Hm9&!&d1>M zeWy2w!en?m8d!Y3RIF<|%Lc>TReSqZH0lj7|No2Ut&h`Is*O9YJB=er#On#Dieo_S{ zli;&+mC8N4QGwGjbLUD_<~!GCTqt+0?9(VaSFSA$1Pav$X)Dxhg}tzPId(=@KGKr~ zrRr6W(9%_1Q{7fw%h|TN8%x6~sI>`s29}>UD^xeif_Np~;KkLU(#;{is`Y3RD0xXi zbpxh-cT$@Tz7c~TmSge3tCv06D^vqOFEAj$<5jpVuvH7&y+`ol1Mx+3%}Tc(-jv)j zB%qA9@E@k+j$1;%@>r)=BJ^Kq0KxYUT5S5ZLk!(uzBV7$YmIPUaBs8QLY#W)mY~sW z&6Vo4m$EPAYPWHUO6S7XsX8m_vUdxTwR{|1DKbAlA)IYTtE~qV3yyDhn-QEU)AI}a zD$Ozy`|&+!&Zdbe_6>5%FjZ;|o;g$r=jNLoOv^rOVy1YH)DPt?v`cega7VM;ox|@z z4W~&#ys73qVl1MN-P?f!rgh}iQF;YLiYM=LdPG+P>Rm?<)L$QFV(*EFvZ*z znFgJ3fAD9pd%QbrAwvPzkbt+^RoV*D;o2EwJWR3sTfz!bBXCDSYu^OBeS}}?LIlI3 z7hyX%aO6mm8c`~@n(cOQETGxs4`q~sHh8rj;7tz9?1Y&bL5F$aZ>9S+DfOaLnyH7o zskaV2s0l_u=@j}3SjFk!K(|us@B_jVbiD(HPmTtg*USW`YZ#d{kmbfNWYbo|hJZS( zOrR-&fW(f@bnv2Dry9KIz>#a(3ym@|HX6+?Qg81%e)PZ*)(*JM)fy$RQ@PphpiylW zKI7R|b8dp)aC7t2Ew>|&7l)Edt%ZP51nda5Y6hipr(3EA_ug{^1P#tKTcnG9SP*PR2e>O}iw&~tl>dYGfxrHhX-Jq(3 zgcWQ$`^trfvU-Sa{ArhqrA7lS>DnLdmYMkZ58cduZP!i~@qiT6ePv&8^A(-&EVe4U z80B`|a?50(YPIJ}WdN4c3Gll(Xo#uTl68S zzAbt`<1Y-oAsL#1s1Lj(xhnvl)PPS881Rfa;2-D%+C{+hA^uz5;62GOiF?*?8*eoC z-^pICuUtX?rKC&S2G`qhY=O);9J5yAVL5F^nS$t>10XsK*@%wdPblZmq}46>3A1T| z$Z#UJe*%)kFi)MW*_eVu)G-~{R7a9+Is2mM^^Z<^Wje6Gi)OGb4$&1|5NZ9zf>=BV@wxxy#*p2yuCtxrxUh#N!vvJ3Xc3U@K4%9Ghl+e zD0PDqnn9GR>x<2j{gTh{N#T3YJwn#0j2yFl+&#j8*?zf!!`=jky&4Wh_Xs&pd~no! zl=uByA^kn)eB;T}3wWA+h@~=F(i!Xp^TgU}Sx+LS3e+5(cH@_IHm8MVFm0CMA0?4? zk$;tYgpK&wkVql(Vgw(Vf0KKJEG`fuWXXJVrH1hI<=(QLgCZYu zgEN34KC=C!dxR|6&Vj?{-6IUZ!AG|L(mg^>+2*K?DBC++n{b>K01iH4f4_T#oMO*W8&T}HW?0uYiC?GJmBMZoDmkyaam|wR zDw=u9`GR|dEIAh=_{jNd-6LdigcxBga{e|q2w8Ie1S6yA;L6;(=b*^@+~5qLh>x8A zwtIvuInRN^Q|=K4;NT_1Am|uV2i6(nx zgg^gKfa7tMsG@mu7E;_|Bx}XzXLN?k{Z|R6pXTk0UPYbpq~?`;Y;C01rA9J00fl(^ zSBE9}y8Ny>YuR_sz@0!6`@mXT2d8*{^?s25`}*k1SKMp892QK1a#S zer1Q`Z=09&=VJ%(`lzIF|=Tdm1tmL z3o0HLTU?gvD;p-k7TXz2_G&s?MBfEjZJLXzHn!rh>Owh10s8e~i-af!Tcl~?W{YJG zB)r*TYo8Y{n?EdmJ;5lJUlhk2@}3>RF$Wo9eTsyN$Hg&^r24Y60&%h6m=`mc?A1o$ zm?HZ1;+TXe2FIjn;^vs!97uR`4Bmo7Qme?j$YvJPFC_THEL1G=xc77j7I`(pq>n|Y zcw8*<&QxFaxz||a9SkOWwNY5)m(i~mizGxbSR_r8eir$KSN!gI>_3_PO{w>|9A3AsbDfi|^9`T@Uv14y94=2BWKyTu3vfTa4UHP#2 zcGvLzwP}g!*>pjvgT(n6yd{aOyJuwAn`WEus&N1z4dmd|yG>f!lIRguV!^!l*SYE6 zb%`k#CX*H-&upeEl5Uv6MVAl15B9Y*s^esfU+@a#-;i`?%leA4oPgJ(8AkST0v>da zkmW8CBlKTc0fobGRGRC!a|CG!>f+CBlEjei+img@*zUAFAC_ygwX%mXO?pV!CLDUZ zc$!ISBB5{4v@YS9ECnx;H=P8@45FUmlWOLF*t39M?j9kFZNvyZY;(>%LKfTb5x^rL znBovB)z_qvCPp=mE_x&@Os>eThdgiISt^%1|AKO%zM!aH z`xh1EDR8(BJ||{fPTY`-%cqlW#viO1=Td#yv2@?R z{#YE4KCa1mOpY!Urke0Jcj`$uV_A`2nRJ(HMS2v?JXfSQx<|-TEn)zmh%3?n{lk~0zr#4GrOBd&Y^kZaTrF*aYL z{y+M})+qMrC%HylXGRyYmmOny+Lc`oR}83d#mFnu#rn!*_T0ZHnbD2`A&?8Vo8mC! zQnV@QW-Lq5&ZN6sOVKmY%yTKa);&U&P7x#cEJe3EN02MPk98^H&?}{--(q83iUv(< zuBGT9CqXioq8IT=^;wFl?h&$jmmVEkLsIkPFbSVr;$uy_-I<1&Dq6NiIOw8X?Q< zb;VeJuF9@At@StZ^0QT6evFR$S05vS>W-@Zj$i^gk3+6KA5Xd&%i8mqq`O>e&mW_i z=i2k}Hhk&19%M)@J%-MaE6=l0 z&$9A-R3JXo$|D;~jinIxa?jlXkod}TkUp`MhkY8y%45PJWt=D=0$4KDJOg;1bSToM zQ^70BN92ItodC{04GTECb7;ii)zvk2>rk=HEx022*tC|9Mwr&cL(D#Y!w?w1{aS(*K2dNj`+;(LQoS8c2J@}vNt8GqkM6q(N37$0L%UU)^cx0s|70KmYfIq1JdK49hp6^oeU9Iv(t>2w_iB#Z-2d$ z5Sd3bUyEj0M=?x;QC#2gv#f!6;rvQY7lw-ovi=JeDEU>*->(h__B+P`_U1kz6SHBQ zz2jDo5Jkz4W}!mow}(ULw>VLKPPjeg9wF<5n;5}3f98Ct`HSvxa-Krt!`l}yZ#J7y z8qhXTE7;F+hQv2DHQ#n4lzF7oe`>zx9wBRLzQsrIpPD6?x-@Z=b87hTBTmf*b3w9A z&xEQX=SVM76Lqm0y{w745Y4dV^O2#Q?h&#kN{nDk)G{o;5*_wg;c=~dl$_JV2On{o z*6I5M+a#^z6(mOTt3v9K8>y_xIp{w*54cCjnjA5LF*z&Pen=uCzA0SF?vZj%5C>qy z30iM#-E1?oTGo(gsRD)BOWl}d&C+TAS$ds&gsfQ-BN(&fT!wn?adOTPA3paS4Qh~a z7}~O_T%5zuXRv~p=Vr+$dGz zZ-1e_g!*JrSPk`pcHR38hxoPlctIJLYs*XA`Cae)e*A@6Sg+vCcKJ$u88>lv)C23o zcc5hIDJLgt);PNp_ypm`U%q)#G}Ldfe{eY_=Y-J4_qDp=37BxD3crS)?my={>Y!RX zS)DqAi)&lKT&Z=6-8c@sabNu%x9w`<_Ww?4f?c2<;7y;P)IP;~5Up|f_-v`&nZi}? zI1yb5=J6${;kxq!v(#f)Dp!Mcw_Jv)INPoB)i{`~ciUBd>3Mo|4BMTr0GbM}+hv2J ztKd|vUPlS^5_L3DE;WJ{U85ezVP_WTj{a7+(Ew8fXXvW+sVR=Tyb1jcNT5xU_}3eR zk$P^eMlCJ5`9J$kOB7=aWchv(4cM{Kf67ntryqOA|Hedr`mrY@)fHP4IdrpLsR!ME z3w@%qHN7}sW9#@$C*<;U0yq56)8)ve`tAS+?CBMT6CFH1#jb8v_ciaIo}S))g5C8W zloGbod2u?po35J%Tb+&!EftQ^19m!c2Sa8=^mg?ywH=)~>O(hBK#Wp%V{n&5p)&}|K)FA%Q zU*$I$+E{LcwmYUxVsuI7%xc4Iy3C}TKS~#8vWF6cG!kBdu-XuWsQ<=?!Wgf7nDoY9 zT=}q@8tjO~T13{-(UER_7{k+N&-cbboU^O}POQhg0%i2V#Ed$mzS>^Af}kRdohyhZGR zyvT|EM-s8wyn~h(iK111il#*@&0%g4+vz~STf{c0kVp0ZjSR9|)((sb{yF_`StMiI65qThj{mJr0yy=i*58RPX11iTqzJ@>-| zg_&lvZr>X78giZO55#=YoAQDiKF0v>;|40u#SO~|W(gPnqImTGPW5J=XpJBKnn7i+ zHVQxdE&3hE4+%*Oen?Zq%@3b(AmGgp+oVG)C`gZ%YfV<(Dxok`ftreqfjO~u8q-t= z23d;+mX(=`b1}$jiGpMjRiL1|BGqd)bi#fL7GP@tTK_ zmI2x9MsR0=kK@d@=IK|SM*LZz!}Finr_s`gg$o-v40{jGvk*G2%`OyMh?6$wig+S? zz8((9C{EvmW9uS2vG~DpBo^C;^vf>}Y>h>laby3p_R4+dBtp?i?6ofeSg4@BawW-6 zW2W^Dg1JU}CkB5#>BgQIe4z~;xy7*ms9^kWN#`S_30q(^(u5~?nlMq9L6&;sQYG-3 zS+c4e`jUT9pf7)>i@ceMz2~7>uEgFSf<$oj8SnBf*D!flXOkt#Go1LOVBIzxtQRp@ zy;Apfxkt##I}#%pc}GjdB#}vkj|z+H-DBj;IpRax6}C0?l~2T=1{pa=77ksUoTKl8 zT{3fy6cl|qM_)#}QF4xGT%L3E2&O5buQKQ8BAbS=ryhM3%}8erOg(zuy=wXIYS$MKkC@Y7PufZ~=>r-jQO^vXeoz%mkLR@t1@v zPenQ*8UpRb4OO4^g;2gu(541EA^|HYqMvxE`c2+A2m?As1B(Go#rpba+eI4z7Vl8? zds01{E3d`}G6?x@2BE#0zK0%nsG5mtI#ivI%kaLWsb$xLa&LXkfsnNIUd!q@Le;Ar zFIi+PbpOel@`5)$&w)rs7O6NFZ#cppf0OFVKFy$tjCj>EOKTQw!?0?pQfI0iw{g9>qDtAB9LL(jJVWG{lYGbwZw_k3uiG9v!YK5hL zF*O*ZPL-v}4DUjJV9LD%UUOr_Oo7b%?5aI)Fp8)H0 z8gEn~#T^+Wlr4>2WvXv7{%vWpmX1h6GT}WPIA7hUS={FC9G-X0-NM}Ex6~}CLik)V$+^kpj zA@RO7TPlbAq<1^0gmX>U6Abwi)n?~Jfb9JfRQ1G70o)25kS}P59TZO-yZ^|M$>90- z-TUmI)jWfybvzhWnGWh7wKkL+uUCQ7xdXjS!iys_rEaCx!GMrWc1y!)63udmZpzITPXEl- zYxDDvT6S=!-lmrqpeCD*V!H!XzJC|~sfW9!gJVqz0TAO5Oi!d_`oZo0N-r0^gz!E1 zjQ``wM5mgFvGA{*wKUcAHDA@FYk*Y{>96=}0IIGufL+H#%P?&bouZ>{{u@m7p)JU2 zi97#x2x>cM&~}OMl#;EH?I)%5zBdfY>wtp>#$l<&_;%O&5=FcUTB218+dX<(hqPV1 z+gJeY;VM=I_up(c_KDL*%T$y~0*32v?izVVnjXn7ICZZ9pNL9bJt-7-k)q$?sv9hg zxO}67yrBYt%Uk6(>84-A=cM80ltBAprex*pB4d;->h%U;&NjC?J* znxSFDq@p7P5Uf?ap1iI!Gt`YNOP8;zZkJ)FN0^~onZFr2^l4(?`S20D2iQ(idceuEWH7C1R& zk_}`2hDw6A10_F?_0_OrHV`h{n|iTmXn0d^=5`GECp24z+Ls0tkdVuWMW?A{ z*WB2suqfj(2SQYb4$U8Cb(Bj}I0KZA;$m$VJn$&Au{{=Pnnsxt)3w#t~i*SON(&0D= z{bXL`ME@fl_4s1mK|hZMS(frB6#X-QiXwDk2wj@P+(P&B4g|b~Zb!?lk+dOO_^p>(F2^*kv>N9VmdD zAl?GFGcR(Y|B(dn*?9-Oc9AIhTz`tD1u)HFZUOw>I0SH~X_5woL%5x;goK8NkOc9F z>mX#>Y88T*E>?1Q!h42<96rous80^5IF}r*mN-d+TNNniI;ma&~*qv-_bf#S*OWQb?9Z6k<8?o#OZhcs8{&*eo^bUsKn9h;3` z%sb@U#zWbU!iA+%HhL%e9fp|k(npd@SLmZ+nvdi~%`#Q-Qgx*ZeN?@FYRKLP&6U$H z`uV(reijWDV`cgR`t_Wxv>qiY>l(tXM}NwJfVq*$?uRm2U*OiqGS`u8T#sDGXR~T! z&17A6l}Q%6?xIbH$Yec_8VoYWl?9bIlXa^XJUMh}TH-C4tX2c#0sxZ5!o&fT$-2p1 zN6s#h%zJh-`AKH7N>5EP2}TyE%=#3$p7JEAbjW2lDsVF`^CT%5aXgdt4xqy`S=pyy zGg(>CTQU;mP!1WB-5lOIe)1{TDC9alqGg55b z0*w({zmmt+-Sia^8}kq*HDo{JI5qkTCsLU~(wCxHmKL%Gd{46mX6$^ufujX-O9d>S zsZupTz2R_q(-?3`LjFeFSd|`!vtGuqlTz9W=%N1)IN_JhQ8V-(oj}jD42ppM`z**5 zq6#Wy2Je5v(nJpCJ(ufr=@;DjFgCRk>3Ef>zf9k|PlNX<2@Ee5B3fTW= z_Xt@LL@|PY1o5xky2@i^Lz5J9A2 zc?5A{7e3Kf89~I&@nRjYM-T5uU0RL?Mh{O1lJ=TqJWbc=Oa_f6UM@hMHI6`3 znn|i3N{e!W$mugV!8A&7wp7Ej0?72E6zXCHCmhN+(RgxpQmD7b&oGT|7)q9v$slpuX7+oiy_75U(M<`;`3&b9gEOQi`cl>K4r=XgE&>Hr1T5kvm^ND zKX5?P(LpNC#Xk;@`L|Mi*;#?s8^JN(WH8yQ=^PV%0u^(F=l=%PbswyiLlS}*9FnGo zn?pYBK){nw=HqFC7OBp2H|Lt2UbB$y`ouGnQm!JKA0&1q@`yG)>g zMcq(wE_PWhagtjeRiL1|Jk@J9bb@i7!JxBO%fUFAL97Jmfn3Dtf(7!^1#o+(HM!%l?Pd;J&!4IOczV^DeCaW9>m|K(VekeTr zO7|8=1`x@_@(3U{ShcZ+hqvrD$ztCX(AGwThtH=5gRH^f!^6A1;2A-OTEfHD4em|= zlEuQr0Tdp-++9b`E|JW8b~E`&hKHr2AejW8@UZl_W;ZHuGa)lPOhyC`4?h5OczBq7 z8ZkV~{XYf{h3J(y0WL2hQuiE*n~5^7Il^5-ihA)g=$eMo$#9Cl>NeGeBY3Vf1sCxY zyA`6xeBa~~jA1IUs<Ry8MY(xL)9%Ha$?@B%)!WlJR6_?-D!3Zzfl|GT1MW}sc>E|{%b)2i&X+pX z-m&V2WAPeswPv%0?$*#_vv8}<&Ev~ja-kP-hs|v5EQ09Ckx>kN3O`SX-1%;+j&JKb z&2n+3R6a$&0-6^2@0Z?>lJW(yxldmh{&EeS^ z2+3ULveJrpMJ1f+ofYxG<>~?=XKX;yKi23-cv3jb3~KzZC_p|9LPEhM}tw zVwT&<*orY13ht1T!Y!{;G2~??UWripEJy@u)+!n+Z76jSlu$+S zQk;cDK)O3OUraa}lfnv+Q608$aSToSMpnXPg*ZnQ&9}pDrCB^XN6fehhq{~Xu&B3W z99HfWPuJQth&%OFtkl}%F#r(+l&hqqL2B255N*g7KN=2>6V-}@CfymqNP~Nx&;e)T zb1bA@Ys>-;!Pn;#qqn;=X0?l`3qXg_ygI%VGBH<7ltY3*u{}>5dM@6CC#^fBvqgFn zyN>@uewNppBzo&`-46u)C0%HhHfVMM`_8`>>&-H5R$9-mHwK0ESxgZ+I2SJq8>f3%)8f@!DM1T>DQk^N4IUV00z@sbD>gO7!Qa z>4%5#ryH-KR&?(N^}*YnV{Oi{`sY~PbKPn{zfyIxC! zx(xNJ0kV)EOjcN0J>wO)rl|=Yr_JQosk?W$vb&An90Ex`4NFl%~_~H;zmjaDnp^o1}e=fTOf3BcEPtl)G)1Q;u@TX3H z)^5k2P4wr(^ylOB=cn@8U#5$<>0)m-U+i)lwlQ*oOgkrUkma>BpgbKXj_9~? zL}>vLr44lB^}2X6PFr8DLCA?!!F{}hG`XzDSz0gQ^)UMo=ee0?J&|};^}>r+0Wsyd~Y2_yt=ltTW|imsXKpycVa7>s(~9xUITfls^F(cuns( z^d0W`faZk6wV@kmzyg?kLz`WpD2tOdFJXFR@oc@nfz<~i;94rRok_f}9q{W>(0>sGYeBT}^90n=6t)u{T;4FK4ga#48RSKYkaGPWGxVro|f@ z%fl;3N-rWfgmgk$UyQtk<=~aAC{BrtLjR`Qpn*>XOdAK-MzmS30=73nDVV{o;}jl^ zZ-h4mT}7oX_FY7$ghV6tp~(2$Tx7i7LB?nbKWYSADhasiMF)-_J9O+$TALW%R%x`f zlMu^-n}V4PA_5edzbnj-=feE19GFYiiJpZ<39iv+=-5R+>qNhca&9fLD*u}?P(2qJ zYdOd$87MkJWE6y3Y0^`%Pd^z4GSRJfV0X}{k*bEkwQ(ilaH2SJKZ+?|n~R#S8Y4By z$DmQO&w~POHxtI^Csu`2^K7|Un-sHM+}c{BT<=zB*Lad_fQbrSB`ItKzWz`D|Hk*9 Ah5!Hn literal 0 HcmV?d00001 diff --git a/docs/_source/_build/html/.doctrees/api/substrate.doctree b/docs/_source/_build/html/.doctrees/api/substrate.doctree new file mode 100644 index 0000000000000000000000000000000000000000..c06778f908a0445c9dbe66095e15d8d1ce59522a GIT binary patch literal 134059 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 ec!PS(_}>QMfd;>wBk74_6`^Yj>B<-QA@`k literal 0 HcmV?d00001 diff --git a/docs/_source/_build/html/.doctrees/environment.pickle b/docs/_source/_build/html/.doctrees/environment.pickle new file mode 100644 index 0000000000000000000000000000000000000000..75f2555f023b08182f9ccfa1c65ba5b21fb008d6 GIT binary patch literal 3409014 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%0D*U|o+eP&*ZIZkqFv0JrT-4RMBEPEz z0s6kruJCuw$IaP(DcfRA;6lqVroAtx@&K=>Wq=+qA^Uil{#coGD9XNC5TKBK;qM2{ zzE~5uBwccUxJSB35TMXDyc!KAJ=%d#=IWADG>Sm|zV|@>Aal%)P^(fw5}?rQy1%N4 zGGSVx`d$(+3ZRZCemOloe>LTyhl}{9y;r?~+##B=Z)dhXqYopXn-g9zW+r1~$v{SDgWOaCw4A8R^##scVr{Y_%i z#&hcY!~!buyOVIR)_Q`L=B$*R_6~v-8K?NX@)N#}1#TV0OgNYo9m=hg*6++{ckyslsIP1x~ zElUty39zmcpNzvzwn$Erb>2h5@v1)Hb^JYCW8mfq%qUmX#8 z6m#C>j{bd9Z(}t;sBLh6enzw1BEzh>0>g^|LG{WZPS&e?EhT2X5-7DEKuF73Z~Xbe z(&EK{K$(nR43teCC1n!S0HF+{He*1$OWer>F)3y+Q6CoLV}5kvE2^QXIH=SWo>lkM zFvtyp=?ATSgpC*g)POVKWYm{E&CEH8;MIVj;$g%Y59j0=chk`%2=ssnSw(x!#j+{N zDks(kRPPQ5U@-t_z{wd!b6ILmne!7;PSt_{g%Y8S0<;TXOiWRUK(CFdHj96*4u}bQ zz|d;PnX66H-qjU#bZ741oYXX%BiYtIQBfCI8fG-uF&z(B4_9lW*$7KOuhxZVb+HWM)MCh+U-M0s zT8Cv$h10~yYVOWVM}8S;3aIK%^pCwztO*n~%jez#wU;yxkz|sUc9vY%JnZ?=bf|PS z<}%jJe6xFaSgqsAovI>nH1nA7Ue4r6F>{K>LONlQI@0@x{iqNIwJFFK+5(hWkekkV zsyYL`C}2&-^51FWxiWQaHYNr!C8EMHR{ zn;L=$P#A=nokIo*S)`KNXJ2`=*m9qyCJ8aQTdz?**+SyXFeZ~Y!ll_6rA}#W_DWqG z-!>&j4V%``>{D`(MaebUS%<&}&dypF$fin=)6&i+Wue=w5}8`x2m?x$p636jXS7*b z3+T<>oi1!{dfY?}6pFLyE*8EQV*1l(ujvYg&$Vr%X6klcrvXaB0{7FW;>N-P_vcT= zjfDm7V9ZN%7d_>WQh7ed!r;=PD~h4{OiPhRgMk=endi{dQtryb28#cwVF+ztzT-3} zTcj!^iUUq}r11SBVq$-0%`4KpYrO5y3qhG?S!gwT@O-Fjr!XfcI_eMuftorZyz0Fk zQ$V1eLojEryPQN4G+IHSO{sKI1sxC`98KLBqp3dqX0E7qu!=VL)RPc@)O$@k1BTBh zFT^4knF zlNr*|havyAlOv=4XS5ZOF7bHoj@F8`;&d

=1NgE-4t{25(BcOiz^6wEc|f5MT_& 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

aj5LM<1CV0? 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

?UJ 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 z

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�+J#2-fzP{NZ0ppq1yCMGAbeAtv6p9XUNAt;DF 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

$MZCIJo9Ky{L^A>Nxc+r|aA@}S`K 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

eWO^j*2?K;#8no=rA3jXoW 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≥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 z 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

Hb13+S!W`HuRV6aODE3oT<)FA`{( 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

%H3<3E2AP%k3+7_>1Ez}yPWt9FFCr9 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

&TiHPwJZNUVf*Vl1 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

sbN=SP6Y>;k0Ym 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%0DK^Mr* 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 z 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ð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

+
+
+ +
+ +
+
+ +
+ +
+
+ +
+
+
+ + + + + Back to top + +
+
+ +
+ +
+
+

Source code for aborist.cli

+"""Aborist CLI: ingest / search / verify / stats."""
+
+from __future__ import annotations
+
+import argparse
+import json
+import os
+import sys
+from pathlib import Path
+
+from aborist import __version__
+from aborist.ingest import ingest_source, verify_random_sample
+from aborist.progress import Progress
+from aborist.search import FTS5Backend
+from aborist.sources import WikipediaCurDump
+from aborist.store import (
+    DEFAULT_DB_PATH,
+    append_audit,
+    connect,
+    connect_query,
+    stats,
+    transaction,
+)
+
+
+def _cmd_ingest(args: argparse.Namespace) -> int:
+    """Ingest a corpus (Wikipedia, HTML, git, etc.) into a shard."""
+    if args.source in ("wikipedia_cur", "wikipedia_old"):
+        if not args.path:
+            print(f"--path is required for {args.source}", file=sys.stderr)
+            return 2
+        from aborist.sources import WikipediaSqlDump
+
+        table = "cur" if args.source == "wikipedia_cur" else "old"
+        shard = None
+        if args.shard:
+            rank_str, total_str = args.shard.split("/", 1)
+            shard = (int(rank_str), int(total_str))
+        src = WikipediaSqlDump(path=args.path, table=table, shard=shard)
+    elif args.source == "html":  # noqa: SIM114 — keep branch shape
+        try:
+            from aborist.sources import HtmlPageSource
+        except ImportError:
+            print(
+                "html source requires extras: pip install 'aborist[html]'",
+                file=sys.stderr,
+            )
+            return 2
+        urls: list[str] = list(args.url or [])
+        if args.urls_from:
+            urls.extend(
+                line.strip()
+                for line in Path(args.urls_from).read_text(encoding="utf-8").splitlines()
+                if line.strip() and not line.lstrip().startswith("#")
+            )
+        if not urls:
+            print("html source needs --url or --urls-from", file=sys.stderr)
+            return 2
+        src = HtmlPageSource(urls, respect_robots=not args.no_robots)
+    elif args.source in ("grok_export", "grok_media"):
+        if not args.path:
+            print(f"--path is required for {args.source}", file=sys.stderr)
+            return 2
+        from aborist.sources import GrokExportSource, GrokMediaPostsSource
+
+        cls = GrokExportSource if args.source == "grok_export" else GrokMediaPostsSource
+        src = cls(path=args.path)
+    elif args.source in ("wikipedia_xml", "wikipedia_xml_history", "wikipedia_abstract"):
+        if not args.path:
+            print(f"--path is required for {args.source}", file=sys.stderr)
+            return 2
+        from aborist.sources import WikipediaAbstractDump, WikipediaXmlDump
+
+        if args.source == "wikipedia_abstract":
+            src = WikipediaAbstractDump(path=args.path)
+        else:
+            shard = None
+            if args.shard:
+                rank_str, total_str = args.shard.split("/", 1)
+                shard = (int(rank_str), int(total_str))
+            src = WikipediaXmlDump(
+                path=args.path,
+                shard=shard,
+                multi_revision=(args.source == "wikipedia_xml_history"),
+            )
+    elif args.source in ("git_repo", "hg_repo"):
+        if not args.path:
+            print(f"--path is required for {args.source}", file=sys.stderr)
+            return 2
+        from aborist.sources import GitRepoSource, MercurialRepoSource
+
+        cls = GitRepoSource if args.source == "git_repo" else MercurialRepoSource
+        src = cls(repo_path=args.path)
+    elif args.source == "providence":
+        # Self-reference: promote STRICT live providence_cache records
+        # past the kindergarten window into the document corpus.
+        # See docs/self-reference-design.md.
+        from aborist.sources.providence import (
+            DEFAULT_KINDERGARTEN_SECONDS,
+            ProvidenceSource,
+        )
+        from aborist.store import connect
+
+        # The source reads from the SAME shard it's writing into —
+        # promote each shard's own STRICT records to its own
+        # documents table. Cross-shard promotion runs as a separate
+        # invocation per shard.
+        target_db_for_read = args.db
+        if args.shards_dir and args.shard:
+            rank_str, total_str = args.shard.split("/", 1)
+            rank = int(rank_str)
+            total = int(total_str)
+            digits = max(3, len(str(total - 1)))
+            target_db_for_read = Path(args.shards_dir) / f"{rank:0{digits}d}.db"
+        if not target_db_for_read:
+            print("--db or --shards-dir + --shard required for providence source", file=sys.stderr)
+            return 2
+        kg_seconds = int(getattr(args, "kindergarten_seconds", None) or DEFAULT_KINDERGARTEN_SECONDS)
+        # Open a separate connection for reading; ingest opens its own
+        # write connection downstream.
+        read_conn = connect(target_db_for_read)
+        src = ProvidenceSource(read_conn, kindergarten_seconds=kg_seconds)
+    else:
+        print(f"unknown source: {args.source}", file=sys.stderr)
+        return 2
+
+    # Resolve target DB: if --shards-dir is set with --shard, write to a
+    # per-shard file. Each shard owns its own SQLite file, so N parallel
+    # ingests have ZERO writer-lock contention.
+    target_db = args.db
+    if args.shards_dir:
+        if not args.shard:
+            print(
+                "--shards-dir requires --shard rank/total",
+                file=sys.stderr,
+            )
+            return 2
+        rank_str, total_str = args.shard.split("/", 1)
+        rank = int(rank_str)
+        total = int(total_str)
+        shards_dir = Path(args.shards_dir)
+        shards_dir.mkdir(parents=True, exist_ok=True)
+        digits = max(3, len(str(total - 1)))
+        target_db = shards_dir / f"{rank:0{digits}d}.db"
+
+    progress: Progress | None = None
+    if not args.quiet:
+        prefix = ""
+        if args.shard:
+            prefix = f"[shard {args.shard}] "
+        progress = Progress(
+            interval=args.progress_interval,
+            total_estimate=args.total_estimate,
+            prefix=prefix,
+        )
+
+    conn = connect(target_db)
+    try:
+        result = ingest_source(
+            conn,
+            src,
+            chunker_name=args.chunker,
+            limit=args.limit,
+            batch_size=args.batch_size,
+            resume=args.resume,
+            progress=progress,
+        )
+    finally:
+        conn.close()
+    print(json.dumps(result.__dict__, indent=2, ensure_ascii=False))
+    return 0
+
+
+def _cmd_search(args: argparse.Namespace) -> int:
+    """Search the corpus with FTS5."""
+    conn = (
+        connect_query(args.db, shards_dir=args.global_shards_dir)
+        if args.global_shards_dir
+        else connect(args.db)
+    )
+    try:
+        backend = FTS5Backend(conn)
+        hits = backend.search(args.query, limit=args.limit)
+    finally:
+        conn.close()
+    if args.json:
+        print(
+            json.dumps(
+                [
+                    {
+                        "document_root": h.document_root,
+                        "document_uri": h.document_uri,
+                        "chunk_idx": h.chunk_idx,
+                        "snippet": h.snippet,
+                        "score": h.score,
+                        "audit_mode": h.audit_mode.value,
+                        "title": h.title,
+                    }
+                    for h in hits
+                ],
+                indent=2, ensure_ascii=False
+            )
+        )
+    else:
+        for h in hits:
+            print(f"[{h.audit_mode.value}] {h.score:7.3f}  {h.title or h.document_uri}")
+            print(f"    chunk {h.chunk_idx}  root={h.document_root[:16]}…")
+            print(f"    {h.snippet}")
+            print()
+    return 0
+
+
+def _cmd_verify(args: argparse.Namespace) -> int:
+    """Verify Q&A cache records and audit chains."""
+    conn = (
+        connect_query(args.db, shards_dir=args.global_shards_dir)
+        if args.global_shards_dir
+        else connect(args.db)
+    )
+    try:
+        result = verify_random_sample(conn, n=args.n)
+    finally:
+        conn.close()
+    print(json.dumps(result, indent=2, ensure_ascii=False))
+    return 0 if result["failed"] == 0 else 1
+
+
+def _cmd_distill(args: argparse.Namespace) -> int:
+    """Distill surface documents into compressed cores."""
+    from aborist.distill import get_distiller
+    from aborist.distill.runner import distill_existing
+    from aborist.store import discover_shards
+
+    try:
+        distiller = get_distiller(args.process)
+    except ValueError as e:
+        print(str(e), file=sys.stderr)
+        return 2
+
+    # Sharded mode: iterate over each shard's DB and distill in place.
+    # Cores stay in their source shard so the per-shard audit/derivation
+    # chains remain self-contained.
+    if args.global_shards_dir:
+        shard_paths = discover_shards(args.global_shards_dir)
+        if not shard_paths:
+            print(f"no shards in {args.global_shards_dir}", file=sys.stderr)
+            return 2
+
+        per_shard: list[dict] = []
+        totals = {
+            "scanned": 0,
+            "distilled": 0,
+            "skipped_existing": 0,
+            "skipped_cold": 0,
+            "skipped_empty": 0,
+        }
+        for sp in shard_paths:
+            conn = connect(sp)
+            try:
+                r = distill_existing(
+                    conn,
+                    distiller,
+                    kind=args.kind,
+                    source_type=args.source_type,
+                    limit=args.limit,
+                    chunker_name=args.chunker,
+                    batch_size=args.batch_size,
+                )
+            finally:
+                conn.close()
+            per_shard.append({"shard": sp.name, **r})
+            for k in totals:
+                totals[k] += r[k]
+        print(json.dumps({**totals, "shards": per_shard}, indent=2, ensure_ascii=False))
+        return 0
+
+    conn = connect(args.db)
+    try:
+        result = distill_existing(
+            conn,
+            distiller,
+            kind=args.kind,
+            source_type=args.source_type,
+            limit=args.limit,
+            chunker_name=args.chunker,
+            batch_size=args.batch_size,
+        )
+    finally:
+        conn.close()
+    print(json.dumps(result, indent=2, ensure_ascii=False))
+    return 0
+
+
+def _cmd_ask(args: argparse.Namespace) -> int:
+    """Ask a question against one document and get a grounded answer."""
+    import os
+
+    from aborist.qa import ask
+    from aborist.qa.client import OpenAICompatibleClient, StubClient
+
+    base_url = args.endpoint or os.environ.get(
+        "ABORIST_LLM_ENDPOINT", "https://hermes.ai.unturf.com/v1"
+    )
+    model = args.model or os.environ.get(
+        "ABORIST_LLM_MODEL",
+        "adamo1139/Hermes-3-Llama-3.1-8B-FP8-Dynamic",
+    )
+    revision = os.environ.get("ABORIST_LLM_REVISION", "")
+    quantization = os.environ.get("ABORIST_LLM_QUANTIZATION", "fp8-dynamic")
+    api_key = os.environ.get("ABORIST_LLM_API_KEY")
+
+    client: object
+    if args.dry_run:
+        client = StubClient(
+            answer=f"[STUB] would have answered '{args.question}' against root {args.document_root[:16]}…"
+        )
+    else:
+        client = OpenAICompatibleClient(base_url=base_url, api_key=api_key)
+
+    conn = (
+        connect_query(args.db, shards_dir=args.global_shards_dir)
+        if args.global_shards_dir
+        else connect(args.db)
+    )
+    # Per-call policy override for --answer-mode. Other knobs flow from
+    # DEFAULT_POLICY.
+    from aborist.qa.runner import DEFAULT_POLICY as _DEFAULT_ASK_POLICY
+    call_policy = dict(_DEFAULT_ASK_POLICY)
+    if getattr(args, "answer_mode", None):
+        call_policy["answer_mode"] = args.answer_mode
+    try:
+        result = ask(
+            conn,
+            document_root=args.document_root,
+            question=args.question,
+            client=client,
+            model_id=model,
+            revision=revision,
+            quantization=quantization,
+            policy=call_policy,
+        )
+    finally:
+        conn.close()
+    print(json.dumps(result, indent=2, ensure_ascii=False))
+    return 0 if result.get("status") in ("cache_hit", "cache_miss_then_written") else 1
+
+
+def _cmd_query(args: argparse.Namespace) -> int:
+    """Multi-source RAG: question -> top-K corpus docs -> Hermes -> cache."""
+    import os
+
+    from aborist.qa.client import OpenAICompatibleClient, StubClient
+    from aborist.qa.query import query
+
+    base_url = args.endpoint or os.environ.get(
+        "ABORIST_LLM_ENDPOINT", "https://hermes.ai.unturf.com/v1"
+    )
+    model = args.model or os.environ.get(
+        "ABORIST_LLM_MODEL",
+        "adamo1139/Hermes-3-Llama-3.1-8B-FP8-Dynamic",
+    )
+    revision = os.environ.get("ABORIST_LLM_REVISION", "")
+    quantization = os.environ.get("ABORIST_LLM_QUANTIZATION", "fp8-dynamic")
+    api_key = os.environ.get("ABORIST_LLM_API_KEY")
+
+    client: object
+    if args.dry_run:
+        client = StubClient(
+            answer="[STUB] dry-run: would have asked Hermes-3 with the assembled context."
+        )
+    else:
+        client = OpenAICompatibleClient(base_url=base_url, api_key=api_key)
+
+    qa_db = args.qa_db
+    if qa_db is None:
+        if args.global_shards_dir:
+            qa_db = Path(args.global_shards_dir) / "qa.db"
+        else:
+            qa_db = Path.home() / ".aborist" / "qa.db"
+    qa_db = Path(qa_db)
+
+    shards_dir = (
+        Path(args.global_shards_dir) if args.global_shards_dir else None
+    )
+    single_db = None if shards_dir else args.db
+
+    # Apply per-call policy overrides (question_dedup, repair, answer_mode)
+    # on top of the default. fidelity is a function-level kwarg, not in
+    # the policy.
+    from aborist.qa.query import DEFAULT_QUERY_POLICY
+    call_policy = dict(DEFAULT_QUERY_POLICY)
+    if getattr(args, "question_dedup", None):
+        call_policy["question_dedup"] = args.question_dedup
+    if getattr(args, "answer_mode", None):
+        call_policy["answer_mode"] = args.answer_mode
+    if getattr(args, "repair", False):
+        # Mechanical-only repair when --repair is set; --repair-reprompts
+        # adds the optional re-prompt tier on top. Both default off so
+        # `make query` stays single-shot unless a knob is flipped.
+        call_policy["repair_enabled"] = True
+        call_policy["repair_max_reprompts"] = max(
+            0, int(getattr(args, "repair_reprompts", 0))
+        )
+    # Ticket #000008 Phase 4 — quantifier-guard CLI overrides.
+    # Six-level disable hierarchy at Levels 2 (per-call CLI flag)
+    # via these flags; Level 3 policy fields are reachable via the
+    # underlying policy dict.
+    if getattr(args, "no_quantifier_guard", False):
+        call_policy["quantifier_guard_enabled"] = False
+    if getattr(args, "allow_broad", False):
+        # Keeps the classifier on (telemetry stays useful) but
+        # zeroes out the apply_caps gate so broad shapes don't
+        # get clipped during emergent search.
+        call_policy["quantifier_guard_apply_caps"] = False
+    if getattr(args, "reject_broad", False):
+        # Phase 4 reject-broad: the actual rejection happens inside
+        # query() via the policy field; this CLI flag just sets the
+        # field. See aborist/qa/query.py for the early-return path.
+        call_policy["quantifier_reject_broad"] = True
+    if getattr(args, "apply_quantifier_caps", False):
+        # Operator opts in to flipping the dry-run gate per-call.
+        # Bench-first per §10.11.3 — this flag is the path from
+        # dry-run to live-cap.
+        call_policy["quantifier_guard_apply_caps"] = True
+    # Ticket #000010 — meta-cognition CLI overrides.
+    if getattr(args, "no_preflight", False):
+        call_policy["metacognition_enabled"] = False
+    if getattr(args, "block_on_contradiction", False):
+        # Strict mode: hard-block on lexical contradictions instead
+        # of label-only.
+        call_policy["metacognition_block_on_contradiction"] = True
+    if getattr(args, "soft_preflight", False):
+        # Ticket #000011 — opt-in to model-assisted soft preflight
+        # sidecar. Adds one short LLM round-trip; NEVER gates
+        # admissibility (D1 preserved).
+        call_policy["soft_preflight_enabled"] = True
+
+    result = query(
+        question=args.question,
+        qa_db=qa_db,
+        chat_client=client,
+        model_id=model,
+        revision=revision,
+        quantization=quantization,
+        shards_dir=shards_dir,
+        single_db=single_db,
+        top_k=args.top_k,
+        over_fetch=args.over_fetch,
+        max_context_chars=args.max_context_chars,
+        policy=call_policy,
+        fidelity=getattr(args, "fidelity", None),
+        burn_existing=bool(getattr(args, "burn", False)),
+        retrieval_keywords=getattr(args, "retrieval_keywords", None),
+    )
+
+    # Emit unfirehose-compatible session journal. One JSONL file per
+    # `make query` invocation, written to ~/.aborist/unfirehose/{slug}/
+    # {session_uuid}.jsonl. Unfirehose's native-harness watcher picks
+    # this up automatically (no registration). Failures here must NEVER
+    # break the query path — wrap in a broad except & swallow.
+    try:
+        _emit_query_journal(args.question, result, model)
+    except Exception:  # pragma: no cover — best-effort journaling
+        pass
+
+    if args.json:
+        print(json.dumps(result, indent=2, ensure_ascii=False))
+    else:
+        print(_render_query_human(result, args.question))
+    return (
+        0
+        if result.get("status") in ("cache_hit", "cache_miss_then_written")
+        else 1
+    )
+
+
+def _emit_query_journal(question: str, result: dict, model: str) -> None:
+    """Write one unfirehose/1.0 session for this query invocation."""
+    from aborist.journal import SessionWriter
+    timings = result.get("timings") or {}
+    answer = result.get("answer_text") or ""
+    aborist_meta = {
+        "audit_mode": result.get("audit_mode"),
+        "verifier_method": result.get("verifier_method"),
+        "n_quotes": result.get("n_quotes"),
+        "n_verified": result.get("n_verified"),
+        "cache_key": result.get("cache_key"),
+        "cache_status": result.get("status"),
+        "lookup_path": result.get("lookup_path"),
+        "violations": [
+            {"kind": v.get("kind"), "rationale": (v.get("rationale") or "")[:160]}
+            for v in (result.get("violations") or [])
+        ],
+        "sources": [
+            {"title": s.get("title"), "uri": s.get("document_uri"), "used": s.get("used"), "role": s.get("source_role")}
+            for s in (result.get("sources") or [])
+        ],
+        "timings_ms": timings,
+        "answer_mode": (result.get("policy") or {}).get("answer_mode"),
+    }
+    with SessionWriter(first_prompt=question) as s:
+        s.user_message(question)
+        s.assistant_message(
+            answer,
+            model=model,
+            provider="hermes",
+            stop_reason="end_turn",
+            duration_ms=int(timings.get("total_ms") or 0) or None,
+            aborist_meta=aborist_meta,
+        )
+
+
+# Soft-demote violation kinds that demote STRICT to HYBRID without
+# rejecting the pointer outright. WARRANT_MISSING / TITLE_MISMATCH /
+# DEFLECTION_DETECTED handled separately as hard demotes (their
+# presence determines POINTER-LINKED vs ANCHOR-WARRANTED).
+_SOFT_DEMOTE_VIOLATION_KINDS = frozenset({
+    "LAZY_ANCHOR_DEMOTED",
+    "POINTER_OVERFLOW_TRIMMED",
+    "TOO_MANY_CLAIMS",
+    "BARE_NAME_CLAIM",
+    # FORMAT_COLLAPSED — model abandoned the claim_lattice_pointer
+    # protocol (multi-line prose, zero [E\d+] tags). Soft-demotes
+    # STRICT → HYBRID; pairs with the bottom UNGROUNDED rung when the
+    # parser found nothing groundable, but at least surfaces the
+    # collapse cause to the operator at audit-line glance.
+    "FORMAT_COLLAPSED",
+    # Ticket #000008 Phase 4 — broad-quantifier soft-demotes (§10.3).
+    # Per §10.3 these stay as soft demotes (cap at ANCHOR-WARRANTED)
+    # rather than minting a new audit_mode token. The audit-line tail
+    # (rendered by _render_warrant_tail) names which one fired so an
+    # operator can tell at a glance.
+    "BROAD_QUANTIFIER_RUNAWAY",      # raw_line_count >> pointer_count
+    "BROAD_QUANTIFIER_CAP_APPLIED",  # preflight cap fired below default
+    "BROAD_QUANTIFIER_SCOPE_UNBOUND", # unbounded universal reached the LLM
+    # BROAD_QUANTIFIER_REJECTED is a HARD demote (UNGROUNDED via
+    # early-return) — listed here for completeness but doesn't
+    # belong in the soft-demote set.
+})
+
+
+def _ladder_rung_for_lattice(audit_mode: str, violations: list[dict] | None) -> str:
+    """Map (audit_mode, violations) → four-rung ladder for claim-lattice
+    methods. Renderer-only transformation; schema column unchanged.
+
+    The ladder names a strictly stronger property at each rung:
+
+        POINTER-LINKED       pointer/source/chunk verified;
+                             warrant either didn't apply or failed
+        ANCHOR-WARRANTED     pointer-linked AND cited evidence contains
+                             required anchors (warrant ran & passed);
+                             other soft-demote violations may be present
+        EVIDENCE-WARRANTED   anchor-warranted AND no soft demotes
+        UNGROUNDED           n_verified == 0 (existing audit_mode)
+
+    HYBRID adds `-PARTIAL` suffix to whichever rung applies.
+
+    The rung logic uses the violations list as the signal — no new
+    verifier output field needed. Three discriminators:
+      - WARRANT_MISSING in violations → warrant ran and failed at
+        least one claim → POINTER-LINKED (pointer ok but warrant
+        didn't anchor the claim)
+      - any soft-demote kind in violations → ANCHOR-WARRANTED (the
+        rung is reached but other demotes pulled it back from STRICT)
+      - no warrant miss AND no soft demotes → EVIDENCE-WARRANTED
+    """
+    if audit_mode == "UNGROUNDED":
+        return "UNGROUNDED"
+    kinds = {v.get("kind") for v in (violations or [])}
+    # Hard demotes: WARRANT_MISSING, TITLE_MISMATCH, DEFLECTION_DETECTED
+    # all indicate the citation is structurally misaligned with the
+    # claim or the answer is structurally off-topic — pointer resolved
+    # but the cited evidence (span, source, or whole answer) doesn't
+    # actually support the user's question. All three drop to
+    # POINTER-LINKED. (DEFLECTION_DETECTED was previously a soft demote
+    # to ANCHOR-WARRANTED; the comeliness/fetish/investitures emergent
+    # case showed that "the model totally shifted topic but anchored
+    # the new topic" earned ANCHOR-WARRANTED unfairly. Off-topic
+    # belongs at the lower rung.)
+    if (
+        "WARRANT_MISSING" in kinds
+        or "TITLE_MISMATCH" in kinds
+        or "DEFLECTION_DETECTED" in kinds
+    ):
+        rung = "POINTER-LINKED"
+    elif kinds & _SOFT_DEMOTE_VIOLATION_KINDS:
+        rung = "ANCHOR-WARRANTED"
+    else:
+        rung = "EVIDENCE-WARRANTED"
+    if audit_mode == "HYBRID":
+        rung = rung + "-PARTIAL"
+    return rung
+
+
+def _render_audit_label(
+    audit_mode: str,
+    verifier_method: str,
+    violations: list[dict] | None = None,
+) -> str:
+    """Map (audit_mode, verifier_method, violations) → human-readable
+    display label.
+
+    Schema-level audit_mode names what the lexical verifier could
+    confirm; the display label names what THAT means in honesty
+    terms. STRICT in claim_lattice mode = "every pointer resolves
+    to a valid evidence object whose source_role is allowed AND
+    every cited span passes the citation-overlap coverage check."
+    That is NOT full semantic entailment. The display label spells
+    out the actual property so users don't read STRICT as "the
+    answer is correct."
+
+    Four-rung ladder for claim-lattice methods (per ticket #000005):
+
+        POINTER-LINKED       pointer verified; warrant either didn't
+                             apply or failed for some claim
+        ANCHOR-WARRANTED     pointer-linked + warrant passed where
+                             it ran; other soft demotes may apply
+        EVIDENCE-WARRANTED   anchor-warranted + no soft demotes
+        UNGROUNDED           no verified pairs
+
+    HYBRID audits get a `-PARTIAL` suffix on whichever rung applies.
+
+    Plus the verifier-method tail (`· via claim_lattice`,
+    `· via claim_lattice_pointer`) so the user can see WHICH
+    verifier path produced the verdict.
+
+    For quote / span / entity / paraphrase mode the audit_mode
+    labels carry less risk of overclaiming (they verify against
+    pinned spans, not synthesis) — keep them as-is.
+
+    `violations` defaults to None for backward compatibility with
+    callers that don't have access to the violation list. With
+    None, the ladder falls back to EVIDENCE-WARRANTED (the most
+    optimistic rung) — operators get the same surface as before
+    until callers thread violations through.
+    """
+    is_claim_lattice = verifier_method.startswith("claim_lattice")
+    if is_claim_lattice:
+        rung = _ladder_rung_for_lattice(audit_mode, violations)
+        return f"{rung} · via {verifier_method}"
+    # Quote / span / entity / paraphrase: keep audit_mode as the
+    # primary token; append method for clarity.
+    return f"{audit_mode} · via {verifier_method}"
+
+
+def _render_warrant_tail(result: dict) -> str:
+    """Append a tail to the audit-line label that names the specific
+    warrant failure mode when one fired. Surfaces the cap reason at
+    the user-facing layer without overloading audit_mode.
+
+    Two failure modes today:
+      - WARRANT_MISSING: relation/date/etc. anchor extracted from
+        claim doesn't appear in any cited span (per-span check).
+      - TITLE_MISMATCH: cited evidence's source title shares no
+        content tokens with the claim (per-source check). 2026-05-02
+        spin-glass case: claim about spin glass cited to *Quantum
+        chromodynamics*.
+
+    When both fire on different claims of the same answer, surface
+    both tails so the operator sees the full picture."""
+    violations = result.get("violations") or []
+    kinds = {v.get("kind") for v in violations}
+    parts: list[str] = []
+    if "WARRANT_MISSING" in kinds:
+        parts.append("warrant missing")
+    if "TITLE_MISMATCH" in kinds:
+        parts.append("title mismatch")
+    if "FORMAT_COLLAPSED" in kinds:
+        parts.append("format collapsed")
+    # Ticket #000008 Phase 4 — broad-quantifier tails (§10.3 / §10.7).
+    # Each names what the preflight detected so operators don't have to
+    # parse violation lists by hand. Cap value comes from
+    # `claim_cap_applied` on the result when present.
+    if "BROAD_QUANTIFIER_REJECTED" in kinds:
+        parts.append("broad rejected")
+    elif "BROAD_QUANTIFIER_CAP_APPLIED" in kinds:
+        cap = result.get("claim_cap_applied")
+        parts.append(f"broad cap {cap}" if cap else "broad cap")
+    elif "BROAD_QUANTIFIER_SCOPE_UNBOUND" in kinds:
+        parts.append("broad unbounded")
+    elif "BROAD_QUANTIFIER_RUNAWAY" in kinds:
+        parts.append("broad runaway")
+    # Ticket #000010 — meta-cognition logical-status tails. Pulled
+    # from result["question_state"]["logical_statuses"] when present.
+    # Doesn't double up with the broad-quantifier tails above (those
+    # come from the verifier violation list, not the preflight).
+    qs = result.get("question_state") or {}
+    statuses = set(qs.get("logical_statuses") or [])
+    if "false_premise_suspected" in statuses:
+        parts.append("false premise")
+    if "contradictory_question" in statuses:
+        parts.append("contradictory")
+    if "stale_risk" in statuses:
+        parts.append("stale risk")
+    if "out_of_corpus_risk" in statuses:
+        parts.append("out of corpus")
+    if "reference_frame_ambiguous" in statuses:
+        parts.append("frame ambiguous")
+    # Ticket #000011 — soft preflight sidecar hint. Renders distinctly
+    # from the hard tails above so an operator can tell at a glance
+    # that the signal is advisory. Skips SOFT_DISABLED / SOFT_PARSE_FAIL
+    # / SOFT_WELL_FORMED (no actionable signal).
+    soft = result.get("soft_preflight_hint") or {}
+    soft_label = soft.get("classifier_label") or ""
+    if soft_label and soft_label not in (
+        "SOFT_DISABLED", "SOFT_PARSE_FAIL", "SOFT_WELL_FORMED",
+    ):
+        # Strip SOFT_ prefix + lowercase for tail readability
+        # (e.g. SOFT_FALSE_PREMISE_SUSPECTED → "false premise suspected").
+        readable = soft_label.removeprefix("SOFT_").lower().replace("_", " ")
+        parts.append(f"soft: {readable}")
+    if not parts:
+        return ""
+    return " · " + " · ".join(parts)
+
+
+def _maybe_render_json_envelope_as_bullets(answer: str) -> str:
+    """If `answer` is a claim_lattice JSON envelope, render bullets.
+
+    JSON-mode runs that land UNGROUNDED have no verified claims so the
+    runtime's bullet renderer produces empty text and `answer_text`
+    falls back to the raw model output — a `{"claims":[...]}` envelope.
+    The user then sees raw JSON for failed runs and bullets for
+    successful ones, which reads as inconsistent. Detect the JSON
+    shape, parse it (lenient), and render each claim's `text` as a
+    bullet line tagged with its evidence_ids so the surface stays
+    consistent across grounded / ungrounded outcomes.
+
+    Falls back to the raw input unchanged if:
+      - input doesn't look like JSON (no leading `{`)
+      - parse fails (lenient parser exception)
+      - parse succeeds but the shape isn't `{"claims": [...]}`
+    """
+    stripped = (answer or "").lstrip()
+    if not stripped.startswith("{") and not stripped.startswith("```"):
+        return answer
+    if "claims" not in stripped:
+        return answer
+    try:
+        from aborist.qa.verify import _lenient_json_parse
+        parsed, _fixups = _lenient_json_parse(answer)
+    except Exception:
+        return answer
+    if not isinstance(parsed, dict):
+        return answer
+    raw_claims = parsed.get("claims")
+    if not isinstance(raw_claims, list) or not raw_claims:
+        return answer
+    out_lines: list[str] = []
+    for c in raw_claims:
+        if not isinstance(c, dict):
+            continue
+        text = c.get("text") or ""
+        if not isinstance(text, str) or not text.strip():
+            continue
+        eids = c.get("evidence_ids") or []
+        if isinstance(eids, list) and eids:
+            ids = ",".join(str(x) for x in eids if isinstance(x, str))
+            out_lines.append(f"- {text.strip()}  [{ids}: unverified]")
+        else:
+            out_lines.append(f"- {text.strip()}")
+    return "\n".join(out_lines) if out_lines else answer
+
+
+def _render_query_human(result: dict, question: str) -> str:
+    """Pretty-print a query result for terminal reading.
+
+    Layout:
+        question
+        AUDIT_MODE  N/M verified  via verifier_method  Xs  (cached|fresh)
+
+        answer text...
+
+        sources (K):
+          [1] Title — host/path  (shard.db)
+          [2] ...
+
+        unverified (J):
+          - "..."
+
+        cache_key: 35ab7d33…   <run with --json for full record>
+
+    Errors / no-source paths fall back to a short status line.
+    """
+    status = result.get("status")
+    if status == "broad_quantifier_rejected":
+        # Phase 4 reject-broad early-return path. The result carries
+        # an answer_text with the rejection rationale + a violations
+        # list; render both so the operator sees WHY without --json.
+        answer_text = result.get("answer_text") or ""
+        violations = result.get("violations") or []
+        kind = next(
+            (v.get("kind") for v in violations
+             if v.get("kind") == "BROAD_QUANTIFIER_REJECTED"),
+            "BROAD_QUANTIFIER_REJECTED",
+        )
+        intensity = result.get("quantifier_intensity") or "?"
+        token = result.get("quantifier_matched_token") or "?"
+        cap = result.get("claim_cap_applied")
+        cap_str = f" · cap was {cap}" if cap else ""
+        return (
+            f"{question}\n"
+            f"  UNGROUNDED · via {kind} · {intensity} (\"{token}\")"
+            f"{cap_str}  0/0  0.0s  (preflight)\n\n"
+            f"{answer_text}"
+        )
+    if status not in ("cache_hit", "cache_miss_then_written"):
+        msg = result.get("msg") or status or "unknown error"
+        return f"  {status or 'error'}: {msg}"
+
+    audit = result.get("audit_mode", "?")
+    n_quotes = result.get("n_quotes", 0) or 0
+    n_verified = result.get("n_verified", 0) or 0
+    method = result.get("verifier_method", "?")
+    timings = result.get("timings") or {}
+    total_ms = timings.get("total_ms")
+    elapsed = f"{total_ms / 1000:.1f}s" if isinstance(total_ms, (int, float)) else "?"
+    cache_status = "cached" if status == "cache_hit" else "fresh"
+    lookup_path = result.get("lookup_path")
+    # Annotate cache_hits when they came from a fallback ckey, not the
+    # primary one — useful when an agent ran with fidelity=equivalence_class
+    # and reused another agent's record.
+    if lookup_path and lookup_path.endswith("_fallback"):
+        cache_status = f"cached via {lookup_path}"
+
+    # Render-layer label honesty: schema audit_mode (STRICT/HYBRID/
+    # UNGROUNDED) describes what the lexical verifier checked, not
+    # full semantic entailment. The display label combines audit_mode
+    # with verifier_method so the user sees what was actually
+    # verified. Four-rung ladder for claim-lattice methods (#000005):
+    #   POINTER-LINKED      pointer verified; warrant didn't apply
+    #                       or failed for some claim
+    #   ANCHOR-WARRANTED    pointer-linked + warrant passed where
+    #                       it ran; other soft demotes may apply
+    #   EVIDENCE-WARRANTED  anchor-warranted + no soft demotes
+    #   UNGROUNDED          no verified pairs
+    # Schema column stays unchanged; pure display.
+    display_label = _render_audit_label(audit, method, result.get("violations"))
+    warrant_tail = _render_warrant_tail(result)
+
+    lines: list[str] = []
+    lines.append(question)
+    lines.append(
+        f"  {display_label}{warrant_tail}  {n_verified}/{n_quotes}  "
+        f"{elapsed}  ({cache_status})"
+    )
+    lines.append("")
+
+    answer = result.get("answer_text") or ""
+    # When JSON-mode runs land UNGROUNDED, rendered_text is empty and
+    # answer_text falls back to the raw model output — a JSON envelope.
+    # Parse it and render each claim as a bullet so the user gets the
+    # same shape whether the run grounded or not. Falls back to raw
+    # display if parse fails or output isn't JSON-shaped.
+    answer = _maybe_render_json_envelope_as_bullets(answer)
+    lines.append(answer)
+    lines.append("")
+
+    sources = result.get("sources") or []
+    if sources:
+        lines.append(f"sources ({len(sources)}):")
+        for i, s in enumerate(sources, start=1):
+            uri = s.get("document_uri", "")
+            title = (s.get("title") or "").strip() or _short_path(uri)
+            shard = s.get("shard")
+            shard_part = f"  ({shard})" if shard else ""
+            # Render-layer source-role display + used/unused annotation
+            # (claim_lattice modes only — quote-mode results don't carry
+            # the per-source `used` flag). Honestly surfaces "the system
+            # retrieved noise but did not rely on it" so the user can
+            # see the model ignoring distractors instead of having to
+            # infer it. Pre-2026-05-01 the source list showed every
+            # retrieved doc indistinguishably.
+            role = s.get("source_role")
+            used = s.get("used")
+            pointer_ids = s.get("used_pointer_ids") or []
+            annotations: list[str] = []
+            if role:
+                annotations.append(role)
+            if used is True:
+                if pointer_ids:
+                    annotations.append(f"used ({','.join(pointer_ids)})")
+                else:
+                    annotations.append("used")
+            elif used is False:
+                annotations.append("unused")
+            if annotations:
+                annotation_part = " — " + " — ".join(annotations)
+            else:
+                annotation_part = ""
+            lines.append(
+                f"  [{i}] {title}{annotation_part}{_strip_scheme(uri)}{shard_part}"
+            )
+        lines.append("")
+
+        # Retrieval-purity one-line summary (claim_lattice modes only).
+        # "primary at #R · used N/M sources · M-N noise unused"
+        # Surfaces noise-resistance at a glance without making the
+        # user count rows themselves.
+        purity = result.get("retrieval_purity")
+        if purity:
+            primary_rank = purity.get("primary_rank") or 0
+            used = purity.get("used_sources", 0)
+            total = purity.get("total_sources", 0)
+            noise_unused = (
+                purity.get("noise_sources_count", 0)
+                - purity.get("noise_sources_used", 0)
+            )
+            primary_part = (
+                f"primary at #{primary_rank}"
+                if primary_rank > 0 else "no primary in top-K"
+            )
+            noise_part = (
+                f" · {noise_unused} noise unused" if noise_unused else ""
+            )
+            lines.append(
+                f"  retrieval purity: {primary_part} · used "
+                f"{used}/{total} sources{noise_part}"
+            )
+            lines.append("")
+
+    partially = result.get("partially_verified_quotes") or []
+    if partially:
+        lines.append(f"partially grounded ({len(partially)}):")
+        for q in partially:
+            qtxt = q if len(q) <= 100 else q[:97] + "..."
+            lines.append(f'  - "{qtxt}"')
+        lines.append("")
+
+    unverified = result.get("unverified_quotes") or []
+    if unverified:
+        lines.append(f"unverified ({len(unverified)}):")
+        for q in unverified:
+            qtxt = q if len(q) <= 100 else q[:97] + "..."
+            lines.append(f'  - "{qtxt}"')
+        lines.append("")
+
+    # Anchor-smell sidecar (claim_lattice mode only). Soft signal —
+    # never persisted, never in cache_key. Surfaces when ≥50% of
+    # verified claim-pointer pairs share one pointer_id AND there
+    # are at least 3 verified pairs to compare; below 3 the ratio is
+    # vacuous (1/1 always = 1.00 even when nothing is wrong).
+    ratio = result.get("lazy_anchor_ratio")
+    distribution = result.get("pointer_id_distribution") or {}
+    total_pairs = sum(distribution.values()) if distribution else 0
+    if (
+        method == "claim_lattice"
+        and isinstance(ratio, (int, float))
+        and ratio >= 0.5
+        and total_pairs >= 3
+    ):
+        top_pid, top_count = max(distribution.items(), key=lambda kv: kv[1])
+        lines.append(
+            f"lazy-anchor smell: {top_count} of {total_pairs} verified "
+            f"pairs cite [{top_pid}] (ratio {ratio:.2f}); "
+            f"distinct pointers cited: {len(distribution)}"
+        )
+        lines.append("")
+
+    pc = result.get("prompt_chars") or {}
+    if pc:
+        # Compact one-liner — operator at a glance: did STRICT come
+        # from a tight prompt or a context-stuffed one?
+        lines.append(
+            f"capacity: prompt {pc.get('messages_total', 0):,} chars "
+            f"(sys {pc.get('system_prompt', 0):,} + "
+            f"reminder {pc.get('grounding_reminder', 0):,} + "
+            f"evidence {pc.get('evidence_or_context', 0):,} + "
+            f"question {pc.get('user_question', 0):,}) → "
+            f"answer {result.get('answer_chars', 0):,} chars"
+        )
+
+    # Per-phase timings — surfaces where the per-call cost lands.
+    # Hermes-bound queries should show `llm_ms` dominating; if
+    # search_ms or persist_ms creeps up that's a retrieval / WAL
+    # signal the operator wants visible. Cache-hit rows skip llm
+    # entirely so the breakdown also tells you which path you're
+    # paying for.
+    timings = result.get("timings") or {}
+    if timings:
+        parts: list[str] = []
+        order = (
+            ("cache_lookup_ms", "cache"),
+            ("search_ms", "search"),
+            ("context_ms", "context"),
+            ("llm_ms", "llm"),
+            ("persist_ms", "persist"),
+        )
+        for key, label in order:
+            v = timings.get(key)
+            if isinstance(v, (int, float)) and v > 0:
+                parts.append(f"{label} {v / 1000:.2f}s")
+        total = timings.get("total_ms")
+        if isinstance(total, (int, float)):
+            parts.append(f"**total {total / 1000:.2f}s**")
+        if parts:
+            lines.append("timings: " + " · ".join(parts))
+
+    # Reference-frame notes (Ticket #000002). When detect_frame
+    # classified the query as `reference`, surface the named work
+    # so an operator knows the substrate routed to a fictional
+    # source. Skipped for literal / no-phrase-route / ambiguous
+    # rows — the line only appears when there's something to say.
+    fd = result.get("frame_detection") or {}
+    if fd.get("kind") == "reference" and fd.get("reference_title"):
+        lines.append("")
+        lines.append(f"reference frame: {fd['reference_title']}")
+        if fd.get("reference_uri"):
+            lines.append(f"  cited as the named work in the answer")
+
+    cache_key = (result.get("cache_key") or "")[:8]
+    lines.append(f"cache_key: {cache_key}…   <run with --json for full record>")
+    return "\n".join(lines)
+
+
+def _strip_scheme(uri: str) -> str:
+    """`https://en.wikipedia.org/wiki/X` -> `en.wikipedia.org/wiki/X`."""
+    for prefix in ("https://", "http://"):
+        if uri.startswith(prefix):
+            return uri[len(prefix):]
+    return uri
+
+
+def _short_path(uri: str) -> str:
+    """Last URL segment as a fallback display name."""
+    s = _strip_scheme(uri).rstrip("/")
+    if "/" in s:
+        return s.rsplit("/", 1)[1]
+    return s
+
+
+def _cmd_inspect(args: argparse.Namespace) -> int:
+    """Sidecar diagnostic — pulls source chunks for a cache_key and
+    classifies each unverified span. Read-only; no audit events, no
+    providence_cache mutations.
+    """
+    from aborist.qa.inspect import inspect_cache_key
+
+    qa_db = args.qa_db
+    if qa_db is None:
+        qa_db = (
+            Path(args.global_shards_dir) / "qa.db"
+            if args.global_shards_dir
+            else Path.home() / ".aborist" / "qa.db"
+        )
+    shards_dir = (
+        Path(args.global_shards_dir) if args.global_shards_dir else None
+    )
+    single_db = None if shards_dir else Path(args.db) if args.db else None
+
+    result = inspect_cache_key(
+        args.cache_key,
+        qa_db=Path(qa_db),
+        shards_dir=shards_dir,
+        single_db=single_db,
+    )
+
+    if args.json:
+        print(json.dumps(result, indent=2, ensure_ascii=False))
+    else:
+        print(_render_inspect_human(result))
+    return 0 if result.get("status") == "ok" else 1
+
+
+def _render_inspect_human(result: dict) -> str:
+    """Pretty-print an inspect result so an operator can scan
+    paraphrase vs invention vs trailing-artifact at a glance."""
+    if result.get("status") != "ok":
+        return f"  {result.get('status', 'error')}: cache_key={result.get('cache_key', '?')}"
+
+    rec = result["record"]
+    ctx = result["context"]
+    sources = result["sources"]
+    diagnoses = result["unverified"]
+
+    lines: list[str] = []
+    lines.append(rec["question_text"])
+    lines.append(
+        f"  {rec['audit_mode']}  {rec['n_verified']}/{rec['n_quotes']} verified  "
+        f"via {rec['verifier_method']}  state={rec['falsification_state']}"
+    )
+    lines.append("")
+    lines.append(
+        f"context: {ctx['raw_chars']:,} raw -> {ctx['base_chars']:,} base "
+        f"(wikitext-strip {'on' if ctx['wikitext_strip_active'] else 'off'})"
+    )
+    if sources:
+        lines.append(f"sources ({len(sources)}):")
+        for i, s in enumerate(sources, start=1):
+            lines.append(
+                f"  [{i}] {s.get('title') or '(untitled)'} — "
+                f"{s.get('chunk_count', '?')} chunks, "
+                f"{s.get('raw_chars', 0):,} chars"
+            )
+    lines.append("")
+
+    if not diagnoses:
+        lines.append("(no unverified spans)")
+        return "\n".join(lines)
+
+    lines.append(f"unverified diagnoses ({len(diagnoses)}):")
+    for i, d in enumerate(diagnoses, start=1):
+        span = d.get("span", "")
+        diag = d.get("diagnosis", "?")
+        lines.append("")
+        lines.append(f"  [{i}] {diag}")
+        lines.append(f"      span: {_short(span, 140)}")
+        if diag == "trailing_artifact":
+            lines.append(f"      matched_prefix_chars: {d.get('matched_prefix_chars')}")
+            lines.append(f"      trailing_artifact: {_short(d.get('trailing_artifact', ''), 100)}")
+        elif diag == "synthetic_elision_inside_quote":
+            lines.append(
+                f"      [...] inserted by model — "
+                f"{d.get('prefix_chars', 0)} prefix chars "
+                f"({'in source' if d.get('prefix_in_source') else 'NOT in source'}), "
+                f"{d.get('suffix_chars', 0)} suffix chars "
+                f"({'in source' if d.get('suffix_in_source') else 'NOT in source'})"
+            )
+        elif diag == "interior_elision":
+            lines.append(
+                f"      matched: {d.get('matched_prefix_chars')} prefix + "
+                f"{d.get('matched_suffix_chars')} suffix chars (parenthetical aside dropped)"
+            )
+            lines.append(f"      dropped_aside: {_short(d.get('dropped_aside', ''), 120)}")
+        elif diag in ("paraphrase", "partial_paraphrase"):
+            lines.append(f"      token_coverage: {d.get('token_coverage')}")
+            counts = d.get("token_counts", {})
+            if counts:
+                top = ", ".join(f"{k}×{v}" for k, v in list(counts.items())[:6])
+                lines.append(f"      tokens_in_base: {top}")
+            missing = d.get("missing_tokens", [])
+            if missing:
+                lines.append(f"      missing_tokens: {missing[:8]}")
+        elif diag == "no_overlap":
+            lines.append(f"      tokens_checked: {d.get('tokens_checked', '?')}")
+            lines.append(f"      tokens_present: {d.get('tokens_present', '?')}")
+        repair = d.get("repair")
+        if repair:
+            action = repair.get("action", "?")
+            reason = repair.get("reason", "")
+            line = f"      repair: {action}"
+            if reason:
+                line += f"  ({reason})"
+            lines.append(line)
+    return "\n".join(lines)
+
+
+def _short(s: str, n: int) -> str:
+    """Truncate string to n chars with ellipsis."""
+    return s if len(s) <= n else s[: n - 3] + "..."
+
+
+def _falsify_cache_key(
+    cache_key_value: str,
+    *,
+    state: str,
+    reason: str,
+    by_actor: str,
+    shards_dir: Path | None,
+    db_path: Path | None,
+) -> dict:
+    """Mark a providence_cache record as failed/stale/quarantined across shards.
+
+    Searches every shard for the cache_key (it lives in exactly one).
+    Updates the row's falsification_state, appends a falsification log
+    entry, and writes a 'falsify' audit event so the chain records the act.
+    """
+    import time as _time
+
+    from aborist.store import append_audit, discover_shards, transaction
+
+    if state not in ("failed", "stale", "quarantined"):
+        return {"status": "invalid_state", "value": state}
+
+    paths: list[Path] = (
+        discover_shards(shards_dir) if shards_dir else [Path(db_path)]
+    )
+
+    for sp in paths:
+        c = connect(sp)
+        try:
+            row = c.execute(
+                "SELECT cache_key, falsification_state FROM providence_cache "
+                "WHERE cache_key = ?",
+                (cache_key_value,),
+            ).fetchone()
+            if row is None:
+                continue
+            now = int(_time.time())
+            with transaction(c):
+                event_hash = append_audit(
+                    c,
+                    event_type="falsify",
+                    subject_root=cache_key_value,
+                    body={
+                        "cache_key": cache_key_value,
+                        "from_state": row["falsification_state"],
+                        "to_state": state,
+                        "reason": reason,
+                        "by_actor": by_actor,
+                    },
+                    ts=now,
+                )
+                c.execute(
+                    "UPDATE providence_cache "
+                    "SET falsification_state = ?, audit_event_hash = ? "
+                    "WHERE cache_key = ?",
+                    (state, event_hash, cache_key_value),
+                )
+                c.execute(
+                    "INSERT INTO falsifications "
+                    "(cache_key, state, reason, by_actor, at, audit_event_hash) "
+                    "VALUES (?, ?, ?, ?, ?, ?)",
+                    (cache_key_value, state, reason, by_actor, now, event_hash),
+                )
+            return {
+                "status": "falsified",
+                "cache_key": cache_key_value,
+                "shard": sp.name,
+                "from_state": row["falsification_state"],
+                "to_state": state,
+                "reason": reason,
+                "by_actor": by_actor,
+                "audit_event_hash": event_hash,
+                "ts": now,
+            }
+        finally:
+            c.close()
+
+    return {"status": "not_found", "cache_key": cache_key_value}
+
+
+def _burn_cache_key(
+    cache_key_value: str,
+    *,
+    reason: str,
+    by_actor: str,
+    shards_dir: Path | None,
+    db_path: Path | None,
+    force: bool = False,
+) -> dict:
+    """Delete a providence_cache leaf, but only if it has no children.
+
+    "Kindergarten of a tree's genesis" — early/scratch use. Falsify keeps
+    history; burn removes the row. Children today = falsifications
+    referencing this cache_key. If any exist, refuse without ``--force``.
+
+    Always writes a 'providence_burn' audit event so the chain records
+    that a leaf was removed and why. Use ``aborist providence --falsify``
+    instead when downstream consumers may have built on this answer.
+    """
+    import time as _time
+
+    from aborist.store import append_audit, discover_shards, transaction
+
+    paths: list[Path] = (
+        discover_shards(shards_dir) if shards_dir else [Path(db_path)]
+    )
+
+    for sp in paths:
+        c = connect(sp)
+        try:
+            row = c.execute(
+                "SELECT cache_key, audit_mode, n_verified, falsification_state, "
+                " question_text FROM providence_cache WHERE cache_key = ?",
+                (cache_key_value,),
+            ).fetchone()
+            if row is None:
+                continue
+            child_falsifications = c.execute(
+                "SELECT COUNT(*) FROM falsifications WHERE cache_key = ?",
+                (cache_key_value,),
+            ).fetchone()[0]
+            if child_falsifications > 0 and not force:
+                return {
+                    "status": "refused_has_children",
+                    "cache_key": cache_key_value,
+                    "shard": sp.name,
+                    "child_falsifications": int(child_falsifications),
+                    "hint": "use --force to burn anyway, or 'providence --falsify' to keep history",
+                }
+            now = int(_time.time())
+            with transaction(c):
+                c.execute(
+                    "DELETE FROM providence_cache WHERE cache_key = ?",
+                    (cache_key_value,),
+                )
+            event_hash = append_audit(
+                c,
+                event_type="providence_burn",
+                subject_root=cache_key_value,
+                body={
+                    "cache_key": cache_key_value,
+                    "burned_audit_mode": row["audit_mode"],
+                    "burned_n_verified": int(row["n_verified"]),
+                    "burned_state": row["falsification_state"],
+                    "question_text": row["question_text"],
+                    "reason": reason,
+                    "by_actor": by_actor,
+                    "child_falsifications_at_burn": int(child_falsifications),
+                    "forced": bool(child_falsifications > 0 and force),
+                },
+                ts=now,
+            )
+            return {
+                "status": "burned",
+                "cache_key": cache_key_value,
+                "shard": sp.name,
+                "burned_audit_mode": row["audit_mode"],
+                "reason": reason,
+                "by_actor": by_actor,
+                "audit_event_hash": event_hash,
+                "ts": now,
+            }
+        finally:
+            c.close()
+
+    return {"status": "not_found", "cache_key": cache_key_value}
+
+
+def _count_document_children(c, document_root: str) -> dict:
+    """Count outbound child references that 'burn' must protect.
+
+    For a document/core leaf, "children" = anything downstream that built on
+    this row. Specifically:
+      - derivations rows where ``src_root = root`` (a core was distilled
+        from this — burning would orphan or silently cascade-truncate the
+        derivation, leaving the descendant core dangling).
+      - edges rows where ``dst_root = root`` (other documents link to this
+        one; burning leaves dangling references).
+      - providence_cache rows where ``source_root = root`` (Q&A grounded
+        in this document).
+
+    NOTE on schema: derivations has ON DELETE CASCADE on BOTH ``core_root``
+    AND ``src_root``. Without this gate, a bare DELETE FROM documents would
+    silently cascade-prune derivations and orphan downstream cores.
+    """
+    derivations_downstream = c.execute(
+        "SELECT COUNT(*) FROM derivations WHERE src_root = ?",
+        (document_root,),
+    ).fetchone()[0]
+    incoming_edges = c.execute(
+        "SELECT COUNT(*) FROM edges WHERE dst_root = ?",
+        (document_root,),
+    ).fetchone()[0]
+    providence_refs = c.execute(
+        "SELECT COUNT(*) FROM providence_cache WHERE source_root = ?",
+        (document_root,),
+    ).fetchone()[0]
+    return {
+        "derivations_downstream": int(derivations_downstream),
+        "incoming_edges": int(incoming_edges),
+        "providence_refs": int(providence_refs),
+    }
+
+
+def _burn_document_root(
+    document_root_value: str,
+    *,
+    reason: str,
+    by_actor: str,
+    shards_dir: Path | None,
+    db_path: Path | None,
+    force: bool = False,
+) -> dict:
+    """Delete a surface document leaf, but only if it has no children.
+
+    Children:
+      - derivations.src_root = root      (downstream cores derived from it)
+      - edges.dst_root       = root      (other docs link to it)
+      - providence_cache.source_root = root  (Q&A grounded in it)
+
+    On burn:
+      - DELETE FROM chunks_fts (FTS5 has no FK; clear before chunks vanish).
+      - DELETE FROM documents — cascades to chunks + merkle_nodes via FK.
+      - Append a 'document_burn' audit event recording counts + forced flag.
+
+    Refuses with status='refused_has_children' (and skips the audit event)
+    when any child count > 0 and ``--force`` is not set, so callers can fix
+    state and retry idempotently.
+    """
+    import time as _time
+
+    from aborist.store import append_audit, discover_shards, transaction
+
+    paths: list[Path] = (
+        discover_shards(shards_dir) if shards_dir else [Path(db_path)]
+    )
+
+    for sp in paths:
+        c = connect(sp)
+        try:
+            row = c.execute(
+                "SELECT document_root, document_uri, kind, title, source_type, "
+                "       chunking_version, canonicalization_version, schema_version "
+                "FROM documents WHERE document_root = ? AND kind = 'surface'",
+                (document_root_value,),
+            ).fetchone()
+            if row is None:
+                continue
+            counts = _count_document_children(c, document_root_value)
+            total_children = sum(counts.values())
+            if total_children > 0 and not force:
+                return {
+                    "status": "refused_has_children",
+                    "document_root": document_root_value,
+                    "kind": "surface",
+                    "shard": sp.name,
+                    **counts,
+                    "hint": "use --force to burn anyway (orphans descendants); "
+                            "prefer evict for cold-tier compression",
+                }
+            chunk_count = c.execute(
+                "SELECT COUNT(*) FROM chunks WHERE document_root = ?",
+                (document_root_value,),
+            ).fetchone()[0]
+            now = int(_time.time())
+            with transaction(c):
+                # FTS5 has no FK to chunks; clear by chunk_id before the
+                # CASCADE on documents wipes the rows that resolve them.
+                for cr in c.execute(
+                    "SELECT chunk_id FROM chunks WHERE document_root = ?",
+                    (document_root_value,),
+                ).fetchall():
+                    c.execute(
+                        "DELETE FROM chunks_fts WHERE rowid = ?",
+                        (cr["chunk_id"],),
+                    )
+                # Outbound edges (src_root = this) carry no FK; clean them
+                # explicitly so we don't leave half-edges pointing from a
+                # ghost. Incoming edges (dst_root = this) are already gated
+                # above by the children check.
+                c.execute(
+                    "DELETE FROM edges WHERE src_root = ?",
+                    (document_root_value,),
+                )
+                # documents -> chunks/merkle_nodes/derivations cascade via FK.
+                c.execute(
+                    "DELETE FROM documents WHERE document_root = ?",
+                    (document_root_value,),
+                )
+            event_hash = append_audit(
+                c,
+                event_type="document_burn",
+                subject_root=document_root_value,
+                body={
+                    "document_root": document_root_value,
+                    "document_uri": row["document_uri"],
+                    "kind": "surface",
+                    "title": row["title"],
+                    "source_type": row["source_type"],
+                    "burned_chunk_count": int(chunk_count),
+                    "child_counts_at_burn": counts,
+                    "reason": reason,
+                    "by_actor": by_actor,
+                    "forced": bool(total_children > 0 and force),
+                },
+                ts=now,
+            )
+            return {
+                "status": "burned",
+                "document_root": document_root_value,
+                "kind": "surface",
+                "shard": sp.name,
+                "burned_chunk_count": int(chunk_count),
+                "child_counts_at_burn": counts,
+                "reason": reason,
+                "by_actor": by_actor,
+                "audit_event_hash": event_hash,
+                "ts": now,
+            }
+        finally:
+            c.close()
+
+    return {"status": "not_found", "document_root": document_root_value, "kind": "surface"}
+
+
+def _burn_core_root(
+    document_root_value: str,
+    *,
+    reason: str,
+    by_actor: str,
+    shards_dir: Path | None,
+    db_path: Path | None,
+    force: bool = False,
+) -> dict:
+    """Delete a core document leaf, but only if it has no children.
+
+    Same children gates as ``_burn_document_root`` (derivations.src_root,
+    edges.dst_root, providence_cache.source_root). The "PLUS no further
+    derivations build cores from this core" rule from the spec is
+    structurally identical to derivations.src_root > 0 — a core acts as a
+    src_root only when something deeper distilled from it.
+
+    CLAUDE.md says "Cores never evict" — that's the eviction subsystem,
+    which only touches kind='surface'. Burn is operator-driven removal:
+    cores CAN be burned, but the children gate is enforced.
+
+    Audit event type is 'core_burn' so chain consumers can distinguish
+    surface vs core leaf removals at a glance.
+    """
+    import time as _time
+
+    from aborist.store import append_audit, discover_shards, transaction
+
+    paths: list[Path] = (
+        discover_shards(shards_dir) if shards_dir else [Path(db_path)]
+    )
+
+    for sp in paths:
+        c = connect(sp)
+        try:
+            row = c.execute(
+                "SELECT document_root, document_uri, kind, title, source_type, "
+                "       compression_depth, chunking_version, "
+                "       canonicalization_version, schema_version "
+                "FROM documents WHERE document_root = ? AND kind = 'core'",
+                (document_root_value,),
+            ).fetchone()
+            if row is None:
+                continue
+            counts = _count_document_children(c, document_root_value)
+            total_children = sum(counts.values())
+            if total_children > 0 and not force:
+                return {
+                    "status": "refused_has_children",
+                    "document_root": document_root_value,
+                    "kind": "core",
+                    "shard": sp.name,
+                    **counts,
+                    "hint": "use --force to burn anyway; cores carry "
+                            "downstream derivations that will be orphaned",
+                }
+            chunk_count = c.execute(
+                "SELECT COUNT(*) FROM chunks WHERE document_root = ?",
+                (document_root_value,),
+            ).fetchone()[0]
+            # Inbound derivations (where this core is core_root, i.e. its
+            # binding back to source surfaces). These are NOT children —
+            # they're the core's own provenance and cascade-delete with it.
+            inbound_derivations = c.execute(
+                "SELECT COUNT(*) FROM derivations WHERE core_root = ?",
+                (document_root_value,),
+            ).fetchone()[0]
+            now = int(_time.time())
+            with transaction(c):
+                for cr in c.execute(
+                    "SELECT chunk_id FROM chunks WHERE document_root = ?",
+                    (document_root_value,),
+                ).fetchall():
+                    c.execute(
+                        "DELETE FROM chunks_fts WHERE rowid = ?",
+                        (cr["chunk_id"],),
+                    )
+                c.execute(
+                    "DELETE FROM edges WHERE src_root = ?",
+                    (document_root_value,),
+                )
+                c.execute(
+                    "DELETE FROM documents WHERE document_root = ?",
+                    (document_root_value,),
+                )
+            event_hash = append_audit(
+                c,
+                event_type="core_burn",
+                subject_root=document_root_value,
+                body={
+                    "document_root": document_root_value,
+                    "document_uri": row["document_uri"],
+                    "kind": "core",
+                    "title": row["title"],
+                    "source_type": row["source_type"],
+                    "compression_depth": int(row["compression_depth"]),
+                    "burned_chunk_count": int(chunk_count),
+                    "burned_inbound_derivations": int(inbound_derivations),
+                    "child_counts_at_burn": counts,
+                    "reason": reason,
+                    "by_actor": by_actor,
+                    "forced": bool(total_children > 0 and force),
+                },
+                ts=now,
+            )
+            return {
+                "status": "burned",
+                "document_root": document_root_value,
+                "kind": "core",
+                "shard": sp.name,
+                "burned_chunk_count": int(chunk_count),
+                "burned_inbound_derivations": int(inbound_derivations),
+                "child_counts_at_burn": counts,
+                "reason": reason,
+                "by_actor": by_actor,
+                "audit_event_hash": event_hash,
+                "ts": now,
+            }
+        finally:
+            c.close()
+
+    return {"status": "not_found", "document_root": document_root_value, "kind": "core"}
+
+
+def _cmd_burn_kindergarten(args: argparse.Namespace) -> int:
+    """Burn all providence_cache rows younger than the kindergarten window.
+
+    Test-ergonomic mass burn: when iterating on retrieval/verifier knobs
+    you want to wipe recent test runs without finding each cache_key.
+    Mirrors the kindergarten window from `mesh sync` so what's still
+    "private" (un-broadcast) is also what's safe to bust without
+    confusing peers.
+
+    Each row goes through the standard `_burn_cache_key` so the
+    children gate is honored (use `--force` to override en masse).
+    Each successful burn writes one ``providence_burn`` audit event;
+    chain integrity is verifiable via `make chain-check-shards` after.
+    """
+    import time as _time
+    from aborist.store import discover_shards
+
+    now = int(_time.time())
+    # `kindergarten_seconds <= 0` means "no time gate — burn every live
+    # row" per the verb's docstring. The earlier `cutoff = now - 0`
+    # treated 0 as a same-second-only window, which made
+    # test_burn_kindergarten_zero_seconds_burns_everything timing-flaky:
+    # if the wall-clock second rolled over between seed and burn,
+    # cutoff > seed.created_at and nothing matched.
+    kindergarten_seconds = max(0, args.kindergarten_seconds)
+    no_time_gate = kindergarten_seconds == 0
+    cutoff = 0 if no_time_gate else now - kindergarten_seconds
+    shards_dir = Path(args.global_shards_dir) if args.global_shards_dir else None
+    single_db = Path(args.db) if args.db else None
+    paths: list[Path] = (
+        discover_shards(shards_dir) if shards_dir else [single_db]
+    )
+    actor = args.by_actor or os.environ.get("USER", "unknown")
+    reason = args.reason or f"burn-kindergarten window={args.kindergarten_seconds}s"
+
+    examined = 0
+    burned = 0
+    refused = 0
+    not_found = 0
+    items: list[dict] = []
+    for sp in paths:
+        c = connect(sp)
+        try:
+            if no_time_gate:
+                rows = c.execute(
+                    "SELECT cache_key, created_at, audit_mode "
+                    "FROM providence_cache "
+                    "WHERE falsification_state = 'live' "
+                    "ORDER BY created_at DESC"
+                ).fetchall()
+            else:
+                rows = c.execute(
+                    "SELECT cache_key, created_at, audit_mode "
+                    "FROM providence_cache "
+                    "WHERE created_at >= ? AND falsification_state = 'live' "
+                    "ORDER BY created_at DESC",
+                    (cutoff,),
+                ).fetchall()
+        finally:
+            c.close()
+        for r in rows:
+            examined += 1
+            if args.dry_run:
+                items.append({
+                    "cache_key": r["cache_key"],
+                    "audit_mode": r["audit_mode"],
+                    "created_at": r["created_at"],
+                    "would_burn": True,
+                })
+                continue
+            result = _burn_cache_key(
+                r["cache_key"],
+                reason=reason,
+                by_actor=actor,
+                shards_dir=shards_dir,
+                db_path=single_db,
+                force=bool(args.force),
+            )
+            status = result.get("status")
+            if status == "burned":
+                burned += 1
+            elif status == "refused_has_children":
+                refused += 1
+            else:
+                not_found += 1
+            items.append(result)
+
+    print(json.dumps({
+        "status": "dry_run" if args.dry_run else "burned",
+        "kindergarten_seconds": args.kindergarten_seconds,
+        "cutoff_at": cutoff,
+        "now": now,
+        "examined": examined,
+        "burned": burned,
+        "refused_has_children": refused,
+        "not_found": not_found,
+        "items": items[: args.verbose],
+    }, indent=2, ensure_ascii=False))
+    return 0
+
+
+def _cmd_burn(args: argparse.Namespace) -> int:
+    """CLI: burn a leaf with no children.
+
+    Dispatches on ``--kind`` to the matching helper. Default 'providence'
+    preserves the original surface (`--cache-key` only) so existing scripts
+    keep working. Document/core kinds use ``--root``.
+    """
+    kind = getattr(args, "kind", "providence") or "providence"
+    shards = Path(args.global_shards_dir) if args.global_shards_dir else None
+    db = Path(args.db) if args.db else None
+    actor = args.by_actor or os.environ.get("USER", "unknown")
+    reason = args.reason or ""
+    force = bool(args.force)
+
+    if kind == "providence":
+        if not getattr(args, "cache_key", None):
+            print("burn --kind providence requires --cache-key", file=sys.stderr)
+            return 2
+        result = _burn_cache_key(
+            args.cache_key,
+            reason=reason,
+            by_actor=actor,
+            shards_dir=shards,
+            db_path=db,
+            force=force,
+        )
+    elif kind in ("document", "core"):
+        if not getattr(args, "root", None):
+            print(f"burn --kind {kind} requires --root", file=sys.stderr)
+            return 2
+        helper = _burn_document_root if kind == "document" else _burn_core_root
+        result = helper(
+            args.root,
+            reason=reason,
+            by_actor=actor,
+            shards_dir=shards,
+            db_path=db,
+            force=force,
+        )
+    else:
+        print(f"unknown burn kind: {kind}", file=sys.stderr)
+        return 2
+
+    print(json.dumps(result, indent=2, ensure_ascii=False))
+    return 0 if result.get("status") == "burned" else 1
+
+
+def _cmd_providence(args: argparse.Namespace) -> int:
+    """List providence_cache records or falsify one by cache_key."""
+    if getattr(args, "falsify", None):
+        result = _falsify_cache_key(
+            args.falsify,
+            state=args.state,
+            reason=args.reason or "",
+            by_actor=args.by_actor or os.environ.get("USER", "unknown"),
+            shards_dir=Path(args.global_shards_dir) if args.global_shards_dir else None,
+            db_path=Path(args.db) if args.db else None,
+        )
+        print(json.dumps(result, indent=2, ensure_ascii=False))
+        return 0 if result.get("status") == "falsified" else 1
+    if getattr(args, "show_preflight", None):
+        # Ticket #000009 §7.2 — pull the preflight stage payload
+        # from a row's run_dag_blob. Operator tool for inspecting
+        # the policy state that governed the cached row.
+        return _cmd_providence_show_preflight(
+            cache_key_prefix=args.show_preflight,
+            shards_dir=args.global_shards_dir,
+            db=args.db,
+        )
+    conn = (
+        connect_query(args.db, shards_dir=args.global_shards_dir)
+        if args.global_shards_dir
+        else connect(args.db)
+    )
+    try:
+        if args.document_uri:
+            rows = conn.execute(
+                "SELECT cache_key, question_text, answer_text, falsification_state, "
+                " hit_count, created_at FROM providence_cache "
+                "WHERE document_uri = ? ORDER BY created_at DESC",
+                (args.document_uri,),
+            ).fetchall()
+        elif args.source_root:
+            rows = conn.execute(
+                "SELECT cache_key, question_text, answer_text, falsification_state, "
+                " hit_count, created_at FROM providence_cache "
+                "WHERE source_root = ? ORDER BY created_at DESC",
+                (args.source_root,),
+            ).fetchall()
+        else:
+            rows = conn.execute(
+                "SELECT cache_key, question_text, answer_text, falsification_state, "
+                " hit_count, created_at FROM providence_cache "
+                "ORDER BY created_at DESC LIMIT ?",
+                (args.limit,),
+            ).fetchall()
+    finally:
+        conn.close()
+    out = [
+        {
+            "cache_key": r["cache_key"],
+            "state": r["falsification_state"],
+            "hit_count": r["hit_count"],
+            "question": r["question_text"],
+            "answer": r["answer_text"],
+            "created_at": r["created_at"],
+        }
+        for r in rows
+    ]
+    print(json.dumps(out, indent=2, ensure_ascii=False))
+    return 0
+
+
+def _cmd_providence_show_preflight(
+    *,
+    cache_key_prefix: str,
+    shards_dir: str | None,
+    db: str | None,
+) -> int:
+    """Render the ``preflight`` stage payload for a cached row.
+
+    Ticket #000009 §7.2. Pulls ``run_dag_blob`` for the matching
+    cache row, parses the JSON, finds the ``preflight`` node, and
+    pretty-prints the five nested CTI clauses (classifier,
+    answer_contract, prompt_contract, evidence_contract,
+    policy_refs) plus the metacognition QuestionState.
+
+    Match is by 12-char prefix on ``cache_key`` (matches what
+    bench rows + `_render_query_human` already truncate to).
+    Returns 0 on success, 1 on miss / parse failure.
+    """
+    conn = (
+        connect_query(db, shards_dir=shards_dir)
+        if shards_dir
+        else connect(db)
+    )
+    try:
+        rows = conn.execute(
+            "SELECT cache_key, question_text, run_dag_blob "
+            "FROM providence_cache WHERE cache_key LIKE ? "
+            "ORDER BY created_at DESC LIMIT 5",
+            (cache_key_prefix + "%",),
+        ).fetchall()
+    finally:
+        conn.close()
+    if not rows:
+        print(
+            f"  no providence_cache row matching cache_key prefix "
+            f"'{cache_key_prefix}'", file=sys.stderr,
+        )
+        return 1
+    if len(rows) > 1:
+        print(
+            f"  {len(rows)} rows match prefix '{cache_key_prefix}'; "
+            "rendering most recent. Pass a longer prefix to disambiguate.",
+            file=sys.stderr,
+        )
+    row = rows[0]
+    blob = row["run_dag_blob"]
+    if not blob:
+        print(
+            f"  cache_key {row['cache_key'][:12]}: no run_dag_blob "
+            "(legacy row, predates #000009)",
+            file=sys.stderr,
+        )
+        return 1
+    try:
+        parsed = json.loads(blob)
+    except json.JSONDecodeError as exc:
+        print(f"  run_dag_blob parse error: {exc}", file=sys.stderr)
+        return 1
+    nodes = parsed.get("nodes") or []
+    preflight_node = next(
+        (n for n in nodes if isinstance(n, dict)
+         and n.get("stage") == "preflight"),
+        None,
+    )
+    if preflight_node is None:
+        print(
+            f"  cache_key {row['cache_key'][:12]}: run_dag has no "
+            "preflight stage (predates #000009 binding)",
+            file=sys.stderr,
+        )
+        return 1
+    # Pull the full preflight payload (Ticket #000009 §7.2 — payload
+    # now persisted alongside nodes via build_run_dag's
+    # preflight_payload kwarg). Fall back to hash-only render for
+    # legacy rows whose blob predates the payload-storage commit.
+    payload = parsed.get("preflight_payload")
+    out: dict = {
+        "cache_key": row["cache_key"][:12],
+        "question": row["question_text"],
+        "preflight_stage_hash": preflight_node.get("hash"),
+        "preflight_hash_12": (preflight_node.get("hash") or "")[:12],
+        "run_dag_root": parsed.get("root"),
+        "run_dag_stages": [n.get("stage") for n in nodes],
+    }
+    if payload is not None:
+        # Verify the persisted payload hashes to the persisted leaf.
+        # Mismatch would indicate post-write tampering or a serialization
+        # drift; surface it explicitly so an auditor can detect.
+        from aborist.qa.dag import _canonical_json, _sha256_hex
+        recomputed = _sha256_hex(_canonical_json(payload))
+        out["preflight_payload"] = payload
+        out["payload_hash_check"] = (
+            "ok" if recomputed == preflight_node.get("hash")
+            else f"MISMATCH (recomputed {recomputed[:12]} != stored {preflight_node.get('hash', '')[:12]})"
+        )
+    else:
+        out["preflight_payload"] = None
+        out["payload_hash_check"] = (
+            "unavailable: legacy row predates preflight_payload "
+            "persistence (Ticket #000009 §7.2)"
+        )
+    print(json.dumps(out, indent=2, ensure_ascii=False))
+    return 0
+
+
+def _load_record_context(row, shards_dir, qa_db):
+    """Reassemble context for a providence record. Returns text or None
+    if any source doc has no hot chunks (cold)."""
+    from aborist.qa.query import _load_doc_text
+
+    proof = json.loads(row["merkle_proof"])
+    sources = proof.get("sources", [])
+    if not sources:
+        return None
+    parts: list[str] = []
+    for src in sources:
+        shard_name = src.get("shard")
+        if not shard_name:
+            return None
+        if shards_dir:
+            shard_path = shards_dir / shard_name
+        else:
+            shard_path = qa_db.parent / shard_name
+        if not shard_path.exists():
+            return None
+        text = _load_doc_text(str(shard_path), src["document_root"])
+        if not text:
+            return None
+        parts.append(text)
+    return "\n\n".join(parts)
+
+
+def _cmd_reclassify(args: argparse.Namespace) -> int:
+    """Re-run the layered verifier against existing live providence records.
+
+    Reads each record's answer + reassembles its context from
+    merkle_proof.sources, runs verify_quotes(), and updates the row only
+    if the verdict differs from what's stored. No LLM calls — this just
+    relabels existing answers under the current verifier.
+
+    Cold-source records (where any source doc has no hot chunks) are
+    skipped: we can't faithfully reclassify without the original context.
+    Run `aborist rehydrate` first if you want those covered too.
+
+    `--compare` runs all four entity policies side-by-side without
+    writing — use it to see what each policy would produce on real data
+    before committing to one. `--entity-policy X` writes under a single
+    policy.
+
+    Each changed record gets one 'providence_reclassify' audit event
+    with old & new state for chain-of-custody.
+    """
+    import time
+    from collections import defaultdict
+
+    from aborist.qa.verify import (
+        DEFAULT_ENTITY_POLICY,
+        ENTITY_POLICIES,
+        verify_quotes,
+    )
+
+    qa_db = args.qa_db
+    if qa_db is None:
+        if args.global_shards_dir:
+            qa_db = Path(args.global_shards_dir) / "qa.db"
+        else:
+            qa_db = Path.home() / ".aborist" / "qa.db"
+    qa_db = Path(qa_db)
+
+    shards_dir = (
+        Path(args.global_shards_dir) if args.global_shards_dir else None
+    )
+
+    conn = connect(qa_db)
+    try:
+        sql = (
+            "SELECT cache_key, answer_text, merkle_proof, audit_mode, "
+            " verifier_method, n_quotes, n_verified, unverified_quotes, "
+            " question_text "
+            "FROM providence_cache "
+            "WHERE falsification_state = 'live' "
+            "ORDER BY created_at DESC"
+        )
+        if args.limit:
+            sql += f" LIMIT {int(args.limit)}"
+        rows = conn.execute(sql).fetchall()
+
+        if args.compare:
+            # Run all four policies side-by-side, no DB write. Output is a
+            # per-record grid + a per-policy distribution summary so fox can
+            # eyeball where the policies disagree.
+            grid = []
+            distribution: dict[str, dict[str, int]] = {
+                p: defaultdict(int) for p in ENTITY_POLICIES
+            }
+            skipped_cold = 0
+            for row in rows:
+                context = _load_record_context(row, shards_dir, qa_db)
+                if context is None:
+                    skipped_cold += 1
+                    continue
+                per_policy = {}
+                for p in ENTITY_POLICIES:
+                    v = verify_quotes(row["answer_text"], context, entity_policy=p)
+                    label = f"{v['audit_mode']}/{v['verifier_method']}"
+                    per_policy[p] = label
+                    distribution[p][label] += 1
+                grid.append({
+                    "cache_key": row["cache_key"][:16] + "…",
+                    "question": row["question_text"][:55],
+                    **per_policy,
+                })
+            print(json.dumps({
+                "examined": len(grid),
+                "skipped_cold": skipped_cold,
+                "distribution": {p: dict(d) for p, d in distribution.items()},
+                "records": grid,
+            }, indent=2, ensure_ascii=False))
+            return 0
+
+        # Single-policy reclassify. Default tracks DEFAULT_ENTITY_POLICY
+        # so the CLI always matches the verifier's current contract.
+        policy_name = args.entity_policy or DEFAULT_ENTITY_POLICY
+        if policy_name not in ENTITY_POLICIES:
+            print(
+                f"--entity-policy must be one of {ENTITY_POLICIES}, "
+                f"got {policy_name!r}",
+                file=sys.stderr,
+            )
+            return 2
+
+        summary = {
+            "examined": 0,
+            "changed": 0,
+            "skipped_cold": 0,
+            "unchanged": 0,
+            "entity_policy": policy_name,
+            "transitions": defaultdict(int),
+        }
+
+        for row in rows:
+            summary["examined"] += 1
+            context = _load_record_context(row, shards_dir, qa_db)
+            if context is None:
+                summary["skipped_cold"] += 1
+                continue
+
+            verdict = verify_quotes(
+                row["answer_text"], context, entity_policy=policy_name
+            )
+
+            old_unverified = row["unverified_quotes"] or "null"
+            new_unverified_blob = (
+                json.dumps(verdict["unverified_quotes"], separators=(",", ":"))
+                if verdict["unverified_quotes"]
+                else None
+            )
+            new_unverified_for_compare = new_unverified_blob or "null"
+
+            unchanged = (
+                verdict["audit_mode"] == row["audit_mode"]
+                and verdict["verifier_method"] == row["verifier_method"]
+                and verdict["n_quotes"] == row["n_quotes"]
+                and verdict["n_verified"] == row["n_verified"]
+                and old_unverified == new_unverified_for_compare
+            )
+            if unchanged:
+                summary["unchanged"] += 1
+                continue
+
+            summary["changed"] += 1
+            transition = (
+                f"{row['audit_mode']}/{row['verifier_method']} "
+                f"-> {verdict['audit_mode']}/{verdict['verifier_method']}"
+            )
+            summary["transitions"][transition] += 1
+
+            if args.dry_run:
+                continue
+
+            now = int(time.time())
+            with transaction(conn):
+                event_hash = append_audit(
+                    conn,
+                    event_type="providence_reclassify",
+                    subject_root=row["cache_key"],
+                    body={
+                        "old_audit_mode": row["audit_mode"],
+                        "new_audit_mode": verdict["audit_mode"],
+                        "old_method": row["verifier_method"],
+                        "new_method": verdict["verifier_method"],
+                        "old_n_verified": row["n_verified"],
+                        "new_n_verified": verdict["n_verified"],
+                        "entity_policy": policy_name,
+                    },
+                    ts=now,
+                )
+                conn.execute(
+                    "UPDATE providence_cache SET "
+                    " audit_mode = ?, n_quotes = ?, n_verified = ?, "
+                    " unverified_quotes = ?, verifier_method = ?, "
+                    " audit_event_hash = ? "
+                    "WHERE cache_key = ?",
+                    (
+                        verdict["audit_mode"],
+                        verdict["n_quotes"],
+                        verdict["n_verified"],
+                        new_unverified_blob,
+                        verdict["verifier_method"],
+                        event_hash,
+                        row["cache_key"],
+                    ),
+                )
+    finally:
+        conn.close()
+
+    summary["transitions"] = dict(summary["transitions"])
+    summary["dry_run"] = bool(args.dry_run)
+    print(json.dumps(summary, indent=2, ensure_ascii=False))
+    return 0
+
+
+def _cmd_emergent(args: argparse.Namespace) -> int:
+    """Surface emergent claims from UNGROUNDED/HYBRID providence records.
+
+    These are spans the model produced that don't appear verbatim in the
+    corpus — candidate ingest targets. Frequent unverified quotes signal
+    knowledge the model has from training that our corpus is missing.
+    """
+    conn = (
+        connect_query(args.db, shards_dir=args.global_shards_dir)
+        if args.global_shards_dir
+        else connect(args.db)
+    )
+    try:
+        if args.aggregate:
+            rows = conn.execute(
+                "SELECT unverified_quotes FROM providence_cache "
+                "WHERE audit_mode IN ('UNGROUNDED','HYBRID') "
+                " AND falsification_state = 'live' "
+                " AND unverified_quotes IS NOT NULL"
+            ).fetchall()
+            counts: dict[str, int] = {}
+            for r in rows:
+                for q in json.loads(r["unverified_quotes"]):
+                    counts[q] = counts.get(q, 0) + 1
+            ranked = sorted(counts.items(), key=lambda kv: -kv[1])[: args.limit]
+            print(json.dumps(
+                [{"quote": q, "count": c} for q, c in ranked],
+                indent=2, ensure_ascii=False
+            ))
+        else:
+            rows = conn.execute(
+                "SELECT cache_key, audit_mode, verifier_method, question_text, "
+                " n_quotes, n_verified, unverified_quotes, created_at "
+                "FROM providence_cache "
+                "WHERE audit_mode IN ('UNGROUNDED','HYBRID') "
+                " AND falsification_state = 'live' "
+                "ORDER BY created_at DESC LIMIT ?",
+                (args.limit,),
+            ).fetchall()
+            out = [
+                {
+                    "cache_key": r["cache_key"],
+                    "audit_mode": r["audit_mode"],
+                    "verifier_method": r["verifier_method"],
+                    "question": r["question_text"],
+                    "n_quotes": r["n_quotes"],
+                    "n_verified": r["n_verified"],
+                    "unverified_quotes": (
+                        json.loads(r["unverified_quotes"])
+                        if r["unverified_quotes"]
+                        else []
+                    ),
+                    "created_at": r["created_at"],
+                }
+                for r in rows
+            ]
+            print(json.dumps(out, indent=2, ensure_ascii=False))
+    finally:
+        conn.close()
+    return 0
+
+
+def _cmd_evict(args: argparse.Namespace) -> int:
+    """Move hot chunks to cold tier (archive unused content)."""
+    from aborist.evict import evict_to_cold
+
+    conn = (
+        connect_query(args.db, shards_dir=args.global_shards_dir)
+        if args.global_shards_dir
+        else connect(args.db)
+    )
+    try:
+        result = evict_to_cold(
+            conn,
+            source_type=args.source_type,
+            older_than_days=args.older_than_days,
+            document_roots=args.document_root or None,
+        )
+    finally:
+        conn.close()
+    print(json.dumps(result, indent=2, ensure_ascii=False))
+    return 0
+
+
+def _cmd_rehydrate(args: argparse.Namespace) -> int:
+    """Rehydrate cold chunks from source (inverse of evict)."""
+    from aborist.evict import rehydrate
+
+    conn = (
+        connect_query(args.db, shards_dir=args.global_shards_dir)
+        if args.global_shards_dir
+        else connect(args.db)
+    )
+    try:
+        if args.all_cold:
+            roots = [
+                r["document_root"]
+                for r in conn.execute(
+                    "SELECT DISTINCT document_root FROM chunks WHERE tier = 'cold'"
+                ).fetchall()
+            ]
+        else:
+            roots = list(args.document_root or [])
+        if not roots:
+            print(
+                "rehydrate needs --document-root R or --all-cold",
+                file=sys.stderr,
+            )
+            return 2
+        results = []
+        for r in roots:
+            res = rehydrate(conn, r)
+            res["document_root"] = r
+            results.append(res)
+    finally:
+        conn.close()
+    print(json.dumps(results, indent=2, ensure_ascii=False))
+    drift = sum(1 for r in results if r.get("status") == "drift_detected")
+    return 1 if drift else 0
+
+
+def _cmd_activity(args: argparse.Namespace) -> int:
+    """Recent activity: Q&A records + freshly cached docs across all shards.
+
+    Designed for an agent to read before deciding the next action — what was
+    just asked, what was just integrated, what's the corpus state.
+    """
+    import time as _time
+
+    from aborist.store import discover_shards
+
+    shard_paths: list[Path] = []
+    if args.global_shards_dir:
+        shard_paths = discover_shards(args.global_shards_dir)
+    else:
+        shard_paths = [Path(args.db)]
+
+    cutoff_ts = 0
+    if args.since_seconds:
+        cutoff_ts = int(_time.time()) - args.since_seconds
+
+    qa_records: list[dict] = []
+    ingest_events: list[dict] = []
+    derive_events: list[dict] = []
+    falsifications: list[dict] = []
+    corpus = {
+        "documents_total": 0,
+        "documents_surface": 0,
+        "documents_core": 0,
+        "providence_total": 0,
+        "providence_live": 0,
+        "providence_stale": 0,
+        "providence_failed": 0,
+        "audit_events_total": 0,
+    }
+
+    for sp in shard_paths:
+        c = connect(sp)
+        try:
+            corpus["documents_total"] += c.execute(
+                "SELECT COUNT(*) FROM documents"
+            ).fetchone()[0]
+            corpus["documents_surface"] += c.execute(
+                "SELECT COUNT(*) FROM documents WHERE kind='surface'"
+            ).fetchone()[0]
+            corpus["documents_core"] += c.execute(
+                "SELECT COUNT(*) FROM documents WHERE kind='core'"
+            ).fetchone()[0]
+            corpus["providence_total"] += c.execute(
+                "SELECT COUNT(*) FROM providence_cache"
+            ).fetchone()[0]
+            corpus["providence_live"] += c.execute(
+                "SELECT COUNT(*) FROM providence_cache WHERE falsification_state='live'"
+            ).fetchone()[0]
+            corpus["providence_stale"] += c.execute(
+                "SELECT COUNT(*) FROM providence_cache WHERE falsification_state='stale'"
+            ).fetchone()[0]
+            corpus["providence_failed"] += c.execute(
+                "SELECT COUNT(*) FROM providence_cache WHERE falsification_state='failed'"
+            ).fetchone()[0]
+            corpus["audit_events_total"] += c.execute(
+                "SELECT COUNT(*) FROM audit_events"
+            ).fetchone()[0]
+
+            # Q&A records
+            for r in c.execute(
+                "SELECT cache_key, question_text, answer_text, "
+                " falsification_state, hit_count, created_at, last_hit_at, "
+                " document_uri FROM providence_cache "
+                "WHERE created_at >= ? ORDER BY created_at DESC LIMIT ?",
+                (cutoff_ts, args.limit),
+            ).fetchall():
+                ans = r["answer_text"] or ""
+                qa_records.append(
+                    {
+                        "ts": r["created_at"],
+                        "shard": sp.name,
+                        "cache_key": r["cache_key"],
+                        "question": r["question_text"],
+                        "answer_preview": (
+                            ans if len(ans) <= args.preview_chars
+                            else ans[: args.preview_chars] + "…"
+                        ),
+                        "sources_uri": r["document_uri"],
+                        "state": r["falsification_state"],
+                        "hit_count": r["hit_count"],
+                        "last_hit_at": r["last_hit_at"],
+                    }
+                )
+
+            # Recent ingest events
+            for r in c.execute(
+                "SELECT subject_root, body, ts FROM audit_events "
+                "WHERE event_type = 'ingest' AND ts >= ? "
+                "ORDER BY ts DESC LIMIT ?",
+                (cutoff_ts, args.limit),
+            ).fetchall():
+                body = json.loads(r["body"]) if r["body"] else {}
+                ingest_events.append(
+                    {
+                        "ts": r["ts"],
+                        "shard": sp.name,
+                        "document_root": r["subject_root"],
+                        "document_uri": body.get("document_uri"),
+                        "source_type": body.get("source_type"),
+                        "chunks": body.get("chunks"),
+                        "supersedes": body.get("supersedes"),
+                    }
+                )
+
+            # Recent derive events (distillations)
+            for r in c.execute(
+                "SELECT subject_root, body, ts FROM audit_events "
+                "WHERE event_type = 'derive' AND ts >= ? "
+                "ORDER BY ts DESC LIMIT ?",
+                (cutoff_ts, args.limit),
+            ).fetchall():
+                body = json.loads(r["body"]) if r["body"] else {}
+                derive_events.append(
+                    {
+                        "ts": r["ts"],
+                        "shard": sp.name,
+                        "core_root": r["subject_root"],
+                        "src_root": body.get("src_root"),
+                        "process_id": body.get("process_id"),
+                        "compression_ratio": body.get("compression_ratio"),
+                        "compression_depth": body.get("compression_depth"),
+                    }
+                )
+
+            # Recent falsifications
+            for r in c.execute(
+                "SELECT cache_key, state, reason, by_actor, at FROM falsifications "
+                "WHERE at >= ? ORDER BY at DESC LIMIT ?",
+                (cutoff_ts, args.limit),
+            ).fetchall():
+                falsifications.append(
+                    {
+                        "ts": r["at"],
+                        "shard": sp.name,
+                        "cache_key": r["cache_key"],
+                        "state": r["state"],
+                        "reason": r["reason"],
+                        "by_actor": r["by_actor"],
+                    }
+                )
+        finally:
+            c.close()
+
+    qa_records.sort(key=lambda x: -x["ts"])
+    ingest_events.sort(key=lambda x: -x["ts"])
+    derive_events.sort(key=lambda x: -x["ts"])
+    falsifications.sort(key=lambda x: -x["ts"])
+
+    print(
+        json.dumps(
+            {
+                "as_of": int(_time.time()),
+                "shards": [str(p) for p in shard_paths],
+                "corpus": corpus,
+                "recent_qa": qa_records[: args.limit],
+                "recent_ingests": ingest_events[: args.limit],
+                "recent_derives": derive_events[: args.limit],
+                "recent_falsifications": falsifications[: args.limit],
+            },
+            indent=2, ensure_ascii=False
+        )
+    )
+    return 0
+
+
+def _cmd_stats(args: argparse.Namespace) -> int:
+    """Show corpus statistics (document count, chunk count, index size)."""
+    conn = (
+        connect_query(args.db, shards_dir=args.global_shards_dir)
+        if args.global_shards_dir
+        else connect(args.db)
+    )
+    try:
+        result = stats(conn)
+    finally:
+        conn.close()
+    print(json.dumps(result, indent=2, ensure_ascii=False))
+    return 0
+
+
+def _check_audit_chain(conn: sqlite3.Connection) -> tuple[int, int]:
+    """Return (events_checked, breaks) for one audit chain in `conn`."""
+    import hashlib
+
+    rows = conn.execute(
+        "SELECT seq, event_hash, prev_event_hash, body FROM audit_events ORDER BY seq"
+    ).fetchall()
+    prev = None
+    breaks = 0
+    for r in rows:
+        h = hashlib.sha256()
+        if r["prev_event_hash"]:
+            h.update(bytes.fromhex(r["prev_event_hash"]))
+        h.update(r["body"].encode("utf-8"))
+        if h.hexdigest() != r["event_hash"]:
+            breaks += 1
+        if r["prev_event_hash"] != prev:
+            breaks += 1
+        prev = r["event_hash"]
+    return len(rows), breaks
+
+
+def _cmd_analyze(args: argparse.Namespace) -> int:
+    """Compression spectrum, depth distribution, audit chain integrity."""
+    from aborist.store import discover_shards
+
+    # In sharded mode, audit chains live per-shard (each shard has its own
+    # genesis -> latest). Check each independently and aggregate.
+    audit_summary: dict | None = None
+    if args.global_shards_dir:
+        per_shard_chain = []
+        total_events = 0
+        total_breaks = 0
+        for sp in discover_shards(args.global_shards_dir):
+            sc = connect(sp)
+            try:
+                ev, br = _check_audit_chain(sc)
+            finally:
+                sc.close()
+            per_shard_chain.append({"shard": sp.name, "events": ev, "breaks": br})
+            total_events += ev
+            total_breaks += br
+        audit_summary = {
+            "events": total_events,
+            "breaks": total_breaks,
+            "shards": per_shard_chain,
+        }
+
+    conn = (
+        connect_query(args.db, shards_dir=args.global_shards_dir)
+        if args.global_shards_dir
+        else connect(args.db)
+    )
+    try:
+        # Depth distribution.
+        depth = conn.execute(
+            "SELECT compression_depth, COUNT(*) AS n "
+            "FROM documents GROUP BY compression_depth ORDER BY 1"
+        ).fetchall()
+
+        # Per-process compression ratios.
+        procs = conn.execute(
+            "SELECT json_extract(body, '$.process_id') AS process_id, "
+            "       json_extract(body, '$.src_kind') AS src_kind, "
+            "       AVG(CAST(json_extract(body, '$.compression_ratio') AS REAL)) AS mean_ratio, "
+            "       MIN(CAST(json_extract(body, '$.compression_ratio') AS REAL)) AS min_ratio, "
+            "       MAX(CAST(json_extract(body, '$.compression_ratio') AS REAL)) AS max_ratio, "
+            "       COUNT(*) AS n_events "
+            "FROM audit_events WHERE event_type='derive' "
+            "GROUP BY process_id, src_kind"
+        ).fetchall()
+
+        # Source/kind crosstab.
+        kinds = conn.execute(
+            "SELECT source_type, kind, COUNT(*) AS n "
+            "FROM documents GROUP BY source_type, kind ORDER BY 3 DESC"
+        ).fetchall()
+
+        # Tier distribution.
+        tiers = conn.execute(
+            "SELECT tier, COUNT(*) AS n FROM chunks GROUP BY tier"
+        ).fetchall()
+
+        # Top inbound link targets (the 'gravity wells' of the corpus).
+        gravity = conn.execute(
+            "SELECT dst_uri, COUNT(*) AS inbound FROM edges "
+            "WHERE edge_type='wikilink' AND dst_uri != '' "
+            "GROUP BY dst_uri ORDER BY inbound DESC LIMIT ?",
+            (args.gravity_top,),
+        ).fetchall()
+
+        # Audit chain integrity (per-shard if sharded; single chain otherwise).
+        if audit_summary is None:
+            ev, br = _check_audit_chain(conn)
+            audit_summary = {"events": ev, "breaks": br}
+
+        report = {
+            "compression_depth_histogram": [
+                {"depth": r["compression_depth"], "count": r["n"]} for r in depth
+            ],
+            "distillers": [
+                {
+                    "process_id": r["process_id"],
+                    "src_kind": r["src_kind"],
+                    "n_events": r["n_events"],
+                    "compression_ratio": {
+                        "mean": (
+                            round(r["mean_ratio"], 4)
+                            if r["mean_ratio"] is not None
+                            else None
+                        ),
+                        "min": (
+                            round(r["min_ratio"], 4)
+                            if r["min_ratio"] is not None
+                            else None
+                        ),
+                        "max": (
+                            round(r["max_ratio"], 4)
+                            if r["max_ratio"] is not None
+                            else None
+                        ),
+                    },
+                }
+                for r in procs
+            ],
+            "documents_by_source_kind": [
+                {"source_type": r["source_type"], "kind": r["kind"], "count": r["n"]}
+                for r in kinds
+            ],
+            "chunks_by_tier": {r["tier"]: r["n"] for r in tiers},
+            "audit_chain": audit_summary,
+            "gravity_top_inbound": [
+                {"uri": r["dst_uri"], "inbound": r["inbound"]} for r in gravity
+            ],
+        }
+    finally:
+        conn.close()
+    print(json.dumps(report, indent=2, ensure_ascii=False))
+    return 0
+
+
+def _cmd_snapshot_create(args: argparse.Namespace) -> int:
+    """Compute snapshot_root over the read scope, persist into args.db.
+
+    Single-DB mode (--db only): read + write are the same connection;
+    delegate to the snapshot module's create_snapshot().
+
+    Cross-shard mode (--shards-dir + --db): read against the in-memory
+    UNION view to get the cluster-level Merkle root, then persist into
+    args.db (a dedicated snapshots store, conventionally
+    `~/.aborist/shards/snapshots.db`). The writer's own documents table
+    is irrelevant to the snapshot value — only the union scope counts.
+    """
+    import time as _time
+
+    from aborist.snapshot import compute_snapshot_root, create_snapshot
+
+    if args.global_shards_dir is None:
+        conn = connect(args.db)
+        try:
+            result = create_snapshot(
+                conn, reason=args.reason, parent_snapshot=args.parent,
+            )
+        finally:
+            conn.close()
+        print(json.dumps(result, indent=2, ensure_ascii=False))
+        return 0
+
+    # Cross-shard: compute against UNION, write to args.db.
+    read_conn = connect_query(args.db, shards_dir=args.global_shards_dir)
+    try:
+        snapshot_root, doc_count = compute_snapshot_root(read_conn)
+    finally:
+        read_conn.close()
+
+    write_conn = connect(args.db)
+    try:
+        parent = args.parent
+        if parent is None:
+            row = write_conn.execute(
+                "SELECT snapshot_root FROM snapshots ORDER BY taken_at DESC LIMIT 1"
+            ).fetchone()
+            if row is not None:
+                parent = row["snapshot_root"]
+
+        now = int(_time.time())
+        body = {
+            "snapshot_root": snapshot_root,
+            "doc_count": doc_count,
+            "parent_snapshot": parent,
+            "reason": args.reason,
+            "scope": "shards-union",
+        }
+        audit_event_hash = append_audit(
+            write_conn,
+            event_type="snapshot_create",
+            body=body,
+            subject_root=snapshot_root,
+            ts=now,
+        )
+        with transaction(write_conn):
+            write_conn.execute(
+                "INSERT OR IGNORE INTO snapshots "
+                "(snapshot_root, taken_at, audit_event_hash, doc_count, "
+                " parent_snapshot, reason) VALUES (?, ?, ?, ?, ?, ?)",
+                (
+                    snapshot_root,
+                    now,
+                    audit_event_hash,
+                    doc_count,
+                    parent,
+                    args.reason,
+                ),
+            )
+    finally:
+        write_conn.close()
+
+    print(
+        json.dumps(
+            {
+                "snapshot_root": snapshot_root,
+                "doc_count": doc_count,
+                "parent_snapshot": parent,
+                "audit_event_hash": audit_event_hash,
+                "taken_at": now,
+                "reason": args.reason,
+                "scope": "shards-union",
+            },
+            indent=2, ensure_ascii=False
+        )
+    )
+    return 0
+
+
+def _cmd_snapshot_list(args: argparse.Namespace) -> int:
+    """List named corpus snapshots (named roots)."""
+    from aborist.snapshot import list_snapshots
+
+    conn = connect(args.db)
+    try:
+        rows = list_snapshots(conn, limit=args.limit)
+    finally:
+        conn.close()
+    print(json.dumps(rows, indent=2, ensure_ascii=False))
+    return 0
+
+
+def _cmd_snapshot_verify(args: argparse.Namespace) -> int:
+    """Verify snapshot integrity (round-trip Merkle proofs)."""
+    from aborist.snapshot import verify_snapshot
+
+    conn = (
+        connect_query(args.db, shards_dir=args.global_shards_dir)
+        if args.global_shards_dir
+        else connect(args.db)
+    )
+    try:
+        result = verify_snapshot(conn, args.snapshot_root)
+    finally:
+        conn.close()
+    print(json.dumps(result, indent=2, ensure_ascii=False))
+    return 0 if result["matches"] else 1
+
+
+def _cmd_snapshot_diff(args: argparse.Namespace) -> int:
+    from aborist.snapshot import diff_against_current
+
+    conn = (
+        connect_query(args.db, shards_dir=args.global_shards_dir)
+        if args.global_shards_dir
+        else connect(args.db)
+    )
+    try:
+        result = diff_against_current(conn, args.snapshot_root)
+    finally:
+        conn.close()
+    print(json.dumps(result, indent=2, ensure_ascii=False))
+    return 0
+
+
+def _cmd_mesh_status(args: argparse.Namespace) -> int:
+    """Show mesh status (members, epochs, identity)."""
+    from aborist.mesh import current_epoch, is_enabled, load_identity
+    from aborist.mesh.state import roster_at
+
+    conn = connect(args.db)
+    try:
+        ident = load_identity(conn)
+        epoch = current_epoch(conn)
+        roster = roster_at(conn, epoch) if epoch is not None else []
+        out = {
+            "enabled": is_enabled(conn),
+            "identity": (
+                {
+                    "member_id": ident.member_id,
+                    "group_name": ident.group_name,
+                    "sign_pub_hex": ident.sign_pub.hex(),
+                    "dh_pub_hex": ident.dh_pub.hex(),
+                    "created_at": ident.created_at,
+                }
+                if ident
+                else None
+            ),
+            "current_epoch": epoch,
+            "roster": [
+                {
+                    "member_id": m.member_id,
+                    "role": m.role,
+                    "sign_pub_hex": m.sign_pub.hex(),
+                    "dh_pub_hex": m.dh_pub.hex(),
+                }
+                for m in roster
+            ],
+        }
+    finally:
+        conn.close()
+    print(json.dumps(out, indent=2, ensure_ascii=False))
+    return 0
+
+
+def _cmd_mesh_init(args: argparse.Namespace) -> int:
+    from aborist.mesh import init_identity
+
+    conn = connect(args.db)
+    try:
+        ident = init_identity(conn, group_name=args.group, member_id=args.member_id)
+    except RuntimeError as e:
+        print(f"error: {e}", file=sys.stderr)
+        conn.close()
+        return 2
+    finally:
+        conn.close()
+    print(
+        json.dumps(
+            {
+                "member_id": ident.member_id,
+                "group_name": ident.group_name,
+                "sign_pub_hex": ident.sign_pub.hex(),
+                "dh_pub_hex": ident.dh_pub.hex(),
+                "note": "share sign_pub_hex + dh_pub_hex with the founder of any group "
+                "you want to join. Run 'mesh enable' to flip the gating flag on.",
+            },
+            indent=2, ensure_ascii=False
+        )
+    )
+    return 0
+
+
+def _cmd_mesh_enable(args: argparse.Namespace) -> int:
+    from aborist.mesh import set_enabled
+
+    conn = connect(args.db)
+    try:
+        set_enabled(conn, True)
+    finally:
+        conn.close()
+    print(json.dumps({"enabled": True}, indent=2, ensure_ascii=False))
+    return 0
+
+
+def _cmd_mesh_disable(args: argparse.Namespace) -> int:
+    from aborist.mesh import set_enabled
+
+    conn = connect(args.db)
+    try:
+        set_enabled(conn, False)
+    finally:
+        conn.close()
+    print(json.dumps({"enabled": False}, indent=2, ensure_ascii=False))
+    return 0
+
+
+def _cmd_mesh_members(args: argparse.Namespace) -> int:
+    from aborist.mesh import current_epoch
+    from aborist.mesh.state import roster_at
+
+    conn = connect(args.db)
+    try:
+        epoch = current_epoch(conn)
+        if epoch is None:
+            print(json.dumps({"error": "mesh not initialized"}, indent=2, ensure_ascii=False))
+            return 2
+        roster = roster_at(conn, epoch)
+    finally:
+        conn.close()
+    print(
+        json.dumps(
+            {
+                "epoch": epoch,
+                "members": [
+                    {
+                        "member_id": m.member_id,
+                        "role": m.role,
+                        "sign_pub_hex": m.sign_pub.hex(),
+                        "dh_pub_hex": m.dh_pub.hex(),
+                    }
+                    for m in roster
+                ],
+            },
+            indent=2, ensure_ascii=False
+        )
+    )
+    return 0
+
+
+def _cmd_mesh_add(args: argparse.Namespace) -> int:
+    from aborist.mesh.members import add_member
+
+    try:
+        sign_pub = bytes.fromhex(args.sign_pub)
+        dh_pub = bytes.fromhex(args.dh_pub)
+    except ValueError:
+        print("error: --sign-pub and --dh-pub must be hex-encoded 32-byte keys", file=sys.stderr)
+        return 2
+    if len(sign_pub) != 32 or len(dh_pub) != 32:
+        print("error: keys must decode to exactly 32 bytes", file=sys.stderr)
+        return 2
+
+    conn = connect(args.db)
+    try:
+        epoch = add_member(
+            conn,
+            member_id=args.member_id,
+            sign_pub=sign_pub,
+            dh_pub=dh_pub,
+            role=args.role,
+        )
+    except (PermissionError, RuntimeError, ValueError) as e:
+        print(f"error: {e}", file=sys.stderr)
+        return 2
+    finally:
+        conn.close()
+    print(json.dumps({"new_epoch": epoch, "added": args.member_id}, indent=2, ensure_ascii=False))
+    return 0
+
+
+def _cmd_mesh_kick(args: argparse.Namespace) -> int:
+    from aborist.mesh.members import kick_member
+
+    conn = connect(args.db)
+    try:
+        epoch = kick_member(conn, member_id=args.member_id, reason=args.reason)
+    except (PermissionError, RuntimeError, ValueError) as e:
+        print(f"error: {e}", file=sys.stderr)
+        return 2
+    finally:
+        conn.close()
+    print(
+        json.dumps(
+            {"new_epoch": epoch, "kicked": args.member_id, "reason": args.reason},
+            indent=2, ensure_ascii=False
+        )
+    )
+    return 0
+
+
+def _cmd_mesh_rotate(args: argparse.Namespace) -> int:
+    from aborist.mesh.members import scheduled_rotate
+
+    conn = connect(args.db)
+    try:
+        epoch = scheduled_rotate(conn, reason=args.reason)
+    except (PermissionError, RuntimeError) as e:
+        print(f"error: {e}", file=sys.stderr)
+        return 2
+    finally:
+        conn.close()
+    print(json.dumps({"new_epoch": epoch, "reason": args.reason}, indent=2, ensure_ascii=False))
+    return 0
+
+
+def _cmd_mesh_serve(args: argparse.Namespace) -> int:
+    """Run the HTTP gossip server until SIGINT."""
+    from aborist.mesh import is_enabled, load_identity
+    from aborist.mesh.wire import MeshWireServer
+
+    conn = connect(args.db)
+    try:
+        if load_identity(conn) is None:
+            print("error: mesh not initialized; run 'aborist mesh init' first", file=sys.stderr)
+            return 2
+        if not is_enabled(conn):
+            print("error: mesh.enabled is off; run 'aborist mesh enable' first", file=sys.stderr)
+            return 2
+    finally:
+        conn.close()
+
+    srv = MeshWireServer(args.db, host=args.host, port=args.port)
+    print(json.dumps({"status": "serving", "url": srv.url, "db": str(args.db)}, ensure_ascii=False))
+    sys.stdout.flush()
+    try:
+        srv.serve()
+    except KeyboardInterrupt:
+        print(json.dumps({"status": "stopped", "reason": "SIGINT"}, ensure_ascii=False))
+    finally:
+        srv.stop()
+    return 0
+
+
+def _cmd_mesh_sync(args: argparse.Namespace) -> int:
+    """Push local roots + falsifications to a peer.
+
+    Two pushes happen by default (unless ``--no-roots`` /
+    ``--no-falsifications`` opts one out):
+
+    1. **ANNOUNCE_ROOT** for the most-recent ``--limit`` documents
+       older than the kindergarten window. Receivers dedup by
+       ``documents.document_root``.
+    2. **ANNOUNCE_FALSIFICATION** for the most-recent ``--limit``
+       falsifications older than the kindergarten window. Burns
+       deliberately NOT propagated — local kindergarten cleanup.
+
+    **Kindergarten window.** Records younger than
+    ``--kindergarten-seconds`` (default 3600 = 1 hour) are NOT
+    broadcast. Gives the operator time to inspect a fresh ingest or
+    falsification & burn it before the network sees it. Override per
+    invocation; ``--kindergarten-seconds 0`` broadcasts everything
+    (cron-friendly opt-out for operators who prefer immediate
+    propagation). The window is sender-side discipline; receivers
+    don't enforce it because they have no view into when the sender
+    created the record.
+
+    Receivers verify the Ed25519 signature, run per-peer chain-of-
+    claims fork detection, then write one ``mesh_received`` audit
+    event per accepted envelope. Duplicate broadcasts produce
+    duplicate audit-log entries on the receiver but no state
+    corruption.
+    """
+    import time as _time
+
+    from aborist.mesh import is_enabled, load_identity
+    from aborist.mesh.wire import MeshWireClient
+
+    now_ts = int(_time.time())
+    cutoff_ts = now_ts - max(0, args.kindergarten_seconds)
+
+    conn = connect(args.db)
+    try:
+        if load_identity(conn) is None:
+            print("error: mesh not initialized", file=sys.stderr)
+            return 2
+        if not is_enabled(conn):
+            print("error: mesh.enabled is off", file=sys.stderr)
+            return 2
+        # Total counts inform skipped-by-kindergarten reporting.
+        total_roots = 0
+        total_falsifications = 0
+        root_rows: list = []
+        falsification_rows: list = []
+        if not args.no_roots:
+            total_roots = conn.execute(
+                "SELECT COUNT(*) FROM documents"
+            ).fetchone()[0]
+            root_rows = conn.execute(
+                "SELECT document_root, document_uri, chunking_version, "
+                " canonicalization_version, schema_version "
+                "FROM documents WHERE ingest_ts <= ? "
+                "ORDER BY rowid DESC LIMIT ?",
+                (cutoff_ts, args.limit),
+            ).fetchall()
+        if not args.no_falsifications:
+            total_falsifications = conn.execute(
+                "SELECT COUNT(*) FROM falsifications"
+            ).fetchone()[0]
+            falsification_rows = conn.execute(
+                "SELECT cache_key, reason FROM falsifications "
+                "WHERE at <= ? "
+                "ORDER BY at DESC LIMIT ?",
+                (cutoff_ts, args.limit),
+            ).fetchall()
+    finally:
+        conn.close()
+
+    # Skipped-by-kindergarten = (rows younger than cutoff that would have
+    # been in the most-recent --limit) — approximated by total minus what
+    # we pulled, capped at limit.
+    fresh_roots_held = max(
+        0,
+        min(total_roots, args.limit) - len(root_rows),
+    ) if not args.no_roots else 0
+    fresh_falsifications_held = max(
+        0,
+        min(total_falsifications, args.limit) - len(falsification_rows),
+    ) if not args.no_falsifications else 0
+
+    sent_roots: list[dict] = []
+    sent_falsifications: list[dict] = []
+    errors: list[dict] = []
+    with MeshWireClient(args.db, args.peer) as client:
+        try:
+            peer_info = client.info()
+        except Exception as e:
+            print(json.dumps({"status": "peer_unreachable", "peer": args.peer, "error": str(e)}, indent=2, ensure_ascii=False))
+            return 2
+        for r in root_rows:
+            try:
+                resp = client.announce_root(
+                    document_root=r["document_root"],
+                    source_uri=r["document_uri"],
+                    chunking_version=r["chunking_version"],
+                    canonicalization_version=r["canonicalization_version"],
+                    schema_version=r["schema_version"],
+                )
+                sent_roots.append({"document_root": r["document_root"], "ack": resp})
+            except Exception as e:
+                errors.append({"document_root": r["document_root"], "error": str(e)})
+        for f in falsification_rows:
+            try:
+                resp = client.announce_falsification(
+                    cache_key=f["cache_key"],
+                    reason=f["reason"] or "",
+                )
+                sent_falsifications.append({"cache_key": f["cache_key"], "ack": resp})
+            except Exception as e:
+                errors.append({"cache_key": f["cache_key"], "error": str(e)})
+
+    print(json.dumps({
+        "status": "synced",
+        "peer": args.peer,
+        "peer_member_id": peer_info.get("member_id"),
+        "peer_epoch": peer_info.get("current_epoch"),
+        "kindergarten_seconds": args.kindergarten_seconds,
+        "announced_roots": len(sent_roots),
+        "announced_falsifications": len(sent_falsifications),
+        "kindergarten_held_roots": fresh_roots_held,
+        "kindergarten_held_falsifications": fresh_falsifications_held,
+        "errors": len(errors),
+        "sent_roots": sent_roots[: args.verbose],
+        "sent_falsifications": sent_falsifications[: args.verbose],
+        "error_samples": errors[:5],
+    }, indent=2, ensure_ascii=False))
+    return 0 if not errors else 1
+
+
+def _cmd_mesh_pull(args: argparse.Namespace) -> int:
+    """Pull a single document body from a peer by document_root.
+
+    Closes the request half of the gossip loop. The wire client already
+    verifies the peer's signature and re-derives the Merkle root from the
+    delivered leaves before returning. This verb then re-ingests the
+    delivered text through the standard ingest path so chunking_version /
+    canonicalization_version stay consistent — and rejects with rc=2 if
+    the local re-ingest produces a different document_root than requested.
+    """
+    from aborist.document import Document
+    from aborist.ingest import ingest_source
+    from aborist.mesh import is_enabled, load_identity
+    from aborist.mesh.wire import MeshWireClient
+
+    conn = connect(args.db)
+    try:
+        if load_identity(conn) is None:
+            print("error: mesh not initialized", file=sys.stderr)
+            return 2
+        if not is_enabled(conn):
+            print("error: mesh.enabled is off", file=sys.stderr)
+            return 2
+        already = conn.execute(
+            "SELECT document_root, document_uri FROM documents WHERE document_root=?",
+            (args.root,),
+        ).fetchone()
+    finally:
+        conn.close()
+
+    if already is not None:
+        print(json.dumps({
+            "status": "already_present",
+            "document_root": already["document_root"],
+            "document_uri": already["document_uri"],
+            "shard": str(args.db),
+        }, indent=2, ensure_ascii=False))
+        return 0
+
+    try:
+        with MeshWireClient(args.db, args.peer) as client:
+            body = client.request_body(root=args.root)
+    except Exception as e:
+        print(f"error: pull failed: {e}", file=sys.stderr)
+        return 2
+
+    delivered_uri = body.get("document_uri") or ""
+    delivered_text = body.get("text") or ""
+
+    class _PulledSource:
+        source_type = "mesh_pull"
+
+        def iter_documents(self):
+            yield Document(
+                uri=delivered_uri,
+                content=delivered_text,
+                source_type="mesh_pull",
+                title=None,
+            )
+
+    conn = connect(args.db)
+    try:
+        ingest_source(conn, _PulledSource())
+        row = conn.execute(
+            "SELECT document_root FROM documents WHERE document_root=?",
+            (args.root,),
+        ).fetchone()
+        if row is None:
+            # Re-ingest produced a different root than the peer claimed.
+            # The pulled text doesn't reproduce the requested root under
+            # this peer's chunker/canonicalization. Fail closed.
+            actual = conn.execute(
+                "SELECT document_root FROM documents WHERE document_uri=? "
+                "ORDER BY ingest_ts DESC LIMIT 1",
+                (delivered_uri,),
+            ).fetchone()
+            actual_root = actual["document_root"] if actual else None
+            print(
+                "error: local re-ingest produced "
+                f"{actual_root!r}, expected {args.root!r}",
+                file=sys.stderr,
+            )
+            return 2
+        with transaction(conn):
+            event_hash = append_audit(
+                conn,
+                event_type="mesh_pulled",
+                body={
+                    "document_root": args.root,
+                    "document_uri": delivered_uri,
+                    "peer": args.peer,
+                },
+                subject_root=args.root,
+            )
+    finally:
+        conn.close()
+
+    print(json.dumps({
+        "status": "pulled",
+        "document_root": args.root,
+        "document_uri": delivered_uri,
+        "shard": str(args.db),
+        "audit_event_hash": event_hash,
+    }, indent=2, ensure_ascii=False))
+    return 0
+
+
+def _cmd_crawl(args: argparse.Namespace) -> int:
+    """BFS-discover same-domain URLs from a seed and optionally ingest.
+
+    Two modes:
+
+    - default: print discovered URLs to stdout (one per line). Compose
+      with `aborist ingest --source html` if you want to feed them
+      through the standard ingest path manually.
+    - ``--ingest``: run the discovery + ingest path in a single shot,
+      capturing ETag + Last-Modified per page so a future
+      ``crawler recrawl-check`` can do conditional HEADs.
+    """
+    try:
+        from aborist.sources.crawler.bridge import crawl_seed, ingest_crawled
+    except ImportError as e:
+        print(f"error: {e}", file=sys.stderr)
+        return 2
+
+    from aborist.progress import Progress
+
+    cap = "no cap" if args.max_pages == 0 else f"max {args.max_pages}"
+    speed = "fast" if args.fast else "polite"
+    print(
+        f"  crawl: seed={args.seed_url} depth={args.depth} {cap} ({speed})",
+        file=sys.stderr,
+        flush=True,
+    )
+    crawl_progress = Progress(prefix="crawl ")
+    urls = crawl_seed(
+        args.seed_url,
+        max_depth=args.depth,
+        max_pages=args.max_pages,
+        progress=crawl_progress,
+        fast=args.fast,
+    )
+    print(
+        f"  crawl: discovery done — {len(urls)} URLs",
+        file=sys.stderr,
+        flush=True,
+    )
+
+    if not args.ingest:
+        for u in urls:
+            print(u)
+        return 0
+
+    print(
+        f"  ingest: starting on {len(urls)} URLs",
+        file=sys.stderr,
+        flush=True,
+    )
+    ingest_progress = Progress(prefix="ingest ", total_estimate=len(urls))
+    conn = connect(args.db)
+    try:
+        result = ingest_crawled(conn, urls, progress=ingest_progress)
+    finally:
+        conn.close()
+    print(json.dumps(
+        {
+            "status": "crawled_and_ingested",
+            "seed": args.seed_url,
+            "depth": args.depth,
+            "max_pages": args.max_pages,
+            "discovered": len(urls),
+            **result,
+        },
+        indent=2, ensure_ascii=False
+    ))
+    return 0
+
+
+def _cmd_crawler_recrawl_check(args: argparse.Namespace) -> int:
+    """Send conditional HEAD requests for ingested documents.
+
+    Reports each as fresh (304), stale (200, body changed), gone
+    (404/410), or unreachable. Updates `document_http_meta.last_status`
+    and `last_checked_at` so consecutive runs target the oldest checks
+    first.
+    """
+    try:
+        from aborist.sources.crawler.bridge import recrawl_check
+    except ImportError as e:
+        print(f"error: {e}", file=sys.stderr)
+        return 2
+
+    conn = connect(args.db)
+    try:
+        result = recrawl_check(
+            conn,
+            domain=args.domain,
+            limit=args.limit,
+        )
+    finally:
+        conn.close()
+    print(json.dumps(result, indent=2, ensure_ascii=False))
+    return 0
+
+
+
+[docs] +def build_parser() -> argparse.ArgumentParser: + p = argparse.ArgumentParser( + prog="aborist", + description="An arborist for trees and forests of cross-linked information.", + ) + p.add_argument("--version", action="version", version=f"aborist {__version__}") + p.add_argument( + "--db", + type=Path, + default=DEFAULT_DB_PATH, + help=f"path to aborist SQLite db (default: {DEFAULT_DB_PATH})", + ) + p.add_argument( + "--shards-dir", + dest="global_shards_dir", + default=None, + help=( + "for read commands: attach all shards in this directory and " + "expose them as UNION views over the standard tables" + ), + ) + sub = p.add_subparsers(dest="cmd", required=True) + + ingest = sub.add_parser("ingest", help="ingest documents from a source") + ingest.add_argument( + "--source", + required=True, + choices=[ + "wikipedia_cur", + "wikipedia_old", + "wikipedia_xml", + "wikipedia_xml_history", + "wikipedia_abstract", + "html", + "grok_export", + "grok_media", + "git_repo", + "hg_repo", + "providence", + ], + help="source type", + ) + ingest.add_argument( + "--kindergarten-seconds", + type=int, + default=None, + help=( + "(providence source only) records younger than this many " + "seconds stay opaque to ingestion — fresh thoughts cool " + "before they become substrate. Default 3600s (1h)." + ), + ) + ingest.add_argument( + "--path", + help=( + "path to dump file (wikipedia) or to xAI export root / " + "prod-grok-backend.json (grok_export, grok_media)" + ), + ) + ingest.add_argument( + "--url", action="append", help="URL to ingest (html source; repeatable)" + ) + ingest.add_argument( + "--urls-from", + dest="urls_from", + help="file with one URL per line (html source)", + ) + ingest.add_argument( + "--no-robots", + dest="no_robots", + action="store_true", + help="do not consult robots.txt (use only for explicitly authorized sites)", + ) + ingest.add_argument( + "--chunker", default=None, help="chunker name (default: tok-512-v1)" + ) + ingest.add_argument( + "--limit", type=int, default=None, help="cap number of documents" + ) + ingest.add_argument( + "--batch-size", + dest="batch_size", + type=int, + default=200, + help="documents per SQLite transaction (default 200)", + ) + ingest.add_argument( + "--shard", + default=None, + help=( + "rank/total — yield only every N-th doc for parallel ingest. " + "spawn N processes, each with --shard 0/N, 1/N, ... they " + "parallelize parser CPU and serialize writes via WAL" + ), + ) + ingest.add_argument( + "--shards-dir", + dest="shards_dir", + default=None, + help=( + "directory for attach-forever sharding. With --shard rank/total, " + "writes to shards-dir/<rank>.db instead of --db, removing the " + "WAL writer-lock contention entirely. Reads via aborist --shards-dir" + ), + ) + ingest.add_argument( + "--resume", + action="store_true", + help=( + "rsync-style: read each source's last high-water mark from this " + "DB's meta table and skip rows whose id is <= it. Safe to kill " + "and restart at any time" + ), + ) + ingest.add_argument( + "--quiet", + action="store_true", + help="suppress periodic stderr progress output", + ) + ingest.add_argument( + "--progress-interval", + dest="progress_interval", + type=float, + default=2.0, + help="seconds between stderr progress lines (default 2.0)", + ) + ingest.add_argument( + "--total-estimate", + dest="total_estimate", + type=int, + default=None, + help=( + "estimated total docs the source will yield. enables percent " + "+ ETA in progress output" + ), + ) + ingest.set_defaults(func=_cmd_ingest) + + search = sub.add_parser("search", help="keyword search (UNGROUNDED audit mode)") + search.add_argument("query", help="query string") + search.add_argument("--limit", type=int, default=20) + search.add_argument("--json", action="store_true", help="output JSON") + search.set_defaults(func=_cmd_search) + + verify = sub.add_parser( + "verify", help="round-trip Merkle proofs for N random documents" + ) + verify.add_argument("-n", type=int, default=10) + verify.set_defaults(func=_cmd_verify) + + distill = sub.add_parser( + "distill", + help="compress docs into Merkle-signed cores (surface->core or core->core)", + ) + distill.add_argument( + "--process", default="first-sentence-v1", help="distiller name" + ) + distill.add_argument( + "--kind", + choices=["surface", "core"], + default="surface", + help="source kind to scan; 'core' runs recursive distillation", + ) + distill.add_argument( + "--source-type", + dest="source_type", + default=None, + help="restrict to one source_type", + ) + distill.add_argument( + "--chunker", default=None, help="chunker for the core doc" + ) + distill.add_argument( + "--limit", type=int, default=None, help="cap number of docs scanned" + ) + distill.add_argument( + "--batch-size", + dest="batch_size", + type=int, + default=200, + help="cores written per SQLite transaction (default 200)", + ) + distill.set_defaults(func=_cmd_distill) + + ask_cmd = sub.add_parser( + "ask", + help="answer a question about a document (cache-first, STRICT)", + ) + ask_cmd.add_argument( + "--document-root", + dest="document_root", + required=True, + help="document_root to ask about", + ) + ask_cmd.add_argument( + "--question", required=True, help="question text" + ) + ask_cmd.add_argument( + "--model", + default=None, + help="model_id (default $ABORIST_LLM_MODEL or hermes-3)", + ) + ask_cmd.add_argument( + "--endpoint", + default=None, + help="OpenAI-compatible base URL (default $ABORIST_LLM_ENDPOINT)", + ) + ask_cmd.add_argument( + "--dry-run", + dest="dry_run", + action="store_true", + help="use StubClient — no network call", + ) + ask_cmd.add_argument( + "--answer-mode", dest="answer_mode", default=None, + choices=["quote", "claim_lattice_pointer", "claim_lattice"], + help=( + "answer schema. See `query --answer-mode` for full semantics. " + "Default 'quote'; 'claim_lattice_pointer' enables quote-by-pointer; " + "'claim_lattice' is the JSON variant (vLLM guided_json + lenient " + "pre-parser; pairs with grammar-constrained inference)." + ), + ) + ask_cmd.set_defaults(func=_cmd_ask) + + query_cmd = sub.add_parser( + "query", + help="multi-source RAG: question -> top-K corpus docs -> Hermes -> cache", + ) + query_cmd.add_argument("question", help="the question to ask") + query_cmd.add_argument( + "--top-k", dest="top_k", type=int, default=8, + help="max distinct source documents in context (default 8)", + ) + query_cmd.add_argument( + "--over-fetch", dest="over_fetch", type=int, default=32, + help="FTS5 hits to fetch per shard before dedup (default 32)", + ) + query_cmd.add_argument( + "--max-context-chars", dest="max_context_chars", type=int, default=None, + help=( + "cap on assembled context bytes. When omitted, falls back to " + "the per-mode default in DEFAULT_QUERY_POLICY['max_context_chars_by_mode'] " + "(quote=24000, claim_lattice_pointer=24000, claim_lattice=48000). " + "Sprint 1b 2026-05-02 — peaks measured per mode." + ), + ) + query_cmd.add_argument( + "--question-dedup", dest="question_dedup", default=None, + choices=["strict", "equivalence_class"], + help=( + "write-time question canonicalization. 'equivalence_class' " + "(default) collapses articles + trailing-punct + case so " + "variants share cache_keys. 'strict' keeps every variant " + "distinct (audit-grade)." + ), + ) + query_cmd.add_argument( + "--fidelity", dest="fidelity", default=None, + choices=["strict", "equivalence_class"], + help=( + "lookup tolerance. 'equivalence_class' (default) tries the " + "primary cache_key then falls back to the alternate dedup " + "mode's cache_key. 'strict' refuses fallback." + ), + ) + query_cmd.add_argument( + "--qa-db", dest="qa_db", default=None, + help=( + "providence_cache target DB. default: <shards-dir>/qa.db, or " + "~/.aborist/qa.db when no shards-dir" + ), + ) + query_cmd.add_argument( + "--model", default=None, + help="model_id (default $ABORIST_LLM_MODEL or hermes-3)", + ) + query_cmd.add_argument( + "--endpoint", default=None, + help="OpenAI-compatible base URL (default $ABORIST_LLM_ENDPOINT)", + ) + query_cmd.add_argument( + "--dry-run", dest="dry_run", action="store_true", + help="use StubClient — assembles context but skips the LLM call", + ) + query_cmd.add_argument( + "--json", action="store_true", + help="emit the raw record as indented JSON (default: human render)", + ) + query_cmd.add_argument( + "--burn", action="store_true", + help=( + "delete the matching live providence_cache row BEFORE lookup, " + "forcing a fresh inference. Test-ergonomic — see new behavior " + "without finding cache_keys by hand. Writes a providence_burn " + "audit event." + ), + ) + query_cmd.add_argument( + "--repair", action="store_true", + help=( + "enable mechanical repair after first verify (off by " + "default). When the verdict is HYBRID/UNGROUNDED, applies " + "synthetic_elision split, trailing_artifact trim, and " + "no_overlap drop deterministically; persists the repaired " + "answer with a providence_repair audit event." + ), + ) + query_cmd.add_argument( + "--repair-reprompts", dest="repair_reprompts", type=int, default=0, + help=( + "max LLM re-prompt iterations after mechanical repair " + "(default 0 = no re-prompt). Each iteration sends a feedback " + "turn naming failed quotes; the model is asked to rewrite " + "using only verbatim citations. Requires --repair." + ), + ) + query_cmd.add_argument( + "--answer-mode", dest="answer_mode", default=None, + choices=["quote", "claim_lattice_pointer", "claim_lattice"], + help=( + "answer schema. 'quote' (default): model writes prose with " + "verbatim quote spans inline. 'claim_lattice_pointer' (G0 " + "/ CTI quote-by-pointer): runtime builds a labeled evidence " + "map (E1, E2, …); model writes pointer-line prose ('Claim. " + "[E12]'); renderer interpolates literal spans. Synthetic-" + "elision-by-construction-impossible. No repair loop " + "(one-shot discipline). 'claim_lattice' is the JSON variant " + "(vLLM guided_json + lenient pre-parser; pairs with grammar-" + "constrained inference like Qwen 3.6 reasoner / Claude / GPT-4)." + ), + ) + query_cmd.add_argument( + "--retrieval-keywords", dest="retrieval_keywords", default=None, + help=( + "operator-supplied keywords appended to the question for " + "FTS5 retrieval ONLY — never sent to the LLM, never enters " + "cache_key, never reaches the verifier. Use to narrow " + "OR-mode retrieval on long discursive questions whose " + "content tokens get diluted by template phrasing. Example: " + "make query Q='what tech may enable one person to " + "reconstruct another person's thoughts...' " + "K='transcranial knowledge acquisition'. Pair with --burn " + "to force fresh inference (keywords are session-only and " + "cache-hits ignore them)." + ), + ) + # Ticket #000008 Phase 4 — quantifier-guard CLI flags. Each + # corresponds to a level of the §10.11.2 disable hierarchy. + query_cmd.add_argument( + "--no-quantifier-guard", + dest="no_quantifier_guard", action="store_true", + help=( + "Disable the broad-quantifier preflight guard for this " + "call. Overrides quantifier_guard_enabled in policy. " + "Bench-side telemetry (quantifier_intensity, etc.) goes " + "to None for the row. Use when the guard misclassifies." + ), + ) + query_cmd.add_argument( + "--allow-broad", + dest="allow_broad", action="store_true", + help=( + "Emergent-search mode: keep the classifier on (telemetry " + "stays useful) but don't apply caps. For broad questions " + "where the operator wants exploratory enumeration, not " + "grounded completeness." + ), + ) + query_cmd.add_argument( + "--reject-broad", + dest="reject_broad", action="store_true", + help=( + "Strict mode: when intensity is ALL/COMPREHENSIVE/" + "OPEN_REQUEST AND scope_bound_hint is unbounded, return " + "UNGROUNDED before the LLM call with a " + "BROAD_QUANTIFIER_REJECTED violation. Saves ~10-15s on " + "rejected runs. Bounded universals (e.g. all members of " + "the Beatles) are NOT rejected." + ), + ) + query_cmd.add_argument( + "--apply-quantifier-caps", + dest="apply_quantifier_caps", action="store_true", + help=( + "Flip the dry-run gate per-call. By default Phase 2 " + "lands with quantifier_guard_apply_caps=False so the " + "cap is reported on the result but not applied to the " + "verifier. This flag enables actual cap enforcement " + "for one call. Use after dry-run bench review confirms " + "the classifier output across the question set." + ), + ) + # Ticket #000010 — meta-cognition CLI flags. + query_cmd.add_argument( + "--no-preflight", + dest="no_preflight", action="store_true", + help=( + "Disable the meta-cognition preflight guard for this " + "call. Skips temporal / contradiction / false-premise / " + "out-of-corpus detectors. The QuestionState surfaces a " + "stub with empty logical_statuses so bench rows stay " + "column-aligned." + ), + ) + query_cmd.add_argument( + "--block-on-contradiction", + dest="block_on_contradiction", action="store_true", + help=( + "Hard-block on lexical contradictions (default: label-" + "only). Strict mode: questions like 'which unmarried " + "spouse is X married to' return PREFLIGHT_BLOCKED." + ), + ) + query_cmd.add_argument( + "--soft-preflight", + dest="soft_preflight", action="store_true", + help=( + "Ticket #000011 — opt-in to the model-assisted soft " + "preflight sidecar. Adds one short LLM round-trip " + "(~200ms median) before the main answer call; the model " + "classifies the question shape and returns a SOFT_* " + "advisory hint that surfaces as `· soft: <label>` on " + "the audit-line tail. NEVER enters the verifier proof " + "path; cannot create PREFLIGHT_OK or PREFLIGHT_BLOCKED." + ), + ) + query_cmd.set_defaults(func=_cmd_query) + + inspect_cmd = sub.add_parser( + "inspect", + help=( + "sidecar diagnostic for a providence_cache record — pulls " + "source chunks and classifies each unverified span " + "(paraphrase / trailing_artifact / interior_elision / " + "synthetic_elision_inside_quote / " + "no_overlap). Read-only, " + "no audit events, no v9.8 field changes." + ), + ) + inspect_cmd.add_argument( + "--cache-key", dest="cache_key", required=True, + help="64-char hex cache_key of the providence record to inspect", + ) + inspect_cmd.add_argument( + "--qa-db", dest="qa_db", default=None, + help="path to qa.db (default: <shards>/qa.db or ~/.aborist/qa.db)", + ) + inspect_cmd.add_argument( + "--json", action="store_true", + help="emit raw diagnosis as JSON (default: human render)", + ) + inspect_cmd.set_defaults(func=_cmd_inspect) + + prov_cmd = sub.add_parser( + "providence", + help="list or falsify providence_cache records", + ) + prov_cmd.add_argument("--document-uri", dest="document_uri", default=None) + prov_cmd.add_argument("--source-root", dest="source_root", default=None) + prov_cmd.add_argument("--limit", type=int, default=20) + prov_cmd.add_argument( + "--falsify", + default=None, + metavar="CACHE_KEY", + help=( + "mark a providence_cache record as failed/stale/quarantined. " + "Lookups will skip it. Audit chain records the act" + ), + ) + prov_cmd.add_argument( + "--state", + default="failed", + choices=["failed", "stale", "quarantined"], + help="falsification state to set (default: failed)", + ) + prov_cmd.add_argument( + "--reason", + default=None, + help="reason text stored in falsifications log", + ) + prov_cmd.add_argument( + "--by-actor", + dest="by_actor", + default=None, + help="who is falsifying (default: $USER)", + ) + prov_cmd.add_argument( + "--show-preflight", + dest="show_preflight", + default=None, + metavar="CACHE_KEY_PREFIX", + help=( + "Pull the preflight stage payload from a row's " + "run_dag_blob. Match by 12-char prefix. Renders the " + "preflight stage hash + run-DAG stage list. Operator " + "tool for inspecting the policy state that governed a " + "cached row (#000009 §7.2)." + ), + ) + prov_cmd.set_defaults(func=_cmd_providence) + + burn_cmd = sub.add_parser( + "burn", + help=( + "delete a leaf with no children — providence_cache, document, " + "or core (kindergarten use; falsify/evict are audit-preserving)" + ), + ) + burn_cmd.add_argument( + "--kind", + choices=("providence", "document", "core"), + default="providence", + help="leaf kind to burn (default: providence — backwards-compatible)", + ) + burn_cmd.add_argument( + "--cache-key", + dest="cache_key", + default=None, + help="cache_key (hex) of the providence record to burn (kind=providence)", + ) + burn_cmd.add_argument( + "--root", + dest="root", + default=None, + help="document_root (hex) of the document/core to burn (kind=document|core)", + ) + burn_cmd.add_argument( + "--reason", + default=None, + help="reason text recorded in the burn audit event", + ) + burn_cmd.add_argument( + "--by-actor", + dest="by_actor", + default=None, + help="who is burning (default: $USER)", + ) + burn_cmd.add_argument( + "--force", + action="store_true", + help="burn even if children exist; not recommended", + ) + burn_cmd.set_defaults(func=_cmd_burn) + + burn_kg_cmd = sub.add_parser( + "burn-kindergarten", + help=( + "burn every providence_cache record younger than the " + "kindergarten window — test-ergonomic mass cleanup that " + "matches the mesh-sync kindergarten window so only " + "un-broadcast records get busted" + ), + ) + burn_kg_cmd.add_argument( + "--kindergarten-seconds", + dest="kindergarten_seconds", + type=int, + default=3600, + help=( + "burn rows younger than this many seconds (default: 3600 = 1 " + "hour, mirrors mesh sync default). 0 = burn everything live." + ), + ) + burn_kg_cmd.add_argument( + "--reason", default=None, + help="reason text recorded in each providence_burn audit event", + ) + burn_kg_cmd.add_argument( + "--by-actor", dest="by_actor", default=None, + help="who is burning (default: $USER)", + ) + burn_kg_cmd.add_argument( + "--force", action="store_true", + help="burn even if rows have falsification children", + ) + burn_kg_cmd.add_argument( + "--dry-run", dest="dry_run", action="store_true", + help="report what would burn without writing", + ) + burn_kg_cmd.add_argument( + "--verbose", type=int, default=10, + help="include this many items in the result JSON (default: 10)", + ) + burn_kg_cmd.set_defaults(func=_cmd_burn_kindergarten) + + reclassify_cmd = sub.add_parser( + "reclassify", + help="re-run the verifier against existing live providence records " + "(no LLM calls; relabels stale classifications)", + ) + reclassify_cmd.add_argument( + "--qa-db", dest="qa_db", default=None, + help="path to qa.db (default: <shards>/qa.db or ~/.aborist/qa.db)", + ) + reclassify_cmd.add_argument( + "--limit", type=int, default=0, + help="reclassify at most N records (0 = unlimited)", + ) + reclassify_cmd.add_argument( + "--dry-run", dest="dry_run", action="store_true", + help="report what would change without writing", + ) + reclassify_cmd.add_argument( + "--entity-policy", dest="entity_policy", default=None, + choices=["strict", "hybrid", "drop", "proximity"], + help=( + "how the entity path classifies: 'strict' (legacy, overclaims), " + "'hybrid' (default — caps at HYBRID), 'drop' (skip entity path → " + "UNGROUNDED), 'proximity' (STRICT only if N entities cluster within " + "W chars in source)" + ), + ) + reclassify_cmd.add_argument( + "--compare", dest="compare", action="store_true", + help="run all four entity policies side-by-side without writing", + ) + reclassify_cmd.set_defaults(func=_cmd_reclassify) + + emergent_cmd = sub.add_parser( + "emergent", + help="surface UNGROUNDED/HYBRID claims — corpus-growth signal", + ) + emergent_cmd.add_argument( + "--aggregate", + action="store_true", + help="rank unverified quotes by frequency (vs per-record list)", + ) + emergent_cmd.add_argument("--limit", type=int, default=20) + emergent_cmd.set_defaults(func=_cmd_emergent) + + evict_cmd = sub.add_parser( + "evict", + help="demote surface chunks hot→cold (NULL content, retain leaf_hash)", + ) + evict_cmd.add_argument( + "--source-type", + dest="source_type", + default=None, + help="restrict to one source_type", + ) + evict_cmd.add_argument( + "--older-than-days", + dest="older_than_days", + type=int, + default=None, + help="only evict docs older than N days", + ) + evict_cmd.add_argument( + "--document-root", + action="append", + default=None, + help="explicit document_root(s) to evict; repeatable", + ) + evict_cmd.set_defaults(func=_cmd_evict) + + rehydrate_cmd = sub.add_parser( + "rehydrate", + help="refetch URI, verify leaves, restore cold content if root matches", + ) + rehydrate_cmd.add_argument( + "--document-root", + action="append", + default=None, + help="explicit document_root(s) to rehydrate; repeatable", + ) + rehydrate_cmd.add_argument( + "--all-cold", + dest="all_cold", + action="store_true", + help="rehydrate every document with cold chunks", + ) + rehydrate_cmd.set_defaults(func=_cmd_rehydrate) + + activity_cmd = sub.add_parser( + "activity", + help="recent Q&A + freshly cached docs (agent-readable timeline)", + ) + activity_cmd.add_argument( + "--limit", type=int, default=10, + help="max items per category (default 10)", + ) + activity_cmd.add_argument( + "--since-seconds", + dest="since_seconds", + type=int, + default=0, + help="only events newer than this many seconds (0 = all time, default)", + ) + activity_cmd.add_argument( + "--preview-chars", + dest="preview_chars", + type=int, + default=240, + help="answer preview length (default 240 chars)", + ) + activity_cmd.set_defaults(func=_cmd_activity) + + stats_cmd = sub.add_parser("stats", help="counts: docs, chunks, edges, audit") + stats_cmd.set_defaults(func=_cmd_stats) + + analyze_cmd = sub.add_parser( + "analyze", + help="compression spectrum, depth distribution, audit chain integrity", + ) + analyze_cmd.add_argument( + "--gravity-top", + dest="gravity_top", + type=int, + default=10, + help="N top inbound-linked URIs to report (default 10)", + ) + analyze_cmd.set_defaults(func=_cmd_analyze) + + # ----- snapshot subcommands ---------------------------------------------- + snap_cmd = sub.add_parser( + "snapshot", + help="corpus-level Merkle snapshots: pin a forest state by single root", + ) + snap_sub = snap_cmd.add_subparsers(dest="snap_op", required=True) + + snap_create = snap_sub.add_parser( + "create", help="compute snapshot_root from current corpus, persist + audit" + ) + snap_create.add_argument("--reason", default="manual") + snap_create.add_argument( + "--parent", + default=None, + help="explicit parent_snapshot hex (default: auto-link to latest prior snapshot)", + ) + snap_create.set_defaults(func=_cmd_snapshot_create) + + snap_list = snap_sub.add_parser("list", help="recent snapshots, newest first") + snap_list.add_argument("--limit", type=int, default=20) + snap_list.set_defaults(func=_cmd_snapshot_list) + + snap_verify = snap_sub.add_parser( + "verify", + help="recompute root from current corpus; matches=True iff nothing has changed", + ) + snap_verify.add_argument("snapshot_root", help="hex snapshot_root to verify") + snap_verify.set_defaults(func=_cmd_snapshot_verify) + + snap_diff = snap_sub.add_parser( + "diff", + help="coarse drift signal between a snapshot and the current corpus", + ) + snap_diff.add_argument("snapshot_root", help="hex snapshot_root to diff against current") + snap_diff.set_defaults(func=_cmd_snapshot_diff) + + # ----- mesh subcommands (off by default) --------------------------------- + mesh_cmd = sub.add_parser( + "mesh", + help="federation/gossip layer (off by default; opt-in via 'mesh enable')", + ) + mesh_sub = mesh_cmd.add_subparsers(dest="mesh_op", required=True) + + mesh_status = mesh_sub.add_parser("status", help="show enabled flag, identity, current epoch + roster") + mesh_status.set_defaults(func=_cmd_mesh_status) + + mesh_init = mesh_sub.add_parser("init", help="generate this peer's keys; create epoch 0") + mesh_init.add_argument("--group", required=True, help="group name") + mesh_init.add_argument("--member-id", dest="member_id", default=None, help="optional fixed member id (default: random 8-hex)") + mesh_init.set_defaults(func=_cmd_mesh_init) + + mesh_enable = mesh_sub.add_parser("enable", help="flip the mesh.enabled flag on") + mesh_enable.set_defaults(func=_cmd_mesh_enable) + + mesh_disable = mesh_sub.add_parser("disable", help="flip the mesh.enabled flag off") + mesh_disable.set_defaults(func=_cmd_mesh_disable) + + mesh_members = mesh_sub.add_parser("members", help="list current epoch's roster") + mesh_members.set_defaults(func=_cmd_mesh_members) + + mesh_add = mesh_sub.add_parser("add", help="admin-only: add a peer to the roster (bumps epoch)") + mesh_add.add_argument("--member-id", dest="member_id", required=True) + mesh_add.add_argument("--sign-pub", dest="sign_pub", required=True, help="hex Ed25519 pubkey (32 bytes / 64 hex chars)") + mesh_add.add_argument("--dh-pub", dest="dh_pub", required=True, help="hex X25519 pubkey") + mesh_add.add_argument("--role", choices=["admin", "member"], default="member") + mesh_add.set_defaults(func=_cmd_mesh_add) + + mesh_kick = mesh_sub.add_parser("kick", help="admin-only: evict a peer (bumps epoch; old signatures stay valid, new gossip is opaque to them)") + mesh_kick.add_argument("--member-id", dest="member_id", required=True) + mesh_kick.add_argument("--reason", required=True) + mesh_kick.set_defaults(func=_cmd_mesh_kick) + + mesh_rotate = mesh_sub.add_parser("rotate", help="refresh epoch secret without changing roster") + mesh_rotate.add_argument("--reason", default="scheduled") + mesh_rotate.set_defaults(func=_cmd_mesh_rotate) + + mesh_serve = mesh_sub.add_parser( + "serve", + help="run the HTTP gossip server (blocks until SIGINT)", + ) + mesh_serve.add_argument("--host", default="127.0.0.1", help="bind host (default: 127.0.0.1)") + mesh_serve.add_argument("--port", type=int, default=8400, help="bind port (default: 8400)") + mesh_serve.set_defaults(func=_cmd_mesh_serve) + + mesh_sync = mesh_sub.add_parser( + "sync", + help="announce local document_roots to a peer's gossip server", + ) + mesh_sync.add_argument("--peer", required=True, help="peer URL, e.g. http://other.example.com:8400") + mesh_sync.add_argument("--limit", type=int, default=100, help="announce at most N most-recent items per category (default: 100)") + mesh_sync.add_argument("--verbose", type=int, default=10, help="include this many ack details in output (default: 10)") + mesh_sync.add_argument( + "--no-roots", + dest="no_roots", + action="store_true", + help="skip ANNOUNCE_ROOT broadcast (only push falsifications)", + ) + mesh_sync.add_argument( + "--no-falsifications", + dest="no_falsifications", + action="store_true", + help="skip ANNOUNCE_FALSIFICATION broadcast (only push roots)", + ) + mesh_sync.add_argument( + "--kindergarten-seconds", + dest="kindergarten_seconds", + type=int, + default=3600, + help=( + "hold records younger than this many seconds back from the " + "broadcast (default: 3600 = 1 hour). Gives operators time to " + "burn or falsify before peers see it. 0 = broadcast everything." + ), + ) + mesh_sync.set_defaults(func=_cmd_mesh_sync) + + mesh_pull = mesh_sub.add_parser( + "pull", + help="pull one document body from a peer by document_root", + ) + mesh_pull.add_argument("--root", required=True, help="64-char hex document_root to pull") + mesh_pull.add_argument("--peer", required=True, help="peer URL, e.g. http://other.example.com:8400") + mesh_pull.set_defaults(func=_cmd_mesh_pull) + + crawl_cmd = sub.add_parser( + "crawl", + help=( + "BFS-discover same-domain URLs from a seed; optionally ingest " + "and store ETag/Last-Modified for cheap recrawl-checks " + "(requires aborist[crawler] extras)" + ), + ) + crawl_cmd.add_argument("--seed-url", dest="seed_url", required=True) + crawl_cmd.add_argument("--depth", type=int, default=2, help="max BFS depth (default: 2)") + crawl_cmd.add_argument( + "--max-pages", + dest="max_pages", + type=int, + default=0, + help="cap discovery at N URLs (0 = no cap, depth is the only bound; default: 0)", + ) + crawl_cmd.add_argument( + "--ingest", + action="store_true", + help="ingest the discovered pages into --db (default: print URL list only)", + ) + crawl_cmd.add_argument( + "--fast", + action="store_true", + help=( + "fast_mode: 5s timeouts, CPU*3 parallel page workers, ignore " + "robots.txt crawl-delay (Disallow is still honored). Use only " + "against domains where aggressive fetching is acceptable." + ), + ) + crawl_cmd.set_defaults(func=_cmd_crawl) + + crawler_cmd = sub.add_parser( + "crawler", + help="crawler maintenance verbs (recrawl-check, ...)", + ) + crawler_sub = crawler_cmd.add_subparsers(dest="crawler_op", required=True) + + recrawl_check_cmd = crawler_sub.add_parser( + "recrawl-check", + help=( + "send conditional HEAD requests for ingested documents and " + "classify each as fresh/stale/gone/unreachable" + ), + ) + recrawl_check_cmd.add_argument( + "--domain", + default=None, + help="restrict to documents whose URI contains this domain", + ) + recrawl_check_cmd.add_argument( + "--limit", + type=int, + default=100, + help="check at most N documents (oldest checks first; default: 100)", + ) + recrawl_check_cmd.set_defaults(func=_cmd_crawler_recrawl_check) + + return p
+ + + +
+[docs] +def main(argv: list[str] | None = None) -> int: + args = build_parser().parse_args(argv) + return args.func(args)
+ + + +if __name__ == "__main__": + raise SystemExit(main()) +
+
+
+
+ + +
+
+ + Made with Sphinx and @pradyunsg's + + Furo + +
+
+ +
+
+ +
+
+ +
+
+ + + + + \ No newline at end of file diff --git a/docs/_source/_build/html/_modules/aborist/concepts/query.html b/docs/_source/_build/html/_modules/aborist/concepts/query.html new file mode 100644 index 0000000..e27b335 --- /dev/null +++ b/docs/_source/_build/html/_modules/aborist/concepts/query.html @@ -0,0 +1,573 @@ + + + + + + + + aborist.concepts.query - Aborist API Reference + + + + + + + + + + + + + + + + Contents + + + + + + Menu + + + + + + + + Expand + + + + + + Light mode + + + + + + + + + + + + + + Dark mode + + + + + + + Auto light/dark, in light mode + + + + + + + + + + + + + + + Auto light/dark, in dark mode + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Skip to content + + + +
+
+
+ +
+ +
+
+ +
+ +
+
+ +
+
+
+ + + + + Back to top + +
+
+ +
+ +
+
+

Source code for aborist.concepts.query

+"""Retrieval-time concept lookup. Cross-shard, read-only.
+
+Public API matches the legacy ``aborist.qa.concepts`` shape so existing
+call sites in ``query.py`` keep working unchanged. Behavior changes:
+
+- Backed by the ``concept_relations`` SQLite table instead of in-Python
+  frozensets.
+- Walks every shard in ``shards_dir`` (same UNION pattern as cross-shard
+  FTS5 search). Concept relations from shard 003 are visible to a query
+  routed at shard 000 — exactly what we want for a 3.47M-doc corpus
+  split across many shards.
+- Token comparison is case-insensitive at the SQL layer (NOCASE on
+  LOWER()). Stored capitalization is preserved.
+
+Cache: a per-process LRU keyed on ``shards_dir`` mtime. Lookups in a
+hot loop don't re-walk shards. Cache invalidates when any shard file's
+mtime changes (e.g. after `aborist concepts derive` writes new rows).
+"""
+
+from __future__ import annotations
+
+import re
+import time
+from pathlib import Path
+
+from aborist.store import connect_query
+
+# Tokens that mean "user wants both sides of any rivalry shown" —
+# kept here (not in DB) because compare-phrasing detection is a
+# query-classification task, not a corpus-derived signal.
+COMPARE_WORDS: frozenset[str] = frozenset({
+    "vs", "versus", "compare", "compared", "comparison", "compares",
+    "between", "difference", "differences", "or", "either",
+})
+
+
+
+[docs] +def has_compare_phrasing(question: str) -> bool: + """True if the question contains comparison language.""" + lower = (question or "").lower() + words = set(re.findall(r"[a-z]+", lower)) + return bool(words & COMPARE_WORDS)
+ + + +# --------------------------------------------------------------------------- +# Cross-shard lookup with mtime-keyed cache +# --------------------------------------------------------------------------- + +# Cache shape: { shards_dir_str: (mtime_sig, manual_index, derived_index, rivalry_pairs, token_idf) } +# - manual_index: curated synonym edges; always expanded +# - derived_index: corpus-derived synonym edges; expansion subject to per-token cap +# - rivalry_pairs: list of (set_a, set_b) — frozensets of lowercase tokens +# - token_idf: { token_lower: doc_freq } summed across shards, used for cap-time ranking +_CACHE: dict[str, tuple[tuple, dict, dict, list, dict]] = {} + + +def _shards_mtime_signature(shards_dir: Path) -> tuple: + """Return a tuple of (path, mtime_ns) for every *.db in shards_dir. + Stable across runs as long as no shard's mtime changes.""" + if not shards_dir.is_dir(): + return () + return tuple( + (str(p.resolve()), p.stat().st_mtime_ns) + for p in sorted(shards_dir.glob("*.db")) + ) + + +def _load_token_idf(shards_dir: Path) -> dict[str, int]: + """Sum per-token doc_freq across all shards. + + The concept_token_idf table is per-shard (the `chunks_fts` index + it derives from is per-shard), so cross-shard ranking aggregates + via SUM over the UNION view exposed by connect_query. Tokens not + in any shard's table get NO entry; callers default to "treat as + rare" via dict.get() with a high-rarity default. + """ + conn = connect_query(shards_dir=shards_dir) + rows = conn.execute( + "SELECT token, SUM(doc_freq) AS df FROM concept_token_idf GROUP BY token" + ).fetchall() + conn.close() + return {(r["token"] or "").lower(): int(r["df"] or 0) for r in rows} + + +def _load_indices(shards_dir: Path) -> tuple[dict, dict, list]: + """Walk all shards, materialize the synonym & rivalry indices. + + Synonyms map every token to its **direct neighbors only**, NOT the + transitive closure across reciprocal-link chains. Why: union-find + over the full Wikipedia reciprocal-link graph collapses everything + into one giant connected component (54k+ tokens for any seed in + a 4-shard corpus). Direct-neighbor expansion preserves the legacy + frozenset semantics (every member of a group expanded to the others + in that group, but the groups didn't chain). + + Two synonym indices are built, one per evidence class: + + - ``manual_index`` — manual_legacy + manual rows. Curated; always + expanded regardless of per-token degree. + Captures the brain-tech / AMD-family / etc. + seed groups whose anchor token has many + deliberate members (e.g. telepathy → 29 + members of the brain-tech group). + - ``derived_index`` — link_reciprocity & other corpus-derived + extractors. Subject to per-token degree + cap because the Wikipedia link graph + carries topic-adjacency noise on generic + tokens (person, thoughts, language). + + Rivalry pairs use the union of both indices for closure. + """ + conn = connect_query(shards_dir=shards_dir) + rows = conn.execute( + "SELECT relation_kind, evidence_kind, token, target FROM concept_relations" + ).fetchall() + conn.close() + + manual_index: dict[str, set[str]] = {} + derived_index: dict[str, set[str]] = {} + rivalry_rows: list[tuple[str, str]] = [] + + # Curated evidence kinds — never capped at expansion time. + MANUAL_KINDS = {"manual", "manual_legacy"} + + for r in rows: + kind = r["relation_kind"] + evidence_kind = r["evidence_kind"] + a = (r["token"] or "").lower() + b = (r["target"] or "").lower() + if not a or not b or a == b: + continue + if kind == "synonym": + target_index = ( + manual_index if evidence_kind in MANUAL_KINDS else derived_index + ) + target_index.setdefault(a, set()).add(b) + target_index.setdefault(b, set()).add(a) + elif kind == "rivalry": + rivalry_rows.append((a, b)) + + # Rivalry pairs use union of manual + derived neighborhoods. + rivalry_pairs: list[tuple[frozenset[str], frozenset[str]]] = [] + for a, b in rivalry_rows: + ga = frozenset( + manual_index.get(a, set()) | derived_index.get(a, set()) | {a} + ) + gb = frozenset( + manual_index.get(b, set()) | derived_index.get(b, set()) | {b} + ) + rivalry_pairs.append((ga, gb)) + + return manual_index, derived_index, rivalry_pairs + + +def _get_indices(shards_dir: Path | str | None) -> tuple[dict, dict, list, dict]: + """Return (manual_index, derived_index, rivalry_pairs, token_idf), + using cached values when the shard mtime signature is unchanged.""" + if shards_dir is None: + return {}, {}, [], {} + p = Path(shards_dir) + key = str(p.resolve()) + sig = _shards_mtime_signature(p) + cached = _CACHE.get(key) + if cached is not None and cached[0] == sig: + return cached[1], cached[2], cached[3], cached[4] + manual, derived, riv = _load_indices(p) + idf = _load_token_idf(p) + _CACHE[key] = (sig, manual, derived, riv, idf) + return manual, derived, riv, idf + + +
+[docs] +def invalidate_cache() -> None: + """Drop all cached indices. Call after a writer commits new rows + (the mtime check would catch this on next read, but invalidating + explicitly is faster on the same-process write+read pattern).""" + _CACHE.clear()
+ + + +# --------------------------------------------------------------------------- +# Public API — matches the legacy ``aborist.qa.concepts`` shape +# --------------------------------------------------------------------------- + + +# Caps that match the legacy (frozenset) expansion size. The corpus- +# derived synonym graph is noisier than hand-curated frozensets: +# generic tokens like "person" / "thoughts" / "language" have ~20+ +# reciprocal-link neighbors each, most of which are topic-adjacency +# noise rather than actual synonyms. Without these caps a 19-token +# query expands to ~400 accept tokens, and the title-LIKE search +# multiplies that by the document count to a many-minute hang. +# +# MAX_NEIGHBORS_PER_TOKEN: any token with more than this many +# direct neighbors is treated as "too generic to expand" — we add +# only the token itself, not its neighbors. Mirrors how the legacy +# frozensets covered named entities (athlon, pentium) but not common +# words (person, thoughts). +# +# MAX_TOTAL_TOKENS: overall cap on the expanded set. Original query +# tokens are always preserved; once total exceeds the cap, neighbors +# are sorted alphabetically & truncated. Bound on title-LIKE clause +# count keeps the SQL tractable on a 3.47M-doc corpus. +MAX_NEIGHBORS_PER_TOKEN = 8 +MAX_TOTAL_TOKENS = 50 + + +
+[docs] +def synonym_expand( + tokens: set[str], + *, + shards_dir: Path | str | None = None, + max_neighbors_per_token: int = MAX_NEIGHBORS_PER_TOKEN, + max_total: int = MAX_TOTAL_TOKENS, +) -> set[str]: + """Add direct synonym neighbors for any input token whose degree + is bounded enough that its neighbors are likely topical, not + topic-adjacency noise. + + Two caps protect retrieval performance & quality: + + 1. ``max_neighbors_per_token`` — tokens with more direct neighbors + than this contribute NO expansion. Generic tokens ("person", + "thoughts") have huge degree in the Wikipedia reciprocal-link + graph; expanding them dumps random topical-cluster noise. + Specific named entities ("athlon", "telepathy") have small + focused neighborhoods that pass the cap. + + 2. ``max_total`` — overall cap on expanded set size. Bounds the + SQL clause count downstream. Original query tokens are always + preserved; if total > cap, neighbors are sorted alphabetically + & truncated. + """ + if not tokens: + return set() + if shards_dir is None: + return set(tokens) + manual_index, derived_index, _, token_idf = _get_indices(shards_dir) + qlower = {t.lower() for t in tokens} + expanded: set[str] = set(qlower) + # Manual (curated) synonyms always expand: brain-tech / AMD-family / + # etc. seed groups have legitimately many members per anchor & we + # trust the curation. + for t in qlower: + if t in manual_index: + expanded |= manual_index[t] + # Derived (corpus-extracted) synonyms cap on per-token degree. + # Generic tokens like "person" / "thoughts" / "language" have wide + # noisy neighborhoods in the reciprocal-link graph — skip those. + # Specific tokens with bounded degree expand cleanly. + for t in qlower: + if t not in derived_index: + continue + neighbors = derived_index[t] + if len(neighbors) > max_neighbors_per_token: + continue + expanded |= neighbors + if len(expanded) > max_total: + # IDF-rank the neighbors (rarer = more topical = keep first). + # Tokens absent from concept_token_idf get a sentinel high- + # rarity score so a hapax doesn't lose to a known-common + # token at the truncation boundary. When the IDF table is + # empty (backfill not run yet), ranking degenerates to + # alphabetical (fallback compatibility). + neighbors_only = expanded - qlower + # Lower doc_freq → rarer → higher rank → kept first. + # `total_docs + 1` sentinel pushes "missing" tokens to the + # rarest-bucket so they tie-break before the most common. + SENTINEL_HIGH_RARITY = 0 + ranked = sorted( + neighbors_only, + key=lambda t: (token_idf.get(t, SENTINEL_HIGH_RARITY), t), + ) + budget = max(0, max_total - len(qlower)) + expanded = qlower | set(ranked[:budget]) + return expanded
+ + + +
+[docs] +def rivalry_excluded( + tokens: set[str], + *, + shards_dir: Path | str | None = None, + compare_phrasing: bool = False, +) -> set[str]: + """Tokens whose presence in a doc title means EXCLUDE that doc. + + For each rivalry pair (A, B): if exactly ONE side appears in the + query AND no comparison language was used, exclude the OTHER side's + tokens. If both sides appear, or if the user asked for a comparison, + no exclusion (they wanted both). + """ + if compare_phrasing or not tokens or shards_dir is None: + return set() + _, _, rivalry_pairs, _ = _get_indices(shards_dir) + qlower = {t.lower() for t in tokens} + excluded: set[str] = set() + for a, b in rivalry_pairs: + a_in = bool(qlower & a) + b_in = bool(qlower & b) + if a_in and not b_in: + excluded |= b + elif b_in and not a_in: + excluded |= a + return excluded
+ +
+
+
+
+ + +
+
+ + Made with Sphinx and @pradyunsg's + + Furo + +
+
+ +
+
+ +
+
+ +
+
+ + + + + \ No newline at end of file diff --git a/docs/_source/_build/html/_modules/aborist/concepts/store.html b/docs/_source/_build/html/_modules/aborist/concepts/store.html new file mode 100644 index 0000000..8ccdafe --- /dev/null +++ b/docs/_source/_build/html/_modules/aborist/concepts/store.html @@ -0,0 +1,394 @@ + + + + + + + + aborist.concepts.store - Aborist API Reference + + + + + + + + + + + + + + + + Contents + + + + + + Menu + + + + + + + + Expand + + + + + + Light mode + + + + + + + + + + + + + + Dark mode + + + + + + + Auto light/dark, in light mode + + + + + + + + + + + + + + + Auto light/dark, in dark mode + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Skip to content + + + +
+
+
+ +
+ +
+
+ +
+ +
+
+ +
+
+
+ + + + + Back to top + +
+
+ +
+ +
+
+

Source code for aborist.concepts.store

+"""DB read/write helpers for concept_relations.
+
+All operations are scoped to a single shard connection. Cross-shard
+queries live in ``aborist.concepts.query``.
+
+Append-only by design: ``add_concept_relation`` uses INSERT OR IGNORE
+on the UNIQUE (source_root, relation_kind, token, target, evidence_kind)
+key, so re-derivation never duplicates rows. ``purge_by_evidence_kind``
+is the only DELETE path & lets an operator revoke one extractor's
+output without touching manual or other-extractor rows.
+"""
+
+from __future__ import annotations
+
+import sqlite3
+import time
+
+# Allowed relation_kind values. The schema's CHECK constraint enforces
+# this too — keeping the Python-side tuple in sync makes API misuse
+# fail loud at the helper level rather than as a SQLite error.
+RELATION_KINDS = ("synonym", "antonym", "rivalry", "category")
+
+
+
+[docs] +def add_concept_relation( + conn: sqlite3.Connection, + *, + source_root: str, + relation_kind: str, + token: str, + target: str, + evidence_kind: str, + confidence: float = 1.0, + derived_from: str | None = None, + derived_at: int | None = None, +) -> bool: + """Append a concept relation. Returns True if a row was inserted, + False if the (source_root, relation_kind, token, target, evidence_kind) + tuple already existed (idempotent re-derivation). + + Tokens are stored exactly as given — case preservation lets the + query layer decide normalization. Substring lookup at retrieval + time is case-insensitive via SQLite's NOCASE comparator. + """ + if relation_kind not in RELATION_KINDS: + raise ValueError( + f"relation_kind must be one of {RELATION_KINDS}, got {relation_kind!r}" + ) + if not token or not target: + raise ValueError("token and target must be non-empty") + if derived_at is None: + derived_at = int(time.time()) + cursor = conn.execute( + "INSERT OR IGNORE INTO concept_relations " + "(source_root, relation_kind, token, target, evidence_kind, " + " confidence, derived_at, derived_from) " + "VALUES (?, ?, ?, ?, ?, ?, ?, ?)", + ( + source_root, + relation_kind, + token, + target, + evidence_kind, + float(confidence), + int(derived_at), + derived_from, + ), + ) + return cursor.rowcount > 0
+ + + +
+[docs] +def concept_relations_for_token( + conn: sqlite3.Connection, + token: str, + *, + relation_kind: str | None = None, +) -> list[dict]: + """Return all relations whose ``token`` matches (case-insensitive). + If ``relation_kind`` is given, filter to that kind.""" + sql = ( + "SELECT source_root, relation_kind, token, target, evidence_kind, " + " confidence, derived_at, derived_from " + "FROM concept_relations WHERE LOWER(token) = LOWER(?)" + ) + params: tuple = (token,) + if relation_kind: + if relation_kind not in RELATION_KINDS: + raise ValueError( + f"relation_kind must be one of {RELATION_KINDS}, got {relation_kind!r}" + ) + sql += " AND relation_kind = ?" + params = params + (relation_kind,) + return [dict(row) for row in conn.execute(sql, params).fetchall()]
+ + + +
+[docs] +def purge_by_evidence_kind( + conn: sqlite3.Connection, + evidence_kind: str, + *, + derived_from: str | None = None, +) -> int: + """Delete every row with the given ``evidence_kind`` (and optional + ``derived_from``). Returns the number of rows removed. + + The intended use: revoke a buggy extractor's output cleanly. Manual + rows live under ``evidence_kind='manual'`` and are NOT touched by + a purge of any other kind. + """ + sql = "DELETE FROM concept_relations WHERE evidence_kind = ?" + params: tuple = (evidence_kind,) + if derived_from is not None: + sql += " AND derived_from = ?" + params = params + (derived_from,) + cursor = conn.execute(sql, params) + return cursor.rowcount
+ + + +def list_evidence_kinds(conn: sqlite3.Connection) -> list[tuple[str, int]]: + """Return ``[(evidence_kind, row_count), ...]`` for the shard, ordered + by row_count descending. Useful for ``aborist concepts list --kinds``.""" + rows = conn.execute( + "SELECT evidence_kind, COUNT(*) AS n " + "FROM concept_relations GROUP BY evidence_kind ORDER BY n DESC" + ).fetchall() + return [(r["evidence_kind"], r["n"]) for r in rows] +
+
+
+
+ + +
+
+ + Made with Sphinx and @pradyunsg's + + Furo + +
+
+ +
+
+ +
+
+ +
+
+ + + + + \ No newline at end of file diff --git a/docs/_source/_build/html/_modules/aborist/distill/base.html b/docs/_source/_build/html/_modules/aborist/distill/base.html new file mode 100644 index 0000000..736c592 --- /dev/null +++ b/docs/_source/_build/html/_modules/aborist/distill/base.html @@ -0,0 +1,312 @@ + + + + + + + + aborist.distill.base - Aborist API Reference + + + + + + + + + + + + + + + + Contents + + + + + + Menu + + + + + + + + Expand + + + + + + Light mode + + + + + + + + + + + + + + Dark mode + + + + + + + Auto light/dark, in light mode + + + + + + + + + + + + + + + Auto light/dark, in dark mode + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Skip to content + + + +
+
+
+ +
+ +
+
+ +
+ +
+
+ +
+
+
+ + + + + Back to top + +
+
+ +
+ +
+
+

Source code for aborist.distill.base

+"""Distiller ABC.
+
+A Distiller compresses a surface Document into a core Document. The runner
+generates Merkle proofs for every contributing source chunk so the resulting
+derivation row cryptographically binds the core back to its source.
+"""
+
+from __future__ import annotations
+
+from abc import ABC, abstractmethod
+from dataclasses import dataclass
+
+from aborist.document import Document
+
+
+
+[docs] +@dataclass +class DistillationResult: + """What a Distiller returns for one source. + + contributing_chunk_indices: 0-based indices into source_chunks that fed + the core's content. The runner Merkle-proves each one against the + source's document_root and stores those proofs in derivations.proof_blob. + """ + + core: Document + contributing_chunk_indices: list[int]
+ + + +
+[docs] +class Distiller(ABC): + """Pure function: surface Document + its chunks -> core DistillationResult. + + Distillers must be deterministic — same source bytes produce the same core + bytes. Bumping a distiller's algorithm requires bumping its `name`. + """ + + name: str + +
+[docs] + @abstractmethod + def distill( + self, source: Document, source_chunks: list[str] + ) -> DistillationResult: + ...
+
+ +
+
+
+
+ + +
+
+ + Made with Sphinx and @pradyunsg's + + Furo + +
+
+ +
+
+ +
+
+ +
+
+ + + + + \ No newline at end of file diff --git a/docs/_source/_build/html/_modules/aborist/distill/first_sentence.html b/docs/_source/_build/html/_modules/aborist/distill/first_sentence.html new file mode 100644 index 0000000..ce2109f --- /dev/null +++ b/docs/_source/_build/html/_modules/aborist/distill/first_sentence.html @@ -0,0 +1,330 @@ + + + + + + + + aborist.distill.first_sentence - Aborist API Reference + + + + + + + + + + + + + + + + Contents + + + + + + Menu + + + + + + + + Expand + + + + + + Light mode + + + + + + + + + + + + + + Dark mode + + + + + + + Auto light/dark, in light mode + + + + + + + + + + + + + + + Auto light/dark, in dark mode + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Skip to content + + + +
+
+
+ +
+ +
+
+ +
+ +
+
+ +
+
+
+ + + + + Back to top + +
+
+ +
+ +
+
+

Source code for aborist.distill.first_sentence

+"""First-sentence-per-chunk distiller (deterministic, no ML).
+
+Compresses a source by taking the first non-trivial sentence of each chunk
+and concatenating. Useful as a stub to exercise the core/derivation schema
+without external models.
+"""
+
+from __future__ import annotations
+
+import re
+
+from aborist.distill.base import DistillationResult, Distiller
+from aborist.document import Document
+
+_SENTENCE_BOUNDARY = re.compile(r"(?<=[.!?])\s+(?=[A-Z0-9])")
+_MIN_SENTENCE_LEN = 10
+
+
+
+[docs] +class FirstSentenceDistiller(Distiller): + name = "first-sentence-v1" + + def __init__(self, max_chars: int = 4096): + self.max_chars = max_chars + +
+[docs] + def distill( + self, source: Document, source_chunks: list[str] + ) -> DistillationResult: + sentences: list[str] = [] + contributing: list[int] = [] + for chunk_idx, chunk in enumerate(source_chunks): + first = self._first_sentence(chunk) + if first: + sentences.append(first) + contributing.append(chunk_idx) + + core_text = "\n".join(sentences) + if len(core_text) > self.max_chars: + core_text = core_text[: self.max_chars].rstrip() + + core = Document( + uri=f"{source.uri}#core/{self.name}", + content=core_text, + source_type=f"core:{self.name}", + title=(source.title or "") + " [CORE]", + ) + return DistillationResult(core=core, contributing_chunk_indices=contributing)
+ + + @staticmethod + def _first_sentence(text: str) -> str | None: + text = text.strip() + if not text: + return None + # Try paragraph-aware: split on blank lines first, then take first paragraph. + for para in text.split("\n\n"): + para = para.strip() + if not para: + continue + # First sentence within the paragraph. + parts = _SENTENCE_BOUNDARY.split(para, maxsplit=1) + first = parts[0].strip() + if len(first) >= _MIN_SENTENCE_LEN: + return first + return None
+ +
+
+
+
+ + +
+
+ + Made with Sphinx and @pradyunsg's + + Furo + +
+
+ +
+
+ +
+
+ +
+
+ + + + + \ No newline at end of file diff --git a/docs/_source/_build/html/_modules/aborist/distill/tfidf.html b/docs/_source/_build/html/_modules/aborist/distill/tfidf.html new file mode 100644 index 0000000..7fdf165 --- /dev/null +++ b/docs/_source/_build/html/_modules/aborist/distill/tfidf.html @@ -0,0 +1,363 @@ + + + + + + + + aborist.distill.tfidf - Aborist API Reference + + + + + + + + + + + + + + + + Contents + + + + + + Menu + + + + + + + + Expand + + + + + + Light mode + + + + + + + + + + + + + + Dark mode + + + + + + + Auto light/dark, in light mode + + + + + + + + + + + + + + + Auto light/dark, in dark mode + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Skip to content + + + +
+
+
+ +
+ +
+
+ +
+ +
+
+ +
+
+
+ + + + + Back to top + +
+
+ +
+ +
+
+

Source code for aborist.distill.tfidf

+"""TF-IDF top-K keyword distiller.
+
+Pure-Python, stdlib-only. Uses chunk-level "documents" as the corpus
+baseline so a term that appears in every chunk of the same source gets
+penalized relative to a term concentrated in fewer chunks.
+
+Output core content is a deterministic comma-separated keyword list —
+extreme compression toward the "tweet/haiku" end of the planet metaphor.
+"""
+
+from __future__ import annotations
+
+import math
+import re
+from collections import Counter
+
+from aborist.distill.base import DistillationResult, Distiller
+from aborist.document import Document
+
+
+_TOKEN_RE = re.compile(r"\b[a-zA-Z][a-zA-Z\-']{2,}\b")
+_STOPWORDS = frozenset(
+    """
+    the and or in of to is are was were for with on as by an be this that
+    these those from at but not have has had been they their his her its
+    our we you he she it all any if no more than such also can may will
+    would should could do does did between which where when what who how
+    some many most into through during above below after before since
+    while well much even only still about other only own same so very
+    just over under
+    """.split()
+)
+
+
+def _tokenize(text: str) -> list[str]:
+    return [t.lower() for t in _TOKEN_RE.findall(text) if t.lower() not in _STOPWORDS]
+
+
+
+[docs] +class TfidfKeywordDistiller(Distiller): + name = "tfidf-keywords-v1" + + def __init__(self, top_k: int = 16): + self.top_k = top_k + +
+[docs] + def distill( + self, source: Document, source_chunks: list[str] + ) -> DistillationResult: + if not source_chunks: + return self._empty_result(source) + + chunk_tokens = [_tokenize(c) for c in source_chunks] + n = len(chunk_tokens) + + df: Counter[str] = Counter() + for toks in chunk_tokens: + df.update(set(toks)) + + tf: Counter[str] = Counter() + for toks in chunk_tokens: + tf.update(toks) + + scores: dict[str, float] = {} + for t, f in tf.items(): + idf = math.log((n + 1) / (df[t] + 1)) + 1.0 + scores[t] = f * idf + + ranked = sorted(scores.items(), key=lambda kv: (-kv[1], kv[0])) + keywords = [t for t, _ in ranked[: self.top_k]] + kw_set = set(keywords) + + contributing: set[int] = set() + for i, toks in enumerate(chunk_tokens): + if any(t in kw_set for t in toks): + contributing.add(i) + + core_text = ", ".join(keywords) + return DistillationResult( + core=Document( + uri=f"{source.uri}#core/{self.name}", + content=core_text, + source_type=f"core:{self.name}", + title=(source.title or "") + " [KEYWORDS]", + ), + contributing_chunk_indices=sorted(contributing), + )
+ + + def _empty_result(self, source: Document) -> DistillationResult: + return DistillationResult( + core=Document( + uri=f"{source.uri}#core/{self.name}", + content="", + source_type=f"core:{self.name}", + title=(source.title or "") + " [KEYWORDS]", + ), + contributing_chunk_indices=[], + )
+ +
+
+
+
+ + +
+
+ + Made with Sphinx and @pradyunsg's + + Furo + +
+
+ +
+
+ +
+
+ +
+
+ + + + + \ No newline at end of file diff --git a/docs/_source/_build/html/_modules/aborist/document.html b/docs/_source/_build/html/_modules/aborist/document.html new file mode 100644 index 0000000..1865f66 --- /dev/null +++ b/docs/_source/_build/html/_modules/aborist/document.html @@ -0,0 +1,392 @@ + + + + + + + + aborist.document - Aborist API Reference + + + + + + + + + + + + + + + + Contents + + + + + + Menu + + + + + + + + Expand + + + + + + Light mode + + + + + + + + + + + + + + Dark mode + + + + + + + Auto light/dark, in light mode + + + + + + + + + + + + + + + Auto light/dark, in dark mode + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Skip to content + + + +
+
+
+ +
+ +
+
+ +
+ +
+
+ +
+
+
+ + + + + Back to top + +
+
+ +
+ +
+
+

Source code for aborist.document

+"""Document and Chunk dataclasses + canonical chunkers.
+
+Every Document carries a URI (identification, backtrack, cross-link) and content.
+Chunkers split content into byte-determined chunks before Merkle hashing. The
+chunker's name is committed in chunking_version — changing chunker invalidates
+all prior cache records under v9.8 admissibility.
+"""
+
+from __future__ import annotations
+
+import re
+import unicodedata
+from dataclasses import dataclass, field
+from typing import Protocol
+
+
+
+[docs] +@dataclass(frozen=True) +class Edge: + """A cross-link from this document to another.""" + + edge_type: str # wikilink | citation | derived_from | ... + dst_uri: str # always present + dst_root: str | None = None # filled in later if/when target is ingested + anchor: str | None = None # optional fragment / chunk index
+ + + +
+[docs] +@dataclass +class Document: + """An ingestable document: URI + content + outbound edges.""" + + uri: str + content: str # normalized text + source_type: str # wikipedia_xml | html | git | ... + title: str | None = None + edges: list[Edge] = field(default_factory=list) + extra: dict = field(default_factory=dict) # source-specific metadata
+ + + +
+[docs] +def canonicalize(text: str) -> str: + """Stable text normalization. Bumping this requires CANONICALIZATION_VERSION bump.""" + # NFC unicode, normalize whitespace runs to single spaces, strip ends. + text = unicodedata.normalize("NFC", text) + text = re.sub(r"[\r\n\t\f\v]+", "\n", text) + text = re.sub(r"[ ]{2,}", " ", text) + return text.strip()
+ + + +
+[docs] +class Chunker(Protocol): + """A chunker splits canonicalized text into ordered chunks.""" + + name: str + +
+[docs] + def split(self, text: str) -> list[str]: ...
+
+ + + +
+[docs] +class TokenChunker: + """512-token chunker (whitespace-tokenized, byte-deterministic). + + "Token" here means whitespace-separated unit, NOT a model BPE token. This + avoids tokenizer-version drift in the chunking_version. + """ + + name = "tok-512-v1" + + def __init__(self, tokens_per_chunk: int = 512): + self.tokens_per_chunk = tokens_per_chunk + +
+[docs] + def split(self, text: str) -> list[str]: + if not text: + return [] + tokens = text.split() + if not tokens: + return [] + chunks: list[str] = [] + for start in range(0, len(tokens), self.tokens_per_chunk): + chunks.append(" ".join(tokens[start : start + self.tokens_per_chunk])) + return chunks
+
+ + + +
+[docs] +class SentenceChunker: + """Sentence-aligned chunker (better for short docs like 2003 Wikipedia).""" + + name = "sent-v1" + + _split_re = re.compile(r"(?<=[.!?])\s+(?=[A-Z0-9])") + +
+[docs] + def split(self, text: str) -> list[str]: + if not text: + return [] + # Naive but deterministic. + sentences = [s.strip() for s in self._split_re.split(text) if s.strip()] + return sentences or ([text] if text else [])
+
+ + + +
+[docs] +def get_chunker(name: str | None = None) -> Chunker: + """Lookup chunker by name. Default = TokenChunker.""" + if name is None or name == TokenChunker.name: + return TokenChunker() + if name == SentenceChunker.name: + return SentenceChunker() + raise ValueError(f"unknown chunker: {name}")
+ +
+
+
+
+ + +
+
+ + Made with Sphinx and @pradyunsg's + + Furo + +
+
+ +
+
+ +
+
+ +
+
+ + + + + \ No newline at end of file diff --git a/docs/_source/_build/html/_modules/aborist/evict.html b/docs/_source/_build/html/_modules/aborist/evict.html new file mode 100644 index 0000000..0e74efc --- /dev/null +++ b/docs/_source/_build/html/_modules/aborist/evict.html @@ -0,0 +1,496 @@ + + + + + + + + aborist.evict - Aborist API Reference + + + + + + + + + + + + + + + + Contents + + + + + + Menu + + + + + + + + Expand + + + + + + Light mode + + + + + + + + + + + + + + Dark mode + + + + + + + Auto light/dark, in light mode + + + + + + + + + + + + + + + Auto light/dark, in dark mode + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Skip to content + + + +
+
+
+ +
+ +
+
+ +
+ +
+
+ +
+
+
+ + + + + Back to top + +
+
+ +
+ +
+
+

Source code for aborist.evict

+"""Reversible eviction + rehydrate.
+
+Implements the systematic-forgetting mechanic from the design philosophy:
+
+- evict_to_cold: surface chunks demote from `hot` to `cold`; content set to
+  NULL, FTS5 row deleted. leaf_hash retained — identity preserved.
+- rehydrate: refetch URI through the same source pipeline, re-chunk with the
+  original chunking_version, compare leaves and root. Match -> content
+  restored, tier hot. Mismatch -> drift event in audit chain, providence
+  records flipped to falsification_state='stale'. No content restored.
+
+Cores never evict.
+"""
+
+from __future__ import annotations
+
+import sqlite3
+import time
+from typing import Callable, Iterable
+
+from aborist.compress import pack_chunk
+from aborist.document import canonicalize, get_chunker
+from aborist.merkle import MerkleTree, hash_leaf
+from aborist.store import append_audit, transaction
+
+
+# Re-fetcher signature: takes a URI, returns parsed/canonicalized text or None.
+Fetcher = Callable[[str], str | None]
+
+
+def _default_html_fetcher(uri: str) -> str | None:
+    """Reuse HtmlPageSource so rehydrate runs the exact same pipeline as ingest."""
+    try:
+        from aborist.sources.html_page import HtmlPageSource
+    except ImportError:
+        return None
+    src = HtmlPageSource([uri])
+    for doc in src.iter_documents():
+        return doc.content
+    return None
+
+
+_FETCHERS: dict[str, Fetcher] = {
+    "html": _default_html_fetcher,
+}
+
+
+
+[docs] +def evict_to_cold( + conn: sqlite3.Connection, + *, + source_type: str | None = None, + older_than_days: int | None = None, + document_roots: Iterable[str] | None = None, +) -> dict: + """Demote matching surface chunks from hot to cold. + + Cores are never evicted. Content is NULLed; FTS row removed. + """ + where = ["d.kind = 'surface'", "c.tier = 'hot'"] + params: list = [] + if source_type: + where.append("d.source_type = ?") + params.append(source_type) + if older_than_days is not None: + cutoff = int(time.time()) - older_than_days * 86400 + where.append("d.ingest_ts < ?") + params.append(cutoff) + if document_roots is not None: + roots = list(document_roots) + if not roots: + return {"evicted_chunks": 0, "documents_affected": 0} + placeholders = ",".join("?" for _ in roots) + where.append(f"c.document_root IN ({placeholders})") + params.extend(roots) + + sql = ( + "SELECT c.document_root, c.idx FROM chunks c " + "JOIN documents d ON d.document_root = c.document_root " + "WHERE " + " AND ".join(where) + ) + candidates = conn.execute(sql, params).fetchall() + if not candidates: + return {"evicted_chunks": 0, "documents_affected": 0} + + per_doc: dict[str, int] = {} + with transaction(conn): + for r in candidates: + # Delete from FTS5 first so we can resolve chunk_id via the same + # row before its content goes away. Contentless FTS5 deletions + # are addressed by rowid (== chunks.chunk_id). + chunk_id_row = conn.execute( + "SELECT chunk_id FROM chunks WHERE document_root=? AND idx=?", + (r["document_root"], r["idx"]), + ).fetchone() + if chunk_id_row is not None: + conn.execute( + "DELETE FROM chunks_fts WHERE rowid=?", + (chunk_id_row["chunk_id"],), + ) + conn.execute( + "UPDATE chunks SET content=NULL, tier='cold' " + "WHERE document_root=? AND idx=?", + (r["document_root"], r["idx"]), + ) + per_doc[r["document_root"]] = per_doc.get(r["document_root"], 0) + 1 + + for doc_root, n in per_doc.items(): + append_audit( + conn, + event_type="evict_cold", + subject_root=doc_root, + body={"chunks_evicted": n}, + ) + + return { + "evicted_chunks": len(candidates), + "documents_affected": len(per_doc), + }
+ + + +
+[docs] +def rehydrate( + conn: sqlite3.Connection, + document_root: str, + *, + fetcher: Fetcher | None = None, +) -> dict: + """Refetch URI, verify leaves, restore content if and only if root matches. + + Returns a dict with `status` ∈ { + unknown_document, nothing_to_do, source_not_rehydratable, + fetch_failed, drift_detected, rehydrated + }. + """ + doc_row = conn.execute( + "SELECT document_uri, source_type, chunking_version " + "FROM documents WHERE document_root = ?", + (document_root,), + ).fetchone() + if doc_row is None: + return {"status": "unknown_document"} + + cold_chunks = conn.execute( + "SELECT idx, leaf_hash FROM chunks " + "WHERE document_root = ? AND tier = 'cold' ORDER BY idx", + (document_root,), + ).fetchall() + if not cold_chunks: + return {"status": "nothing_to_do", "cold_chunks": 0} + + # Pick fetcher by source_type unless caller supplies one. + use_fetcher = fetcher or _FETCHERS.get(doc_row["source_type"]) + if use_fetcher is None: + return { + "status": "source_not_rehydratable", + "source_type": doc_row["source_type"], + } + + try: + text = use_fetcher(doc_row["document_uri"]) + except Exception as e: # noqa: BLE001 — surface any error in status + return {"status": "fetch_failed", "error": repr(e)} + if text is None: + return {"status": "fetch_failed", "error": "fetcher returned None"} + + chunker = get_chunker(doc_row["chunking_version"]) + new_text = canonicalize(text) + new_chunk_strs = chunker.split(new_text) + new_leaves = [hash_leaf(c.encode("utf-8")) for c in new_chunk_strs] + new_root = MerkleTree.build(new_leaves).root.hex() + + if new_root != document_root: + with transaction(conn): + append_audit( + conn, + event_type="rehydrate_drift", + subject_root=document_root, + body={ + "expected_root": document_root, + "actual_root": new_root, + "uri": doc_row["document_uri"], + }, + ) + # v9.8 falsification: any cached providence record from this + # source is now stale. + conn.execute( + "UPDATE providence_cache SET falsification_state = 'stale' " + "WHERE source_root = ? AND falsification_state = 'live'", + (document_root,), + ) + return { + "status": "drift_detected", + "expected_root": document_root, + "actual_root": new_root, + } + + # Roots match. Restore content for every cold chunk. + restored = 0 + with transaction(conn): + for c in cold_chunks: + i = c["idx"] + if i >= len(new_chunk_strs): + continue + recomputed = hash_leaf(new_chunk_strs[i].encode("utf-8")).hex() + if recomputed != c["leaf_hash"]: + # Defensive: shouldn't happen if roots match, but bail safely. + continue + conn.execute( + "UPDATE chunks SET content = ?, tier = 'hot' " + "WHERE document_root = ? AND idx = ?", + (pack_chunk(new_chunk_strs[i]), document_root, i), + ) + chunk_id_row = conn.execute( + "SELECT chunk_id FROM chunks WHERE document_root = ? AND idx = ?", + (document_root, i), + ).fetchone() + if chunk_id_row is not None: + conn.execute( + "INSERT INTO chunks_fts (rowid, content) VALUES (?, ?)", + (chunk_id_row["chunk_id"], new_chunk_strs[i]), + ) + restored += 1 + append_audit( + conn, + event_type="rehydrate_success", + subject_root=document_root, + body={"chunks_restored": restored, "uri": doc_row["document_uri"]}, + ) + + return {"status": "rehydrated", "chunks_restored": restored}
+ +
+
+
+
+ + +
+
+ + Made with Sphinx and @pradyunsg's + + Furo + +
+
+ +
+
+ +
+
+ +
+
+ + + + + \ No newline at end of file diff --git a/docs/_source/_build/html/_modules/aborist/ingest.html b/docs/_source/_build/html/_modules/aborist/ingest.html new file mode 100644 index 0000000..b4e6dcc --- /dev/null +++ b/docs/_source/_build/html/_modules/aborist/ingest.html @@ -0,0 +1,696 @@ + + + + + + + + aborist.ingest - Aborist API Reference + + + + + + + + + + + + + + + + Contents + + + + + + Menu + + + + + + + + Expand + + + + + + Light mode + + + + + + + + + + + + + + Dark mode + + + + + + + Auto light/dark, in light mode + + + + + + + + + + + + + + + Auto light/dark, in dark mode + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Skip to content + + + +
+
+
+ +
+ +
+
+ +
+ +
+
+ +
+
+
+ + + + + Back to top + +
+
+ +
+ +
+
+

Source code for aborist.ingest

+"""Ingest pipeline: Source -> normalize -> chunk -> merkle -> upsert.
+
+Idempotent: re-ingesting the same Document is a no-op (document_root collision
+is the upsert key).
+
+Performance shape — bulk-batched writer:
+  Each batch collapses ALL inserts across N docs into a small set of
+  executemany() calls (one per table) instead of per-doc calls. Audit chain
+  hashes computed in pure Python via store.chain_audit_events, then inserted
+  in one shot. With WAL+synchronous=NORMAL, the dominant cost shifts from
+  Python<->C boundary crossings to actual SQLite work.
+"""
+
+from __future__ import annotations
+
+import sqlite3
+import time
+from dataclasses import dataclass
+
+from aborist import (
+    CANONICALIZATION_VERSION,
+    SCHEMA_VERSION,
+)
+from aborist.compress import pack_chunk, unpack_chunk
+from aborist.document import Document, canonicalize, get_chunker
+from aborist.merkle import MerkleTree, hash_leaf
+from aborist.progress import Progress
+from aborist.source import Source
+from aborist.store import (
+    chain_audit_events,
+    get_meta,
+    latest_event_hash,
+    set_meta,
+    transaction,
+)
+
+
+DEFAULT_BATCH_SIZE = 200
+
+
+@dataclass
+class _DocArtifacts:
+    document_root: str
+    leaves: list[bytes]
+    chunk_strs: list[str]
+    tree: MerkleTree
+
+
+
+[docs] +@dataclass +class IngestStats: + seen: int = 0 + inserted: int = 0 + skipped_duplicate: int = 0 + chunks_total: int = 0 + edges_total: int = 0
+ + + +
+[docs] +def ingest_source( + conn: sqlite3.Connection, + source: Source, + chunker_name: str | None = None, + limit: int | None = None, + batch_size: int = DEFAULT_BATCH_SIZE, + resume: bool = False, + progress: Progress | None = None, +) -> IngestStats: + """Ingest every document the source yields. Returns counts. + + `resume=True` reads the per-source high-water mark from this DB's meta + table and asks the source to fast-forward past it. After each successful + batch flush, the high-water mark is updated in meta. A killed process + can rsync forward by re-running with --resume. + + `progress` (optional) gets a `tick(seen, inserted=...)` call after each + batch flush. Pass an `aborist.progress.Progress` for live stderr output. + """ + chunker = get_chunker(chunker_name) + stats = IngestStats() + batch: list[tuple[Document, _DocArtifacts]] = [] + + meta_key = f"source_high_water:{source.source_type}" + if resume: + prior = get_meta(conn, meta_key) + if prior is not None and hasattr(source, "start_id"): + try: + source.start_id = int(prior) + source.last_id = int(prior) + except (TypeError, ValueError): + pass + + def flush() -> None: + if not batch: + return + inserted, skipped = _flush_batch(conn, batch, chunker.name) + stats.inserted += inserted + stats.skipped_duplicate += skipped + batch.clear() + if hasattr(source, "last_id") and source.last_id: + with transaction(conn): + set_meta(conn, meta_key, str(source.last_id)) + if progress is not None: + progress.tick(stats.seen, inserted=stats.inserted) + + for doc in source.iter_documents(): + stats.seen += 1 + if limit is not None and stats.seen > limit: + break + art = _compute_artifacts(doc, chunker) + if art is None: + stats.skipped_duplicate += 1 + continue + batch.append((doc, art)) + if len(batch) >= batch_size: + flush() + flush() + + if progress is not None: + progress.done(stats.seen, inserted=stats.inserted) + + stats.chunks_total = conn.execute("SELECT COUNT(*) FROM chunks").fetchone()[0] + stats.edges_total = conn.execute("SELECT COUNT(*) FROM edges").fetchone()[0] + return stats
+ + + +def _compute_artifacts(doc: Document, chunker) -> _DocArtifacts | None: + """Pure: canonicalize, chunk, hash leaves, build the tree. No DB access.""" + text = canonicalize(doc.content) + chunk_strs = chunker.split(text) + if not chunk_strs: + return None + leaves = [hash_leaf(c.encode("utf-8")) for c in chunk_strs] + tree = MerkleTree.build(leaves) + return _DocArtifacts( + document_root=tree.root.hex(), + leaves=leaves, + chunk_strs=chunk_strs, + tree=tree, + ) + + +def _flush_batch( + conn: sqlite3.Connection, + batch: list[tuple[Document, _DocArtifacts]], + chunker_name: str, +) -> tuple[int, int]: + """Bulk-insert the whole batch. Returns (inserted, skipped_duplicate). + + All collisions and prior-version lookups happen up front via batched + SELECTs. New rows accumulate into per-table mega-lists and flush via + one executemany per table. Audit-chain hashes are computed in pure + Python and inserted in one shot. + """ + inserted = 0 + skipped = 0 + ingest_ts = int(time.time()) + + with transaction(conn): + # 1) Collision check: which document_roots already exist? + roots = [art.document_root for _, art in batch] + existing: set[str] = _select_existing_roots(conn, roots) + inserted_this_batch: set[str] = set() + # Pre-compute the chunk_id range we'll use this batch. Reading MAX + # under BEGIN IMMEDIATE is safe — concurrent writers serialize on + # the WAL writer lock, so this snapshot won't race. + next_chunk_id = ( + conn.execute("SELECT COALESCE(MAX(chunk_id), 0) FROM chunks") + .fetchone()[0] + + 1 + ) + + # 2) Batched prior-URI resolution: one IN-clause SELECT instead of + # one per-doc SELECT. Maps each URI to the most-recent existing + # document_root in the DB (pre-batch state). + new_uris = list({doc.uri for doc, art in batch + if art.document_root not in existing}) + prior_db: dict[str, str] = {} + for slab_start in range(0, len(new_uris), 500): + slab = new_uris[slab_start : slab_start + 500] + placeholders = ",".join("?" * len(slab)) + for row in conn.execute( + "SELECT document_uri, document_root FROM documents " + f"WHERE document_uri IN ({placeholders}) " + "ORDER BY ingest_ts DESC", + slab, + ): + # First wins (most recent by ORDER BY DESC). + prior_db.setdefault(row["document_uri"], row["document_root"]) + + # Within-batch chain state: as we process, the "prior" for the next + # doc with the same URI becomes the doc we just inserted. + prior_for_doc: dict[str, str] = {} + + documents_rows: list[tuple] = [] + chunk_rows: list[tuple] = [] + fts_rows: list[tuple] = [] + merkle_rows: list[tuple] = [] + edge_rows: list[tuple] = [] + audit_events: list[dict] = [] + edges_to_upsert: list[tuple[str, Document]] = [] + + for doc, art in batch: + if art.document_root in existing or art.document_root in inserted_this_batch: + edges_to_upsert.append((art.document_root, doc)) + skipped += 1 + continue + + prior_root = prior_for_doc.get(doc.uri) or prior_db.get(doc.uri) + if prior_root == art.document_root: + prior_root = None # same content, not a real prior + + documents_rows.append( + ( + art.document_root, + doc.uri, + doc.source_type, + doc.title, + chunker_name, + CANONICALIZATION_VERSION, + SCHEMA_VERSION, + ingest_ts, + ) + ) + for i, c in enumerate(art.chunk_strs): + chunk_id = next_chunk_id + next_chunk_id += 1 + chunk_rows.append( + (chunk_id, art.document_root, i, art.leaves[i].hex(), pack_chunk(c)) + ) + # Contentless FTS5 indexes the plaintext but stores no copy; + # rowid must equal chunks.chunk_id so search-time JOINs line up. + fts_rows.append((chunk_id, c)) + for layer_idx in range(1, len(art.tree.layers)): + for node_idx, h in enumerate(art.tree.layers[layer_idx]): + merkle_rows.append( + (art.document_root, layer_idx, node_idx, h.hex()) + ) + if prior_root is not None: + edge_rows.append( + (art.document_root, prior_root, doc.uri, "supersedes", "") + ) + edges_to_upsert.append((art.document_root, doc)) + inserted_this_batch.add(art.document_root) + prior_for_doc[doc.uri] = art.document_root + audit_events.append( + { + "event_type": "ingest", + "subject_root": art.document_root, + "ts": ingest_ts, + "body": { + "document_uri": doc.uri, + "source_type": doc.source_type, + "chunks": len(art.chunk_strs), + "chunking_version": chunker_name, + "canonicalization_version": CANONICALIZATION_VERSION, + "schema_version": SCHEMA_VERSION, + "supersedes": prior_root, + }, + } + ) + inserted += 1 + + # 3) One executemany per table — minimal Python<->C boundary crossings. + if documents_rows: + conn.executemany( + "INSERT INTO documents " + "(document_root, document_uri, source_type, kind, compression_depth, " + " title, chunking_version, canonicalization_version, schema_version, " + " ingest_ts) " + "VALUES (?, ?, ?, 'surface', 0, ?, ?, ?, ?, ?)", + documents_rows, + ) + if chunk_rows: + conn.executemany( + "INSERT INTO chunks (chunk_id, document_root, idx, leaf_hash, content) " + "VALUES (?, ?, ?, ?, ?)", + chunk_rows, + ) + conn.executemany( + "INSERT INTO chunks_fts (rowid, content) VALUES (?, ?)", + fts_rows, + ) + if merkle_rows: + conn.executemany( + "INSERT INTO merkle_nodes (document_root, layer, idx, hash) " + "VALUES (?, ?, ?, ?)", + merkle_rows, + ) + + # 4) Edges: collect all wikilinks across the batch and resolve in + # one SELECT. Then one executemany. + _flush_edges(conn, edges_to_upsert) + if edge_rows: + conn.executemany( + "INSERT OR IGNORE INTO edges " + "(src_root, dst_root, dst_uri, edge_type, anchor) " + "VALUES (?, ?, ?, ?, ?)", + edge_rows, + ) + + # 5) Audit chain — hashes computed in Python, inserted in one call. + if audit_events: + prev = latest_event_hash(conn) + audit_rows, _ = chain_audit_events(prev, audit_events) + conn.executemany( + "INSERT INTO audit_events " + "(event_hash, prev_event_hash, event_type, subject_root, body, ts) " + "VALUES (?, ?, ?, ?, ?, ?)", + audit_rows, + ) + + return inserted, skipped + + +def _select_existing_roots( + conn: sqlite3.Connection, roots: list[str] +) -> set[str]: + """Single SELECT to find which document_roots already exist.""" + if not roots: + return set() + # SQLite has a default 999-param limit; chunk just in case. + found: set[str] = set() + for i in range(0, len(roots), 500): + slab = roots[i : i + 500] + placeholders = ",".join("?" * len(slab)) + for row in conn.execute( + f"SELECT document_root FROM documents WHERE document_root IN ({placeholders})", + slab, + ): + found.add(row["document_root"]) + return found + + +def _flush_edges( + conn: sqlite3.Connection, + edges_to_upsert: list[tuple[str, Document]], +) -> None: + """Upsert all wikilink/hyperlink edges across the batch. + + Resolves dst_root for previously-unresolved URIs using a single batched + SELECT (URI -> document_root) instead of N per-edge SELECTs. + """ + if not edges_to_upsert: + return + + # Collect distinct dst_uris across the batch for one resolution lookup. + distinct_uris: set[str] = set() + for _, doc in edges_to_upsert: + for e in doc.edges: + if e.dst_uri: + distinct_uris.add(e.dst_uri) + + uri_to_root: dict[str, str] = {} + if distinct_uris: + uris_list = list(distinct_uris) + for i in range(0, len(uris_list), 500): + slab = uris_list[i : i + 500] + placeholders = ",".join("?" * len(slab)) + for row in conn.execute( + "SELECT document_uri, document_root FROM documents " + f"WHERE document_uri IN ({placeholders})", + slab, + ): + # Earliest ingest wins (matches prior LIMIT 1 ASC behavior). + uri_to_root.setdefault(row["document_uri"], row["document_root"]) + + rows: list[tuple] = [] + for src_root, doc in edges_to_upsert: + for e in doc.edges: + dst_root = e.dst_root or uri_to_root.get(e.dst_uri or "", "") + rows.append( + ( + src_root, + dst_root, + e.dst_uri or "", + e.edge_type, + e.anchor or "", + ) + ) + if rows: + conn.executemany( + "INSERT OR IGNORE INTO edges " + "(src_root, dst_root, dst_uri, edge_type, anchor) VALUES (?, ?, ?, ?, ?)", + rows, + ) + + +
+[docs] +def verify_random_sample(conn: sqlite3.Connection, n: int = 10) -> dict: + """Sample N documents, regenerate Merkle proof for chunk 0, verify.""" + from aborist.merkle import hash_leaf, verify_proof + + rows = conn.execute( + "SELECT document_root FROM documents ORDER BY RANDOM() LIMIT ?", (n,) + ).fetchall() + if not rows: + return {"sampled": 0, "passed": 0, "failed": 0} + + passed = 0 + failed = 0 + for row in rows: + document_root = row["document_root"] + chunk_rows = conn.execute( + "SELECT idx, leaf_hash, content FROM chunks " + "WHERE document_root = ? ORDER BY idx ASC", + (document_root,), + ).fetchall() + if not chunk_rows: + failed += 1 + continue + leaves = [bytes.fromhex(r["leaf_hash"]) for r in chunk_rows] + c0 = chunk_rows[0] + c0_content = unpack_chunk(c0["content"]) + if c0_content is not None: + recomputed_leaf = hash_leaf(c0_content.encode("utf-8")) + if recomputed_leaf != leaves[0]: + failed += 1 + continue + tree = MerkleTree.build(leaves) + if tree.root.hex() != document_root: + failed += 1 + continue + proof = tree.proof(0) + if verify_proof(proof) and proof.root.hex() == document_root: + passed += 1 + else: + failed += 1 + return {"sampled": len(rows), "passed": passed, "failed": failed}
+ +
+
+
+
+ + +
+
+ + Made with Sphinx and @pradyunsg's + + Furo + +
+
+ +
+
+ +
+
+ +
+
+ + + + + \ No newline at end of file diff --git a/docs/_source/_build/html/_modules/aborist/merkle.html b/docs/_source/_build/html/_modules/aborist/merkle.html new file mode 100644 index 0000000..5442824 --- /dev/null +++ b/docs/_source/_build/html/_modules/aborist/merkle.html @@ -0,0 +1,461 @@ + + + + + + + + aborist.merkle - Aborist API Reference + + + + + + + + + + + + + + + + Contents + + + + + + Menu + + + + + + + + Expand + + + + + + Light mode + + + + + + + + + + + + + + Dark mode + + + + + + + Auto light/dark, in light mode + + + + + + + + + + + + + + + Auto light/dark, in dark mode + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Skip to content + + + +
+
+
+ +
+ +
+
+ +
+ +
+
+ +
+
+
+ + + + + Back to top + +
+
+ +
+ +
+
+

Source code for aborist.merkle

+"""Merkle tree with non-commutative HashCombine.
+
+Python port of ~/git/proxy.unturf.com/pkg/verified/merkle.go conventions:
+
+- Domain separation via single-byte prefixes (leaf=0x00, node=0x03).
+- HashCombine is non-commutative; sibling order matters always.
+- Odd layers self-duplicate the trailing element (NOT zero-pad).
+- Proof carries explicit IsLeft flag per sibling (NOT lexical sort).
+- Empty tree root is ZeroHash (32 zero bytes).
+"""
+
+from __future__ import annotations
+
+import hashlib
+from dataclasses import dataclass, field
+from typing import Iterable
+
+LEAF_PREFIX = b"\x00"
+NODE_PREFIX = b"\x03"
+ZERO_HASH = b"\x00" * 32
+HASH_LEN = 32
+
+
+def _sha256(*parts: bytes) -> bytes:
+    h = hashlib.sha256()
+    for p in parts:
+        h.update(p)
+    return h.digest()
+
+
+
+[docs] +def hash_leaf(content: bytes) -> bytes: + """Hash a leaf with domain prefix 0x00.""" + return _sha256(LEAF_PREFIX, content)
+ + + +
+[docs] +def hash_combine(left: bytes, right: bytes) -> bytes: + """Non-commutative interior combine with domain prefix 0x03.""" + if len(left) != HASH_LEN or len(right) != HASH_LEN: + raise ValueError("hash inputs must be 32 bytes") + return _sha256(NODE_PREFIX, left, right)
+ + + +
+[docs] +@dataclass(frozen=True) +class ProofNode: + """One sibling step in a Merkle inclusion proof. + + is_left=True means the sibling sits to the LEFT of the running hash, + so verification order is: HashCombine(sibling, current). + """ + + hash: bytes + is_left: bool
+ + + +
+[docs] +@dataclass(frozen=True) +class MerkleProof: + """Merkle inclusion proof: leaf + index + sibling path to root. + + Proves that a leaf at leaf_index exists in a tree with the given root. + verify_proof() recomputes the root by combining the leaf with siblings. + """ + leaf: bytes + leaf_index: int + siblings: tuple[ProofNode, ...] + root: bytes
+ + + +
+[docs] +@dataclass +class MerkleTree: + """Layered tree. layers[0] = leaves, layers[-1] = [root].""" + + layers: list[list[bytes]] = field(default_factory=list) + + @property + def root(self) -> bytes: + """Root hash of the tree (topmost layer). Empty tree → ZERO_HASH.""" + if not self.layers or not self.layers[-1]: + return ZERO_HASH + return self.layers[-1][0] + + @property + def leaves(self) -> list[bytes]: + """Leaf hashes in input order (bottom layer of tree).""" + return self.layers[0] if self.layers else [] + +
+[docs] + @classmethod + def build(cls, leaves: Iterable[bytes]) -> MerkleTree: + """Build tree from leaf hashes. Applies odd-element self-duplication.""" + leaves = list(leaves) + if not leaves: + return cls(layers=[[]]) + layers: list[list[bytes]] = [list(leaves)] + current = list(leaves) + while len(current) > 1: + nxt: list[bytes] = [] + i = 0 + while i < len(current): + left = current[i] + right = current[i + 1] if i + 1 < len(current) else current[i] + nxt.append(hash_combine(left, right)) + i += 2 + layers.append(nxt) + current = nxt + return cls(layers=layers)
+ + +
+[docs] + def proof(self, leaf_index: int) -> MerkleProof: + """Generate inclusion proof for the leaf at leaf_index.""" + if not self.layers or not self.layers[0]: + raise IndexError("empty tree has no proofs") + if leaf_index < 0 or leaf_index >= len(self.layers[0]): + raise IndexError(f"leaf_index {leaf_index} out of range") + + siblings: list[ProofNode] = [] + idx = leaf_index + # Walk up every layer except the root layer. + for layer in self.layers[:-1]: + if idx % 2 == 0: + sibling_idx = idx + 1 + is_left = False # sibling is to our right + else: + sibling_idx = idx - 1 + is_left = True # sibling is to our left + if sibling_idx >= len(layer): + # odd-element rule: self-duplicate + sibling_idx = idx + siblings.append(ProofNode(hash=layer[sibling_idx], is_left=is_left)) + idx //= 2 + + return MerkleProof( + leaf=self.layers[0][leaf_index], + leaf_index=leaf_index, + siblings=tuple(siblings), + root=self.root, + )
+
+ + + +
+[docs] +def verify_proof(proof: MerkleProof) -> bool: + """Recompute root from leaf + sibling path. Returns True iff matches.""" + current = proof.leaf + for node in proof.siblings: + if node.is_left: + current = hash_combine(node.hash, current) + else: + current = hash_combine(current, node.hash) + return current == proof.root
+ + + +
+[docs] +def proof_to_dict(proof: MerkleProof) -> dict: + """JSON-serializable form for storage in providence_cache.merkle_proof.""" + return { + "leaf": proof.leaf.hex(), + "leaf_index": proof.leaf_index, + "siblings": [ + {"hash": s.hash.hex(), "is_left": s.is_left} for s in proof.siblings + ], + "root": proof.root.hex(), + }
+ + + +
+[docs] +def proof_from_dict(d: dict) -> MerkleProof: + """Deserialize a proof from JSON dict (inverse of proof_to_dict).""" + return MerkleProof( + leaf=bytes.fromhex(d["leaf"]), + leaf_index=int(d["leaf_index"]), + siblings=tuple( + ProofNode(hash=bytes.fromhex(s["hash"]), is_left=bool(s["is_left"])) + for s in d["siblings"] + ), + root=bytes.fromhex(d["root"]), + )
+ +
+
+
+
+ + +
+
+ + Made with Sphinx and @pradyunsg's + + Furo + +
+
+ +
+
+ +
+
+ +
+
+ + + + + \ No newline at end of file diff --git a/docs/_source/_build/html/_modules/aborist/mesh/crypto.html b/docs/_source/_build/html/_modules/aborist/mesh/crypto.html new file mode 100644 index 0000000..59fec9f --- /dev/null +++ b/docs/_source/_build/html/_modules/aborist/mesh/crypto.html @@ -0,0 +1,387 @@ + + + + + + + + aborist.mesh.crypto - Aborist API Reference + + + + + + + + + + + + + + + + Contents + + + + + + Menu + + + + + + + + Expand + + + + + + Light mode + + + + + + + + + + + + + + Dark mode + + + + + + + Auto light/dark, in light mode + + + + + + + + + + + + + + + Auto light/dark, in dark mode + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Skip to content + + + +
+
+
+ +
+ +
+
+ +
+ +
+
+ +
+
+
+ + + + + Back to top + +
+
+ +
+ +
+
+

Source code for aborist.mesh.crypto

+"""Cryptographic primitives for the mesh layer.
+
+Ed25519 for signing (membership events, gossip envelopes).
+X25519 for key agreement (wrap epoch secrets per-member).
+ChaCha20-Poly1305 for AEAD (optional payload encryption).
+
+All key material is bytes (raw 32-byte forms) so the storage layer can
+keep keys in BLOB columns without serialization. The `cryptography`
+library is the audited backend; this module is a thin wrapper that
+hides the import surface and enforces consistent error handling.
+"""
+
+from __future__ import annotations
+
+from cryptography.exceptions import InvalidSignature, InvalidTag
+from cryptography.hazmat.primitives import hashes
+from cryptography.hazmat.primitives.asymmetric import ed25519, x25519
+from cryptography.hazmat.primitives.ciphers.aead import ChaCha20Poly1305
+from cryptography.hazmat.primitives.kdf.hkdf import HKDF
+
+
+# -----------------------------------------------------------------------------
+# Ed25519 — signing
+# -----------------------------------------------------------------------------
+
+
+
+[docs] +def generate_signing_keypair() -> tuple[bytes, bytes]: + """Return (priv_bytes, pub_bytes) for a fresh Ed25519 keypair.""" + priv = ed25519.Ed25519PrivateKey.generate() + priv_bytes = priv.private_bytes_raw() + pub_bytes = priv.public_key().public_bytes_raw() + return priv_bytes, pub_bytes
+ + + +
+[docs] +def sign(priv_bytes: bytes, message: bytes) -> bytes: + """Ed25519 sign. 64-byte signature.""" + priv = ed25519.Ed25519PrivateKey.from_private_bytes(priv_bytes) + return priv.sign(message)
+ + + +
+[docs] +def verify(pub_bytes: bytes, signature: bytes, message: bytes) -> bool: + """Ed25519 verify. Returns True/False — never raises.""" + try: + pub = ed25519.Ed25519PublicKey.from_public_bytes(pub_bytes) + pub.verify(signature, message) + return True + except (InvalidSignature, ValueError): + return False
+ + + +# ----------------------------------------------------------------------------- +# X25519 — key agreement for wrapping epoch secrets per-member +# ----------------------------------------------------------------------------- + + +
+[docs] +def generate_dh_keypair() -> tuple[bytes, bytes]: + """Return (priv_bytes, pub_bytes) for a fresh X25519 keypair.""" + priv = x25519.X25519PrivateKey.generate() + priv_bytes = priv.private_bytes_raw() + pub_bytes = priv.public_key().public_bytes_raw() + return priv_bytes, pub_bytes
+ + + +
+[docs] +def ecdh_shared_secret(priv_bytes: bytes, peer_pub_bytes: bytes) -> bytes: + """X25519 ECDH -> 32-byte shared secret (HKDF-extracted).""" + priv = x25519.X25519PrivateKey.from_private_bytes(priv_bytes) + peer = x25519.X25519PublicKey.from_public_bytes(peer_pub_bytes) + raw = priv.exchange(peer) + # HKDF-Extract+Expand to a 32-byte AEAD key. The salt is fixed; the + # info string distinguishes this key from any other use of ECDH on + # the same peer-pair (e.g. if we ever add another protocol layer). + return HKDF( + algorithm=hashes.SHA256(), + length=32, + salt=b"aborist.mesh.epoch.v1", + info=b"epoch-secret-wrap", + ).derive(raw)
+ + + +# ----------------------------------------------------------------------------- +# AEAD — ChaCha20-Poly1305 for envelope payloads + secret wrapping +# ----------------------------------------------------------------------------- + + +
+[docs] +def aead_encrypt(key: bytes, nonce: bytes, plaintext: bytes, aad: bytes = b"") -> bytes: + """Encrypt + authenticate. Returns ciphertext||tag.""" + if len(key) != 32: + raise ValueError("AEAD key must be 32 bytes") + if len(nonce) != 12: + raise ValueError("ChaCha20-Poly1305 nonce must be 12 bytes") + cipher = ChaCha20Poly1305(key) + return cipher.encrypt(nonce, plaintext, aad)
+ + + +
+[docs] +def aead_decrypt(key: bytes, nonce: bytes, ciphertext: bytes, aad: bytes = b"") -> bytes: + """Decrypt + verify. Raises ValueError on tag mismatch (no plaintext leak).""" + if len(key) != 32: + raise ValueError("AEAD key must be 32 bytes") + if len(nonce) != 12: + raise ValueError("ChaCha20-Poly1305 nonce must be 12 bytes") + cipher = ChaCha20Poly1305(key) + try: + return cipher.decrypt(nonce, ciphertext, aad) + except InvalidTag as e: + raise ValueError("AEAD authentication failed") from e
+ +
+
+
+
+ + +
+
+ + Made with Sphinx and @pradyunsg's + + Furo + +
+
+ +
+
+ +
+
+ +
+
+ + + + + \ No newline at end of file diff --git a/docs/_source/_build/html/_modules/aborist/mesh/state.html b/docs/_source/_build/html/_modules/aborist/mesh/state.html new file mode 100644 index 0000000..4cfcfb0 --- /dev/null +++ b/docs/_source/_build/html/_modules/aborist/mesh/state.html @@ -0,0 +1,685 @@ + + + + + + + + aborist.mesh.state - Aborist API Reference + + + + + + + + + + + + + + + + Contents + + + + + + Menu + + + + + + + + Expand + + + + + + Light mode + + + + + + + + + + + + + + Dark mode + + + + + + + Auto light/dark, in light mode + + + + + + + + + + + + + + + Auto light/dark, in dark mode + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Skip to content + + + +
+
+
+ +
+ +
+
+ +
+ +
+
+ +
+
+
+ + + + + Back to top + +
+
+ +
+ +
+
+

Source code for aborist.mesh.state

+"""Mesh state persisted in the standard aborist DB.
+
+Three tables (defined in `aborist.store.SCHEMA_SQL`):
+  mesh_identity  — this peer's keys + group name (singleton)
+  mesh_roster    — per-epoch (member_id, sign_pub, dh_pub, role) tuples
+  mesh_epochs    — epoch lifecycle: started_at, audit linkage, secret envelope
+
+The `meta.mesh.enabled` flag gates everything. Default off. Mesh-related
+CLI commands and any future network code paths short-circuit when the
+flag is unset / '0'.
+"""
+
+from __future__ import annotations
+
+import base64
+import json
+import os
+import sqlite3
+import time
+import uuid
+from dataclasses import dataclass
+
+from aborist.mesh.crypto import (
+    aead_decrypt,
+    aead_encrypt,
+    ecdh_shared_secret,
+    generate_dh_keypair,
+    generate_signing_keypair,
+)
+from aborist.store import (
+    append_audit,
+    get_meta,
+    set_meta,
+    transaction,
+)
+
+
+MESH_ENABLED_KEY = "mesh.enabled"
+
+
+
+[docs] +@dataclass +class MeshIdentity: + member_id: str + sign_priv: bytes + sign_pub: bytes + dh_priv: bytes + dh_pub: bytes + group_name: str + created_at: int
+ + + +
+[docs] +@dataclass +class MeshRosterEntry: + member_id: str + sign_pub: bytes + dh_pub: bytes + role: str # 'admin' | 'member'
+ + + +# --------------------------------------------------------------------------- +# Enable / disable flag +# --------------------------------------------------------------------------- + + +
+[docs] +def is_enabled(conn: sqlite3.Connection) -> bool: + return get_meta(conn, MESH_ENABLED_KEY) == "1"
+ + + +
+[docs] +def set_enabled(conn: sqlite3.Connection, enabled: bool) -> None: + with transaction(conn): + set_meta(conn, MESH_ENABLED_KEY, "1" if enabled else "0") + append_audit( + conn, + event_type="mesh_enable" if enabled else "mesh_disable", + body={"enabled": bool(enabled)}, + )
+ + + +# --------------------------------------------------------------------------- +# Identity +# --------------------------------------------------------------------------- + + +
+[docs] +def init_identity( + conn: sqlite3.Connection, + *, + group_name: str, + member_id: str | None = None, +) -> MeshIdentity: + """Generate this peer's keys and seed epoch 0 with this peer as founding admin. + + Idempotent on re-call only in the sense that it raises — the schema + enforces a singleton via PK = 1. Caller is expected to check + load_identity() first. + """ + if load_identity(conn) is not None: + raise RuntimeError("mesh identity already initialized") + sign_priv, sign_pub = generate_signing_keypair() + dh_priv, dh_pub = generate_dh_keypair() + member_id = member_id or _short_id() + now = int(time.time()) + + with transaction(conn): + conn.execute( + "INSERT INTO mesh_identity " + "(id, member_id, sign_priv, sign_pub, dh_priv, dh_pub, group_name, created_at) " + "VALUES (1, ?, ?, ?, ?, ?, ?, ?)", + (member_id, sign_priv, sign_pub, dh_priv, dh_pub, group_name, now), + ) + # Epoch 0 — founder is sole admin. + conn.execute( + "INSERT INTO mesh_roster (epoch_id, member_id, sign_pub, dh_pub, role) " + "VALUES (0, ?, ?, ?, 'admin')", + (member_id, sign_pub, dh_pub), + ) + # Epoch 0 secret: random 32-byte symmetric key, wrapped to founder's + # own DH key. (One-member envelope is degenerate but the structure + # is consistent — every later rotate appends a fresh entry.) + secret = os.urandom(32) + envelope = _wrap_secret_for_members( + secret, + members=[(member_id, dh_pub)], + sender_dh_priv=dh_priv, + ) + conn.execute( + "INSERT INTO mesh_epochs " + "(epoch_id, started_at, started_event_hash, secret_envelope, reason) " + "VALUES (0, ?, '', ?, 'genesis')", + (now, json.dumps(envelope, separators=(",", ":"), sort_keys=True)), + ) + event_hash = append_audit( + conn, + event_type="mesh_init", + body={ + "group_name": group_name, + "founder": member_id, + "sign_pub_hex": sign_pub.hex(), + "dh_pub_hex": dh_pub.hex(), + }, + ) + # Backfill the epoch's audit linkage. + with transaction(conn): + conn.execute( + "UPDATE mesh_epochs SET started_event_hash = ? WHERE epoch_id = 0", + (event_hash,), + ) + return MeshIdentity( + member_id=member_id, + sign_priv=sign_priv, + sign_pub=sign_pub, + dh_priv=dh_priv, + dh_pub=dh_pub, + group_name=group_name, + created_at=now, + )
+ + + +
+[docs] +def load_identity(conn: sqlite3.Connection) -> MeshIdentity | None: + row = conn.execute( + "SELECT member_id, sign_priv, sign_pub, dh_priv, dh_pub, group_name, created_at " + "FROM mesh_identity WHERE id = 1" + ).fetchone() + if row is None: + return None + return MeshIdentity( + member_id=row["member_id"], + sign_priv=bytes(row["sign_priv"]), + sign_pub=bytes(row["sign_pub"]), + dh_priv=bytes(row["dh_priv"]), + dh_pub=bytes(row["dh_pub"]), + group_name=row["group_name"], + created_at=int(row["created_at"]), + )
+ + + +# --------------------------------------------------------------------------- +# Roster + epoch queries +# --------------------------------------------------------------------------- + + +
+[docs] +def current_epoch(conn: sqlite3.Connection) -> int | None: + row = conn.execute("SELECT MAX(epoch_id) AS e FROM mesh_epochs").fetchone() + if row is None or row["e"] is None: + return None + return int(row["e"])
+ + + +def roster_at(conn: sqlite3.Connection, epoch_id: int) -> list[MeshRosterEntry]: + rows = conn.execute( + "SELECT member_id, sign_pub, dh_pub, role " + "FROM mesh_roster WHERE epoch_id = ? ORDER BY member_id", + (epoch_id,), + ).fetchall() + return [ + MeshRosterEntry( + member_id=r["member_id"], + sign_pub=bytes(r["sign_pub"]), + dh_pub=bytes(r["dh_pub"]), + role=r["role"], + ) + for r in rows + ] + + +# --------------------------------------------------------------------------- +# Epoch rotation (also used for join + kick) +# --------------------------------------------------------------------------- + + +def rotate_epoch( + conn: sqlite3.Connection, + *, + new_members: list[MeshRosterEntry], + reason: str, + actor_member_id: str, +) -> int: + """Create a new epoch with the given roster. + + `new_members` is the FULL post-rotation roster (not a diff). Eviction = + omit a member from new_members. Joins = include a new member. The + secret envelope is regenerated and wrapped to every new member's DH + pubkey via ECDH from this peer's own DH private key. + + Caller is responsible for verifying authority (e.g., admin role) before + calling. Audit chain records the rotation rationale. + """ + me = load_identity(conn) + if me is None: + raise RuntimeError("no mesh identity; call init_identity first") + prior = current_epoch(conn) + if prior is None: + raise RuntimeError("no prior epoch; call init_identity first") + new_epoch = prior + 1 + + secret = os.urandom(32) + envelope = _wrap_secret_for_members( + secret, + members=[(m.member_id, m.dh_pub) for m in new_members], + sender_dh_priv=me.dh_priv, + ) + + with transaction(conn): + for m in new_members: + conn.execute( + "INSERT INTO mesh_roster (epoch_id, member_id, sign_pub, dh_pub, role) " + "VALUES (?, ?, ?, ?, ?)", + (new_epoch, m.member_id, m.sign_pub, m.dh_pub, m.role), + ) + conn.execute( + "INSERT INTO mesh_epochs " + "(epoch_id, started_at, started_event_hash, secret_envelope, reason) " + "VALUES (?, ?, '', ?, ?)", + ( + new_epoch, + int(time.time()), + json.dumps(envelope, separators=(",", ":"), sort_keys=True), + reason, + ), + ) + event_hash = append_audit( + conn, + event_type="mesh_epoch_rotate", + body={ + "actor": actor_member_id, + "new_epoch": new_epoch, + "members": [m.member_id for m in new_members], + "reason": reason, + }, + ) + with transaction(conn): + conn.execute( + "UPDATE mesh_epochs SET started_event_hash = ? WHERE epoch_id = ?", + (event_hash, new_epoch), + ) + return new_epoch + + +# --------------------------------------------------------------------------- +# Helpers +# --------------------------------------------------------------------------- + + +def _short_id() -> str: + """8-hex-char member id. Collisions across a small mesh are negligible.""" + return uuid.uuid4().hex[:8] + + +def _wrap_secret_for_members( + secret: bytes, + *, + members: list[tuple[str, bytes]], + sender_dh_priv: bytes, +) -> dict[str, dict[str, str]]: + """Per-member ECDH+AEAD wrap of the epoch secret. + + Each member gets a dict {nonce_b64, ct_b64}. Decrypt path: derive the + same shared secret via ECDH(member_dh_priv, sender_dh_pub), then + ChaCha20-Poly1305 decrypt with the recorded nonce. + """ + envelope: dict[str, dict[str, str]] = {} + for member_id, member_dh_pub in members: + shared = ecdh_shared_secret(sender_dh_priv, member_dh_pub) + nonce = os.urandom(12) + ct = aead_encrypt(shared, nonce, secret, aad=member_id.encode("utf-8")) + envelope[member_id] = { + "nonce_b64": base64.b64encode(nonce).decode("ascii"), + "ct_b64": base64.b64encode(ct).decode("ascii"), + } + return envelope + + +def unwrap_secret_for_self( + conn: sqlite3.Connection, + *, + epoch_id: int, + sender_dh_pub: bytes, +) -> bytes: + """Recover the symmetric epoch secret using this peer's DH private key. + + `sender_dh_pub` is the wrapping peer's X25519 pubkey (typically the + epoch's rotator). Raises ValueError if this peer has no entry in the + epoch's envelope (i.e. they were evicted) or if the AEAD tag mismatches. + """ + me = load_identity(conn) + if me is None: + raise RuntimeError("no mesh identity") + row = conn.execute( + "SELECT secret_envelope FROM mesh_epochs WHERE epoch_id = ?", + (epoch_id,), + ).fetchone() + if row is None: + raise ValueError(f"unknown epoch: {epoch_id}") + envelope = json.loads(row["secret_envelope"]) + entry = envelope.get(me.member_id) + if entry is None: + raise ValueError( + f"this peer ({me.member_id}) is not in epoch {epoch_id}'s envelope" + ) + nonce = base64.b64decode(entry["nonce_b64"]) + ct = base64.b64decode(entry["ct_b64"]) + shared = ecdh_shared_secret(me.dh_priv, sender_dh_pub) + return aead_decrypt(shared, nonce, ct, aad=me.member_id.encode("utf-8")) + + +def recover_epoch_secret( + conn: sqlite3.Connection, + *, + epoch_id: int, +) -> bytes: + """Convenience: locate the rotator's dh_pub locally and unwrap our slot. + + The rotator is recorded in the epoch's audit event body — `actor` for + rotations (epoch >= 1), `founder` for the genesis epoch 0. We resolve + the actor's dh_pub via `mesh_roster` at that epoch (the actor was a + member of the post-rotation roster by construction). Then we hand off + to `unwrap_secret_for_self`. + + This is the path used by both senders (re-unwrapping their own slot + to AEAD-encrypt outbound gossip) and receivers (decrypting an inbound + encrypted body). Sender-side it's the simplest answer to "where does + the sender get the epoch secret" without a new caching layer. + + Raises: + RuntimeError if mesh identity not initialized. + ValueError if the epoch row is missing, the audit event is missing, + the actor is not in the epoch's roster, this peer has no slot in + the envelope (evicted), or the AEAD tag mismatches. + """ + row = conn.execute( + "SELECT started_event_hash FROM mesh_epochs WHERE epoch_id = ?", + (epoch_id,), + ).fetchone() + if row is None: + raise ValueError(f"unknown epoch: {epoch_id}") + started_event_hash = row["started_event_hash"] + if not started_event_hash: + raise ValueError(f"epoch {epoch_id} has no audit linkage") + ev = conn.execute( + "SELECT body FROM audit_events WHERE event_hash = ?", + (started_event_hash,), + ).fetchone() + if ev is None: + raise ValueError( + f"epoch {epoch_id} audit event {started_event_hash!r} not found" + ) + body = json.loads(ev["body"]) + # Genesis writes "founder"; rotations write "actor". + actor = body.get("actor") or body.get("founder") + if not actor: + raise ValueError( + f"epoch {epoch_id} audit body has no actor/founder field" + ) + rotator = next( + (m for m in roster_at(conn, epoch_id) if m.member_id == actor), + None, + ) + if rotator is None: + raise ValueError( + f"rotator {actor!r} not in epoch {epoch_id} roster" + ) + return unwrap_secret_for_self( + conn, epoch_id=epoch_id, sender_dh_pub=rotator.dh_pub + ) +
+
+
+
+ + +
+
+ + Made with Sphinx and @pradyunsg's + + Furo + +
+
+ +
+
+ +
+
+ +
+
+ + + + + \ No newline at end of file diff --git a/docs/_source/_build/html/_modules/aborist/qa/client.html b/docs/_source/_build/html/_modules/aborist/qa/client.html new file mode 100644 index 0000000..841675f --- /dev/null +++ b/docs/_source/_build/html/_modules/aborist/qa/client.html @@ -0,0 +1,493 @@ + + + + + + + + aborist.qa.client - Aborist API Reference + + + + + + + + + + + + + + + + Contents + + + + + + Menu + + + + + + + + Expand + + + + + + Light mode + + + + + + + + + + + + + + Dark mode + + + + + + + Auto light/dark, in light mode + + + + + + + + + + + + + + + Auto light/dark, in dark mode + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Skip to content + + + +
+
+
+ +
+ +
+
+ +
+ +
+
+ +
+
+
+ + + + + Back to top + +
+
+ +
+ +
+
+

Source code for aborist.qa.client

+"""Chat-completion clients.
+
+ChatClient is a Protocol — any object with a `chat_completion` method
+plugs in. We ship two concrete clients:
+
+- OpenAICompatibleClient — talks to any OpenAI-compatible /v1/chat/completions
+  endpoint (vllm, llama.cpp server, ollama, TGI, hosted services).
+- StubClient — offline canned responses for tests and dry-runs. No
+  network. Operation Voyeur safe.
+"""
+
+from __future__ import annotations
+
+from typing import Protocol
+
+
+
+[docs] +class ChatClient(Protocol): +
+[docs] + def chat_completion( + self, + messages: list[dict], + *, + model: str, + temperature: float = 0.1, + max_tokens: int = 512, + top_p: float = 1.0, + extra_body: dict | None = None, + ) -> str: + """Return the assistant's text response. + + ``extra_body`` is forwarded as additional fields in the JSON + request payload — used for vLLM-specific knobs like + ``guided_json`` (constrain output to a JSON Schema at sampling + time, eliminating SCHEMA_INVALID failures from prompt drift). + Endpoints that don't recognize the field ignore it; the client + passes it through opaque-ly. + """ + ...
+
+ + + +
+[docs] +class StubClient: + """Offline client for tests / --dry-run. + + Pass `answer=callable(messages, **kw) -> str` for dynamic stubbing. + """ + + def __init__(self, answer="[STUB] dry-run answer; no LLM was called."): + self._answer = answer + self.calls: list[dict] = [] + +
+[docs] + def chat_completion(self, messages, **kwargs) -> str: + self.calls.append({"messages": messages, "kwargs": kwargs}) + if callable(self._answer): + return self._answer(messages, **kwargs) + return self._answer
+
+ + + # StubClient ignores extra_body — the offline path doesn't go through + # any inference engine that would honor grammar guidance. Tests that + # want to assert extra_body was passed should inspect `self.calls`. + + +
+[docs] +class OpenAICompatibleClient: + """OpenAI-compatible chat completion over HTTP. + + Default endpoint is configurable via env. Pass api_key only if the + target requires it; uncloseai's free endpoint does not. + + 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 `guided_json` 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. + """ + + # HTTP status codes worth retrying — transient gateway/server + # failures from a flaky upstream. 4xx codes are client errors and + # never retried. + _RETRY_STATUS = (502, 503, 504) + + def __init__( + self, + base_url: str, + api_key: str | None = None, + timeout: float = 60.0, + max_retries: int = 3, + retry_backoff_base_s: float = 0.5, + ): + self.base_url = base_url.rstrip("/") + self.api_key = api_key + self.timeout = timeout + self.max_retries = max(1, max_retries) + self.retry_backoff_base_s = retry_backoff_base_s + # Persistent httpx.Client for HTTP/1.1 keep-alive + connection + # reuse. Constructing a fresh Client per chat_completion paid a + # TLS handshake every call (~100-300ms vs free for keep-alive), + # which adds up fast under bench --concurrency. httpx.Client is + # thread-safe for sequential or concurrent use; its internal + # connection pool serializes pool access. Closed via close(). + import httpx + self._http = httpx.Client(timeout=self.timeout) + +
+[docs] + def close(self) -> None: + """Release the underlying connection pool.""" + try: + self._http.close() + except Exception: + pass
+ + + def __enter__(self): + return self + + def __exit__(self, exc_type, exc, tb): + self.close() + return False + + @staticmethod + def _scrub_surrogates(s: str) -> str: + """Replace lone UTF-16 surrogates with U+FFFD. + + Wikipedia chunks (and other ingested text) occasionally + contain unpaired surrogates from the ingest of invalid-UTF-8 + source. httpx's json= path does ``.encode('utf-8')`` on the + serialized request body, which raises UnicodeEncodeError on + any lone surrogate. Sanitize incoming message content here + so the outbound HTTP request always serializes cleanly. We + round-trip through WTF-8 (surrogatepass) bytes, then decode + as standard UTF-8 with replacement — invalid sequences + become U+FFFD (REPLACEMENT CHARACTER). + """ + return s.encode("utf-8", errors="surrogatepass").decode("utf-8", errors="replace") + +
+[docs] + def chat_completion( + self, + messages: list[dict], + *, + model: str, + temperature: float = 0.1, + max_tokens: int = 512, + top_p: float = 1.0, + extra_body: dict | None = None, + stop: list[str] | None = None, + ) -> str: + import httpx + import time as _time + + client = self._http # persistent connection pool from __init__ + headers = {"Content-Type": "application/json"} + # Sanitize message content for httpx's json-encode path. + messages = [ + { + **m, + "content": ( + self._scrub_surrogates(m["content"]) + if isinstance(m.get("content"), str) + else m.get("content") + ), + } + for m in messages + ] + if self.api_key: + headers["Authorization"] = f"Bearer {self.api_key}" + payload = { + "model": model, + "messages": messages, + "temperature": temperature, + "max_tokens": max_tokens, + "top_p": top_p, + } + if stop: + payload["stop"] = list(stop) + # extra_body merges into the payload root — vLLM accepts knobs + # like {"guided_json": {...schema...}} or {"guided_grammar": "..."}. + # Endpoints that don't recognize a key silently drop it. + if extra_body: + for k, v in extra_body.items(): + payload[k] = v + url = f"{self.base_url}/chat/completions" + last_exc: Exception | None = None + for attempt in range(self.max_retries): + try: + resp = client.post(url, headers=headers, json=payload) + if resp.status_code in self._RETRY_STATUS and attempt < self.max_retries - 1: + # Exponential backoff: 0.5s, 1.0s, 2.0s with the + # default base. Last attempt raises through. + sleep_s = self.retry_backoff_base_s * (2 ** attempt) + _time.sleep(sleep_s) + continue + resp.raise_for_status() + data = resp.json() + return data["choices"][0]["message"]["content"] + except httpx.HTTPStatusError as e: + # Retry only the configured transient codes; raise others. + if e.response.status_code in self._RETRY_STATUS and attempt < self.max_retries - 1: + sleep_s = self.retry_backoff_base_s * (2 ** attempt) + _time.sleep(sleep_s) + last_exc = e + continue + raise + except (httpx.ConnectError, httpx.ReadTimeout, httpx.RemoteProtocolError) as e: + # Network-layer transient errors get the same retry. + if attempt < self.max_retries - 1: + sleep_s = self.retry_backoff_base_s * (2 ** attempt) + _time.sleep(sleep_s) + last_exc = e + continue + raise + # Defensive — loop should have returned or raised. + if last_exc is not None: + raise last_exc + raise RuntimeError("OpenAICompatibleClient.chat_completion: retry loop exhausted without raising")
+
+ +
+
+
+
+ + +
+
+ + Made with Sphinx and @pradyunsg's + + Furo + +
+
+ +
+
+ +
+
+ +
+
+ + + + + \ No newline at end of file diff --git a/docs/_source/_build/html/_modules/aborist/qa/dag.html b/docs/_source/_build/html/_modules/aborist/qa/dag.html new file mode 100644 index 0000000..b615cf3 --- /dev/null +++ b/docs/_source/_build/html/_modules/aborist/qa/dag.html @@ -0,0 +1,731 @@ + + + + + + + + aborist.qa.dag - Aborist API Reference + + + + + + + + + + + + + + + + Contents + + + + + + Menu + + + + + + + + Expand + + + + + + Light mode + + + + + + + + + + + + + + Dark mode + + + + + + + Auto light/dark, in light mode + + + + + + + + + + + + + + + Auto light/dark, in dark mode + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Skip to content + + + +
+
+
+ +
+ +
+
+ +
+ +
+
+ +
+
+
+ + + + + Back to top + +
+
+ +
+ +
+
+

Source code for aborist.qa.dag

+"""Per-run Merkle-DAG provenance for providence records.
+
+Each query/ask call passes through several stages:
+
+    question → retrieval → context → prompt → answer → verify → final_label
+
+Each stage emits a hash; the run's identity is the Merkle root over the
+ordered sequence of stage hashes. Stored on the providence record as
+``run_dag_root`` (alongside ``cache_key``). The DAG is verifiable: given
+the persisted node list & 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 & confirm the run was constructed as recorded.
+
+Distinct from the linear ``audit_events`` chain — that chain tracks
+state-changing operations across the DB. This DAG tracks the
+computation provenance of one specific answer. Both coexist; the
+record's ``audit_event_hash`` links to the chain, ``run_dag_root`` &
+``run_dag_blob`` carry the per-run computation graph.
+
+Stages chosen to mirror the toy-Hermes design (fox 2026-04-30):
+
+    question      hash of question_hash (8-dim cache_key dim)
+    retrieval     hash of sources summary (document_roots + roles +
+                  scores) — captures which docs ranked & how
+    context       context_root (Merkle root over sorted source roots,
+                  the "source" dim of the cache_key)
+    prompt        conversation_hash (the assembled messages)
+    answer        sha256(answer_text)
+    verify        hash of verdict summary (audit_mode, verifier_method,
+                  n_quotes, n_verified, claim_statuses)
+    final_label   hash of (audit_mode, verifier_method, lookup_path)
+
+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.
+"""
+
+from __future__ import annotations
+
+import hashlib
+import json
+
+from aborist.merkle import MerkleTree
+
+
+def _sha256_hex(s: str) -> str:
+    # ``errors='surrogatepass'`` lets lone UTF-16 surrogates through as
+    # their WTF-8 form. Hermes occasionally emits text with unpaired
+    # surrogates inside multi-byte sequences; bare ``.encode('utf-8')``
+    # raises UnicodeEncodeError on those, which previously aborted the
+    # run with no Merkle root. The hash stays deterministic because the
+    # WTF-8 byte sequence is reversible & unique per input.
+    return hashlib.sha256(s.encode("utf-8", errors="surrogatepass")).hexdigest()
+
+
+def _canonical_json(obj) -> str:
+    return json.dumps(obj, sort_keys=True, separators=(",", ":"), ensure_ascii=False)
+
+
+
+[docs] +def localize_failure( + *, + audit_mode: str, + n_sources: int, + n_quotes: int, + n_verified: int, +) -> str | None: + """Map a non-STRICT verdict to the pipeline stage that introduced + the failure. Returns ``None`` for STRICT outcomes. + + Stage labels (in pipeline order): + + - ``retrieval`` — 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. + - ``context`` — 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. + - ``answer`` — sources retrieved & quotes extracted but they don't + verify. The model either fabricated content, paraphrased inside + quotes, or appended citation tails. Repair path: the + ``mechanical_repair`` pass + (when wired) the re-prompt feedback + loop. + + The toy-Hermes design pass calls this "chain-segment failure + localization" — debugging becomes typed instead of vague. An + operator reading ``failure_stage='answer'`` knows retrieval & + context were fine; the model is what to fix. ``failure_stage='retrieval'`` + means stop tuning the verifier & go ingest a relevant source. + """ + if audit_mode == "STRICT": + return None + if n_sources == 0: + return "retrieval" + if n_quotes == 0: + return "context" + # Quotes were extracted but didn't all verify (or none did). + return "answer"
+ + + +PREFLIGHT_NODE_VERSION = "preflight-node-v1" + + +
+[docs] +def build_preflight_node_payload( + *, + question_state: dict | None = None, + quantifier: dict | None = None, + answer_contract: dict | None = None, + prompt_contract: dict | None = None, + evidence_contract: dict | None = None, + policy_refs: dict | None = None, +) -> dict: + """Build the canonical nested-clause payload for the preflight + DAG stage. Returns a JSON-ready dict; pair with + :func:`preflight_node_hash` to get the SHA-256 hex. + + Five-clause structure per ticket #000009 §8.2 / feedback §3: + + - ``classifier`` — quantifier classifier output (#000008): + intensity, matched_token, explicit_count, scope_bound_hint, + is_broad, classifier_version, operational_shape. + - ``answer_contract`` — guard / cap / reject decisions taken + on this run. + - ``prompt_contract`` — reminder enabled / injected / + template_id (#000008 §10.5). + - ``evidence_contract`` — exposure budget, one-claim-per-line + discipline (#000010 §10.4). + - ``policy_refs`` — governance_policy_hash + model_profile_hash + + answer_mode. Reference-by-hash rather than raw policy + bundles (feedback §4: avoid double-committing + already-hashed state). + + Plus the metacog ``question_state`` from #000010 — that's its + own clause for now (logical_statuses, false_premise_hints, + contradiction_pairs). It's hashed separately by + `metacognition.preflight_policy_hash` already. + + Any clause may be None / empty — the resulting payload is + still stable. Includes ``node_version`` so legacy runs without + the node can be unambiguously labeled `unavailable_legacy_run` + by audit tools. + """ + return { + "stage": "preflight", + "node_version": PREFLIGHT_NODE_VERSION, + "classifier": dict(quantifier) if quantifier else {}, + "answer_contract": dict(answer_contract) if answer_contract else {}, + "prompt_contract": dict(prompt_contract) if prompt_contract else {}, + "evidence_contract": dict(evidence_contract) if evidence_contract else {}, + "policy_refs": dict(policy_refs) if policy_refs else {}, + # Metacognition QuestionState carries + # ``preflight_policy_hash`` internally so flipping a metacog + # detector invalidates this clause via that field. Stored + # nested so audit-replay can read all metacog signal in one + # place without descending into the quantifier classifier. + "question_state": dict(question_state) if question_state else {}, + }
+ + + +
+[docs] +def preflight_node_hash( + *, + question_state: dict | None = None, + quantifier: dict | None = None, + answer_contract: dict | None = None, + prompt_contract: dict | None = None, + evidence_contract: dict | None = None, + policy_refs: dict | None = None, +) -> str: + """Hash the preflight decision into a stable SHA-256 hex string. + + Returns the hash of the nested-clause payload built by + :func:`build_preflight_node_payload`. See that function for the + five-clause structure. + + 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 ``run_dag_root`` via + :func:`build_run_dag`. + + Backward compatibility note: Pre-2026-05-04 (`c36e85c`) callers + used a flat 3-key payload (`question_state` / `quantifier` / + `policy_state`). Hashes computed with that callsite will NOT + match this restructured callsite — `run_dag_root` values for + rows written between `c36e85c` and the current commit are + treated as a discrete generation; they're still verifiable by + re-reading `run_dag_blob` (the persisted blob captures the + payload that was actually hashed). + """ + payload = build_preflight_node_payload( + question_state=question_state, + quantifier=quantifier, + answer_contract=answer_contract, + prompt_contract=prompt_contract, + evidence_contract=evidence_contract, + policy_refs=policy_refs, + ) + return _sha256_hex(_canonical_json(payload))
+ + + +
+[docs] +def build_run_dag( + *, + question_hash: str, + sources: list[dict], + context_root: str, + conversation_hash: str, + answer_text: str, + audit_mode: str, + verifier_method: str, + n_quotes: int, + n_verified: int, + claim_statuses: list[dict] | None = None, + lookup_path: str | None = None, + evidence_map_root: str | None = None, + answer_mode: str | None = None, + violations: list[dict] | None = None, + raw_answer_text: str | None = None, + parsed_lattice: list | None = None, + rendered_text: str | None = None, + retrieval_plan_hash: str | None = None, + preflight_hash: str | None = None, + preflight_payload: dict | None = None, +) -> dict: + """Return ``{"root": <hex>, "nodes": [<stage>, <hash>], ...}``. + + All inputs are already-computed hashes or text; no I/O. Idempotent & + deterministic — same inputs always produce the same root, byte-for- + byte across machines (as long as the Merkle conventions stay pinned; + they do, via ``aborist.merkle``). + + Two base DAG shapes; both gain an optional ``preflight`` stage + when ``preflight_hash`` is supplied (Ticket #000009): + + - **Quote mode (default).** 7 stages — + ``question / retrieval / context / prompt / answer / verify / + final_label``. Triggered when ``evidence_map_root`` is None. + Backward-compatible with all run_dag_root values written by code + that pre-dates G0. With ``preflight_hash``, becomes 8 stages — + ``question / preflight / retrieval / ...``. + + - **Claim-lattice-pointer mode (G0 / CTI).** 9 stages — + ``question / retrieval / evidence_map / prompt / raw_answer / + parsed_claim_lattice / verify / render / final_label``. Triggered + when ``evidence_map_root`` is non-None. Splits the single + ``answer`` node into three: the model's raw output, the parsed + claim-lattice, and the rendered prose with literal spans + interpolated. ``context`` drops out (the context IS the evidence + map). All three of ``raw_answer_text`` / ``parsed_lattice`` / + ``rendered_text`` should be supplied; missing args fall back to + ``answer_text`` for the raw_answer & render hashes and ``[]`` for + the parsed_lattice hash. With ``preflight_hash``, becomes 10 + stages. + + ``answer_mode`` & ``violations`` fold into the verify & final_label + payloads when provided. ``preflight_hash`` (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 ``question`` and + ``retrieval``) per ticket #000009 §3.1. + """ + sources_summary = [ + { + "document_root": s.get("document_root"), + "source_role": s.get("source_role"), + "score": s.get("score"), + "chunk_idx": s.get("chunk_idx"), + } + for s in sources + ] + sources_summary_hash = _sha256_hex(_canonical_json(sources_summary)) + # Retrieval stage hash: when a retrieval_plan_hash is supplied + # (per ticket #000001 — provenance binding for operator-influenced + # retrieval inputs like keywords / top_k / over_fetch), the stage + # hash binds BOTH the plan (input) and the sources_summary + # (output). Without a plan supplied, fall back to the historical + # sources-summary-only hash so pre-#000001 records keep their + # run_dag_root values stable. Greenfield records that omit the + # plan stay readable by the run-DAG validator. + if retrieval_plan_hash is not None: + retrieval_hash = _sha256_hex(_canonical_json({ + "retrieval_plan_hash": retrieval_plan_hash, + "sources_summary_hash": sources_summary_hash, + })) + else: + retrieval_hash = sources_summary_hash + answer_hash = _sha256_hex(answer_text) + failure_stage = localize_failure( + audit_mode=audit_mode, + n_sources=len(sources), + n_quotes=n_quotes, + n_verified=n_verified, + ) + verify_payload = { + "audit_mode": audit_mode, + "verifier_method": verifier_method, + "n_quotes": n_quotes, + "n_verified": n_verified, + "claim_statuses": claim_statuses or [], + "failure_stage": failure_stage, + } + if violations is not None: + verify_payload["violations"] = violations + verify_hash = _sha256_hex(_canonical_json(verify_payload)) + final_label_payload = { + "audit_mode": audit_mode, + "verifier_method": verifier_method, + "lookup_path": lookup_path, + } + if answer_mode is not None: + final_label_payload["answer_mode"] = answer_mode + final_label_hash = _sha256_hex(_canonical_json(final_label_payload)) + + if evidence_map_root is None: + # Quote-mode 7-stage shape — backward-compatible. + nodes = [ + {"stage": "question", "hash": question_hash}, + {"stage": "retrieval", "hash": retrieval_hash}, + {"stage": "context", "hash": context_root}, + {"stage": "prompt", "hash": conversation_hash}, + {"stage": "answer", "hash": answer_hash}, + {"stage": "verify", "hash": verify_hash}, + {"stage": "final_label", "hash": final_label_hash}, + ] + else: + # Pointer-mode 9-stage shape (CTI). ``context`` drops out; + # ``answer`` splits into raw_answer / parsed_claim_lattice / + # render so each provenance step gets its own commitment. + raw_text = raw_answer_text if raw_answer_text is not None else answer_text + rendered = rendered_text if rendered_text is not None else answer_text + raw_answer_hash = _sha256_hex(raw_text) + # Parsed lattice = list of {claim_text, evidence_ids[]} dicts in + # input order; canonical-json so reordering claims changes the + # hash. Pointer ids are run-dependent — we prefer the + # content-addressed evidence_ids here for run-stable provenance. + parsed_lattice_hash = _sha256_hex( + _canonical_json(parsed_lattice or []) + ) + rendered_hash = _sha256_hex(rendered) + nodes = [ + {"stage": "question", "hash": question_hash}, + {"stage": "retrieval", "hash": retrieval_hash}, + {"stage": "evidence_map", "hash": evidence_map_root}, + {"stage": "prompt", "hash": conversation_hash}, + {"stage": "raw_answer", "hash": raw_answer_hash}, + {"stage": "parsed_claim_lattice", "hash": parsed_lattice_hash}, + {"stage": "verify", "hash": verify_hash}, + {"stage": "render", "hash": rendered_hash}, + {"stage": "final_label", "hash": final_label_hash}, + ] + # Ticket #000009 — preflight stage binding. When supplied, + # insert ``preflight`` between ``question`` and ``retrieval``. + # Optional so legacy run_dag_root values from pre-#000009 code + # remain reproducible (None → original 7/9-stage shape). The + # preflight_hash bundles #000008 quantifier output, #000010 + # QuestionState, AND the policy decisions taken on this run + # — see preflight_node_hash() for the canonical payload. + if preflight_hash is not None: + nodes.insert( + 1, + {"stage": "preflight", "hash": preflight_hash}, + ) + leaves = [bytes.fromhex(n["hash"]) for n in nodes] + root_hex = MerkleTree.build(leaves).root.hex() + out = {"root": root_hex, "nodes": nodes} + # Ticket #000009 §7.2 — recoverable preflight payload. Storing + # the canonical dict alongside the leaf hash means + # `aborist providence --show-preflight` can render the full + # 5-clause CTI contract (classifier / answer_contract / + # prompt_contract / evidence_contract / policy_refs + + # question_state) from `run_dag_blob` without needing a + # separate column or re-running the classifier. Audit replay + # CAN re-verify the hash matches: + # _sha256_hex(_canonical_json(preflight_payload)) == preflight_hash + # (caller-side check; verify_run_dag does not enforce because + # the hash is in `nodes` and the payload is sidecar data.) + if preflight_payload is not None: + out["preflight_payload"] = preflight_payload + return out
+ + + +
+[docs] +def build_reject_run_dag( + *, + question_hash: str, + preflight_hash: str, + rejection_reason: str, + answer_text: str, + audit_mode: str = "UNGROUNDED", + verifier_method: str = "claim_lattice_pointer", + violations: list[dict] | None = None, + preflight_payload: dict | None = None, +) -> dict: + """3-stage reject-broad run-DAG: ``question → preflight → + final_label``. + + Ticket #000009 §8.2 / 2026-05-04 feedback §6.2: preflight + rejection currently early-returns from ``query()`` before the + standard ``build_run_dag()`` 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. + + The returned shape is INTENTIONALLY shorter than the standard + 7/9/8/10-stage shapes — `audit replay can read the stage + list` and tell instantly that this row is a preflight + rejection: 3 stages always means reject path. + + `final_label` 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 + (`"preflight rejection — broad-quantifier query with + unbounded scope. ..."`), NOT the operator-facing rendered + answer_text — that lets policy template changes invalidate + the hash even if the operator-visible text is unchanged. + """ + final_label_payload = { + "audit_mode": audit_mode, + "verifier_method": verifier_method, + "lookup_path": "preflight", + "rejection_reason": rejection_reason, + "answer_text_hash": _sha256_hex(answer_text or ""), + } + if violations is not None: + final_label_payload["violations"] = violations + final_label_hash = _sha256_hex(_canonical_json(final_label_payload)) + nodes = [ + {"stage": "question", "hash": question_hash}, + {"stage": "preflight", "hash": preflight_hash}, + {"stage": "final_label", "hash": final_label_hash}, + ] + leaves = [bytes.fromhex(n["hash"]) for n in nodes] + root_hex = MerkleTree.build(leaves).root.hex() + out = {"root": root_hex, "nodes": nodes} + if preflight_payload is not None: + out["preflight_payload"] = preflight_payload + return out
+ + + +
+[docs] +def verify_run_dag(blob: str | dict) -> bool: + """Recompute the Merkle root from ``blob`` and check it matches. + + Used by audit tooling. Accepts either a parsed dict or the JSON + string we persist in ``providence_cache.run_dag_blob``. + """ + if isinstance(blob, str): + blob = json.loads(blob) + nodes = blob.get("nodes") or [] + if not nodes: + return False + leaves = [bytes.fromhex(n["hash"]) for n in nodes] + return MerkleTree.build(leaves).root.hex() == blob.get("root")
+ +
+
+
+
+ + +
+
+ + Made with Sphinx and @pradyunsg's + + Furo + +
+
+ +
+
+ +
+
+ +
+
+ + + + + \ No newline at end of file diff --git a/docs/_source/_build/html/_modules/aborist/qa/evidence.html b/docs/_source/_build/html/_modules/aborist/qa/evidence.html new file mode 100644 index 0000000..5f192e0 --- /dev/null +++ b/docs/_source/_build/html/_modules/aborist/qa/evidence.html @@ -0,0 +1,777 @@ + + + + + + + + aborist.qa.evidence - Aborist API Reference + + + + + + + + + + + + + + + + Contents + + + + + + Menu + + + + + + + + Expand + + + + + + Light mode + + + + + + + + + + + + + + Dark mode + + + + + + + Auto light/dark, in light mode + + + + + + + + + + + + + + + Auto light/dark, in dark mode + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Skip to content + + + +
+
+
+ +
+ +
+
+ +
+ +
+
+ +
+
+
+ + + + + Back to top + +
+
+ +
+ +
+
+

Source code for aborist.qa.evidence

+"""Evidence map for claim-lattice-pointer (quote-by-pointer) answer mode.
+
+Builds a deterministic table of evidence objects from already-retrieved
+chunks. The model references each object by a short ``pointer_id``
+("E1", "E2", ...) which the runtime maps back to a content-addressed
+``evidence_id`` for the cache, run-DAG, and audit chain.
+
+Design pinned by G0 ticket (2026-04-29) and the CTI / Clause Lattice
+Intelligence reframe:
+
+    Models should not generate verbatim quotes.
+    They should point to evidence IDs extracted by deterministic code.
+
+This kills the synthetic-elision class by construction — the model
+never types the quote string, so it can't drop characters from one.
+
+Two-layer id scheme:
+
+- ``pointer_id``    short numeric tag the model sees in the prompt and
+                     writes back in pointer-line answers. ``E`` + the
+                     1-based position of the evidence object in the map
+                     (``E1``, ``E2``, …, ``E37``). One BPE token per id
+                     in standard tokenizers. Stays in the model's
+                     in-distribution citation style.
+- ``evidence_id``   content-addressed handle. ``E`` + first 8 hex of
+                     ``sha256(chunk_root:offset_start:offset_end)``.
+                     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.
+
+The verifier (``verify_claim_lattice``) maps each pointer_id the model
+writes back to its content-addressed evidence_id before persistence.
+The model's literal output is run-dependent (run #1's ``E1`` and run
+#2's ``E1`` likely point at different chunks); the content-addressed
+layer is what stays stable.
+
+For the first cut every chunk produces exactly one evidence object
+covering ``offset_start=0 .. offset_end=len(span)``. Sub-chunk
+extraction (paragraph-level, sentence-level) is a future refinement;
+the schema already accepts arbitrary offsets so adding finer-grained
+splits later doesn't break the contract.
+"""
+
+from __future__ import annotations
+
+import hashlib
+import re
+from dataclasses import asdict, dataclass
+
+from aborist.merkle import MerkleTree
+
+
+def _sha256_hex(s: str) -> str:
+    # ``errors='surrogatepass'`` for model-output text containing lone
+    # UTF-16 surrogates; same rationale as ``aborist.qa.dag._sha256_hex``.
+    return hashlib.sha256(s.encode("utf-8", errors="surrogatepass")).hexdigest()
+
+
+
+[docs] +@dataclass(frozen=True) +class EvidenceObject: + """One pinned span the model may reference by ``pointer_id``. + + All fields are deterministic from inputs; same chunk + offsets yields + the same object byte-for-byte. + + - ``pointer_id`` prompt-facing id ("E1", "E2", …) — what the + model sees & writes back. Position-derived; + run-dependent on purpose. + - ``evidence_id`` content-addressed handle ("E" + 8 hex of + sha256(chunk_root:start:end)) — what the + cache, run-DAG, and audit chain use. + Run-stable. + - ``source_root`` document_root the chunk belongs to + - ``document_uri`` human-readable URI (for the renderer) + - ``title`` doc title (for the renderer & prompt) + - ``chunk_idx`` chunk index within the document + - ``chunk_root`` leaf hash of the chunk + - ``offset_start`` byte offset within the chunk (0 for whole-chunk) + - ``offset_end`` end offset (exclusive) + - ``source_role`` role classification (primary_answer_source / ...) + - ``text_hash`` sha256 of the span (for tamper detection) + - ``span`` the literal text (what the renderer interpolates) + """ + + pointer_id: str + evidence_id: str + source_root: str + document_uri: str + title: str | None + chunk_idx: int + chunk_root: str + offset_start: int + offset_end: int + source_role: str + text_hash: str + span: str + +
+[docs] + def to_dict(self) -> dict: + return asdict(self)
+
+ + + +def _evidence_id_for(chunk_root: str, offset_start: int, offset_end: int) -> str: + """Content-addressed handle. Same chunk + offsets = same ID, forever.""" + h = _sha256_hex(f"{chunk_root}:{offset_start}:{offset_end}") + return f"E{h[:8]}" + + +
+[docs] +def build_evidence_map( + chunks: list[dict], +) -> list[EvidenceObject]: + """Build the evidence table from retrieved chunks. + + ``chunks`` is a list of dicts with keys: + source_root, document_uri, title (optional), chunk_idx, + chunk_root, span, source_role (optional, default 'unclassified') + + Returns a list of ``EvidenceObject``s, one per chunk, in input order. + The 1-based position drives ``pointer_id`` (E1, E2, …); the chunk's + content drives ``evidence_id`` (sha256-derived). For the first cut + each chunk = one whole-span evidence object (offset 0 .. len(span)). + Sub-chunk splitting is a future refinement. + """ + out: list[EvidenceObject] = [] + for i, c in enumerate(chunks): + span = c["span"] + offset_start = 0 + offset_end = len(span) + chunk_root = c["chunk_root"] + evidence_id = _evidence_id_for(chunk_root, offset_start, offset_end) + out.append( + EvidenceObject( + pointer_id=f"E{i + 1}", + evidence_id=evidence_id, + source_root=c["source_root"], + document_uri=c["document_uri"], + title=c.get("title"), + chunk_idx=c["chunk_idx"], + chunk_root=chunk_root, + offset_start=offset_start, + offset_end=offset_end, + source_role=c.get("source_role", "unclassified"), + text_hash=_sha256_hex(span), + span=span, + ) + ) + return out
+ + + +
+[docs] +def evidence_map_root(evidence: list[EvidenceObject]) -> str: + """Merkle root over the sorted evidence_id leaves. + + Sorting makes the root order-independent — two retrieval runs that + return the same chunks in different orders produce the same root. + Use as the ``evidence_map`` stage hash in the run-DAG. + """ + if not evidence: + return "00" * 32 + leaves_hex = sorted(_sha256_hex(e.evidence_id) for e in evidence) + if len(leaves_hex) == 1: + return leaves_hex[0] + leaves = [bytes.fromhex(h) for h in leaves_hex] + return MerkleTree.build(leaves).root.hex()
+ + + +
+[docs] +def render_evidence_block(e: EvidenceObject) -> str: + """Format one evidence object for the LLM prompt. + + 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: + + === E1 (Jurassic_Park_(film) | primary_answer_source) === + <literal span text> + + The runtime maps E1 back to the content-addressed evidence_id + before persistence; the model never sees the hex form. + """ + label = (e.title or e.document_uri.rsplit("/", 1)[-1]) or "untitled" + return f"=== {e.pointer_id} ({label} | {e.source_role}) ===\n{e.span}"
+ + + +
+[docs] +def render_evidence_map(evidence: list[EvidenceObject]) -> str: + """Concatenated evidence blocks, ready to drop into the prompt.""" + return "\n\n".join(render_evidence_block(e) for e in evidence)
+ + + +
+[docs] +def render_evidence_block_for_json(e: EvidenceObject) -> str: + """Format one evidence object for the JSON-mode LLM prompt. + + 2026-04-30: header uses the prompt-facing ``pointer_id`` (E1, E2, + …) — same as claim_lattice_pointer mode — instead of the + content-addressed ``evidence_id`` (long hex). The change closes a + real failure mode: small models (Hermes-3-8B observed) were + fabricating plausible-looking content-addressed IDs (e.g. + ``E1b6e396`` when the runtime had ``Eed1b6e396``) → UNKNOWN_ + EVIDENCE_ID → UNGROUNDED, even when the answer text was correct. + Pointer IDs (``E1``-``E10``) are short, enumerable, and fabrication- + obvious — the model can't invent ``E27`` if only ``E1``-``E10`` were + shown. + + The runtime still stores content-addressed ``evidence_id`` in the + cache & run-DAG (resolved on-the-fly in ``verify_claim_lattice_json``); + only the prompt-facing string changes:: + + === E1 (Jurassic_Park_(film) | primary_answer_source) === + <literal span text> + """ + label = (e.title or e.document_uri.rsplit("/", 1)[-1]) or "untitled" + return f"=== {e.pointer_id} ({label} | {e.source_role}) ===\n{e.span}"
+ + + +
+[docs] +def render_evidence_map_for_json(evidence: list[EvidenceObject]) -> str: + """Concatenated evidence blocks for JSON mode.""" + return "\n\n".join(render_evidence_block_for_json(e) for e in evidence)
+ + + +
+[docs] +def evidence_map_by_pointer_id( + evidence: list[EvidenceObject], +) -> dict[str, EvidenceObject]: + """Index by prompt-facing pointer_id (E1, E2, …).""" + return {e.pointer_id: e for e in evidence}
+ + + +
+[docs] +def evidence_map_by_evidence_id( + evidence: list[EvidenceObject], +) -> dict[str, EvidenceObject]: + """Index by content-addressed evidence_id (E1f8e4c2a, …).""" + return {e.evidence_id: e for e in evidence}
+ + + +
+[docs] +def render_claim_lattice( + claims: list[dict], + by_id: dict[str, EvidenceObject], + *, + window: int = 200, +) -> str: + """Convert structured claims to human-readable prose with literal spans. + + Each claim becomes one bullet line followed by inlined evidence + excerpts. The model's claim text is rendered verbatim; each cited + pointer_id is followed by a **spotlight excerpt** of the literal + source span — a window of ``window`` 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. + + 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 *about* — "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. + + ``by_id`` is the pointer_id → EvidenceObject index — what + ``evidence_map_by_pointer_id`` returns. Determinism: same + (claims, by_id, window) → same prose, byte-for-byte. Unknown ids + render as ``[<id>: ?]`` so violations are visible at a glance. + """ + lines: list[str] = [] + for c in claims: + text = (c.get("text") or "").strip() + if not text: + continue + lines.append(f"- {text}") + for eid in c.get("pointer_ids") or c.get("evidence_ids") or []: + obj = by_id.get(eid) + if obj is None: + lines.append(f' [{eid}: ?]') + continue + # Provenance-clear evidence pointer: + # [E5 | <source title> | <chunk_root prefix>: "<excerpt>"] + # Closes the visual confusion observed 2026-05-01 on the + # Orwell run where `[E5: "..."]` displayed alongside a + # source list whose `[5]` slot was a different document + # (E# is a chunk pointer, not a 1-indexed source rank). + # Title comes from the EvidenceObject (URI tail fallback); + # chunk_root prefix is the first 8 hex chars — enough for + # the operator to disambiguate while staying compact. + label = obj.title or obj.document_uri.rsplit("/", 1)[-1] or "untitled" + chunk_prefix = (obj.chunk_root or "")[:8] + excerpt = _spotlight_excerpt(text, obj.span, window=window) + lines.append(f' [{eid} | {label} | {chunk_prefix}: "{excerpt}"]') + return "\n".join(lines)
+ + + +# Stopwords for spotlight content-token extraction. Smaller set than +# verify._ENGLISH_STOPWORDS — we only need to filter the words the +# model is most likely to share between claim text & every span. A +# handful of high-frequency 4+ char fillers is enough; the spotlight +# falls back to the leading window when no token matches anyway, so +# false negatives degrade gracefully. +_SPOTLIGHT_STOPWORDS = frozenset({ + "from", "with", "into", "onto", "upon", "this", "that", "these", + "those", "have", "been", "being", "their", "there", "they", + "them", "your", "what", "when", "where", "while", "which", + "would", "could", "should", "might", "shall", "first", "last", + "also", "very", "much", "many", "more", "most", "less", "some", + "such", "than", "then", "back", "next", "after", "before", + "between", "through", "across", "above", "below", "during", + "without", "within", "until", "since", "about", "around", + "along", "among", "appear", "appears", "appeared", "feature", + "features", "include", "includes", "shown", "shows", +}) + +_TOKEN_PUNCT_STRIP_R = ".,;:!?\"'()[]{}—-" + + +def _content_tokens(text: str) -> list[str]: + """Lowercase content tokens from ``text``, sorted by length desc. + + Filters: drop ``< 4`` chars (function words), drop a small stopword + set, dedup. Sorted longest-first so the spotlight matches the most + specific topical token before generic ones — for "Brachiosaurus + appears in the film", that's ``brachiosaurus`` ahead of ``film``. + """ + seen: set[str] = set() + out: list[str] = [] + for raw in text.lower().split(): + t = raw.strip(_TOKEN_PUNCT_STRIP_R) + if len(t) < 4 or t in _SPOTLIGHT_STOPWORDS or t in seen: + continue + seen.add(t) + out.append(t) + out.sort(key=len, reverse=True) + return out + + +_SENTENCE_END_RE = re.compile(r"[.!?][\"')\]]?\s+(?=[A-Z\"'(\[])|[.!?][\"')\]]?$") + + +def _expand_to_sentence_boundaries(span: str, start: int, end: int) -> tuple[int, int]: + """Expand a (start, end) byte window in ``span`` outward to the + nearest sentence boundaries. + + Boundary discovery uses a conservative regex: ``[.!?][\"')\\]]?`` + followed by whitespace + capital letter (or end of span). The + result is byte-clean and idempotent — re-expanding an already- + sentence-bounded window returns the same indices. + + Returns clamped ``(new_start, new_end)``. If the input is the + whole span or no sentence boundary is detectable in either + direction, the input is returned unchanged. + """ + if start <= 0 and end >= len(span): + return 0, len(span) + # Walk left from `start` to find the previous sentence boundary + # (or start of span). Use the regex's match positions in the + # text leading up to `start`. + new_start = 0 + for m in _SENTENCE_END_RE.finditer(span, 0, start): + new_start = m.end() + # Walk right from `end` to find the next sentence boundary (or + # end of span). The first match whose START is >= end is the + # boundary that closes the spotlit sentence. + new_end = len(span) + for m in _SENTENCE_END_RE.finditer(span, end): + new_end = m.end() + break + return new_start, new_end + + +def _spotlight_excerpt(claim_text: str, span: str, *, window: int) -> str: + """Return a sentence-bounded excerpt of ``span`` centered on the + first claim-token match. + + Pre-2026-05-01 the excerpt was a fixed-width byte window with + leading/trailing ``"..."`` markers; that frequently cut mid-word + and produced excerpts like ``"...freewheeling plot about a boy + and a girl, and the many amazing creatures they have for friends + and p..."`` (the trailing ``p...`` is a half-word truncation). The + new version finds the spotlight token by claim-content-token + match (same as before), then expands outward to the nearest + sentence boundaries — never cuts a word. + + Behavior: + + 1. If ``span`` already fits in ``window``, return it unchanged. + 2. Otherwise locate the first content-token match in ``span``. + 3. Expand the match position to the surrounding sentence(s). + 4. If the expanded sentence range fits within ``2 * window`` bytes + (a soft budget — sentences carry meaning intact), return it + with leading/trailing ellipsis only when the range doesn't + reach the span boundaries. + 5. If the expanded range exceeds ``2 * window``, fall back to the + window-centered approach but EXPAND the window's edges to the + nearest WORD boundaries (`\\b`-equivalent) so we never cut a + word. + 6. If no claim token matches anywhere, return the leading window + expanded to the nearest sentence end. + + Determinism: same (claim, span, window) → same byte-exact output. + """ + if len(span) <= window: + return span + span_lower = span.lower() + tokens = _content_tokens(claim_text) + + # Find ALL match positions for ALL content tokens, then pick the + # position whose ±half-window cluster contains the most distinct + # tokens. The Homer-Simpson-boss case (2026-05-01) showed why + # first-match-of-longest-token loses: "homer" matches early in + # voice-actor prose, but the actual answer ("Mr. Burns") is + # deeper in the chunk where boss/burns/homer all cluster + # together. Density picks the load-bearing slice; first-match + # picks whatever phrasing the chunk happens to lead with. + half = window // 2 + positions: list[tuple[str, int]] = [] + for tok in tokens: + i = 0 + while True: + j = span_lower.find(tok, i) + if j < 0: + break + positions.append((tok, j)) + i = j + len(tok) + + if not positions: + # No content match — return the leading sentence(s) up to + # ~window bytes, expanded to the next sentence end so we + # never cut a word at the boundary. + new_start, new_end = _expand_to_sentence_boundaries(span, 0, min(window, len(span))) + # Cap at 2× window so a runaway sentence doesn't blow the + # excerpt budget. + if new_end - new_start > 2 * window: + new_end = _word_boundary_before(span, new_start + 2 * window) + suffix = "..." if new_end < len(span) else "" + return f"{span[new_start:new_end]}{suffix}" + + # Density rank: for each candidate position, count distinct + # tokens whose match positions fall within ±half. Pick the + # position with max distinct count; tie-break on smallest idx + # (deterministic, reproducible). + best_score = -1 + match_idx = positions[0][1] + for _tok, idx in positions: + distinct: set[str] = set() + lo, hi = idx - half, idx + half + for tok2, idx2 in positions: + if lo <= idx2 <= hi: + distinct.add(tok2) + score = len(distinct) + if score > best_score or (score == best_score and idx < match_idx): + best_score = score + match_idx = idx + + raw_start = max(0, match_idx - half) + raw_end = min(len(span), match_idx + len(tokens[0]) + half) + + # Expand outward to sentence boundaries — this is the main change. + new_start, new_end = _expand_to_sentence_boundaries(span, raw_start, raw_end) + + # Soft budget cap: if the expanded sentence range is more than + # 2× window, fall back to the windowed form but truncate at WORD + # boundaries so we don't cut a word. + if new_end - new_start > 2 * window: + new_start = _word_boundary_after(span, max(0, match_idx - half)) + new_end = _word_boundary_before(span, min(len(span), new_start + 2 * window)) + + prefix = "..." if new_start > 0 else "" + suffix = "..." if new_end < len(span) else "" + return f"{prefix}{span[new_start:new_end].strip()}{suffix}" + + +def _word_boundary_after(span: str, idx: int) -> int: + """Smallest ``i >= idx`` such that ``span[i-1]`` is whitespace or + ``i == 0``. Walks forward to a clean word start.""" + if idx <= 0: + return 0 + while idx < len(span) and not span[idx - 1].isspace(): + idx += 1 + return idx + + +def _word_boundary_before(span: str, idx: int) -> int: + """Largest ``i <= idx`` such that ``span[i]`` is whitespace or + ``i == len(span)``. Walks backward to a clean word end.""" + if idx >= len(span): + return len(span) + while idx > 0 and not span[idx].isspace(): + idx -= 1 + return idx +
+
+
+
+ + +
+
+ + Made with Sphinx and @pradyunsg's + + Furo + +
+
+ +
+
+ +
+
+ +
+
+ + + + + \ No newline at end of file diff --git a/docs/_source/_build/html/_modules/aborist/qa/keys.html b/docs/_source/_build/html/_modules/aborist/qa/keys.html new file mode 100644 index 0000000..d35fb44 --- /dev/null +++ b/docs/_source/_build/html/_modules/aborist/qa/keys.html @@ -0,0 +1,598 @@ + + + + + + + + aborist.qa.keys - Aborist API Reference + + + + + + + + + + + + + + + + Contents + + + + + + Menu + + + + + + + + Expand + + + + + + Light mode + + + + + + + + + + + + + + Dark mode + + + + + + + Auto light/dark, in light mode + + + + + + + + + + + + + + + Auto light/dark, in dark mode + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Skip to content + + + +
+
+
+ +
+ +
+
+ +
+ +
+
+ +
+
+
+ + + + + Back to top + +
+
+ +
+ +
+
+

Source code for aborist.qa.keys

+"""The 8-dim Merkle-AGI v9.8 cache_key.
+
+v9.8 invariant: no answer is reused unless all eight match and the
+record is live (not failed/stale/quarantined):
+
+    1. source_root              — content fingerprint of the document
+    2. question_hash             — SHA-256 of normalized question text
+    3. model_profile_hash        — model_id + revision + quantization
+    4. conversation_hash         — full canonical OpenAI messages array
+    5. governance_policy_hash    — sampling/policy parameters dict
+    6. schema_version            — aborist DB schema version
+    7. canonicalization_version  — text normalization rules
+    8. chunking_version          — chunker name & parameters
+
+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" — that's a simplification; the rigorous form is
+all eight dimensions hashed together.
+"""
+
+from __future__ import annotations
+
+import hashlib
+import json
+
+from aborist.document import canonicalize
+
+
+def _sha256(s: str) -> str:
+    # ``errors='surrogatepass'`` survives lone UTF-16 surrogates from
+    # model output; same rationale as ``aborist.qa.dag._sha256_hex``.
+    return hashlib.sha256(s.encode("utf-8", errors="surrogatepass")).hexdigest()
+
+
+def _canonical_json(obj) -> str:
+    return json.dumps(obj, sort_keys=True, separators=(",", ":"), ensure_ascii=False)
+
+
+QUESTION_DEDUP_MODES = ("strict", "equivalence_class")
+DEFAULT_QUESTION_DEDUP = "equivalence_class"
+
+# Lookup-time fidelity. Decoupled from write-time `question_dedup`:
+# write determines under which `cache_key` a record lands; fidelity
+# determines which `cache_key`s a lookup will check.
+#
+#   strict             only the cache_key matching the agent's policy
+#                      is checked. No fallback. Audit-grade behavior.
+#   equivalence_class  primary cache_key checked first; if miss AND the
+#                      OTHER dedup mode produces a different cache_key,
+#                      the alternate is also checked. Lets a fast-cache
+#                      agent reuse records written under either mode.
+FIDELITY_MODES = ("strict", "equivalence_class")
+DEFAULT_FIDELITY = "equivalence_class"
+
+
+
+[docs] +def canonical_question( + question: str, *, mode: str = DEFAULT_QUESTION_DEDUP +) -> str: + """Canonical form of `question` for the given dedup ``mode``. + + Two modes: + + - ``"equivalence_class"`` (default): four-step canonicalization — + ``canonicalize()`` (NFC + ws-collapse + strip ends), then + lowercase, then trailing-punctuation strip, then standalone-article + filter (``the``, ``a``, ``an``). 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. + + - ``"strict"``: only ``canonicalize()`` — 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. + + Exposed as a function so callers can dedup BEFORE hashing — e.g. + inject the canonical form into the user message used for + ``conversation_hash``, while still sending the verbatim question to + the LLM. Without this split ``"who is batman"``, ``"who is + batman?"``, and ``"who is the batman?"`` collapse on + ``question_hash`` (under equivalence_class) but each hits + ``conversation_hash`` differently, missing cache. + + The choice of mode flows through ``policy["question_dedup"]`` into + ``governance_policy_hash`` so two agents under different modes + write records under different ``cache_key``s — they coexist in + parallel namespaces, never collide. + """ + if mode not in QUESTION_DEDUP_MODES: + raise ValueError( + f"question dedup mode must be one of {QUESTION_DEDUP_MODES}, got {mode!r}" + ) + canon = canonicalize(question) + if mode == "strict": + return canon + canon = canon.lower().rstrip(_QUESTION_TRAILING_STRIP) + tokens = [t for t in canon.split() if t not in _QUESTION_ARTICLE_STRIP] + return " ".join(tokens)
+ + + +
+[docs] +def question_hash( + question: str, *, mode: str = DEFAULT_QUESTION_DEDUP +) -> str: + """SHA-256 of the dedup-mode-canonicalized question. + + See ``canonical_question`` for what each mode does. The hash is the + SHA-256 of the canonical form. Bumping + ``_QUESTION_TRAILING_STRIP`` or ``_QUESTION_ARTICLE_STRIP`` (the + equivalence-class strip sets) orphans prior cache records whose + canonical question contained newly-stripped tokens; they live as + history but won't be re-hit on lookup. + + Equivalence class examples (mode="equivalence_class"):: + + "who is X" | + "who is X?" | + "Who Is X." | -> same question_hash + "who is the X" | + "who is a X" | + "who is an X?" | (CJK question mark) + + Strict mode (mode="strict") distinguishes all of those. + + What's IN the trailing-strip set: ``.?!,;:`` (ASCII), ``?!。、`` + (CJK full-width), ``…`` (ellipsis). Pairs like ``"`` ``'`` ``)`` + ``]`` ``}`` are NOT — naive one-sided stripping breaks balance. + Apostrophes aren't either — ``X's`` is a different question from + ``X``. + """ + return _sha256(canonical_question(question, mode=mode))
+ + + +# Trailing punctuation that carries no semantic difference at the end +# of a question. Order doesn't matter (rstrip walks char-by-char from +# the right). Repeats handled trivially: ``X???`` → ``X``. +# +# ASCII: . ? ! , ; : +# CJK: ? U+FF1F full-width question mark +# ! U+FF01 full-width exclamation +# 。 U+3002 ideographic full stop +# 、 U+3001 ideographic comma +# Other: … U+2026 horizontal ellipsis +_QUESTION_TRAILING_STRIP = ".?!,;:?!。、…" + +# English articles stripped as standalone tokens after lowercasing. The +# question equivalence class treats "the foo" and "foo" as the same +# question — fox's 2026-04-29 catch: `who is the batman` & `who is +# batman` produced different cache records under earlier rules. Tokens +# are matched as EXACT lowercase strings, so substrings like "thesis" +# (contains "the") stay untouched. +# +# Conservative on purpose: only ASCII English articles. "El", "la", +# "los", "le", "les", "der", "die", "das" etc. are not stripped today. +# Adding them when needed flows through the same equivalence-class +# expansion the trailing-punctuation set went through. +_QUESTION_ARTICLE_STRIP = frozenset({"the", "a", "an"}) + + +
+[docs] +def model_profile_hash( + model_id: str, revision: str = "", quantization: str = "" +) -> str: + """SHA-256 of model identity. Bumping any field bumps the cache key.""" + return _sha256(f"{model_id}|{revision}|{quantization}")
+ + + +
+[docs] +def conversation_hash(messages: list[dict]) -> str: + """SHA-256 of canonical JSON of the full OpenAI messages array. + + Order matters: a 6-turn dialogue arriving at the same final question + produces a different hash than a single-turn ask. + """ + return _sha256(_canonical_json(messages))
+ + + +
+[docs] +def governance_policy_hash(policy: dict) -> str: + """SHA-256 of canonical JSON of the sampling/policy dict. + + 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. + """ + return _sha256(_canonical_json(policy))
+ + + +# Verifier-policy fields — the subset of `policy` that names what +# the deterministic verifier does. Separate from the broader +# `governance_policy_hash` so an auditor can answer "did the verifier +# rules change?" with a single hash diff rather than scanning the +# whole policy. See docs/cti-architecture.md §6 + the de-novo +# synthesis (2026-05-01) on verifier-policy identity. +# +# Adding a field here bumps `verifier_policy_hash` for every cached +# record on next lookup. Removing a field does the same. Reordering +# does not (set membership, not list ordering). +_VERIFIER_POLICY_FIELDS = frozenset({ + # Mode + parser identity + "answer_mode", + # Pointer-mode hard checks + "claim_lattice_max_pointers_per_claim", + "claim_lattice_min_citation_coverage", + "claim_lattice_min_claim_content_tokens", + "claim_lattice_lazy_anchor_demote_threshold", + "claim_lattice_lazy_anchor_demote_min_pairs", + "claim_lattice_allowed_source_roles", + # Retrieval-side knob with verifier consequences + "claim_lattice_max_chunks_per_source", + # JSON variant identity + "claim_lattice_use_guided_json", + "claim_lattice_json_stop_sequences", + # Warrant-lite (relation-question hard check, Ticket H, 2026-05-01) + "claim_lattice_warrant_check_enabled", + "claim_lattice_deflection_check_enabled", + "claim_lattice_format_collapse_check_enabled", + # Subject-tokens-absent / premise-parroting (Ticket #000006 amend + # 2026-05-02b, Rule 9). Threshold of question∩claim content tokens + # absent from cited evidence union that demotes STRICT → HYBRID. + "claim_lattice_subject_tokens_absent_threshold", + # Ticket #000008 Phase 2-4 — quantifier preflight guard. The seven + # fields together control whether broad-quantifier classification + # affects the per-call claim cap, which modes are gated, whether + # the reminder fires, and whether reject-broad early-return takes + # over. Plus #000010 adds six more for metacognition (see below). + # Adding a model to model_profiles.py PROFILES doesn't bump + # governance_policy_hash on its own (the dict isn't policy); + # but flipping any of these knobs DOES bump the hash, which + # invalidates prior cache records on lookup — exactly the + # invalidation we want when a guard knob changes. + "quantifier_guard_enabled", + "quantifier_guard_apply_caps", + "quantifier_apply_caps_modes", + "quantifier_caps_by_intensity", + "quantifier_guard_modes", + "quantifier_reminder_enabled", + "quantifier_reject_broad", + # Ticket #000010 — Meta-Cognition Preflight Guard. The six + # fields together control whether preflight runs and which + # detectors fire. Flipping any of them invalidates prior cache + # records on lookup — same governance discipline as #000008. + "metacognition_enabled", + "metacognition_temporal_check", + "metacognition_contradiction_check", + "metacognition_false_premise_check", + "metacognition_out_of_corpus_check", + "metacognition_block_on_contradiction", + # Quote-mode entity policy + "entity_policy", + "entity_proximity_n", + "entity_proximity_window", + # Wikitext base-prose pinning (changes verifier surface) + "base_version", +}) + + +
+[docs] +def verifier_policy_hash(policy: dict) -> str: + """SHA-256 of canonical JSON of the verifier-relevant subset of policy. + + Pulls `_VERIFIER_POLICY_FIELDS` out of `policy` and hashes only + those. Empty dict → constant hash (`sha256("{}")`). Folded into + `cache_key` as a 9th dimension so a verifier-policy change is + observable from the cache_key alone, separate from + `governance_policy_hash` which folds in temperature / top_p / + prompts. + + The two hashes overlap (verifier fields ARE in the broader policy + dict and so contribute to governance_policy_hash too). That's + 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. + """ + subset = {k: v for k, v in policy.items() if k in _VERIFIER_POLICY_FIELDS} + return _sha256(_canonical_json(subset))
+ + + +
+[docs] +def cache_key( + source_root: str, + question_hash_value: str, + model_profile_hash_value: str, + conversation_hash_value: str, + governance_policy_hash_value: str, + schema_version: str, + canonicalization_version: str, + chunking_version: str, + verifier_policy_hash_value: str | None = None, +) -> str: + """SHA-256 of the cache-identity dimensions joined with '|'. + + 8-dim form (legacy): omit `verifier_policy_hash_value` (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. + + 9-dim form: pass `verifier_policy_hash_value` 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. + + Any drift in any dimension produces a distinct cache_key. + """ + parts = [ + source_root, + question_hash_value, + model_profile_hash_value, + conversation_hash_value, + governance_policy_hash_value, + schema_version, + canonicalization_version, + chunking_version, + ] + if verifier_policy_hash_value is not None: + parts.append(verifier_policy_hash_value) + return _sha256( + "|".join(parts) + )
+ +
+
+
+
+ + +
+
+ + Made with Sphinx and @pradyunsg's + + Furo + +
+
+ +
+
+ +
+
+ +
+
+ + + + + \ No newline at end of file diff --git a/docs/_source/_build/html/_modules/aborist/qa/metacognition.html b/docs/_source/_build/html/_modules/aborist/qa/metacognition.html new file mode 100644 index 0000000..32970fb --- /dev/null +++ b/docs/_source/_build/html/_modules/aborist/qa/metacognition.html @@ -0,0 +1,880 @@ + + + + + + + + aborist.qa.metacognition - Aborist API Reference + + + + + + + + + + + + + + + + Contents + + + + + + Menu + + + + + + + + Expand + + + + + + Light mode + + + + + + + + + + + + + + Dark mode + + + + + + + Auto light/dark, in light mode + + + + + + + + + + + + + + + Auto light/dark, in dark mode + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Skip to content + + + +
+
+
+ +
+ +
+
+ +
+ +
+
+ +
+
+
+ + + + + Back to top + +
+
+ +
+ +
+
+

Source code for aborist.qa.metacognition

+"""Meta-Cognition Preflight Guard — Ticket #000010 Phase 1.
+
+Runtime epistemic control layer that classifies a question's 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).
+
+Pure and deterministic. No I/O, no model call, no retrieval call.
+Reuses ``aborist.qa.quantifier.classify_question_quantifier`` for
+the broad-quantifier rung; adds four new lightweight detectors:
+
+  - temporal sensitivity     (current/latest/today/CEO/etc.)
+  - contradiction (lexical)  (unmarried+spouse, always+sometimes-not)
+  - false-premise (lite)     (presupposition patterns)
+  - out-of-corpus            (my-uploaded-X / my-file shapes)
+
+Reference-frame detection lives in ``aborist.qa.query._detect_frame``
+(ticket #000002) and is called from the surrounding runtime, not
+from this module — keeps detection pure-on-question (no corpus
+lookup needed here).
+
+The output is a ``QuestionState`` dataclass that becomes a CTI root
+node. First pass surfaces it on the ``query()`` result dict only;
+run-DAG node binding deferred to the same Phase 5 work tracked in
+ticket #000009 (both nodes can land together).
+
+Hard rule (D1): No LLM in this hard path. Model-assisted preflight,
+if added later, labels itself ``SOFT_PREFLIGHT_HINT`` and never
+produces a ``PREFLIGHT_OK`` / ``PREFLIGHT_BLOCKED`` without
+deterministic support.
+"""
+
+from __future__ import annotations
+
+import hashlib
+import re
+from dataclasses import asdict, dataclass, field
+from typing import Any, Literal
+
+PREFLIGHT_VERSION = "metacognition-v0.1"
+
+
+# ---------------------------------------------------------------- types
+
+LogicalStatus = Literal[
+    "well_formed",
+    "under_specified",
+    "false_premise_suspected",
+    "contradictory_question",
+    "out_of_corpus_risk",
+    "stale_risk",
+    "reference_frame_ambiguous",
+    "broad_quantifier_unbounded",
+]
+
+PreflightResult = Literal[
+    "PREFLIGHT_OK",
+    "PREFLIGHT_PARTIAL",
+    "PREFLIGHT_BLOCKED",
+]
+
+TemporalSensitivity = Literal["high", "medium", "low"]
+
+
+
+[docs] +@dataclass(frozen=True) +class QuestionState: + """Runtime epistemic state for one question. + + All fields are deterministic from the question + per-call + `model_profile` / `corpus_profile` / `policy` inputs. No + randomness, no LLM. Hashable via `preflight_policy_hash` so + the run-DAG (Phase 5) can bind the decision into the audit + chain. + """ + + raw_question: str + question_hash: str + logical_statuses: tuple[LogicalStatus, ...] + question_shape: str + quantifier_intensity: str | None + quantifier_matched_token: str | None + scope_bound_hint: str + reference_frames: tuple[str, ...] + temporal_sensitivity: TemporalSensitivity + temporal_matched_tokens: tuple[str, ...] + contradiction_pairs: tuple[tuple[str, str], ...] + false_premise_hints: tuple[dict, ...] + corpus_requirement: str + known_boundaries: tuple[str, ...] + answer_constraints: dict + preflight_result: PreflightResult + preflight_policy_hash: str + classifier_version: str = PREFLIGHT_VERSION + +
+[docs] + def to_dict(self) -> dict: + """Convert to JSON-serializable dict for run-DAG / bench.""" + out = asdict(self) + # asdict converts inner dataclasses but tuples-of-tuples + # come back as nested lists already — keep them as lists + # for JSON hygiene. + return out
+
+ + + +# ---------------------------------------------------------------- temporal + +# Lexical patterns at start-of-question or as standalone tokens. +# `current`, `latest`, `today`, `now`, `as of`, `this year`. +_TEMPORAL_HIGH_PATTERNS = [ + re.compile(r"\bcurrent(?:ly)?\b", re.IGNORECASE), + re.compile(r"\blatest\b", re.IGNORECASE), + re.compile(r"\btoday\b", re.IGNORECASE), + re.compile(r"\bright now\b", re.IGNORECASE), + re.compile(r"\bas of\b", re.IGNORECASE), + re.compile(r"\bthis year\b", re.IGNORECASE), + re.compile(r"\bthis month\b", re.IGNORECASE), + re.compile(r"\bthis week\b", re.IGNORECASE), + re.compile(r"\brecently?\b", re.IGNORECASE), +] + +# Role-shape patterns: questions about who currently holds a role. +# Conservative — only positions with rapid turnover. +_TEMPORAL_ROLE_PATTERNS = [ + re.compile(r"\bCEO\b"), + re.compile(r"\bpresident of\b", re.IGNORECASE), + re.compile(r"\bprime minister\b", re.IGNORECASE), + re.compile(r"\bcurrent (?:champion|holder|price|stock)\b", re.IGNORECASE), +] + + +
+[docs] +def detect_temporal_sensitivity( + question: str, +) -> tuple[TemporalSensitivity, tuple[str, ...]]: + """Return ``(sensitivity, matched_tokens)``. + + `high` = explicit temporal anchor (`current`, `latest`, etc.) + OR rapid-turnover role pattern. `medium` reserved for future + weekly/monthly cadence detection (not implemented in this + pass). `low` = no temporal markers detected (the default). + """ + matched: list[str] = [] + for pat in _TEMPORAL_HIGH_PATTERNS: + m = pat.search(question) + if m: + matched.append(m.group(0)) + for pat in _TEMPORAL_ROLE_PATTERNS: + m = pat.search(question) + if m: + matched.append(m.group(0)) + if matched: + return "high", tuple(matched) + return "low", ()
+ + + +# ---------------------------------------------------------------- contradiction + +# Conservative lexical-contradiction pairs. Only fires when BOTH +# tokens appear in the question. False positives are operator- +# hostile so we keep the list short and obvious. +_CONTRADICTION_PAIRS: tuple[tuple[str, str], ...] = ( + ("unmarried", "spouse"), + ("unmarried", "married"), + ("never", "always"), + ("alive", "dead"), + ("nonexistent", "existing"), + ("only", "also"), +) + + +
+[docs] +def detect_contradiction( + question: str, +) -> tuple[tuple[str, str], ...]: + """Return tuple of (token_a, token_b) pairs whose BOTH members + appear in ``question`` (case-insensitive whole-word match). + + 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. + """ + q_lower = question.lower() + found: list[tuple[str, str]] = [] + for a, b in _CONTRADICTION_PAIRS: + # Word-boundary match on each side independently. + a_re = re.compile(rf"\b{re.escape(a)}\b") + b_re = re.compile(rf"\b{re.escape(b)}\b") + if a_re.search(q_lower) and b_re.search(q_lower): + found.append((a, b)) + return tuple(found)
+ + + +# ---------------------------------------------------------------- false premise + +# Presupposition patterns. Each pattern extracts an implied relation +# from the question shape. The verifier uses `false_premise_hints` +# as a `required_evidence` hint — the question is NOT blocked, but +# the audit-line tail surfaces "false premise suspected" so the +# operator knows the system didn't blindly accept the premise. + +# Subject and predicate character classes deliberately allow periods +# ("Mr.", "U.S."), apostrophes ("Homer's"), and hyphens +# ("by-law"). End-marker is `?` only (declarative variants of these +# question-shapes are not the target). +_FP_SUBJ = r"[\w\s\.\-']+?" +_FP_PRED = r"[\w\s\.\-']+?" + +_FALSE_PREMISE_PATTERNS = [ + # "when did X stop Y?" → presupposes X did Y + ( + re.compile( + rf"\bwhen did\s+(?P<subject>{_FP_SUBJ})\s+stop\s+(?P<predicate>{_FP_PRED})\s*\?", + re.IGNORECASE, + ), + "stopped_doing", + "X did Y at some prior time", + ), + # "why did X cause Y?" → presupposes X caused Y + ( + re.compile( + rf"\bwhy did\s+(?P<subject>{_FP_SUBJ})\s+cause\s+(?P<predicate>{_FP_PRED})\s*\?", + re.IGNORECASE, + ), + "caused", + "X caused Y", + ), + # "how did X become Y?" → presupposes X became Y + ( + re.compile( + rf"\bhow did\s+(?P<subject>{_FP_SUBJ})\s+become\s+(?P<predicate>{_FP_PRED})\s*\?", + re.IGNORECASE, + ), + "became", + "X became Y", + ), + # "when did X become Y?" → presupposes X became Y + ( + re.compile( + rf"\bwhen did\s+(?P<subject>{_FP_SUBJ})\s+become\s+(?P<predicate>{_FP_PRED})\s*\?", + re.IGNORECASE, + ), + "became", + "X became Y", + ), +] + + +
+[docs] +def detect_false_premise(question: str) -> tuple[dict, ...]: + """Return tuple of presupposition dicts surfacing the implied + relation. Each dict carries: + + kind — pattern label (stopped_doing, caused, ...) + presupposition — natural-language statement of the + presupposition + subject — extracted subject token-span + predicate — extracted predicate token-span + + 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. + + Returns empty tuple when no pattern fires. + """ + hints: list[dict] = [] + if not question: + return () + # Append a `?` if the question lacks one — the patterns + # require a sentence-ending marker for the predicate group. + test_q = question if question.rstrip().endswith(("?", ".")) else question + "?" + for pat, kind, presup_template in _FALSE_PREMISE_PATTERNS: + m = pat.search(test_q) + if m: + subject = m.group("subject").strip() + predicate = m.group("predicate").strip() + hints.append({ + "kind": kind, + "presupposition": presup_template.replace( + "X", subject + ).replace("Y", predicate), + "subject": subject, + "predicate": predicate, + }) + return tuple(hints)
+ + + +# ---------------------------------------------------------------- out-of-corpus + +# Patterns that signal the operator is asking about a private / +# uploaded / non-corpus document. Conservative — defaults to +# "likely_in_corpus" for typical encyclopedic questions. +_OUT_OF_CORPUS_PATTERNS = [ + re.compile(r"\bmy (?:uploaded|unpublished|attached|private) [\w\s]+\b", re.IGNORECASE), + re.compile(r"\bthe file (?:i sent|i uploaded|i attached)\b", re.IGNORECASE), + re.compile(r"\bthe document (?:i sent|i uploaded|i attached)\b", re.IGNORECASE), + re.compile(r"\bin my (?:contract|email|notes|spreadsheet|inbox)\b", re.IGNORECASE), + re.compile(r"\bwhat does my [\w\s]+ say\b", re.IGNORECASE), +] + + +
+[docs] +def detect_out_of_corpus(question: str) -> bool: + """Return True iff the question references a private / uploaded + document that the encyclopedic corpus cannot have.""" + for pat in _OUT_OF_CORPUS_PATTERNS: + if pat.search(question): + return True + return False
+ + + +# ---------------------------------------------------------------- preflight + +def _question_hash(question: str) -> str: + """Stable SHA-256 of the raw question string. Lower-cased, + whitespace-normalized so trivial variants share a hash.""" + canon = re.sub(r"\s+", " ", question.strip().lower()) + return hashlib.sha256(canon.encode("utf-8")).hexdigest() + + +def _preflight_policy_hash(*, policy: dict | None, version: str) -> str: + """Hash of the policy fields that drive preflight behavior + + the classifier version. Bumping any of them invalidates prior + QuestionState records on lookup.""" + relevant = { + "metacognition_enabled": (policy or {}).get("metacognition_enabled", True), + "metacognition_temporal_check": (policy or {}).get( + "metacognition_temporal_check", True + ), + "metacognition_contradiction_check": (policy or {}).get( + "metacognition_contradiction_check", True + ), + "metacognition_false_premise_check": (policy or {}).get( + "metacognition_false_premise_check", True + ), + "metacognition_out_of_corpus_check": (policy or {}).get( + "metacognition_out_of_corpus_check", True + ), + "metacognition_block_on_contradiction": (policy or {}).get( + "metacognition_block_on_contradiction", False + ), + "version": version, + } + payload = "|".join(f"{k}={relevant[k]}" for k in sorted(relevant)) + return hashlib.sha256(payload.encode("utf-8")).hexdigest() + + +def _classify_question_shape( + quantifier_intensity: str | None, + temporal: TemporalSensitivity, + has_contradiction: bool, + has_false_premise: bool, + has_out_of_corpus: bool, +) -> str: + """Map the detector outputs onto a coarse shape mnemonic. + + Used by downstream policy + audit display so the operator can + eyeball the question type without parsing the full QuestionState. + """ + if has_out_of_corpus: + return "out_of_corpus" + if has_contradiction: + return "contradictory" + if has_false_premise: + return "presupposing" + if temporal == "high": + return "time_sensitive" + if quantifier_intensity in {"ALL", "COMPREHENSIVE", "OPEN_REQUEST"}: + return "broad_request" + if quantifier_intensity in {"SMALL_NUM_EXPLICIT", "COMPARATIVE_BOUND"}: + return "bounded_count" + if quantifier_intensity == "ABSENT": + return "negation" + if quantifier_intensity == "PROPORTIONAL": + return "proportional" + return "single_fact" + + +
+[docs] +def preflight_question( + question: str, + *, + model_profile_id: str | None = None, + corpus_profile: dict | None = None, + reference_frames: tuple[str, ...] = (), + policy: dict | None = None, +) -> QuestionState: + """Classify ``question`` deterministically into a QuestionState. + + Pure function. Reuses the Phase 1 quantifier classifier + (#000008) plus four new lightweight detectors (temporal, + contradiction, false-premise-lite, out-of-corpus). + + `corpus_profile` is an optional dict carrying corpus boundary + metadata (e.g. ``{"corpus_latest_timestamp": "2003-05-16"}``); + when present, the temporal detector cross-checks against it. + First-pass implementation just records `corpus_requirement` + based on the temporal sensitivity — full cutoff arithmetic + deferred to a future amend. + + `reference_frames` is passed in by the caller because frame + detection requires retrieved sources (lives in + `aborist.qa.query._detect_frame`). Empty tuple is the default + for "no frame routing happened". + + `policy` overrides for the per-detector enables. Defaults are + permissive (all checks on) per ticket #000010 §7.3. + """ + from aborist.qa.quantifier import classify_question_quantifier + + policy = policy or {} + enabled = bool(policy.get("metacognition_enabled", True)) + temporal_on = bool(policy.get("metacognition_temporal_check", True)) + contradiction_on = bool(policy.get("metacognition_contradiction_check", True)) + false_premise_on = bool(policy.get("metacognition_false_premise_check", True)) + out_of_corpus_on = bool(policy.get("metacognition_out_of_corpus_check", True)) + block_on_contradiction = bool( + policy.get("metacognition_block_on_contradiction", False) + ) + + # Empty-question short-circuit. + if not question or not question.strip(): + return QuestionState( + raw_question=question or "", + question_hash=_question_hash(question or ""), + logical_statuses=(), + question_shape="empty", + quantifier_intensity=None, + quantifier_matched_token=None, + scope_bound_hint="unknown", + reference_frames=(), + temporal_sensitivity="low", + temporal_matched_tokens=(), + contradiction_pairs=(), + false_premise_hints=(), + corpus_requirement="not_applicable", + known_boundaries=("empty question",), + answer_constraints={}, + preflight_result="PREFLIGHT_BLOCKED", + preflight_policy_hash=_preflight_policy_hash( + policy=policy, version=PREFLIGHT_VERSION + ), + ) + + # Master kill — return a stub QuestionState with no detector + # output so the result schema stays consistent. Caller can + # distinguish "guard off" from "well-formed question" via the + # logical_statuses tuple being empty AND classifier_version. + if not enabled: + return QuestionState( + raw_question=question, + question_hash=_question_hash(question), + logical_statuses=(), + question_shape="metacognition_disabled", + quantifier_intensity=None, + quantifier_matched_token=None, + scope_bound_hint="unknown", + reference_frames=(), + temporal_sensitivity="low", + temporal_matched_tokens=(), + contradiction_pairs=(), + false_premise_hints=(), + corpus_requirement="not_evaluated", + known_boundaries=(), + answer_constraints={}, + preflight_result="PREFLIGHT_OK", + preflight_policy_hash=_preflight_policy_hash( + policy=policy, version=PREFLIGHT_VERSION + ), + ) + + # Reuse the #000008 quantifier classifier. + quant = classify_question_quantifier(question) + + # Run the four new detectors (each gateable). + if temporal_on: + temporal, temporal_matched = detect_temporal_sensitivity(question) + else: + temporal, temporal_matched = "low", () + + if contradiction_on: + contradictions = detect_contradiction(question) + else: + contradictions = () + + if false_premise_on: + false_premise = detect_false_premise(question) + else: + false_premise = () + + if out_of_corpus_on: + out_of_corpus = detect_out_of_corpus(question) + else: + out_of_corpus = False + + # Compose logical statuses. + statuses: list[LogicalStatus] = [] + if quant.get("is_broad") and quant.get("scope_bound_hint") == "unbounded": + statuses.append("broad_quantifier_unbounded") + elif quant.get("is_broad"): + statuses.append("under_specified") + if temporal == "high": + statuses.append("stale_risk") + if contradictions: + statuses.append("contradictory_question") + if false_premise: + statuses.append("false_premise_suspected") + if out_of_corpus: + statuses.append("out_of_corpus_risk") + if reference_frames and len(reference_frames) > 1: + statuses.append("reference_frame_ambiguous") + if not statuses: + statuses.append("well_formed") + + # Compose answer constraints. + answer_constraints: dict[str, Any] = {} + if "broad_quantifier_unbounded" in statuses or "under_specified" in statuses: + answer_constraints["bounded_or_reject"] = True + answer_constraints["max_claims_hint"] = quant.get("explicit_count") or 8 + if "stale_risk" in statuses: + answer_constraints["requires_current_source"] = True + if "false_premise_suspected" in statuses: + answer_constraints["require_premise_evidence"] = [ + h["presupposition"] for h in false_premise + ] + if "out_of_corpus_risk" in statuses: + answer_constraints["expected_corpus_status"] = "out_of_corpus" + + # Known boundaries — human-readable hints for the audit-line + # render layer + bench operator. + boundaries: list[str] = [] + if temporal_matched: + boundaries.append( + f"temporal markers: {', '.join(temporal_matched)}" + ) + if contradictions: + boundaries.append( + "lexical contradiction: " + + ", ".join(f"{a}/{b}" for a, b in contradictions) + ) + if false_premise: + boundaries.append( + "presuppositions: " + + "; ".join(h["presupposition"] for h in false_premise) + ) + if out_of_corpus: + boundaries.append("references private/uploaded document") + if quant.get("is_broad"): + boundaries.append( + f"broad quantifier ({quant.get('intensity')}, " + f"scope={quant.get('scope_bound_hint')})" + ) + + # Decide preflight result. + # PREFLIGHT_BLOCKED only when an explicit blocking condition is + # set in policy (default False for contradiction-block); otherwise + # PREFLIGHT_PARTIAL when any non-OK status fires; PREFLIGHT_OK + # when only "well_formed" is present. + if "well_formed" in statuses and len(statuses) == 1: + preflight_result: PreflightResult = "PREFLIGHT_OK" + elif "out_of_corpus_risk" in statuses: + preflight_result = "PREFLIGHT_BLOCKED" + elif block_on_contradiction and "contradictory_question" in statuses: + preflight_result = "PREFLIGHT_BLOCKED" + else: + preflight_result = "PREFLIGHT_PARTIAL" + + corpus_requirement = ( + "needs_current_source" + if temporal == "high" + else "out_of_corpus_likely" + if out_of_corpus + else "encyclopedic" + ) + + return QuestionState( + raw_question=question, + question_hash=_question_hash(question), + logical_statuses=tuple(statuses), + question_shape=_classify_question_shape( + quantifier_intensity=quant.get("intensity"), + temporal=temporal, + has_contradiction=bool(contradictions), + has_false_premise=bool(false_premise), + has_out_of_corpus=out_of_corpus, + ), + quantifier_intensity=quant.get("intensity"), + quantifier_matched_token=quant.get("matched_token"), + scope_bound_hint=quant.get("scope_bound_hint", "unknown"), + reference_frames=tuple(reference_frames), + temporal_sensitivity=temporal, + temporal_matched_tokens=tuple(temporal_matched), + contradiction_pairs=tuple(contradictions), + false_premise_hints=tuple(false_premise), + corpus_requirement=corpus_requirement, + known_boundaries=tuple(boundaries), + answer_constraints=answer_constraints, + preflight_result=preflight_result, + preflight_policy_hash=_preflight_policy_hash( + policy=policy, version=PREFLIGHT_VERSION + ), + )
+ +
+
+
+
+ + +
+
+ + Made with Sphinx and @pradyunsg's + + Furo + +
+
+ +
+
+ +
+
+ +
+
+ + + + + \ No newline at end of file diff --git a/docs/_source/_build/html/_modules/aborist/qa/quantifier.html b/docs/_source/_build/html/_modules/aborist/qa/quantifier.html new file mode 100644 index 0000000..5c7f1ac --- /dev/null +++ b/docs/_source/_build/html/_modules/aborist/qa/quantifier.html @@ -0,0 +1,703 @@ + + + + + + + + aborist.qa.quantifier - Aborist API Reference + + + + + + + + + + + + + + + + Contents + + + + + + Menu + + + + + + + + Expand + + + + + + Light mode + + + + + + + + + + + + + + Dark mode + + + + + + + Auto light/dark, in light mode + + + + + + + + + + + + + + + Auto light/dark, in dark mode + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Skip to content + + + +
+
+
+ +
+ +
+
+ +
+ +
+
+ +
+
+
+ + + + + Back to top + +
+
+ +
+ +
+
+

Source code for aborist.qa.quantifier

+"""Pure quantifier preflight classifier — Ticket #000008 Phase 1.
+
+Maps a question string onto the ten-rung intensity ladder defined in
+``docs/tickets/ticket-000008-broad-quantifier-preflight-guard.md`` §2.
+The classifier exists to estimate **expected number of claims in the
+answer** and **format-discipline risk on small models**. It is not
+formal-semantics quantifier theory; the operational axis is what
+matters.
+
+Pure function. No I/O. No model call. No retrieval call. Folds into
+``governance_policy_hash`` via ``classifier_version`` (added to
+``aborist.qa.keys._VERIFIER_POLICY_FIELDS`` in Phase 2).
+
+Intensity rungs (highest wins for multi-quantifier questions):
+
+    1.  ABSENT             universal-negation, single-claim shape
+    2.  SINGULAR           one-fact wh / definite reference
+    3.  PROPORTIONAL       descriptive fraction (`most`, `half`)
+    4.  SMALL_NUM_EXPLICIT bounded by digit/word (`top 3`, `seven X`)
+    5.  COMPARATIVE_BOUND  bounded by inequality (`at least 5`)
+    6.  FEW                small set, vague (`some`, `a few`)
+    7.  MANY               medium set, vague (`many`, `numerous`)
+    8.  ALL                universal quantifier (`all`, `every`)
+    9.  COMPREHENSIVE      exhaustive request (`complete list of`,
+                          `tell me everything`)
+    10. OPEN_REQUEST       verb-driven enumeration (`tell me about`,
+                          `describe`, `explain`)
+
+Returns a dict with:
+
+    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;
+                          None otherwise
+    is_broad               True for ALL / COMPREHENSIVE / OPEN_REQUEST
+    operational_shape      mnemonic for downstream policy (e.g.
+                          "universal_enumeration", "exhaustive_request")
+    scope_bound_hint       "bounded" | "unbounded" | "unknown"
+                          (see ticket §10.1 — bounded ≠ unbounded
+                           universals; classifier defaults to "unknown"
+                           when intensity is broad and no domain anchor
+                           is present)
+
+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 ``_RUNG_PRIORITY`` codifies
+this — later rungs win.
+"""
+
+from __future__ import annotations
+
+import re
+
+CLASSIFIER_VERSION = "quantifier-v0.1"
+
+# ---------------------------------------------------------------- intensities
+
+_RUNG_PRIORITY = (
+    "SINGULAR",
+    "PROPORTIONAL",
+    "SMALL_NUM_EXPLICIT",
+    "COMPARATIVE_BOUND",
+    "FEW",
+    "MANY",
+    "ABSENT",
+    "ALL",
+    # OPEN_REQUEST sits below COMPREHENSIVE: "tell me everything
+    # about X" is BOTH OPEN_REQUEST-shape ("tell me about") AND
+    # COMPREHENSIVE-shape ("everything"). COMPREHENSIVE wins because
+    # it carries the explicit exhaustive request — see §2.2 of
+    # ticket #000008 ("COMPREHENSIVE strictly stronger than ALL").
+    # On the cap table, COMPREHENSIVE caps higher than OPEN_REQUEST
+    # for large models because the operator is asking for depth
+    # explicitly; both clamp at 5 on small models.
+    "OPEN_REQUEST",
+    "COMPREHENSIVE",
+)
+
+_BROAD_RUNGS = frozenset({"ALL", "COMPREHENSIVE", "OPEN_REQUEST"})
+
+
+# Lexical patterns per rung. Patterns are compiled with re.IGNORECASE
+# at module-load. Order within each rung doesn't matter — first match
+# wins for matched_token reporting, but rung selection is by priority
+# (later rung = higher intensity, see _classify).
+
+# OPEN_REQUEST — verb-driven enumeration without explicit quantifier.
+_OPEN_REQUEST_PATTERNS = [
+    r"\btell me (?:about|all about)\b",
+    r"\btell me everything\b",
+    r"\bdescribe\b",
+    r"\bexplain\b",
+    r"\bsummari[sz]e\b",
+    r"\bgive me (?:an? )?(?:overview|summary)\b",
+    r"\bwalk me through\b",
+    r"\bdiscuss\b",
+    r"\belaborate on\b",
+    r"\bexpound on\b",
+    r"\bwhat about\b",
+]
+
+# COMPREHENSIVE — exhaustive request, strictly stronger than ALL.
+_COMPREHENSIVE_PATTERNS = [
+    r"\bcomprehensive\b",
+    r"\bcomplete (?:list|inventory|set|enumeration|account)\b",
+    r"\bexhaustive\b",
+    r"\bdefinitive\b",
+    r"\beverything (?:you know|there is)\b",
+    r"\btell me everything\b",
+    r"\bthe whole (?:story|picture|thing)\b",
+    r"\bthe full (?:story|picture|account)\b",
+    r"\bfrom a to z\b",
+    r"\ball there is to know\b",
+]
+
+# ALL — universal quantifier.
+_ALL_PATTERNS = [
+    r"\ball\b",
+    r"\bevery\b",
+    r"\beach (?:and every )?\b",
+    r"\bevery single\b",
+    r"\bthe whole\b",
+    r"\bthe entirety of\b",
+    r"\bthe totality of\b",
+    r"\bany\b",            # universal use ("any X is Y")
+    r"\bwhatever\b",
+    r"\bwhoever\b",
+]
+
+# MANY — medium set, vague.
+_MANY_PATTERNS = [
+    r"\bmany\b",
+    r"\bvarious\b",
+    r"\bmultiple\b",
+    r"\bnumerous\b",
+    r"\ba number of\b",
+    r"\blots of\b",
+    r"\bplenty of\b",
+    r"\ba great many\b",
+    r"\bmultitudes\b",
+    r"\bseveral dozen\b",
+]
+
+# FEW — small set, vague.
+_FEW_PATTERNS = [
+    r"\bsome\b",
+    r"\ba few\b",
+    r"\bseveral\b",
+    r"\ba couple\b",
+    r"\ba handful\b",
+    r"\ba small number of\b",
+    r"\ba smattering of\b",
+    r"\bnot many\b",
+    r"\bhardly any\b",
+]
+
+# SMALL_NUM_EXPLICIT — bounded by digit or numeric word.
+# Matched token reports the count phrase; explicit_count populated
+# from the digit / lexicon below.
+_SMALL_NUM_DIGIT = re.compile(
+    r"\btop (\d+)\b|\b(\d+) (?:biggest|smallest|largest|most|best|worst)\b"
+    r"|\b(?:first|last|top) (\d+)\b",
+    re.IGNORECASE,
+)
+_NUMBER_WORDS = {
+    "one": 1, "two": 2, "three": 3, "four": 4, "five": 5,
+    "six": 6, "seven": 7, "eight": 8, "nine": 9, "ten": 10,
+    "eleven": 11, "twelve": 12, "dozen": 12,
+}
+_SMALL_NUM_WORD_PATTERNS = [
+    rf"\b(?:top |first |last )?({w})\b" for w in _NUMBER_WORDS
+]
+_PAIR_OF = re.compile(r"\bpair of\b", re.IGNORECASE)
+_HANDFUL_OF = re.compile(r"\ba handful of\b", re.IGNORECASE)
+
+# COMPARATIVE_BOUND — bounded by inequality.
+# at_least / at_most / more_than / fewer_than / under / over /
+# up_to / between A and B.
+_COMPARATIVE_PATTERNS = [
+    re.compile(r"\bat least (\d+)\b", re.IGNORECASE),
+    re.compile(r"\bat most (\d+)\b", re.IGNORECASE),
+    re.compile(r"\bno more than (\d+)\b", re.IGNORECASE),
+    re.compile(r"\bmore than (\d+)\b", re.IGNORECASE),
+    re.compile(r"\bfewer than (\d+)\b", re.IGNORECASE),
+    re.compile(r"\bless than (\d+)\b", re.IGNORECASE),
+    re.compile(r"\bunder (\d+)\b", re.IGNORECASE),
+    re.compile(r"\bover (\d+)\b", re.IGNORECASE),
+    re.compile(r"\bup to (\d+)\b", re.IGNORECASE),
+    re.compile(r"\bbetween (\d+) and (\d+)\b", re.IGNORECASE),
+]
+
+# PROPORTIONAL — descriptive fraction.
+_PROPORTIONAL_PATTERNS = [
+    r"\bmost\b",
+    r"\bmajority of\b",
+    r"\bminority of\b",
+    r"\bhalf (?:of|the)\b",
+    r"\ba third of\b",
+    r"\ba quarter of\b",
+    r"\b\d+%\s*of\b",
+    r"\bthe bulk of\b",
+    r"\bthe lion's share of\b",
+]
+
+# Count-question short-circuit. `how many` / `how much` at the
+# start of a question (or after a leading wh-clause like
+# "and how many...") is asking for a single numeric answer, not
+# enumeration. Without this short-circuit the bare `\bmany\b`
+# pattern below misfires.
+#
+# Anchored so we only short-circuit when the question is a count-
+# question SHAPE — `how many` further into the question (e.g.
+# "list the states; how many are there?") doesn't take precedence
+# over the rest of the question's quantifier markers.
+_COUNT_QUESTION_RE = re.compile(
+    r"^\s*(?:and\s+|but\s+|so\s+)?how (?:many|much)\b",
+    re.IGNORECASE,
+)
+
+
+# ABSENT — universal-negation.
+_ABSENT_PATTERNS = [
+    r"\bnone\b",
+    r"\bno (?:one|body|where)\b",
+    r"\bnothing\b",
+    r"\bnobody\b",
+    r"\bnowhere\b",
+    r"\bneither\b",
+    r"\bnever\b",
+    r"\bnot a single\b",
+    r"\bzero\b",
+    # Negative wh-shape: "which X is/are/do/does/did/has/have not Y".
+    # Catches both copular ("which X is not Y") and auxiliary
+    # ("which X do not Y") forms — both express universal negation
+    # over the X universe.
+    r"\bwhich \w+ (?:is |are |do |does |did |has |have |were |was )?not\b",
+    r"\bwho (?:is |are |do |does |did |has |have )?not\b",
+    r"\bwhat (?:is |are |do |does |did |has |have )?not\b",
+]
+
+# Compile each rung's patterns once.
+_OPEN_REQUEST_RE = [re.compile(p, re.IGNORECASE) for p in _OPEN_REQUEST_PATTERNS]
+_COMPREHENSIVE_RE = [re.compile(p, re.IGNORECASE) for p in _COMPREHENSIVE_PATTERNS]
+_ALL_RE = [re.compile(p, re.IGNORECASE) for p in _ALL_PATTERNS]
+_MANY_RE = [re.compile(p, re.IGNORECASE) for p in _MANY_PATTERNS]
+_FEW_RE = [re.compile(p, re.IGNORECASE) for p in _FEW_PATTERNS]
+_PROPORTIONAL_RE = [re.compile(p, re.IGNORECASE) for p in _PROPORTIONAL_PATTERNS]
+_ABSENT_RE = [re.compile(p, re.IGNORECASE) for p in _ABSENT_PATTERNS]
+
+
+# ---------------------------------------------------------------- shape mnemonics
+
+_OPERATIONAL_SHAPE = {
+    "ABSENT": "universal_negation",
+    "SINGULAR": "single_fact",
+    "PROPORTIONAL": "descriptive_fraction",
+    "SMALL_NUM_EXPLICIT": "bounded_count",
+    "COMPARATIVE_BOUND": "bounded_inequality",
+    "FEW": "small_set_vague",
+    "MANY": "medium_set_vague",
+    "ALL": "universal_enumeration",
+    "COMPREHENSIVE": "exhaustive_request",
+    "OPEN_REQUEST": "verb_driven_enumeration",
+}
+
+
+# ---------------------------------------------------------------- scope hint
+
+# Lexical anchors that hint a bounded universe — when present alongside
+# a broad quantifier, scope_bound_hint upgrades from "unknown" to
+# "bounded". This is a heuristic; the corpus arity check (§10.1) is
+# left for a future refinement.
+_BOUNDED_DOMAIN_ANCHORS = (
+    re.compile(r"\bthe (?:beatles|fab four)\b", re.IGNORECASE),
+    re.compile(r"\b(?:US|U\.S\.|united states) (?:states|presidents)\b", re.IGNORECASE),
+    re.compile(r"\bplanets (?:in (?:the|our) solar system)?\b", re.IGNORECASE),
+    re.compile(r"\bfounding fathers\b", re.IGNORECASE),
+    re.compile(r"\bcontinents\b", re.IGNORECASE),
+    re.compile(r"\boceans\b", re.IGNORECASE),
+    # Year/season-anchored questions tend to bound the universe to one
+    # event — "winners of the 2024 World Series" is bounded.
+    re.compile(r"\b(?:19|20)\d{2}\b"),
+    re.compile(r"\b(?:season|year|championship|tournament|event) (?:of|for)\b", re.IGNORECASE),
+)
+
+
+def _scope_bound_hint(question: str, intensity: str) -> str:
+    """Return ``"bounded"``, ``"unbounded"``, or ``"unknown"``.
+
+    Bounded universals (``"all members of the Beatles"``, ``"every US
+    state"``) have a finite, corpus-known answer set. Unbounded
+    universals (``"winners of all major sports"``) have an undefined
+    set under the current scope. The classifier defaults to
+    ``"unknown"`` for non-broad intensities (the question doesn't
+    have universal pressure to gate) and to ``"unbounded"`` for broad
+    intensities lacking a domain anchor.
+
+    Heuristic only. The corpus arity check (§10.1 future refinement)
+    will sharpen this when implemented.
+    """
+    if intensity not in _BROAD_RUNGS:
+        return "unknown"
+    for anchor in _BOUNDED_DOMAIN_ANCHORS:
+        if anchor.search(question):
+            return "bounded"
+    return "unbounded"
+
+
+# ---------------------------------------------------------------- classifier
+
+
+[docs] +def classify_question_quantifier(question: str) -> dict: + """Classify ``question`` onto the ten-rung intensity ladder. + + 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 rung's cap, which is what we + want under enumeration pressure. + + Returns a dict; see module docstring for fields. + + Empty / whitespace-only questions classify SINGULAR (no quantifier + pressure) with no matched_token. + """ + if not question or not question.strip(): + return { + "intensity": "SINGULAR", + "matched_token": None, + "explicit_count": None, + "is_broad": False, + "operational_shape": _OPERATIONAL_SHAPE["SINGULAR"], + "scope_bound_hint": "unknown", + "classifier_version": CLASSIFIER_VERSION, + } + + # Count-question short-circuit (caught by 2026-05-03 dry-run + # review across bench/qa_questions.txt). `how many X?` and + # `how much X?` ask for a SINGLE numeric answer ("50 states", + # "206 bones") — not enumeration. Without this short-circuit, + # the bare `\bmany\b` pattern in _MANY_PATTERNS misfires on + # `how many` and the question lands in MANY rung (cap 8 on + # Hermes), which is wrong: a count question deserves cap 1 + # (SINGULAR), not 8. + # + # The same applies to `how often`, `how long`, `how big` — + # all count/measurement questions with single-fact answers. + # We catch the dominant `how many|much` shape here; the others + # already classify SINGULAR by default. + if _COUNT_QUESTION_RE.search(question): + m = _COUNT_QUESTION_RE.search(question) + return { + "intensity": "SINGULAR", + "matched_token": m.group(0), + "explicit_count": None, + "is_broad": False, + "operational_shape": _OPERATIONAL_SHAPE["SINGULAR"], + "scope_bound_hint": "unknown", + "classifier_version": CLASSIFIER_VERSION, + } + + candidates: list[tuple[str, str, int | None]] = [] + + # Per-rung detection. Earlier rungs run first but rung selection + # uses _RUNG_PRIORITY (highest-priority match wins). + def _check(rung_re_list: list[re.Pattern], rung_name: str) -> None: + for pat in rung_re_list: + m = pat.search(question) + if m: + token = m.group(0) + candidates.append((rung_name, token, None)) + return + + _check(_ABSENT_RE, "ABSENT") + _check(_PROPORTIONAL_RE, "PROPORTIONAL") + _check(_FEW_RE, "FEW") + _check(_MANY_RE, "MANY") + _check(_ALL_RE, "ALL") + _check(_COMPREHENSIVE_RE, "COMPREHENSIVE") + _check(_OPEN_REQUEST_RE, "OPEN_REQUEST") + + # SMALL_NUM_EXPLICIT — explicit digit or number word. + digit_match = _SMALL_NUM_DIGIT.search(question) + if digit_match: + # Pull the first non-None group as the count. + count = next( + (int(g) for g in digit_match.groups() if g is not None), + None, + ) + candidates.append(("SMALL_NUM_EXPLICIT", digit_match.group(0), count)) + else: + # Number-word path. Try each word; first hit wins. + for word, count in _NUMBER_WORDS.items(): + if re.search(rf"\b(?:top |first |last )?{word}\b", + question, re.IGNORECASE): + candidates.append( + ("SMALL_NUM_EXPLICIT", word, count) + ) + break + # `pair of` → 2; `a handful of` → 5 (folds into FEW + # operationally, but record as SMALL_NUM_EXPLICIT with + # count=2/5 so the cap is exact). + if _PAIR_OF.search(question): + candidates.append(("SMALL_NUM_EXPLICIT", "pair of", 2)) + if _HANDFUL_OF.search(question): + candidates.append(("SMALL_NUM_EXPLICIT", "a handful of", 5)) + + # COMPARATIVE_BOUND — explicit inequality. + for pat in _COMPARATIVE_PATTERNS: + m = pat.search(question) + if m: + # `between A and B` → use the upper bound; otherwise the + # single captured number. + groups = [int(g) for g in m.groups() if g is not None] + count = max(groups) if groups else None + candidates.append(("COMPARATIVE_BOUND", m.group(0), count)) + break + + if not candidates: + # Default — SINGULAR for any wh-question or definite reference + # without quantifier markers. + intensity = "SINGULAR" + matched_token: str | None = None + explicit_count: int | None = None + else: + # Highest-intensity wins (later in _RUNG_PRIORITY = higher). + priority = {r: i for i, r in enumerate(_RUNG_PRIORITY)} + candidates.sort(key=lambda c: priority.get(c[0], -1), reverse=True) + intensity, matched_token, explicit_count = candidates[0] + + return { + "intensity": intensity, + "matched_token": matched_token, + "explicit_count": explicit_count, + "is_broad": intensity in _BROAD_RUNGS, + "operational_shape": _OPERATIONAL_SHAPE[intensity], + "scope_bound_hint": _scope_bound_hint(question, intensity), + "classifier_version": CLASSIFIER_VERSION, + }
+ +
+
+
+
+ + +
+
+ + Made with Sphinx and @pradyunsg's + + Furo + +
+
+ +
+
+ +
+
+ +
+
+ + + + + \ No newline at end of file diff --git a/docs/_source/_build/html/_modules/aborist/qa/query.html b/docs/_source/_build/html/_modules/aborist/qa/query.html new file mode 100644 index 0000000..c2c5e83 --- /dev/null +++ b/docs/_source/_build/html/_modules/aborist/qa/query.html @@ -0,0 +1,3431 @@ + + + + + + + + aborist.qa.query - Aborist API Reference + + + + + + + + + + + + + + + + Contents + + + + + + Menu + + + + + + + + Expand + + + + + + Light mode + + + + + + + + + + + + + + Dark mode + + + + + + + Auto light/dark, in light mode + + + + + + + + + + + + + + + Auto light/dark, in dark mode + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Skip to content + + + +
+
+
+ +
+ +
+
+ +
+ +
+
+ +
+
+
+ + + + + Back to top + +
+
+ +
+ +
+
+

Source code for aborist.qa.query

+"""Multi-source corpus Q&A.
+
+Pose a question, the tree finds related cached docs, assembles them as context,
+asks Hermes, caches the answer.
+
+The flow:
+    1. FTS5 search across all shards (chunks_fts can't be UNION'd in views,
+       so we query each shard's index independently and merge by score).
+    2. 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).
+    3. Pick top-K distinct documents within a character budget.
+    4. Compute `context_root` = Merkle root over the sorted source
+       document_roots — that's the "source" dimension of v9.8's 8-dim
+       cache_key for this multi-source answer.
+    5. Cache lookup; hit returns the persisted audit_mode.
+    6. Miss calls Hermes via the OpenAI-compatible client, then runs the
+       faithfulness check (`verify_quotes`) — every double-quoted span in
+       the answer is verbatim-matched against the assembled context.
+       Result classifies the answer:
+           STRICT   every quote (>=1) verified against context
+           HYBRID   some claims sourced, some emergent (training-derived)
+           UNGROUNDED   no quotes verify — purely emergent
+    7. Persist record with merkle_proof = {context_root, sources: [...]},
+       audit_mode, and unverified_quotes (the spans the model produced
+       that didn't appear in any source — corpus-growth signal).
+
+Per-source proofs are not bundled here (the source roots themselves are
+already content-addressed). A verifier asks the shards for any specific
+chunk's proof on demand.
+"""
+
+from __future__ import annotations
+
+import json
+import re
+import time
+from dataclasses import dataclass
+from pathlib import Path
+
+from aborist import (
+    CANONICALIZATION_VERSION,
+    CHUNKING_VERSION,
+    SCHEMA_VERSION,
+)
+from aborist.compress import unpack_chunk
+from aborist.merkle import MerkleTree
+from aborist.qa.client import ChatClient
+from aborist.qa.prompts import (
+    CLAIM_LATTICE_GROUNDING_REMINDER,
+    CLAIM_LATTICE_JSON_GROUNDING_REMINDER,
+    CLAIM_LATTICE_JSON_SYSTEM_PROMPT,
+    CLAIM_LATTICE_SYSTEM_PROMPT,
+)
+from aborist.qa.concepts import (
+    has_compare_phrasing,
+    rivalry_excluded,
+    synonym_expand,
+)
+from aborist.qa.keys import (
+    DEFAULT_FIDELITY,
+    DEFAULT_QUESTION_DEDUP,
+    FIDELITY_MODES,
+    QUESTION_DEDUP_MODES,
+    cache_key,
+    canonical_question,
+    conversation_hash,
+    governance_policy_hash,
+    model_profile_hash,
+    question_hash,
+    verifier_policy_hash,
+)
+from aborist.qa.dag import build_run_dag
+from aborist.qa.frame import FrameDetection, detect_frame as _detect_frame
+from aborist.qa.retrieval_plan import RetrievalPlan, retrieval_plan_hash
+from aborist.qa.evidence import (
+    build_evidence_map,
+    evidence_map_root,
+    render_evidence_map,
+    render_evidence_map_for_json,
+)
+from aborist.qa.repair import mechanical_repair, reprompt_repair
+from aborist.qa.verify import (
+    ANSWER_MODES,
+    CLAIM_LATTICE_JSON_SCHEMA,
+    verify_claim_lattice_json,
+    DEFAULT_ANSWER_MODE,
+    verify_claim_lattice,
+    verify_quotes,
+)
+
+try:
+    from aborist.wikitext import BASE_VERSION as _WIKITEXT_BASE_VERSION
+    from aborist.wikitext import to_base as _wikitext_to_base
+except ImportError:  # pragma: no cover
+    _WIKITEXT_BASE_VERSION = None
+    _wikitext_to_base = None
+from aborist.search import FTS5Backend
+from aborist.store import (
+    append_audit,
+    connect,
+    discover_shards,
+    transaction,
+)
+
+
+_TITLE_TOKEN_RE = re.compile(r"[A-Za-z][A-Za-z0-9]*")
+# Hyphen-joined run of two-or-more word tokens. Used by
+# `_hyphen_fold_variants` to emit joined-no-hyphen variants. See
+# Ticket #000007 for the FTS5 hyphen-tokenization-asymmetry rationale:
+# `Bipolar disorder` indexes as [bipolar], `Bi-Polar (album)` indexes
+# as [bi, polar, ...]. Without the fold, query "bi-polar" hits only
+# the album cluster.
+_HYPHEN_RUN_RE = re.compile(
+    r"[A-Za-z][A-Za-z0-9]*(?:-[A-Za-z][A-Za-z0-9]*)+"
+)
+# Kept in sync with FTS5 stopwords in aborist.search.fts5 — both filter
+# the same set of question-shaping words. "tell" leaking into title-LIKE
+# search caused "tell me about permacomputer" to pull Tell_(poker), the
+# Tell-Tale_Heart movie, Tell_City Indiana, etc.
+_TITLE_STOPWORDS = frozenset(
+    """
+    the a an is are was were be been being of to in on at for with by from
+    as about into through during and or but not no nor so yet too very also just
+    what who where when why how which this that these those such i you he she
+    it we they me him her us them do does did have has had can could should
+    would will may might
+    tell show describe explain summarize say give list find make please
+    all there know everything anything something
+    """.split()
+)
+
+
+def _hyphen_fold_variants(s: str) -> set[str]:
+    """For each hyphen-joined run of word tokens in ``s``, emit the
+    joined-no-hyphen form. Lets retrieval reach indexed forms that
+    survived the FTS5 hyphen-split asymmetry (Ticket #000007):
+
+        "bi-polar is rare?"  -> {"bipolar"}
+        "high-school co-op"  -> {"highschool", "coop"}
+        "plain query"        -> set()
+
+    Stopword and length filters mirror ``_title_query_tokens`` so a
+    junk fold like "of-the" -> "ofthe" never enters the candidate set.
+    """
+    out: set[str] = set()
+    for run in _HYPHEN_RUN_RE.findall(s):
+        joined = run.replace("-", "").lower()
+        if len(joined) > 1 and joined not in _TITLE_STOPWORDS:
+            out.add(joined)
+    return out
+
+
+def _title_query_tokens(s: str) -> set[str]:
+    base = {
+        t.lower()
+        for t in _TITLE_TOKEN_RE.findall(s)
+        if t.lower() not in _TITLE_STOPWORDS and len(t) > 1
+    }
+    # Hyphen-fold: additively include joined-no-hyphen variants for
+    # hyphenated runs in `s`. Symmetric — the function is called on
+    # both queries and titles, and additive fold preserves existing
+    # match patterns (e.g. `Coca-Cola history` query keeps {coca,
+    # cola, cocacola, history} so a `Coca-Cola` title still passes
+    # title-breadth via {coca, cola, cocacola}). See Ticket #000007.
+    base |= _hyphen_fold_variants(s)
+    return base
+
+
+def _rerank_by_title(
+    hits: list,
+    question: str,
+    boost: float = 10.0,
+) -> list:
+    """Boost hits whose title overlaps query tokens. Pure ordering aid."""
+    qtokens = _title_query_tokens(question)
+    if not qtokens:
+        return hits
+    for h in hits:
+        if not h.title:
+            continue
+        ttokens = _title_query_tokens(h.title.replace("_", " "))
+        overlap = len(qtokens & ttokens)
+        if overlap:
+            h.score += overlap * boost
+    hits.sort(key=lambda h: -h.score)
+    return hits
+
+
+def _filter_by_title_relevance(
+    hits: list,
+    question: str,
+    *,
+    core_match_roots: set[str] | None = None,
+    body_density_check: callable | None = None,
+    phrase_match_roots: set[str] | None = None,
+    hyphen_fold_anchors: set[str] | None = None,
+    fallback_top_n: int = 5,
+    shards_dir=None,
+) -> list:
+    """Concept-aware relevance filter with five accept paths:
+
+    1. Title-token overlap (after synonym expansion). Strongest signal.
+    2. TF-IDF core keyword overlap — `core_match_roots` is a precomputed
+       set of source document_roots whose TF-IDF cores contain query
+       tokens. Closes the gap for neologisms like "permacomputer" that
+       never appear in titles but are distinctive enough to be TF-IDF
+       keywords of conversation bodies.
+    3. Body density — docs mentioning the query token >= N times pass
+       even without title or core match. Cheap proxy for "actually about
+       the topic." `body_density_check(hit)` returns bool.
+    4. Phrase-match — docs whose body contains a verbatim 4+ token
+       sequence from the question pass even when title and content
+       tokens don't overlap. Closes the allusion gap (2026-05-01
+       Orwell case): "has oceania always been at war with east asia"
+       has zero token overlap with the title "Nineteen Eighty-Four"
+       but the body contains the verbatim phrase "always been at
+       war" — without this accept path, the phrase-route hit gets
+       filtered out before it can rerank into the top-K. The
+       upstream phrase route already gates on 4-token-min sequences
+       (see _question_phrases) so false-positive risk is low.
+    5. Hyphen-fold anchor — when the question has hyphenated runs
+       (Ticket #000007), `hyphen_fold_anchors` is the joined-form
+       set ({"bipolar"} for "bi-polar is rare?"). Title-side stem
+       overlap with this anchor passes the filter even when the
+       breadth threshold fails. Rescues non-hyphen titles like
+       `Bipolar disorder` from rejection while leaving non-hyphen
+       queries (anchors empty) unaffected.
+
+    Rivalry exclusion (Intel-titled docs in AMD queries) still applies on
+    every accept path.
+
+    If all five accept paths together produce nothing, fall back to the
+    top `fallback_top_n` body-BM25 hits — the LLM gets enough context to
+    say "I don't know" rather than fabricating from a single tangential
+    source.
+    """
+    qtokens = _title_query_tokens(question)
+    if not qtokens:
+        return hits
+    qtokens_stem = {_stem_token_for_match(t) for t in qtokens}
+    accept = synonym_expand(qtokens, shards_dir=shards_dir)
+    exclude = rivalry_excluded(
+        qtokens,
+        compare_phrasing=has_compare_phrasing(question),
+        shards_dir=shards_dir,
+    )
+    core_roots = core_match_roots or set()
+    phrase_roots = phrase_match_roots or set()
+    anchor_stems = (
+        {_stem_token_for_match(a) for a in hyphen_fold_anchors}
+        if hyphen_fold_anchors
+        else set()
+    )
+    # Title-overlap breadth threshold scales with query length, mirroring
+    # _body_density_passes: ≤2 tokens require ALL, 3+ require N-1. Without
+    # this, a 2-token query like "supermans girlfriend" admits docs that
+    # share only ONE token with the title (e.g. `Girlfriends` the TV show)
+    # — title-overlap fires first & body-density never gets to reject.
+    title_breadth = len(qtokens) if len(qtokens) <= 2 else len(qtokens) - 1
+
+    kept: list = []
+    for h in hits:
+        ttokens = _title_query_tokens(h.title.replace("_", " ")) if h.title else set()
+        ttokens_stem = {_stem_token_for_match(t) for t in ttokens}
+        if exclude & ttokens:
+            continue  # rivalry: opposing-side title, drop it
+        # Direct stem-aware match against query tokens (each qtoken must
+        # be present, possessive/plural-tolerant). Strict signal.
+        direct_matches = len(qtokens_stem & ttokens_stem)
+        if direct_matches >= title_breadth:
+            kept.append(h)
+            continue
+        # Synonym fallback only for 1-token queries — otherwise a single
+        # synonym hit (e.g. "amd" matching an "intel"-titled doc via the
+        # Intel/AMD group) would over-recall.
+        if len(qtokens) == 1 and accept & ttokens:
+            kept.append(h)
+            continue
+        if h.document_root in core_roots:
+            kept.append(h)
+            continue
+        if h.document_root in phrase_roots:
+            kept.append(h)
+            continue
+        # Accept-path 5: hyphen-fold anchor (Ticket #000007). The
+        # joined-form variant from a hyphenated query token (e.g.
+        # "bipolar" from "bi-polar") matching the title's stem set
+        # is enough signal to pass — rescues `Bipolar disorder` from
+        # the breadth gate when the query was "bi-polar is rare?".
+        # Empty anchor set on non-hyphen queries — zero side effect.
+        if anchor_stems and (anchor_stems & ttokens_stem):
+            kept.append(h)
+            continue
+        if body_density_check is not None and body_density_check(h):
+            kept.append(h)
+            continue
+    if not kept:
+        return hits[: max(1, fallback_top_n)] if hits else []
+    return kept
+
+
+DEFAULT_QUERY_POLICY = {
+    # Ticket #000007 — query-layer hyphen-fold marker. Folds into
+    # `governance_policy_hash` so records produced under the new
+    # rule (`Bipolar disorder` reachable from query "bi-polar")
+    # cache-split cleanly from pre-fold records. Code applies the
+    # fold unconditionally; this flag exists to make the policy
+    # transition observable from the cache_key alone.
+    "hyphen_fold_v1": True,
+    # Ticket #000006 amend 2026-05-02b (Rule 9) — premise-parroting /
+    # subject-tokens-absent demote. Threshold = number of question∩
+    # claim content tokens that must be absent from the union of
+    # cited evidence spans before STRICT → HYBRID. Default 3 keeps
+    # the signal unambiguous (single-token absence is often a
+    # stem-variant near-miss; three+ is the parroting fingerprint).
+    # Folds into verifier_policy_hash + governance_policy_hash.
+    "claim_lattice_subject_tokens_absent_threshold": 3,
+    "system_prompt": (
+        "You are answering a question using ONLY the sources provided below. "
+        "Each source is delimited by '=== Source: <URI> ===' headers.\n\n"
+        "GROUNDING RULE (most important):\n"
+        "For EVERY factual claim in your answer, include a verbatim quote "
+        "from a source enclosed in double quotes (\"...\"). The quoted span "
+        "must appear word-for-word in one of the sources. Make a claim "
+        "only when a verbatim quote in one of the sources supports it. "
+        "Quote the source word-for-word inside the double quotes.\n\n"
+        "ATTRIBUTION RULES:\n"
+        "1. A single source may discuss MULTIPLE products, companies, or "
+        "competitors. Read carefully and attribute facts only to the entity "
+        "the source explicitly names for that fact.\n"
+        "2. When the question asks about ONE specific entity (e.g., 'fastest "
+        "AMD CPU'), keep facts about that entity in the answer; leave facts "
+        "about competitors (Intel, Pentium) out, even when the source "
+        "discusses both — they are different products that happen to share "
+        "an article.\n"
+        "3. When referencing model numbers like 'Athlon XP 3200+', remember "
+        "that AMD's PR-rating numbers (3200+, 2500+) are model labels, not "
+        "the clock speed in MHz. Quote the source's own wording for clock "
+        "speeds; let the source state the speed.\n"
+        "4. When the sources contain the answer, write it. When the answer "
+        "is absent from the sources, say 'I don't know based on the "
+        "provided sources.' and stop there. Stay inside the sources at "
+        "all times — let the corpus speak."
+    ),
+    # Restated rule fired as a user message immediately before the sources
+    # turn. Hermes (and most instruction-tuned 8B models) follow recent
+    # user-turn instructions more reliably than a system-turn rule that
+    # decays under long context. Repetition is not redundancy — it raises
+    # the prior on the response shape we want.
+    "grounding_reminder": (
+        "REMINDER: wrap every factual claim in double quotes (\"...\") "
+        "and the quoted span must appear word-for-word in one of the "
+        "sources. Each claim earns a verbatim quote. "
+        "Example:\n\n"
+        "  Q: who founded Apple?\n"
+        "  Sources: ...Apple Inc. was founded by Steve Jobs, Steve "
+        "Wozniak, and Ronald Wayne in 1976...\n"
+        "  A: Apple's founders are named in the source: \"Apple Inc. was "
+        "founded by Steve Jobs, Steve Wozniak, and Ronald Wayne\".\n\n"
+        "Now answer the question on the next message."
+    ),
+    "temperature": 0.1,
+    "top_p": 1.0,
+    "max_tokens": 768,
+    # Entity-path policy for the faithfulness verifier. See
+    # aborist/qa/verify.py:ENTITY_POLICIES. Default 'proximity' promotes
+    # to STRICT only if N verified entities cluster within W chars of
+    # each other in source — separating "source documents these entities
+    # as a group" (cast list / infobox / roster) from "source mentions
+    # them incidentally in scattered prose". Lives in policy so changing
+    # it bumps governance_policy_hash and invalidates cache cleanly.
+    "entity_policy": "proximity",
+    "entity_proximity_n": 3,
+    "entity_proximity_window": 300,
+    # Strip wikitext markup before the LLM ever sees the context. Lets
+    # Hermes quote prose verbatim and shrinks token bills (~43% on
+    # Wikipedia chunks). Bumps governance_policy_hash so prior cached
+    # answers under raw-wikitext policy stay distinct on lookup. No-op
+    # if mwparserfromhell isn't installed.
+    "base_version": _WIKITEXT_BASE_VERSION,
+    # Mechanical answer repair after first verify. Off by default so
+    # existing callers don't see answer text mutate. When on:
+    # synthetic_elision splits, trailing_artifact trims, and no_overlap
+    # claim drops are applied deterministically; the repaired answer is
+    # re-verified & persisted (cache_key inputs unchanged, only
+    # answer_text differs from what the LLM produced). One audit event
+    # `providence_repair` records the pre→post transition. Bumps
+    # governance_policy_hash so on/off agents share no cache silos.
+    "repair_enabled": False,
+    # Maximum re-prompt iterations after mechanical repair. 0 = no
+    # re-prompt (mechanical only). 1 = at most one extra LLM call
+    # asking the model to rewrite around the failed quotes.
+    "repair_max_reprompts": 0,
+    # G0 / CTI — claim-lattice-pointer answer mode. See
+    # aborist/qa/runner.py:DEFAULT_POLICY for full semantics. Default
+    # "quote" preserves existing behavior; "claim_lattice_pointer"
+    # instructs the runtime to build an evidence map, show short
+    # pointer ids (E1, E2, …) to the model, and accept pointer-line
+    # output ("Claim. [E12]") that the verifier maps back to
+    # content-addressed evidence_ids for the cache & run-DAG.
+    "answer_mode": DEFAULT_ANSWER_MODE,
+    "claim_lattice_system_prompt": CLAIM_LATTICE_SYSTEM_PROMPT,
+    "claim_lattice_grounding_reminder": CLAIM_LATTICE_GROUNDING_REMINDER,
+    # Reference-frame polarity preamble (Ticket #000002 / Module L).
+    # Injected as an additional user-role message before the
+    # grounding_reminder when `detect_frame` classifies the query as
+    # `reference` (allusion-shape query whose phrase route surfaced a
+    # fictional / reference-work source). The preamble nudges the
+    # model toward multi-frame answers — distinguish what the cited
+    # work depicts as actual continuity from what in-universe
+    # propaganda or characters claim. Pure prompt-side hint;
+    # verifier still runs the same hard checks. Empty string disables
+    # the augmentation. Folds into governance_policy_hash so two
+    # policies with different preamble text produce different
+    # cache_keys.
+    "claim_lattice_polarity_preamble": (
+        "This question may be a reference to {reference_title}. When "
+        "you answer, distinguish what the cited work depicts as "
+        "actual continuity from what in-universe propaganda or "
+        "characters claim within it. Cite evidence for each "
+        "substantive claim using the pointer format above."
+    ),
+    "claim_lattice_allowed_source_roles": [
+        "primary_answer_source",
+        "secondary_context_source",
+        "background_source",
+        "unclassified",
+        # Self-reference: STRICT-trusted-as-fact unless falsified.
+        # See docs/self-reference-design.md.
+        "self_reference_source",
+    ],
+    "claim_lattice_max_pointers_per_claim": 2,
+    # Cap on evidence blocks (chunks) per retrieved source. Default 2.
+    # Without this cap, a long Wikipedia article alone can split into
+    # ~20 chunks, each becoming a separate E* — the model then sees
+    # E1-E26 for what is really 5 sources and writes a mega-claim
+    # citing all of them. With the cap, 5 sources × 2 = 10 evidence
+    # blocks max. Chunks within each source are still relevance-ranked
+    # (distinct_query_tokens DESC, total_mentions DESC, chunk_idx ASC)
+    # so the cap keeps the most-relevant 2 chunks. Folds into
+    # governance_policy_hash; changing the cap invalidates prior
+    # cached records.
+    "claim_lattice_max_chunks_per_source": 2,
+    "claim_lattice_min_citation_coverage": 0.30,
+    "claim_lattice_min_claim_content_tokens": 2,
+    "claim_lattice_lazy_anchor_demote_threshold": 0.5,
+    "claim_lattice_lazy_anchor_demote_min_pairs": 3,
+    "claim_lattice_warrant_check_enabled": True,
+    # Deflection check: subject-anchor heuristic catches "model deflected
+    # to an adjacent grounded question" (e.g. "who burns the amazon
+    # river?" answered about rainforest deforestation, "river" never
+    # in answer). Promoted from sidecar to soft-demote 2026-05-02 —
+    # DEFLECTION_DETECTED downgrades EVIDENCE-WARRANTED → ANCHOR-
+    # WARRANTED via the existing soft-demote ladder path.
+    "claim_lattice_deflection_check_enabled": True,
+    "claim_lattice_format_collapse_check_enabled": True,
+    # Ticket #000008 Phase 2 — quantifier preflight guard. See
+    # aborist/qa/runner.py:DEFAULT_POLICY for the full rationale.
+    # Phase 2 lands with apply_caps=False (dry-run); cap is
+    # reported on result dict but not applied to the verifier.
+    "quantifier_guard_enabled": True,
+    "quantifier_guard_apply_caps": False,
+    # Mode allowlist when apply_caps flips True. See runner.DEFAULT_POLICY
+    # for the n=5 bench data driving the JSON-only default.
+    "quantifier_apply_caps_modes": ["claim_lattice"],
+    "quantifier_caps_by_intensity": {},
+    "quantifier_guard_modes": ["claim_lattice_pointer", "claim_lattice"],
+    # Phase 3 — default ON for lattice modes per the 2026-05-03 bench
+    # A/B (#000008 §12). See runner.DEFAULT_POLICY for full rationale.
+    "quantifier_reminder_enabled": True,
+    # Phase 4 — strict reject for broad-unbounded. See runner.py for
+    # rationale. Default OFF.
+    "quantifier_reject_broad": False,
+    # Ticket #000010 — see runner.DEFAULT_POLICY for rationale.
+    "metacognition_enabled": True,
+    "metacognition_temporal_check": True,
+    "metacognition_contradiction_check": True,
+    "metacognition_false_premise_check": True,
+    "metacognition_out_of_corpus_check": True,
+    "metacognition_block_on_contradiction": False,
+    # Ticket #000011 — soft preflight sidecar. See runner.DEFAULT_POLICY
+    # for full rationale. Default OFF.
+    "soft_preflight_enabled": False,
+    # Claim-count ceiling — see runner.DEFAULT_POLICY for rationale.
+    # Bench finding (york-england "tell me all there is to know")
+    # caught the runaway shape; cap of 12 admits entity-list
+    # questions while flagging encyclopedic spam. Folds into
+    # governance_policy_hash on change.
+    "claim_lattice_max_claims_per_answer": 12,
+    # JSON variant — `answer_mode="claim_lattice"`. Pairs with grammar-
+    # constrained inference (vLLM guided_json, Claude/GPT-4 native
+    # JSON, Qwen 3.6 reasoner). Lenient pre-parser keeps the path
+    # survivable on inference paths without grammar guidance. Toggling
+    # `claim_lattice_use_guided_json=False` disables the extra_body
+    # pass for endpoints that 400 on unknown fields.
+    "claim_lattice_json_system_prompt": CLAIM_LATTICE_JSON_SYSTEM_PROMPT,
+    "claim_lattice_json_grounding_reminder": CLAIM_LATTICE_JSON_GROUNDING_REMINDER,
+    "claim_lattice_use_guided_json": True,
+    "claim_lattice_json_stop_sequences": ["\n\n"],
+    # Per-mode context-budget defaults. Sprint 1b (2026-05-02) bench
+    # measured each answer mode's peak strict-rate bucket on a sweep
+    # over 8 KB → 1 MB context budgets. Previous flat default of
+    # 60 KB was past peak for both quote and pointer modes (which
+    # degrade after 32 KB) and only marginally above peak for the
+    # JSON variant (which keeps climbing into the 32-64 KB bucket).
+    # Defaults below are the mid of each mode's peak bucket rounded
+    # to nice numbers:
+    #   quote                  → 16-32KB peak  → 24000
+    #   claim_lattice_pointer  → 16-32KB peak  → 24000
+    #   claim_lattice (JSON)   → 32-64KB peak  → 48000
+    # Selected by `query()` when the caller does not pass an explicit
+    # `max_context_chars`. Any explicit caller value still wins
+    # (backward-compatible at the API boundary). The mapping itself
+    # lives in policy so changes fold into governance_policy_hash and
+    # partition the cache namespace cleanly. See
+    # docs/qa-modes-bench.md "recommended context budget".
+    "max_context_chars_by_mode": {
+        "quote": 24000,
+        "claim_lattice_pointer": 24000,
+        "claim_lattice": 48000,
+    },
+}
+
+
+@dataclass
+class _Hit:
+    document_root: str
+    document_uri: str
+    title: str | None
+    score: float
+    shard_path: str
+    chunk_idx: int
+    source_role: str = "unclassified"
+
+
+# Heuristic role classification + per-role budget multiplier. Lets the
+# primary answer page (e.g. `Jurassic Park (film)` for a JP film query)
+# claim a wider context slice than peripheral pages (`Jurassic Park (film
+# score)`, `Jurassic Park video games`). The running `char_budget` check
+# still bounds total context to `max_context_chars`; weights just shift
+# how the budget gets divided.
+SOURCE_ROLE_BUDGET_WEIGHTS = {
+    "primary_answer_source": 2.0,
+    "secondary_context_source": 1.0,
+    "noisy_background_source": 0.5,
+    "sequel_background_source": 0.5,
+    "background_source": 1.0,
+    "unclassified": 1.0,
+    # Self-promoted providence records (STRICT live, past kindergarten
+    # window). Same budget weight as background — Wikipedia stays the
+    # canonical primary; self-reference is supplementary anchoring.
+    # Trust model: STRICT-as-fact unless the verifier falsifies it.
+    "self_reference_source": 1.0,
+}
+
+# Title patterns that demote a source's role. Lower-cased substring match.
+# 2026-04-30: extended to catch tie-in spinoff titles. The JP-dinosaurs
+# query lazy-anchored on "Jurassic Park: Operation Genesis" (a video game)
+# whose enumerative dinosaur tables pattern-matched the question shape
+# more cleanly than the actual film article's prose. Adding the explicit
+# game subtitle plus generic markers ("the game", "video games") so
+# similar tie-ins classify as noisy and drop out of the evidence map.
+_NOISY_TITLE_MARKERS = (
+    "score", "music", "soundtrack", "video game", "video games",
+    "merchandise", "discography", "operation genesis", "the game",
+)
+_SEQUEL_TITLE_MARKERS = (
+    " iii", " ii)", " ii ", " iv", " v ", " v)", "lost world", "sequel",
+    " 2)", " 3)", " 4)",
+)
+_SECONDARY_TITLE_MARKERS = (
+    "list of", "characters", "franchise", "history of", "people",
+    "timeline of",
+)
+
+
+def _classify_source_role(
+    title: str | None,
+    qtokens_stem: set[str],
+    *,
+    document_uri: str | None = None,
+) -> str:
+    """Tag a source by its likely role for an N-token query.
+
+    URI-scheme classification fires first: documents whose URI starts
+    with ``aborist://providence/`` are self-promoted providence
+    records (per ``aborist/sources/providence.py``) and classify as
+    ``self_reference_source`` regardless of title shape — that role
+    captures the trust model "STRICT-as-fact unless verifier
+    falsifies."
+
+    Order matters for the title-based fallback: noisy/sequel/secondary
+    markers fire first because they catch peripheral pages whose
+    titles otherwise overlap query tokens fully (e.g. `Jurassic Park
+    (film score)` shares 3 stems with `{dinosaur, jurassic, park,
+    film}` but is not the primary answer source for a dinosaurs
+    question). Primary requires the strongest title coverage (N-1
+    of N stems present).
+    """
+    if document_uri and document_uri.startswith("aborist://providence/"):
+        return "self_reference_source"
+    if not title:
+        return "unclassified"
+    t = title.lower()
+    if any(k in t for k in _NOISY_TITLE_MARKERS):
+        return "noisy_background_source"
+    if any(k in t for k in _SEQUEL_TITLE_MARKERS):
+        return "sequel_background_source"
+    if any(k in t for k in _SECONDARY_TITLE_MARKERS):
+        return "secondary_context_source"
+    title_tokens = _title_query_tokens(t.replace("_", " "))
+    title_stems = {_stem_token_for_match(tok) for tok in title_tokens}
+    if qtokens_stem and len(title_stems & qtokens_stem) >= max(1, len(qtokens_stem) - 1):
+        return "primary_answer_source"
+    return "background_source"
+
+
+def _search_titles(conn, qtokens: list[str], limit: int) -> list[tuple]:
+    """SQL LIKE over documents.title — finds the HTTP article that FTS5
+    misses because list-pages with many URLs have higher 'http' term
+    frequency than the actual protocol article. Returns rows shaped
+    to match the FTS5 hit tuple.
+
+    Bug fix 2026-05-02 (fox case: ``"what date did back to the
+    future come out?"``): the previous SQL had no ``ORDER BY``, so
+    SQLite returned rows in arbitrary internal order and ``LIMIT``
+    truncated before the actual title-token-overlap winners landed.
+    The film article ``"Back to the Future"`` (title contains
+    ``back`` AND ``future``) lost the LIMIT race to substring-match
+    junk like ``"Out (poker)"`` (matches ``out`` substring),
+    ``"Aberdeen, South Dakota"`` (``south`` contains ``out``),
+    ``"Backplane"`` (``back`` substring), etc.
+
+    Fix: ``ORDER BY LENGTH(title) ASC`` (shorter titles win the
+    LIMIT race; title-purity proxy) and bump LIMIT to ``limit * 4``
+    so the post-filter (word-boundary stem-aware token-set
+    intersect) sees enough candidates to surface genuine matches
+    even on long-question OR'd LIKE queries.
+
+    The earlier 2026-05-02 v1 of this fix used a per-row
+    ``CASE WHEN ... THEN 1 ELSE 0 END + ...`` token-hit score in
+    SQL, which broke on long questions (fox 2026-05-02:
+    18-content-token query → SQLite "Expression tree is too large
+    (maximum depth 1000)" — each ``CASE WHEN`` is multiple
+    expression-tree nodes; ``+``-chained N times exceeded the
+    bound). The simplified shape is universal: short queries see
+    a tight LIMIT, long queries see ``limit * 4`` candidates the
+    caller's post-filter ranks via stem-aware token intersection.
+    Title-length-asc keeps the LIMIT race biased toward
+    title-pure matches.
+
+    Also: cap the OR-chain at MAX_TITLE_LIKE_TOKENS to bound the
+    expression-tree depth. Beyond ~24 tokens the post-filter is
+    doing all the work anyway; extra LIKEs just inflate the
+    candidate set without adding signal.
+    """
+    if not qtokens:
+        return []
+    over_fetch_limit = limit * 4
+
+    # Try FTS5 documents_fts first — O(K) hash lookup vs the un-indexable
+    # LOWER(title) LIKE '%tok%' that this function used through 2026-
+    # 05-02. The MATCH expression OR-joins the input tokens (quoted to
+    # neutralize FTS5 syntax). Empirical: ~0.05s/shard regardless of
+    # token count, vs. 10-15s for the LIKE form on the 870k-doc shard.
+    # Falls back to LIKE only on shards whose documents_fts isn't
+    # populated yet (e.g. legacy ingest before this index landed).
+    bounded = list(qtokens)[:24]
+    has_fts = conn.execute(
+        "SELECT 1 FROM documents_fts WHERE rowid = (SELECT MIN(rowid) FROM documents_fts) LIMIT 1"
+    ).fetchone()
+    if has_fts:
+        # Quote each token & OR-join. FTS5's tokenizer applies the same
+        # porter stemming we use elsewhere, so 'permacomputer' / 'permac'
+        # match coherently.
+        match_expr = " OR ".join(f'"{t.lower().replace(chr(34), chr(34) * 2)}"' for t in bounded)
+        try:
+            rows = conn.execute(
+                "SELECT d.document_root, d.document_uri, d.title "
+                "FROM documents_fts AS f "
+                "JOIN documents AS d ON d.rowid = f.rowid "
+                "WHERE documents_fts MATCH ? "
+                "ORDER BY LENGTH(d.title) ASC LIMIT ?",
+                (match_expr, over_fetch_limit),
+            ).fetchall()
+            return rows
+        except Exception:
+            # Malformed MATCH (rare; tokenizer-strange chars survived
+            # the quote escape). Fall through to LIKE form.
+            pass
+
+    # LIKE fallback — kept for shards lacking documents_fts data.
+    # Capped at 24 tokens so the OR-chain expression-tree stays under
+    # SQLite's depth-1000 limit on long queries.
+    clauses = " OR ".join(["LOWER(title) LIKE ?"] * len(bounded))
+    likes = [f"%{t.lower()}%" for t in bounded]
+    params = likes + [over_fetch_limit]
+    rows = conn.execute(
+        f"SELECT document_root, document_uri, title FROM documents "
+        f"WHERE {clauses} "
+        f"ORDER BY LENGTH(title) ASC LIMIT ?",
+        params,
+    ).fetchall()
+    return rows
+
+
+def _question_phrases(question: str, *, n: int = 4) -> list[str]:
+    """Extract verbatim n-token sliding-window phrases from the question.
+
+    Used by the phrase-pattern retrieval route to catch allusions /
+    idioms / fictional-world references whose diagnostic signal is
+    the EXACT sequence including function words. Stopword stripping
+    would kill this:
+
+        "always been at war"   — diagnostic Orwell signal
+        "always war"           — generic, useless
+
+    So we DON'T strip stopwords here. Skip phrases whose tokens are
+    all ≤ 3 chars (pure boilerplate, no diagnostic value). Output
+    is lowercase, deduped, in source order. Default ``n=4`` is the
+    sweet spot empirically: 3-grams are too noisy ("the cat in"
+    matches loads of things), 5-grams miss shorter idioms ("winter
+    is coming" → 3 tokens).
+    """
+    import re as _re
+    tokens = _re.findall(r"[A-Za-z][A-Za-z0-9]+", question)
+    if len(tokens) < n:
+        return []
+    out: list[str] = []
+    seen: set[str] = set()
+    for i in range(len(tokens) - n + 1):
+        window = tokens[i:i + n]
+        if max(len(t) for t in window) < 4:
+            continue  # all-short-tokens → boilerplate
+        phrase = " ".join(t.lower() for t in window)
+        if phrase in seen:
+            continue
+        seen.add(phrase)
+        out.append(phrase)
+    return out
+
+
+def _search_phrases(conn, phrases: list[str], limit: int) -> list[tuple]:
+    """FTS5 phrase-match search across chunk bodies.
+
+    Each phrase becomes an FTS5 quoted-phrase token (``'"phrase"'``);
+    we OR the phrases so any verbatim match wins. Returns sqlite3.Row
+    objects with columns ``document_root, idx, document_uri, title``
+    matching the rest of the search-route surface.
+
+    Why this exists: AND-mode FTS5 token-matching (the default body
+    search route) treats query tokens independently — a doc must
+    contain every token but the tokens can be anywhere. For
+    allusion-shape queries the diagnostic signal is the verbatim
+    sequence:
+
+        Q = "has oceania always been at war with east asia"
+        body BM25 surfaces literal-geography articles (Oceania, Asia,
+        Far East) because they have the most occurrences of "Oceania"
+        + "Asia" + "war" individually.
+        phrase MATCH '"always been at war"' surfaces
+        Nineteen_Eighty-Four because the phrase is verbatim Orwell.
+
+    The verbatim phrase route doesn't dominate: in ``_search_corpus``
+    its score is 70 (between core-keyword and title-LIKE ranks), and
+    the existing rerank pipeline still gates by title relevance.
+    Phrase matches just get a seat at the table.
+
+    Defensive: silently skip phrases containing double-quotes
+    (adversarial / malformed input). Wraps the FTS5 query in a
+    try/except so a malformed MATCH doesn't crash the search;
+    upstream callers see an empty result set.
+    """
+    if not phrases:
+        return []
+    quoted = [f'"{p}"' for p in phrases if '"' not in p]
+    if not quoted:
+        return []
+    fts_query = " OR ".join(quoted)
+    try:
+        rows = conn.execute(
+            """
+            SELECT
+                c.document_root,
+                c.idx,
+                d.document_uri,
+                d.title
+            FROM chunks_fts AS f
+            JOIN chunks    AS c ON c.chunk_id = f.rowid
+            JOIN documents AS d ON d.document_root = c.document_root
+            WHERE chunks_fts MATCH ?
+            ORDER BY bm25(chunks_fts) ASC
+            LIMIT ?
+            """,
+            (fts_query, limit),
+        ).fetchall()
+    except Exception:  # noqa: BLE001 — search must fail soft
+        rows = []
+    return rows
+
+
+def _docs_with_core_keyword_match(
+    conn, qtokens: list[str], limit: int
+) -> list[tuple]:
+    """Find SOURCE docs whose TF-IDF core keywords contain a query token.
+
+    TF-IDF cores act as enriched titles: a doc's distinctive low-frequency
+    terms get distilled into the core's content as comma-separated keywords.
+    A query for "permacomputer" (a neologism that never makes it into a
+    title) can match the TF-IDF core of a Grok conversation that mentioned
+    it, because permacomputer is a rare term that ranks high under TF-IDF.
+
+    Returns rows of (document_root, document_uri, title) for the SOURCE docs
+    (not the cores) — the source is what gets fed to the LLM as context.
+    """
+    if not qtokens:
+        return []
+    # Word-boundary match against the comma-separated TF-IDF keyword list.
+    # Prepending/appending ", " lets one LIKE pattern (`%, token, %`) check
+    # for the token regardless of its position in the keyword string.
+    # Without this, naive `LIKE '%intel%'` would match "intelligence",
+    # "intellectual", "intellivision" — drowning real hits like Pentium_4
+    # (whose TF-IDF core has "intel" as an exact keyword) in noise.
+    #
+    # Per-row `match_count` tallies how many distinct query tokens hit
+    # this doc's TF-IDF core. Multi-token coverage is a strong relevance
+    # signal — a doc whose core has "intel" + "cpu" + "faster" beats a
+    # doc whose only signal is "intel" appearing in its TITLE. The
+    # caller boosts the score by match_count.
+    case_clauses = " + ".join(
+        [
+            "(CASE WHEN LOWER(', ' || c.content || ', ') LIKE ? THEN 1 ELSE 0 END)"
+        ]
+        * len(qtokens)
+    )
+    where_clauses = " OR ".join(
+        ["LOWER(', ' || c.content || ', ') LIKE ?"] * len(qtokens)
+    )
+    patterns = [f"%, {t.lower()}, %" for t in qtokens]
+    params = patterns + patterns + [limit]
+    rows = conn.execute(
+        f"""
+        SELECT
+            src.document_root,
+            src.document_uri,
+            src.title,
+            MAX({case_clauses}) AS match_count
+        FROM chunks c
+        JOIN documents core ON core.document_root = c.document_root
+        JOIN derivations der ON der.core_root = core.document_root
+        JOIN documents src ON src.document_root = der.src_root
+        WHERE core.source_type LIKE 'core:tfidf-%'
+          AND ({where_clauses})
+        GROUP BY src.document_root, src.document_uri, src.title
+        ORDER BY match_count DESC
+        LIMIT ?
+        """,
+        params,
+    ).fetchall()
+    return rows
+
+
+def _stem_token_for_match(t: str) -> str:
+    """Light suffix-strip for query-token vs body matching.
+
+    Two normalizations:
+        possessive  ``"superman's" -> "supermans" -> "superman"`` (the apostrophe
+                    is already gone via _TITLE_TOKEN_RE; we drop the trailing
+                    ``s`` here so the lookup matches plain ``superman`` in body).
+        plural      ``"powers" -> "power"``, ``"girlfriends" -> "girlfriend"``
+                    so plural questions match singular source mentions.
+
+    Both are the same operation: strip trailing ``s`` for tokens > 4 chars.
+    Conservative on short tokens (``"is"``, ``"as"``, ``"us"`` would lose
+    meaning) and on tokens that don't end in ``s`` (no-op).
+    """
+    if len(t) > 4 and t.endswith("s") and not t.endswith("ss"):
+        return t[:-1]
+    return t
+
+
+def _body_count_with_stem(body: str, t: str) -> int:
+    """Count mentions of ``t`` in ``body``, falling back to the lite-stemmed
+    form if the literal didn't match. Returns the LARGER of the two counts
+    so a query token that appears under both forms (rare) still scores."""
+    n_literal = body.count(t)
+    if n_literal:
+        return n_literal
+    stem = _stem_token_for_match(t)
+    if stem != t:
+        return body.count(stem)
+    return 0
+
+
+def _chunk_query_relevance(
+    span: str, qtokens_stem: set[str]
+) -> tuple[int, int]:
+    """Rank one chunk by query-token overlap. Returns
+    ``(distinct_present, total_mentions)``.
+
+    Stem-aware: same ``_body_count_with_stem`` we use elsewhere, so
+    ``"supermans"`` matches ``"superman"`` in the chunk text. Soft
+    signal — the score never enters the proof path; it only orders
+    chunks within a source so the most-relevant chunk gets the lowest
+    pointer id (and the model's lazy-anchor habit lands on a useful
+    chunk by accident).
+
+    Sort callers should walk ``(-distinct, -total, chunk_idx_asc)``
+    to break ties stably toward document order.
+    """
+    if not qtokens_stem:
+        return (0, 0)
+    body = span.lower()
+    counts = {t: _body_count_with_stem(body, t) for t in qtokens_stem}
+    distinct_present = sum(1 for n in counts.values() if n > 0)
+    total = sum(counts.values())
+    return (distinct_present, total)
+
+
+def _body_density_passes(
+    conn, document_root: str, qtokens: set[str], min_mentions: int = 3
+) -> bool:
+    """Body-token CO-OCCURRENCE relevance.
+
+    Pre-2026-04-27 this counted any token's mentions in the body (so
+    Intel_8086, with 30 "Intel" mentions, would pass for a query of
+    {intel, fastest, cpu} despite never mentioning "fastest"). Pre-2026-
+    04-29 the threshold was "at least HALF" — too lenient for 2-token
+    queries: ``"supermans girlfriend"`` admitted ``Girlfriends`` (TV
+    show) which had ``girlfriend`` in body but no ``superman`` whatsoever.
+
+    Current rules — breadth scales with query length:
+
+        ≤ 2 tokens   require ALL of them present in body
+        3+ tokens    require N - 1 (allow one weak signal token to miss)
+
+    Plus depth (``total_mentions >= min_mentions``) is still enforced.
+
+    Token matching is stem-tolerant (``_stem_token_for_match``): so a query
+    token ``"supermans"`` matches body ``"superman"`` and ``"girlfriends"``
+    matches body ``"girlfriend"``.
+    """
+    if not qtokens:
+        return False
+    rows = conn.execute(
+        "SELECT content FROM chunks WHERE document_root = ? AND content IS NOT NULL",
+        (document_root,),
+    ).fetchall()
+    if not rows:
+        return False
+    body = " ".join(unpack_chunk(r["content"]) or "" for r in rows).lower()
+    counts = {t: _body_count_with_stem(body, t.lower()) for t in qtokens}
+    distinct_present = sum(1 for n in counts.values() if n > 0)
+    total_mentions = sum(counts.values())
+    if len(qtokens) <= 2:
+        breadth_threshold = len(qtokens)
+    else:
+        breadth_threshold = len(qtokens) - 1
+    return distinct_present >= breadth_threshold and total_mentions >= min_mentions
+
+
+def _search_corpus(
+    shards_dir: Path | None,
+    single_db: Path | None,
+    question: str,
+    over_fetch: int,
+) -> list[_Hit]:
+    """Two parallel searches across shards, merged:
+
+    - FTS5 body search (BM25 over chunk content).
+    - SQL title-LIKE search (catches articles whose body is short on the
+      query terms but whose title is the literal topic — e.g., the HTTP
+      protocol article doesn't out-frequency-score URL-heavy list pages
+      but it IS the topic).
+
+    Dedupe by document_root. Title hits get a baseline score that
+    out-ranks FTS5 body hits so the actual topic article rises to the top.
+    """
+    qtokens = _title_query_tokens(question)
+    # Title-LIKE backup uses ORIGINAL qtokens only (LIKE %tok% can't
+    # use any index — adding synonyms makes it O(corpus × |accept|)).
+    # Synonym expansion stays useful in two places: (1) the FTS5
+    # OR-mode fallback (top-5 longest pool merged with synonyms — long
+    # topical synonyms like "neurotechnology" surface relevant titles
+    # without paying for full-scan), and (2) `_filter_by_title_relevance`
+    # post-retrieval filtering (in-memory, cheap).
+    accept_tokens = set(qtokens)
+    or_synonym_pool = synonym_expand(qtokens, shards_dir=shards_dir)
+    paths: list[Path]
+    if shards_dir is not None:
+        paths = discover_shards(shards_dir)
+    elif single_db is not None:
+        paths = [Path(single_db)]
+    else:
+        paths = []
+
+    raw: list[tuple] = []
+    # Roots whose TF-IDF cores contain a query token — collected across
+    # shards. Used downstream by _filter_by_title_relevance as accept-path 2.
+    core_match_roots: set[str] = set()
+    # Roots that matched a verbatim 4+ token phrase from the question.
+    # Used downstream by _filter_by_title_relevance as accept-path 4 so
+    # an allusion-shape hit (e.g. Nineteen_Eighty-Four for "always been
+    # at war") survives the title-token-overlap filter even when its
+    # title shares no tokens with the question.
+    phrase_match_roots: set[str] = set()
+    # Per-shard mapping of doc root -> shard path, for body-density lookups
+    # in accept-path 3. Lets us reach back to the source shard cheaply.
+    root_to_shard: dict[str, str] = {}
+
+    for p in paths:
+        conn = connect(p)
+        try:
+            backend = FTS5Backend(conn)
+            for h in backend.search(
+                question, limit=over_fetch, extra_or_tokens=or_synonym_pool
+            ):
+                raw.append(
+                    (
+                        h.score,
+                        h.document_root,
+                        h.document_uri,
+                        h.title,
+                        h.chunk_idx,
+                        str(p.resolve()),
+                    )
+                )
+                root_to_shard[h.document_root] = str(p.resolve())
+            # Parallel title search using synonym-expanded tokens.
+            # The score starts deliberately low so this signal can't drown
+            # FTS5 BM25 + body relevance. _rerank_by_title later adds
+            # `overlap*10` to every hit (FTS5 and title-search alike) that
+            # has title-token overlap, so a doc whose title genuinely IS
+            # the topic ends up rewarded twice (once here, once in rerank).
+            # Single-token title matches against generic terms ("intel",
+            # "cpu") used to score 60+ standalone, dominating top-K with
+            # legacy 80486-era articles for queries like "fastest intel
+            # CPU?". Now that contribution is the same scale as FTS5 body
+            # BM25, which lets Pentium_4 (high body relevance, no title
+            # overlap) win on its actual topical fit.
+            # Word-boundary overlap check (was substring-match,
+            # which falsely passed `"out" in "south"`,
+            # `"date" in "candidate"`, `"come" in "outcome"`, etc.).
+            # 2026-05-02 case fox surfaced: "what date did back to
+            # the future come out?" — the substring check admitted
+            # "Aberdeen, South Dakota" (south contains "out"),
+            # "Backplane" (back), "Outline of biology" (out), and
+            # consumed the over_fetch budget so the legitimate
+            # `Back to the Future` film article never made the
+            # rerank cut. Tokenizing the title via
+            # `_title_query_tokens` + stem-aware comparison keeps
+            # the title-LIKE pass returning only docs whose title
+            # has an actual matching word.
+            accept_stems = {
+                _stem_token_for_match(t) for t in accept_tokens
+            }
+            # Title search now uses documents_fts FTS5 index (~0.05s/shard
+            # regardless of token count) — the prior >5-token bypass
+            # existed because LIKE '%tok%' was O(corpus × |tokens|).
+            # FTS5 MATCH makes this an O(K) hash lookup, so synonym-
+            # expanded title search is affordable at any query length.
+            title_search_rows = _search_titles(
+                conn, list(accept_tokens), over_fetch
+            )
+            for r in title_search_rows:
+                title_norm = (r["title"] or "").replace("_", " ")
+                title_stems = {
+                    _stem_token_for_match(t)
+                    for t in _title_query_tokens(title_norm)
+                }
+                overlap = len(accept_stems & title_stems)
+                if overlap == 0:
+                    continue
+                title_score = overlap * 10.0
+                raw.append(
+                    (
+                        title_score,
+                        r["document_root"],
+                        r["document_uri"],
+                        r["title"],
+                        0,
+                        str(p.resolve()),
+                    )
+                )
+                root_to_shard[r["document_root"]] = str(p.resolve())
+            # Phrase-pattern search — verbatim multi-token sequences
+            # from the question. Catches allusions / idioms / fictional-
+            # world references whose diagnostic signal is the exact
+            # sequence including function words. Two passes for layered
+            # specificity:
+            #   - n=6 (highest specificity): "oceania always been at
+            #     war with" is essentially unique to Orwell. Score 100.
+            #   - n=5 (high specificity): "oceania always been at war"
+            #     still strongly Orwell-anchored. Score 90.
+            # 4-grams were tried (2026-05-01) and dropped: "always been
+            # at war" matches generic war-history articles too often,
+            # creating retrieval noise that the rerank pipeline can't
+            # cleanly separate from the actual allusion. Empirically
+            # 5+ grams trade recall for precision — most allusions
+            # ("may the force be with you", "to be or not to be",
+            # "winter is coming") survive at length 5 or 3-with-light-
+            # tokens, but the 4-gram floor is where diagnostic-ness
+            # collapses.
+            for n in (6, 5):
+                phrase_score = 100.0 if n == 6 else 90.0
+                for r in _search_phrases(
+                    conn, _question_phrases(question, n=n), over_fetch
+                ):
+                    raw.append(
+                        (
+                            phrase_score,
+                            r["document_root"],
+                            r["document_uri"],
+                            r["title"],
+                            r["idx"],
+                            str(p.resolve()),
+                        )
+                    )
+                    root_to_shard[r["document_root"]] = str(p.resolve())
+                    phrase_match_roots.add(r["document_root"])
+            # Core-keyword search: docs whose TF-IDF core keywords match.
+            # The query token doesn't need to be in title or even in body —
+            # being a TF-IDF keyword of the doc's core is enough signal.
+            for r in _docs_with_core_keyword_match(
+                conn, list(accept_tokens), over_fetch
+            ):
+                core_match_roots.add(r["document_root"])
+                # Score scales with how many query tokens hit this doc's
+                # TF-IDF core. A 3-token coverage (e.g. Pentium_4's core
+                # carries "intel", "cpu", "faster" for the query "fastest
+                # intel CPU?") beats single-token title boosts (~80) that
+                # otherwise saturate the top with Intel_80486DX,
+                # Intel_8086, etc. — articles that share *one* word with
+                # the query but aren't the topical answer.
+                match_count = r["match_count"] or 1
+                kw_score = 40.0 + 25.0 * match_count
+                raw.append(
+                    (
+                        kw_score,
+                        r["document_root"],
+                        r["document_uri"],
+                        r["title"],
+                        0,
+                        str(p.resolve()),
+                    )
+                )
+                root_to_shard[r["document_root"]] = str(p.resolve())
+        finally:
+            conn.close()
+
+    raw.sort(key=lambda r: -r[0])
+    seen: set[str] = set()
+    out: list[_Hit] = []
+    for score, root, uri, title, idx, sp in raw:
+        if root in seen:
+            continue
+        seen.add(root)
+        out.append(
+            _Hit(
+                document_root=root,
+                document_uri=uri,
+                title=title,
+                score=score,
+                shard_path=sp,
+                chunk_idx=idx,
+            )
+        )
+    # Sidecar sets returned alongside the hit list. Pre-2026-05-01
+    # the function returned a bare list and the caller used
+    # `getattr(hits, "_core_match_roots", set())` to fish out the
+    # sets — but the sidecar was never attached, so the
+    # `core_match_roots` accept-path in _filter_by_title_relevance
+    # silently received an empty set. Returning a tuple corrects
+    # the plumbing AND threads the new `phrase_match_roots` for
+    # accept-path 4.
+    return out, core_match_roots, phrase_match_roots, root_to_shard
+
+
+def _rerank(
+    hits: list[_Hit],
+    question: str,
+    *,
+    core_match_roots: set[str] | None = None,
+    body_density_check: callable | None = None,
+    phrase_match_roots: set[str] | None = None,
+    hyphen_fold_anchors: set[str] | None = None,
+    shards_dir=None,
+) -> list[_Hit]:
+    """Filter off-topic, then layer in body-coverage, title-overlap, and
+    source-role rank boosts.
+
+    Order matters: filter first (drops noise), body-coverage rerank next
+    (counters BM25's short-doc bias by rewarding topical density across
+    distinct query tokens), title-overlap rerank (breaks ties when a doc
+    IS the named topic), source-role rank-boost last so a primary
+    answer source outranks a list-page even when the list-page won on
+    BM25 + title-overlap (caught the "where is florida" defect:
+    ``List_of_places_in_Florida`` and ``List_of_State_Roads_in_Florida``
+    each contain "Florida" hundreds of times in row markup, scoring
+    above the actual ``Florida`` article on body density).
+    """
+    hits = _filter_by_title_relevance(
+        hits,
+        question,
+        core_match_roots=core_match_roots,
+        body_density_check=body_density_check,
+        phrase_match_roots=phrase_match_roots,
+        hyphen_fold_anchors=hyphen_fold_anchors,
+        shards_dir=shards_dir,
+    )
+    hits = _rerank_by_body_coverage(hits, question)
+    hits = _rerank_by_title(hits, question)
+    hits = _rerank_by_source_role(hits, question)
+    hits = _rerank_by_title_purity(hits, question)
+    return _rerank_by_ordered_token_match(hits, question)
+
+
+# Per-role rank multiplier. Affects sort order, NOT just per-source
+# context cap (the latter is SOURCE_ROLE_BUDGET_WEIGHTS, applied later).
+# Defaults skew strongly toward primary so a real topic article beats
+# list-pages and franchise/sequel siblings even when the list-page wins
+# on body-density. Tuned against the JP-dinosaurs and "where is florida"
+# defects.
+SOURCE_ROLE_RANK_WEIGHTS = {
+    "primary_answer_source": 2.0,
+    "secondary_context_source": 0.7,
+    "background_source": 0.9,
+    "noisy_background_source": 0.3,
+    "sequel_background_source": 0.3,
+    "unclassified": 1.0,
+    # Self-reference: STRICT live providence records past kindergarten
+    # window. Treated like background — Wikipedia stays canonical
+    # primary; self-reference is supplementary anchoring trusted as
+    # fact unless the verifier falsifies the underlying record.
+    "self_reference_source": 0.9,
+}
+
+
+def _rerank_by_source_role(hits: list[_Hit], question: str) -> list[_Hit]:
+    """Classify each hit by source role and rescale score by role weight.
+
+    Mutates ``h.source_role`` so the classification happens once and
+    downstream context-build code can reuse the value (instead of
+    re-classifying at cap time). Stable sort by score desc.
+    """
+    qtokens_stem = {
+        _stem_token_for_match(t.lower())
+        for t in _title_query_tokens(question)
+    }
+    for h in hits:
+        h.source_role = _classify_source_role(
+            h.title, qtokens_stem, document_uri=h.document_uri
+        )
+        weight = SOURCE_ROLE_RANK_WEIGHTS.get(h.source_role, 1.0)
+        h.score = h.score * weight
+    hits.sort(key=lambda h: -h.score)
+    return hits
+
+
+def _rerank_by_title_purity(hits: list[_Hit], question: str) -> list[_Hit]:
+    """Boost titles by both purity AND multi-token-match breadth.
+
+    Two signals combine here:
+
+    - **Purity** = ``|title_tokens ∩ query_tokens| / |title_tokens|``.
+      Rewards titles that ARE the topic without off-topic suffix tokens.
+      ``Jurassic Park (film)`` (purity 1.0) beats ``Jurassic Park
+      (NES game)`` (purity 0.5).
+    - **Overlap count** = ``|title_tokens ∩ query_tokens|``. Rewards
+      titles that match more of the query's content tokens. For a
+      query ``{dawson, creek}``: ``List of Dawson's Creek episodes``
+      (overlap 2) beats ``Clinton Creek, Yukon`` (overlap 1) even
+      when both have similar purity.
+
+    Multiplier: ``(1 + overlap_count) * (1 + purity)``:
+
+        overlap=2, purity=0.5 (e.g. ``Dawson's Creek episodes``)  → 4.5×
+        overlap=1, purity=1.0 (bare-token-title match)            → 4.0×
+        overlap=2, purity=0.4 (e.g. ``List of ... Dawson Creek``) → 4.2×
+        overlap=1, purity=0.5 (e.g. ``Dawson Leery``)             → 3.0×
+        overlap=1, purity=0.33 (e.g. ``Clinton Creek, Yukon``)    → 2.67×
+        overlap=0                                                 → 1.0× (no change)
+
+    Pre-2026-05-01 the multiplier was ``1 + 2 * purity`` — purity
+    only, indifferent to overlap-count. That let ``Clinton Creek,
+    Yukon`` (purity 0.33 → 1.67× boost) outrank ``List of Dawson's
+    Creek episodes`` (purity 0.5 → 2.0×) on a query like "in
+    dawsons creek who is the girl across the creek?" once BM25's
+    short-title bias is folded in. The 2-token-match should beat
+    the 1-token-match cleanly.
+
+    Original use case (JP-dinosaurs lazy-anchor) still served:
+    ``Jurassic Park (film)`` (overlap 2, purity 1.0) → 6.0× sits
+    well above ``Jurassic Park (NES game)`` (overlap 2, purity 0.5)
+    → 4.5×, and far above ``Jurassic Park (franchise)`` (overlap 2,
+    purity 0.67) → 5.0×.
+    """
+    qtokens = _title_query_tokens(question)
+    if not qtokens:
+        return hits
+    # Stem-aware matching so possessive / plural variants match. The
+    # 2026-05-01 Dawson's Creek defect: question "dawsons creek" with
+    # title "List of Dawson's Creek episodes" — raw set intersection
+    # treated `dawsons` and `dawson` as distinct → overlap=1 (only
+    # `creek`) and the multi-token title bonus didn't fire. Stemming
+    # both sides via `_stem_token_for_match` (trailing-s strip on
+    # tokens >4 chars, skipping ss-enders) collapses both forms onto
+    # `dawson`, the overlap goes to 2, and the title beats single-
+    # token ``Clinton Creek, Yukon`` matches.
+    qstems = {_stem_token_for_match(t) for t in qtokens}
+    for h in hits:
+        if not h.title:
+            continue
+        ttokens = _title_query_tokens(h.title.replace("_", " "))
+        if not ttokens:
+            continue
+        tstems = {_stem_token_for_match(t) for t in ttokens}
+        overlap = tstems & qstems
+        if not overlap:
+            continue
+        purity = len(overlap) / len(tstems)
+        overlap_count = len(overlap)
+        h.score = h.score * (1.0 + overlap_count) * (1.0 + purity)
+    hits.sort(key=lambda h: -h.score)
+    return hits
+
+
+def _ordered_match_length(query_tokens: list[str], title_tokens: list[str]) -> int:
+    """Longest contiguous-or-subsequence match of query tokens (in
+    query order) inside title tokens (in title order).
+
+    Implementation: longest common subsequence over the two stem-
+    aware token lists. Returns the LCS length. The function is
+    O(N*M) where N = len(query_tokens), M = len(title_tokens). Both
+    are typically <10 in practice (titles short, query content
+    tokens few), so the cost is negligible.
+
+    Examples (query "red fish blue fish"):
+        title "Red Fish Blue Fish"          → 4 (all four in order)
+        title "One Fish Two Fish Red Fish"  → 4 (red-fish-blue? — no
+                                                 'blue' in title, so 3
+                                                 actually: red-fish-fish...
+                                                 LCS counts longest common
+                                                 SUBSEQUENCE not contiguous)
+        title "Red Dwarf"                   → 1 (red only)
+        title "Toronto Blue Jays"           → 1 (blue only)
+        title "Blue Velvet (film)"          → 1 (blue only)
+    """
+    if not query_tokens or not title_tokens:
+        return 0
+    n = len(query_tokens)
+    m = len(title_tokens)
+    # 1D rolling dp
+    prev = [0] * (m + 1)
+    for i in range(1, n + 1):
+        cur = [0] * (m + 1)
+        for j in range(1, m + 1):
+            if query_tokens[i - 1] == title_tokens[j - 1]:
+                cur[j] = prev[j - 1] + 1
+            else:
+                cur[j] = max(cur[j - 1], prev[j])
+        prev = cur
+    return prev[m]
+
+
+def _rerank_by_ordered_token_match(hits: list[_Hit], question: str) -> list[_Hit]:
+    """Boost titles whose tokens appear in the same order as the query.
+
+    Multi-token queries like "red fish blue fish" should rank a
+    "Red Fish Blue Fish"-shaped title above a "Red Dwarf"-shaped
+    one, even when both pass the existing title-purity check. The
+    ordered-token-match length distinguishes them: 4 vs 1.
+
+    Multiplier: ``1 + 0.5 * (match_length - 1)`` for match_length ≥ 2.
+    Single-token matches get no boost (already covered by purity).
+
+        match_length 1 → 1.0× (no change; single-token rewarded by purity)
+        match_length 2 → 1.5×
+        match_length 3 → 2.0×
+        match_length 4 → 2.5×
+
+    Stem-aware (uses ``_stem_token_for_match``) so possessive /
+    plural / "dawsons" vs "dawson" variants collapse onto the same
+    stem before LCS.
+
+    Caught the 2026-05-01 "plot of red fish blue fish?" defect:
+    pre-fix, body BM25 + title purity tied across multiple
+    color/animal-titled docs; with the ordered-match boost, the
+    Dr. Seuss book's title (purity 1.0, ordered-match 4) sits
+    cleanly above Red Dwarf, Toronto Blue Jays, etc. (purity 0.5,
+    ordered-match 1).
+    """
+    qtokens = _title_query_tokens(question)
+    if len(qtokens) < 2:
+        # No order to match on a single-token query.
+        return hits
+    # Preserve query token ORDER (not the set ordering from
+    # _title_query_tokens which de-dupes via set comprehension).
+    # Walk the question text, applying the same regex + filter, so
+    # the resulting list reflects natural reading order.
+    qtokens_ordered: list[str] = []
+    seen: set[str] = set()
+    for tok in _TITLE_TOKEN_RE.findall(question):
+        t = tok.lower()
+        if (
+            t in _TITLE_STOPWORDS
+            or len(t) <= 1
+            or t in seen
+        ):
+            continue
+        seen.add(t)
+        qtokens_ordered.append(_stem_token_for_match(t))
+    if len(qtokens_ordered) < 2:
+        return hits
+    for h in hits:
+        if not h.title:
+            continue
+        # Title tokens in TITLE order, deduped on first occurrence.
+        ttokens_ordered: list[str] = []
+        title_seen: set[str] = set()
+        for tok in _TITLE_TOKEN_RE.findall(h.title.replace("_", " ")):
+            t = tok.lower()
+            if (
+                t in _TITLE_STOPWORDS
+                or len(t) <= 1
+                or t in title_seen
+            ):
+                continue
+            title_seen.add(t)
+            ttokens_ordered.append(_stem_token_for_match(t))
+        if not ttokens_ordered:
+            continue
+        match_len = _ordered_match_length(qtokens_ordered, ttokens_ordered)
+        if match_len >= 2:
+            h.score = h.score * (1.0 + 0.5 * (match_len - 1))
+    hits.sort(key=lambda h: -h.score)
+    return hits
+
+
+def _rerank_by_body_coverage(
+    hits: list,
+    question: str,
+    *,
+    weight: float = 0.6,
+) -> list:
+    """Boost score by per-token body coverage to counteract BM25's short-doc bias.
+
+    BM25 normalizes by document length, but its `b` parameter under-penalizes
+    *very* short docs that happen to mention every query token. Result: a
+    1-paragraph stub on Intel 4040 (1974 microcontroller) outscored a 30-page
+    Intel Core i7 article for "what is the fastest intel CPU?".
+
+    Approach: for each hit's full body, sum sqrt(count) per query token.
+    Sqrt scaling lets long topical articles meaningfully out-score short
+    tangential ones without runaway domination by enumerative list pages.
+
+      stub article: 5 intel + 1 fastest + 4 cpu  ->  sqrt(5)+sqrt(1)+sqrt(4) ~  5.2
+      long topical: 200 + 10 + 80               ->  sqrt(200)+sqrt(10)+sqrt(80) ~  26.2
+      enumeration: 1000 + 50 + 300              ->  sqrt(1000)+sqrt(50)+sqrt(300) ~  55.8
+
+    Multiply by `weight` (default 0.6) and add to the existing score. The
+    differentiation in the example above is decisive but bounded: long topical
+    articles get +15-16, enumerations get +33, stubs get +3. Combined with
+    FTS5 base scores in the 40s, the long topical article wins comfortably.
+
+    Cost: one body fetch per surviving candidate (typically 24-32). Bounded.
+    """
+    import math
+
+    qtokens_lower = {t.lower() for t in _title_query_tokens(question)}
+    if not qtokens_lower:
+        return hits
+    for h in hits:
+        body = _load_doc_text(h.shard_path, h.document_root)
+        if body is None:
+            continue
+        body_lower = body.lower()
+        coverage = sum(
+            math.sqrt(body_lower.count(t)) for t in qtokens_lower
+        )
+        h.score += coverage * weight
+    hits.sort(key=lambda h: -h.score)
+    return hits
+
+
+def _load_doc_text(shard_path: str, document_root: str) -> str | None:
+    """Concatenate all hot chunks of a document. Returns None if cold or missing."""
+    conn = connect(shard_path)
+    try:
+        rows = conn.execute(
+            "SELECT content FROM chunks "
+            "WHERE document_root = ? AND content IS NOT NULL "
+            "ORDER BY idx ASC",
+            (document_root,),
+        ).fetchall()
+    finally:
+        conn.close()
+    if not rows:
+        return None
+    return "\n\n".join(unpack_chunk(r["content"]) or "" for r in rows)
+
+
+def _load_doc_chunks(
+    shard_path: str, document_root: str
+) -> list[tuple[int, str, str]] | None:
+    """Per-chunk hot rows of a document.
+
+    Returns ``[(chunk_idx, leaf_hash, span), ...]`` in chunk order, or
+    ``None`` if the document is cold or absent. Cold individual chunks
+    are skipped (the WHERE clause filters NULL content). Used by the
+    claim-lattice-pointer evidence-map builder to emit one
+    ``EvidenceObject`` per chunk so the model can cite the specific
+    paragraph that supports a claim instead of lazy-anchoring the
+    whole article.
+    """
+    conn = connect(shard_path)
+    try:
+        rows = conn.execute(
+            "SELECT idx, leaf_hash, content FROM chunks "
+            "WHERE document_root = ? AND content IS NOT NULL "
+            "ORDER BY idx ASC",
+            (document_root,),
+        ).fetchall()
+    finally:
+        conn.close()
+    if not rows:
+        return None
+    out: list[tuple[int, str, str]] = []
+    for r in rows:
+        span = unpack_chunk(r["content"]) or ""
+        if not span:
+            continue
+        out.append((r["idx"], r["leaf_hash"], span))
+    return out or None
+
+
+def _extract_preflight_hash_from_blob(blob: str | None) -> str | None:
+    """Pull the ``preflight`` stage hash out of a persisted
+    ``run_dag_blob`` (Ticket #000009 §7.2). Returns ``None`` when
+    the blob is absent / unparseable / lacks a preflight stage —
+    legacy rows written before #000009 fall through this path
+    cleanly without raising.
+    """
+    if not blob:
+        return None
+    try:
+        parsed = json.loads(blob) if isinstance(blob, str) else blob
+    except (json.JSONDecodeError, TypeError):
+        return None
+    if not isinstance(parsed, dict):
+        return None
+    for node in parsed.get("nodes") or []:
+        if isinstance(node, dict) and node.get("stage") == "preflight":
+            return node.get("hash")
+    return None
+
+
+def _context_root(source_roots: list[str]) -> str:
+    """Merkle root over sorted source document_roots — the v9.8 'source' dim
+    for multi-source answers. Sorting makes the root deterministic regardless
+    of search ranking order."""
+    if not source_roots:
+        return "00" * 32
+    sorted_roots = sorted(source_roots)
+    if len(sorted_roots) == 1:
+        return sorted_roots[0]
+    leaves = [bytes.fromhex(r) for r in sorted_roots]
+    return MerkleTree.build(leaves).root.hex()
+
+
+
+[docs] +def query( + *, + question: str, + qa_db: Path, + chat_client: ChatClient, + model_id: str, + revision: str = "", + quantization: str = "", + shards_dir: Path | None = None, + single_db: Path | None = None, + top_k: int = 8, + over_fetch: int = 32, + max_context_chars: int | None = None, + policy: dict | None = None, + chain: str = "private", + fidelity: str | None = None, + burn_existing: bool = False, + retrieval_keywords: str | None = None, +) -> dict: + """Answer `question` using the corpus. Cache to qa_db. Returns a result dict. + + `fidelity` controls lookup tolerance — see ``FIDELITY_MODES`` in + ``aborist.qa.keys``. ``"strict"`` checks only the cache_key + matching this call's ``policy["question_dedup"]``. ``"equivalence_class"`` + (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 ``lookup_path`` + naming which key matched (or ``"miss"`` when the LLM ran). + + `burn_existing=True` 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 ``providence_burn`` + audit event. Test-ergonomic: run `make query Q=... BURN=1` after + tweaking a knob to see the new behavior without finding cache_keys + by hand. Result includes ``burned_existing`` 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). + + `retrieval_keywords` 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 person's 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. + + Keywords do NOT enter ``question_hash`` directly, but they DO + change which sources get chosen — and that re-routes the + ``context_root`` and ``conversation_hash`` components of + ``cache_key``. Two calls with the same question and different + keywords therefore land under different cache_keys (different + contexts, different cached records — correctly so). Pair with + ``burn_existing=True`` to force fresh inference when iterating + on keyword sets. + """ + policy = policy or DEFAULT_QUERY_POLICY + if fidelity is None: + fidelity = policy.get("fidelity", DEFAULT_FIDELITY) + if fidelity not in FIDELITY_MODES: + raise ValueError( + f"fidelity must be one of {FIDELITY_MODES}, got {fidelity!r}" + ) + answer_mode = policy.get("answer_mode", DEFAULT_ANSWER_MODE) + if answer_mode not in ANSWER_MODES: + raise ValueError( + f"policy['answer_mode'] must be one of {ANSWER_MODES}, got {answer_mode!r}" + ) + # Resolve per-mode context budget when the caller didn't pass one + # explicitly. Sprint 1b (2026-05-02) — different answer modes peak + # at different budgets; quote/pointer at 24 KB, JSON at 48 KB. + # Explicit caller value always wins (backward-compatible). + if max_context_chars is None: + by_mode = policy.get("max_context_chars_by_mode") or {} + max_context_chars = int( + by_mode.get(answer_mode, policy.get("max_context_chars", 60000)) + ) + # Quantifier preflight (Ticket #000008 Phase 1+2). Phase 1 runs + # the lexical classifier; Phase 2 looks up the per-model cap. + # The cap is REPORTED on the result dict (claim_cap_applied) but + # only applied to the verifier when quantifier_guard_apply_caps + # is True (default False through dry-run rollout per §10.11.3). + # Six-level disable hierarchy gates each step: master + # (quantifier_guard_enabled), per-mode (quantifier_guard_modes), + # per-call (quantifier_caps_by_intensity overrides), per-test + # (policy={"quantifier_guard_enabled": False}). + from aborist.qa.model_profiles import cap_for_intensity + from aborist.qa.quantifier import classify_question_quantifier + quantifier_guard_on = bool(policy.get("quantifier_guard_enabled", True)) + quantifier_guard_modes = policy.get( + "quantifier_guard_modes", + ["claim_lattice_pointer", "claim_lattice"], + ) + quantifier_mode_gated = answer_mode in (quantifier_guard_modes or []) + if quantifier_guard_on: + quantifier = classify_question_quantifier(question) + else: + # Master kill — emit a stub so the result schema stays + # consistent. Bench rows can still distinguish "guard off" + # from "no classification" via quantifier_intensity=None. + quantifier = { + "intensity": None, + "matched_token": None, + "explicit_count": None, + "is_broad": False, + "operational_shape": None, + "scope_bound_hint": "unknown", + "classifier_version": None, + } + if quantifier_guard_on and quantifier_mode_gated and quantifier["intensity"]: + claim_cap_lookup = cap_for_intensity( + model_profile_id=model_id, + intensity=quantifier["intensity"], + explicit_count=quantifier["explicit_count"], + policy_overrides=policy.get("quantifier_caps_by_intensity") or None, + ) + else: + claim_cap_lookup = None + # Effective cap that the verifier will see. Dry-run mode + # (apply_caps=False) preserves the policy default; once an + # operator flips apply_caps=True, the looked-up cap shadows the + # default for this call only — but ONLY for modes in + # quantifier_apply_caps_modes. n=5 bench (#000008 §12.10) found + # cap-on-pointer fires TOO_MANY_CLAIMS 20× without moving the + # 0/45 STRICT floor, while cap-on-JSON wins +14pp. Default + # allowlist is ["claim_lattice"] (JSON only); empty/None falls + # back to all guard_modes. + # The full cap fallback chain reads: + # 1. quantifier-guard cap (when apply_caps=True AND mode allowed) + # 2. claim_lattice_max_claims_per_answer policy field + # 3. hard-coded default 12 + quantifier_apply_caps = bool(policy.get("quantifier_guard_apply_caps", False)) + quantifier_apply_caps_modes = policy.get( + "quantifier_apply_caps_modes", + quantifier_guard_modes, # legacy fallback + ) or quantifier_guard_modes + quantifier_caps_mode_gated = answer_mode in (quantifier_apply_caps_modes or []) + _policy_max_claims = int(policy.get("claim_lattice_max_claims_per_answer", 12)) + if ( + quantifier_apply_caps + and quantifier_caps_mode_gated + and claim_cap_lookup is not None + ): + effective_max_claims = int(claim_cap_lookup) + else: + effective_max_claims = _policy_max_claims + # Ticket #000010 — meta-cognition preflight. Pure deterministic + # classifier wraps the quantifier output plus four new detectors + # (temporal, contradiction, false-premise-lite, out-of-corpus). + # Surfaces a QuestionState on the result dict; first pass does + # NOT bind into run_dag_root (deferred to Phase 5 / ticket #000009 + # where the quantifier_preflight node lands too — both nodes can + # land together to keep the run-DAG schema atomic). Reference + # frames not yet plumbed through (frame_detection runs after + # retrieval, and preflight here is pre-retrieval — frame info + # lives on the result dict separately, not on QuestionState + # in this pass). + from aborist.qa.metacognition import preflight_question + _t_preflight = time.monotonic() + question_state = preflight_question( + question, + model_profile_id=model_id, + reference_frames=(), + policy=policy, + ) + preflight_ms = _ms_since(_t_preflight) + # Ticket #000011 — optional soft preflight sidecar. Default OFF; + # one short LLM round-trip when policy["soft_preflight_enabled"] + # is True. Returns a stub hint (SOFT_DISABLED) when off so the + # result-dict / run-DAG schema stays consistent. NEVER enters + # the verifier proof path; advisory only. + from aborist.qa.soft_preflight import soft_preflight_question + _t_soft_preflight = time.monotonic() + soft_hint = soft_preflight_question( + question, + chat_client=chat_client, + model_id=model_id, + policy=policy, + ) + soft_preflight_ms = _ms_since(_t_soft_preflight) + # Ticket #000008 Phase 4 — strict reject for broad-unbounded. + # When opt-in via policy / --reject-broad CLI flag, return + # UNGROUNDED before the LLM call for ALL/COMPREHENSIVE/ + # OPEN_REQUEST + scope_bound_hint==unbounded shapes. Bounded + # universals (scope_bound_hint==bounded) are NOT rejected per + # §10.1 — those are answerable. Saves the ~10-15s LLM call on + # rejected runs. + quantifier_reject_broad = bool(policy.get("quantifier_reject_broad", False)) + quantifier_should_reject = ( + quantifier_guard_on + and quantifier_mode_gated + and quantifier_reject_broad + and quantifier.get("is_broad") + and quantifier.get("scope_bound_hint") == "unbounded" + ) + if quantifier_should_reject: + # Early-return without an LLM call. Skips retrieval cost too — + # we already know the answer set is undefined. Result schema + # mirrors a normal UNGROUNDED row so bench/CLI rendering + # stays consistent. + # Ticket #000009 §8.2 / feedback §6.2: build a 3-stage + # reject-broad DAG so the rejection is Merkle-auditable. + # Without this, two rejections under different policy state + # would be indistinguishable in audit replay. + from aborist.qa.dag import ( + build_reject_run_dag, + preflight_node_hash as _pre_hash, + ) + # question_hash / verifier_policy_hash / model_profile_hash + # already imported at module top; do NOT re-import locally + # (would shadow free-variable uses elsewhere in this function). + _reject_qhash = question_hash( + question, + mode=policy.get("question_dedup", "equivalence_class"), + ) + _reject_ghash = verifier_policy_hash(policy) + _reject_mhash = model_profile_hash(model_id, revision, quantization) + _reject_rationale = ( + "preflight rejection — broad-quantifier query with " + "unbounded scope. Operator opted in via " + "quantifier_reject_broad policy." + ) + _reject_violations = [{ + "kind": "BROAD_QUANTIFIER_REJECTED", + "intensity": quantifier["intensity"], + "matched_token": quantifier["matched_token"], + "scope_bound_hint": quantifier["scope_bound_hint"], + "reason": _reject_rationale, + }] + _reject_answer_text = ( + "BROAD-QUANTIFIER PREFLIGHT REJECTED · scope unbounded\n\n" + f"Question matched {quantifier['intensity']} intensity " + f"(\"{quantifier['matched_token']}\") with an under-" + "specified universe. Narrow the question (e.g. add a " + "year, league, country, or category) or run with " + "--allow-broad for exploratory enumeration." + ) + # Same payload-then-hash pattern as the miss path so + # `--show-preflight` can render the full clause set on + # reject rows too. + from aborist.qa.dag import ( + _canonical_json as _reject_canon, + _sha256_hex as _reject_sha, + build_preflight_node_payload as _reject_build_payload, + ) + _reject_preflight_payload = _reject_build_payload( + question_state=question_state.to_dict(), + quantifier=quantifier, + answer_contract={ + "guard_enabled": quantifier_guard_on, + "mode_gated": quantifier_mode_gated, + "apply_caps_active": quantifier_apply_caps, + "apply_caps_mode_gated": quantifier_caps_mode_gated, + "claim_cap_resolved": claim_cap_lookup, + "claim_cap_applied": None, # cap never reaches verifier on reject + "manual_quotes_allowed": False, + "evidence_pointer_required": True, + "allow_unbounded_enumeration": False, + "reject_broad_active": True, + "metacognition_enabled": bool( + policy.get("metacognition_enabled", True) + ), + "block_on_contradiction": bool( + policy.get("metacognition_block_on_contradiction", False) + ), + }, + prompt_contract={ + # Rejection skips the LLM, so no reminder ever fires. + "reminder_enabled": bool( + policy.get("quantifier_reminder_enabled", False) + ), + "reminder_injected": False, + "reminder_template_id": None, + }, + evidence_contract={ + "max_evidence_ids_exposed": int(policy.get( + "claim_lattice_max_pointers_per_claim", 2 + )), + "one_claim_per_line": True, + }, + policy_refs={ + "governance_policy_hash": _reject_ghash, + "model_profile_hash": _reject_mhash, + "answer_mode": answer_mode, + }, + ) + _reject_preflight_hash = _reject_sha( + _reject_canon(_reject_preflight_payload) + ) + _reject_run_dag = build_reject_run_dag( + question_hash=_reject_qhash, + preflight_hash=_reject_preflight_hash, + preflight_payload=_reject_preflight_payload, + rejection_reason=_reject_rationale, + answer_text=_reject_answer_text, + audit_mode="UNGROUNDED", + verifier_method=( + "claim_lattice_pointer" + if answer_mode == "claim_lattice_pointer" + else "claim_lattice" + if answer_mode == "claim_lattice" + else "quote" + ), + violations=_reject_violations, + ) + return { + "status": "broad_quantifier_rejected", + "audit_mode": "UNGROUNDED", + "cache_key": None, + "lookup_path": "preflight", + # Audit binding: reject path now carries its own + # 3-stage run_dag (question → preflight → final_label) + # so audit replay can read the rejection from + # run_dag_blob the same way it reads any other row. + "run_dag_root": _reject_run_dag["root"], + "run_dag_blob": json.dumps(_reject_run_dag, separators=(",", ":")), + "preflight_hash": _reject_preflight_hash, + "answer_text": _reject_answer_text, + "sources": [], + "n_quotes": 0, + "n_verified": 0, + "verifier_method": "claim_lattice_pointer" + if answer_mode == "claim_lattice_pointer" + else "claim_lattice" + if answer_mode == "claim_lattice" + else "quote", + "unverified_quotes": [], + "partially_verified_quotes": [], + "violations": _reject_violations, + "format_collapsed": None, + "raw_answer": None, + "quantifier_intensity": quantifier["intensity"], + "quantifier_matched_token": quantifier["matched_token"], + "scope_bound_hint": quantifier["scope_bound_hint"], + "quantifier_explicit_count": quantifier["explicit_count"], + "claim_cap_applied": claim_cap_lookup, + # Ticket #000010 — meta-cognition QuestionState surfaced + # for bench / CLI render. Preflight rejection path still + # returns its own status; this is the upstream classifier + # output regardless of guard outcome. + "question_state": question_state.to_dict(), + "pointer_id_distribution": None, + "lazy_anchor_ratio": None, + "retrieval_purity": None, + "prompt_chars": { + "system_prompt": 0, + "grounding_reminder": 0, + "user_question": len(question), + "evidence_or_context": 0, + "messages_total": 0, + }, + "answer_chars": 0, + "frame_detection": None, + "burned_existing": 0, + "context_root": None, + "timings": { + "search_ms": 0.0, + "context_ms": 0.0, + "cache_lookup_ms": 0.0, + "llm_ms": None, + "persist_ms": None, + # Preflight rejection runs in <1ms — record 0.0 + # rather than re-fetching wall-time. The point of + # the path is to NOT spend wall time. + "total_ms": 0.0, + }, + } + t_start = time.monotonic() + + # 1. Search. + # + # Retrieval-only query string: question + operator-supplied + # ``retrieval_keywords`` (a hint, never part of the cache_key / + # LLM prompt / verifier surface). When the user passes + # `--retrieval-keywords "transcranial knowledge acquisition"`, + # only the FTS5 MATCH and title-filter token set see those + # tokens; the question text fed to the LLM and to question_hash + # stays untouched. + retrieval_query = question + if retrieval_keywords and retrieval_keywords.strip(): + retrieval_query = f"{question} {retrieval_keywords.strip()}" + t_phase = time.monotonic() + hits, core_match_roots, phrase_match_roots, root_to_shard = _search_corpus( + shards_dir, single_db, retrieval_query, over_fetch + ) + if not hits: + return { + "status": "no_sources", + "msg": "FTS5 search returned no hits", + "timings": { + "search_ms": _ms_since(t_phase), + "total_ms": _ms_since(t_start), + }, + } + qtokens_lower = {t.lower() for t in _title_query_tokens(retrieval_query)} + + def _body_density_check(h) -> bool: + # Lazy per-hit check: open the shard, count token mentions in this doc. + sp = root_to_shard.get(h.document_root) or h.shard_path + if not sp: + return False + c = connect(sp) + try: + return _body_density_passes(c, h.document_root, qtokens_lower) + finally: + c.close() + + hits = _rerank( + hits, + retrieval_query, + core_match_roots=core_match_roots, + body_density_check=_body_density_check, + phrase_match_roots=phrase_match_roots, + hyphen_fold_anchors=_hyphen_fold_variants(retrieval_query), + shards_dir=shards_dir, + ) + search_ms = _ms_since(t_phase) + + # 2. Pull doc texts within budget. + # + # Per-source cap so a single huge document can't monopolize the + # context window. Without this, a top-ranked bibliography page + # (e.g. List_of_Batman_comics at 80 KB) consumes the entire 60 KB + # budget at hit #1 and every subsequent doc is dropped with + # char_budget <= 0 — even when the bio article is hit #2 with + # the actual answer. By default we cap each source at + # `max_context_chars // top_k` so all top_k hits land in context. + # Total context ≤ max_context_chars by construction. + t_phase = time.monotonic() + chosen: list[_Hit] = [] + context_parts: list[str] = [] + per_source_cap = max(1, max_context_chars // max(1, top_k)) + char_budget = max_context_chars + for h in hits[:top_k]: + text = _load_doc_text(h.shard_path, h.document_root) + if not text: + continue + # source_role is already set by _rerank_by_source_role; reuse + # it for the per-source cap. Primary answer source gets 2× the + # baseline cap, noisy/sequel get 0.5×, secondary & background + # get 1×. Total context still bounded by `char_budget`. + weight = SOURCE_ROLE_BUDGET_WEIGHTS.get(h.source_role, 1.0) + hit_cap = max(1, int(per_source_cap * weight)) + if len(text) > hit_cap: + text = text[:hit_cap] + if len(text) > char_budget: + text = text[:char_budget] + if not text: + continue + context_parts.append( + f"=== Source: {h.document_uri} ===\n{text}" + ) + chosen.append(h) + char_budget -= len(text) + if char_budget <= 0: + break + + if not chosen: + return { + "status": "no_sources", + "msg": "top-k hits had cold or empty content", + "timings": { + "search_ms": search_ms, + "context_ms": _ms_since(t_phase), + "total_ms": _ms_since(t_start), + }, + } + context = "\n\n".join(context_parts) + + # Wikitext → prose before the LLM sees it. The model can then quote + # verbatim against the prose form; the verifier compares like-against- + # like. Idempotent if context is already plain prose. Gated on + # policy["base_version"] so this is part of governance_policy_hash. + if policy.get("base_version") and _wikitext_to_base is not None: + context = _wikitext_to_base(context) + context_ms = _ms_since(t_phase) + + # 3. Build messages + hashes. Branch on answer_mode: + # "quote" (default) raw sources block + verbatim-quote rules. + # "claim_lattice" one evidence object per chosen source, each + # labeled with a content-addressed evidence_id; + # model emits JSON referencing IDs. + evidence_map = [] + if answer_mode == "claim_lattice_pointer": + # G0.1 — per-chunk evidence granularity. Each retrieved source + # contributes ONE evidence object per chunk (up to the + # role-weighted per_source_cap budget) instead of one + # whole-doc span. + # + # G0.3 — query-relevance chunk ordering. Within each source, + # chunks are ranked by (distinct_query_tokens_present, + # total_mentions, chunk_idx_asc) so the chunk that most + # textually supports the question gets the lowest pointer id + # and lands at the top of the per-source evidence stack. Without + # this re-rank, Hermes-3-8B lazy-anchors on the first few + # chunks regardless of relevance — burying the actual answer + # paragraph behind irrelevant article-header text. Soft signal + # only (token overlap; no embeddings) so it stays out of the + # proof path; the verifier still runs the same hard checks + # against whatever the model picked. + qtokens_stem_for_chunks = { + _stem_token_for_match(t.lower()) + for t in _title_query_tokens(question) + } + chunks_for_map: list[dict] = [] + for h in chosen: + doc_chunks = _load_doc_chunks(h.shard_path, h.document_root) + if not doc_chunks: + continue + weight = SOURCE_ROLE_BUDGET_WEIGHTS.get(h.source_role, 1.0) + hit_cap = max(1, int(per_source_cap * weight)) + # Score each chunk by query-token overlap. Tuple sort: + # distinct present DESC, total mentions DESC, doc order ASC. + scored = [] + for chunk_idx, leaf_hash, span in doc_chunks: + distinct, total = _chunk_query_relevance( + span, qtokens_stem_for_chunks + ) + scored.append( + (chunk_idx, leaf_hash, span, distinct, total) + ) + scored.sort(key=lambda r: (-r[3], -r[4], r[0])) + # Greedy: fill the per-source budget with relevance-ranked + # chunks. If a single chunk exceeds what's left, truncate + # that one chunk and stop. Total context across the source + # stays bounded by hit_cap, same shape as the prose path. + # Per-source chunk cap also bounds chunk COUNT (in addition + # to char budget) so an encyclopedic article doesn't inflate + # the evidence catalog into E1-E26 territory and induce + # mega-claim failures. + max_chunks = max(1, int(policy.get( + "claim_lattice_max_chunks_per_source", 2 + ))) + spent = 0 + chunks_used = 0 + for chunk_idx, leaf_hash, span, _d, _t in scored: + if spent >= hit_cap or chunks_used >= max_chunks: + break + if policy.get("base_version") and _wikitext_to_base is not None: + span = _wikitext_to_base(span) + remaining = hit_cap - spent + if len(span) > remaining: + span = span[:remaining] + if not span: + break + chunks_for_map.append({ + "source_root": h.document_root, + "document_uri": h.document_uri, + "title": h.title, + "chunk_idx": chunk_idx, + "chunk_root": leaf_hash, + "span": span, + "source_role": h.source_role, + }) + spent += len(span) + chunks_used += 1 + evidence_map = build_evidence_map(chunks_for_map) + sys_prompt = policy["claim_lattice_system_prompt"] + grounding_reminder = policy.get("claim_lattice_grounding_reminder") + rendered_evidence = render_evidence_map(evidence_map) + + def _user_payload(q: str) -> str: + return f"EVIDENCE:\n\n{rendered_evidence}\n\n---\n\nQUESTION: {q}" + elif answer_mode == "claim_lattice": + # JSON variant — same evidence-map construction as the pointer + # path, but blocks are labeled with content-addressed + # ``evidence_id`` (long hex) since the model emits IDs in JSON. + # The lenient pre-parser in verify_claim_lattice_json keeps the + # path survivable on inference paths without grammar guidance; + # vLLM ``guided_json`` (passed via extra_body below) eliminates + # SCHEMA_INVALID failures at sampling time when available. + qtokens_stem_for_chunks = { + _stem_token_for_match(t.lower()) + for t in _title_query_tokens(question) + } + chunks_for_map: list[dict] = [] + for h in chosen: + doc_chunks = _load_doc_chunks(h.shard_path, h.document_root) + if not doc_chunks: + continue + weight = SOURCE_ROLE_BUDGET_WEIGHTS.get(h.source_role, 1.0) + hit_cap = max(1, int(per_source_cap * weight)) + scored = [] + for chunk_idx, leaf_hash, span in doc_chunks: + distinct, total = _chunk_query_relevance( + span, qtokens_stem_for_chunks + ) + scored.append((chunk_idx, leaf_hash, span, distinct, total)) + scored.sort(key=lambda r: (-r[3], -r[4], r[0])) + max_chunks = max(1, int(policy.get( + "claim_lattice_max_chunks_per_source", 2 + ))) + spent = 0 + chunks_used = 0 + for chunk_idx, leaf_hash, span, _d, _t in scored: + if spent >= hit_cap or chunks_used >= max_chunks: + break + if policy.get("base_version") and _wikitext_to_base is not None: + span = _wikitext_to_base(span) + remaining = hit_cap - spent + if len(span) > remaining: + span = span[:remaining] + if not span: + break + chunks_for_map.append({ + "source_root": h.document_root, + "document_uri": h.document_uri, + "title": h.title, + "chunk_idx": chunk_idx, + "chunk_root": leaf_hash, + "span": span, + "source_role": h.source_role, + }) + spent += len(span) + chunks_used += 1 + evidence_map = build_evidence_map(chunks_for_map) + sys_prompt = policy.get( + "claim_lattice_json_system_prompt", + policy["claim_lattice_system_prompt"], + ) + grounding_reminder = policy.get( + "claim_lattice_json_grounding_reminder", + policy.get("claim_lattice_grounding_reminder"), + ) + rendered_evidence = render_evidence_map_for_json(evidence_map) + + def _user_payload(q: str) -> str: + return f"EVIDENCE:\n\n{rendered_evidence}\n\n---\n\nQUESTION: {q}" + else: + sys_prompt = policy["system_prompt"] + grounding_reminder = policy.get("grounding_reminder") + + def _user_payload(q: str) -> str: + return f"Sources:\n\n{context}\n\n---\n\nQuestion: {q}" + + # Frame detection (Ticket #000002 / Module L). Lattice-mode only. + # Surfaces whether the query is allusion-shape AND the phrase + # route surfaced a reference-work source. When `reference`, the + # polarity preamble below nudges the model toward multi-frame + # answers. + # + # Body sample for the fiction-marker density check uses the + # ARTICLE LEAD (chunk_idx=0) — that's where fiction markers + # cluster on Wikipedia ("is a dystopian science fiction novel + # by..."). Reusing chunks_for_map would give us the query- + # relevant chunks (e.g. the plot section containing 'always been + # at war') which may have fewer fiction markers. + frame_detection: FrameDetection | None = None + if answer_mode in ("claim_lattice_pointer", "claim_lattice"): + sources_for_frame: list[dict] = [] + seen_roots: set[str] = set() + for h in chosen: + if h.document_root in seen_roots: + continue + seen_roots.add(h.document_root) + doc_chunks = _load_doc_chunks(h.shard_path, h.document_root) + # First chunk by idx ASC — the article lead. + body_sample = doc_chunks[0][2] if doc_chunks else "" + # Wikitext-strip so fiction markers buried under + # `[[wikilinks]]` and `{{templates}}` surface in the + # density check. Bench-time policy gates the strip; we + # apply it unconditionally here since a no-op fallback + # leaves raw wikitext (and the markers still match the + # `\bnovel\b` regex even with surrounding markup). + if ( + policy.get("base_version") + and _wikitext_to_base is not None + and body_sample + ): + body_sample = _wikitext_to_base(body_sample) + sources_for_frame.append({ + "document_root": h.document_root, + "document_uri": h.document_uri, + "title": h.title, + "body_sample": body_sample, + }) + frame_detection = _detect_frame( + question, sources_for_frame, phrase_match_roots=phrase_match_roots + ) + + # Ticket #000010 §12.6 — refine QuestionState with frame data + # post-retrieval. Pre-retrieval preflight ran with empty + # reference_frames=() (frame detection needs source titles + # which only exist after retrieval). Now that frames are + # known, re-run the classifier so the run-DAG and result-dict + # QuestionState carry the frame-aware logical_statuses + # (specifically `reference_frame_ambiguous` when 2+ frames + # match). Pure function; cheap to re-call. + refined_frames: tuple[str, ...] = () + if frame_detection is not None: + if frame_detection.frame_kind == "reference": + refined_frames = ( + ("literal_geography", frame_detection.reference_title or "reference") + if frame_detection.confidence < 1.0 + else (frame_detection.reference_title or "reference",) + ) + elif frame_detection.frame_kind == "ambiguous": + refined_frames = ("literal", "ambiguous_reference") + if refined_frames: + question_state = preflight_question( + question, + model_profile_id=model_id, + reference_frames=refined_frames, + policy=policy, + ) + + messages = [{"role": "system", "content": sys_prompt}] + # Polarity preamble for reference-frame queries (Ticket #000002). + # Injected as a user-role message BEFORE the grounding_reminder + # so the model sees the frame hint first, then the + # always-applicable structural reminder, then the actual + # evidence + question. + polarity_template = policy.get("claim_lattice_polarity_preamble", "") + if ( + frame_detection is not None + and frame_detection.frame_kind == "reference" + and polarity_template + ): + polarity_msg = polarity_template.format( + reference_title=frame_detection.reference_title or "" + ) + messages.append({"role": "user", "content": polarity_msg}) + if grounding_reminder: + messages.append({"role": "user", "content": grounding_reminder}) + # Quantifier-specific reminder (Ticket #000008 Phase 3, default + # off). Same mechanism as runner.ask — see runner.py for + # rationale. Mode-gated and master-killable. + if ( + quantifier_guard_on + and quantifier_mode_gated + and quantifier.get("is_broad") + and bool(policy.get("quantifier_reminder_enabled", False)) + ): + from aborist.qa.quantifier_reminder import broad_quantifier_reminder + broad = broad_quantifier_reminder( + intensity=quantifier["intensity"], + cap=effective_max_claims, + scope_bound_hint=quantifier["scope_bound_hint"], + ) + if broad: + messages.append({"role": "user", "content": broad}) + messages.append({"role": "user", "content": _user_payload(question)}) + + # Capacity metrics. Char-level for now — a fast model-agnostic proxy + # for prompt size (rule of thumb: ~4 chars/token for English prose, + # ~2.5 for JSON-evidence-block heavy contexts). Surfaced in the + # result dict so the bench can correlate strict-rate with input + # size and the operator can tell at a glance whether a STRICT + # verdict came from a tight 5KB prompt or a 50KB context-stuffed + # one. Never enters cache_key — these are runtime measurements, + # not policy. + if answer_mode in ("claim_lattice_pointer", "claim_lattice"): + evidence_or_context_chars = len(rendered_evidence) + else: + evidence_or_context_chars = len(context) + prompt_chars = { + "system_prompt": len(sys_prompt or ""), + "grounding_reminder": len(grounding_reminder or ""), + "user_question": len(question or ""), + "evidence_or_context": evidence_or_context_chars, + "messages_total": sum(len(m["content"]) for m in messages), + } + + context_root = _context_root([h.document_root for h in chosen]) + mhash = model_profile_hash(model_id, revision, quantization) + + # Dedup-mode-aware cache_key build. For each mode we substitute the + # mode's canonical question form into the user message used for + # `conversation_hash` (LLM still sees the verbatim question), AND we + # vary `policy["question_dedup"]` to match the mode so + # `governance_policy_hash` matches what an agent under that mode + # would have written. This makes cross-silo fallback work: a + # strict-policy agent looking up with equivalence_class fidelity can + # find a record written by an equivalence_class-policy agent. + def _ckey_for_mode(mode: str) -> str: + canon_q = canonical_question(question, mode=mode) + canon_msgs = list(messages[:-1]) + [ + {"role": "user", "content": _user_payload(canon_q)}, + ] + policy_variant = dict(policy, question_dedup=mode) + return cache_key( + context_root, + question_hash(question, mode=mode), + mhash, + conversation_hash(canon_msgs), + governance_policy_hash(policy_variant), + SCHEMA_VERSION, + CANONICALIZATION_VERSION, + CHUNKING_VERSION, + verifier_policy_hash(policy_variant), + ) + + ghash = governance_policy_hash(policy) # for the legacy INSERT below + + primary_dedup = policy.get("question_dedup", DEFAULT_QUESTION_DEDUP) + if primary_dedup not in QUESTION_DEDUP_MODES: + raise ValueError( + f"policy['question_dedup'] must be one of {QUESTION_DEDUP_MODES}, " + f"got {primary_dedup!r}" + ) + # Re-derive the per-mode hashes for use in the INSERT below. The legacy + # INSERT references qhash/chash by name; _ckey_for_mode already builds + # them but doesn't expose the intermediates. + qhash = question_hash(question, mode=primary_dedup) + canonical_q_primary = canonical_question(question, mode=primary_dedup) + canonical_messages_primary = list(messages[:-1]) + [ + {"role": "user", "content": _user_payload(canonical_q_primary)}, + ] + chash = conversation_hash(canonical_messages_primary) + primary_ckey = _ckey_for_mode(primary_dedup) + ckey = primary_ckey # keep the legacy name in the rest of the function + + qa_conn = connect(qa_db) + burned_existing = 0 + try: + # 3.5. Optional pre-lookup burn: deletes the matching live row + # under the primary cache_key so the lookup misses & a fresh + # inference runs. Test-ergonomic — pass `burn_existing=True` + # (or `make query Q=... BURN=1`) after tweaking a knob to see + # the new behavior. The equivalence-class fallback key is + # deliberately NOT touched: prior alt-mode records stay as + # historic witnesses. + if burn_existing: + existing = qa_conn.execute( + "SELECT cache_key, audit_mode, n_verified, " + " falsification_state, question_text " + "FROM providence_cache WHERE cache_key = ?", + (primary_ckey,), + ).fetchone() + if existing is not None: + with transaction(qa_conn): + qa_conn.execute( + "DELETE FROM providence_cache WHERE cache_key = ?", + (primary_ckey,), + ) + append_audit( + qa_conn, + event_type="providence_burn", + subject_root=primary_ckey, + body={ + "cache_key": primary_ckey, + "burned_audit_mode": existing["audit_mode"], + "burned_n_verified": int(existing["n_verified"] or 0), + "burned_state": existing["falsification_state"], + "question_text": existing["question_text"], + "reason": "query --burn (test-ergonomic mid-query bust)", + }, + ) + burned_existing = 1 + + # 4. Cache lookup. Try the primary dedup-mode cache_key first. + # If fidelity allows fallback AND the alternate dedup mode + # produces a different cache_key, try that too — lets a + # fast-cache agent reuse a record written under either mode. + t_phase = time.monotonic() + cached = qa_conn.execute( + "SELECT * FROM providence_cache " + "WHERE cache_key = ? AND falsification_state = 'live'", + (primary_ckey,), + ).fetchone() + hit_ckey = primary_ckey + lookup_path = primary_dedup if cached is not None else None + if cached is None and fidelity == "equivalence_class": + other_mode = ( + "equivalence_class" if primary_dedup == "strict" else "strict" + ) + other_ckey = _ckey_for_mode(other_mode) + if other_ckey != primary_ckey: + cached = qa_conn.execute( + "SELECT * FROM providence_cache " + "WHERE cache_key = ? AND falsification_state = 'live'", + (other_ckey,), + ).fetchone() + if cached is not None: + hit_ckey = other_ckey + lookup_path = f"{other_mode}_fallback" + cache_lookup_ms = _ms_since(t_phase) + if cached is not None: + now = int(time.time()) + with transaction(qa_conn): + qa_conn.execute( + "UPDATE providence_cache " + "SET hit_count = hit_count + 1, last_hit_at = ? " + "WHERE cache_key = ?", + (now, hit_ckey), + ) + return { + "status": "cache_hit", + "audit_mode": cached["audit_mode"], + "cache_key": hit_ckey, + "lookup_path": lookup_path, + "burned_existing": burned_existing, + "context_root": context_root, + "answer_text": cached["answer_text"], + "sources": json.loads(cached["merkle_proof"])["sources"], + "n_quotes": cached["n_quotes"], + "n_verified": cached["n_verified"], + "verifier_method": cached["verifier_method"], + "unverified_quotes": ( + json.loads(cached["unverified_quotes"]) + if cached["unverified_quotes"] + else [] + ), + # Cache schema doesn't carry the partially-verified split — + # those claims were folded into unverified_quotes pre-2026- + # 04-30. Cache hits surface an empty partial list; new + # writes populate it correctly. Acceptable degradation + # since governance_policy_hash invalidated prior records. + "partially_verified_quotes": [], + # Quantifier preflight (Ticket #000008 Phase 1) — the + # classifier is pure on the question string, so cache + # hits can re-classify cheaply and carry the same + # schema as miss-path rows. Bench rows stay + # column-aligned across hit/miss. + "quantifier_intensity": quantifier["intensity"], + "quantifier_matched_token": quantifier["matched_token"], + "scope_bound_hint": quantifier["scope_bound_hint"], + "quantifier_explicit_count": quantifier["explicit_count"], + "claim_cap_applied": claim_cap_lookup, + # Ticket #000010 — meta-cognition QuestionState. Pure + # function, cache hits re-classify cheaply. + "question_state": question_state.to_dict(), + # Ticket #000009 §7.2 — pull preflight_hash out of + # the persisted run_dag_blob. Cache hits don't + # rebuild the DAG; the blob carries the original + # preflight stage hash from the write-time policy. + # None when the cached row predates #000009. + # cached is a sqlite3.Row; column access via + # subscript, not .get(); guard with `keys()` since + # legacy rows may lack the run_dag_blob column. + "preflight_hash": _extract_preflight_hash_from_blob( + cached["run_dag_blob"] if "run_dag_blob" in cached.keys() else None + ), + "prompt_chars": prompt_chars, + "answer_chars": len(cached["answer_text"] or ""), + "timings": { + "search_ms": search_ms, + "context_ms": context_ms, + "cache_lookup_ms": cache_lookup_ms, + "llm_ms": None, + "persist_ms": None, + "total_ms": _ms_since(t_start), + }, + } + + # 5. Cache miss — call LLM. JSON mode passes guided_json via + # extra_body so vLLM constrains output to the schema at sampling + # time. Non-vLLM endpoints silently drop the field; the lenient + # pre-parser in the verifier handles whatever drift remains. + extra_body: dict | None = None + stop_seqs: list[str] | None = None + if answer_mode == "claim_lattice" and policy.get( + "claim_lattice_use_guided_json", True + ): + extra_body = {"guided_json": CLAIM_LATTICE_JSON_SCHEMA} + if answer_mode == "claim_lattice": + # JSON-mode token-runaway guard — see runner.py for the + # full rationale. Stops generation on a blank line so + # post-JSON whitespace spam doesn't blow max_tokens. + stop_seqs = list(policy.get( + "claim_lattice_json_stop_sequences", ["\n\n"] + )) + t_phase = time.monotonic() + raw_answer = chat_client.chat_completion( + messages, + model=model_id, + temperature=policy["temperature"], + max_tokens=policy["max_tokens"], + top_p=policy.get("top_p", 1.0), + extra_body=extra_body, + stop=stop_seqs, + ) + llm_ms = _ms_since(t_phase) + + # 5b. Faithfulness check. Branch on answer_mode: + # "quote" substring-verify quoted spans against context. + # Optional repair loop (mechanical + reprompt). + # "claim_lattice" deterministic checks on the JSON output: + # evidence_id resolution, source_role allowlist, + # manual-quote prohibition. NO repair loop — + # one-shot benchmark discipline. + repair_changes: list[dict] = [] + pre_repair_verdict: dict | None = None + + if answer_mode == "claim_lattice_pointer": + verdict = verify_claim_lattice( + raw_answer, + evidence_map, + allowed_source_roles=tuple( + policy.get( + "claim_lattice_allowed_source_roles", + [ + "primary_answer_source", + "secondary_context_source", + "background_source", + "unclassified", + ], + ) + ), + max_pointers_per_claim=int(policy.get( + "claim_lattice_max_pointers_per_claim", 2 + )), + min_citation_coverage=float(policy.get( + "claim_lattice_min_citation_coverage", 0.30 + )), + min_claim_content_tokens=int(policy.get( + "claim_lattice_min_claim_content_tokens", 3 + )), + lazy_anchor_demote_threshold=float(policy.get( + "claim_lattice_lazy_anchor_demote_threshold", 0.5 + )), + lazy_anchor_demote_min_pairs=int(policy.get( + "claim_lattice_lazy_anchor_demote_min_pairs", 3 + )), + max_claims_per_answer=effective_max_claims, + subject_tokens_absent_threshold=int(policy.get( + "claim_lattice_subject_tokens_absent_threshold", 3 + )), + question=question, + warrant_check_enabled=bool(policy.get( + "claim_lattice_warrant_check_enabled", True + )), + deflection_check_enabled=bool(policy.get( + "claim_lattice_deflection_check_enabled", True + )), + format_collapse_check_enabled=bool(policy.get( + "claim_lattice_format_collapse_check_enabled", True + )), + ) + rendered = verdict["rendered_text"] + answer_text = rendered if rendered else raw_answer + elif answer_mode == "claim_lattice": + verdict = verify_claim_lattice_json( + raw_answer, + evidence_map, + allowed_source_roles=tuple( + policy.get( + "claim_lattice_allowed_source_roles", + [ + "primary_answer_source", + "secondary_context_source", + "background_source", + "unclassified", + ], + ) + ), + max_evidence_per_claim=int(policy.get( + "claim_lattice_max_pointers_per_claim", 2 + )), + min_citation_coverage=float(policy.get( + "claim_lattice_min_citation_coverage", 0.30 + )), + max_claims_per_answer=effective_max_claims, + subject_tokens_absent_threshold=int(policy.get( + "claim_lattice_subject_tokens_absent_threshold", 3 + )), + question=question, + warrant_check_enabled=bool(policy.get( + "claim_lattice_warrant_check_enabled", True + )), + deflection_check_enabled=bool(policy.get( + "claim_lattice_deflection_check_enabled", True + )), + ) + rendered = verdict["rendered_text"] + answer_text = rendered if rendered else raw_answer + else: + answer_text = raw_answer + verdict = verify_quotes( + answer_text, + context, + entity_policy=policy.get("entity_policy", "hybrid"), + proximity_n=policy.get("entity_proximity_n", 3), + proximity_window=policy.get("entity_proximity_window", 300), + ) + + def _verify(text: str) -> dict: + return verify_quotes( + text, + context, + entity_policy=policy.get("entity_policy", "hybrid"), + proximity_n=policy.get("entity_proximity_n", 3), + proximity_window=policy.get("entity_proximity_window", 300), + ) + + if ( + policy.get("repair_enabled") + and verdict["audit_mode"] != "STRICT" + and verdict.get("unverified_quotes") + ): + # Tier 1: mechanical (deterministic, no extra LLM call). + repair_result = mechanical_repair( + answer_text, verdict["unverified_quotes"], context + ) + if repair_result["changes"]: + new_verdict = _verify(repair_result["repaired_text"]) + if new_verdict["n_verified"] >= verdict["n_verified"]: + pre_repair_verdict = verdict + answer_text = repair_result["repaired_text"] + verdict = new_verdict + repair_changes = list(repair_result["changes"]) + + # Tier 2: re-prompt feedback (one extra LLM call max). + max_reprompts = int(policy.get("repair_max_reprompts", 0)) + for _ in range(max_reprompts): + if ( + verdict["audit_mode"] == "STRICT" + or not verdict.get("unverified_quotes") + ): + break + new_text = reprompt_repair( + chat_client=chat_client, + model_id=model_id, + original_messages=messages, + original_answer=answer_text, + failed_quotes=verdict["unverified_quotes"], + policy=policy, + ) + if not new_text: + break + new_verdict = _verify(new_text) + if new_verdict["n_verified"] > verdict["n_verified"]: + if pre_repair_verdict is None: + pre_repair_verdict = verdict + answer_text = new_text + verdict = new_verdict + repair_changes.append({ + "action": "reprompt_rewrite", + "diagnosis": "model_feedback_loop", + }) + else: + break + + unverified_blob = ( + json.dumps(verdict["unverified_quotes"], separators=(",", ":")) + if verdict["unverified_quotes"] + else None + ) + + # 6. Persist record + audit event. + t_phase = time.monotonic() + proof_obj = { + "context_root": context_root, + "sources": [ + { + "document_root": h.document_root, + "document_uri": h.document_uri, + "title": h.title, + "score": h.score, + "chunk_idx": h.chunk_idx, + "shard": Path(h.shard_path).name, + "source_role": h.source_role, + } + for h in chosen + ], + } + proof_blob = json.dumps(proof_obj, separators=(",", ":")) + + # Per-run Merkle-DAG. Quote mode base shape: 7 stages + # (question / retrieval / context / prompt / answer / verify + # / final_label); becomes 8 when preflight_hash is supplied + # (#000009 inserts ``preflight`` between question & retrieval). + # Pointer mode base shape: 9 stages (question / retrieval / + # evidence_map / prompt / raw_answer / parsed_claim_lattice / + # verify / render / final_label); becomes 10 with preflight. + # Reject-broad early-return path uses a 3-stage minimal DAG + # (question / preflight / final_label) via build_reject_run_dag(). + ev_root = evidence_map_root(evidence_map) if evidence_map else None + parsed_lattice = None + is_lattice_mode = answer_mode in ("claim_lattice_pointer", "claim_lattice") + if is_lattice_mode: + evidence_id_pairs = verdict.get("evidence_id_pairs") or [] + parsed_lattice = [ + { + "claim_text": cs.get("text", ""), + "evidence_ids": evidence_id_pairs[i] if i < len(evidence_id_pairs) else [], + } + for i, cs in enumerate(verdict.get("claim_statuses") or []) + ] + # Render-layer source-role display + used/unused. Compute + # which document_roots the verified evidence_ids point at + # (each EvidenceObject's source_root field carries the + # document_root the chunk came from), then annotate each + # source dict in proof_obj. Lets the CLI show per-source + # `primary_answer_source — used (E1)` style annotations. + used_doc_roots: set[str] = set() + evidence_id_to_source_root = { + e.evidence_id: e.source_root for e in (evidence_map or []) + } + for pair in evidence_id_pairs: + for eid in (pair or []): + sroot = evidence_id_to_source_root.get(eid) + if sroot: + used_doc_roots.add(sroot) + # Also map document_root → list of pointer_ids that cited it, + # so the renderer can show the actual pointer tags + # ("used (E1)" not just "used"). + evidence_id_to_pointer = { + e.evidence_id: e.pointer_id for e in (evidence_map or []) + } + doc_root_to_pointers: dict[str, list[str]] = {} + for pair in evidence_id_pairs: + for eid in (pair or []): + sroot = evidence_id_to_source_root.get(eid) + pid = evidence_id_to_pointer.get(eid) + if sroot and pid and pid not in doc_root_to_pointers.get(sroot, []): + doc_root_to_pointers.setdefault(sroot, []).append(pid) + for s in proof_obj["sources"]: + droot = s.get("document_root") + s["used"] = droot in used_doc_roots + s["used_pointer_ids"] = doc_root_to_pointers.get(droot, []) + + # Retrieval purity metrics — sidecar signals for the bench + # ("did the model ignore noise? did retrieval over-fetch?"). + # Pure observation, no decision. Useful for the + # noise-resistance bench fixture and for spotting a + # creeping retrieval-quality regression at aggregate scale. + primary_rank = next( + (i for i, s in enumerate(proof_obj["sources"], start=1) + if s.get("source_role") == "primary_answer_source"), + 0, # 0 = no primary in top-K + ) + noisy_roles = { + "noisy_background_source", "sequel_background_source", + } + noise_sources = [ + s for s in proof_obj["sources"] + if s.get("source_role") in noisy_roles + ] + noise_used = [s for s in noise_sources if s.get("used")] + retrieval_purity = { + "primary_rank": primary_rank, + "primary_used": ( + primary_rank > 0 + and proof_obj["sources"][primary_rank - 1].get("used") is True + ), + "noise_sources_count": len(noise_sources), + "noise_sources_used": len(noise_used), + "total_sources": len(proof_obj["sources"]), + "used_sources": sum( + 1 for s in proof_obj["sources"] if s.get("used") + ), + } + proof_obj["retrieval_purity"] = retrieval_purity + # Retrieval-plan hash (Ticket #000001 / Directive D4): + # capture the operator-influenceable retrieval inputs so the + # run-DAG's retrieval stage binds BOTH plan (what guided the + # search) and result (what got chosen). Folds shard ids when + # available so an audit can reproduce which shards the search + # ran against. Question text intentionally NOT included here + # — already covered by question_hash. + plan = RetrievalPlan( + retrieval_keywords=retrieval_keywords or "", + top_k=int(top_k), + over_fetch=int(over_fetch), + max_context_chars=int(max_context_chars), + shard_ids=tuple( + sorted( + {root_to_shard.get(h.document_root, h.shard_path or "") + for h in chosen if (root_to_shard.get(h.document_root) + or h.shard_path)} + ) + ), + ) + plan_hash = retrieval_plan_hash(plan) + # Ticket #000009 — preflight node binding (nested CTI clauses + # per ticket §8 / 2026-05-04 feedback). Single DAG stage with + # five nested clauses (classifier, answer_contract, + # prompt_contract, evidence_contract, policy_refs) + the + # metacognition QuestionState. + from aborist.qa.dag import preflight_node_hash + # verifier_policy_hash + model_profile_hash already imported + # at module top; reusing the existing names. Local re-imports + # would shadow earlier free-variable uses. + ghash_for_dag = verifier_policy_hash(policy) + claim_cap_actually_applied = ( + claim_cap_lookup + if (quantifier_apply_caps + and quantifier_caps_mode_gated + and claim_cap_lookup is not None) + else None + ) + # Reminder injection actually fires when guard is on AND + # mode-gated AND quantifier is broad AND policy enables it. + # Mirrors the gate in the runner.ask() / query() reminder + # block above. + reminder_eligible = ( + quantifier_guard_on + and quantifier_mode_gated + and quantifier.get("is_broad", False) + ) + reminder_enabled = bool(policy.get("quantifier_reminder_enabled", False)) + reminder_injected = reminder_eligible and reminder_enabled + reminder_template_id = None + if reminder_injected: + reminder_template_id = ( + "broad-quantifier-bounded-v1" + if quantifier.get("scope_bound_hint") == "bounded" + else "broad-quantifier-unbounded-v1" + ) + # Build the canonical payload once; hash it AND persist it + # alongside the DAG nodes so audit replay can render the + # full 5-clause CTI contract via `aborist providence + # --show-preflight`. Hash is deterministic from payload, so + # an auditor can re-verify: + # _sha256_hex(_canonical_json(preflight_payload)) + # == nodes[preflight_idx]["hash"] + from aborist.qa.dag import build_preflight_node_payload + _preflight_payload = build_preflight_node_payload( + question_state=question_state.to_dict(), + quantifier=quantifier, + answer_contract={ + "guard_enabled": quantifier_guard_on, + "mode_gated": quantifier_mode_gated, + "apply_caps_active": quantifier_apply_caps, + "apply_caps_mode_gated": quantifier_caps_mode_gated, + "claim_cap_resolved": claim_cap_lookup, + "claim_cap_applied": claim_cap_actually_applied, + "manual_quotes_allowed": False, + "evidence_pointer_required": is_lattice_mode, + "allow_unbounded_enumeration": False, + "reject_broad_active": bool( + policy.get("quantifier_reject_broad", False) + ), + "metacognition_enabled": bool( + policy.get("metacognition_enabled", True) + ), + "block_on_contradiction": bool( + policy.get( + "metacognition_block_on_contradiction", False + ) + ), + }, + prompt_contract={ + "reminder_enabled": reminder_enabled, + "reminder_injected": reminder_injected, + "reminder_template_id": reminder_template_id, + }, + evidence_contract={ + "max_evidence_ids_exposed": int(policy.get( + "claim_lattice_max_pointers_per_claim", 2 + )), + "one_claim_per_line": is_lattice_mode, + }, + policy_refs={ + "governance_policy_hash": ghash_for_dag, + "model_profile_hash": mhash, + "answer_mode": answer_mode, + }, + ) + from aborist.qa.dag import _sha256_hex, _canonical_json + preflight_hash = _sha256_hex(_canonical_json(_preflight_payload)) + run_dag = build_run_dag( + question_hash=qhash, + sources=proof_obj["sources"], + context_root=context_root, + conversation_hash=chash, + answer_text=answer_text, + audit_mode=verdict["audit_mode"], + verifier_method=verdict["verifier_method"], + n_quotes=verdict["n_quotes"], + n_verified=verdict["n_verified"], + claim_statuses=verdict.get("claim_statuses", []), + lookup_path="miss", + evidence_map_root=ev_root, + answer_mode=answer_mode if answer_mode != "quote" else None, + violations=verdict.get("violations"), + raw_answer_text=raw_answer if is_lattice_mode else None, + parsed_lattice=parsed_lattice, + rendered_text=answer_text if is_lattice_mode else None, + retrieval_plan_hash=plan_hash, + preflight_hash=preflight_hash, + preflight_payload=_preflight_payload, + ) + run_dag_blob = json.dumps(run_dag, separators=(",", ":")) + + now = int(time.time()) + with transaction(qa_conn): + # Record the repair event BEFORE the providence_query event so + # the audit chain shows: repair-happened, THEN we wrote the + # final record. Repair body links pre→post verdicts so an + # auditor can reconstruct what changed. + if repair_changes and pre_repair_verdict is not None: + append_audit( + qa_conn, + event_type="providence_repair", + subject_root=ckey, + body={ + "kind": "mechanical", + "n_changes": len(repair_changes), + "changes": repair_changes, + "pre_audit_mode": pre_repair_verdict["audit_mode"], + "post_audit_mode": verdict["audit_mode"], + "pre_n_verified": pre_repair_verdict["n_verified"], + "post_n_verified": verdict["n_verified"], + }, + ts=now, + ) + event_hash = append_audit( + qa_conn, + event_type="providence_query", + subject_root=ckey, + body={ + "context_root": context_root, + "n_sources": len(chosen), + "model_id": model_id, + "revision": revision, + "quantization": quantization, + "answer_chars": len(answer_text), + "context_chars": len(context), + "audit_mode": verdict["audit_mode"], + "n_quotes": verdict["n_quotes"], + "n_verified": verdict["n_verified"], + "verifier_method": verdict["verifier_method"], + }, + ts=now, + ) + qa_conn.execute( + "INSERT INTO providence_cache " + "(cache_key, source_root, document_uri, question_hash, question_text, " + " answer_text, merkle_proof, model_profile_hash, conversation_hash, " + " governance_policy_hash, schema_version, canonicalization_version, " + " chunking_version, falsification_state, chain, audit_event_hash, " + " created_at, hit_count, audit_mode, n_quotes, n_verified, " + " unverified_quotes, verifier_method, run_dag_root, run_dag_blob) " + "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 'live', ?, ?, ?, 0, " + " ?, ?, ?, ?, ?, ?, ?)", + ( + ckey, + context_root, + "corpus://multi-source", + qhash, + question, + answer_text, + proof_blob, + mhash, + chash, + ghash, + SCHEMA_VERSION, + CANONICALIZATION_VERSION, + CHUNKING_VERSION, + chain, + event_hash, + now, + verdict["audit_mode"], + verdict["n_quotes"], + verdict["n_verified"], + unverified_blob, + verdict["verifier_method"], + run_dag["root"], + run_dag_blob, + ), + ) + finally: + qa_conn.close() + + persist_ms = _ms_since(t_phase) + # Pull the verify node's failure_stage out of the run_dag for the result. + failure_stage = next( + (n.get("hash") for n in run_dag["nodes"] if n["stage"] == "verify"), + None, + ) + # The actual label is in the verify_payload, which we computed in + # localize_failure earlier — recompute for the result dict. + from aborist.qa.dag import localize_failure as _localize + failure_stage = _localize( + audit_mode=verdict["audit_mode"], + n_sources=len(chosen), + n_quotes=verdict["n_quotes"], + n_verified=verdict["n_verified"], + ) + return { + "status": "cache_miss_then_written", + "audit_mode": verdict["audit_mode"], + "cache_key": ckey, + "run_dag_root": run_dag["root"], + "lookup_path": "miss", + "failure_stage": failure_stage, + "repair_changes": repair_changes, + "pre_repair_audit_mode": ( + pre_repair_verdict["audit_mode"] if pre_repair_verdict else None + ), + "burned_existing": burned_existing, + "context_root": context_root, + "answer_text": answer_text, + "sources": proof_obj["sources"], + "n_quotes": verdict["n_quotes"], + "n_verified": verdict["n_verified"], + "verifier_method": verdict["verifier_method"], + "unverified_quotes": verdict["unverified_quotes"], + "partially_verified_quotes": verdict.get("partially_verified_quotes") or [], + # Violations (per-claim hard-check failures + soft demotes + # like LAZY_ANCHOR_DEMOTE / WARRANT_MISSING). Surfaced so the + # CLI render can name WHY a verdict capped at HYBRID instead + # of reaching STRICT. Persisted into run_dag_blob via the + # verify stage's payload. + "violations": verdict.get("violations") or [], + # Format-collapse signal (pointer-mode only — None elsewhere). + # True when the model emitted ≥5 meaningful prose lines with + # zero `[E\d+]` pointer tags, i.e. abandoned the + # claim_lattice_pointer protocol entirely. Surfaced on the + # result dict so bench harness can measure FC rate without + # re-deriving it from raw_answer (which is lattice-only). + # See verify.py:format_collapsed and ticket #000008. + "format_collapsed": verdict.get("format_collapsed"), + # Model's raw output before the renderer interpolates literal + # spans. Lattice modes only — quote/span/entity/paraphrase + # rows have answer_text == raw_answer so this stays None to + # avoid duplication. Bench reads it for bracket-count + # diagnostics; never persisted in providence_cache. + "raw_answer": raw_answer if is_lattice_mode else None, + # Quantifier preflight result (Ticket #000008 Phase 1). + # Surfaced on the result so bench rows pick it up. Phase 1 + # is dry-run only — caps not applied; Phase 2 wires + # `claim_cap_applied`. None semantics: classifier always + # returns a dict so these are never None on the miss path, + # but the cache-hit path (line ~2080) doesn't carry them + # since the cached record predates the classifier. + "quantifier_intensity": quantifier["intensity"], + "quantifier_matched_token": quantifier["matched_token"], + "scope_bound_hint": quantifier["scope_bound_hint"], + "quantifier_explicit_count": quantifier["explicit_count"], + # Cap that was looked up for this run. NULL semantics: + # None → guard off, mode opted out, or classifier + # returned no intensity (no cap recorded). + # int → cap that WOULD apply to the verifier when + # quantifier_guard_apply_caps=True. Reported on + # dry-run rows so bench can chart cap distribution + # before the gate flips. + # Phase 2 dry-run: cap is REPORTED but not APPLIED to the + # verifier — claim_lattice_max_claims_per_answer (default + # 12) still drives TOO_MANY_CLAIMS demote until + # quantifier_guard_apply_caps flips True. + "claim_cap_applied": claim_cap_lookup, + # Ticket #000010 — meta-cognition QuestionState. Surfaces + # the full preflight classification (logical_statuses, + # question_shape, contradiction_pairs, false_premise_hints, + # temporal_sensitivity, etc.) for bench / CLI render. First + # pass does NOT bind into run_dag_root (deferred to ticket + # #000009 Phase 5). + "question_state": question_state.to_dict(), + # Ticket #000009 §7.2 — preflight stage hash. Surfaced + # for cross-row preflight-policy comparison in bench / + # operator tools. Same hash that's bound into the + # `preflight` stage of run_dag_root. + "preflight_hash": preflight_hash, + # Ticket #000011 — soft preflight sidecar hint. Advisory + # only; NEVER enters the verifier proof path. Renderer + # surfaces as `· soft: <label>` on the audit-line tail. + "soft_preflight_hint": soft_hint.to_dict(), + # Sidecar smell signals (claim_lattice mode only) — surfaced + # for the renderer; never persisted in providence_cache and + # never threaded into run_dag_root. + "pointer_id_distribution": verdict.get("pointer_id_distribution"), + "lazy_anchor_ratio": verdict.get("lazy_anchor_ratio"), + # Retrieval-purity sidecar (claim_lattice modes; None for + # quote/span/entity/paraphrase). Render-layer + bench-tracking + # metric: surfaces "model ignored N noisy sources, used the + # primary at rank R" without folding into the proof path. + "retrieval_purity": proof_obj.get("retrieval_purity"), + "prompt_chars": prompt_chars, + "answer_chars": len(answer_text or ""), + # Frame detection (Ticket #000002 / Module L). Sidecar signal + # for renderer / bench; never persisted in providence_cache, + # never enters governance_policy_hash. None for quote-mode + # rows; populated for lattice-mode rows. + "frame_detection": ( + { + "kind": frame_detection.frame_kind, + "reference_title": frame_detection.reference_title, + "reference_uri": frame_detection.reference_uri, + "confidence": frame_detection.confidence, + } + if frame_detection is not None + else None + ), + "timings": { + "preflight_ms": preflight_ms, + "soft_preflight_ms": soft_preflight_ms, + "search_ms": search_ms, + "context_ms": context_ms, + "cache_lookup_ms": cache_lookup_ms, + "llm_ms": llm_ms, + "persist_ms": persist_ms, + "total_ms": _ms_since(t_start), + }, + }
+ + + +def _ms_since(t: float) -> float: + """Wall-time elapsed in milliseconds, rounded to 1 decimal.""" + return round((time.monotonic() - t) * 1000, 1) +
+
+
+
+ + +
+
+ + Made with Sphinx and @pradyunsg's + + Furo + +
+
+ +
+
+ +
+
+ +
+
+ + + + + \ No newline at end of file diff --git a/docs/_source/_build/html/_modules/aborist/qa/runner.html b/docs/_source/_build/html/_modules/aborist/qa/runner.html new file mode 100644 index 0000000..d77cdb6 --- /dev/null +++ b/docs/_source/_build/html/_modules/aborist/qa/runner.html @@ -0,0 +1,1348 @@ + + + + + + + + aborist.qa.runner - Aborist API Reference + + + + + + + + + + + + + + + + Contents + + + + + + Menu + + + + + + + + Expand + + + + + + Light mode + + + + + + + + + + + + + + Dark mode + + + + + + + Auto light/dark, in light mode + + + + + + + + + + + + + + + Auto light/dark, in dark mode + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Skip to content + + + +
+
+
+ +
+ +
+
+ +
+ +
+
+ +
+
+
+ + + + + Back to top + +
+
+ +
+ +
+
+

Source code for aborist.qa.runner

+"""Q&A runner: cache-first lookup -> inference fallback -> provable record.
+
+Implements the v9.8 admissibility invariant:
+    No record reused unless all 8 cache_key dimensions match AND state
+    is 'live' (not failed/stale/quarantined).
+
+Cache hit  -> persisted audit_mode (STRICT/HYBRID/UNGROUNDED).
+Cache miss -> call ChatClient, run faithfulness check, classify, store
+              record, audit event.
+"""
+
+from __future__ import annotations
+
+import json
+import sqlite3
+import time
+
+from aborist import (
+    CANONICALIZATION_VERSION,
+    SCHEMA_VERSION,
+)
+from aborist.compress import unpack_chunk
+from aborist.merkle import MerkleTree, proof_to_dict
+from aborist.qa.client import ChatClient
+from aborist.qa.prompts import (
+    CLAIM_LATTICE_GROUNDING_REMINDER,
+    CLAIM_LATTICE_JSON_GROUNDING_REMINDER,
+    CLAIM_LATTICE_JSON_SYSTEM_PROMPT,
+    CLAIM_LATTICE_SYSTEM_PROMPT,
+)
+from aborist.qa.keys import (
+    DEFAULT_FIDELITY,
+    DEFAULT_QUESTION_DEDUP,
+    FIDELITY_MODES,
+    QUESTION_DEDUP_MODES,
+    cache_key,
+    canonical_question,
+    conversation_hash,
+    governance_policy_hash,
+    model_profile_hash,
+    question_hash,
+    verifier_policy_hash,
+)
+from aborist.qa.dag import build_run_dag
+from aborist.qa.evidence import (
+    build_evidence_map,
+    evidence_map_root,
+    render_evidence_map,
+    render_evidence_map_for_json,
+)
+from aborist.qa.repair import mechanical_repair, reprompt_repair
+from aborist.qa.verify import (
+    ANSWER_MODES,
+    CLAIM_LATTICE_JSON_SCHEMA,
+    DEFAULT_ANSWER_MODE,
+    verify_claim_lattice,
+    verify_claim_lattice_json,
+    verify_quotes,
+)
+from aborist.store import append_audit, transaction
+
+try:
+    from aborist.wikitext import BASE_VERSION as _WIKITEXT_BASE_VERSION
+    from aborist.wikitext import to_base as _wikitext_to_base
+except ImportError:  # pragma: no cover
+    _WIKITEXT_BASE_VERSION = None
+    _wikitext_to_base = None
+
+
+DEFAULT_POLICY = {
+    # Ticket #000007 — query-layer hyphen-fold marker. See
+    # aborist/qa/query.py:DEFAULT_QUERY_POLICY for rationale.
+    "hyphen_fold_v1": True,
+    # Ticket #000006 amend 2026-05-02b (Rule 9). See
+    # aborist/qa/query.py:DEFAULT_QUERY_POLICY for full rationale.
+    "claim_lattice_subject_tokens_absent_threshold": 3,
+    "system_prompt": (
+        "Answer the user's question based ONLY on the document below. "
+        "For EVERY factual claim, include a verbatim quote from the "
+        "document enclosed in double quotes (\"...\"). The quoted span "
+        "must appear word-for-word. Make a claim only when a verbatim "
+        "quote in the document directly supports it. "
+        "If the answer is in the document, write it. "
+        "If the answer is absent from the document, say 'I don't know "
+        "based on the provided document.' and stop there. "
+        "Stay inside the document at all times."
+    ),
+    # Restated rule fired as a user message right before the document +
+    # question arrive. See aborist/qa/query.py for the rationale (recent
+    # user-turn instructions outweigh decayed system-turn rules in 8B
+    # instruction-tuned models).
+    "grounding_reminder": (
+        "REMINDER: wrap every factual claim in double quotes (\"...\") "
+        "and the quoted span must appear word-for-word in the "
+        "document. Each claim earns a verbatim quote. "
+        "Now answer the question on the next message."
+    ),
+    "temperature": 0.1,
+    "top_p": 1.0,
+    "max_tokens": 512,
+    "entity_policy": "proximity",
+    "entity_proximity_n": 3,
+    "entity_proximity_window": 300,
+    # Mechanical answer repair after first verify. Off by default; see
+    # aborist/qa/query.py for semantics.
+    "repair_enabled": False,
+    "repair_max_reprompts": 0,
+    # Strip wikitext markup before the LLM ever sees the context. Lets
+    # Hermes quote prose verbatim and shrinks token bills (~43% on
+    # Wikipedia chunks). Bumps governance_policy_hash so prior cached
+    # answers under raw-wikitext policy stay distinct on lookup. Set
+    # via the wikitext extras; no-op if mwparserfromhell isn't installed.
+    "base_version": _WIKITEXT_BASE_VERSION,
+    # G0 / CTI — claim-lattice-pointer answer mode. "quote" (default):
+    # existing behavior, model writes prose with verbatim quotes inline.
+    # "claim_lattice_pointer": runtime builds an evidence map and shows
+    # the model short pointer ids (E1, E2, …); model writes natural
+    # prose with bracket pointer tags ("Claim. [E12]") instead of
+    # quoting source text. Renderer interpolates literal spans at
+    # display time. Synthetic-elision-by-construction-impossible: the
+    # model never types the quote string. Two-layer id discipline keeps
+    # the cache & run-DAG keyed on content-addressed evidence_ids.
+    # Folds into governance_policy_hash so two modes write under
+    # different cache_keys and never alias. No iterative repair in
+    # pointer mode (one-shot benchmark discipline).
+    "answer_mode": DEFAULT_ANSWER_MODE,
+    "claim_lattice_system_prompt": CLAIM_LATTICE_SYSTEM_PROMPT,
+    "claim_lattice_grounding_reminder": CLAIM_LATTICE_GROUNDING_REMINDER,
+    # Allowed source roles for claim-lattice verification. Roles outside
+    # this set get classified SOURCE_ROLE_BLOCKED and downgrade the
+    # verdict. Mirrors aborist.qa.verify.DEFAULT_ALLOWED_SOURCE_ROLES;
+    # noisy_background_source / sequel_background_source are excluded by
+    # default. Folds into governance_policy_hash on change.
+    "claim_lattice_allowed_source_roles": [
+        "primary_answer_source",
+        "secondary_context_source",
+        "background_source",
+        "unclassified",
+        # Self-promoted providence records (`aborist://providence/`
+        # URI scheme). Trusted-as-fact substrate per the
+        # self-reference design — STRICT live records past the
+        # kindergarten window. See
+        # docs/self-reference-design.md for the
+        # falsification trust model.
+        "self_reference_source",
+    ],
+    # Hard cap on pointer ids per claim line — mirrors prompt Rule 9.
+    # Lines exceeding this cap classify as SCHEMA_INVALID and the
+    # verdict can no longer reach STRICT. Folds into
+    # governance_policy_hash so changing the cap invalidates prior
+    # cached records.
+    "claim_lattice_max_pointers_per_claim": 2,
+    # Minimum claim-token coverage required for the citation-overlap
+    # check (Rule 6) to pass. Pre-2026-04-30 the threshold was implicit
+    # at "≥1 shared token", which let through lazy-anchored claims
+    # whose only overlap was a single topical word (e.g. "Yale
+    # University... [E9]" cited to a highway-data span containing only
+    # "Connecticut"). 0.30 means a 10-token claim needs ≥3 of its
+    # content tokens to appear in the cited span. Short claims (≤3
+    # content tokens) keep the old ≥1-token floor so narrow factoids
+    # like "Steve Jobs co-founded Apple" still pass. Folds into
+    # governance_policy_hash on change.
+    "claim_lattice_min_citation_coverage": 0.30,
+    # Bare-name claim guard. A claim with fewer than this many content
+    # tokens (>=4 chars, post-spotlight-stopword) is rejected as
+    # SCHEMA_INVALID. Catches the JP-dinosaurs lazy-anchor where
+    # "Triceratops. [E16]" passes lexical overlap on a single token
+    # even when E16 is a video-game tie-in chunk rather than the film
+    # article. Default 2: bare-entity-name claims (one content token
+    # after stopword strip) fail; sentence-shape claims pass. Note
+    # ``_content_tokens`` already filters "appears", "shown", etc. so
+    # "Trex appears" → 1 content token (filtered), "Trex appears in
+    # the film" → 2 content tokens (passes). Folds into
+    # governance_policy_hash on change.
+    "claim_lattice_min_claim_content_tokens": 2,
+    # Lazy-anchor smell auto-demote. When >= threshold of verified
+    # pointer-pairs cite a single pointer AND there are >= min_pairs
+    # total, cap audit_mode at HYBRID. The smell sidecar was advisory
+    # only pre-2026-04-30; now it's load-bearing. STRICT requires
+    # diverse anchoring across pointers.
+    "claim_lattice_lazy_anchor_demote_threshold": 0.5,
+    "claim_lattice_lazy_anchor_demote_min_pairs": 3,
+    # Warrant-lite — relation-question hard check (Ticket H from
+    # feedback-3, 2026-05-01). Detects relation-shape questions
+    # ("who is X's boss?", "who founded Y?") and requires the cited
+    # span to contain at least one named answer entity (proper-noun
+    # phrase) from the claim. Catches the Homer-Simpson lazy-anchor
+    # case where claim asserts "Mr. Burns" but cited span is the
+    # voice-actor bio. WARRANT_MISSING violations cap audit_mode
+    # at HYBRID. See aborist/qa/warrant.py.
+    "claim_lattice_warrant_check_enabled": True,
+    "claim_lattice_deflection_check_enabled": True,
+    # Format-collapse check (pointer-mode only): when the model emits
+    # ≥5 meaningful prose lines with zero `[E\d+]` pointer tags, it
+    # abandoned the claim_lattice_pointer protocol entirely. Soft-demote
+    # so audit display surfaces "format collapsed" vs "graceful per-
+    # claim refusal" — different failure shapes, same UNGROUNDED rung.
+    # JSON-mode collapse already shows up as SCHEMA_INVALID so this
+    # check is redundant there. Surfaced 2026-05-02 by fox's "Winners
+    # of all major sports?" case where Hermes dumped 50+ free-form
+    # sentences.
+    "claim_lattice_format_collapse_check_enabled": True,
+    # Quantifier preflight guard (Ticket #000008 Phase 2). Per-call
+    # claim cap derived from the question's quantifier intensity and
+    # the configured model profile (aborist/qa/model_profiles.py).
+    # Phase 2 lands the lookup wiring with apply_caps=False per
+    # §10.11.3 dry-run discipline — claim_cap_applied is computed
+    # and reported on the result dict, but the verifier still uses
+    # claim_lattice_max_claims_per_answer as the actual cap.
+    # Operator flips quantifier_guard_apply_caps=True after dry-run
+    # bench review confirms classifier output across the full
+    # question set.
+    #
+    # Six-level disable hierarchy (§10.11.2):
+    #   - quantifier_guard_enabled: master kill (False = no
+    #     classifier output, no cap lookup, no telemetry).
+    #   - quantifier_guard_apply_caps: dry-run gate (True = cap
+    #     applied; False = cap reported but not applied).
+    #   - quantifier_caps_by_intensity: per-call override dict;
+    #     wins over the model_profiles.py table when present.
+    #   - quantifier_guard_modes: list of answer_modes the guard
+    #     applies to. Quote mode opts out by default — already
+    #     stable HYBRID 0.455 on baseline, different failure shape.
+    "quantifier_guard_enabled": True,
+    "quantifier_guard_apply_caps": False,
+    # When apply_caps flips True, this allowlist gates which modes
+    # actually have caps applied. n=5 verification 2026-05-03 (#000008
+    # §12.10): cap on claim_lattice (JSON) wins +14pp on STRICT-rate;
+    # cap on claim_lattice_pointer fires TOO_MANY_CLAIMS 20× without
+    # moving the verdict floor (still 0 STRICT). Default to JSON only
+    # so flipping the master switch doesn't add wasted cap-noise on
+    # pointer mode. Empty list / None = honor quantifier_guard_modes
+    # (legacy fallback).
+    "quantifier_apply_caps_modes": ["claim_lattice"],
+    "quantifier_caps_by_intensity": {},
+    "quantifier_guard_modes": ["claim_lattice_pointer", "claim_lattice"],
+    # Phase 3 — broad-quantifier reminder injection. Default ON for
+    # lattice modes (gated via quantifier_guard_modes) per the
+    # 2026-05-03 bench A/B (#000008 §12). Reminder eliminates
+    # FORMAT_COLLAPSED (2→0), reduces NO_EVIDENCE_POINTER 33%,
+    # boosts mean ratio +17pp on pointer / +21pp on JSON, and
+    # rescues JSON UNGROUNDED 7→1. n=5 verification 2026-05-03
+    # confirms the compound effect with cap survives at higher
+    # sample size. Quote mode is mode-gated off (different failure
+    # shape; paraphrase verifier doesn't need pointer-tag reminders).
+    "quantifier_reminder_enabled": True,
+    # Phase 4 — strict reject for broad-unbounded queries. When True
+    # AND intensity ∈ {ALL, COMPREHENSIVE, OPEN_REQUEST} AND
+    # scope_bound_hint == "unbounded", query()/ask() return UNGROUNDED
+    # before the LLM call with a BROAD_QUANTIFIER_REJECTED violation.
+    # Saves the ~10-15s LLM call on rejected runs. Default OFF — opt-in
+    # via --reject-broad CLI flag or per-call policy override.
+    # Bounded universals (e.g. all members of the Beatles, year-anchored
+    # questions) are NOT rejected per §10.1.
+    "quantifier_reject_broad": False,
+    # Ticket #000010 — Meta-Cognition Preflight Guard (M0 / MCTL).
+    # Pure deterministic detectors (temporal, contradiction,
+    # false-premise-lite, out-of-corpus) wrap the #000008 quantifier
+    # classifier and surface a QuestionState on the result dict.
+    # Master switch ON by default — detectors are pure-on-question
+    # so cost is negligible. Each sub-detector has its own enable
+    # switch for granular A/B. block_on_contradiction defaults False
+    # (label-only by default; opt-in to hard-block — false-positive
+    # rate not yet bench-validated).
+    "metacognition_enabled": True,
+    "metacognition_temporal_check": True,
+    "metacognition_contradiction_check": True,
+    "metacognition_false_premise_check": True,
+    "metacognition_out_of_corpus_check": True,
+    "metacognition_block_on_contradiction": False,
+    # Ticket #000011 — soft preflight sidecar. Default OFF —
+    # adds one short LLM round-trip (~200ms median) so cost is
+    # operator-opt-in only. NEVER enters the verifier proof path
+    # (D1); produces only SOFT_* labels that surface as advisory
+    # hints alongside the deterministic detector output.
+    "soft_preflight_enabled": False,
+    # Claim-count ceiling. Bench finding (2026-04-30 york-england):
+    # "tell me all there is to know about X" prompted Hermes to spam
+    # 26-59 encyclopedic claims sourced from training, only 2-4 of
+    # which grounded in retrieval. Atomic-claim prompt rule (b5925c8)
+    # cut this to ~10, but a hard structural cap is defense in depth.
+    # Cap of 12 admits typical entity-list questions (5-7 dinosaurs,
+    # Simpsons + pets) while flagging the runaway shape. Folds into
+    # governance_policy_hash on change.
+    "claim_lattice_max_claims_per_answer": 12,
+    # JSON variant — `answer_mode="claim_lattice"`. Mirrors the
+    # multi-source query path. Pairs with grammar-constrained inference
+    # (vLLM guided_json, Claude/GPT-4 native JSON, Qwen 3.6 reasoner).
+    # Lenient pre-parser in verify_claim_lattice_json keeps the path
+    # survivable on inference paths without grammar guidance.
+    "claim_lattice_json_system_prompt": CLAIM_LATTICE_JSON_SYSTEM_PROMPT,
+    "claim_lattice_json_grounding_reminder": CLAIM_LATTICE_JSON_GROUNDING_REMINDER,
+    "claim_lattice_use_guided_json": True,
+    # JSON-mode stop sequences. Hermes-3-8B sometimes spams whitespace
+    # / newlines after the closing brace on broad-descriptive shapes
+    # ("plot of X", "tell me about Y") — the response runs out the
+    # max_tokens budget and the lenient parser sees truncated JSON.
+    # Stopping on a blank line cuts the runaway. JSON-mode output
+    # never legitimately contains a blank line (single object, single
+    # line) so this is a safe filter. Folds into
+    # governance_policy_hash on change.
+    "claim_lattice_json_stop_sequences": ["\n\n"],
+}
+
+
+def _ms_since(t: float) -> float:
+    return round((time.monotonic() - t) * 1000, 1)
+
+
+
+[docs] +def ask( + conn: sqlite3.Connection, + *, + document_root: str, + question: str, + client: ChatClient, + model_id: str, + revision: str = "", + quantization: str = "", + policy: dict | None = None, + chain: str = "private", + fidelity: str | None = None, +) -> dict: + """Look up cached answer or run inference. Returns a result dict. + + See ``aborist.qa.query.query`` for `fidelity` semantics — it + controls lookup tolerance: ``"strict"`` only checks the cache_key + matching the call's ``policy["question_dedup"]``; the default + ``"equivalence_class"`` falls back to the alternate dedup mode's + cache_key on miss so a fast-cache agent can reuse records written + under either mode. Result includes ``lookup_path``. + """ + policy = policy or DEFAULT_POLICY + if fidelity is None: + fidelity = policy.get("fidelity", DEFAULT_FIDELITY) + if fidelity not in FIDELITY_MODES: + raise ValueError( + f"fidelity must be one of {FIDELITY_MODES}, got {fidelity!r}" + ) + # Quantifier preflight (Ticket #000008 Phase 1+2). Same wiring + # as query() — see aborist/qa/query.py for the rationale and + # disable hierarchy. + from aborist.qa.model_profiles import cap_for_intensity + from aborist.qa.quantifier import classify_question_quantifier + answer_mode_for_guard = policy.get("answer_mode", "quote") + quantifier_guard_on = bool(policy.get("quantifier_guard_enabled", True)) + quantifier_guard_modes = policy.get( + "quantifier_guard_modes", + ["claim_lattice_pointer", "claim_lattice"], + ) + quantifier_mode_gated = answer_mode_for_guard in (quantifier_guard_modes or []) + if quantifier_guard_on: + quantifier = classify_question_quantifier(question) + else: + quantifier = { + "intensity": None, + "matched_token": None, + "explicit_count": None, + "is_broad": False, + "operational_shape": None, + "scope_bound_hint": "unknown", + "classifier_version": None, + } + if quantifier_guard_on and quantifier_mode_gated and quantifier["intensity"]: + claim_cap_lookup = cap_for_intensity( + model_profile_id=model_id, + intensity=quantifier["intensity"], + explicit_count=quantifier["explicit_count"], + policy_overrides=policy.get("quantifier_caps_by_intensity") or None, + ) + else: + claim_cap_lookup = None + quantifier_apply_caps = bool(policy.get("quantifier_guard_apply_caps", False)) + quantifier_apply_caps_modes = policy.get( + "quantifier_apply_caps_modes", + quantifier_guard_modes, # legacy fallback + ) or quantifier_guard_modes + quantifier_caps_mode_gated = answer_mode_for_guard in ( + quantifier_apply_caps_modes or [] + ) + _policy_max_claims = int(policy.get("claim_lattice_max_claims_per_answer", 12)) + if ( + quantifier_apply_caps + and quantifier_caps_mode_gated + and claim_cap_lookup is not None + ): + effective_max_claims = int(claim_cap_lookup) + else: + effective_max_claims = _policy_max_claims + # Ticket #000010 — meta-cognition preflight (mirror of query()). + from aborist.qa.metacognition import preflight_question + question_state = preflight_question( + question, + model_profile_id=model_id, + reference_frames=(), + policy=policy, + ) + t_start = time.monotonic() + + doc = conn.execute( + "SELECT document_uri, chunking_version FROM documents " + "WHERE document_root = ?", + (document_root,), + ).fetchone() + if doc is None: + return {"status": "unknown_document"} + + chunk_rows = conn.execute( + "SELECT idx, leaf_hash, content FROM chunks " + "WHERE document_root = ? ORDER BY idx ASC", + (document_root,), + ).fetchall() + if not chunk_rows: + return {"status": "unknown_document"} + if any(r["content"] is None for r in chunk_rows): + return {"status": "source_cold", "msg": "rehydrate before asking"} + + answer_mode = policy.get("answer_mode", DEFAULT_ANSWER_MODE) + if answer_mode not in ANSWER_MODES: + raise ValueError( + f"policy['answer_mode'] must be one of {ANSWER_MODES}, got {answer_mode!r}" + ) + + chunk_texts = [unpack_chunk(r["content"]) for r in chunk_rows] + document_text = "\n\n".join(chunk_texts) + + # Wikitext → prose before the LLM sees it. The model can then quote + # verbatim against the prose form; the verifier compares like-against- + # like. Idempotent if context is already plain prose. Gated on + # policy["base_version"] so this is part of governance_policy_hash. + if policy.get("base_version") and _wikitext_to_base is not None: + document_text = _wikitext_to_base(document_text) + chunk_texts = [_wikitext_to_base(t) for t in chunk_texts] + + evidence_map = [] + if answer_mode == "claim_lattice_pointer": + # Quote-by-pointer: one evidence object per chunk. The model sees + # the literal spans labeled with content-addressed IDs and is + # instructed to reference IDs, not type quote text. Synthetic + # elision is impossible by construction — the model never produces + # the quote string. + chunks_for_map = [ + { + "source_root": document_root, + "document_uri": doc["document_uri"], + "title": None, + "chunk_idx": r["idx"], + "chunk_root": r["leaf_hash"], + "span": chunk_texts[i], + "source_role": "primary_answer_source", + } + for i, r in enumerate(chunk_rows) + ] + evidence_map = build_evidence_map(chunks_for_map) + sys_prompt = policy["claim_lattice_system_prompt"] + grounding_reminder = policy.get("claim_lattice_grounding_reminder") + rendered_evidence = render_evidence_map(evidence_map) + + def _user_payload(q: str) -> str: + return f"EVIDENCE:\n\n{rendered_evidence}\n\n---\n\nQUESTION: {q}" + elif answer_mode == "claim_lattice": + # JSON variant — same per-chunk evidence map as pointer mode, + # blocks labeled with content-addressed evidence_id (long hex) + # since the model emits IDs in JSON. Pairs with grammar- + # constrained inference; lenient pre-parser handles drift. + chunks_for_map = [ + { + "source_root": document_root, + "document_uri": doc["document_uri"], + "title": None, + "chunk_idx": r["idx"], + "chunk_root": r["leaf_hash"], + "span": chunk_texts[i], + "source_role": "primary_answer_source", + } + for i, r in enumerate(chunk_rows) + ] + evidence_map = build_evidence_map(chunks_for_map) + sys_prompt = policy.get( + "claim_lattice_json_system_prompt", + policy["claim_lattice_system_prompt"], + ) + grounding_reminder = policy.get( + "claim_lattice_json_grounding_reminder", + policy.get("claim_lattice_grounding_reminder"), + ) + rendered_evidence = render_evidence_map_for_json(evidence_map) + + def _user_payload(q: str) -> str: + return f"EVIDENCE:\n\n{rendered_evidence}\n\n---\n\nQUESTION: {q}" + else: + sys_prompt = policy["system_prompt"] + grounding_reminder = policy.get("grounding_reminder") + + def _user_payload(q: str) -> str: + return f"Document:\n\n{document_text}\n\n---\n\nQuestion: {q}" + + # System sets the policy; a user-turn reminder restates the rule one + # message before the payload arrives. Payload (document or evidence + # map + question) lands last as the most-recent tokens before + # generation. + messages = [{"role": "system", "content": sys_prompt}] + if grounding_reminder: + messages.append({"role": "user", "content": grounding_reminder}) + # Quantifier-specific reminder (Ticket #000008 Phase 3, default + # off). When the question is broad (ALL/COMPREHENSIVE/OPEN_ + # REQUEST) and the operator opted in via + # quantifier_reminder_enabled=True, append a one-line reminder + # restating the cap and the no-prior-enumeration rule. + # quantifier_reminder_enabled defaults to False because Hermes-3-8B + # already ignores parts of the existing reminder under enumeration + # pressure (§3 Option B con); empirical effect requires bench + # measurement before flipping default-on (§10.8 decision tree). + if ( + quantifier_guard_on + and quantifier_mode_gated + and quantifier.get("is_broad") + and bool(policy.get("quantifier_reminder_enabled", False)) + ): + from aborist.qa.quantifier_reminder import broad_quantifier_reminder + broad = broad_quantifier_reminder( + intensity=quantifier["intensity"], + cap=effective_max_claims, + scope_bound_hint=quantifier["scope_bound_hint"], + ) + if broad: + messages.append({"role": "user", "content": broad}) + messages.append({"role": "user", "content": _user_payload(question)}) + + mhash = model_profile_hash(model_id, revision, quantization) + + # Dedup-mode-aware cache_key. See aborist/qa/query.py for rationale — + # policy_variant matches the alternate mode so governance_policy_hash + # agrees with what an agent under that mode would have written, + # enabling cross-silo fallback. + def _ckey_for_mode(mode: str) -> str: + canon_q = canonical_question(question, mode=mode) + canon_msgs = list(messages[:-1]) + [ + {"role": "user", "content": _user_payload(canon_q)}, + ] + policy_variant = dict(policy, question_dedup=mode) + return cache_key( + document_root, + question_hash(question, mode=mode), + mhash, + conversation_hash(canon_msgs), + governance_policy_hash(policy_variant), + SCHEMA_VERSION, + CANONICALIZATION_VERSION, + doc["chunking_version"], + verifier_policy_hash(policy_variant), + ) + + ghash = governance_policy_hash(policy) # for the legacy INSERT below + + primary_dedup = policy.get("question_dedup", DEFAULT_QUESTION_DEDUP) + if primary_dedup not in QUESTION_DEDUP_MODES: + raise ValueError( + f"policy['question_dedup'] must be one of {QUESTION_DEDUP_MODES}, " + f"got {primary_dedup!r}" + ) + # Re-derive the per-mode hashes for use in the INSERT below. _ckey_for_mode + # already builds them, but the legacy INSERT references qhash/chash by name. + qhash = question_hash(question, mode=primary_dedup) + canonical_q_primary = canonical_question(question, mode=primary_dedup) + canonical_messages_primary = list(messages[:-1]) + [ + {"role": "user", "content": _user_payload(canonical_q_primary)}, + ] + chash = conversation_hash(canonical_messages_primary) + primary_ckey = _ckey_for_mode(primary_dedup) + ckey = primary_ckey # legacy name for the rest of the function + + t_lookup = time.monotonic() + cached = conn.execute( + "SELECT * FROM providence_cache " + "WHERE cache_key = ? AND falsification_state = 'live'", + (primary_ckey,), + ).fetchone() + hit_ckey = primary_ckey + lookup_path = primary_dedup if cached is not None else None + if cached is None and fidelity == "equivalence_class": + other_mode = ( + "equivalence_class" if primary_dedup == "strict" else "strict" + ) + other_ckey = _ckey_for_mode(other_mode) + if other_ckey != primary_ckey: + cached = conn.execute( + "SELECT * FROM providence_cache " + "WHERE cache_key = ? AND falsification_state = 'live'", + (other_ckey,), + ).fetchone() + if cached is not None: + hit_ckey = other_ckey + lookup_path = f"{other_mode}_fallback" + cache_lookup_ms = _ms_since(t_lookup) + if cached is not None: + with transaction(conn): + now = int(time.time()) + conn.execute( + "UPDATE providence_cache " + "SET hit_count = hit_count + 1, last_hit_at = ? " + "WHERE cache_key = ?", + (now, hit_ckey), + ) + return { + "status": "cache_hit", + "audit_mode": cached["audit_mode"], + "cache_key": hit_ckey, + "lookup_path": lookup_path, + "source_root": document_root, + "answer_text": cached["answer_text"], + "merkle_proof": json.loads(cached["merkle_proof"]), + "n_quotes": cached["n_quotes"], + "n_verified": cached["n_verified"], + "verifier_method": cached["verifier_method"], + "unverified_quotes": ( + json.loads(cached["unverified_quotes"]) + if cached["unverified_quotes"] + else [] + ), + "partially_verified_quotes": [], + # Quantifier preflight (Ticket #000008 Phase 1+2). Pure + # on the question string, so cache hits re-classify + # cheaply and carry the same schema as miss-path rows. + "quantifier_intensity": quantifier["intensity"], + "quantifier_matched_token": quantifier["matched_token"], + "scope_bound_hint": quantifier["scope_bound_hint"], + "quantifier_explicit_count": quantifier["explicit_count"], + "claim_cap_applied": claim_cap_lookup, + # Ticket #000010 — meta-cognition QuestionState. + "question_state": question_state.to_dict(), + "timings": { + "cache_lookup_ms": cache_lookup_ms, + "llm_ms": None, + "total_ms": _ms_since(t_start), + }, + } + + t_llm = time.monotonic() + # JSON mode: pass guided_json schema so vLLM constrains output at + # sampling time. Endpoints without guided-decoding silently drop the + # field; the lenient pre-parser handles whatever drift remains. + extra_body: dict | None = None + stop_seqs: list[str] | None = None + if answer_mode == "claim_lattice" and policy.get( + "claim_lattice_use_guided_json", True + ): + extra_body = {"guided_json": CLAIM_LATTICE_JSON_SCHEMA} + if answer_mode == "claim_lattice": + # JSON-mode token-runaway guard. On broad-descriptive / + # comparison questions Hermes-3-8B sometimes spams whitespace + # / newlines after the closing brace until max_tokens + # exhausts; the resulting truncated payload won't parse and + # the run lands UNGROUNDED 0/0 at 12-15s instead of 2-4s. + # Stopping on a blank line (\n\n) cuts the runaway — + # well-formed JSON-mode output never contains a blank line + # since the model emits a single object on one line (or + # with simple internal newlines). + stop_seqs = list(policy.get( + "claim_lattice_json_stop_sequences", ["\n\n"] + )) + raw_answer = client.chat_completion( + messages, + model=model_id, + temperature=policy["temperature"], + max_tokens=policy["max_tokens"], + top_p=policy.get("top_p", 1.0), + extra_body=extra_body, + stop=stop_seqs, + ) + llm_ms = _ms_since(t_llm) + + repair_changes: list[dict] = [] + pre_repair_verdict: dict | None = None + + if answer_mode == "claim_lattice_pointer": + verdict = verify_claim_lattice( + raw_answer, + evidence_map, + allowed_source_roles=tuple( + policy.get( + "claim_lattice_allowed_source_roles", + [ + "primary_answer_source", + "secondary_context_source", + "background_source", + "unclassified", + ], + ) + ), + max_pointers_per_claim=int(policy.get( + "claim_lattice_max_pointers_per_claim", 2 + )), + min_citation_coverage=float(policy.get( + "claim_lattice_min_citation_coverage", 0.30 + )), + min_claim_content_tokens=int(policy.get( + "claim_lattice_min_claim_content_tokens", 3 + )), + lazy_anchor_demote_threshold=float(policy.get( + "claim_lattice_lazy_anchor_demote_threshold", 0.5 + )), + lazy_anchor_demote_min_pairs=int(policy.get( + "claim_lattice_lazy_anchor_demote_min_pairs", 3 + )), + max_claims_per_answer=effective_max_claims, + subject_tokens_absent_threshold=int(policy.get( + "claim_lattice_subject_tokens_absent_threshold", 3 + )), + question=question, + warrant_check_enabled=bool(policy.get( + "claim_lattice_warrant_check_enabled", True + )), + deflection_check_enabled=bool(policy.get( + "claim_lattice_deflection_check_enabled", True + )), + format_collapse_check_enabled=bool(policy.get( + "claim_lattice_format_collapse_check_enabled", True + )), + ) + # Rendered prose (literal spans interpolated) is the user-facing + # answer text — never the model's raw pointer-line output. If + # rendering produced nothing (no valid claims), persist the raw + # output so an operator can see what the model actually said. + rendered = verdict["rendered_text"] + answer_text = rendered if rendered else raw_answer + elif answer_mode == "claim_lattice": + verdict = verify_claim_lattice_json( + raw_answer, + evidence_map, + allowed_source_roles=tuple( + policy.get( + "claim_lattice_allowed_source_roles", + [ + "primary_answer_source", + "secondary_context_source", + "background_source", + "unclassified", + ], + ) + ), + max_evidence_per_claim=int(policy.get( + "claim_lattice_max_pointers_per_claim", 2 + )), + min_citation_coverage=float(policy.get( + "claim_lattice_min_citation_coverage", 0.30 + )), + max_claims_per_answer=effective_max_claims, + subject_tokens_absent_threshold=int(policy.get( + "claim_lattice_subject_tokens_absent_threshold", 3 + )), + question=question, + warrant_check_enabled=bool(policy.get( + "claim_lattice_warrant_check_enabled", True + )), + deflection_check_enabled=bool(policy.get( + "claim_lattice_deflection_check_enabled", True + )), + ) + rendered = verdict["rendered_text"] + answer_text = rendered if rendered else raw_answer + else: + answer_text = raw_answer + verdict = verify_quotes( + answer_text, + document_text, + entity_policy=policy.get("entity_policy", "hybrid"), + proximity_n=policy.get("entity_proximity_n", 3), + proximity_window=policy.get("entity_proximity_window", 300), + ) + + def _verify(text: str) -> dict: + return verify_quotes( + text, + document_text, + entity_policy=policy.get("entity_policy", "hybrid"), + proximity_n=policy.get("entity_proximity_n", 3), + proximity_window=policy.get("entity_proximity_window", 300), + ) + + if ( + policy.get("repair_enabled") + and verdict["audit_mode"] != "STRICT" + and verdict.get("unverified_quotes") + ): + repair_result = mechanical_repair( + answer_text, verdict["unverified_quotes"], document_text + ) + if repair_result["changes"]: + new_verdict = _verify(repair_result["repaired_text"]) + if new_verdict["n_verified"] >= verdict["n_verified"]: + pre_repair_verdict = verdict + answer_text = repair_result["repaired_text"] + verdict = new_verdict + repair_changes = list(repair_result["changes"]) + + max_reprompts = int(policy.get("repair_max_reprompts", 0)) + for _ in range(max_reprompts): + if ( + verdict["audit_mode"] == "STRICT" + or not verdict.get("unverified_quotes") + ): + break + new_text = reprompt_repair( + chat_client=client, + model_id=model_id, + original_messages=messages, + original_answer=answer_text, + failed_quotes=verdict["unverified_quotes"], + policy=policy, + ) + if not new_text: + break + new_verdict = _verify(new_text) + if new_verdict["n_verified"] > verdict["n_verified"]: + if pre_repair_verdict is None: + pre_repair_verdict = verdict + answer_text = new_text + verdict = new_verdict + repair_changes.append({ + "action": "reprompt_rewrite", + "diagnosis": "model_feedback_loop", + }) + else: + break + + unverified_blob = ( + json.dumps(verdict["unverified_quotes"], separators=(",", ":")) + if verdict["unverified_quotes"] + else None + ) + + leaves = [bytes.fromhex(r["leaf_hash"]) for r in chunk_rows] + tree = MerkleTree.build(leaves) + proof_obj = { + "document_root": document_root, + "chunk_0_proof": proof_to_dict(tree.proof(0)), + } + proof_blob = json.dumps(proof_obj, separators=(",", ":")) + + # Per-run Merkle-DAG (see aborist/qa/dag.py). Single-doc shape: + # the only "source" is document_root. Quote mode: 7 stages base + # (8 with #000009 preflight). Pointer mode: 9 stages base (10 with + # preflight); context drops out and answer splits into raw_answer + # / parsed_claim_lattice / render. + ev_root = evidence_map_root(evidence_map) if evidence_map else None + parsed_lattice = None + is_lattice_mode = answer_mode in ("claim_lattice_pointer", "claim_lattice") + if is_lattice_mode: + # Per-claim list of {claim_text, content-addressed evidence_ids} + # for the parsed_claim_lattice node hash. Pointer ids are + # run-dependent; evidence_ids are content-addressed → the run- + # DAG hashes the run-stable form. Same shape for JSON and + # pointer; verifier already returns evidence_id_pairs. + evidence_id_pairs = verdict.get("evidence_id_pairs") or [] + parsed_lattice = [ + { + "claim_text": cs.get("text", ""), + "evidence_ids": evidence_id_pairs[i] if i < len(evidence_id_pairs) else [], + } + for i, cs in enumerate(verdict.get("claim_statuses") or []) + ] + # Ticket #000009 — preflight node binding (mirror of query(); + # nested CTI clauses per ticket §8 / 2026-05-04 feedback). + from aborist.qa.dag import preflight_node_hash + # verifier_policy_hash + model_profile_hash imported at module + # top; do NOT re-import locally (free-variable shadowing). + ghash_for_dag = verifier_policy_hash(policy) + claim_cap_actually_applied = ( + claim_cap_lookup + if (quantifier_apply_caps + and quantifier_caps_mode_gated + and claim_cap_lookup is not None) + else None + ) + reminder_eligible = ( + quantifier_guard_on + and quantifier_mode_gated + and quantifier.get("is_broad", False) + ) + reminder_enabled = bool(policy.get("quantifier_reminder_enabled", False)) + reminder_injected = reminder_eligible and reminder_enabled + reminder_template_id = None + if reminder_injected: + reminder_template_id = ( + "broad-quantifier-bounded-v1" + if quantifier.get("scope_bound_hint") == "bounded" + else "broad-quantifier-unbounded-v1" + ) + # Build payload + hash separately so we can persist both into + # run_dag_blob (Ticket #000009 §7.2 — `aborist providence + # --show-preflight` renders the full clause set). + from aborist.qa.dag import ( + _canonical_json as _runner_canon, + _sha256_hex as _runner_sha, + build_preflight_node_payload as _runner_build_payload, + ) + _runner_preflight_payload = _runner_build_payload( + question_state=question_state.to_dict(), + quantifier=quantifier, + answer_contract={ + "guard_enabled": quantifier_guard_on, + "mode_gated": quantifier_mode_gated, + "apply_caps_active": quantifier_apply_caps, + "apply_caps_mode_gated": quantifier_caps_mode_gated, + "claim_cap_resolved": claim_cap_lookup, + "claim_cap_applied": claim_cap_actually_applied, + "manual_quotes_allowed": False, + "evidence_pointer_required": is_lattice_mode, + "allow_unbounded_enumeration": False, + "reject_broad_active": bool( + policy.get("quantifier_reject_broad", False) + ), + "metacognition_enabled": bool( + policy.get("metacognition_enabled", True) + ), + "block_on_contradiction": bool( + policy.get("metacognition_block_on_contradiction", False) + ), + }, + prompt_contract={ + "reminder_enabled": reminder_enabled, + "reminder_injected": reminder_injected, + "reminder_template_id": reminder_template_id, + }, + evidence_contract={ + "max_evidence_ids_exposed": int(policy.get( + "claim_lattice_max_pointers_per_claim", 2 + )), + "one_claim_per_line": is_lattice_mode, + }, + policy_refs={ + "governance_policy_hash": ghash_for_dag, + "model_profile_hash": mhash, + "answer_mode": answer_mode, + }, + ) + preflight_hash = _runner_sha(_runner_canon(_runner_preflight_payload)) + run_dag = build_run_dag( + question_hash=qhash, + sources=[{ + "document_root": document_root, + "source_role": "primary_answer_source", + "score": None, + "chunk_idx": None, + }], + context_root=document_root, + conversation_hash=chash, + answer_text=answer_text, + audit_mode=verdict["audit_mode"], + verifier_method=verdict["verifier_method"], + n_quotes=verdict["n_quotes"], + n_verified=verdict["n_verified"], + claim_statuses=verdict.get("claim_statuses", []), + lookup_path="miss", + evidence_map_root=ev_root, + answer_mode=answer_mode if answer_mode != "quote" else None, + violations=verdict.get("violations"), + raw_answer_text=raw_answer if is_lattice_mode else None, + parsed_lattice=parsed_lattice, + rendered_text=answer_text if is_lattice_mode else None, + preflight_hash=preflight_hash, + preflight_payload=_runner_preflight_payload, + ) + run_dag_blob = json.dumps(run_dag, separators=(",", ":")) + + now = int(time.time()) + with transaction(conn): + if repair_changes and pre_repair_verdict is not None: + append_audit( + conn, + event_type="providence_repair", + subject_root=ckey, + body={ + "kind": "mechanical", + "n_changes": len(repair_changes), + "changes": repair_changes, + "pre_audit_mode": pre_repair_verdict["audit_mode"], + "post_audit_mode": verdict["audit_mode"], + "pre_n_verified": pre_repair_verdict["n_verified"], + "post_n_verified": verdict["n_verified"], + }, + ts=now, + ) + event_hash = append_audit( + conn, + event_type="providence_write", + subject_root=ckey, + body={ + "source_root": document_root, + "model_id": model_id, + "revision": revision, + "quantization": quantization, + "chunks_in_context": len(chunk_rows), + "answer_chars": len(answer_text), + "audit_mode": verdict["audit_mode"], + "n_quotes": verdict["n_quotes"], + "n_verified": verdict["n_verified"], + "verifier_method": verdict["verifier_method"], + }, + ts=now, + ) + conn.execute( + "INSERT INTO providence_cache " + "(cache_key, source_root, document_uri, question_hash, question_text, " + " answer_text, merkle_proof, model_profile_hash, conversation_hash, " + " governance_policy_hash, schema_version, canonicalization_version, " + " chunking_version, falsification_state, chain, audit_event_hash, " + " created_at, hit_count, audit_mode, n_quotes, n_verified, " + " unverified_quotes, verifier_method, run_dag_root, run_dag_blob) " + "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 'live', ?, ?, ?, 0, " + " ?, ?, ?, ?, ?, ?, ?)", + ( + ckey, + document_root, + doc["document_uri"], + qhash, + question, + answer_text, + proof_blob, + mhash, + chash, + ghash, + SCHEMA_VERSION, + CANONICALIZATION_VERSION, + doc["chunking_version"], + chain, + event_hash, + now, + verdict["audit_mode"], + verdict["n_quotes"], + verdict["n_verified"], + unverified_blob, + verdict["verifier_method"], + run_dag["root"], + run_dag_blob, + ), + ) + + from aborist.qa.dag import localize_failure as _localize + failure_stage = _localize( + audit_mode=verdict["audit_mode"], + n_sources=1, # ask() runs against one document + n_quotes=verdict["n_quotes"], + n_verified=verdict["n_verified"], + ) + return { + "status": "cache_miss_then_written", + "audit_mode": verdict["audit_mode"], + "cache_key": ckey, + "run_dag_root": run_dag["root"], + "lookup_path": "miss", + "failure_stage": failure_stage, + "repair_changes": repair_changes, + "pre_repair_audit_mode": ( + pre_repair_verdict["audit_mode"] if pre_repair_verdict else None + ), + "source_root": document_root, + "answer_text": answer_text, + "merkle_proof": proof_obj, + "n_quotes": verdict["n_quotes"], + "n_verified": verdict["n_verified"], + "verifier_method": verdict["verifier_method"], + "unverified_quotes": verdict["unverified_quotes"], + "partially_verified_quotes": verdict.get("partially_verified_quotes") or [], + # Quantifier preflight (Ticket #000008 Phase 1+2). See query.py + # for full rationale; runner.ask carries the same schema for + # CLI-side `aborist ask` parity with `aborist query`. + "quantifier_intensity": quantifier["intensity"], + "quantifier_matched_token": quantifier["matched_token"], + "scope_bound_hint": quantifier["scope_bound_hint"], + "quantifier_explicit_count": quantifier["explicit_count"], + "claim_cap_applied": claim_cap_lookup, + # Ticket #000010 — meta-cognition QuestionState. + "question_state": question_state.to_dict(), + # Sidecar smell signals (claim_lattice mode only) — render- + # layer; never persisted, never in run_dag_root. + "pointer_id_distribution": verdict.get("pointer_id_distribution"), + "lazy_anchor_ratio": verdict.get("lazy_anchor_ratio"), + "timings": { + "cache_lookup_ms": cache_lookup_ms, + "llm_ms": llm_ms, + "total_ms": _ms_since(t_start), + }, + }
+ +
+
+
+
+ + +
+
+ + Made with Sphinx and @pradyunsg's + + Furo + +
+
+ +
+
+ +
+
+ +
+
+ + + + + \ No newline at end of file diff --git a/docs/_source/_build/html/_modules/aborist/qa/verify.html b/docs/_source/_build/html/_modules/aborist/qa/verify.html new file mode 100644 index 0000000..41a92b3 --- /dev/null +++ b/docs/_source/_build/html/_modules/aborist/qa/verify.html @@ -0,0 +1,2434 @@ + + + + + + + + aborist.qa.verify - Aborist API Reference + + + + + + + + + + + + + + + + Contents + + + + + + Menu + + + + + + + + Expand + + + + + + Light mode + + + + + + + + + + + + + + Dark mode + + + + + + + Auto light/dark, in light mode + + + + + + + + + + + + + + + Auto light/dark, in dark mode + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Skip to content + + + +
+
+
+ +
+ +
+
+ +
+ +
+
+ +
+
+
+ + + + + Back to top + +
+
+ +
+ +
+
+

Source code for aborist.qa.verify

+"""Post-LLM faithfulness check: did the answer ground its claims in context?
+
+Three layered strategies, tried in order. The first one that finds evidence
+classifies the answer. `verifier_method` on the result records which path
+fired so the audit chain stays diagnostic.
+
+    1. quote     model wrapped claims in double quotes per system prompt.
+                 Strongest signal — explicit, verbatim, model-asserted.
+    2. span      no quotes, but bullet/sentence-level lines from the answer
+                 appear verbatim in context. Catches models that quote
+                 inline without "..." marks.
+    3. entity    no quotes and no span match, but multi-word proper-noun
+                 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.
+
+Each strategy classifies into v9.8's audit-mode trichotomy (RAG-adapted
+vocabulary; substrate calls UNGROUNDED "VISUAL"):
+
+    STRICT      every evidence unit (>=1) verifies verbatim against context
+    HYBRID      some verify, others do not  (mixed source / emergent)
+    UNGROUNDED  no evidence, or none verify (purely emergent)
+
+`unverified_quotes` (kept under that name for schema continuity) collects
+spans the model produced that don't appear in any source — the
+corpus-growth signal mined by `aborist emergent`.
+
+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 isn't in the context."
+
+Wikitext context is run through ``aborist.wikitext.to_base`` 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 *markup*
+(``[[Cloud]]`` vs ``Cloud``) verify, while paraphrases of *prose* still
+flag honestly. mwparserfromhell is an optional dep; if absent, the
+strip is a no-op and verification falls back to today's behavior.
+"""
+
+from __future__ import annotations
+
+import re
+import unicodedata
+
+from aborist.qa.warrant import warrant_check
+
+# Deferred import: aborist.qa.inspect imports aborist.compress &
+# aborist.store at module load. The verifier doesn't need either
+# until deflection actually runs, so defer to call-site to keep
+# import order clean if anything else imports verify.py.
+try:
+    from aborist.wikitext import to_base as _wikitext_to_base
+except ImportError:  # pragma: no cover
+    _wikitext_to_base = None
+
+
+# Locate every double-quote character (ASCII or curly). Sequential
+# pairing in extract_quotes() turns these into intentional (open, close)
+# pairs: 1st & 2nd char, 3rd & 4th, etc. Pure-regex pairing fails on
+# adjacent quote pairs like `"title" prose "quote"` — the regex captures
+# `prose` as a "quoted span" because every `"` looks like both an opener
+# and a closer to it.
+_QUOTE_CHAR_RE = re.compile(r'["“”]')
+
+# Bullet markers at line start: -, *, +, •, 1., 2), etc.
+_BULLET_RE = re.compile(r'^\s*(?:[-*+•]|\d+[.)])\s+')
+
+# Sentence boundary: punctuation + whitespace + capital letter.
+_SENT_RE = re.compile(r'(?<=[.!?])\s+(?=[A-Z])')
+
+# Multi-word capitalized phrase. Two or more whitespace-separated tokens,
+# each starting with a capital letter (allowing initials like "A.", hyphens
+# like "Carrie-Anne", and trailing lowercase like "Smith"). Matches "Keanu
+# Reeves", "Thomas A. Anderson", "Carrie-Anne Moss", "Agent Smith". Skips
+# single capitalized words to avoid sentence-starter false positives.
+_PROPER_NOUN_RE = re.compile(
+    # Token gap is non-newline whitespace so a phrase never crosses a
+    # paragraph break. Caught a real case where "Joe Pantoliano\n\nThe
+    # sources" matched as one phrase via \s+.
+    r"\b[A-Z][A-Za-z'’\-]*(?:[ \t]+(?:[A-Z]\.|[A-Z][A-Za-z'’\-]+))+\b"
+)
+
+MIN_QUOTE_CHARS = 8
+MIN_SPAN_CHARS = 12
+
+# Trailing parenthetical the model often appends to verbatim source
+# prose, defeating substring match even when the prose itself IS in
+# the corpus. Examples we strip:
+#
+#     "...lightning-based attacks. (Source: https://...)"
+#     "...invented in 1976. (citing Wikipedia)"
+#     "...protagonist of the game. (see Pikachu_(character))"
+#     "...released in 1997 (https://en.wikipedia.org/...)"
+#
+# Conservative regex: only strips a SINGLE trailing parenthetical at
+# end-of-string after optional whitespace, and only when the contents
+# either start with a recognized citation cue OR contain a URL. Refuses
+# to strip parentheticals that look like genuine prose (e.g.
+# "Pikachu (a Pokémon species)").
+_TRAILING_CITATION_RE = re.compile(
+    r"""
+    \s*\(\s*
+    (?:                                           # one of:
+        (?:source|src|citing|see|ref|reference|from)  # citation cue word
+        \s*:?\s*[^()]*                            #   optional content
+      |                                           # OR
+        https?://\S+\s*[^()]*                     # URL-led parenthetical
+    )
+    \s*\)\s*$
+    """,
+    re.IGNORECASE | re.VERBOSE,
+)
+
+
+def _strip_trailing_citation(text: str) -> str:
+    """Drop a trailing `(Source: ...)`-like parenthetical, if any.
+
+    Idempotent: applies once. The model rarely chains citations, so we
+    don't loop. Returns the input unchanged if no match.
+    """
+    return _TRAILING_CITATION_RE.sub("", text).rstrip()
+
+
+# Paraphrase strategy thresholds. The 4th verifier method runs only
+# when quote/span/entity have all failed to classify; it accepts a
+# span as "paraphrase-verified" when token coverage in the source
+# context crosses ``DEFAULT_PARAPHRASE_COVERAGE`` and the span has at
+# least ``DEFAULT_PARAPHRASE_MIN_TOKENS`` content tokens (>4 chars).
+#
+# Soft-signal note: token overlap is a heuristic, NOT byte-equivalence.
+# The hard chain still records `verifier_method = 'paraphrase'` so an
+# auditor can distinguish lexical-verbatim from paraphrase-overlap.
+# A span verified via paraphrase contributes to `n_verified` but the
+# audit_mode trichotomy stays unchanged: STRICT requires all units
+# (quote/span/entity/paraphrase) to verify; HYBRID = some verify some
+# don't; UNGROUNDED = none.
+DEFAULT_PARAPHRASE_COVERAGE = 0.85
+DEFAULT_PARAPHRASE_MIN_TOKENS = 4
+
+# Entity-path policies. Entity-existence in source is circumstantial, not
+# claim-level proof — the model could correctly name entities while making
+# claims around them that came from training. These four policies span the
+# trade-off: max-trust to no-trust.
+#
+#   strict     all entities verify → STRICT (legacy behavior; overclaims)
+#   hybrid     any entity verifies → HYBRID (honest cap; safe default)
+#   drop       skip entity path entirely → UNGROUNDED (most conservative)
+#   proximity  STRICT only if N verified entities cluster within W chars
+#              of each other in context (e.g. an infobox cast list).
+#              Otherwise demotes to HYBRID/UNGROUNDED based on partial match.
+ENTITY_POLICIES = ("strict", "hybrid", "drop", "proximity")
+DEFAULT_ENTITY_POLICY = "proximity"
+
+# Proximity tuning. N entities within W chars of each other.
+DEFAULT_PROXIMITY_N = 3
+DEFAULT_PROXIMITY_WINDOW = 300
+
+# Framing phrases that aren't real claims even when they're in source. We
+# strip these from the answer before span/entity extraction so they don't
+# become noise in unverified_quotes.
+_FRAMING_PREFIXES = (
+    "based on the provided sources",
+    "based on the provided source",
+    "based on the source",
+    "based on the document",
+    "the sources do not",
+    "the source does not",
+    "the document does not",
+    "according to the sources",
+    "according to the source",
+)
+
+
+def _normalize(s: str) -> str:
+    """norm-v1 + lowercase. Same canonicalization as chunk leaf hashing,
+    plus case-folding so the verifier doesn't fail on capitalization drift
+    between source prose and the model's quoted span."""
+    s = unicodedata.normalize("NFC", s)
+    s = " ".join(s.split())
+    return s.lower()
+
+
+def _is_framing(span: str) -> bool:
+    n = _normalize(span)
+    return any(n.startswith(p) for p in _FRAMING_PREFIXES)
+
+
+
+[docs] +def extract_quotes(answer_text: str) -> list[str]: + """Pull double-quoted spans of length >= MIN_QUOTE_CHARS from `answer_text`. + + 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 model's own framing + prose (not captured). This is the correct model for adjacent quote + pairs like `"title" prose "quote"` — naive regex matching paired + the close of "title" with the open of "quote" and captured `prose` + as a phantom quote, dragging classifications down to HYBRID + incorrectly. + """ + positions = [m.start() for m in _QUOTE_CHAR_RE.finditer(answer_text)] + quotes: list[str] = [] + for i in range(0, len(positions) - 1, 2): + span = answer_text[positions[i] + 1:positions[i + 1]] + # Strip model-appended citations BEFORE the length gate so a + # `verbatim... (Source: https://...)` span that's >MIN long with + # the citation but short without it doesn't bypass the test. + span = _strip_trailing_citation(span) + if len(span) >= MIN_QUOTE_CHARS: + quotes.append(span) + return quotes
+ + + +
+[docs] +def extract_claim_spans(answer_text: str) -> list[str]: + """Strip bullet markers, split into sentences, drop framing prefixes. + + Returns each non-empty span of length >= MIN_SPAN_CHARS. These are the + "claim units" the model wrote — each one we'll substring-test against + context. + """ + spans: list[str] = [] + for line in answer_text.splitlines(): + stripped = _BULLET_RE.sub("", line).strip() + if not stripped: + continue + for sent in _SENT_RE.split(stripped): + sent = sent.strip().rstrip(".:,;") + # Drop model-appended `(Source: ...)` parentheticals so a + # verbatim sentence doesn't fail substring match because of + # an inserted citation. + sent = _strip_trailing_citation(sent) + if len(sent) < MIN_SPAN_CHARS: + continue + if _is_framing(sent): + continue + spans.append(sent) + return spans
+ + + +
+[docs] +def extract_proper_nouns(answer_text: str) -> list[str]: + """Pull multi-word capitalized phrases. Deduplicated, order preserved. + + 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. + """ + seen: set[str] = set() + out: list[str] = [] + for m in _PROPER_NOUN_RE.findall(answer_text): + if m in seen: + continue + seen.add(m) + out.append(m) + return out
+ + + +def _classify(verified: list[str], unverified: list[str]) -> str: + if verified and not unverified: + return "STRICT" + if verified: + return "HYBRID" + return "UNGROUNDED" + + +def _has_entity_cluster( + verified_entities: list[str], + norm_ctx: str, + n: int, + window: int, +) -> bool: + """Do at least `n` distinct verified entities appear within `window` + chars of each other in `norm_ctx`? Crude proxy for "the source has a + section about these entities" (cast list, infobox, roster) vs + "the source incidentally mentions them in scattered prose." + """ + if len(verified_entities) < n: + return False + positions: list[int] = [] + for e in verified_entities: + idx = norm_ctx.find(_normalize(e)) + if idx >= 0: + positions.append(idx) + if len(positions) < n: + return False + positions.sort() + for i in range(len(positions) - n + 1): + if positions[i + n - 1] - positions[i] <= window: + return True + return False + + +def _check_each(items: list[str], norm_ctx: str) -> tuple[list[str], list[str]]: + verified: list[str] = [] + unverified: list[str] = [] + for it in items: + if _normalize(it) in norm_ctx: + verified.append(it) + else: + unverified.append(it) + return verified, unverified + + +def _token_coverage( + span: str, + norm_ctx: str, + *, + min_token_len: int = 4, +) -> tuple[float, int]: + """Fraction of meaningful tokens from `span` that appear anywhere + in `norm_ctx`. Returns ``(coverage_fraction, content_token_count)``. + + Two filters narrow the token set to topical content: + + 1. ``len(t) >= min_token_len`` (default 4). Excludes ``the / a / an + / of / to / is / in / on / at`` etc. — short function words. + 2. Stopword exclusion. Common English filler 4+ chars long + (``from``, ``with``, ``have``, ``this``, ``that``, ``which``, + ``where``, ``their``, ``would``, ``could``, etc.) match almost + any English text & inflate coverage scores for cases where the + *topical* content is missing. Filtering them tightens the + signal: a span that paraphrases stylistic choice (replaces + ``with`` → ``from``) still scores 1.0 if topical tokens match; + a span where topical tokens are missing scores lower because + the denominator dropped. + + The 0.85 paraphrase-coverage threshold is calibrated for THIS + cleaner signal — lowering the threshold would promote fabrications + (Q1 Batman case: "wealthy/businessman/resides" missing, model- + invented). Tightening the denominator instead keeps the threshold + stable and the discrimination crisp. + + Strip from numerator AND denominator so a span composed entirely + of stopwords (e.g. ``"have been there"``) returns coverage 0.0 + rather than dividing by zero. + """ + nspan = _normalize(span) + # Strip per-token leading/trailing punctuation BEFORE the length + # gate and the stopword filter so `batman,` and `wayne.` line up + # with bare `batman`/`wayne` in context. We don't apply this in + # _normalize() because the substring path needs punctuation- + # preserving canonicalization (a span ending in `."` is a + # different surface from one ending without). + tokens: list[str] = [] + for raw in nspan.split(): + t = raw.strip(_TOKEN_PUNCT_STRIP) + if len(t) < min_token_len: + continue + if t in _ENGLISH_STOPWORDS: + continue + tokens.append(t) + if not tokens: + return (0.0, 0) + present = sum(1 for t in tokens if t in norm_ctx) + return (present / len(tokens), len(tokens)) + + +# Per-token punctuation stripped before the coverage check. Tokens like +# `wayne,` and `bruce!` line up with bare `wayne` / `bruce` in context. +# We don't strip apostrophes (``'``) so possessives stay distinct: +# ``batman's`` is a different content token from ``batman``. +_TOKEN_PUNCT_STRIP = ".,;:!?\"()[]{}" + + +# Common English stopwords of length >= 4 chars. Hand-curated rather +# than imported from NLTK to keep aborist dependency-light and the +# behavior pinned to a known set. Tokens are normalized form +# (lowercase, NFC). Includes auxiliaries, prepositions, pronouns, +# wh-words, conjunctions, and high-frequency adverbs/quantifiers that +# carry little topical signal. +_ENGLISH_STOPWORDS = frozenset({ + # auxiliaries / be-forms (>= 4) + "have", "been", "being", "were", "will", "would", "could", "should", + "might", "must", "shall", + # prepositions / particles (>= 4) + "from", "with", "into", "onto", "upon", "over", "under", "after", + "before", "between", "through", "across", "above", "below", "behind", + "beside", "beyond", "during", "without", "within", "until", "since", + "about", "around", "along", "among", + # demonstratives / pronouns (>= 4) + "this", "that", "these", "those", "their", "them", "they", "there", + "here", "your", "yours", "ours", "mine", + # wh-words (>= 4) + "what", "when", "where", "which", "while", "whom", "whose", + "whoever", "whatever", "wherever", "whenever", + # conjunctions (>= 4) + "because", "although", "however", "therefore", "though", "unless", + # adverbs / quantifiers (>= 4) + "also", "very", "much", "many", "more", "most", "less", "some", + "such", "even", "ever", "just", "only", "than", "then", "still", + "again", "always", "never", "often", "rather", "really", "quite", + "very", "well", "back", "next", + # auxiliaries / discourse (>= 4) + "also", "both", "each", "every", "into", "like", +}) + + +def _is_prose_span(span: str, *, min_lowercase_content: int = 2) -> bool: + """Heuristic: does this span look like prose (eligible for paraphrase + matching) vs. a list of proper nouns (better matched by entity)? + + Counts tokens in the ORIGINAL (pre-normalize) span whose first + letter is lowercase and whose length is >= 4 chars. A pure list + like ``"Keanu Reeves, Laurence Fishburne"`` has zero such tokens — + those go through the entity path. A real sentence like ``"Pikachu + is a species of Pokémon creatures..."`` has multiple ("species", + "creatures", "from", etc.) and qualifies for paraphrase. + + Threshold ``min_lowercase_content=2`` lets through "the cast..." + (1 lowercase content token: "cast") only if more lowercase prose + is present. Lists with a leading "The" don't sneak through. + """ + n_lower = 0 + for tok in span.split(): + # Strip leading/trailing punctuation for the case check (so + # "cast:" still counts as a lowercase token). + core = tok.strip(".,;:!?\"'()[]{}") + if len(core) < 4: + continue + if core[0].islower(): + n_lower += 1 + if n_lower >= min_lowercase_content: + return True + return False + + +def _build_claim_statuses( + *, + verified: list[str] | None = None, + paraphrase: list[str] | None = None, + unverified: list[str] | None = None, + method: str, +) -> list[dict]: + """Per-evidence-unit status list. Three labels drawn from the toy- + Hermes taxonomy: + + VERIFIED_QUOTE unit substring-matched in normalized context + (any of quote/span/entity strategies) + SUPPORTED_PARAPHRASE unit cleared the paraphrase token-coverage + threshold (>=85% topical tokens present) + UNSUPPORTED unit didn't match anything + + Soft-signal labels (QUOTE_INTEGRITY_FAILED, SOURCE_MISMATCH, + FALSIFIED) live in the sidecar / falsification machinery, not on + the binary verifier output — see the + ``feedback_verifier_no_diagnostics`` discipline. Order preserved so + callers can map back to the model's original answer ordering. + """ + out: list[dict] = [] + for t in verified or []: + out.append({"text": t, "status": "VERIFIED_QUOTE", "method": method}) + for t in paraphrase or []: + out.append( + { + "text": t, + "status": "SUPPORTED_PARAPHRASE", + "method": "paraphrase", + } + ) + for t in unverified or []: + out.append({"text": t, "status": "UNSUPPORTED", "method": method}) + return out + + +def _check_each_with_paraphrase( + items: list[str], + norm_ctx: str, + *, + paraphrase_coverage: float = DEFAULT_PARAPHRASE_COVERAGE, + paraphrase_min_tokens: int = DEFAULT_PARAPHRASE_MIN_TOKENS, +) -> tuple[list[str], list[str], list[str]]: + """Three-bucket variant of ``_check_each``. + + For each item: + - if its normalized form is a substring of ``norm_ctx``: STRICT + (verbatim verified) + - else if its meaningful-token coverage in ``norm_ctx`` is + ``>= paraphrase_coverage`` and it has at least + ``paraphrase_min_tokens`` content tokens: PARAPHRASE + (token-overlap verified) + - else: UNVERIFIED + + Returns ``(strict_verified, paraphrase_verified, unverified)``. + Order within each bucket preserves input order. + + Soft-signal note: paraphrase verification is heuristic. Callers + that need byte-equivalence (proof export to other peers, audit + chain claims) must use ``_check_each`` directly. + """ + strict: list[str] = [] + paraphrase: list[str] = [] + unverified: list[str] = [] + for it in items: + if _normalize(it) in norm_ctx: + strict.append(it) + continue + # Paraphrase only fires for prose-shaped spans. Lists of proper + # nouns (e.g. "Keanu Reeves, Laurence Fishburne") fall through + # to the entity strategy where proximity policy can disambiguate + # tight clusters from scattered mentions. + if not _is_prose_span(it): + unverified.append(it) + continue + cov, n_tok = _token_coverage(it, norm_ctx) + if n_tok >= paraphrase_min_tokens and cov >= paraphrase_coverage: + paraphrase.append(it) + else: + unverified.append(it) + return strict, paraphrase, unverified + + +
+[docs] +def verify_quotes( + answer_text: str, + context: str, + *, + entity_policy: str = DEFAULT_ENTITY_POLICY, + proximity_n: int = DEFAULT_PROXIMITY_N, + proximity_window: int = DEFAULT_PROXIMITY_WINDOW, +) -> dict: + """Classify an answer's grounding against its retrieved context. + + Tries quote → span → entity verification in sequence. The first + strategy that finds evidence classifies the answer; later strategies + don't run. + + `entity_policy` 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. + + Returns: + { + "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 couldn't ground in context + "verifier_method": str, # 'quote' | 'span' | 'entity' | 'none' + } + """ + if entity_policy not in ENTITY_POLICIES: + raise ValueError( + f"entity_policy must be one of {ENTITY_POLICIES}, got {entity_policy!r}" + ) + + # Wikitext markup → plain prose. Identity if mwparserfromhell isn't + # installed (extras: pip install 'aborist[wikitext]'). + if _wikitext_to_base is not None: + context = _wikitext_to_base(context) + + norm_ctx = _normalize(context) + + # Strategy 1: explicit double-quoted spans. + quotes = extract_quotes(answer_text) + if quotes: + verified, unverified = _check_each(quotes, norm_ctx) + return { + "n_quotes": len(quotes), + "n_verified": len(verified), + "audit_mode": _classify(verified, unverified), + "unverified_quotes": unverified, + "verifier_method": "quote", + "claim_statuses": _build_claim_statuses( + verified=verified, unverified=unverified, method="quote" + ), + } + + # Strategy 2: bullet/sentence spans. Try verbatim substring first; + # then fall back to paraphrase (token-coverage) for items that didn't + # substring-match. Spans verified via paraphrase contribute to + # n_verified — the verifier_method label flips to "paraphrase" when + # any soft-verified items are present so an auditor can tell. + spans = extract_claim_spans(answer_text) + if spans: + strict, paraphrase, unverified = _check_each_with_paraphrase( + spans, norm_ctx + ) + verified = strict + paraphrase + if verified: + method = "paraphrase" if paraphrase else "span" + return { + "n_quotes": len(spans), + "n_verified": len(verified), + "audit_mode": _classify(verified, unverified), + "unverified_quotes": unverified, + "verifier_method": method, + "claim_statuses": _build_claim_statuses( + verified=strict, + paraphrase=paraphrase, + unverified=unverified, + method="span", + ), + } + + # Strategy 3: multi-word proper nouns (entity grounding) — gated by + # `entity_policy`. Entity-existence is weaker proof than quote or span; + # the operator chooses how much weight to give it. + if entity_policy == "drop": + # Skip entity path entirely. Falls through to UNGROUNDED/none. + pass + else: + entities = extract_proper_nouns(answer_text) + if entities: + verified, unverified = _check_each(entities, norm_ctx) + if verified: + if entity_policy == "strict": + # Legacy behavior: all match → STRICT. Overclaims. + mode = _classify(verified, unverified) + elif entity_policy == "hybrid": + # Cap at HYBRID. Honest middle: evidence exists, but + # entity-existence ≠ claim-existence. + mode = "HYBRID" + else: # proximity + cluster = _has_entity_cluster( + verified, norm_ctx, proximity_n, proximity_window + ) + if cluster and not unverified: + mode = "STRICT" + elif cluster: + mode = "HYBRID" + elif verified: + mode = "HYBRID" + else: + mode = "UNGROUNDED" + return { + "n_quotes": len(entities), + "n_verified": len(verified), + "audit_mode": mode, + "unverified_quotes": unverified, + "verifier_method": "entity", + "claim_statuses": _build_claim_statuses( + verified=verified, + unverified=unverified, + method="entity", + ), + } + + # Nothing extracted, or nothing verified. Truly emergent. + return { + "n_quotes": 0, + "n_verified": 0, + "audit_mode": "UNGROUNDED", + "unverified_quotes": [], + "verifier_method": "none", + "claim_statuses": [], + }
+ + + +# --------------------------------------------------------------------------- +# Claim-lattice-pointer verifier — G0 / CTI Clause Lattice Intelligence. +# +# Companion to ``verify_quotes`` for ``policy["answer_mode"] == +# "claim_lattice_pointer"``. The model emits weak natural-language +# pointer clauses (``Claim text. [E12]``); the runtime parses them +# into structured claim nodes and runs deterministic checks against +# the runtime-built evidence map. +# +# Why pointer-line, not JSON: small instruction-tuned models follow +# citation-style prose far more reliably than free-form JSON. JSON +# discipline failures generate spurious one-shot SCHEMA_INVALID +# verdicts even when the model knew the right answer; pointer-line +# stays inside the model's prose-generation distribution. +# +# Why decimal pointer ids (E1, E2, …) not hex (E1f8e4c2a): +# - One BPE token per id in standard tokenizers (8-hex tokenizes to +# 4–6 tokens of out-of-distribution noise that nudges the model +# toward DSL/code mode). +# - Citation style (footnotes, references) is heavily represented in +# training; random hex is not. +# - The runtime maps pointer ids back to content-addressed evidence +# ids (``evidence_map_by_pointer_id``) for cache, run-DAG, audit. +# +# Hard-soft boundary: only deterministic checks. No entailment, no +# completeness, no predicate compatibility. Those stay sidecar. +# --------------------------------------------------------------------------- + +ANSWER_MODES = ("quote", "claim_lattice_pointer", "claim_lattice") +DEFAULT_ANSWER_MODE = "quote" + +# JSON-mode pre-parser. 8B and small-context models drift on JSON +# discipline (markdown fences, prose preamble, smart quotes, trailing +# commas). Larger reasoning models (Qwen 3.6 reasoner, Claude, GPT-4) +# emit valid JSON natively; the pre-parser is the defensive belt that +# keeps the JSON path survivable across the inference-quality spectrum. +# Lenient on syntax, strict on semantics: parsed JSON still has to +# pass the schema check & the same hard verifier rules as pointer mode. +_JSON_FENCE_RE = re.compile(r"^\s*```(?:json)?\s*\n(.*?)\n\s*```\s*$", re.DOTALL) +_TRAILING_COMMA_RE = re.compile(r",(\s*[}\]])") + + +def _repair_truncated_json(text: str) -> tuple[str, list[str]]: + """Best-effort completion of truncated JSON. + + Walks ``text`` once tracking string state and bracket/brace stack. + At end-of-input, if the parse is unbalanced (stuck mid-string, + open ``[`` / ``{`` without matching close) or has a dangling + structural artifact (trailing comma, partial key), repair so the + result is parseable. Returns ``(repaired, fixups)``. + + Targets the truncation pattern observed on Hermes-3-8B JSON-mode + output for broad-descriptive questions: the model writes one + long claim text and runs out of ``max_tokens`` mid-sentence, + yielding e.g.:: + + {"claims":[{"text":"The Apollo program was the United + States spaceflight effort which landed... <CUT> + + No closing ``"``, no closing ``}``, no closing ``]``, no closing + outer ``}``. The lenient parse path can't recover any structure. + Self-healing closes the open string, balances the stack, and + drops trailing commas / partial keys so the partial content is + preserved as a single claim with whatever fields survived. + + Fixups recorded: + - ``close_string`` — appended ``"`` to close an open string + - ``drop_partial_key`` — dropped a key without value + (``,"key":`` or ``,"key`` or ``"key":``) + - ``strip_trailing_comma`` — removed a comma immediately + before stack close (separate from the regex pass which + only handles structurally-correct trailing commas) + - ``close_brace`` / ``close_bracket`` — appended ``}`` / ``]`` + per open frame on the stack + + Conservative: never inserts content (no key names, no values, + no commas), only closes / drops. Worst case the repair is a + no-op or makes parsing fail in a different way; never silently + fabricates data. + """ + if not text or not text.strip(): + return text, [] + + fixups: list[str] = [] + stack: list[str] = [] + in_string = False + escaped = False + + for ch in text: + if escaped: + escaped = False + continue + if in_string: + if ch == "\\": + escaped = True + elif ch == '"': + in_string = False + else: + if ch == '"': + in_string = True + elif ch == "{" or ch == "[": + stack.append(ch) + elif ch == "}" or ch == "]": + if stack: + stack.pop() + + if not stack and not in_string: + return text, fixups + + repaired = text + + if in_string: + repaired += '"' + fixups.append("close_string") + + # Drop dangling structural fragments after the last legitimate + # value, walking back from end-of-string. Order matters: handle + # partial-key (`,"foo":` or `,"foo"` or `"foo":`) before + # trailing-comma so we don't strip the wrong comma. + while True: + rstripped = repaired.rstrip() + if not rstripped: + break + # Partial key: `..., "key": ` (colon at end after trim). + m = _PARTIAL_KEY_COLON_RE.search(rstripped) + if m and m.end() == len(rstripped): + repaired = rstripped[: m.start()] + if "drop_partial_key" not in fixups: + fixups.append("drop_partial_key") + continue + # Partial key: `..., "key"` (key without colon). + m = _PARTIAL_KEY_NO_COLON_RE.search(rstripped) + if m and m.end() == len(rstripped): + repaired = rstripped[: m.start()] + if "drop_partial_key" not in fixups: + fixups.append("drop_partial_key") + continue + # Trailing comma — strip when it would otherwise stick before close. + if rstripped.endswith(","): + repaired = rstripped[:-1] + if "strip_trailing_comma" not in fixups: + fixups.append("strip_trailing_comma") + continue + break + + # Close stack in reverse, mapping `{` → `}`, `[` → `]`. + while stack: + opener = stack.pop() + if opener == "{": + repaired += "}" + fixups.append("close_brace") + else: + repaired += "]" + fixups.append("close_bracket") + + return repaired, fixups + + +# Partial-key patterns for _repair_truncated_json. ``,"foo":`` or +# ``"foo":`` at end-of-string after rstrip = a key with no value. +_PARTIAL_KEY_COLON_RE = re.compile(r',?\s*"[^"]*"\s*:\s*$') +# ``,"foo"`` or ``"foo"`` with no following colon — also dangling. +_PARTIAL_KEY_NO_COLON_RE = re.compile(r',\s*"[^"]*"\s*$') + + +def _lenient_json_parse(raw: str) -> tuple[object, list[str]]: + """Parse ``raw`` as JSON, defensively peeling common model drift. + + Returns ``(parsed_obj, fixups_applied)`` — fixups list is empty + when strict parse succeeded, otherwise names what we had to peel + (``"fence"``, ``"prose_trim"``, ``"curly_quotes"``, + ``"trailing_comma"``) or repair (``"close_string"``, + ``"close_brace"``, ``"close_bracket"``, ``"drop_partial_key"``, + ``"strip_trailing_comma"``). + Raises ``json.JSONDecodeError`` if the lenient pass also fails. + + The fixups list lands in the verify payload so an agent can + observe model drift across runs & decide whether the inference + path is JSON-clean enough to keep using. + """ + import json as _json + fixups: list[str] = [] + try: + return _json.loads(raw), fixups + except _json.JSONDecodeError: + pass + + text = raw + + # 1. Strip markdown fence wrappers (```json\n...\n``` or ```\n...\n```). + m = _JSON_FENCE_RE.match(text) + if m: + text = m.group(1) + fixups.append("fence") + + # 2. Trim leading prose to first `{` or `[`; trailing prose past last + # matching `}`/`]`. Preserves the JSON object even when the model + # writes "Here is the JSON: {...}\n\nLet me know if you need more." + first_brace = min( + (text.find(c) for c in "{[" if text.find(c) >= 0), + default=-1, + ) + last_brace = max(text.rfind("}"), text.rfind("]")) + if first_brace > 0 or (last_brace >= 0 and last_brace < len(text) - 1): + if first_brace >= 0 and last_brace >= first_brace: + text = text[first_brace : last_brace + 1] + fixups.append("prose_trim") + + # 3. Normalize curly quotes — model-emitted “…” / ‘…’ become "…" / '…'. + if any(c in text for c in "“”‘’"): + text = ( + text.replace("“", '"').replace("”", '"') + .replace("‘", "'").replace("’", "'") + ) + fixups.append("curly_quotes") + + # 4. Fix trailing commas before `}` or `]`. Conservative: only + # comma immediately followed by whitespace + close bracket. + if "," in text: + new_text = _TRAILING_COMMA_RE.sub(r"\1", text) + if new_text != text: + text = new_text + fixups.append("trailing_comma") + + # 5. Try strict parse before invoking the truncation repair — + # peeling alone may have made it valid. + try: + return _json.loads(text), fixups + except _json.JSONDecodeError: + pass + + # 6. Self-heal truncated JSON: close open strings, drop dangling + # partial keys / trailing commas, balance the bracket stack. The + # model ran out of max_tokens mid-output; close what we can and + # parse the partial structure rather than failing the whole run. + repaired, repair_fixups = _repair_truncated_json(text) + if repair_fixups: + text = repaired + fixups.extend(repair_fixups) + + return _json.loads(text), fixups + +# Default allowed source roles for claim_lattice_pointer mode. Roles +# outside this set get classified as SOURCE_ROLE_BLOCKED. Mirrors the +# role classifications in aborist/qa/query.py:_classify_source_role; +# "noisy_background_source" and "sequel_background_source" are +# deliberately excluded by default. +DEFAULT_ALLOWED_SOURCE_ROLES = ( + "primary_answer_source", + "secondary_context_source", + "background_source", + "unclassified", +) + + +def _has_manual_quote(text: str) -> bool: + """Strict no-quote rule: ANY double-quote character in claim text + is a violation. + + The premise of claim-lattice-pointer mode is that models do not type + quote text — period. Even a 3-char quoted span (``"hi"``) is a + model-asserted verbatim citation that the runtime didn't authorize. + Catching every quote keeps the discipline honest: the model is + forbidden, not just length-discouraged. + + Covers ASCII (``"``) and curly quotes (``“`` / ``”``) — same set + ``_QUOTE_CHAR_RE`` recognizes for the legacy quote verifier. + """ + return any(ch in text for ch in ('"', '“', '”')) + + +DEFAULT_MIN_CITATION_COVERAGE = 0.30 + +# Premise-parroting / generic-vocab-ride-along threshold. When ≥ this +# many tokens shared by the question AND the claim are ABSENT from the +# union of cited evidence spans, the claim is parroting the question's +# subject without anchoring it. Surfaced by the 200-cycle bench-emergent +# delta on `steer/reply/correcter` (Ticket #000006 amend 2026-05-02b): +# claim affirmed three question-distinctive tokens (correcter, steer, +# reply) that appeared ZERO times in the cited 33.5K-char glossary. The +# generic linguistic vocabulary (language, communication, terms, +# relationships) carried Rule 5's coverage check on its own. +# +# Threshold of 3 keeps the signal unambiguous: a single absent parroted +# token is often a stem-variant near-miss; three or more is the +# parroting fingerprint. Folds into verifier_policy_hash. +DEFAULT_SUBJECT_TOKENS_ABSENT_THRESHOLD = 3 + + +def _claim_textually_overlaps_evidence( + claim_text: str, + evidence_span: str, + *, + min_coverage: float = DEFAULT_MIN_CITATION_COVERAGE, +) -> bool: + """Return True if claim's content-token coverage in ``evidence_span`` + meets ``min_coverage`` (case-insensitive substring match). + + Hard 6th check on a (claim, pointer) pair. Catches the lazy-anchor + failure where the model cites an evidence pointer whose text has + insufficient overlap with the claim's actual subject — e.g. claim + "Yale University in New Haven and the University of Connecticut..." + cited to a highway-data span containing only the token + ``connecticut`` (1/10 = 10% coverage; below the 30% default + threshold → CITATION_MISMATCH). + + Pre-2026-04-30 this function required only ≥1 shared content token, + which let through lazy-anchored claims whose only overlap was a + common topical word. Coverage-based threshold scales with claim + length: short claims (1-3 content tokens) need 1 match (same as + the old behavior), longer claims need a proportional share. + + Lexical only, no NER, no embeddings; stays inside the soft/hard + boundary. + + A pure-stopword claim (no content tokens after the spotlight token + extractor's filter) returns True vacuously — there's nothing + topical to check, and the verifier's other hard checks already + own that case (claim_text_non_empty, no_manual_quotes, etc.). + """ + from aborist.qa.evidence import _content_tokens + + tokens = _content_tokens(claim_text) + if not tokens: + return True + span_lower = evidence_span.lower() + matched = sum(1 for t in tokens if t in span_lower) + coverage = matched / len(tokens) + # Floor: a single shared content token always counts when the claim + # is itself short (≤3 content tokens) so single-fact narrow claims + # like "Steve Jobs co-founded Apple" don't fail on a coverage + # technicality. The threshold bites on prose-shaped multi-token + # claims where 1/10 token overlap is the lazy-anchor signature. + if matched >= 1 and len(tokens) <= 3: + return True + return coverage >= min_coverage + + +def _parroted_subject_tokens_absent( + question_text: str | None, + claim_text: str, + cited_spans: list[str], +) -> set[str]: + """Return claim∩question content tokens that are NOT present in + the union of cited evidence spans. + + Premise-parroting / generic-vocab-ride-along detector (Ticket + #000006 amend 2026-05-02b). The model affirms the question's + distinctive subject tokens in its claim, but those tokens are + absent from the cited evidence — the citation rode in on + overlapping generic vocabulary while the actual subject went + unverified. + + Mechanism: substring match on lowercased text, mirroring Rule 5 + (`_claim_textually_overlaps_evidence`). Stem-tolerant via the + substring rule — "polar" matches inside "bipolar", "rare" + matches "rarely", etc. + + No-question-text → empty set (skip the check). + No question∩claim overlap → empty set (claim isn't parroting). + Empty cited_spans → return the full parroted set (defensive; no + grounding at all is its own failure mode caught elsewhere). + """ + from aborist.qa.evidence import _content_tokens + + if not question_text or not claim_text: + return set() + qtok = set(_content_tokens(question_text)) + ctok = set(_content_tokens(claim_text)) + parroted = qtok & ctok + if not parroted: + return set() + union_lower = " ".join((s or "").lower() for s in cited_spans) + if not union_lower.strip(): + return parroted + return {t for t in parroted if t not in union_lower} + + +DEFAULT_MAX_POINTERS_PER_CLAIM = 2 +DEFAULT_MIN_CLAIM_CONTENT_TOKENS = 2 +DEFAULT_LAZY_ANCHOR_DEMOTE_THRESHOLD = 0.5 +DEFAULT_LAZY_ANCHOR_DEMOTE_MIN_PAIRS = 3 +# Claim-count ceiling. Bench evidence (2026-04-30 york-england run): +# pre-atomic-claim-rule, JSON mode emitted 26-59 claim-pointer pairs +# of which only 2-4 verified — the model treats "tell me all there +# is to know about X" as a license to spam encyclopedic claims from +# training. Atomic-claim prompt rule (commit b5925c8) reduced this +# to ~10 well-formed claims, but defence-in-depth: any answer with +# more than this many claims is structurally suspect regardless of +# how each claim verifies. Default 12 chosen to comfortably admit +# entity-list questions ("dinosaurs in jurassic park" → 5; "simpsons +# family + pets" → 5-7) while catching the runaway shape. +DEFAULT_MAX_CLAIMS_PER_ANSWER = 12 + + +# Title-relevance check (Rule 8). Cited evidence's source title must +# share at least one stemmed content token with the claim text. +# Catches the retrieval-driven hallucination class fox surfaced +# 2026-05-02 on "explain spin glass modeling & tensors?": claim +# tokens {spin, glass, modeling, tensor, ...} cited to a chunk from +# the *Quantum chromodynamics* article whose title tokens are +# {quantum, chromodynamics} — zero overlap. Token-coverage check +# inside the chunk passed accidentally on shared physics vocabulary; +# the SOURCE was never about the claim's subject. +def _claim_title_overlap(claim_text: str, source_title: str | None) -> bool: + """Return True iff the source title shares ≥1 stemmed content + token with the claim text. Vacuous-pass when either side has no + extractable tokens (defensive — prevents the rule from firing + on degenerate inputs).""" + if not source_title or not claim_text: + return True + from aborist.qa.evidence import _content_tokens as _ct + + claim_tokens = _ct(claim_text) + title_tokens = _ct((source_title or "").replace("_", " ")) + if not claim_tokens or not title_tokens: + return True + + # Reuse the retrieval-side stem helper so possessive / plural + # collapse the same way ('movies' vs 'movie', 'simpsons' vs + # 'simpson'). Defined in qa/query.py to avoid an import cycle: + # inline a minimal copy here instead. + def _stem(t: str) -> str: + if len(t) > 4 and t.endswith("s") and not t.endswith("ss"): + return t[:-1] + return t + + claim_stems = {_stem(t) for t in claim_tokens} + title_stems = {_stem(t) for t in title_tokens} + return bool(claim_stems & title_stems) + + +
+[docs] +def verify_claim_lattice( + answer_text: str, + evidence_map, + *, + allowed_source_roles: tuple[str, ...] = DEFAULT_ALLOWED_SOURCE_ROLES, + max_pointers_per_claim: int = DEFAULT_MAX_POINTERS_PER_CLAIM, + min_citation_coverage: float = DEFAULT_MIN_CITATION_COVERAGE, + min_claim_content_tokens: int = DEFAULT_MIN_CLAIM_CONTENT_TOKENS, + lazy_anchor_demote_threshold: float = DEFAULT_LAZY_ANCHOR_DEMOTE_THRESHOLD, + lazy_anchor_demote_min_pairs: int = DEFAULT_LAZY_ANCHOR_DEMOTE_MIN_PAIRS, + max_claims_per_answer: int = DEFAULT_MAX_CLAIMS_PER_ANSWER, + subject_tokens_absent_threshold: int = DEFAULT_SUBJECT_TOKENS_ABSENT_THRESHOLD, + question: str | None = None, + warrant_check_enabled: bool = True, + deflection_check_enabled: bool = True, + format_collapse_check_enabled: bool = True, +) -> dict: + """Deterministic verifier for ``answer_mode="claim_lattice_pointer"``. + + The model wrote pointer-line prose (``Claim text. [E12]``); 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: + + 1. Parser succeeded — ``parse_status == "PARSED"`` (line had a + bracket tag). NO_EVIDENCE_POINTER claims (prose without tag) + count toward the denominator and downgrade the verdict. + 2. Pointer id resolves to an entry in the runtime-built evidence + map. No model-invented ids. + 3. Resolved entry's ``source_role`` is in ``allowed_source_roles``. + 4. Claim text non-empty after tag strip. + 5. Claim's content tokens textually overlap the cited evidence + span at coverage ≥ ``min_citation_coverage`` (per-pair, lexical + only — see ``_claim_textually_overlaps_evidence``). Catches the + magnet-chunk lazy-anchor where the model cites an evidence + pointer whose text contains few claim-content tokens. + 6. Pointer count per claim does not exceed ``max_pointers_per_claim`` + (default 2 — matches the prompt's "1 or 2 pointers per claim" + rule). When exceeded, the claim is TRIMMED to the first N + pointers and verification proceeds normally; a + ``POINTER_OVERFLOW_TRIMMED`` 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 ``n_quotes`` so + the denominator reflects what the model emitted. + + Removed 2026-04-30: the strict no-double-quote rule. The model + routinely paraphrases source prose but copies named-quoted phrases + verbatim (e.g. ``"Constitution State"`` from a Connecticut span). + Hard-rejecting claims that contained any ``"`` 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. ``_has_manual_quote`` is still defined and + used by ``verify_claim_lattice_json``. + + Returns a verdict in the same shape as ``verify_quotes`` + extras: + + n_quotes total claim-pointer pairs (denominator) + n_verified pairs where pointer resolved AND + source_role allowed AND coverage met + AND claim text non-empty + audit_mode STRICT / HYBRID / UNGROUNDED + unverified_quotes claim texts that didn't reach + EVIDENCE_LINKED — kept under that name + for schema continuity with verify_quotes + verifier_method "claim_lattice" + claim_statuses per-claim {text, evidence_ids, + pointer_ids, status, reasons[]}; status ∈ + {EVIDENCE_LINKED, EVIDENCE_LINKED_PARTIAL, + UNKNOWN_EVIDENCE_ID, + SOURCE_ROLE_BLOCKED, + CITATION_MISMATCH, + NO_EVIDENCE_POINTER, SCHEMA_INVALID} + violations structured violation records for the + run-DAG / sidecar + rendered_text human-readable prose with literal spans + interpolated; what the runner persists + as ``answer_text`` + evidence_id_pairs per-claim list of resolved + content-addressed evidence_ids (run-stable + form). Used to thread the parsed lattice + into the run-DAG. + """ + from aborist.qa.evidence import ( + evidence_map_by_pointer_id as _by_pointer, + render_claim_lattice as _render, + ) + from aborist.qa.parse_claims import parse_pointer_claims + + by_pointer = _by_pointer(evidence_map) + violations: list[dict] = [] + claim_statuses: list[dict] = [] + # Three-bucket rendering. ``unverified`` holds claims whose + # status reached neither EVIDENCE_LINKED nor EVIDENCE_LINKED_PARTIAL + # — i.e. fully failed (no pointer verified). ``partially_verified`` + # holds EVIDENCE_LINKED_PARTIAL claims (some pointers ok, some + # failed). The renderer shows them as their own section so a + # claim never appears in BOTH a verified bullet and the unverified + # footer; that previously happened for partial-status claims and + # read as "is it grounded or not?". Per-pointer detail lives in + # ``claim_statuses`` for audit. + unverified: list[str] = [] + partially_verified: list[str] = [] + + raw_claims = parse_pointer_claims(answer_text or "") + + # Claim-count ceiling — see DEFAULT_MAX_CLAIMS_PER_ANSWER. Records + # the violation but doesn't truncate; the per-claim loop below + # still verifies every claim so the operator sees full evidence + # of the runaway. Demotes verdict via the violation list. + if len(raw_claims) > max_claims_per_answer: + violations.append({ + "kind": "TOO_MANY_CLAIMS", + "n_claims": len(raw_claims), + "max": max_claims_per_answer, + }) + + n_pairs = 0 + n_pairs_verified = 0 + # Renderer claims: pointer-id form so the human display still shows + # the short tags the model used. + valid_claims: list[dict] = [] + # Evidence-id pairs: content-addressed form for the run-DAG & + # cache. Per-claim list so the parsed_claim_lattice node hashes the + # run-stable handle, not the run-dependent pointer-id. + evidence_id_pairs: list[list[str]] = [] + + for idx, c in enumerate(raw_claims): + claim_text = c.claim_text + pointer_ids = c.pointer_ids + parse_status = c.parse_status + + if parse_status == "NO_EVIDENCE_POINTER": + violations.append({ + "kind": "NO_EVIDENCE_POINTER", + "claim_idx": idx, + "claim_text": claim_text, + }) + claim_statuses.append({ + "claim_idx": idx, + "text": claim_text, + "pointer_ids": [], + "evidence_ids": [], + "status": "NO_EVIDENCE_POINTER", + "reasons": ["no [E\\d+] tag on line"], + }) + unverified.append(claim_text) + evidence_id_pairs.append([]) + # NO_EVIDENCE_POINTER counts as one denominator pair so the + # verdict reflects the failure rate. + n_pairs += 1 + continue + + if not claim_text: + violations.append({ + "kind": "SCHEMA_INVALID", + "claim_idx": idx, + "reason": "tag with no claim text", + }) + claim_statuses.append({ + "claim_idx": idx, + "text": "", + "pointer_ids": pointer_ids, + "evidence_ids": [], + "status": "SCHEMA_INVALID", + "reasons": ["tag with no claim text"], + }) + n_pairs += len(pointer_ids) + evidence_id_pairs.append([]) + continue + + # Bare-name claim guard. A claim like "Tyrannosaurus rex. [E15]" + # has 1 content token; the citation passes any span that mentions + # T-rex anywhere, even when E15 is a video-game-behavior chunk + # rather than a film-context one. Forcing a sentence-shape claim + # ("Tyrannosaurus rex appeared in the first JP film") raises the + # token-coverage bar so an off-topic chunk can no longer satisfy + # the citation. Folds into governance_policy_hash via + # ``claim_lattice_min_claim_content_tokens``. + from aborist.qa.evidence import _content_tokens as _ct + claim_content_tokens = _ct(claim_text) + if len(claim_content_tokens) < min_claim_content_tokens: + violations.append({ + "kind": "SCHEMA_INVALID", + "claim_idx": idx, + "reason": ( + f"bare-name claim ({len(claim_content_tokens)} content " + f"tokens < {min_claim_content_tokens}); write a sentence" + ), + }) + claim_statuses.append({ + "claim_idx": idx, + "text": claim_text, + "pointer_ids": pointer_ids, + "evidence_ids": [], + "status": "SCHEMA_INVALID", + "reasons": ["bare-name claim — write a sentence with predicate"], + }) + n_pairs += len(pointer_ids) + evidence_id_pairs.append([]) + unverified.append(claim_text) + continue + + # Pointer-count cap (Rule 9). Catches the encyclopedic-mega- + # claim where the model produces one line citing every + # pointer at once. Counts every pointer toward the denominator + # so the failure is loud in n_quotes. 2026-04-30: trim-and- + # verify rather than hard-fail. A correct claim cited with too + # many pointers ("Leonardo da Vinci painted the Mona Lisa. + # [E2,...,E14]") deserves to count if its first N pointers + # actually verify; the violation still blocks STRICT (audit_mode + # caps at HYBRID) so the over-citation pattern stays surfaced. + # Hard SCHEMA_INVALID would have nuked correct answers for a + # cosmetic over-cite. The dropped pointers count toward + # n_pairs so the denominator reflects what the model emitted. + pointer_overflow_trimmed = False + if len(pointer_ids) > max_pointers_per_claim: + dropped = pointer_ids[max_pointers_per_claim:] + n_pairs += len(dropped) + pointer_ids = pointer_ids[:max_pointers_per_claim] + pointer_overflow_trimmed = True + violations.append({ + "kind": "POINTER_OVERFLOW_TRIMMED", + "claim_idx": idx, + "kept": list(pointer_ids), + "dropped": dropped, + "max_pointers_per_claim": max_pointers_per_claim, + }) + + per_id_results: list[dict] = [] + resolved_evidence_ids: list[str] = [] + for pid in pointer_ids: + n_pairs += 1 + obj = by_pointer.get(pid) + if obj is None: + violations.append({ + "kind": "UNKNOWN_EVIDENCE_ID", + "claim_idx": idx, + "pointer_id": pid, + }) + per_id_results.append({ + "pid": pid, "ok": False, "kind": "UNKNOWN_EVIDENCE_ID", + }) + continue + if obj.source_role not in allowed_source_roles: + violations.append({ + "kind": "SOURCE_ROLE_BLOCKED", + "claim_idx": idx, + "pointer_id": pid, + "evidence_id": obj.evidence_id, + "source_role": obj.source_role, + }) + per_id_results.append({ + "pid": pid, "ok": False, "kind": "SOURCE_ROLE_BLOCKED", + }) + continue + if not _claim_textually_overlaps_evidence( + claim_text, obj.span, min_coverage=min_citation_coverage + ): + # Cited evidence span has zero textual overlap with any + # content token from the claim. Strongest lazy-anchor + # signal promoted to a hard fail — the model cited a + # magnet chunk that doesn't textually support its claim. + violations.append({ + "kind": "CITATION_MISMATCH", + "claim_idx": idx, + "pointer_id": pid, + "evidence_id": obj.evidence_id, + }) + per_id_results.append({ + "pid": pid, "ok": False, "kind": "CITATION_MISMATCH", + }) + continue + per_id_results.append({"pid": pid, "ok": True, "evidence_id": obj.evidence_id}) + resolved_evidence_ids.append(obj.evidence_id) + n_pairs_verified += 1 + + ok_pids = [r["pid"] for r in per_id_results if r["ok"]] + bad_kinds = sorted({r["kind"] for r in per_id_results if not r["ok"]}) + + if ok_pids and not bad_kinds: + status = "EVIDENCE_LINKED" + elif ok_pids: + status = "EVIDENCE_LINKED_PARTIAL" + elif "CITATION_MISMATCH" in bad_kinds: + status = "CITATION_MISMATCH" + elif "UNKNOWN_EVIDENCE_ID" in bad_kinds: + status = "UNKNOWN_EVIDENCE_ID" + elif "SOURCE_ROLE_BLOCKED" in bad_kinds: + status = "SOURCE_ROLE_BLOCKED" + else: + status = "SCHEMA_INVALID" + + claim_statuses.append({ + "claim_idx": idx, + "text": claim_text, + "pointer_ids": pointer_ids, + "evidence_ids": resolved_evidence_ids, + "status": status, + "reasons": bad_kinds, + }) + evidence_id_pairs.append(resolved_evidence_ids) + if status in ("EVIDENCE_LINKED", "EVIDENCE_LINKED_PARTIAL"): + valid_claims.append({"text": claim_text, "pointer_ids": ok_pids}) + if status == "EVIDENCE_LINKED_PARTIAL": + partially_verified.append(claim_text) + elif status != "EVIDENCE_LINKED": + unverified.append(claim_text) + + rendered_text = _render(valid_claims, by_pointer) if valid_claims else "" + + # Aggregate. STRICT requires ≥1 verified pair AND zero violations of + # any kind (schema, unknown pointer, blocked role, manual quote, + # missing pointer). HYBRID = some pairs verified, some failed. + # UNGROUNDED = no verified pairs (no parseable claims, or every + # claim failed at least one check). + if n_pairs_verified > 0 and not violations: + audit_mode = "STRICT" + elif n_pairs_verified > 0: + audit_mode = "HYBRID" + else: + audit_mode = "UNGROUNDED" + + # Anchor-smell sidecar (render-layer only — never persisted as a + # v9.8 field). Counts how many distinct pointer_ids the model used + # across the verified-or-partial claims. ``lazy_anchor_ratio`` is + # the max share any single pointer claimed: 1.0 = every claim cites + # the same pointer (Hermes-3-8B's lazy-anchor habit on the JP- + # dinosaurs benchmark), 1/N = every claim cites a unique pointer. + # The distribution is recoverable from ``claim_statuses`` which + # IS persisted in run_dag_blob; we surface the derived numbers in + # the verdict for the human renderer, but they never thread back + # into ``build_run_dag``'s verify_payload, so ``run_dag_root`` + # stays clean. + pointer_distribution: dict[str, int] = {} + for cs in claim_statuses: + if cs["status"] not in ("EVIDENCE_LINKED", "EVIDENCE_LINKED_PARTIAL"): + continue + for pid in cs.get("pointer_ids") or []: + pointer_distribution[pid] = pointer_distribution.get(pid, 0) + 1 + total_pointers = sum(pointer_distribution.values()) + lazy_anchor_ratio = ( + max(pointer_distribution.values()) / total_pointers + if total_pointers + else 0.0 + ) + + # Smell → demote. Pre-2026-04-30 the lazy-anchor signal was advisory + # only; the verdict could still be STRICT while every claim cited + # the same magnet chunk. Now: when ratio ≥ threshold AND total pairs + # ≥ floor, cap audit_mode at HYBRID. STRICT becomes unreachable for + # answers where one pointer carries every claim — that pattern is + # almost never honest verbatim grounding. UNGROUNDED is left alone + # (a verdict with zero verified pairs has no smell to flag). + lazy_anchor_demoted = False + if ( + audit_mode == "STRICT" + and total_pointers >= lazy_anchor_demote_min_pairs + and lazy_anchor_ratio >= lazy_anchor_demote_threshold + ): + audit_mode = "HYBRID" + lazy_anchor_demoted = True + violations.append({ + "kind": "LAZY_ANCHOR_DEMOTE", + "ratio": round(lazy_anchor_ratio, 3), + "min_pairs": lazy_anchor_demote_min_pairs, + "threshold": lazy_anchor_demote_threshold, + }) + + # Warrant-lite — relation-question hard check (Ticket H from + # feedback-3, 2026-05-01). Claim-cited spans must contain at + # least one of the claim's named answer entities (proper-noun + # phrases). Catches the Homer-Simpson lazy-anchor case fox + # surfaced — claim asserts "Mr. Burns" but cited span is + # Castellaneta voice-actor prose. See aborist/qa/warrant.py + # for the lexical algorithm and rationale (deterministic, + # not NLI). Fires only when the question shape suggests a + # relation lookup AND the lookup is enabled by policy + # (warrant_check_enabled). Per-claim WARRANT_MISSING violations + # cap audit_mode at HYBRID via the same demote pattern as + # lazy_anchor_demoted. + warrant_missing_claims: list[int] = [] + if warrant_check_enabled: + for cs in claim_statuses: + if cs.get("status") not in ("EVIDENCE_LINKED", "EVIDENCE_LINKED_PARTIAL"): + continue + cited_eids = cs.get("evidence_ids") or [] + cited_spans = [ + obj.span + for eid in cited_eids + for obj in [evidence_map_by_evidence_id_local(evidence_map, eid)] + if obj is not None + ] + ok, missing = warrant_check( + cs.get("text") or "", cited_spans, question=question + ) + if not ok: + warrant_missing_claims.append(cs.get("claim_idx")) + violations.append({ + "kind": "WARRANT_MISSING", + "claim_idx": cs.get("claim_idx"), + "missing_anchors": missing, + "rationale": ( + "claim asserts an answer entity or specific date " + "not present in any cited span — pointer-linked " + "but warrant missing" + ), + }) + if warrant_missing_claims and audit_mode == "STRICT": + audit_mode = "HYBRID" + + # Rule 8 — Title-relevance check. For each claim that resolved, + # at least one cited evidence's source title must share a + # stemmed content token with the claim. Catches the + # retrieval-driven hallucination class (2026-05-02 spin-glass + # case): claim about spin glass cited to a chunk from + # *Quantum chromodynamics* — token-coverage check passed on + # incidental physics vocabulary, but the SOURCE was never about + # the claim's subject. + title_mismatch_claims: list[int] = [] + for cs in claim_statuses: + if cs.get("status") not in ("EVIDENCE_LINKED", "EVIDENCE_LINKED_PARTIAL"): + continue + cited_eids = cs.get("evidence_ids") or [] + cited_titles = [ + obj.title + for eid in cited_eids + for obj in [evidence_map_by_evidence_id_local(evidence_map, eid)] + if obj is not None + ] + if not cited_titles: + continue + any_overlap = any( + _claim_title_overlap(cs.get("text") or "", t) + for t in cited_titles + ) + if not any_overlap: + title_mismatch_claims.append(cs.get("claim_idx")) + violations.append({ + "kind": "TITLE_MISMATCH", + "claim_idx": cs.get("claim_idx"), + "claim_text": (cs.get("text") or "")[:200], + "cited_titles": cited_titles, + "rationale": ( + "no cited source's title shares a content token " + "with the claim — pointer-linked but the cited " + "document is structurally unrelated to the claim" + ), + }) + if title_mismatch_claims and audit_mode == "STRICT": + audit_mode = "HYBRID" + # Tightening (2026-05-02 emergent-log finding): when EVERY resolving + # claim has TITLE_MISMATCH, the substrate has zero structural + # grounding for the user's question — every cited source is + # title-irrelevant. The cashback case ("widescreens offer cashback" + # cited to a generic Coupon article) had n_verified=1 but the + # citation was meaningless; HYBRID overclaimed. Demote to + # UNGROUNDED so the four-rung ladder maps it to UNGROUNDED, not + # POINTER-LINKED-PARTIAL. + n_resolving = sum( + 1 + for cs in claim_statuses + if cs.get("status") in ("EVIDENCE_LINKED", "EVIDENCE_LINKED_PARTIAL") + ) + if ( + title_mismatch_claims + and n_resolving > 0 + and len(title_mismatch_claims) == n_resolving + ): + audit_mode = "UNGROUNDED" + + # Rule 9 — Subject-tokens-absent / premise-parroting check (Ticket + # #000006 amend 2026-05-02b, surfaced by `steer/reply/correcter` + # 200-cycle bench-emergent finding). For each resolving claim, + # collect the union of cited evidence spans and check whether ≥ + # subject_tokens_absent_threshold tokens shared by question AND + # claim are absent from that union. If so, the claim is parroting + # the question's distinctive subject without anchoring it — the + # citation rode in on overlapping generic vocabulary while the + # actual subject went unverified. + subject_absent_claims: list[int] = [] + if question and subject_tokens_absent_threshold > 0: + for cs in claim_statuses: + if cs.get("status") not in ("EVIDENCE_LINKED", "EVIDENCE_LINKED_PARTIAL"): + continue + cited_eids = cs.get("evidence_ids") or [] + cited_spans = [] + for eid in cited_eids: + obj = evidence_map_by_evidence_id_local(evidence_map, eid) + if obj is not None and obj.span: + cited_spans.append(obj.span) + if not cited_spans: + continue + absent = _parroted_subject_tokens_absent( + question, cs.get("text") or "", cited_spans + ) + if len(absent) >= subject_tokens_absent_threshold: + subject_absent_claims.append(cs.get("claim_idx")) + violations.append({ + "kind": "SUBJECT_TOKENS_ABSENT", + "claim_idx": cs.get("claim_idx"), + "claim_text": (cs.get("text") or "")[:200], + "absent_tokens": sorted(absent), + "rationale": ( + f"{len(absent)} question-distinctive tokens echoed in " + f"the claim are absent from cited evidence — claim " + f"parrots question premise without anchoring it" + ), + }) + if subject_absent_claims and audit_mode == "STRICT": + audit_mode = "HYBRID" + + # Deflection check (soft demote, promoted from sidecar 2026-05-02). + # When the question's subject anchor is missing from the answer, + # the model deflected — answered an adjacent grounded question + # instead of the user's specific one. Caught the live cases: + # "who burns the amazon river?" → answered about Amazon + # Rainforest deforestation, "river" never in answer + # "what culture burns the amazon rain forest?" → answered + # "what causes burning", "culture" never in answer + # Both passed every other check but the user's question wasn't + # structurally answered. DEFLECTION_DETECTED downgrades + # EVIDENCE-WARRANTED → ANCHOR-WARRANTED via the soft-demote + # path. Render-layer ladder picks this up automatically. + deflection_detected = False + if deflection_check_enabled and question and rendered_text: + # Deferred import to avoid pulling aborist.compress + aborist.store + # at verify.py module-load time when callers may not need them. + from aborist.qa.inspect import diagnose_deflection + signal = diagnose_deflection(question, rendered_text) + if signal.get("kind") == "deflection": + deflection_detected = True + violations.append({ + "kind": "DEFLECTION_DETECTED", + "subject_anchor": signal.get("subject_anchor"), + "overlap_ratio": signal.get("overlap_ratio"), + "rationale": ( + "answer's content tokens omit the question's " + "subject anchor — model answered an adjacent " + "grounded question rather than the user's " + "specific one" + ), + }) + if deflection_detected and audit_mode == "STRICT": + audit_mode = "HYBRID" + + # Format-collapse check (FORMAT_COLLAPSED soft demote). + # The "winners of all major sports?" case fox surfaced 2026-05-02: + # Hermes melted under an under-specified broad question, dumped + # 50+ free-form prose claims with ZERO `[E\d+]` pointer tags. The + # parser found 2 line-shaped fragments to count as claims; both + # ungrounded → UNGROUNDED 0/2. Verifier was honest, but operators + # couldn't tell from the audit line whether UNGROUNDED meant + # "tried to ground & failed" vs "abandoned the protocol entirely." + # This sidecar separates those two failure shapes by inspecting + # the raw answer text for the absence of bracket tags amid + # multiple meaningful prose lines. + format_collapsed = False + if format_collapse_check_enabled and answer_text: + meaningful_lines = [ + line for line in answer_text.splitlines() + if len(line.strip()) > 20 + ] + bracket_count = len(re.findall(r"\[E\d+", answer_text)) + if len(meaningful_lines) >= 5 and bracket_count == 0: + format_collapsed = True + violations.append({ + "kind": "FORMAT_COLLAPSED", + "meaningful_lines": len(meaningful_lines), + "bracket_count": bracket_count, + "rationale": ( + "model emitted multi-line prose with zero [E\\d+] " + "pointer tags — abandoned the claim_lattice_pointer " + "protocol entirely. UNGROUNDED below this signal is " + "format collapse, not graceful per-claim refusal." + ), + }) + if format_collapsed and audit_mode == "STRICT": + audit_mode = "HYBRID" + + return { + "n_quotes": n_pairs, + "n_verified": n_pairs_verified, + "audit_mode": audit_mode, + "unverified_quotes": unverified, + "partially_verified_quotes": partially_verified, + "verifier_method": "claim_lattice", + "claim_statuses": claim_statuses, + "violations": violations, + "rendered_text": rendered_text, + "evidence_id_pairs": evidence_id_pairs, + "pointer_id_distribution": pointer_distribution, + "lazy_anchor_ratio": lazy_anchor_ratio, + "lazy_anchor_demoted": lazy_anchor_demoted, + "warrant_missing_claim_idxs": warrant_missing_claims, + "title_mismatch_claim_idxs": title_mismatch_claims, + "deflection_detected": deflection_detected, + "format_collapsed": format_collapsed, + }
+ + + +
+[docs] +def evidence_map_by_evidence_id_local(evidence_map, eid: str): + """Local helper — returns the EvidenceObject whose ``evidence_id`` + matches ``eid``, or None. Avoids the import-cycle risk of pulling + `evidence_map_by_evidence_id` into this module's hot path; the + O(N) walk is fine since evidence maps are <30 entries. + """ + for obj in evidence_map or []: + if obj.evidence_id == eid: + return obj + return None
+ + + +# --------------------------------------------------------------------------- +# JSON variant — `answer_mode="claim_lattice"`. Same lattice semantics as +# the pointer variant, but the model emits a structured JSON object +# {"claims":[{"text":str,"evidence_ids":[str,...]}]} with content- +# addressed evidence_ids directly. Pairs naturally with grammar- +# constrained inference (vLLM guided_json, Claude/GPT-4 native JSON +# mode, Qwen 3.6 reasoner) where schema-conformance is generation-time- +# enforced. The lenient pre-parser above keeps the path survivable on +# inference paths without grammar guidance. +# --------------------------------------------------------------------------- + + +CLAIM_LATTICE_JSON_SCHEMA = { + "type": "object", + "properties": { + "claims": { + "type": "array", + "items": { + "type": "object", + "properties": { + "text": {"type": "string"}, + "evidence_ids": { + "type": "array", + "items": {"type": "string"}, + }, + }, + "required": ["text", "evidence_ids"], + "additionalProperties": False, + }, + }, + }, + "required": ["claims"], + "additionalProperties": False, +} + + +
+[docs] +def verify_claim_lattice_json( + answer_json_text: str, + evidence_map, + *, + allowed_source_roles: tuple[str, ...] = DEFAULT_ALLOWED_SOURCE_ROLES, + max_evidence_per_claim: int = DEFAULT_MAX_POINTERS_PER_CLAIM, + min_citation_coverage: float = DEFAULT_MIN_CITATION_COVERAGE, + max_claims_per_answer: int = DEFAULT_MAX_CLAIMS_PER_ANSWER, + subject_tokens_absent_threshold: int = DEFAULT_SUBJECT_TOKENS_ABSENT_THRESHOLD, + question: str | None = None, + warrant_check_enabled: bool = True, + deflection_check_enabled: bool = True, +) -> dict: + """Deterministic verifier for ``answer_mode="claim_lattice"`` (JSON). + + Parses the model's JSON output (lenient pre-parser handles markdown + fences / preamble / curly quotes / trailing commas), validates the + schema, then runs the same hard checks as ``verify_claim_lattice`` + but reading ``evidence_ids`` from the JSON claim objects. + + 2026-04-30: switched from content-addressed evidence_ids + (``Eed1b6e396``) to pointer_ids (``E1``, ``E2``, …) in the prompt + & JSON output. Hermes-3-8B was fabricating plausible content- + addressed IDs (``E1b6e396``-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 ``evidence_id_pairs`` + (cache/run-DAG continuity); only the prompt-facing surface + changes. + + 1. JSON parses (lenient). Failure → SCHEMA_INVALID, UNGROUNDED. + 2. Top-level is ``{"claims": [...]}``. + 3. Each claim is ``{"text": str, "evidence_ids": [str, ...]}``. + 4. Each evidence_id resolves in the runtime-built evidence map + (no model-invented IDs). + 5. Resolved entry's ``source_role`` is in ``allowed_source_roles``. + 6. Claim text contains no double-quote characters anywhere. + 7. Claim text non-empty. + 8. Claim's content tokens textually overlap the cited evidence span. + 9. ``len(evidence_ids) <= max_evidence_per_claim``. + + Returns a verdict in the same shape as ``verify_claim_lattice`` plus + a ``json_fixups`` field naming any drift the lenient parser had to + peel (``"fence"`` / ``"prose_trim"`` / ``"curly_quotes"`` / + ``"trailing_comma"``). Empty list = strict JSON parse on first try. + """ + from aborist.qa.evidence import ( + evidence_map_by_pointer_id as _by_pointer, + render_claim_lattice as _render, + ) + + by_pointer = _by_pointer(evidence_map) + violations: list[dict] = [] + claim_statuses: list[dict] = [] + unverified: list[str] = [] + json_fixups: list[str] = [] + + parsed = None + try: + parsed, json_fixups = _lenient_json_parse(answer_json_text or "") + except Exception as exc: + violations.append({ + "kind": "SCHEMA_INVALID", + "reason": f"json parse: {str(exc)[:200]}", + }) + if parsed is not None and not isinstance(parsed, dict): + violations.append({ + "kind": "SCHEMA_INVALID", + "reason": f"top-level not object (got {type(parsed).__name__})", + }) + parsed = None + raw_claims = (parsed or {}).get("claims") if parsed is not None else None + if parsed is not None and not isinstance(raw_claims, list): + violations.append({ + "kind": "SCHEMA_INVALID", + "reason": "missing or non-list 'claims'", + }) + raw_claims = None + + # Claim-count ceiling — same defense-in-depth signal as the + # pointer verifier. A "tell me all there is to know" prompt + # shape can spam encyclopedic claims; cap demotes the verdict + # so the runaway is operator-visible regardless of per-claim + # verification success. + if isinstance(raw_claims, list) and len(raw_claims) > max_claims_per_answer: + violations.append({ + "kind": "TOO_MANY_CLAIMS", + "n_claims": len(raw_claims), + "max": max_claims_per_answer, + }) + + n_pairs = 0 + n_pairs_verified = 0 + valid_claims: list[dict] = [] + evidence_id_pairs: list[list[str]] = [] + + for idx, c in enumerate(raw_claims or []): + if not isinstance(c, dict): + violations.append({ + "kind": "SCHEMA_INVALID", + "claim_idx": idx, + "reason": f"claim not object (got {type(c).__name__})", + }) + claim_statuses.append({ + "text": "", "evidence_ids": [], + "status": "SCHEMA_INVALID", "reasons": ["not_object"], + }) + continue + claim_text = c.get("text") or "" + eids = c.get("evidence_ids") or [] + if not isinstance(claim_text, str) or not isinstance(eids, list): + violations.append({ + "kind": "SCHEMA_INVALID", "claim_idx": idx, + "reason": "claim shape: text=str, evidence_ids=list[str]", + }) + claim_statuses.append({ + "text": str(claim_text)[:200], "evidence_ids": [], + "status": "SCHEMA_INVALID", "reasons": ["bad_field_types"], + }) + continue + + # Manual-quote prohibition (same rule as pointer mode). + if _has_manual_quote(claim_text): + violations.append({ + "kind": "MANUAL_QUOTE_VIOLATION", "claim_idx": idx, + "claim_text": claim_text[:200], + }) + unverified.append(claim_text) + claim_statuses.append({ + "text": claim_text, "evidence_ids": eids, + "status": "MANUAL_QUOTE_VIOLATION", + "reasons": ["double_quote_in_text"], + }) + n_pairs += max(1, len(eids)) + continue + + if not claim_text.strip(): + violations.append({ + "kind": "SCHEMA_INVALID", "claim_idx": idx, + "reason": "empty claim text", + }) + claim_statuses.append({ + "text": "", "evidence_ids": eids, + "status": "SCHEMA_INVALID", "reasons": ["empty_text"], + }) + continue + + if len(eids) > max_evidence_per_claim: + violations.append({ + "kind": "TOO_MANY_EVIDENCE_IDS", "claim_idx": idx, + "claim_text": claim_text[:200], + "n_ids": len(eids), "max": max_evidence_per_claim, + }) + + # Per-id resolution + checks. ``eids`` are pointer_ids + # (E1, E2, …) emitted by the model; we resolve each to its + # EvidenceObject and capture the content-addressed + # ``evidence_id`` for the cache/run-DAG handle. Pointer-style + # IDs make fabrication obvious — if only E1-E10 were shown, + # an emitted "E27" reads as a hallucination at the schema + # check, not as a near-miss content-addressed string. + per_id_results = [] + verified_pointer_ids: list[str] = [] + verified_evidence_ids: list[str] = [] + for eid in eids: + if not isinstance(eid, str): + per_id_results.append({"eid": str(eid), "ok": False, "kind": "SCHEMA_INVALID"}) + continue + obj = by_pointer.get(eid) + if obj is None: + per_id_results.append({"eid": eid, "ok": False, "kind": "UNKNOWN_EVIDENCE_ID"}) + violations.append({ + "kind": "UNKNOWN_EVIDENCE_ID", + "claim_idx": idx, "evidence_id": eid, + }) + continue + if obj.source_role not in allowed_source_roles: + per_id_results.append({"eid": eid, "ok": False, "kind": "SOURCE_ROLE_BLOCKED"}) + violations.append({ + "kind": "SOURCE_ROLE_BLOCKED", + "claim_idx": idx, "evidence_id": obj.evidence_id, + "pointer_id": eid, + "source_role": obj.source_role, + }) + continue + if not _claim_textually_overlaps_evidence( + claim_text, obj.span, min_coverage=min_citation_coverage + ): + per_id_results.append({"eid": eid, "ok": False, "kind": "CITATION_MISMATCH"}) + violations.append({ + "kind": "CITATION_MISMATCH", + "claim_idx": idx, "evidence_id": obj.evidence_id, + "pointer_id": eid, + "claim_text": claim_text[:200], + }) + continue + per_id_results.append({"eid": eid, "ok": True}) + verified_pointer_ids.append(eid) + verified_evidence_ids.append(obj.evidence_id) + + n_pairs += max(1, len(eids)) + n_pairs_verified += len(verified_pointer_ids) + + if not eids: + claim_statuses.append({ + "text": claim_text, "evidence_ids": [], + "status": "NO_EVIDENCE_POINTER", + "reasons": ["no_evidence_ids"], + }) + unverified.append(claim_text) + n_pairs += 1 + continue + + if len(verified_pointer_ids) == len(eids): + status = "EVIDENCE_LINKED" + elif verified_pointer_ids: + status = "EVIDENCE_LINKED_PARTIAL" + else: + # Pick the worst per-id reason for the claim status. + kinds = [r["kind"] for r in per_id_results if not r["ok"]] + status = kinds[0] if kinds else "UNKNOWN_EVIDENCE_ID" + unverified.append(claim_text) + + # claim_statuses records BOTH ids: pointer (what model wrote) + # and content-addressed (run-stable handle). Keeps the audit + # trail legible at both layers. + claim_statuses.append({ + "text": claim_text, + "pointer_ids": list(eids), + "evidence_ids": list(verified_evidence_ids), + "status": status, + "reasons": [r["kind"] for r in per_id_results if not r["ok"]], + }) + if verified_pointer_ids: + # Renderer takes the pointer-id form (model's view) and the + # by_pointer index; cache/run-DAG get the content-addressed + # evidence_ids (run-stable form). + valid_claims.append({ + "text": claim_text, + "pointer_ids": verified_pointer_ids, + }) + evidence_id_pairs.append(list(verified_evidence_ids)) + + rendered_text = _render(valid_claims, by_pointer) if valid_claims else "" + + if n_pairs_verified > 0 and not violations: + audit_mode = "STRICT" + elif n_pairs_verified > 0: + audit_mode = "HYBRID" + else: + audit_mode = "UNGROUNDED" + + # Warrant-lite — same relation-question hard check as the pointer + # variant. See verify_claim_lattice for the rationale (Ticket H, + # 2026-05-01). Identical demote-to-HYBRID semantics; the JSON + # variant carries the same WARRANT_MISSING violations & the same + # warrant_missing_claim_idxs field on the verdict. + warrant_missing_claims: list[int] = [] + if warrant_check_enabled: + for cs in claim_statuses: + if cs.get("status") not in ("EVIDENCE_LINKED", "EVIDENCE_LINKED_PARTIAL"): + continue + cited_eids = cs.get("evidence_ids") or [] + cited_spans = [ + obj.span + for eid in cited_eids + for obj in [evidence_map_by_evidence_id_local(evidence_map, eid)] + if obj is not None + ] + ok, missing = warrant_check( + cs.get("text") or "", cited_spans, question=question + ) + if not ok: + warrant_missing_claims.append(cs.get("claim_idx")) + violations.append({ + "kind": "WARRANT_MISSING", + "claim_idx": cs.get("claim_idx"), + "missing_anchors": missing, + "rationale": ( + "claim asserts an answer entity or specific date " + "not present in any cited span — pointer-linked " + "but warrant missing" + ), + }) + if warrant_missing_claims and audit_mode == "STRICT": + audit_mode = "HYBRID" + + # Rule 8 — Title-relevance check (mirrors the pointer variant). + # See verify_claim_lattice for rationale (2026-05-02 spin-glass + # case). Demote-to-HYBRID semantics; JSON variant emits the same + # TITLE_MISMATCH violation kind & title_mismatch_claim_idxs field. + title_mismatch_claims: list[int] = [] + for cs in claim_statuses: + if cs.get("status") not in ("EVIDENCE_LINKED", "EVIDENCE_LINKED_PARTIAL"): + continue + cited_eids = cs.get("evidence_ids") or [] + cited_titles = [ + obj.title + for eid in cited_eids + for obj in [evidence_map_by_evidence_id_local(evidence_map, eid)] + if obj is not None + ] + if not cited_titles: + continue + any_overlap = any( + _claim_title_overlap(cs.get("text") or "", t) + for t in cited_titles + ) + if not any_overlap: + title_mismatch_claims.append(cs.get("claim_idx")) + violations.append({ + "kind": "TITLE_MISMATCH", + "claim_idx": cs.get("claim_idx"), + "claim_text": (cs.get("text") or "")[:200], + "cited_titles": cited_titles, + "rationale": ( + "no cited source's title shares a content token " + "with the claim — pointer-linked but the cited " + "document is structurally unrelated to the claim" + ), + }) + if title_mismatch_claims and audit_mode == "STRICT": + audit_mode = "HYBRID" + # Tightening (2026-05-02): mirrors the pointer-variant promotion. + # When EVERY resolving claim has TITLE_MISMATCH, demote to + # UNGROUNDED — the substrate has zero structural grounding for + # the user's question. See verify_claim_lattice for full rationale. + n_resolving = sum( + 1 + for cs in claim_statuses + if cs.get("status") in ("EVIDENCE_LINKED", "EVIDENCE_LINKED_PARTIAL") + ) + if ( + title_mismatch_claims + and n_resolving > 0 + and len(title_mismatch_claims) == n_resolving + ): + audit_mode = "UNGROUNDED" + + # Rule 9 — Subject-tokens-absent / premise-parroting check. See + # `verify_claim_lattice` for the full rationale. + subject_absent_claims: list[int] = [] + if question and subject_tokens_absent_threshold > 0: + for cs in claim_statuses: + if cs.get("status") not in ("EVIDENCE_LINKED", "EVIDENCE_LINKED_PARTIAL"): + continue + cited_eids = cs.get("evidence_ids") or [] + cited_spans = [] + for eid in cited_eids: + obj = evidence_map_by_evidence_id_local(evidence_map, eid) + if obj is not None and obj.span: + cited_spans.append(obj.span) + if not cited_spans: + continue + absent = _parroted_subject_tokens_absent( + question, cs.get("text") or "", cited_spans + ) + if len(absent) >= subject_tokens_absent_threshold: + subject_absent_claims.append(cs.get("claim_idx")) + violations.append({ + "kind": "SUBJECT_TOKENS_ABSENT", + "claim_idx": cs.get("claim_idx"), + "claim_text": (cs.get("text") or "")[:200], + "absent_tokens": sorted(absent), + "rationale": ( + f"{len(absent)} question-distinctive tokens echoed in " + f"the claim are absent from cited evidence — claim " + f"parrots question premise without anchoring it" + ), + }) + if subject_absent_claims and audit_mode == "STRICT": + audit_mode = "HYBRID" + + # Deflection check (parallel to pointer-variant promotion). + deflection_detected = False + if deflection_check_enabled and question and rendered_text: + # Deferred import to avoid pulling aborist.compress + aborist.store + # at verify.py module-load time when callers may not need them. + from aborist.qa.inspect import diagnose_deflection + signal = diagnose_deflection(question, rendered_text) + if signal.get("kind") == "deflection": + deflection_detected = True + violations.append({ + "kind": "DEFLECTION_DETECTED", + "subject_anchor": signal.get("subject_anchor"), + "overlap_ratio": signal.get("overlap_ratio"), + "rationale": ( + "answer's content tokens omit the question's " + "subject anchor — model answered an adjacent " + "grounded question rather than the user's " + "specific one" + ), + }) + if deflection_detected and audit_mode == "STRICT": + audit_mode = "HYBRID" + + # Same `verifier_method` as the pointer variant ("claim_lattice") + # so the providence_cache CHECK constraint accepts both. The mode + # is disambiguated downstream via `answer_mode` on the run-DAG & + # via the JSON-only `json_fixups` field on this verdict. + return { + "n_quotes": n_pairs, + "n_verified": n_pairs_verified, + "audit_mode": audit_mode, + "unverified_quotes": unverified, + "verifier_method": "claim_lattice", + "claim_statuses": claim_statuses, + "violations": violations, + "rendered_text": rendered_text, + "evidence_id_pairs": evidence_id_pairs, + "json_fixups": json_fixups, + "warrant_missing_claim_idxs": warrant_missing_claims, + "title_mismatch_claim_idxs": title_mismatch_claims, + }
+ +
+
+
+
+ + +
+
+ + Made with Sphinx and @pradyunsg's + + Furo + +
+
+ +
+
+ +
+
+ +
+
+ + + + + \ No newline at end of file diff --git a/docs/_source/_build/html/_modules/aborist/search/base.html b/docs/_source/_build/html/_modules/aborist/search/base.html new file mode 100644 index 0000000..852e070 --- /dev/null +++ b/docs/_source/_build/html/_modules/aborist/search/base.html @@ -0,0 +1,325 @@ + + + + + + + + aborist.search.base - Aborist API Reference + + + + + + + + + + + + + + + + Contents + + + + + + Menu + + + + + + + + Expand + + + + + + Light mode + + + + + + + + + + + + + + Dark mode + + + + + + + Auto light/dark, in light mode + + + + + + + + + + + + + + + Auto light/dark, in dark mode + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Skip to content + + + +
+
+
+ +
+ +
+
+ +
+ +
+
+ +
+
+
+ + + + + Back to top + +
+
+ +
+ +
+
+

Source code for aborist.search.base

+"""Search backend ABC + Hit dataclass with explicit audit mode.
+
+Every search hit carries an `audit_mode` so callers never overclaim. Aborist
+adapts the Merkle-AGI v7 audit-mode trichotomy to the RAG layer:
+- STRICT     — Merkle-verified evidence: every claim cited verbatim against
+               the source-content tree.
+- HYBRID     — partial / mixed evidence: some claims source-grounded, others
+               emerged from training. Cache or search hit is partially trusted.
+- UNGROUNDED — no recoverable proof of grounding. Keyword (FTS5) hits land
+               here by default; LLM answers fall here when no double-quoted
+               span, sentence, or proper-noun phrase verifies against context.
+               Substrate name was VISUAL (no formal guarantees attached); we
+               renamed to UNGROUNDED so the RAG semantic is explicit.
+"""
+
+from __future__ import annotations
+
+import enum
+import sqlite3
+from abc import ABC, abstractmethod
+from dataclasses import dataclass
+
+
+
+[docs] +class AuditMode(str, enum.Enum): + STRICT = "STRICT" + HYBRID = "HYBRID" + UNGROUNDED = "UNGROUNDED"
+ + + +
+[docs] +@dataclass(frozen=True) +class Hit: + document_root: str + document_uri: str + chunk_idx: int + snippet: str + score: float + audit_mode: AuditMode + title: str | None = None
+ + + +
+[docs] +class SearchBackend(ABC): + """A search hook over the chunk store.""" + + name: str + audit_mode: AuditMode # default mode this backend reports + + def __init__(self, conn: sqlite3.Connection): + self.conn = conn + +
+[docs] + @abstractmethod + def search(self, query: str, limit: int = 20) -> list[Hit]: + ...
+
+ +
+
+
+
+ + +
+
+ + Made with Sphinx and @pradyunsg's + + Furo + +
+
+ +
+
+ +
+
+ +
+
+ + + + + \ No newline at end of file diff --git a/docs/_source/_build/html/_modules/aborist/search/fts5.html b/docs/_source/_build/html/_modules/aborist/search/fts5.html new file mode 100644 index 0000000..bfa9573 --- /dev/null +++ b/docs/_source/_build/html/_modules/aborist/search/fts5.html @@ -0,0 +1,508 @@ + + + + + + + + aborist.search.fts5 - Aborist API Reference + + + + + + + + + + + + + + + + Contents + + + + + + Menu + + + + + + + + Expand + + + + + + Light mode + + + + + + + + + + + + + + Dark mode + + + + + + + Auto light/dark, in light mode + + + + + + + + + + + + + + + Auto light/dark, in dark mode + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Skip to content + + + +
+
+
+ +
+ +
+
+ +
+ +
+
+ +
+
+
+ + + + + Back to top + +
+
+ +
+ +
+
+

Source code for aborist.search.fts5

+"""SQLite FTS5 keyword search. Returns UNGROUNDED-mode hits (no proof claim).
+
+Snippet generation runs in Python because chunks_fts is contentless
+(`content=''`) — SQLite's snippet()/highlight() functions return empty
+strings under contentless mode. We JOIN the FTS5 hit rowid back to
+`chunks.chunk_id` to fetch and decompress the original chunk content,
+then locate query tokens locally.
+"""
+
+from __future__ import annotations
+
+import re
+
+from aborist.compress import unpack_chunk
+from aborist.search.base import AuditMode, Hit, SearchBackend
+
+
+_FTS5_TOKEN_RE = re.compile(r"[A-Za-z][A-Za-z0-9]*")
+_FTS5_STOPWORDS = frozenset(
+    """
+    the a an is are was were be been being
+    of to in on at for with by from as about into through during
+    and or but not no nor so yet too very also just
+    what who where when why how which this that these those such
+    i you he she it we they me him her us them
+    do does did have has had can could should would will may might
+    tell show describe explain summarize say give list find make
+    please
+    all there know everything anything something
+
+    one some another without soon currently
+    """.split()
+)
+
+
+# OR-mode fallback hits SQLite FTS5 with one clause per token. With 15+
+# tokens including common English connectors it matches millions of
+# docs, then BM25 has to rank them all to pick the top-K — 13s/shard
+# observed on a 3.47M-doc corpus. Long queries that fail AND-mode
+# should not pay for an OR-mode that's effectively a full-corpus scan.
+# Cap OR-mode at the top-N LONGEST tokens (proxy for rarity / topical
+# specificity — "neurotechnology" matters; "soon" doesn't).
+_OR_FALLBACK_MAX_TOKENS = 5
+
+
+def _query_tokens(query: str) -> list[str]:
+    raw = _FTS5_TOKEN_RE.findall(query)
+    return [t for t in raw if t.lower() not in _FTS5_STOPWORDS and len(t) > 1]
+
+
+def _quote(t: str) -> str:
+    return '"' + t.replace('"', '""') + '"'
+
+
+def _escape_fts5(
+    query: str,
+    *,
+    mode: str = "and",
+    extra_or_tokens: set[str] | None = None,
+) -> str:
+    """Build a MATCH expression from a free-text query.
+
+    Tokenizes by alpha runs (so `?` and other punctuation can't break the
+    quoted phrase), drops question stopwords ('what', 'tell', etc.), then:
+
+    - mode='and' (default): every content token must appear in the doc.
+      Strict relevance — keeps unrelated docs out of the context window.
+    - mode='or':  the top-N LONGEST tokens (proxy for topical specificity)
+      get OR-joined. Used as a fallback when AND returns zero hits.
+      Capped at ``_OR_FALLBACK_MAX_TOKENS`` so OR-mode doesn't degrade
+      into a full-corpus scan on long noisy queries (a 19-token OR
+      clause matches millions of docs and forces BM25 to rank them all
+      — 13s/shard observed pre-cap).
+
+    The ``extra_or_tokens`` kwarg accepts synonym-expanded tokens
+    (e.g. "telepathy" / "neurotechnology" expanded from the query token
+    "thoughts"). These join the top-N-longest OR pool — long synonym
+    tokens like "neurotechnology" (15 chars) outrank short query tokens
+    like "thoughts" (8) by length and surface the right titles. Pure
+    quality win at OR-mode-fallback time without extra retrieval cost
+    since the top-N cap still applies to the merged pool.
+
+    All-stopword queries fall back to OR over the raw tokens so they
+    still find something instead of crashing FTS5 with an empty MATCH.
+    """
+    tokens = _query_tokens(query)
+    if not tokens:
+        raw = _FTS5_TOKEN_RE.findall(query)
+        tokens = [t for t in raw if len(t) > 1] or ['""']
+        sep = " OR "
+    elif mode == "and":
+        sep = " AND "
+    else:
+        # OR fallback: keep only the rarest tokens (approximated by
+        # longest — long words tend to be more topical / rarer in the
+        # corpus). Bounds the per-clause cost so OR-mode terminates
+        # quickly instead of scanning the corpus.
+        sep = " OR "
+        candidate_pool = list(tokens)
+        if extra_or_tokens:
+            # Synonyms join the OR pool; dedupe lowercase.
+            seen_lower = {t.lower() for t in candidate_pool}
+            for t in extra_or_tokens:
+                tl = t.lower()
+                if tl and tl not in seen_lower and tl not in _FTS5_STOPWORDS:
+                    candidate_pool.append(tl)
+                    seen_lower.add(tl)
+        if len(candidate_pool) > _OR_FALLBACK_MAX_TOKENS:
+            candidate_pool = sorted(candidate_pool, key=len, reverse=True)[
+                :_OR_FALLBACK_MAX_TOKENS
+            ]
+        tokens = candidate_pool
+    return sep.join(_quote(t) for t in tokens)
+
+
+# Snippet rendering. Locate any query token (case-insensitive) in the chunk
+# text, return ~16 words of surrounding context with the matched token
+# bracketed. If no token matches (rare: query was all-stopwords or the
+# tokens only appear in titles), fall back to the chunk's leading slice.
+_SNIPPET_WINDOW_WORDS = 16
+
+
+def _build_snippet(text: str, query: str) -> str:
+    if not text:
+        return ""
+    tokens = _query_tokens(query)
+    if not tokens:
+        # Best-effort: leading slice.
+        words = text.split()
+        return " ".join(words[: _SNIPPET_WINDOW_WORDS * 2])
+
+    # Find the earliest case-insensitive match of any query token.
+    text_lower = text.lower()
+    best_pos = -1
+    best_token = ""
+    for t in tokens:
+        pos = text_lower.find(t.lower())
+        if pos >= 0 and (best_pos < 0 or pos < best_pos):
+            best_pos = pos
+            best_token = t
+    if best_pos < 0:
+        words = text.split()
+        return " ".join(words[: _SNIPPET_WINDOW_WORDS * 2])
+
+    # Walk word boundaries around the match position.
+    words = text.split()
+    if not words:
+        return ""
+    # Map character position to word index (approximate — split() collapses
+    # runs of whitespace; close enough for visual snippet purposes).
+    char_count = 0
+    target_word = 0
+    for i, w in enumerate(words):
+        char_count += len(w) + 1  # +1 for the join space
+        if char_count > best_pos:
+            target_word = i
+            break
+
+    start = max(0, target_word - _SNIPPET_WINDOW_WORDS)
+    end = min(len(words), target_word + _SNIPPET_WINDOW_WORDS)
+    window = words[start:end]
+
+    # Bracket every case-insensitive occurrence of every matched token in
+    # the window. Done with a precompiled regex for each token.
+    rendered = " ".join(window)
+    for t in tokens:
+        pat = re.compile(re.escape(t), re.IGNORECASE)
+        rendered = pat.sub(lambda m: f"[{m.group(0)}]", rendered)
+
+    if start > 0:
+        rendered = "…" + rendered
+    if end < len(words):
+        rendered = rendered + "…"
+    return rendered
+
+
+
+[docs] +class FTS5Backend(SearchBackend): + name = "fts5" + audit_mode = AuditMode.UNGROUNDED + +
+[docs] + def search( + self, + query: str, + limit: int = 20, + extra_or_tokens: set[str] | None = None, + ) -> list[Hit]: + """Run FTS5 BM25 over chunk content. + + ``extra_or_tokens`` (synonym-expanded set) is passed through to + the OR-mode fallback only. AND mode stays on original query + tokens (adding synonyms there would relax the AND constraint + and pull in noise). The intended caller is the retrieval + pipeline that has already computed ``synonym_expand(qtokens)`` + — passing it here saves the OR-mode pool from missing topical + synonym terms. + """ + if not query.strip(): + return [] + # Try strict AND first; fall back to OR if it returns nothing. + for mode in ("and", "or"): + fts_query = _escape_fts5( + query, + mode=mode, + extra_or_tokens=extra_or_tokens if mode == "or" else None, + ) + try: + rows = self.conn.execute( + """ + SELECT + c.document_root, + c.idx, + c.content AS raw_content, + bm25(chunks_fts) AS rank, + d.document_uri, + d.title + FROM chunks_fts AS f + JOIN chunks AS c ON c.chunk_id = f.rowid + JOIN documents AS d ON d.document_root = c.document_root + WHERE chunks_fts MATCH ? + ORDER BY rank ASC + LIMIT ? + """, + (fts_query, limit), + ).fetchall() + except Exception: + rows = [] + if rows: + break + return [ + Hit( + document_root=r["document_root"], + document_uri=r["document_uri"], + chunk_idx=r["idx"], + snippet=_build_snippet(unpack_chunk(r["raw_content"]) or "", query), + # bm25 returns negative numbers (lower = better); flip sign. + score=-float(r["rank"]) if r["rank"] is not None else 0.0, + audit_mode=self.audit_mode, + title=r["title"], + ) + for r in rows + ]
+
+ +
+
+
+
+ + +
+
+ + Made with Sphinx and @pradyunsg's + + Furo + +
+
+ +
+
+ +
+
+ +
+
+ + + + + \ No newline at end of file diff --git a/docs/_source/_build/html/_modules/aborist/source.html b/docs/_source/_build/html/_modules/aborist/source.html new file mode 100644 index 0000000..4c5bde8 --- /dev/null +++ b/docs/_source/_build/html/_modules/aborist/source.html @@ -0,0 +1,291 @@ + + + + + + + + aborist.source - Aborist API Reference + + + + + + + + + + + + + + + + Contents + + + + + + Menu + + + + + + + + Expand + + + + + + Light mode + + + + + + + + + + + + + + Dark mode + + + + + + + Auto light/dark, in light mode + + + + + + + + + + + + + + + Auto light/dark, in dark mode + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Skip to content + + + +
+
+
+ +
+ +
+
+ +
+ +
+
+ +
+
+
+ + + + + Back to top + +
+
+ +
+ +
+
+

Source code for aborist.source

+"""Source ABC.
+
+Adding a new corpus to aborist = one new Source subclass. The Source contract
+is intentionally minimal: yield Document objects, one at a time.
+"""
+
+from __future__ import annotations
+
+from abc import ABC, abstractmethod
+from typing import Iterator
+
+from aborist.document import Document
+
+
+
+[docs] +class Source(ABC): + """A corpus that yields documents into the ingest pipeline.""" + + #: source_type tag stored on every Document this source produces. + source_type: str + +
+[docs] + @abstractmethod + def iter_documents(self) -> Iterator[Document]: + """Yield Document objects. Must be deterministic & idempotent.""" + ...
+
+ +
+
+
+
+ + +
+
+ + Made with Sphinx and @pradyunsg's + + Furo + +
+
+ +
+
+ +
+
+ +
+
+ + + + + \ No newline at end of file diff --git a/docs/_source/_build/html/_modules/aborist/sources/html_page.html b/docs/_source/_build/html/_modules/aborist/sources/html_page.html new file mode 100644 index 0000000..3f5774f --- /dev/null +++ b/docs/_source/_build/html/_modules/aborist/sources/html_page.html @@ -0,0 +1,419 @@ + + + + + + + + aborist.sources.html_page - Aborist API Reference + + + + + + + + + + + + + + + + Contents + + + + + + Menu + + + + + + + + Expand + + + + + + Light mode + + + + + + + + + + + + + + Dark mode + + + + + + + Auto light/dark, in light mode + + + + + + + + + + + + + + + Auto light/dark, in dark mode + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Skip to content + + + +
+
+
+ +
+ +
+
+ +
+ +
+
+ +
+
+
+ + + + + Back to top + +
+
+ +
+ +
+
+

Source code for aborist.sources.html_page

+"""HTML page source.
+
+Fetches URLs, honors robots.txt automatically, strips noise (script/style/nav/
+footer/header), extracts main body text + outbound `<a href>` links as edges.
+
+Optional dependency. Install with `pip install aborist[html]`.
+"""
+
+from __future__ import annotations
+
+import re
+import urllib.parse
+import urllib.robotparser
+from pathlib import Path
+from typing import Iterable, Iterator
+
+try:
+    import httpx
+    from selectolax.parser import HTMLParser
+except ImportError as e:  # pragma: no cover
+    raise ImportError(
+        "HTML source requires extras: pip install 'aborist[html]'"
+    ) from e
+
+from aborist.document import Document, Edge
+from aborist.source import Source
+
+
+USER_AGENT = "aborist/0.0.1 (+https://unturf.com)"
+NOISE_SELECTORS = ("script", "style", "noscript", "nav", "header", "footer", "aside")
+
+
+def _normalize_text(text: str) -> str:
+    text = re.sub(r"[ \t]+", " ", text)
+    text = re.sub(r"\n{3,}", "\n\n", text)
+    return text.strip()
+
+
+
+[docs] +def parse_html(url: str, html: str, source_type: str = "html") -> Document | None: + """Pure parse function. Separated so tests can run without network.""" + tree = HTMLParser(html) + for sel in NOISE_SELECTORS: + for node in tree.css(sel): + node.decompose() + + body = tree.css_first("body") or tree.root + if body is None: + return None + text = _normalize_text(body.text(separator="\n", strip=True)) + if not text: + return None + + title_node = tree.css_first("title") + title = title_node.text(strip=True) if title_node is not None else None + + edges: list[Edge] = [] + seen: set[tuple[str, str]] = set() + for a in tree.css("a[href]"): + href = (a.attributes.get("href") or "").strip() + if not href or href.startswith(("javascript:", "mailto:", "tel:", "#")): + continue + absolute = urllib.parse.urljoin(url, href) + split = urllib.parse.urlsplit(absolute) + if split.scheme not in ("http", "https"): + continue + anchor = split.fragment or "" + dst_uri = urllib.parse.urlunsplit(split._replace(fragment="")) + key = (dst_uri, anchor) + if key in seen: + continue + seen.add(key) + edges.append(Edge(edge_type="hyperlink", dst_uri=dst_uri, anchor=anchor or None)) + + return Document( + uri=url, + content=text, + source_type=source_type, + title=title, + edges=edges, + )
+ + + +
+[docs] +class HtmlPageSource(Source): + """Iterates a list of URLs, fetching and parsing each as HTML.""" + + source_type = "html" + + def __init__( + self, + urls: Iterable[str], + *, + respect_robots: bool = True, + timeout: float = 30.0, + ): + self.urls = list(urls) + self.respect_robots = respect_robots + self.timeout = timeout + self._robots_cache: dict[str, urllib.robotparser.RobotFileParser] = {} + +
+[docs] + @classmethod + def from_file(cls, path: str | Path, **kwargs) -> HtmlPageSource: + urls = [ + line.strip() + for line in Path(path).read_text(encoding="utf-8").splitlines() + if line.strip() and not line.lstrip().startswith("#") + ] + return cls(urls, **kwargs)
+ + +
+[docs] + def iter_documents(self) -> Iterator[Document]: + with httpx.Client( + headers={"User-Agent": USER_AGENT}, + timeout=self.timeout, + follow_redirects=True, + ) as client: + for url in self.urls: + if self.respect_robots and not self._allowed(client, url): + continue + try: + resp = client.get(url) + resp.raise_for_status() + except httpx.HTTPError: + continue + ctype = resp.headers.get("content-type", "").lower() + if "html" not in ctype and "xml" not in ctype: + continue + doc = parse_html(str(resp.url), resp.text, self.source_type) + if doc is not None: + yield doc
+ + + def _allowed(self, client: "httpx.Client", url: str) -> bool: + parsed = urllib.parse.urlparse(url) + origin = f"{parsed.scheme}://{parsed.netloc}" + rp = self._robots_cache.get(origin) + if rp is None: + rp = urllib.robotparser.RobotFileParser() + try: + resp = client.get(f"{origin}/robots.txt") + except httpx.HTTPError: + resp = None + if resp is not None and resp.status_code == 200: + rp.parse(resp.text.splitlines()) + else: + # Missing robots.txt = no rules per RFC 9309. + rp.allow_all = True + self._robots_cache[origin] = rp + return rp.can_fetch(USER_AGENT, url)
+ +
+
+
+
+ + +
+
+ + Made with Sphinx and @pradyunsg's + + Furo + +
+
+ +
+
+ +
+
+ +
+
+ + + + + \ No newline at end of file diff --git a/docs/_source/_build/html/_modules/aborist/sources/wikipedia.html b/docs/_source/_build/html/_modules/aborist/sources/wikipedia.html new file mode 100644 index 0000000..7e01318 --- /dev/null +++ b/docs/_source/_build/html/_modules/aborist/sources/wikipedia.html @@ -0,0 +1,676 @@ + + + + + + + + aborist.sources.wikipedia - Aborist API Reference + + + + + + + + + + + + + + + + Contents + + + + + + Menu + + + + + + + + Expand + + + + + + Light mode + + + + + + + + + + + + + + Dark mode + + + + + + + Auto light/dark, in light mode + + + + + + + + + + + + + + + Auto light/dark, in dark mode + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Skip to content + + + +
+
+
+ +
+ +
+
+ +
+ +
+
+ +
+
+
+ + + + + Back to top + +
+
+ +
+ +
+
+

Source code for aborist.sources.wikipedia

+"""MediaWiki 'cur' table SQL dump source.
+
+Handles 2003-era SQL dumps in bz2 format (e.g. 20030516_cur_tablesql.bz2).
+Yields one Document per non-redirect main-namespace article, with
+[[wikilinks]] extracted as outbound edges.
+
+Implements a stream parser for MySQL extended INSERT syntax. The cur table
+schema for that era starts: cur_id, cur_namespace, cur_title, cur_text, ...
+We rely on positional access for the first four columns.
+"""
+
+from __future__ import annotations
+
+import bz2
+import re
+from pathlib import Path
+from typing import IO, Iterator
+
+from aborist.document import Document, Edge
+from aborist.source import Source
+
+
+# Match [[Target]], [[Target|display]], [[Target#anchor]] forms.
+WIKILINK_RE = re.compile(r"\[\[([^\]\|#\n\r]+)(?:#[^\]\|\n\r]*)?(?:\|[^\]\n\r]*)?\]\]")
+NAMESPACE_MAIN = 0
+
+
+_MYSQL_ESCAPE_MAP = {
+    "n": "\n",
+    "r": "\r",
+    "t": "\t",
+    "0": "\0",
+    "\\": "\\",
+    "'": "'",
+    '"': '"',
+    "Z": "\x1a",
+}
+
+
+def _decode_mysql_string(s: str) -> str:
+    """Decode MySQL-escaped string content (outer quotes already stripped).
+
+    Hot fast path: the vast majority of string fields contain no backslashes
+    at all. Returning the input unchanged for those skips the slow loop.
+    """
+    if "\\" not in s:
+        return s
+    out: list[str] = []
+    i = 0
+    n = len(s)
+    # Cache the mapping locally for tight-loop dispatch.
+    while i < n:
+        # Jump forward to the next backslash with C-level find.
+        bs = s.find("\\", i)
+        if bs < 0:
+            out.append(s[i:])
+            break
+        if bs > i:
+            out.append(s[i:bs])
+        if bs + 1 >= n:
+            out.append("\\")
+            i = bs + 1
+            continue
+        nxt = s[bs + 1]
+        out.append(_MYSQL_ESCAPE_MAP.get(nxt, nxt))
+        i = bs + 2
+    return "".join(out)
+
+
+def _find_string_end(payload: str, start: int) -> int:
+    """Return position of the closing `'` for a string opened just before `start`.
+
+    Backslash escapes considered: even count of preceding backslashes => the
+    quote is a real terminator; odd count => the quote is escaped.
+    """
+    n = len(payload)
+    i = start
+    while i < n:
+        pos = payload.find("'", i)
+        if pos < 0:
+            return -1
+        bs = 0
+        p = pos - 1
+        while p >= start and payload[p] == "\\":
+            bs += 1
+            p -= 1
+        if bs % 2 == 0:
+            return pos
+        i = pos + 1
+    return -1
+
+
+def _split_values_tuples(payload: str) -> list[list[str | None]]:
+    """Parse `(v1,v2,...),(...),...` into tuples of decoded strings or None.
+
+    String slicing + str.find based. No per-char list.append. Roughly 5-10x
+    faster than the char-by-char version on real Wikipedia dumps.
+    """
+    rows: list[list[str | None]] = []
+    i = 0
+    n = len(payload)
+    while i < n:
+        # Find the next '(' starting a tuple.
+        open_paren = payload.find("(", i)
+        if open_paren < 0:
+            break
+        i = open_paren + 1
+        values: list[str | None] = []
+        while i < n:
+            # Skip leading whitespace inside the tuple.
+            while i < n and payload[i] in " \t":
+                i += 1
+            if i >= n:
+                break
+            if payload[i] == "'":
+                end = _find_string_end(payload, i + 1)
+                if end < 0:
+                    return rows  # malformed; bail
+                values.append(_decode_mysql_string(payload[i + 1 : end]))
+                i = end + 1
+            else:
+                # NULL or unquoted scalar; ends at , or )
+                end = i
+                while end < n and payload[end] not in ",)":
+                    end += 1
+                v = payload[i:end].strip()
+                values.append(None if v.upper() == "NULL" else v)
+                i = end
+            while i < n and payload[i] in " \t":
+                i += 1
+            if i < n and payload[i] == ",":
+                i += 1
+                continue
+            if i < n and payload[i] == ")":
+                i += 1
+                break
+            break
+        rows.append(values)
+    return rows
+
+
+def _iter_insert_statements(file_obj: IO[str]) -> Iterator[str]:
+    """Yield complete SQL statements using buffered string find.
+
+    State persists across read() chunks via three indices:
+      yield_from  position in `pending` where the next yielded statement starts
+      scan_pos    position to resume the scanner from (do NOT restart at 0
+                  across chunks — would re-find the already-processed open `'`)
+      in_string   are we inside a single-quoted string
+
+    The previous version reset the scanner to position 0 on every chunk,
+    which silently flipped in_string=False as soon as the first `'` in the
+    new buffer was re-encountered (the title-field open quote of the
+    article we were already deep inside). Persisting scan_pos fixes it.
+    """
+    pending = ""
+    in_string = False
+    yield_from = 0  # start of current statement, in `pending` coords
+    scan_pos = 0    # next position to scan, in `pending` coords
+
+    while True:
+        chunk = file_obj.read(1 << 19)
+        if not chunk:
+            break
+        pending += chunk
+        n = len(pending)
+
+        i = scan_pos
+        while i < n:
+            if in_string:
+                # Find string terminator (handle escape parity).
+                end = i
+                while True:
+                    pos = pending.find("'", end)
+                    if pos < 0:
+                        i = n  # need more data
+                        break
+                    bs = 0
+                    # Don't walk back past the start of the current statement;
+                    # chars before yield_from belong to a previous statement.
+                    p = pos - 1
+                    while p >= yield_from and pending[p] == "\\":
+                        bs += 1
+                        p -= 1
+                    if bs % 2 == 0:
+                        in_string = False
+                        i = pos + 1
+                        break
+                    end = pos + 1
+                if in_string:
+                    break
+                continue
+            sc = pending.find(";", i)
+            qt = pending.find("'", i)
+            if sc < 0 and qt < 0:
+                i = n
+                break
+            if qt < 0 or (sc >= 0 and sc < qt):
+                yield pending[yield_from : sc + 1]
+                yield_from = sc + 1
+                i = sc + 1
+            else:
+                in_string = True
+                i = qt + 1
+
+        scan_pos = i
+        # Release yielded bytes; remap our two indices into the new buffer.
+        if yield_from > 0:
+            pending = pending[yield_from:]
+            scan_pos -= yield_from
+            yield_from = 0
+
+    tail = pending[yield_from:]
+    if tail.strip():
+        yield tail
+
+
+def _extract_wikilinks(text: str, base_uri: str) -> list[Edge]:
+    seen: set[str] = set()
+    edges: list[Edge] = []
+    for m in WIKILINK_RE.finditer(text):
+        target = m.group(1).strip()
+        if not target or target.startswith(":"):
+            continue
+        # Skip image / file / category interlinks (they often start "Image:" etc.)
+        if ":" in target:
+            continue
+        uri = base_uri + target.replace(" ", "_")
+        if uri in seen:
+            continue
+        seen.add(uri)
+        edges.append(Edge(edge_type="wikilink", dst_uri=uri))
+    return edges
+
+
+
+[docs] +class WikipediaSqlDump(Source): + """Iterates a MediaWiki SQL table dump (cur or old), bz2 or plain. + + Both `cur` (current snapshot) and `old` (revision history) tables share + the first four column positions: id, namespace, title, text. The `cur` + table has `cur_is_redirect` at position 10 (we skip redirects); `old` + has no redirect flag (every revision is real). + + Shard support: pass `shard=(rank, total)` and the source yields only + docs whose 0-based index satisfies `index % total == rank`. Useful for + spawning N parallel ingest processes against the same dump file — + parser CPU runs in parallel, writes serialize at the WAL writer lock. + """ + + def __init__( + self, + path: str | Path, + *, + table: str = "cur", + namespace: int = NAMESPACE_MAIN, + base_uri: str = "https://en.wikipedia.org/wiki/", + shard: tuple[int, int] | None = None, + start_id: int = 0, + encoding: str = "latin-1", + ): + if table not in ("cur", "old"): + raise ValueError("table must be 'cur' or 'old'") + self.path = Path(path) + self.table = table + self.namespace = namespace + self.base_uri = base_uri + self.source_type = f"wikipedia_{table}" + if shard is not None: + rank, total = shard + if not (0 <= rank < total) or total < 1: + raise ValueError( + f"invalid shard {shard}: need 0 <= rank < total, total >= 1" + ) + self.shard = shard + # Resume support: skip rows whose id (cur_id or old_id) is <= start_id. + # The rsync-style fast-forward — already-cached docs aren't re-hashed. + self.start_id = start_id + # High-water mark observed during iteration. Caller reads this back + # after each batch and persists it via store.set_meta(). + self.last_id: int = start_id + # 2003-era MediaWiki dumps mix Latin-1 raw bytes (e.g., 0xE9 for é) + # with HTML entities. Latin-1 decode is lossless on every byte and + # gives the right code point for the raw-byte cases. Modern dumps + # are UTF-8 — pass encoding="utf-8" for those. + self.encoding = encoding + +
+[docs] + def iter_documents(self) -> Iterator[Document]: + opener = bz2.open if str(self.path).endswith(".bz2") else open + rank, total = (0, 1) if self.shard is None else self.shard + idx = 0 + with opener(self.path, "rt", encoding=self.encoding, errors="replace") as f: + for stmt in _iter_insert_statements(f): + head = stmt.lstrip() + if not head.upper().startswith("INSERT INTO"): + continue + up = head.upper() + vidx = up.find("VALUES") + if vidx < 0: + continue + table_clause = head[:vidx].lower() + token = f" {self.table} " + if token not in (table_clause + " "): + continue + payload = head[vidx + len("VALUES"):] + payload = payload.rstrip().rstrip(";").rstrip() + for row in _split_values_tuples(payload): + # Stride filter applied at the row index — every shard sees + # the full SQL stream but only emits its share. + if idx % total != rank: + idx += 1 + continue + idx += 1 + # Resume fast-forward: skip rows already cached. We still + # parse the value tuples (needed to find row[0]) but skip + # the wikilink extraction + Document construction, which + # is the dominant per-row cost. + if self.start_id: + try: + row_id = int(row[0]) if row[0] is not None else 0 + except (ValueError, TypeError): + row_id = 0 + if row_id <= self.start_id: + continue + if row_id > self.last_id: + self.last_id = row_id + else: + try: + row_id = int(row[0]) if row[0] is not None else 0 + if row_id > self.last_id: + self.last_id = row_id + except (ValueError, TypeError): + pass + yield from self._row_to_doc(row)
+ + + def _row_to_doc(self, row: list[str | None]) -> Iterator[Document]: + if len(row) < 4: + return + try: + ns = int(row[1]) if row[1] is not None else None + except (ValueError, TypeError): + return + if ns != self.namespace: + return + title = row[2] or "" + text = row[3] or "" + if not title or not text: + return + # Cur-only: skip rows flagged as redirects (col 10 in the 2003 schema). + if self.table == "cur": + is_redirect = False + if len(row) > 10 and row[10] is not None: + try: + is_redirect = bool(int(row[10])) + except (ValueError, TypeError): + is_redirect = False + if is_redirect: + return + edges = _extract_wikilinks(text, self.base_uri) + uri = self.base_uri + title.replace(" ", "_") + extra: dict = {} + # Surface the row id for resume / chronological ordering. + if row[0] is not None: + extra[f"{self.table}_id"] = row[0] + # `old` rows also carry a timestamp at position 7. + if self.table == "old" and len(row) > 7 and row[7]: + extra["old_timestamp"] = row[7] + yield Document( + uri=uri, + content=text, + source_type=self.source_type, + title=title, + edges=edges, + extra=extra, + )
+ + + +# Backward-compatible thin wrapper. +
+[docs] +class WikipediaCurDump(WikipediaSqlDump): + """Iterates a MediaWiki 'cur' table SQL dump.""" + + def __init__( + self, + path: str | Path, + namespace: int = NAMESPACE_MAIN, + base_uri: str = "https://en.wikipedia.org/wiki/", + ): + super().__init__( + path, table="cur", namespace=namespace, base_uri=base_uri + )
+ + + +
+[docs] +class WikipediaOldDump(WikipediaSqlDump): + """Iterates a MediaWiki 'old' (revision history) table SQL dump.""" + + def __init__( + self, + path: str | Path, + namespace: int = NAMESPACE_MAIN, + base_uri: str = "https://en.wikipedia.org/wiki/", + ): + super().__init__( + path, table="old", namespace=namespace, base_uri=base_uri + )
+ +
+
+
+
+ + +
+
+ + Made with Sphinx and @pradyunsg's + + Furo + +
+
+ +
+
+ +
+
+ +
+
+ + + + + \ No newline at end of file diff --git a/docs/_source/_build/html/_modules/aborist/store.html b/docs/_source/_build/html/_modules/aborist/store.html new file mode 100644 index 0000000..fe719f5 --- /dev/null +++ b/docs/_source/_build/html/_modules/aborist/store.html @@ -0,0 +1,1293 @@ + + + + + + + + aborist.store - Aborist API Reference + + + + + + + + + + + + + + + + Contents + + + + + + Menu + + + + + + + + Expand + + + + + + Light mode + + + + + + + + + + + + + + Dark mode + + + + + + + Auto light/dark, in light mode + + + + + + + + + + + + + + + Auto light/dark, in dark mode + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Skip to content + + + +
+
+
+ +
+ +
+
+ +
+ +
+
+ +
+
+
+ + + + + Back to top + +
+
+ +
+ +
+
+

Source code for aborist.store

+"""SQLite-backed v9.8 store.
+
+Schema implements the Merkle-AGI v9.8 admissibility ledger:
+- 8-dim providence_cache key (source_root, question_hash, model_profile_hash,
+  conversation_hash, governance_policy_hash, schema_version,
+  canonicalization_version, chunking_version)
+- falsification_state ∈ {live, failed, stale, quarantined}
+- audit_events append-only chain (event_hash chains via prev_event_hash)
+- documents.kind ∈ {surface, core} for layered compression
+- chunks.tier ∈ {hot, warm, cold} for reversible eviction
+- derivations table binds core docs back to source surface roots
+
+The providence_cache layer is schema-only in Phase 0 — no Q&A inference yet.
+"""
+
+from __future__ import annotations
+
+import json
+import sqlite3
+import time
+from contextlib import contextmanager
+from pathlib import Path
+from typing import Iterator
+
+
+DEFAULT_DB_PATH = Path.home() / ".aborist" / "aborist.db"
+
+
+SCHEMA_SQL = """
+PRAGMA journal_mode = WAL;
+PRAGMA foreign_keys = ON;
+
+CREATE TABLE IF NOT EXISTS schema_meta (
+    key   TEXT PRIMARY KEY,
+    value TEXT NOT NULL
+);
+
+-- Free-form per-DB metadata. Used by the resume mechanic to track each
+-- source's high-water mark so a stopped ingest can rsync forward without
+-- re-parsing rows that are already in this DB.
+CREATE TABLE IF NOT EXISTS meta (
+    key   TEXT PRIMARY KEY,
+    value TEXT NOT NULL,
+    updated_at INTEGER
+);
+
+-- Documents: surface (raw ingest) or core (distilled, Merkle-signed back).
+CREATE TABLE IF NOT EXISTS documents (
+    document_root            TEXT PRIMARY KEY,    -- hex sha256 of merkle root
+    document_uri             TEXT NOT NULL,
+    source_type              TEXT NOT NULL,
+    kind                     TEXT NOT NULL DEFAULT 'surface'
+                                CHECK (kind IN ('surface','core')),
+    compression_depth        INTEGER NOT NULL DEFAULT 0,
+    title                    TEXT,
+    chunking_version         TEXT NOT NULL,
+    canonicalization_version TEXT NOT NULL,
+    schema_version           TEXT NOT NULL,
+    ingest_ts                INTEGER NOT NULL,
+    hit_count                INTEGER NOT NULL DEFAULT 0,
+    last_hit_at              INTEGER
+);
+CREATE INDEX IF NOT EXISTS idx_documents_uri  ON documents(document_uri);
+CREATE INDEX IF NOT EXISTS idx_documents_kind ON documents(kind);
+
+-- Per-document HTTP metadata for cheap recrawl-checks. ETag and
+-- Last-Modified come from the response headers at ingest time and let a
+-- recrawl pass send conditional HEAD requests (If-None-Match /
+-- If-Modified-Since); a 304 lets us skip the body fetch entirely.
+-- last_status / last_checked_at record the most recent recheck so
+-- operators can audit "when was this URL last verified."
+CREATE TABLE IF NOT EXISTS document_http_meta (
+    document_root    TEXT PRIMARY KEY,
+    etag             TEXT,
+    last_modified    TEXT,
+    last_fetched_at  INTEGER NOT NULL,
+    last_status      INTEGER,
+    last_checked_at  INTEGER,
+    FOREIGN KEY (document_root) REFERENCES documents(document_root) ON DELETE CASCADE
+);
+
+-- Chunks with tier-based reversible eviction.
+-- content nullable: cold tier evicts content but retains leaf_hash + URI for
+-- rehydration. Identity verified on rehydrate by recomputing leaf_hash.
+--
+-- chunk_id INTEGER PRIMARY KEY AUTOINCREMENT serves dual duty: it's both the
+-- primary key and the rowid that the contentless FTS5 virtual table joins
+-- against. The (document_root, idx) UNIQUE constraint preserves the prior
+-- "one chunk per (doc, position)" invariant for callers that look up by it.
+CREATE TABLE IF NOT EXISTS chunks (
+    chunk_id      INTEGER PRIMARY KEY AUTOINCREMENT,
+    document_root TEXT NOT NULL,
+    idx           INTEGER NOT NULL,
+    leaf_hash     TEXT NOT NULL,
+    content       TEXT,
+    tier          TEXT NOT NULL DEFAULT 'hot'
+                     CHECK (tier IN ('hot','warm','cold')),
+    UNIQUE (document_root, idx),
+    FOREIGN KEY (document_root) REFERENCES documents(document_root) ON DELETE CASCADE
+);
+CREATE INDEX IF NOT EXISTS idx_chunks_leaf ON chunks(leaf_hash);
+
+-- Interior Merkle nodes (layer >= 1). Layer 0 lives in chunks.leaf_hash.
+CREATE TABLE IF NOT EXISTS merkle_nodes (
+    document_root TEXT NOT NULL,
+    layer         INTEGER NOT NULL,
+    idx           INTEGER NOT NULL,
+    hash          TEXT NOT NULL,
+    PRIMARY KEY (document_root, layer, idx),
+    FOREIGN KEY (document_root) REFERENCES documents(document_root) ON DELETE CASCADE
+);
+
+-- Cross-links between documents (the forest).
+-- Unresolved forward links (dst not yet ingested) carry dst_root='' and the
+-- ingest pass backfills dst_root when the target appears.
+--
+-- WITHOUT ROWID: the PK covers every column, so a default rowid-based table
+-- would near-duplicate the row data in the PK index. WITHOUT ROWID makes
+-- the table itself a B-tree keyed on the PK and saves ~50% of edge storage
+-- on real Wikipedia ingests (measured: 38 MB -> 21 MB / 1000 docs).
+-- Behaviorally identical; only the on-disk layout changes.
+CREATE TABLE IF NOT EXISTS edges (
+    src_root  TEXT NOT NULL,
+    dst_root  TEXT NOT NULL DEFAULT '',      -- '' = unresolved, backfilled later
+    dst_uri   TEXT NOT NULL DEFAULT '',      -- always present so we can resolve later
+    edge_type TEXT NOT NULL,                 -- wikilink, citation, derived_from, ...
+    anchor    TEXT NOT NULL DEFAULT '',      -- chunk index or fragment, '' if N/A
+    PRIMARY KEY (src_root, edge_type, dst_root, dst_uri, anchor)
+) WITHOUT ROWID;
+CREATE INDEX IF NOT EXISTS idx_edges_dst_root ON edges(dst_root) WHERE dst_root <> '';
+-- idx_edges_dst_uri intentionally omitted: only the gravity_top_inbound
+-- analytical query in cli.py filters on dst_uri alone, and a full scan +
+-- sort over edges is acceptable for that one-shot reporting path.
+
+-- Distillation: core_root <- src_root with Merkle-signed proof binding.
+CREATE TABLE IF NOT EXISTS derivations (
+    core_root    TEXT NOT NULL,
+    src_root     TEXT NOT NULL,
+    proof_blob   TEXT NOT NULL,              -- JSON merkle proof
+    process_id   TEXT NOT NULL,              -- distillation process identifier
+    distilled_at INTEGER NOT NULL,
+    PRIMARY KEY (core_root, src_root, process_id),
+    FOREIGN KEY (core_root) REFERENCES documents(document_root) ON DELETE CASCADE,
+    FOREIGN KEY (src_root)  REFERENCES documents(document_root) ON DELETE CASCADE
+);
+
+-- v9.8 providence cache: 8-dim admissibility key + falsification state.
+-- Schema-only in Phase 0 (no Q&A runs yet); ready for Phase 1.
+CREATE TABLE IF NOT EXISTS providence_cache (
+    cache_key                TEXT PRIMARY KEY,
+    source_root              TEXT NOT NULL,
+    document_uri             TEXT NOT NULL,
+    question_hash            TEXT NOT NULL,
+    question_text            TEXT NOT NULL,
+    answer_text              TEXT NOT NULL,
+    merkle_proof             TEXT NOT NULL,   -- JSON
+    model_profile_hash       TEXT NOT NULL,   -- model_id + revision + quantization
+    conversation_hash        TEXT NOT NULL,
+    governance_policy_hash   TEXT NOT NULL,
+    schema_version           TEXT NOT NULL,
+    canonicalization_version TEXT NOT NULL,
+    chunking_version         TEXT NOT NULL,
+    falsification_state      TEXT NOT NULL DEFAULT 'live'
+                                CHECK (falsification_state IN ('live','failed','stale','quarantined')),
+    chain                    TEXT NOT NULL DEFAULT 'private'
+                                CHECK (chain IN ('private','public')),
+    audit_event_hash         TEXT,            -- latest audit event for this record
+    created_at               INTEGER NOT NULL,
+    last_hit_at              INTEGER,
+    hit_count                INTEGER NOT NULL DEFAULT 0,
+    -- v9.8 audit_mode trichotomy (RAG-adapted vocabulary; substrate calls
+    -- UNGROUNDED "VISUAL"): STRICT (every quote in answer verified against
+    -- context), HYBRID (some claims verified, some emergent), UNGROUNDED
+    -- (no verbatim grounding — purely emergent from training).
+    -- Default UNGROUNDED: an unclassified record is the weakest claim.
+    audit_mode               TEXT NOT NULL DEFAULT 'UNGROUNDED'
+                                CHECK (audit_mode IN ('STRICT','HYBRID','UNGROUNDED')),
+    n_quotes                 INTEGER NOT NULL DEFAULT 0,
+    n_verified               INTEGER NOT NULL DEFAULT 0,
+    -- JSON array of quoted spans the model produced but we couldn't find
+    -- verbatim in context. Mining these surfaces "what the model emerged
+    -- beyond the corpus" — candidate ingest targets.
+    unverified_quotes        TEXT,
+    -- Which verifier strategy classified this record. 'quote' = model
+    -- followed the format and wrapped claims in double quotes. 'span' =
+    -- bullet/sentence-level substring match in context. 'entity' = no
+    -- spans matched but multi-word proper nouns did. 'paraphrase' =
+    -- token-coverage match (soft signal). 'claim_lattice' = quote-by-
+    -- pointer mode (model emitted JSON; verifier checked evidence_id
+    -- resolution + source_role + manual-quote prohibition). 'none' = no
+    -- evidence at all (truly emergent).
+    verifier_method          TEXT NOT NULL DEFAULT 'none'
+                                CHECK (verifier_method IN ('quote','span','entity','paraphrase','claim_lattice','none')),
+    -- Per-run Merkle-DAG. run_dag_root = MerkleTree over ordered stage
+    -- hashes (question / retrieval / context / prompt / answer / verify /
+    -- final_label). run_dag_blob carries the full {root, nodes} JSON so
+    -- an auditor can recompute & verify. Distinct from audit_event_hash
+    -- (linear DB-wide chain). NULL on legacy records pre-2026-04-30.
+    run_dag_root             TEXT,
+    run_dag_blob             TEXT
+);
+CREATE INDEX IF NOT EXISTS idx_providence_root  ON providence_cache(source_root);
+CREATE INDEX IF NOT EXISTS idx_providence_state ON providence_cache(falsification_state);
+-- idx_providence_audit lives in _migrate_audit_mode() so legacy shards
+-- (where audit_mode column gets added by ALTER TABLE) don't trip this
+-- script before the migration runs.
+
+-- Append-only audit chain. event_hash = sha256(prev_event_hash || canonical(body)).
+CREATE TABLE IF NOT EXISTS audit_events (
+    seq             INTEGER PRIMARY KEY AUTOINCREMENT,
+    event_hash      TEXT NOT NULL UNIQUE,
+    prev_event_hash TEXT,                    -- NULL for genesis
+    event_type      TEXT NOT NULL,           -- ingest|falsify|evict_warm|evict_cold|derive|rehydrate|...
+    subject_root    TEXT,                    -- document_root or cache_key
+    body            TEXT NOT NULL,           -- canonical JSON
+    ts              INTEGER NOT NULL
+);
+CREATE INDEX IF NOT EXISTS idx_audit_subject ON audit_events(subject_root);
+
+-- Falsification log: which records were marked failed/stale/quarantined and why.
+CREATE TABLE IF NOT EXISTS falsifications (
+    cache_key        TEXT NOT NULL,
+    state            TEXT NOT NULL,
+    reason           TEXT,
+    by_actor         TEXT,
+    at               INTEGER NOT NULL,
+    audit_event_hash TEXT NOT NULL,
+    PRIMARY KEY (cache_key, at)
+);
+
+-- Snapshots: corpus-level Merkle root pinning a forest state at a point in
+-- time. snapshot_root = MerkleTree.build([sorted document_roots]). Audit-
+-- chain-linked so peers can verify a claimed snapshot was actually witnessed
+-- by this instance. parent_snapshot lets snapshots chain (A -> B -> C) for
+-- diff/replay. doc_count is informational; the root is the canonical id.
+CREATE TABLE IF NOT EXISTS snapshots (
+    snapshot_root      TEXT PRIMARY KEY,
+    taken_at           INTEGER NOT NULL,
+    audit_event_hash   TEXT NOT NULL,
+    doc_count          INTEGER NOT NULL,
+    parent_snapshot    TEXT,
+    reason             TEXT
+);
+CREATE INDEX IF NOT EXISTS idx_snapshots_taken_at ON snapshots(taken_at);
+
+-- Mesh layer tables. Off by default — populated only when the user runs
+-- `aborist mesh init`. Never accessed by ingest / query / distill paths;
+-- mesh state is opt-in plumbing for federated peers (see aborist.mesh).
+CREATE TABLE IF NOT EXISTS mesh_identity (
+    id           INTEGER PRIMARY KEY CHECK (id = 1),  -- singleton
+    member_id    TEXT NOT NULL UNIQUE,
+    sign_priv    BLOB NOT NULL,                       -- ed25519 32B raw
+    sign_pub     BLOB NOT NULL,                       -- ed25519 32B raw
+    dh_priv      BLOB NOT NULL,                       -- x25519 32B raw
+    dh_pub       BLOB NOT NULL,                       -- x25519 32B raw
+    group_name   TEXT NOT NULL,
+    created_at   INTEGER NOT NULL
+);
+
+-- Per-epoch roster. epoch 0 = group genesis (founder only). Each membership
+-- mutation (join, kick, scheduled rotate) bumps the epoch_id by 1 and writes
+-- a fresh row-set capturing the new roster.
+CREATE TABLE IF NOT EXISTS mesh_roster (
+    epoch_id     INTEGER NOT NULL,
+    member_id    TEXT NOT NULL,
+    sign_pub     BLOB NOT NULL,
+    dh_pub       BLOB NOT NULL,
+    role         TEXT NOT NULL DEFAULT 'member'
+                    CHECK (role IN ('admin','member')),
+    PRIMARY KEY (epoch_id, member_id)
+);
+CREATE INDEX IF NOT EXISTS idx_mesh_roster_member ON mesh_roster(member_id);
+
+-- Epoch lifecycle log. secret_envelope is JSON of the form
+--    {"member_id": {"nonce_b64": "...", "ct_b64": "..."}, ...}
+-- where each entry is the symmetric epoch secret AEAD-wrapped to that
+-- member's X25519 pubkey via ECDH. Eviction happens by NOT including the
+-- evicted member's entry in the next epoch's envelope.
+CREATE TABLE IF NOT EXISTS mesh_epochs (
+    epoch_id           INTEGER PRIMARY KEY,
+    started_at         INTEGER NOT NULL,
+    started_event_hash TEXT NOT NULL,
+    secret_envelope    TEXT NOT NULL,
+    reason             TEXT
+);
+
+-- Per-peer audit-chain tracking. Each row records the most recent
+-- event_hash a given peer has broadcast to us; we enforce that every
+-- subsequent gossip envelope carries `prev_event_hash == last_event_hash`
+-- of that peer. A mismatch is a fork — the gossip is rejected (409).
+-- last_seq is the local count of accepted envelopes from that peer
+-- (informational; the canonical chain identity is last_event_hash).
+CREATE TABLE IF NOT EXISTS mesh_peer_chains (
+    peer_member_id    TEXT PRIMARY KEY,
+    last_event_hash   TEXT NOT NULL,
+    last_seq          INTEGER NOT NULL,
+    last_seen_at      INTEGER NOT NULL
+);
+
+-- FTS5 over chunk content for UNGROUNDED-mode keyword search.
+--
+-- Contentless mode (`content=''`): FTS5 stores ONLY the inverted index, no
+-- copy of the indexed text. This eliminates the ~28 MB / 1000 docs that the
+-- prior schema spent on chunks_fts_content (the stored copy was redundant
+-- with chunks.content). The trade: snippet() / highlight() return empty
+-- in contentless mode, so the FTS5 backend builds snippets in Python by
+-- joining `chunks_fts.rowid = chunks.chunk_id`, decompressing chunks.content,
+-- and locating query tokens.
+--
+-- Inserts use `INSERT INTO chunks_fts (rowid, content) VALUES (chunk_id, plain)`
+-- — the rowid must equal the chunks.chunk_id of the underlying row so the
+-- search-time join lines up.
+CREATE VIRTUAL TABLE IF NOT EXISTS chunks_fts USING fts5(
+    content,
+    content='',
+    contentless_delete=1,
+    tokenize = 'porter unicode61'
+);
+
+-- Document-title FTS5 index. Replaces the un-indexable
+-- `LOWER(title) LIKE '%tok%'` title-LIKE search with O(K) hash
+-- lookup. Pre-2026-05-02 the title-LIKE backup was either skipped
+-- (>5 tokens) or paid ~10s/shard for short queries. The MATCH-based
+-- replacement runs in ~0.05s/shard regardless of token count, which
+-- means we can re-enable synonym-expanded title search for long
+-- queries without paying the corpus-scan cost.
+--
+-- Contentless mode: same trick as chunks_fts — store only the
+-- inverted index, not a copy of the title. The rowid joins back to
+-- documents.rowid (sqlite's hidden integer rowid is fine for a
+-- 1-1 mapping). On re-ingest, the FTS5 row gets replaced via the
+-- ingest path's INSERT OR REPLACE INTO documents flow.
+CREATE VIRTUAL TABLE IF NOT EXISTS documents_fts USING fts5(
+    title,
+    content='',
+    contentless_delete=1,
+    tokenize = 'porter unicode61'
+);
+
+-- Concept-relations layer. Append-only secondary index over the corpus.
+-- Each row is a (token, target) edge of a given relation_kind, derived
+-- from a specific source document by a specific extractor (evidence_kind).
+-- Re-derivation is idempotent at the (source_root, relation_kind, token,
+-- target, evidence_kind) level via UNIQUE.
+--
+-- This table is SEPARATE from the Merkle layer: writes here NEVER affect
+-- document_root / chunk_root / cache_key. So the corpus's whole Merkle
+-- tree stays valid across re-derivations; we can backfill or re-extract
+-- concept relations without invalidating any cached answers.
+--
+-- Cross-shard lookup. Concept relations live in the shard whose document
+-- they were derived from; the lookup helpers in aborist.concepts walk all
+-- shards (same pattern as cross-shard FTS5 search). Mesh sync moves shards
+-- between peers; concept relations come along for the ride automatically.
+--
+-- relation_kind:
+--   'synonym'  - token & target retrieve interchangeably (See-also
+--                bidirectional, redirect target, internal-link cluster)
+--   'antonym'  - token & target are explicit opposites (manual / hatnote
+--                "not to be confused with")
+--   'rivalry'  - token & target compete in a category (same-category
+--                membership without cross-link; manual rivalries)
+--   'category' - token belongs to category target (Wikipedia
+--                [[Category:X]] tail; HTML schema.org/<meta> classification)
+--
+-- evidence_kind: which extractor produced the row. Lets `aborist concepts
+-- purge --evidence-kind X` revoke a single extractor's output cleanly
+-- without touching manual or other-extractor rows. New extractors register
+-- a stable evidence_kind string; legacy seeds are 'manual_legacy'.
+CREATE TABLE IF NOT EXISTS concept_relations (
+    id              INTEGER PRIMARY KEY AUTOINCREMENT,
+    source_root     TEXT NOT NULL,
+    relation_kind   TEXT NOT NULL
+                        CHECK (relation_kind IN ('synonym','antonym','rivalry','category')),
+    token           TEXT NOT NULL,
+    target          TEXT NOT NULL,
+    evidence_kind   TEXT NOT NULL,
+    confidence      REAL NOT NULL DEFAULT 1.0,
+    derived_at      INTEGER NOT NULL,
+    derived_from    TEXT,                                  -- shard/uri/extractor identifier
+    UNIQUE (source_root, relation_kind, token, target, evidence_kind)
+);
+CREATE INDEX IF NOT EXISTS idx_concept_token  ON concept_relations(token);
+CREATE INDEX IF NOT EXISTS idx_concept_target ON concept_relations(target);
+CREATE INDEX IF NOT EXISTS idx_concept_kind   ON concept_relations(relation_kind);
+CREATE INDEX IF NOT EXISTS idx_concept_evid   ON concept_relations(evidence_kind);
+
+-- Per-token corpus document-frequency (for IDF ranking at synonym
+-- expansion cap-time). Computed once at backfill via fts5vocab over
+-- chunks_fts. Only tokens that appear in concept_relations get a row;
+-- the synonym layer is the consumer & it ranks expansion by 1/log(doc_freq)
+-- when the cap saturates so common-corpus words drop before rare topical
+-- ones.
+--
+-- doc_freq is FTS5-chunk-level (number of chunks containing the term);
+-- adequate proxy for true doc-level since chunks are sized 512 tokens
+-- and a doc rarely has the same term in only one chunk. Cross-shard
+-- ranking sums doc_freq across all shards' rows.
+CREATE TABLE IF NOT EXISTS concept_token_idf (
+    token       TEXT PRIMARY KEY,
+    doc_freq    INTEGER NOT NULL,
+    total_docs  INTEGER NOT NULL,
+    derived_at  INTEGER NOT NULL
+);
+CREATE INDEX IF NOT EXISTS idx_token_idf_freq ON concept_token_idf(doc_freq);
+"""
+
+
+
+[docs] +def connect(db_path: Path | str = DEFAULT_DB_PATH) -> sqlite3.Connection: + """Open a writable connection, creating the parent dir + schema if needed. + + Performance pragmas applied per-connection. Under WAL (set in the schema): + - synchronous=NORMAL skips the per-commit fsync; durable up to the last + checkpoint (SQLite auto-checkpoints at WAL ~1000 frames). + - cache_size=-65536 = 64 MB page cache (reduces re-reads). + - temp_store=MEMORY keeps temp tables in RAM (no /tmp churn). + - mmap_size=256 MB lets reads come from page-cache without read() syscalls. + """ + p = Path(db_path) + p.parent.mkdir(parents=True, exist_ok=True) + conn = sqlite3.connect(p, isolation_level=None) # autocommit; we'll BEGIN manually + conn.row_factory = sqlite3.Row + conn.executescript(SCHEMA_SQL) + _migrate_audit_mode(conn) + _migrate_mesh_peer_chains(conn) + _migrate_document_http_meta(conn) + conn.execute("PRAGMA synchronous = NORMAL") + conn.execute("PRAGMA cache_size = -65536") + conn.execute("PRAGMA temp_store = MEMORY") + conn.execute("PRAGMA mmap_size = 268435456") + return conn
+ + + +def _migrate_audit_mode(conn: sqlite3.Connection) -> None: + """Forward-migrate pre-v9.8-audit-mode providence_cache shards. + + Adds audit_mode + n_quotes + n_verified + unverified_quotes + verifier_method + columns to DBs that pre-date the faithfulness-classification rollout. SQLite + ALTER TABLE ADD COLUMN is O(1) (metadata-only) so this is cheap on every + open. Idempotent — checks PRAGMA before each ADD. + + Also handles the VISUAL → UNGROUNDED rename for the audit_mode value + space. SQLite cannot ALTER a column's CHECK in place, so legacy tables + with the old `CHECK (audit_mode IN ('STRICT','HYBRID','VISUAL'))` get + rebuilt via the standard temp-table dance, with values translated. + """ + cols = {row["name"] for row in conn.execute("PRAGMA table_info(providence_cache)")} + if "audit_mode" not in cols: + conn.execute( + "ALTER TABLE providence_cache ADD COLUMN audit_mode TEXT " + "NOT NULL DEFAULT 'UNGROUNDED' " + "CHECK (audit_mode IN ('STRICT','HYBRID','UNGROUNDED'))" + ) + if "n_quotes" not in cols: + conn.execute( + "ALTER TABLE providence_cache ADD COLUMN n_quotes INTEGER NOT NULL DEFAULT 0" + ) + if "n_verified" not in cols: + conn.execute( + "ALTER TABLE providence_cache ADD COLUMN n_verified INTEGER NOT NULL DEFAULT 0" + ) + if "unverified_quotes" not in cols: + conn.execute( + "ALTER TABLE providence_cache ADD COLUMN unverified_quotes TEXT" + ) + if "verifier_method" not in cols: + conn.execute( + "ALTER TABLE providence_cache ADD COLUMN verifier_method TEXT " + "NOT NULL DEFAULT 'none' " + "CHECK (verifier_method IN ('quote','span','entity','paraphrase','none'))" + ) + if "run_dag_root" not in cols: + conn.execute( + "ALTER TABLE providence_cache ADD COLUMN run_dag_root TEXT" + ) + if "run_dag_blob" not in cols: + conn.execute( + "ALTER TABLE providence_cache ADD COLUMN run_dag_blob TEXT" + ) + + # VISUAL → UNGROUNDED rename. Detect legacy CHECK by inspecting DDL. + ddl_row = conn.execute( + "SELECT sql FROM sqlite_master WHERE type='table' AND name='providence_cache'" + ).fetchone() + if ddl_row and "'VISUAL'" in (ddl_row[0] or ""): + _rebuild_providence_cache_ungrounded(conn) + + # paraphrase verifier_method addition. Detect legacy CHECK by + # inspecting DDL — if the constraint doesn't already list + # 'paraphrase', rebuild the table. + ddl_row = conn.execute( + "SELECT sql FROM sqlite_master WHERE type='table' AND name='providence_cache'" + ).fetchone() + if ddl_row and "'paraphrase'" not in (ddl_row[0] or ""): + _rebuild_providence_cache_paraphrase(conn) + + # claim_lattice verifier_method addition (G0 — quote-by-pointer mode). + ddl_row = conn.execute( + "SELECT sql FROM sqlite_master WHERE type='table' AND name='providence_cache'" + ).fetchone() + if ddl_row and "'claim_lattice'" not in (ddl_row[0] or ""): + _rebuild_providence_cache_claim_lattice(conn) + + conn.execute( + "CREATE INDEX IF NOT EXISTS idx_providence_audit " + "ON providence_cache(audit_mode)" + ) + + +def _migrate_document_http_meta(conn: sqlite3.Connection) -> None: + """Forward-migrate pre-recrawl-check shards. + + Adds ``document_http_meta`` to DBs that pre-date the recrawl-check + feature. Mirrors ``_migrate_mesh_peer_chains``: idempotent + table-existence probe, then CREATE if missing. + """ + row = conn.execute( + "SELECT name FROM sqlite_master WHERE type='table' AND name='document_http_meta'" + ).fetchone() + if row is None: + conn.execute( + "CREATE TABLE document_http_meta (" + " document_root TEXT PRIMARY KEY," + " etag TEXT," + " last_modified TEXT," + " last_fetched_at INTEGER NOT NULL," + " last_status INTEGER," + " last_checked_at INTEGER," + " FOREIGN KEY (document_root) REFERENCES documents(document_root)" + " ON DELETE CASCADE" + ")" + ) + + +def _migrate_mesh_peer_chains(conn: sqlite3.Connection) -> None: + """Forward-migrate pre-mesh-fork-detection shards. + + Adds the `mesh_peer_chains` table to DBs that pre-date per-peer + audit-chain tracking on the mesh wire. CREATE TABLE IF NOT EXISTS + in SCHEMA_SQL covers brand-new shards; this migration is a belt- + and-suspenders idempotency check for callers that bypass the full + SCHEMA_SQL pass (cross-shard query views, etc.). Idempotent — + PRAGMA-checks before issuing CREATE. + """ + row = conn.execute( + "SELECT name FROM sqlite_master WHERE type='table' AND name='mesh_peer_chains'" + ).fetchone() + if row is None: + conn.execute( + "CREATE TABLE mesh_peer_chains (" + " peer_member_id TEXT PRIMARY KEY," + " last_event_hash TEXT NOT NULL," + " last_seq INTEGER NOT NULL," + " last_seen_at INTEGER NOT NULL" + ")" + ) + + +def _rebuild_providence_cache_paraphrase(conn: sqlite3.Connection) -> None: + """One-time table rebuild: expand verifier_method CHECK to include + 'paraphrase' (4th verifier strategy: token-coverage paraphrase + matching, alongside quote/span/entity). + + Same pattern as ``_rebuild_providence_cache_ungrounded``: SQLite + can't modify a CHECK constraint in place, so we create a new table + with the expanded CHECK, copy the data verbatim (no value + translation needed — paraphrase is additive), drop the old, rename + the new. Caller probes existing CHECK from sqlite_master and only + invokes this when 'paraphrase' is missing. + """ + new_create = """ + CREATE TABLE providence_cache_new ( + cache_key TEXT PRIMARY KEY, + source_root TEXT NOT NULL, + document_uri TEXT NOT NULL, + question_hash TEXT NOT NULL, + question_text TEXT NOT NULL, + answer_text TEXT NOT NULL, + merkle_proof TEXT NOT NULL, + model_profile_hash TEXT NOT NULL, + conversation_hash TEXT NOT NULL, + governance_policy_hash TEXT NOT NULL, + schema_version TEXT NOT NULL, + canonicalization_version TEXT NOT NULL, + chunking_version TEXT NOT NULL, + falsification_state TEXT NOT NULL DEFAULT 'live' + CHECK (falsification_state IN ('live','failed','stale','quarantined')), + chain TEXT NOT NULL DEFAULT 'private' + CHECK (chain IN ('private','public')), + audit_event_hash TEXT, + created_at INTEGER NOT NULL, + last_hit_at INTEGER, + hit_count INTEGER NOT NULL DEFAULT 0, + audit_mode TEXT NOT NULL DEFAULT 'UNGROUNDED' + CHECK (audit_mode IN ('STRICT','HYBRID','UNGROUNDED')), + n_quotes INTEGER NOT NULL DEFAULT 0, + n_verified INTEGER NOT NULL DEFAULT 0, + unverified_quotes TEXT, + verifier_method TEXT NOT NULL DEFAULT 'none' + CHECK (verifier_method IN ('quote','span','entity','paraphrase','none')), + run_dag_root TEXT, + run_dag_blob TEXT + ) + """ + conn.execute("BEGIN IMMEDIATE") + try: + conn.execute(new_create) + conn.execute( + "INSERT INTO providence_cache_new " + "(cache_key, source_root, document_uri, question_hash, question_text, " + " answer_text, merkle_proof, model_profile_hash, conversation_hash, " + " governance_policy_hash, schema_version, canonicalization_version, " + " chunking_version, falsification_state, chain, audit_event_hash, " + " created_at, last_hit_at, hit_count, audit_mode, n_quotes, " + " n_verified, unverified_quotes, verifier_method) " + "SELECT " + " cache_key, source_root, document_uri, question_hash, question_text, " + " answer_text, merkle_proof, model_profile_hash, conversation_hash, " + " governance_policy_hash, schema_version, canonicalization_version, " + " chunking_version, falsification_state, chain, audit_event_hash, " + " created_at, last_hit_at, hit_count, audit_mode, n_quotes, " + " n_verified, unverified_quotes, verifier_method " + "FROM providence_cache" + ) + conn.execute("DROP TABLE providence_cache") + conn.execute("ALTER TABLE providence_cache_new RENAME TO providence_cache") + conn.execute("COMMIT") + except Exception: + conn.execute("ROLLBACK") + raise + + +def _rebuild_providence_cache_claim_lattice(conn: sqlite3.Connection) -> None: + """One-time table rebuild: expand verifier_method CHECK to include + 'claim_lattice' (quote-by-pointer answer mode added in G0). + + Same pattern as the paraphrase / ungrounded rebuilds: SQLite cannot + modify a CHECK constraint in place, so we create a new table with + the expanded CHECK, copy the data verbatim (claim_lattice is + additive — no value translation needed), drop the old, rename the + new. Caller probes existing CHECK from sqlite_master and only + invokes this when 'claim_lattice' is missing. + + Unlike the older rebuilds this one preserves ``run_dag_root`` & + ``run_dag_blob`` columns in the copy. By the time a shard reaches + this migration those columns may already be populated; dropping + them would erase per-run computation provenance. + """ + new_create = """ + CREATE TABLE providence_cache_new ( + cache_key TEXT PRIMARY KEY, + source_root TEXT NOT NULL, + document_uri TEXT NOT NULL, + question_hash TEXT NOT NULL, + question_text TEXT NOT NULL, + answer_text TEXT NOT NULL, + merkle_proof TEXT NOT NULL, + model_profile_hash TEXT NOT NULL, + conversation_hash TEXT NOT NULL, + governance_policy_hash TEXT NOT NULL, + schema_version TEXT NOT NULL, + canonicalization_version TEXT NOT NULL, + chunking_version TEXT NOT NULL, + falsification_state TEXT NOT NULL DEFAULT 'live' + CHECK (falsification_state IN ('live','failed','stale','quarantined')), + chain TEXT NOT NULL DEFAULT 'private' + CHECK (chain IN ('private','public')), + audit_event_hash TEXT, + created_at INTEGER NOT NULL, + last_hit_at INTEGER, + hit_count INTEGER NOT NULL DEFAULT 0, + audit_mode TEXT NOT NULL DEFAULT 'UNGROUNDED' + CHECK (audit_mode IN ('STRICT','HYBRID','UNGROUNDED')), + n_quotes INTEGER NOT NULL DEFAULT 0, + n_verified INTEGER NOT NULL DEFAULT 0, + unverified_quotes TEXT, + verifier_method TEXT NOT NULL DEFAULT 'none' + CHECK (verifier_method IN ('quote','span','entity','paraphrase','claim_lattice','none')), + run_dag_root TEXT, + run_dag_blob TEXT + ) + """ + conn.execute("BEGIN IMMEDIATE") + try: + conn.execute(new_create) + conn.execute( + "INSERT INTO providence_cache_new " + "(cache_key, source_root, document_uri, question_hash, question_text, " + " answer_text, merkle_proof, model_profile_hash, conversation_hash, " + " governance_policy_hash, schema_version, canonicalization_version, " + " chunking_version, falsification_state, chain, audit_event_hash, " + " created_at, last_hit_at, hit_count, audit_mode, n_quotes, " + " n_verified, unverified_quotes, verifier_method, " + " run_dag_root, run_dag_blob) " + "SELECT " + " cache_key, source_root, document_uri, question_hash, question_text, " + " answer_text, merkle_proof, model_profile_hash, conversation_hash, " + " governance_policy_hash, schema_version, canonicalization_version, " + " chunking_version, falsification_state, chain, audit_event_hash, " + " created_at, last_hit_at, hit_count, audit_mode, n_quotes, " + " n_verified, unverified_quotes, verifier_method, " + " run_dag_root, run_dag_blob " + "FROM providence_cache" + ) + conn.execute("DROP TABLE providence_cache") + conn.execute("ALTER TABLE providence_cache_new RENAME TO providence_cache") + conn.execute("COMMIT") + except Exception: + conn.execute("ROLLBACK") + raise + + +def _rebuild_providence_cache_ungrounded(conn: sqlite3.Connection) -> None: + """One-time table rebuild: rename audit_mode value VISUAL → UNGROUNDED. + + SQLite cannot modify a column's CHECK constraint in place. Standard + pattern: create new table with new CHECK, copy data while translating + values, drop old, rename new. Wrapped in IMMEDIATE transaction so a + failure rolls back cleanly without leaving the DB half-migrated. + """ + new_create = """ + CREATE TABLE providence_cache_new ( + cache_key TEXT PRIMARY KEY, + source_root TEXT NOT NULL, + document_uri TEXT NOT NULL, + question_hash TEXT NOT NULL, + question_text TEXT NOT NULL, + answer_text TEXT NOT NULL, + merkle_proof TEXT NOT NULL, + model_profile_hash TEXT NOT NULL, + conversation_hash TEXT NOT NULL, + governance_policy_hash TEXT NOT NULL, + schema_version TEXT NOT NULL, + canonicalization_version TEXT NOT NULL, + chunking_version TEXT NOT NULL, + falsification_state TEXT NOT NULL DEFAULT 'live' + CHECK (falsification_state IN ('live','failed','stale','quarantined')), + chain TEXT NOT NULL DEFAULT 'private' + CHECK (chain IN ('private','public')), + audit_event_hash TEXT, + created_at INTEGER NOT NULL, + last_hit_at INTEGER, + hit_count INTEGER NOT NULL DEFAULT 0, + audit_mode TEXT NOT NULL DEFAULT 'UNGROUNDED' + CHECK (audit_mode IN ('STRICT','HYBRID','UNGROUNDED')), + n_quotes INTEGER NOT NULL DEFAULT 0, + n_verified INTEGER NOT NULL DEFAULT 0, + unverified_quotes TEXT, + verifier_method TEXT NOT NULL DEFAULT 'none' + CHECK (verifier_method IN ('quote','span','entity','paraphrase','none')), + run_dag_root TEXT, + run_dag_blob TEXT + ) + """ + conn.execute("BEGIN IMMEDIATE") + try: + conn.execute(new_create) + conn.execute( + "INSERT INTO providence_cache_new " + "(cache_key, source_root, document_uri, question_hash, question_text, " + " answer_text, merkle_proof, model_profile_hash, conversation_hash, " + " governance_policy_hash, schema_version, canonicalization_version, " + " chunking_version, falsification_state, chain, audit_event_hash, " + " created_at, last_hit_at, hit_count, audit_mode, n_quotes, " + " n_verified, unverified_quotes, verifier_method) " + "SELECT " + " cache_key, source_root, document_uri, question_hash, question_text, " + " answer_text, merkle_proof, model_profile_hash, conversation_hash, " + " governance_policy_hash, schema_version, canonicalization_version, " + " chunking_version, falsification_state, chain, audit_event_hash, " + " created_at, last_hit_at, hit_count, " + " CASE WHEN audit_mode = 'VISUAL' THEN 'UNGROUNDED' ELSE audit_mode END, " + " n_quotes, n_verified, unverified_quotes, verifier_method " + "FROM providence_cache" + ) + conn.execute("DROP TABLE providence_cache") + conn.execute("ALTER TABLE providence_cache_new RENAME TO providence_cache") + conn.execute("COMMIT") + except Exception: + conn.execute("ROLLBACK") + raise + + +# Tables that exist in every shard with the same schema. Used to build +# cross-shard UNION views in connect_query(). +_SHARDABLE_TABLES = ( + "documents", + "chunks", + "merkle_nodes", + "edges", + "derivations", + "providence_cache", + "audit_events", + "falsifications", + "concept_relations", + "concept_token_idf", +) + +# Per-table column lists for cross-shard UNION views. The `chunks` table +# is pinned explicitly because the column order matters for cross-shard +# search: chunks_fts is contentless and joins back to `chunks.chunk_id`. +# Mixing legacy (composite-PK, no chunk_id column) shards with current +# (chunk_id-keyed) shards in the same --shards-dir is unsupported — run +# the migration on legacy shards first or keep them in a separate dir. +_SHARED_COLUMNS = { + "chunks": "chunk_id, document_root, idx, leaf_hash, content, tier", +} + + +
+[docs] +def discover_shards(shards_dir: Path | str) -> list[Path]: + """Enumerate shard DB files in `shards_dir`. Returns sorted list of paths.""" + p = Path(shards_dir) + if not p.is_dir(): + return [] + return sorted(p.glob("*.db"))
+ + + +
+[docs] +def connect_query( + db_path: Path | str | None = None, + shards_dir: Path | str | None = None, +) -> sqlite3.Connection: + """Open a read-only-style connection that surfaces ALL shards as one DB. + + If `shards_dir` is set, every `*.db` in it is ATTACHed and UNION ALL views + are created over the standard tables so existing queries (`SELECT * FROM + documents`) work unchanged across shards. Reads only — writes still go + through `connect()` against a specific shard. + + If `shards_dir` is None, returns a normal `connect(db_path)` for back-compat. + """ + if shards_dir is None: + return connect(db_path or DEFAULT_DB_PATH) + + shard_paths = discover_shards(shards_dir) + conn = sqlite3.connect(":memory:", isolation_level=None) + conn.row_factory = sqlite3.Row + conn.execute("PRAGMA temp_store = MEMORY") + + if not shard_paths: + # Nothing attached; create empty placeholder tables so callers don't crash. + conn.executescript(SCHEMA_SQL) + return conn + + aliases: list[str] = [] + for i, sp in enumerate(shard_paths): + alias = f"sh{i:03d}" + conn.execute(f"ATTACH DATABASE ? AS {alias}", (str(sp.resolve()),)) + aliases.append(alias) + + # UNION ALL views over the shardable tables. Columns are listed + # explicitly (not `SELECT *`) so a shard cluster that mixes the prior + # composite-PK chunks layout with the newer chunk_id-keyed layout still + # unions cleanly — the explicit list is the intersection of columns + # present in both schema generations. + for table in _SHARDABLE_TABLES: + cols = _SHARED_COLUMNS.get(table, "*") + unions = " UNION ALL ".join( + f"SELECT {cols} FROM {a}.{table}" for a in aliases + ) + conn.execute(f"CREATE TEMP VIEW {table} AS {unions}") + + # Stash the shard list for tools that want it. + conn.execute( + "CREATE TEMP TABLE _shards (shard_id TEXT, path TEXT, alias TEXT)" + ) + conn.executemany( + "INSERT INTO _shards (shard_id, path, alias) VALUES (?, ?, ?)", + [(p.stem, str(p.resolve()), a) for p, a in zip(shard_paths, aliases)], + ) + return conn
+ + + +
+[docs] +@contextmanager +def transaction(conn: sqlite3.Connection) -> Iterator[sqlite3.Connection]: + """BEGIN IMMEDIATE / COMMIT / ROLLBACK around a block.""" + conn.execute("BEGIN IMMEDIATE") + try: + yield conn + except Exception: + conn.execute("ROLLBACK") + raise + else: + conn.execute("COMMIT")
+ + + +def _canonical_json(obj) -> str: + """Stable JSON for audit hashing: sorted keys, no whitespace.""" + return json.dumps(obj, sort_keys=True, separators=(",", ":"), ensure_ascii=False) + + +
+[docs] +def get_meta(conn: sqlite3.Connection, key: str) -> str | None: + """Read a value from the per-DB meta table; None if missing.""" + row = conn.execute("SELECT value FROM meta WHERE key = ?", (key,)).fetchone() + return row["value"] if row else None
+ + + +
+[docs] +def set_meta(conn: sqlite3.Connection, key: str, value: str) -> None: + """Upsert a (key, value) into meta. Caller wraps in a transaction.""" + conn.execute( + "INSERT INTO meta (key, value, updated_at) VALUES (?, ?, ?) " + "ON CONFLICT(key) DO UPDATE SET value = excluded.value, " + "updated_at = excluded.updated_at", + (key, value, int(time.time())), + )
+ + + +
+[docs] +def latest_event_hash(conn: sqlite3.Connection) -> str | None: + """Return the last event_hash in the audit chain, or None for genesis.""" + row = conn.execute( + "SELECT event_hash FROM audit_events ORDER BY seq DESC LIMIT 1" + ).fetchone() + return row["event_hash"] if row else None
+ + + +
+[docs] +def chain_audit_events( + prev_event_hash: str | None, + events: list[dict], +) -> tuple[list[tuple], str | None]: + """Compute the event_hash chain for a batch in pure Python. + + Each event dict needs: `event_type`, `body` (dict), `subject_root` (str|None), `ts` (int). + Returns (rows_for_executemany, last_event_hash). Insert with: + + executemany("INSERT INTO audit_events + (event_hash, prev_event_hash, event_type, subject_root, + body, ts) VALUES (?, ?, ?, ?, ?, ?)", rows) + + All chain SHA-256s are computed locally — zero DB round-trips per event. + """ + import hashlib + + rows: list[tuple] = [] + prev = prev_event_hash + for ev in events: + body_json = _canonical_json(ev["body"]) + h = hashlib.sha256() + if prev is not None: + h.update(bytes.fromhex(prev)) + h.update(body_json.encode("utf-8", errors="surrogatepass")) + event_hash = h.hexdigest() + rows.append( + ( + event_hash, + prev, + ev["event_type"], + ev.get("subject_root"), + body_json, + ev["ts"], + ) + ) + prev = event_hash + return rows, prev
+ + + +
+[docs] +def append_audit( + conn: sqlite3.Connection, + event_type: str, + body: dict, + subject_root: str | None = None, + ts: int | None = None, +) -> str: + """Append one event to the audit chain. Returns the new event_hash (hex). + + Convenience wrapper for one-off events. Bulk inserts should use + chain_audit_events() + executemany() for ~10x throughput on large batches. + """ + import hashlib + + if ts is None: + ts = int(time.time()) + prev = latest_event_hash(conn) + body_json = _canonical_json(body) + h = hashlib.sha256() + if prev is not None: + h.update(bytes.fromhex(prev)) + h.update(body_json.encode("utf-8", errors="surrogatepass")) + event_hash = h.hexdigest() + conn.execute( + "INSERT INTO audit_events (event_hash, prev_event_hash, event_type, subject_root, body, ts) " + "VALUES (?, ?, ?, ?, ?, ?)", + (event_hash, prev, event_type, subject_root, body_json, ts), + ) + return event_hash
+ + + +
+[docs] +def stats(conn: sqlite3.Connection) -> dict: + """Quick landscape report.""" + def one(sql: str, *args) -> int: + return conn.execute(sql, args).fetchone()[0] + + return { + "documents_total": one("SELECT COUNT(*) FROM documents"), + "documents_surface": one("SELECT COUNT(*) FROM documents WHERE kind='surface'"), + "documents_core": one("SELECT COUNT(*) FROM documents WHERE kind='core'"), + "chunks_total": one("SELECT COUNT(*) FROM chunks"), + "chunks_hot": one("SELECT COUNT(*) FROM chunks WHERE tier='hot'"), + "chunks_warm": one("SELECT COUNT(*) FROM chunks WHERE tier='warm'"), + "chunks_cold": one("SELECT COUNT(*) FROM chunks WHERE tier='cold'"), + "edges_total": one("SELECT COUNT(*) FROM edges"), + "providence_total": one("SELECT COUNT(*) FROM providence_cache"), + "audit_events_total": one("SELECT COUNT(*) FROM audit_events"), + }
+ +
+
+
+
+ + +
+
+ + Made with Sphinx and @pradyunsg's + + Furo + +
+
+ +
+
+ +
+
+ +
+
+ + + + + \ No newline at end of file diff --git a/docs/_source/_build/html/_modules/aborist/wikitext.html b/docs/_source/_build/html/_modules/aborist/wikitext.html new file mode 100644 index 0000000..021a167 --- /dev/null +++ b/docs/_source/_build/html/_modules/aborist/wikitext.html @@ -0,0 +1,406 @@ + + + + + + + + aborist.wikitext - Aborist API Reference + + + + + + + + + + + + + + + + Contents + + + + + + Menu + + + + + + + + Expand + + + + + + Light mode + + + + + + + + + + + + + + Dark mode + + + + + + + Auto light/dark, in light mode + + + + + + + + + + + + + + + Auto light/dark, in dark mode + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Skip to content + + + +
+
+
+ +
+ +
+
+ +
+ +
+
+ +
+
+
+ + + + + Back to top + +
+
+ +
+ +
+
+

Source code for aborist.wikitext

+"""Wikitext → base prose conversion.
+
+Aborist stores raw MediaWiki wikitext in ``chunks.content`` so the link
+graph and original markup are recoverable from any page on demand. For
+LLM context and post-LLM faithfulness verification we need *prose* — a
+deterministic plain-text projection of the same chunk.
+
+This module provides that projection. ``to_base(raw)`` is a pure function
+of its input plus ``BASE_VERSION``: same wikitext → same prose, forever,
+as long as ``BASE_VERSION`` is unchanged.
+
+Versioning protocol
+-------------------
+Bump ``BASE_VERSION`` whenever the algorithm changes. Callers fold
+``BASE_VERSION`` into ``governance_policy_hash`` (via ``policy["base_version"]``
+in ``aborist.qa.runner`` / ``aborist.qa.query``) so a bump invalidates every
+prior providence-cache record's 8-dim cache_key on the next lookup. No
+schema migration; the next ``ask`` re-derives against fresh prose.
+
+Algorithm (wikitext-base-v1)
+----------------------------
+1. Parse with ``mwparserfromhell`` (handles nested templates, complex
+   tables, and edge cases that pure regex mangles).
+2. Drop ``<ref>...</ref>`` and self-closing ``<ref ... />`` tags. Citations
+   are not quotable claims about the topic.
+3. Drop namespace-prefixed wikilinks: ``[[File:...]]``, ``[[Image:...]]``,
+   ``[[Category:...]]``. Image params (``thumb|250px|...``) and category
+   tags are not prose; they're metadata.
+4. ``strip_code(normalize=True, collapse=True)`` — converts surviving
+   templates to empty, wikilinks to their display text, headers to bare
+   text, bold/italic markers to plain text, HTML tags to inner text,
+   HTML entities to characters, external links to anchor text.
+5. Whitespace pass: collapse runs of spaces/tabs, drop trailing space on
+   lines, collapse 3+ newlines to 2.
+
+Optional dependency. Install with ``pip install aborist[wikitext]``.
+"""
+
+from __future__ import annotations
+
+import re
+
+try:
+    import mwparserfromhell as _mw
+except ImportError as e:  # pragma: no cover
+    raise ImportError(
+        "wikitext base conversion requires extras: "
+        "pip install 'aborist[wikitext]'"
+    ) from e
+
+
+BASE_VERSION = "wikitext-base-v1"
+
+# Namespaces whose links carry no prose. ``File`` and ``Image`` are the
+# same target type (image inclusion); MediaWiki accepts both prefixes.
+# ``Category`` tags categorize a page but don't render as readable prose
+# in the article body.
+_DROP_NAMESPACES = frozenset({"file", "image", "category"})
+
+_WS_RUN = re.compile(r"[ \t]+")
+_TRAILING_WS = re.compile(r" +\n")
+_BLANK_LINES = re.compile(r"\n{3,}")
+
+
+
+[docs] +def to_base(raw: str) -> str: + """Convert raw wikitext to base prose. Deterministic. Idempotent. + + Empty / whitespace-only input returns ``""``. Non-wikitext input + (already-clean prose) round-trips unchanged modulo whitespace + collapsing. + """ + if not raw or not raw.strip(): + return "" + + code = _mw.parse(raw) + + # Drop <ref>...</ref> and self-closing <ref ... /> tags. We match on + # the tag name (case-insensitive) so that <REF>, <Ref>, etc. all go. + for tag in list(code.filter_tags()): + if str(tag.tag).strip().lower() == "ref": + try: + code.remove(tag) + except ValueError: + # Tag was already removed via a parent node. mwparserfromhell + # raises rather than no-op'ing; we swallow it. + pass + + # Drop File: / Image: / Category: wikilinks. Image captions sometimes + # contain useful prose ("thumb|250px|<caption>") but the technical + # parameters dominate and corrupt the prose stream; cleaner to drop. + for link in list(code.filter_wikilinks()): + title = str(link.title).strip() + if ":" in title: + ns = title.split(":", 1)[0].strip().lower() + if ns in _DROP_NAMESPACES: + try: + code.remove(link) + except ValueError: + pass + + base = code.strip_code(normalize=True, collapse=True) + + # Whitespace normalization — keeps paragraph breaks, drops runs. + base = _WS_RUN.sub(" ", base) + base = _TRAILING_WS.sub("\n", base) + base = _BLANK_LINES.sub("\n\n", base) + return base.strip()
+ + + + + +
+
+
+
+ + +
+
+ + Made with Sphinx and @pradyunsg's + + Furo + +
+
+ +
+
+ +
+
+ +
+
+ + + + + \ No newline at end of file diff --git a/docs/_source/_build/html/_modules/index.html b/docs/_source/_build/html/_modules/index.html new file mode 100644 index 0000000..b625381 --- /dev/null +++ b/docs/_source/_build/html/_modules/index.html @@ -0,0 +1,289 @@ + + + + + + + + Overview: module code - Aborist API Reference + + + + + + + + + + + + + + + + Contents + + + + + + Menu + + + + + + + + Expand + + + + + + Light mode + + + + + + + + + + + + + + Dark mode + + + + + + + Auto light/dark, in light mode + + + + + + + + + + + + + + + Auto light/dark, in dark mode + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Skip to content + + + + + + + + + \ No newline at end of file diff --git a/docs/_source/_build/html/_sources/api/cli.rst.txt b/docs/_source/_build/html/_sources/api/cli.rst.txt new file mode 100644 index 0000000..b1a17cb --- /dev/null +++ b/docs/_source/_build/html/_sources/api/cli.rst.txt @@ -0,0 +1,8 @@ +CLI: Command-line interface +============================ + +Entry point for all aborist operations. + +.. automodule:: aborist.cli + :members: + :undoc-members: diff --git a/docs/_source/_build/html/_sources/api/distill.rst.txt b/docs/_source/_build/html/_sources/api/distill.rst.txt new file mode 100644 index 0000000..e8597b6 --- /dev/null +++ b/docs/_source/_build/html/_sources/api/distill.rst.txt @@ -0,0 +1,9 @@ +Distillation: surface → core compression +========================================== + +Surface-to-core extraction and recursive distillation. + +.. automodule:: aborist.distill + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/_source/_build/html/_sources/api/mesh.rst.txt b/docs/_source/_build/html/_sources/api/mesh.rst.txt new file mode 100644 index 0000000..d190ec8 --- /dev/null +++ b/docs/_source/_build/html/_sources/api/mesh.rst.txt @@ -0,0 +1,9 @@ +Federation: multiplayer aborist +================================ + +Gossip-based mesh for cross-peer data sharing. + +.. automodule:: aborist.mesh + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/_source/_build/html/_sources/api/qa.rst.txt b/docs/_source/_build/html/_sources/api/qa.rst.txt new file mode 100644 index 0000000..536a794 --- /dev/null +++ b/docs/_source/_build/html/_sources/api/qa.rst.txt @@ -0,0 +1,67 @@ +Q&A Pipeline: question → answer → verify → cache +================================================== + +Question answering, caching, verification, evidence mapping. + +keys +---- + +.. automodule:: aborist.qa.keys + :members: + :undoc-members: + +runner +------ + +.. automodule:: aborist.qa.runner + :members: + :undoc-members: + +query +----- + +.. automodule:: aborist.qa.query + :members: + :undoc-members: + +verify +------ + +.. automodule:: aborist.qa.verify + :members: + :undoc-members: + +evidence +-------- + +.. automodule:: aborist.qa.evidence + :members: + :undoc-members: + +quantifier +---------- + +.. automodule:: aborist.qa.quantifier + :members: + :undoc-members: + +metacognition +------------- + +.. automodule:: aborist.qa.metacognition + :members: + :undoc-members: + +dag +--- + +.. automodule:: aborist.qa.dag + :members: + :undoc-members: + +client +------ + +.. automodule:: aborist.qa.client + :members: + :undoc-members: diff --git a/docs/_source/_build/html/_sources/api/retrieval.rst.txt b/docs/_source/_build/html/_sources/api/retrieval.rst.txt new file mode 100644 index 0000000..2ca3cfa --- /dev/null +++ b/docs/_source/_build/html/_sources/api/retrieval.rst.txt @@ -0,0 +1,35 @@ +Retrieval: FTS5 search and concepts +=================================== + +Full-text search, concept relations (synonym/rivalry overlay). + +search +------ + +.. automodule:: aborist.search + :members: + :undoc-members: + :show-inheritance: + +sources +------- + +.. automodule:: aborist.source + :members: + :undoc-members: + +.. automodule:: aborist.sources.wikipedia + :members: + :undoc-members: + +.. automodule:: aborist.sources.html_page + :members: + :undoc-members: + +concepts +-------- + +.. automodule:: aborist.concepts + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/_source/_build/html/_sources/api/storage.rst.txt b/docs/_source/_build/html/_sources/api/storage.rst.txt new file mode 100644 index 0000000..17a90b5 --- /dev/null +++ b/docs/_source/_build/html/_sources/api/storage.rst.txt @@ -0,0 +1,27 @@ +Storage: SQLite schema and audit +================================ + +v9.8 SQLite schema, audit chain, and cross-shard views. + +store +----- + +.. automodule:: aborist.store + :members: + :undoc-members: + :show-inheritance: + +ingest +------ + +.. automodule:: aborist.ingest + :members: + :undoc-members: + :show-inheritance: + +evict +----- + +.. automodule:: aborist.evict + :members: + :undoc-members: diff --git a/docs/_source/_build/html/_sources/api/substrate.rst.txt b/docs/_source/_build/html/_sources/api/substrate.rst.txt new file mode 100644 index 0000000..7007f6f --- /dev/null +++ b/docs/_source/_build/html/_sources/api/substrate.rst.txt @@ -0,0 +1,27 @@ +Substrate: Core data structures +=============================== + +Pure Merkle tree and document primitives. + +merkle +------ + +.. automodule:: aborist.merkle + :members: + :undoc-members: + :show-inheritance: + +document +-------- + +.. automodule:: aborist.document + :members: + :undoc-members: + :show-inheritance: + +wikitext +-------- + +.. automodule:: aborist.wikitext + :members: + :undoc-members: diff --git a/docs/_source/_build/html/_sources/index.rst.txt b/docs/_source/_build/html/_sources/index.rst.txt new file mode 100644 index 0000000..1d1d5b9 --- /dev/null +++ b/docs/_source/_build/html/_sources/index.rst.txt @@ -0,0 +1,26 @@ +Aborist API Reference +===================== + +Generated from docstrings. Replaces the static modules.md. + +Contents: + +.. toctree:: + :maxdepth: 3 + :caption: API Modules + + api/substrate + api/storage + api/retrieval + api/qa + api/distill + api/mesh + api/cli + + +Indices and tables +================== + +* :ref:`genindex` +* :ref:`modindex` +* :ref:`search` diff --git a/docs/_source/_build/html/_static/base-stemmer.js b/docs/_source/_build/html/_static/base-stemmer.js new file mode 100644 index 0000000..e6fa0c4 --- /dev/null +++ b/docs/_source/_build/html/_static/base-stemmer.js @@ -0,0 +1,476 @@ +// @ts-check + +/**@constructor*/ +BaseStemmer = function() { + /** @protected */ + this.current = ''; + this.cursor = 0; + this.limit = 0; + this.limit_backward = 0; + this.bra = 0; + this.ket = 0; + + /** + * @param {string} value + */ + this.setCurrent = function(value) { + this.current = value; + this.cursor = 0; + this.limit = this.current.length; + this.limit_backward = 0; + this.bra = this.cursor; + this.ket = this.limit; + }; + + /** + * @return {string} + */ + this.getCurrent = function() { + return this.current; + }; + + /** + * @param {BaseStemmer} other + */ + this.copy_from = function(other) { + /** @protected */ + this.current = other.current; + this.cursor = other.cursor; + this.limit = other.limit; + this.limit_backward = other.limit_backward; + this.bra = other.bra; + this.ket = other.ket; + }; + + /** + * @param {number[]} s + * @param {number} min + * @param {number} max + * @return {boolean} + */ + this.in_grouping = function(s, min, max) { + /** @protected */ + if (this.cursor >= this.limit) return false; + var ch = this.current.charCodeAt(this.cursor); + if (ch > max || ch < min) return false; + ch -= min; + if ((s[ch >>> 3] & (0x1 << (ch & 0x7))) == 0) return false; + this.cursor++; + return true; + }; + + /** + * @param {number[]} s + * @param {number} min + * @param {number} max + * @return {boolean} + */ + this.go_in_grouping = function(s, min, max) { + /** @protected */ + while (this.cursor < this.limit) { + var ch = this.current.charCodeAt(this.cursor); + if (ch > max || ch < min) + return true; + ch -= min; + if ((s[ch >>> 3] & (0x1 << (ch & 0x7))) == 0) + return true; + this.cursor++; + } + return false; + }; + + /** + * @param {number[]} s + * @param {number} min + * @param {number} max + * @return {boolean} + */ + this.in_grouping_b = function(s, min, max) { + /** @protected */ + if (this.cursor <= this.limit_backward) return false; + var ch = this.current.charCodeAt(this.cursor - 1); + if (ch > max || ch < min) return false; + ch -= min; + if ((s[ch >>> 3] & (0x1 << (ch & 0x7))) == 0) return false; + this.cursor--; + return true; + }; + + /** + * @param {number[]} s + * @param {number} min + * @param {number} max + * @return {boolean} + */ + this.go_in_grouping_b = function(s, min, max) { + /** @protected */ + while (this.cursor > this.limit_backward) { + var ch = this.current.charCodeAt(this.cursor - 1); + if (ch > max || ch < min) return true; + ch -= min; + if ((s[ch >>> 3] & (0x1 << (ch & 0x7))) == 0) return true; + this.cursor--; + } + return false; + }; + + /** + * @param {number[]} s + * @param {number} min + * @param {number} max + * @return {boolean} + */ + this.out_grouping = function(s, min, max) { + /** @protected */ + if (this.cursor >= this.limit) return false; + var ch = this.current.charCodeAt(this.cursor); + if (ch > max || ch < min) { + this.cursor++; + return true; + } + ch -= min; + if ((s[ch >>> 3] & (0X1 << (ch & 0x7))) == 0) { + this.cursor++; + return true; + } + return false; + }; + + /** + * @param {number[]} s + * @param {number} min + * @param {number} max + * @return {boolean} + */ + this.go_out_grouping = function(s, min, max) { + /** @protected */ + while (this.cursor < this.limit) { + var ch = this.current.charCodeAt(this.cursor); + if (ch <= max && ch >= min) { + ch -= min; + if ((s[ch >>> 3] & (0X1 << (ch & 0x7))) != 0) { + return true; + } + } + this.cursor++; + } + return false; + }; + + /** + * @param {number[]} s + * @param {number} min + * @param {number} max + * @return {boolean} + */ + this.out_grouping_b = function(s, min, max) { + /** @protected */ + if (this.cursor <= this.limit_backward) return false; + var ch = this.current.charCodeAt(this.cursor - 1); + if (ch > max || ch < min) { + this.cursor--; + return true; + } + ch -= min; + if ((s[ch >>> 3] & (0x1 << (ch & 0x7))) == 0) { + this.cursor--; + return true; + } + return false; + }; + + /** + * @param {number[]} s + * @param {number} min + * @param {number} max + * @return {boolean} + */ + this.go_out_grouping_b = function(s, min, max) { + /** @protected */ + while (this.cursor > this.limit_backward) { + var ch = this.current.charCodeAt(this.cursor - 1); + if (ch <= max && ch >= min) { + ch -= min; + if ((s[ch >>> 3] & (0x1 << (ch & 0x7))) != 0) { + return true; + } + } + this.cursor--; + } + return false; + }; + + /** + * @param {string} s + * @return {boolean} + */ + this.eq_s = function(s) + { + /** @protected */ + if (this.limit - this.cursor < s.length) return false; + if (this.current.slice(this.cursor, this.cursor + s.length) != s) + { + return false; + } + this.cursor += s.length; + return true; + }; + + /** + * @param {string} s + * @return {boolean} + */ + this.eq_s_b = function(s) + { + /** @protected */ + if (this.cursor - this.limit_backward < s.length) return false; + if (this.current.slice(this.cursor - s.length, this.cursor) != s) + { + return false; + } + this.cursor -= s.length; + return true; + }; + + /** + * @param {Among[]} v + * @return {number} + */ + this.find_among = function(v) + { + /** @protected */ + var i = 0; + var j = v.length; + + var c = this.cursor; + var l = this.limit; + + var common_i = 0; + var common_j = 0; + + var first_key_inspected = false; + + while (true) + { + var k = i + ((j - i) >>> 1); + var diff = 0; + var common = common_i < common_j ? common_i : common_j; // smaller + // w[0]: string, w[1]: substring_i, w[2]: result, w[3]: function (optional) + var w = v[k]; + var i2; + for (i2 = common; i2 < w[0].length; i2++) + { + if (c + common == l) + { + diff = -1; + break; + } + diff = this.current.charCodeAt(c + common) - w[0].charCodeAt(i2); + if (diff != 0) break; + common++; + } + if (diff < 0) + { + j = k; + common_j = common; + } + else + { + i = k; + common_i = common; + } + if (j - i <= 1) + { + if (i > 0) break; // v->s has been inspected + if (j == i) break; // only one item in v + + // - but now we need to go round once more to get + // v->s inspected. This looks messy, but is actually + // the optimal approach. + + if (first_key_inspected) break; + first_key_inspected = true; + } + } + do { + var w = v[i]; + if (common_i >= w[0].length) + { + this.cursor = c + w[0].length; + if (w.length < 4) return w[2]; + var res = w[3](this); + this.cursor = c + w[0].length; + if (res) return w[2]; + } + i = w[1]; + } while (i >= 0); + return 0; + }; + + // find_among_b is for backwards processing. Same comments apply + /** + * @param {Among[]} v + * @return {number} + */ + this.find_among_b = function(v) + { + /** @protected */ + var i = 0; + var j = v.length + + var c = this.cursor; + var lb = this.limit_backward; + + var common_i = 0; + var common_j = 0; + + var first_key_inspected = false; + + while (true) + { + var k = i + ((j - i) >> 1); + var diff = 0; + var common = common_i < common_j ? common_i : common_j; + var w = v[k]; + var i2; + for (i2 = w[0].length - 1 - common; i2 >= 0; i2--) + { + if (c - common == lb) + { + diff = -1; + break; + } + diff = this.current.charCodeAt(c - 1 - common) - w[0].charCodeAt(i2); + if (diff != 0) break; + common++; + } + if (diff < 0) + { + j = k; + common_j = common; + } + else + { + i = k; + common_i = common; + } + if (j - i <= 1) + { + if (i > 0) break; + if (j == i) break; + if (first_key_inspected) break; + first_key_inspected = true; + } + } + do { + var w = v[i]; + if (common_i >= w[0].length) + { + this.cursor = c - w[0].length; + if (w.length < 4) return w[2]; + var res = w[3](this); + this.cursor = c - w[0].length; + if (res) return w[2]; + } + i = w[1]; + } while (i >= 0); + return 0; + }; + + /* to replace chars between c_bra and c_ket in this.current by the + * chars in s. + */ + /** + * @param {number} c_bra + * @param {number} c_ket + * @param {string} s + * @return {number} + */ + this.replace_s = function(c_bra, c_ket, s) + { + /** @protected */ + var adjustment = s.length - (c_ket - c_bra); + this.current = this.current.slice(0, c_bra) + s + this.current.slice(c_ket); + this.limit += adjustment; + if (this.cursor >= c_ket) this.cursor += adjustment; + else if (this.cursor > c_bra) this.cursor = c_bra; + return adjustment; + }; + + /** + * @return {boolean} + */ + this.slice_check = function() + { + /** @protected */ + if (this.bra < 0 || + this.bra > this.ket || + this.ket > this.limit || + this.limit > this.current.length) + { + return false; + } + return true; + }; + + /** + * @param {number} c_bra + * @return {boolean} + */ + this.slice_from = function(s) + { + /** @protected */ + var result = false; + if (this.slice_check()) + { + this.replace_s(this.bra, this.ket, s); + result = true; + } + return result; + }; + + /** + * @return {boolean} + */ + this.slice_del = function() + { + /** @protected */ + return this.slice_from(""); + }; + + /** + * @param {number} c_bra + * @param {number} c_ket + * @param {string} s + */ + this.insert = function(c_bra, c_ket, s) + { + /** @protected */ + var adjustment = this.replace_s(c_bra, c_ket, s); + if (c_bra <= this.bra) this.bra += adjustment; + if (c_bra <= this.ket) this.ket += adjustment; + }; + + /** + * @return {string} + */ + this.slice_to = function() + { + /** @protected */ + var result = ''; + if (this.slice_check()) + { + result = this.current.slice(this.bra, this.ket); + } + return result; + }; + + /** + * @return {string} + */ + this.assign_to = function() + { + /** @protected */ + return this.current.slice(0, this.limit); + }; +}; diff --git a/docs/_source/_build/html/_static/basic.css b/docs/_source/_build/html/_static/basic.css new file mode 100644 index 0000000..4738b2e --- /dev/null +++ b/docs/_source/_build/html/_static/basic.css @@ -0,0 +1,906 @@ +/* + * Sphinx stylesheet -- basic theme. + */ + +/* -- main layout ----------------------------------------------------------- */ + +div.clearer { + clear: both; +} + +div.section::after { + display: block; + content: ''; + clear: left; +} + +/* -- relbar ---------------------------------------------------------------- */ + +div.related { + width: 100%; + font-size: 90%; +} + +div.related h3 { + display: none; +} + +div.related ul { + margin: 0; + padding: 0 0 0 10px; + list-style: none; +} + +div.related li { + display: inline; +} + +div.related li.right { + float: right; + margin-right: 5px; +} + +/* -- sidebar --------------------------------------------------------------- */ + +div.sphinxsidebarwrapper { + padding: 10px 5px 0 10px; +} + +div.sphinxsidebar { + float: left; + width: 230px; + margin-left: -100%; + font-size: 90%; + word-wrap: break-word; + overflow-wrap : break-word; +} + +div.sphinxsidebar ul { + list-style: none; +} + +div.sphinxsidebar ul ul, +div.sphinxsidebar ul.want-points { + margin-left: 20px; + list-style: square; +} + +div.sphinxsidebar ul ul { + margin-top: 0; + margin-bottom: 0; +} + +div.sphinxsidebar form { + margin-top: 10px; +} + +div.sphinxsidebar input { + border: 1px solid #98dbcc; + font-family: sans-serif; + font-size: 1em; +} + +div.sphinxsidebar #searchbox form.search { + overflow: hidden; +} + +div.sphinxsidebar #searchbox input[type="text"] { + float: left; + width: 80%; + padding: 0.25em; + box-sizing: border-box; +} + +div.sphinxsidebar #searchbox input[type="submit"] { + float: left; + width: 20%; + border-left: none; + padding: 0.25em; + box-sizing: border-box; +} + + +img { + border: 0; + max-width: 100%; +} + +/* -- search page ----------------------------------------------------------- */ + +ul.search { + margin-top: 10px; +} + +ul.search li { + padding: 5px 0; +} + +ul.search li a { + font-weight: bold; +} + +ul.search li p.context { + color: #888; + margin: 2px 0 0 30px; + text-align: left; +} + +ul.keywordmatches li.goodmatch a { + font-weight: bold; +} + +/* -- index page ------------------------------------------------------------ */ + +table.contentstable { + width: 90%; + margin-left: auto; + margin-right: auto; +} + +table.contentstable p.biglink { + line-height: 150%; +} + +a.biglink { + font-size: 1.3em; +} + +span.linkdescr { + font-style: italic; + padding-top: 5px; + font-size: 90%; +} + +/* -- general index --------------------------------------------------------- */ + +table.indextable { + width: 100%; +} + +table.indextable td { + text-align: left; + vertical-align: top; +} + +table.indextable ul { + margin-top: 0; + margin-bottom: 0; + list-style-type: none; +} + +table.indextable > tbody > tr > td > ul { + padding-left: 0em; +} + +table.indextable tr.pcap { + height: 10px; +} + +table.indextable tr.cap { + margin-top: 10px; + background-color: #f2f2f2; +} + +img.toggler { + margin-right: 3px; + margin-top: 3px; + cursor: pointer; +} + +div.modindex-jumpbox { + border-top: 1px solid #ddd; + border-bottom: 1px solid #ddd; + margin: 1em 0 1em 0; + padding: 0.4em; +} + +div.genindex-jumpbox { + border-top: 1px solid #ddd; + border-bottom: 1px solid #ddd; + margin: 1em 0 1em 0; + padding: 0.4em; +} + +/* -- domain module index --------------------------------------------------- */ + +table.modindextable td { + padding: 2px; + border-collapse: collapse; +} + +/* -- general body styles --------------------------------------------------- */ + +div.body { + min-width: 360px; + max-width: 800px; +} + +div.body p, div.body dd, div.body li, div.body blockquote { + -moz-hyphens: auto; + -ms-hyphens: auto; + -webkit-hyphens: auto; + hyphens: auto; +} + +a.headerlink { + visibility: hidden; +} + +a:visited { + color: #551A8B; +} + +h1:hover > a.headerlink, +h2:hover > a.headerlink, +h3:hover > a.headerlink, +h4:hover > a.headerlink, +h5:hover > a.headerlink, +h6:hover > a.headerlink, +dt:hover > a.headerlink, +caption:hover > a.headerlink, +p.caption:hover > a.headerlink, +div.code-block-caption:hover > a.headerlink { + visibility: visible; +} + +div.body p.caption { + text-align: inherit; +} + +div.body td { + text-align: left; +} + +.first { + margin-top: 0 !important; +} + +p.rubric { + margin-top: 30px; + font-weight: bold; +} + +img.align-left, figure.align-left, .figure.align-left, object.align-left { + clear: left; + float: left; + margin-right: 1em; +} + +img.align-right, figure.align-right, .figure.align-right, object.align-right { + clear: right; + float: right; + margin-left: 1em; +} + +img.align-center, figure.align-center, .figure.align-center, object.align-center { + display: block; + margin-left: auto; + margin-right: auto; +} + +img.align-default, figure.align-default, .figure.align-default { + display: block; + margin-left: auto; + margin-right: auto; +} + +.align-left { + text-align: left; +} + +.align-center { + text-align: center; +} + +.align-default { + text-align: center; +} + +.align-right { + text-align: right; +} + +/* -- sidebars -------------------------------------------------------------- */ + +div.sidebar, +aside.sidebar { + margin: 0 0 0.5em 1em; + border: 1px solid #ddb; + padding: 7px; + background-color: #ffe; + width: 40%; + float: right; + clear: right; + overflow-x: auto; +} + +p.sidebar-title { + font-weight: bold; +} + +nav.contents, +aside.topic, +div.admonition, div.topic, blockquote { + clear: left; +} + +/* -- topics ---------------------------------------------------------------- */ + +nav.contents, +aside.topic, +div.topic { + border: 1px solid #ccc; + padding: 7px; + margin: 10px 0 10px 0; +} + +p.topic-title { + font-size: 1.1em; + font-weight: bold; + margin-top: 10px; +} + +/* -- admonitions ----------------------------------------------------------- */ + +div.admonition { + margin-top: 10px; + margin-bottom: 10px; + padding: 7px; +} + +div.admonition dt { + font-weight: bold; +} + +p.admonition-title { + margin: 0px 10px 5px 0px; + font-weight: bold; +} + +div.body p.centered { + text-align: center; + margin-top: 25px; +} + +/* -- content of sidebars/topics/admonitions -------------------------------- */ + +div.sidebar > :last-child, +aside.sidebar > :last-child, +nav.contents > :last-child, +aside.topic > :last-child, +div.topic > :last-child, +div.admonition > :last-child { + margin-bottom: 0; +} + +div.sidebar::after, +aside.sidebar::after, +nav.contents::after, +aside.topic::after, +div.topic::after, +div.admonition::after, +blockquote::after { + display: block; + content: ''; + clear: both; +} + +/* -- tables ---------------------------------------------------------------- */ + +table.docutils { + margin-top: 10px; + margin-bottom: 10px; + border: 0; + border-collapse: collapse; +} + +table.align-center { + margin-left: auto; + margin-right: auto; +} + +table.align-default { + margin-left: auto; + margin-right: auto; +} + +table caption span.caption-number { + font-style: italic; +} + +table caption span.caption-text { +} + +table.docutils td, table.docutils th { + padding: 1px 8px 1px 5px; + border-top: 0; + border-left: 0; + border-right: 0; + border-bottom: 1px solid #aaa; +} + +th { + text-align: left; + padding-right: 5px; +} + +table.citation { + border-left: solid 1px gray; + margin-left: 1px; +} + +table.citation td { + border-bottom: none; +} + +th > :first-child, +td > :first-child { + margin-top: 0px; +} + +th > :last-child, +td > :last-child { + margin-bottom: 0px; +} + +/* -- figures --------------------------------------------------------------- */ + +div.figure, figure { + margin: 0.5em; + padding: 0.5em; +} + +div.figure p.caption, figcaption { + padding: 0.3em; +} + +div.figure p.caption span.caption-number, +figcaption span.caption-number { + font-style: italic; +} + +div.figure p.caption span.caption-text, +figcaption span.caption-text { +} + +/* -- field list styles ----------------------------------------------------- */ + +table.field-list td, table.field-list th { + border: 0 !important; +} + +.field-list ul { + margin: 0; + padding-left: 1em; +} + +.field-list p { + margin: 0; +} + +.field-name { + -moz-hyphens: manual; + -ms-hyphens: manual; + -webkit-hyphens: manual; + hyphens: manual; +} + +/* -- hlist styles ---------------------------------------------------------- */ + +table.hlist { + margin: 1em 0; +} + +table.hlist td { + vertical-align: top; +} + +/* -- object description styles --------------------------------------------- */ + +.sig { + font-family: 'Consolas', 'Menlo', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; +} + +.sig-name, code.descname { + background-color: transparent; + font-weight: bold; +} + +.sig-name { + font-size: 1.1em; +} + +code.descname { + font-size: 1.2em; +} + +.sig-prename, code.descclassname { + background-color: transparent; +} + +.optional { + font-size: 1.3em; +} + +.sig-paren { + font-size: larger; +} + +.sig-param.n { + font-style: italic; +} + +/* C++ specific styling */ + +.sig-inline.c-texpr, +.sig-inline.cpp-texpr { + font-family: unset; +} + +.sig.c .k, .sig.c .kt, +.sig.cpp .k, .sig.cpp .kt { + color: #0033B3; +} + +.sig.c .m, +.sig.cpp .m { + color: #1750EB; +} + +.sig.c .s, .sig.c .sc, +.sig.cpp .s, .sig.cpp .sc { + color: #067D17; +} + + +/* -- other body styles ----------------------------------------------------- */ + +ol.arabic { + list-style: decimal; +} + +ol.loweralpha { + list-style: lower-alpha; +} + +ol.upperalpha { + list-style: upper-alpha; +} + +ol.lowerroman { + list-style: lower-roman; +} + +ol.upperroman { + list-style: upper-roman; +} + +:not(li) > ol > li:first-child > :first-child, +:not(li) > ul > li:first-child > :first-child { + margin-top: 0px; +} + +:not(li) > ol > li:last-child > :last-child, +:not(li) > ul > li:last-child > :last-child { + margin-bottom: 0px; +} + +ol.simple ol p, +ol.simple ul p, +ul.simple ol p, +ul.simple ul p { + margin-top: 0; +} + +ol.simple > li:not(:first-child) > p, +ul.simple > li:not(:first-child) > p { + margin-top: 0; +} + +ol.simple p, +ul.simple p { + margin-bottom: 0; +} + +aside.footnote > span, +div.citation > span { + float: left; +} +aside.footnote > span:last-of-type, +div.citation > span:last-of-type { + padding-right: 0.5em; +} +aside.footnote > p { + margin-left: 2em; +} +div.citation > p { + margin-left: 4em; +} +aside.footnote > p:last-of-type, +div.citation > p:last-of-type { + margin-bottom: 0em; +} +aside.footnote > p:last-of-type:after, +div.citation > p:last-of-type:after { + content: ""; + clear: both; +} + +dl.field-list { + display: grid; + grid-template-columns: fit-content(30%) auto; +} + +dl.field-list > dt { + font-weight: bold; + word-break: break-word; + padding-left: 0.5em; + padding-right: 5px; +} + +dl.field-list > dd { + padding-left: 0.5em; + margin-top: 0em; + margin-left: 0em; + margin-bottom: 0em; +} + +dl { + margin-bottom: 15px; +} + +dd > :first-child { + margin-top: 0px; +} + +dd ul, dd table { + margin-bottom: 10px; +} + +dd { + margin-top: 3px; + margin-bottom: 10px; + margin-left: 30px; +} + +.sig dd { + margin-top: 0px; + margin-bottom: 0px; +} + +.sig dl { + margin-top: 0px; + margin-bottom: 0px; +} + +dl > dd:last-child, +dl > dd:last-child > :last-child { + margin-bottom: 0; +} + +dt:target, span.highlighted { + background-color: #fbe54e; +} + +rect.highlighted { + fill: #fbe54e; +} + +dl.glossary dt { + font-weight: bold; + font-size: 1.1em; +} + +.versionmodified { + font-style: italic; +} + +.system-message { + background-color: #fda; + padding: 5px; + border: 3px solid red; +} + +.footnote:target { + background-color: #ffa; +} + +.line-block { + display: block; + margin-top: 1em; + margin-bottom: 1em; +} + +.line-block .line-block { + margin-top: 0; + margin-bottom: 0; + margin-left: 1.5em; +} + +.guilabel, .menuselection { + font-family: sans-serif; +} + +.accelerator { + text-decoration: underline; +} + +.classifier { + font-style: oblique; +} + +.classifier:before { + font-style: normal; + margin: 0 0.5em; + content: ":"; + display: inline-block; +} + +abbr, acronym { + border-bottom: dotted 1px; + cursor: help; +} + +/* -- code displays --------------------------------------------------------- */ + +pre { + overflow: auto; + overflow-y: hidden; /* fixes display issues on Chrome browsers */ +} + +pre, div[class*="highlight-"] { + clear: both; +} + +span.pre { + -moz-hyphens: none; + -ms-hyphens: none; + -webkit-hyphens: none; + hyphens: none; + white-space: nowrap; +} + +div[class*="highlight-"] { + margin: 1em 0; +} + +td.linenos pre { + border: 0; + background-color: transparent; + color: #aaa; +} + +table.highlighttable { + display: block; +} + +table.highlighttable tbody { + display: block; +} + +table.highlighttable tr { + display: flex; +} + +table.highlighttable td { + margin: 0; + padding: 0; +} + +table.highlighttable td.linenos { + padding-right: 0.5em; +} + +table.highlighttable td.code { + flex: 1; + overflow: hidden; +} + +.highlight .hll { + display: block; +} + +div.highlight pre, +table.highlighttable pre { + margin: 0; +} + +div.code-block-caption + div { + margin-top: 0; +} + +div.code-block-caption { + margin-top: 1em; + padding: 2px 5px; + font-size: small; +} + +div.code-block-caption code { + background-color: transparent; +} + +table.highlighttable td.linenos, +span.linenos, +div.highlight span.gp { /* gp: Generic.Prompt */ + user-select: none; + -webkit-user-select: text; /* Safari fallback only */ + -webkit-user-select: none; /* Chrome/Safari */ + -moz-user-select: none; /* Firefox */ + -ms-user-select: none; /* IE10+ */ +} + +div.code-block-caption span.caption-number { + padding: 0.1em 0.3em; + font-style: italic; +} + +div.code-block-caption span.caption-text { +} + +div.literal-block-wrapper { + margin: 1em 0; +} + +code.xref, a code { + background-color: transparent; + font-weight: bold; +} + +h1 code, h2 code, h3 code, h4 code, h5 code, h6 code { + background-color: transparent; +} + +.viewcode-link { + float: right; +} + +.viewcode-back { + float: right; + font-family: sans-serif; +} + +div.viewcode-block:target { + margin: -1px -10px; + padding: 0 10px; +} + +/* -- math display ---------------------------------------------------------- */ + +img.math { + vertical-align: middle; +} + +div.body div.math p { + text-align: center; +} + +span.eqno { + float: right; +} + +span.eqno a.headerlink { + position: absolute; + z-index: 1; +} + +div.math:hover a.headerlink { + visibility: visible; +} + +/* -- printout stylesheet --------------------------------------------------- */ + +@media print { + div.document, + div.documentwrapper, + div.bodywrapper { + margin: 0 !important; + width: 100%; + } + + div.sphinxsidebar, + div.related, + div.footer, + #top-link { + display: none; + } +} \ No newline at end of file diff --git a/docs/_source/_build/html/_static/debug.css b/docs/_source/_build/html/_static/debug.css new file mode 100644 index 0000000..74d4aec --- /dev/null +++ b/docs/_source/_build/html/_static/debug.css @@ -0,0 +1,69 @@ +/* + This CSS file should be overridden by the theme authors. It's + meant for debugging and developing the skeleton that this theme provides. +*/ +body { + font-family: -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, + "Apple Color Emoji", "Segoe UI Emoji"; + background: lavender; +} +.sb-announcement { + background: rgb(131, 131, 131); +} +.sb-announcement__inner { + background: black; + color: white; +} +.sb-header { + background: lightskyblue; +} +.sb-header__inner { + background: royalblue; + color: white; +} +.sb-header-secondary { + background: lightcyan; +} +.sb-header-secondary__inner { + background: cornflowerblue; + color: white; +} +.sb-sidebar-primary { + background: lightgreen; +} +.sb-main { + background: blanchedalmond; +} +.sb-main__inner { + background: antiquewhite; +} +.sb-header-article { + background: lightsteelblue; +} +.sb-article-container { + background: snow; +} +.sb-article-main { + background: white; +} +.sb-footer-article { + background: lightpink; +} +.sb-sidebar-secondary { + background: lightgoldenrodyellow; +} +.sb-footer-content { + background: plum; +} +.sb-footer-content__inner { + background: palevioletred; +} +.sb-footer { + background: pink; +} +.sb-footer__inner { + background: salmon; +} +.sb-article { + background: white; +} diff --git a/docs/_source/_build/html/_static/doctools.js b/docs/_source/_build/html/_static/doctools.js new file mode 100644 index 0000000..807cdb1 --- /dev/null +++ b/docs/_source/_build/html/_static/doctools.js @@ -0,0 +1,150 @@ +/* + * Base JavaScript utilities for all Sphinx HTML documentation. + */ +"use strict"; + +const BLACKLISTED_KEY_CONTROL_ELEMENTS = new Set([ + "TEXTAREA", + "INPUT", + "SELECT", + "BUTTON", +]); + +const _ready = (callback) => { + if (document.readyState !== "loading") { + callback(); + } else { + document.addEventListener("DOMContentLoaded", callback); + } +}; + +/** + * Small JavaScript module for the documentation. + */ +const Documentation = { + init: () => { + Documentation.initDomainIndexTable(); + Documentation.initOnKeyListeners(); + }, + + /** + * i18n support + */ + TRANSLATIONS: {}, + PLURAL_EXPR: (n) => (n === 1 ? 0 : 1), + LOCALE: "unknown", + + // gettext and ngettext don't access this so that the functions + // can safely bound to a different name (_ = Documentation.gettext) + gettext: (string) => { + const translated = Documentation.TRANSLATIONS[string]; + switch (typeof translated) { + case "undefined": + return string; // no translation + case "string": + return translated; // translation exists + default: + return translated[0]; // (singular, plural) translation tuple exists + } + }, + + ngettext: (singular, plural, n) => { + const translated = Documentation.TRANSLATIONS[singular]; + if (typeof translated !== "undefined") + return translated[Documentation.PLURAL_EXPR(n)]; + return n === 1 ? singular : plural; + }, + + addTranslations: (catalog) => { + Object.assign(Documentation.TRANSLATIONS, catalog.messages); + Documentation.PLURAL_EXPR = new Function( + "n", + `return (${catalog.plural_expr})`, + ); + Documentation.LOCALE = catalog.locale; + }, + + /** + * helper function to focus on search bar + */ + focusSearchBar: () => { + document.querySelectorAll("input[name=q]")[0]?.focus(); + }, + + /** + * Initialise the domain index toggle buttons + */ + initDomainIndexTable: () => { + const toggler = (el) => { + const idNumber = el.id.substr(7); + const toggledRows = document.querySelectorAll(`tr.cg-${idNumber}`); + if (el.src.substr(-9) === "minus.png") { + el.src = `${el.src.substr(0, el.src.length - 9)}plus.png`; + toggledRows.forEach((el) => (el.style.display = "none")); + } else { + el.src = `${el.src.substr(0, el.src.length - 8)}minus.png`; + toggledRows.forEach((el) => (el.style.display = "")); + } + }; + + const togglerElements = document.querySelectorAll("img.toggler"); + togglerElements.forEach((el) => + el.addEventListener("click", (event) => toggler(event.currentTarget)), + ); + togglerElements.forEach((el) => (el.style.display = "")); + if (DOCUMENTATION_OPTIONS.COLLAPSE_INDEX) togglerElements.forEach(toggler); + }, + + initOnKeyListeners: () => { + // only install a listener if it is really needed + if ( + !DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS + && !DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS + ) + return; + + document.addEventListener("keydown", (event) => { + // bail for input elements + if (BLACKLISTED_KEY_CONTROL_ELEMENTS.has(document.activeElement.tagName)) + return; + // bail with special keys + if (event.altKey || event.ctrlKey || event.metaKey) return; + + if (!event.shiftKey) { + switch (event.key) { + case "ArrowLeft": + if (!DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) break; + + const prevLink = document.querySelector('link[rel="prev"]'); + if (prevLink && prevLink.href) { + window.location.href = prevLink.href; + event.preventDefault(); + } + break; + case "ArrowRight": + if (!DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) break; + + const nextLink = document.querySelector('link[rel="next"]'); + if (nextLink && nextLink.href) { + window.location.href = nextLink.href; + event.preventDefault(); + } + break; + } + } + + // some keyboard layouts may need Shift to get / + switch (event.key) { + case "/": + if (!DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS) break; + Documentation.focusSearchBar(); + event.preventDefault(); + } + }); + }, +}; + +// quick alias for translations +const _ = Documentation.gettext; + +_ready(Documentation.init); diff --git a/docs/_source/_build/html/_static/documentation_options.js b/docs/_source/_build/html/_static/documentation_options.js new file mode 100644 index 0000000..a795c44 --- /dev/null +++ b/docs/_source/_build/html/_static/documentation_options.js @@ -0,0 +1,13 @@ +const DOCUMENTATION_OPTIONS = { + VERSION: '9.8.0', + LANGUAGE: 'en', + COLLAPSE_INDEX: false, + BUILDER: 'html', + FILE_SUFFIX: '.html', + LINK_SUFFIX: '.html', + HAS_SOURCE: true, + SOURCELINK_SUFFIX: '.txt', + NAVIGATION_WITH_KEYS: false, + SHOW_SEARCH_SUMMARY: true, + ENABLE_SEARCH_SHORTCUTS: true, +}; \ No newline at end of file diff --git a/docs/_source/_build/html/_static/english-stemmer.js b/docs/_source/_build/html/_static/english-stemmer.js new file mode 100644 index 0000000..056760e --- /dev/null +++ b/docs/_source/_build/html/_static/english-stemmer.js @@ -0,0 +1,1066 @@ +// Generated from english.sbl by Snowball 3.0.1 - https://snowballstem.org/ + +/**@constructor*/ +var EnglishStemmer = function() { + var base = new BaseStemmer(); + + /** @const */ var a_0 = [ + ["arsen", -1, -1], + ["commun", -1, -1], + ["emerg", -1, -1], + ["gener", -1, -1], + ["later", -1, -1], + ["organ", -1, -1], + ["past", -1, -1], + ["univers", -1, -1] + ]; + + /** @const */ var a_1 = [ + ["'", -1, 1], + ["'s'", 0, 1], + ["'s", -1, 1] + ]; + + /** @const */ var a_2 = [ + ["ied", -1, 2], + ["s", -1, 3], + ["ies", 1, 2], + ["sses", 1, 1], + ["ss", 1, -1], + ["us", 1, -1] + ]; + + /** @const */ var a_3 = [ + ["succ", -1, 1], + ["proc", -1, 1], + ["exc", -1, 1] + ]; + + /** @const */ var a_4 = [ + ["even", -1, 2], + ["cann", -1, 2], + ["inn", -1, 2], + ["earr", -1, 2], + ["herr", -1, 2], + ["out", -1, 2], + ["y", -1, 1] + ]; + + /** @const */ var a_5 = [ + ["", -1, -1], + ["ed", 0, 2], + ["eed", 1, 1], + ["ing", 0, 3], + ["edly", 0, 2], + ["eedly", 4, 1], + ["ingly", 0, 2] + ]; + + /** @const */ var a_6 = [ + ["", -1, 3], + ["bb", 0, 2], + ["dd", 0, 2], + ["ff", 0, 2], + ["gg", 0, 2], + ["bl", 0, 1], + ["mm", 0, 2], + ["nn", 0, 2], + ["pp", 0, 2], + ["rr", 0, 2], + ["at", 0, 1], + ["tt", 0, 2], + ["iz", 0, 1] + ]; + + /** @const */ var a_7 = [ + ["anci", -1, 3], + ["enci", -1, 2], + ["ogi", -1, 14], + ["li", -1, 16], + ["bli", 3, 12], + ["abli", 4, 4], + ["alli", 3, 8], + ["fulli", 3, 9], + ["lessli", 3, 15], + ["ousli", 3, 10], + ["entli", 3, 5], + ["aliti", -1, 8], + ["biliti", -1, 12], + ["iviti", -1, 11], + ["tional", -1, 1], + ["ational", 14, 7], + ["alism", -1, 8], + ["ation", -1, 7], + ["ization", 17, 6], + ["izer", -1, 6], + ["ator", -1, 7], + ["iveness", -1, 11], + ["fulness", -1, 9], + ["ousness", -1, 10], + ["ogist", -1, 13] + ]; + + /** @const */ var a_8 = [ + ["icate", -1, 4], + ["ative", -1, 6], + ["alize", -1, 3], + ["iciti", -1, 4], + ["ical", -1, 4], + ["tional", -1, 1], + ["ational", 5, 2], + ["ful", -1, 5], + ["ness", -1, 5] + ]; + + /** @const */ var a_9 = [ + ["ic", -1, 1], + ["ance", -1, 1], + ["ence", -1, 1], + ["able", -1, 1], + ["ible", -1, 1], + ["ate", -1, 1], + ["ive", -1, 1], + ["ize", -1, 1], + ["iti", -1, 1], + ["al", -1, 1], + ["ism", -1, 1], + ["ion", -1, 2], + ["er", -1, 1], + ["ous", -1, 1], + ["ant", -1, 1], + ["ent", -1, 1], + ["ment", 15, 1], + ["ement", 16, 1] + ]; + + /** @const */ var a_10 = [ + ["e", -1, 1], + ["l", -1, 2] + ]; + + /** @const */ var a_11 = [ + ["andes", -1, -1], + ["atlas", -1, -1], + ["bias", -1, -1], + ["cosmos", -1, -1], + ["early", -1, 5], + ["gently", -1, 3], + ["howe", -1, -1], + ["idly", -1, 2], + ["news", -1, -1], + ["only", -1, 6], + ["singly", -1, 7], + ["skies", -1, 1], + ["sky", -1, -1], + ["ugly", -1, 4] + ]; + + /** @const */ var /** Array */ g_aeo = [17, 64]; + + /** @const */ var /** Array */ g_v = [17, 65, 16, 1]; + + /** @const */ var /** Array */ g_v_WXY = [1, 17, 65, 208, 1]; + + /** @const */ var /** Array */ g_valid_LI = [55, 141, 2]; + + var /** boolean */ B_Y_found = false; + var /** number */ I_p2 = 0; + var /** number */ I_p1 = 0; + + + /** @return {boolean} */ + function r_prelude() { + B_Y_found = false; + /** @const */ var /** number */ v_1 = base.cursor; + lab0: { + base.bra = base.cursor; + if (!(base.eq_s("'"))) + { + break lab0; + } + base.ket = base.cursor; + if (!base.slice_del()) + { + return false; + } + } + base.cursor = v_1; + /** @const */ var /** number */ v_2 = base.cursor; + lab1: { + base.bra = base.cursor; + if (!(base.eq_s("y"))) + { + break lab1; + } + base.ket = base.cursor; + if (!base.slice_from("Y")) + { + return false; + } + B_Y_found = true; + } + base.cursor = v_2; + /** @const */ var /** number */ v_3 = base.cursor; + lab2: { + while(true) + { + /** @const */ var /** number */ v_4 = base.cursor; + lab3: { + golab4: while(true) + { + /** @const */ var /** number */ v_5 = base.cursor; + lab5: { + if (!(base.in_grouping(g_v, 97, 121))) + { + break lab5; + } + base.bra = base.cursor; + if (!(base.eq_s("y"))) + { + break lab5; + } + base.ket = base.cursor; + base.cursor = v_5; + break golab4; + } + base.cursor = v_5; + if (base.cursor >= base.limit) + { + break lab3; + } + base.cursor++; + } + if (!base.slice_from("Y")) + { + return false; + } + B_Y_found = true; + continue; + } + base.cursor = v_4; + break; + } + } + base.cursor = v_3; + return true; + }; + + /** @return {boolean} */ + function r_mark_regions() { + I_p1 = base.limit; + I_p2 = base.limit; + /** @const */ var /** number */ v_1 = base.cursor; + lab0: { + lab1: { + /** @const */ var /** number */ v_2 = base.cursor; + lab2: { + if (base.find_among(a_0) == 0) + { + break lab2; + } + break lab1; + } + base.cursor = v_2; + if (!base.go_out_grouping(g_v, 97, 121)) + { + break lab0; + } + base.cursor++; + if (!base.go_in_grouping(g_v, 97, 121)) + { + break lab0; + } + base.cursor++; + } + I_p1 = base.cursor; + if (!base.go_out_grouping(g_v, 97, 121)) + { + break lab0; + } + base.cursor++; + if (!base.go_in_grouping(g_v, 97, 121)) + { + break lab0; + } + base.cursor++; + I_p2 = base.cursor; + } + base.cursor = v_1; + return true; + }; + + /** @return {boolean} */ + function r_shortv() { + lab0: { + /** @const */ var /** number */ v_1 = base.limit - base.cursor; + lab1: { + if (!(base.out_grouping_b(g_v_WXY, 89, 121))) + { + break lab1; + } + if (!(base.in_grouping_b(g_v, 97, 121))) + { + break lab1; + } + if (!(base.out_grouping_b(g_v, 97, 121))) + { + break lab1; + } + break lab0; + } + base.cursor = base.limit - v_1; + lab2: { + if (!(base.out_grouping_b(g_v, 97, 121))) + { + break lab2; + } + if (!(base.in_grouping_b(g_v, 97, 121))) + { + break lab2; + } + if (base.cursor > base.limit_backward) + { + break lab2; + } + break lab0; + } + base.cursor = base.limit - v_1; + if (!(base.eq_s_b("past"))) + { + return false; + } + } + return true; + }; + + /** @return {boolean} */ + function r_R1() { + return I_p1 <= base.cursor; + }; + + /** @return {boolean} */ + function r_R2() { + return I_p2 <= base.cursor; + }; + + /** @return {boolean} */ + function r_Step_1a() { + var /** number */ among_var; + /** @const */ var /** number */ v_1 = base.limit - base.cursor; + lab0: { + base.ket = base.cursor; + if (base.find_among_b(a_1) == 0) + { + base.cursor = base.limit - v_1; + break lab0; + } + base.bra = base.cursor; + if (!base.slice_del()) + { + return false; + } + } + base.ket = base.cursor; + among_var = base.find_among_b(a_2); + if (among_var == 0) + { + return false; + } + base.bra = base.cursor; + switch (among_var) { + case 1: + if (!base.slice_from("ss")) + { + return false; + } + break; + case 2: + lab1: { + /** @const */ var /** number */ v_2 = base.limit - base.cursor; + lab2: { + { + /** @const */ var /** number */ c1 = base.cursor - 2; + if (c1 < base.limit_backward) + { + break lab2; + } + base.cursor = c1; + } + if (!base.slice_from("i")) + { + return false; + } + break lab1; + } + base.cursor = base.limit - v_2; + if (!base.slice_from("ie")) + { + return false; + } + } + break; + case 3: + if (base.cursor <= base.limit_backward) + { + return false; + } + base.cursor--; + if (!base.go_out_grouping_b(g_v, 97, 121)) + { + return false; + } + base.cursor--; + if (!base.slice_del()) + { + return false; + } + break; + } + return true; + }; + + /** @return {boolean} */ + function r_Step_1b() { + var /** number */ among_var; + base.ket = base.cursor; + among_var = base.find_among_b(a_5); + base.bra = base.cursor; + lab0: { + /** @const */ var /** number */ v_1 = base.limit - base.cursor; + lab1: { + switch (among_var) { + case 1: + /** @const */ var /** number */ v_2 = base.limit - base.cursor; + lab2: { + lab3: { + /** @const */ var /** number */ v_3 = base.limit - base.cursor; + lab4: { + if (base.find_among_b(a_3) == 0) + { + break lab4; + } + if (base.cursor > base.limit_backward) + { + break lab4; + } + break lab3; + } + base.cursor = base.limit - v_3; + if (!r_R1()) + { + break lab2; + } + if (!base.slice_from("ee")) + { + return false; + } + } + } + base.cursor = base.limit - v_2; + break; + case 2: + break lab1; + case 3: + among_var = base.find_among_b(a_4); + if (among_var == 0) + { + break lab1; + } + switch (among_var) { + case 1: + /** @const */ var /** number */ v_4 = base.limit - base.cursor; + if (!(base.out_grouping_b(g_v, 97, 121))) + { + break lab1; + } + if (base.cursor > base.limit_backward) + { + break lab1; + } + base.cursor = base.limit - v_4; + base.bra = base.cursor; + if (!base.slice_from("ie")) + { + return false; + } + break; + case 2: + if (base.cursor > base.limit_backward) + { + break lab1; + } + break; + } + break; + } + break lab0; + } + base.cursor = base.limit - v_1; + /** @const */ var /** number */ v_5 = base.limit - base.cursor; + if (!base.go_out_grouping_b(g_v, 97, 121)) + { + return false; + } + base.cursor--; + base.cursor = base.limit - v_5; + if (!base.slice_del()) + { + return false; + } + base.ket = base.cursor; + base.bra = base.cursor; + /** @const */ var /** number */ v_6 = base.limit - base.cursor; + among_var = base.find_among_b(a_6); + switch (among_var) { + case 1: + if (!base.slice_from("e")) + { + return false; + } + return false; + case 2: + { + /** @const */ var /** number */ v_7 = base.limit - base.cursor; + lab5: { + if (!(base.in_grouping_b(g_aeo, 97, 111))) + { + break lab5; + } + if (base.cursor > base.limit_backward) + { + break lab5; + } + return false; + } + base.cursor = base.limit - v_7; + } + break; + case 3: + if (base.cursor != I_p1) + { + return false; + } + /** @const */ var /** number */ v_8 = base.limit - base.cursor; + if (!r_shortv()) + { + return false; + } + base.cursor = base.limit - v_8; + if (!base.slice_from("e")) + { + return false; + } + return false; + } + base.cursor = base.limit - v_6; + base.ket = base.cursor; + if (base.cursor <= base.limit_backward) + { + return false; + } + base.cursor--; + base.bra = base.cursor; + if (!base.slice_del()) + { + return false; + } + } + return true; + }; + + /** @return {boolean} */ + function r_Step_1c() { + base.ket = base.cursor; + lab0: { + /** @const */ var /** number */ v_1 = base.limit - base.cursor; + lab1: { + if (!(base.eq_s_b("y"))) + { + break lab1; + } + break lab0; + } + base.cursor = base.limit - v_1; + if (!(base.eq_s_b("Y"))) + { + return false; + } + } + base.bra = base.cursor; + if (!(base.out_grouping_b(g_v, 97, 121))) + { + return false; + } + lab2: { + if (base.cursor > base.limit_backward) + { + break lab2; + } + return false; + } + if (!base.slice_from("i")) + { + return false; + } + return true; + }; + + /** @return {boolean} */ + function r_Step_2() { + var /** number */ among_var; + base.ket = base.cursor; + among_var = base.find_among_b(a_7); + if (among_var == 0) + { + return false; + } + base.bra = base.cursor; + if (!r_R1()) + { + return false; + } + switch (among_var) { + case 1: + if (!base.slice_from("tion")) + { + return false; + } + break; + case 2: + if (!base.slice_from("ence")) + { + return false; + } + break; + case 3: + if (!base.slice_from("ance")) + { + return false; + } + break; + case 4: + if (!base.slice_from("able")) + { + return false; + } + break; + case 5: + if (!base.slice_from("ent")) + { + return false; + } + break; + case 6: + if (!base.slice_from("ize")) + { + return false; + } + break; + case 7: + if (!base.slice_from("ate")) + { + return false; + } + break; + case 8: + if (!base.slice_from("al")) + { + return false; + } + break; + case 9: + if (!base.slice_from("ful")) + { + return false; + } + break; + case 10: + if (!base.slice_from("ous")) + { + return false; + } + break; + case 11: + if (!base.slice_from("ive")) + { + return false; + } + break; + case 12: + if (!base.slice_from("ble")) + { + return false; + } + break; + case 13: + if (!base.slice_from("og")) + { + return false; + } + break; + case 14: + if (!(base.eq_s_b("l"))) + { + return false; + } + if (!base.slice_from("og")) + { + return false; + } + break; + case 15: + if (!base.slice_from("less")) + { + return false; + } + break; + case 16: + if (!(base.in_grouping_b(g_valid_LI, 99, 116))) + { + return false; + } + if (!base.slice_del()) + { + return false; + } + break; + } + return true; + }; + + /** @return {boolean} */ + function r_Step_3() { + var /** number */ among_var; + base.ket = base.cursor; + among_var = base.find_among_b(a_8); + if (among_var == 0) + { + return false; + } + base.bra = base.cursor; + if (!r_R1()) + { + return false; + } + switch (among_var) { + case 1: + if (!base.slice_from("tion")) + { + return false; + } + break; + case 2: + if (!base.slice_from("ate")) + { + return false; + } + break; + case 3: + if (!base.slice_from("al")) + { + return false; + } + break; + case 4: + if (!base.slice_from("ic")) + { + return false; + } + break; + case 5: + if (!base.slice_del()) + { + return false; + } + break; + case 6: + if (!r_R2()) + { + return false; + } + if (!base.slice_del()) + { + return false; + } + break; + } + return true; + }; + + /** @return {boolean} */ + function r_Step_4() { + var /** number */ among_var; + base.ket = base.cursor; + among_var = base.find_among_b(a_9); + if (among_var == 0) + { + return false; + } + base.bra = base.cursor; + if (!r_R2()) + { + return false; + } + switch (among_var) { + case 1: + if (!base.slice_del()) + { + return false; + } + break; + case 2: + lab0: { + /** @const */ var /** number */ v_1 = base.limit - base.cursor; + lab1: { + if (!(base.eq_s_b("s"))) + { + break lab1; + } + break lab0; + } + base.cursor = base.limit - v_1; + if (!(base.eq_s_b("t"))) + { + return false; + } + } + if (!base.slice_del()) + { + return false; + } + break; + } + return true; + }; + + /** @return {boolean} */ + function r_Step_5() { + var /** number */ among_var; + base.ket = base.cursor; + among_var = base.find_among_b(a_10); + if (among_var == 0) + { + return false; + } + base.bra = base.cursor; + switch (among_var) { + case 1: + lab0: { + lab1: { + if (!r_R2()) + { + break lab1; + } + break lab0; + } + if (!r_R1()) + { + return false; + } + { + /** @const */ var /** number */ v_1 = base.limit - base.cursor; + lab2: { + if (!r_shortv()) + { + break lab2; + } + return false; + } + base.cursor = base.limit - v_1; + } + } + if (!base.slice_del()) + { + return false; + } + break; + case 2: + if (!r_R2()) + { + return false; + } + if (!(base.eq_s_b("l"))) + { + return false; + } + if (!base.slice_del()) + { + return false; + } + break; + } + return true; + }; + + /** @return {boolean} */ + function r_exception1() { + var /** number */ among_var; + base.bra = base.cursor; + among_var = base.find_among(a_11); + if (among_var == 0) + { + return false; + } + base.ket = base.cursor; + if (base.cursor < base.limit) + { + return false; + } + switch (among_var) { + case 1: + if (!base.slice_from("sky")) + { + return false; + } + break; + case 2: + if (!base.slice_from("idl")) + { + return false; + } + break; + case 3: + if (!base.slice_from("gentl")) + { + return false; + } + break; + case 4: + if (!base.slice_from("ugli")) + { + return false; + } + break; + case 5: + if (!base.slice_from("earli")) + { + return false; + } + break; + case 6: + if (!base.slice_from("onli")) + { + return false; + } + break; + case 7: + if (!base.slice_from("singl")) + { + return false; + } + break; + } + return true; + }; + + /** @return {boolean} */ + function r_postlude() { + if (!B_Y_found) + { + return false; + } + while(true) + { + /** @const */ var /** number */ v_1 = base.cursor; + lab0: { + golab1: while(true) + { + /** @const */ var /** number */ v_2 = base.cursor; + lab2: { + base.bra = base.cursor; + if (!(base.eq_s("Y"))) + { + break lab2; + } + base.ket = base.cursor; + base.cursor = v_2; + break golab1; + } + base.cursor = v_2; + if (base.cursor >= base.limit) + { + break lab0; + } + base.cursor++; + } + if (!base.slice_from("y")) + { + return false; + } + continue; + } + base.cursor = v_1; + break; + } + return true; + }; + + this.stem = /** @return {boolean} */ function() { + lab0: { + /** @const */ var /** number */ v_1 = base.cursor; + lab1: { + if (!r_exception1()) + { + break lab1; + } + break lab0; + } + base.cursor = v_1; + lab2: { + { + /** @const */ var /** number */ v_2 = base.cursor; + lab3: { + { + /** @const */ var /** number */ c1 = base.cursor + 3; + if (c1 > base.limit) + { + break lab3; + } + base.cursor = c1; + } + break lab2; + } + base.cursor = v_2; + } + break lab0; + } + base.cursor = v_1; + r_prelude(); + r_mark_regions(); + base.limit_backward = base.cursor; base.cursor = base.limit; + /** @const */ var /** number */ v_3 = base.limit - base.cursor; + r_Step_1a(); + base.cursor = base.limit - v_3; + /** @const */ var /** number */ v_4 = base.limit - base.cursor; + r_Step_1b(); + base.cursor = base.limit - v_4; + /** @const */ var /** number */ v_5 = base.limit - base.cursor; + r_Step_1c(); + base.cursor = base.limit - v_5; + /** @const */ var /** number */ v_6 = base.limit - base.cursor; + r_Step_2(); + base.cursor = base.limit - v_6; + /** @const */ var /** number */ v_7 = base.limit - base.cursor; + r_Step_3(); + base.cursor = base.limit - v_7; + /** @const */ var /** number */ v_8 = base.limit - base.cursor; + r_Step_4(); + base.cursor = base.limit - v_8; + /** @const */ var /** number */ v_9 = base.limit - base.cursor; + r_Step_5(); + base.cursor = base.limit - v_9; + base.cursor = base.limit_backward; + /** @const */ var /** number */ v_10 = base.cursor; + r_postlude(); + base.cursor = v_10; + } + return true; + }; + + /**@return{string}*/ + this['stemWord'] = function(/**string*/word) { + base.setCurrent(word); + this.stem(); + return base.getCurrent(); + }; +}; diff --git a/docs/_source/_build/html/_static/file.png b/docs/_source/_build/html/_static/file.png new file mode 100644 index 0000000000000000000000000000000000000000..a858a410e4faa62ce324d814e4b816fff83a6fb3 GIT binary patch literal 286 zcmV+(0pb3MP)s`hMrGg#P~ix$^RISR_I47Y|r1 z_CyJOe}D1){SET-^Amu_i71Lt6eYfZjRyw@I6OQAIXXHDfiX^GbOlHe=Ae4>0m)d(f|Me07*qoM6N<$f}vM^LjV8( literal 0 HcmV?d00001 diff --git a/docs/_source/_build/html/_static/language_data.js b/docs/_source/_build/html/_static/language_data.js new file mode 100644 index 0000000..5776786 --- /dev/null +++ b/docs/_source/_build/html/_static/language_data.js @@ -0,0 +1,13 @@ +/* + * This script contains the language-specific data used by searchtools.js, + * namely the set of stopwords, stemmer, scorer and splitter. + */ + +const stopwords = new Set(["a", "about", "above", "after", "again", "against", "all", "am", "an", "and", "any", "are", "aren't", "as", "at", "be", "because", "been", "before", "being", "below", "between", "both", "but", "by", "can't", "cannot", "could", "couldn't", "did", "didn't", "do", "does", "doesn't", "doing", "don't", "down", "during", "each", "few", "for", "from", "further", "had", "hadn't", "has", "hasn't", "have", "haven't", "having", "he", "he'd", "he'll", "he's", "her", "here", "here's", "hers", "herself", "him", "himself", "his", "how", "how's", "i", "i'd", "i'll", "i'm", "i've", "if", "in", "into", "is", "isn't", "it", "it's", "its", "itself", "let's", "me", "more", "most", "mustn't", "my", "myself", "no", "nor", "not", "of", "off", "on", "once", "only", "or", "other", "ought", "our", "ours", "ourselves", "out", "over", "own", "same", "shan't", "she", "she'd", "she'll", "she's", "should", "shouldn't", "so", "some", "such", "than", "that", "that's", "the", "their", "theirs", "them", "themselves", "then", "there", "there's", "these", "they", "they'd", "they'll", "they're", "they've", "this", "those", "through", "to", "too", "under", "until", "up", "very", "was", "wasn't", "we", "we'd", "we'll", "we're", "we've", "were", "weren't", "what", "what's", "when", "when's", "where", "where's", "which", "while", "who", "who's", "whom", "why", "why's", "with", "won't", "would", "wouldn't", "you", "you'd", "you'll", "you're", "you've", "your", "yours", "yourself", "yourselves"]); +window.stopwords = stopwords; // Export to global scope + + +/* Non-minified versions are copied as separate JavaScript files, if available */ +BaseStemmer=function(){this.current="",this.cursor=0,this.limit=0,this.limit_backward=0,this.bra=0,this.ket=0,this.setCurrent=function(t){this.current=t,this.cursor=0,this.limit=this.current.length,this.limit_backward=0,this.bra=this.cursor,this.ket=this.limit},this.getCurrent=function(){return this.current},this.copy_from=function(t){this.current=t.current,this.cursor=t.cursor,this.limit=t.limit,this.limit_backward=t.limit_backward,this.bra=t.bra,this.ket=t.ket},this.in_grouping=function(t,r,i){return!(this.cursor>=this.limit||i<(i=this.current.charCodeAt(this.cursor))||i>>3]&1<<(7&i))||(this.cursor++,0))},this.go_in_grouping=function(t,r,i){for(;this.cursor>>3]&1<<(7&s)))return!0;this.cursor++}return!1},this.in_grouping_b=function(t,r,i){return!(this.cursor<=this.limit_backward||i<(i=this.current.charCodeAt(this.cursor-1))||i>>3]&1<<(7&i))||(this.cursor--,0))},this.go_in_grouping_b=function(t,r,i){for(;this.cursor>this.limit_backward;){var s=this.current.charCodeAt(this.cursor-1);if(i>>3]&1<<(7&s)))return!0;this.cursor--}return!1},this.out_grouping=function(t,r,i){return!(this.cursor>=this.limit)&&(i<(i=this.current.charCodeAt(this.cursor))||i>>3]&1<<(7&i)))&&(this.cursor++,!0)},this.go_out_grouping=function(t,r,i){for(;this.cursor>>3]&1<<(7&s)))return!0;this.cursor++}return!1},this.out_grouping_b=function(t,r,i){return!(this.cursor<=this.limit_backward)&&(i<(i=this.current.charCodeAt(this.cursor-1))||i>>3]&1<<(7&i)))&&(this.cursor--,!0)},this.go_out_grouping_b=function(t,r,i){for(;this.cursor>this.limit_backward;){var s=this.current.charCodeAt(this.cursor-1);if(s<=i&&r<=s&&0!=(t[(s-=r)>>>3]&1<<(7&s)))return!0;this.cursor--}return!1},this.eq_s=function(t){return!(this.limit-this.cursor>>1),o=0,a=e=(l=t[r])[0].length){if(this.cursor=s+l[0].length,l.length<4)return l[2];var g=l[3](this);if(this.cursor=s+l[0].length,g)return l[2]}}while(0<=(r=l[1]));return 0},this.find_among_b=function(t){for(var r=0,i=t.length,s=this.cursor,h=this.limit_backward,e=0,n=0,c=!1;;){for(var u,o=r+(i-r>>1),a=0,l=e=(u=t[r])[0].length){if(this.cursor=s-u[0].length,u.length<4)return u[2];var g=u[3](this);if(this.cursor=s-u[0].length,g)return u[2]}}while(0<=(r=u[1]));return 0},this.replace_s=function(t,r,i){var s=i.length-(r-t);return this.current=this.current.slice(0,t)+i+this.current.slice(r),this.limit+=s,this.cursor>=r?this.cursor+=s:this.cursor>t&&(this.cursor=t),s},this.slice_check=function(){return!(this.bra<0||this.bra>this.ket||this.ket>this.limit||this.limit>this.current.length)},this.slice_from=function(t){var r=!1;return this.slice_check()&&(this.replace_s(this.bra,this.ket,t),r=!0),r},this.slice_del=function(){return this.slice_from("")},this.insert=function(t,r,i){r=this.replace_s(t,r,i);t<=this.bra&&(this.bra+=r),t<=this.ket&&(this.ket+=r)},this.slice_to=function(){var t="";return t=this.slice_check()?this.current.slice(this.bra,this.ket):t},this.assign_to=function(){return this.current.slice(0,this.limit)}}; +var EnglishStemmer=function(){var a=new BaseStemmer,c=[["arsen",-1,-1],["commun",-1,-1],["emerg",-1,-1],["gener",-1,-1],["later",-1,-1],["organ",-1,-1],["past",-1,-1],["univers",-1,-1]],o=[["'",-1,1],["'s'",0,1],["'s",-1,1]],u=[["ied",-1,2],["s",-1,3],["ies",1,2],["sses",1,1],["ss",1,-1],["us",1,-1]],t=[["succ",-1,1],["proc",-1,1],["exc",-1,1]],l=[["even",-1,2],["cann",-1,2],["inn",-1,2],["earr",-1,2],["herr",-1,2],["out",-1,2],["y",-1,1]],n=[["",-1,-1],["ed",0,2],["eed",1,1],["ing",0,3],["edly",0,2],["eedly",4,1],["ingly",0,2]],f=[["",-1,3],["bb",0,2],["dd",0,2],["ff",0,2],["gg",0,2],["bl",0,1],["mm",0,2],["nn",0,2],["pp",0,2],["rr",0,2],["at",0,1],["tt",0,2],["iz",0,1]],_=[["anci",-1,3],["enci",-1,2],["ogi",-1,14],["li",-1,16],["bli",3,12],["abli",4,4],["alli",3,8],["fulli",3,9],["lessli",3,15],["ousli",3,10],["entli",3,5],["aliti",-1,8],["biliti",-1,12],["iviti",-1,11],["tional",-1,1],["ational",14,7],["alism",-1,8],["ation",-1,7],["ization",17,6],["izer",-1,6],["ator",-1,7],["iveness",-1,11],["fulness",-1,9],["ousness",-1,10],["ogist",-1,13]],m=[["icate",-1,4],["ative",-1,6],["alize",-1,3],["iciti",-1,4],["ical",-1,4],["tional",-1,1],["ational",5,2],["ful",-1,5],["ness",-1,5]],b=[["ic",-1,1],["ance",-1,1],["ence",-1,1],["able",-1,1],["ible",-1,1],["ate",-1,1],["ive",-1,1],["ize",-1,1],["iti",-1,1],["al",-1,1],["ism",-1,1],["ion",-1,2],["er",-1,1],["ous",-1,1],["ant",-1,1],["ent",-1,1],["ment",15,1],["ement",16,1]],k=[["e",-1,1],["l",-1,2]],g=[["andes",-1,-1],["atlas",-1,-1],["bias",-1,-1],["cosmos",-1,-1],["early",-1,5],["gently",-1,3],["howe",-1,-1],["idly",-1,2],["news",-1,-1],["only",-1,6],["singly",-1,7],["skies",-1,1],["sky",-1,-1],["ugly",-1,4]],d=[17,64],v=[17,65,16,1],i=[1,17,65,208,1],w=[55,141,2],p=!1,y=0,h=0;function q(){var r=a.limit-a.cursor;return!!(a.out_grouping_b(i,89,121)&&a.in_grouping_b(v,97,121)&&a.out_grouping_b(v,97,121)||(a.cursor=a.limit-r,a.out_grouping_b(v,97,121)&&a.in_grouping_b(v,97,121)&&!(a.cursor>a.limit_backward))||(a.cursor=a.limit-r,a.eq_s_b("past")))}function z(){return h<=a.cursor}function Y(){return y<=a.cursor}this.stem=function(){var r=a.cursor;if(!(()=>{var r;if(a.bra=a.cursor,0!=(r=a.find_among(g))&&(a.ket=a.cursor,!(a.cursora.limit)a.cursor=i;else{a.cursor=e,a.cursor=r,(()=>{p=!1;var r=a.cursor;if(a.bra=a.cursor,!a.eq_s("'")||(a.ket=a.cursor,a.slice_del())){a.cursor=r;r=a.cursor;if(a.bra=a.cursor,a.eq_s("y")){if(a.ket=a.cursor,!a.slice_from("Y"))return;p=!0}a.cursor=r;for(r=a.cursor;;){var i=a.cursor;r:{for(;;){var e=a.cursor;if(a.in_grouping(v,97,121)&&(a.bra=a.cursor,a.eq_s("y"))){a.ket=a.cursor,a.cursor=e;break}if(a.cursor=e,a.cursor>=a.limit)break r;a.cursor++}if(!a.slice_from("Y"))return;p=!0;continue}a.cursor=i;break}a.cursor=r}})(),h=a.limit,y=a.limit;i=a.cursor;r:{var s=a.cursor;if(0==a.find_among(c)){if(a.cursor=s,!a.go_out_grouping(v,97,121))break r;if(a.cursor++,!a.go_in_grouping(v,97,121))break r;a.cursor++}h=a.cursor,a.go_out_grouping(v,97,121)&&(a.cursor++,a.go_in_grouping(v,97,121))&&(a.cursor++,y=a.cursor)}a.cursor=i,a.limit_backward=a.cursor,a.cursor=a.limit;var e=a.limit-a.cursor,r=((()=>{var r=a.limit-a.cursor;if(a.ket=a.cursor,0==a.find_among_b(o))a.cursor=a.limit-r;else if(a.bra=a.cursor,!a.slice_del())return;if(a.ket=a.cursor,0!=(r=a.find_among_b(u)))switch(a.bra=a.cursor,r){case 1:if(a.slice_from("ss"))break;return;case 2:r:{var i=a.limit-a.cursor,e=a.cursor-2;if(!(e{a.ket=a.cursor,o=a.find_among_b(n),a.bra=a.cursor;r:{var r=a.limit-a.cursor;i:{switch(o){case 1:var i=a.limit-a.cursor;e:{var e=a.limit-a.cursor;if(0==a.find_among_b(t)||a.cursor>a.limit_backward){if(a.cursor=a.limit-e,!z())break e;if(!a.slice_from("ee"))return}}a.cursor=a.limit-i;break;case 2:break i;case 3:if(0==(o=a.find_among_b(l)))break i;switch(o){case 1:var s=a.limit-a.cursor;if(!a.out_grouping_b(v,97,121))break i;if(a.cursor>a.limit_backward)break i;if(a.cursor=a.limit-s,a.bra=a.cursor,a.slice_from("ie"))break;return;case 2:if(a.cursor>a.limit_backward)break i}}break r}a.cursor=a.limit-r;var c=a.limit-a.cursor;if(!a.go_out_grouping_b(v,97,121))return;if(a.cursor--,a.cursor=a.limit-c,!a.slice_del())return;a.ket=a.cursor,a.bra=a.cursor;var o,c=a.limit-a.cursor;switch(o=a.find_among_b(f)){case 1:return a.slice_from("e");case 2:var u=a.limit-a.cursor;if(a.in_grouping_b(d,97,111)&&!(a.cursor>a.limit_backward))return;a.cursor=a.limit-u;break;case 3:return a.cursor!=h||(u=a.limit-a.cursor,q()&&(a.cursor=a.limit-u,a.slice_from("e")))}if(a.cursor=a.limit-c,a.ket=a.cursor,a.cursor<=a.limit_backward)return;if(a.cursor--,a.bra=a.cursor,!a.slice_del())return}})(),a.cursor=a.limit-r,a.limit-a.cursor),r=(a.ket=a.cursor,e=a.limit-a.cursor,(a.eq_s_b("y")||(a.cursor=a.limit-e,a.eq_s_b("Y")))&&(a.bra=a.cursor,a.out_grouping_b(v,97,121))&&a.cursor>a.limit_backward&&a.slice_from("i"),a.cursor=a.limit-i,a.limit-a.cursor),e=((()=>{var r;if(a.ket=a.cursor,0!=(r=a.find_among_b(_))&&(a.bra=a.cursor,z()))switch(r){case 1:if(a.slice_from("tion"))break;return;case 2:if(a.slice_from("ence"))break;return;case 3:if(a.slice_from("ance"))break;return;case 4:if(a.slice_from("able"))break;return;case 5:if(a.slice_from("ent"))break;return;case 6:if(a.slice_from("ize"))break;return;case 7:if(a.slice_from("ate"))break;return;case 8:if(a.slice_from("al"))break;return;case 9:if(a.slice_from("ful"))break;return;case 10:if(a.slice_from("ous"))break;return;case 11:if(a.slice_from("ive"))break;return;case 12:if(a.slice_from("ble"))break;return;case 13:if(a.slice_from("og"))break;return;case 14:if(!a.eq_s_b("l"))return;if(a.slice_from("og"))break;return;case 15:if(a.slice_from("less"))break;return;case 16:if(!a.in_grouping_b(w,99,116))return;if(a.slice_del())break}})(),a.cursor=a.limit-r,a.limit-a.cursor),i=((()=>{var r;if(a.ket=a.cursor,0!=(r=a.find_among_b(m))&&(a.bra=a.cursor,z()))switch(r){case 1:if(a.slice_from("tion"))break;return;case 2:if(a.slice_from("ate"))break;return;case 3:if(a.slice_from("al"))break;return;case 4:if(a.slice_from("ic"))break;return;case 5:if(a.slice_del())break;return;case 6:if(!Y())return;if(a.slice_del())break}})(),a.cursor=a.limit-e,a.limit-a.cursor),r=((()=>{var r;if(a.ket=a.cursor,0!=(r=a.find_among_b(b))&&(a.bra=a.cursor,Y()))switch(r){case 1:if(a.slice_del())break;return;case 2:var i=a.limit-a.cursor;if(!a.eq_s_b("s")&&(a.cursor=a.limit-i,!a.eq_s_b("t")))return;if(a.slice_del())break}})(),a.cursor=a.limit-i,a.limit-a.cursor),e=((()=>{var r;if(a.ket=a.cursor,0!=(r=a.find_among_b(k)))switch(a.bra=a.cursor,r){case 1:if(!Y()){if(!z())return;var i=a.limit-a.cursor;if(q())return;a.cursor=a.limit-i}if(a.slice_del())break;return;case 2:if(!Y())return;if(!a.eq_s_b("l"))return;if(a.slice_del())break}})(),a.cursor=a.limit-r,a.cursor=a.limit_backward,a.cursor);(()=>{if(p)for(;;){var r=a.cursor;r:{for(;;){var i=a.cursor;if(a.bra=a.cursor,a.eq_s("Y")){a.ket=a.cursor,a.cursor=i;break}if(a.cursor=i,a.cursor>=a.limit)break r;a.cursor++}if(a.slice_from("y"))continue;return}a.cursor=r;break}})(),a.cursor=e}}return!0},this.stemWord=function(r){return a.setCurrent(r),this.stem(),a.getCurrent()}}; +window.Stemmer = EnglishStemmer; diff --git a/docs/_source/_build/html/_static/minus.png b/docs/_source/_build/html/_static/minus.png new file mode 100644 index 0000000000000000000000000000000000000000..d96755fdaf8bb2214971e0db9c1fd3077d7c419d GIT binary patch literal 90 zcmeAS@N?(olHy`uVBq!ia0vp^+#t*WBp7;*Yy1LIik>cxAr*|t7R?Mi>2?kWtu=nj kDsEF_5m^0CR;1wuP-*O&G^0G}KYk!hp00i_>zopr08q^qX#fBK literal 0 HcmV?d00001 diff --git a/docs/_source/_build/html/_static/plus.png b/docs/_source/_build/html/_static/plus.png new file mode 100644 index 0000000000000000000000000000000000000000..7107cec93a979b9a5f64843235a16651d563ce2d GIT binary patch literal 90 zcmeAS@N?(olHy`uVBq!ia0vp^+#t*WBp7;*Yy1LIik>cxAr*|t7R?Mi>2?kWtu>-2 m3q%Vub%g%s<8sJhVPMczOq}xhg9DJoz~JfX=d#Wzp$Pyb1r*Kz literal 0 HcmV?d00001 diff --git a/docs/_source/_build/html/_static/pygments.css b/docs/_source/_build/html/_static/pygments.css new file mode 100644 index 0000000..9d1083b --- /dev/null +++ b/docs/_source/_build/html/_static/pygments.css @@ -0,0 +1,250 @@ +.highlight pre { line-height: 125%; } +.highlight td.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; } +.highlight span.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; } +.highlight td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; } +.highlight span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; } +.highlight .hll { background-color: #fdf2e2 } +.highlight { background: #f2f2f2; color: #1E1E1E } +.highlight .c { color: #515151 } /* Comment */ +.highlight .err { color: #D71835 } /* Error */ +.highlight .k { color: #8045E5 } /* Keyword */ +.highlight .l { color: #7F4707 } /* Literal */ +.highlight .n { color: #1E1E1E } /* Name */ +.highlight .o { color: #163 } /* Operator */ +.highlight .p { color: #1E1E1E } /* Punctuation */ +.highlight .ch { color: #515151 } /* Comment.Hashbang */ +.highlight .cm { color: #515151 } /* Comment.Multiline */ +.highlight .cp { color: #515151 } /* Comment.Preproc */ +.highlight .cpf { color: #515151 } /* Comment.PreprocFile */ +.highlight .c1 { color: #515151 } /* Comment.Single */ +.highlight .cs { color: #515151 } /* Comment.Special */ +.highlight .gd { color: #00749C } /* Generic.Deleted */ +.highlight .ge { font-style: italic } /* Generic.Emph */ +.highlight .gh { color: #00749C } /* Generic.Heading */ +.highlight .gs { font-weight: bold } /* Generic.Strong */ +.highlight .gu { color: #00749C } /* Generic.Subheading */ +.highlight .kc { color: #8045E5 } /* Keyword.Constant */ +.highlight .kd { color: #8045E5 } /* Keyword.Declaration */ +.highlight .kn { color: #8045E5 } /* Keyword.Namespace */ +.highlight .kp { color: #8045E5 } /* Keyword.Pseudo */ +.highlight .kr { color: #8045E5 } /* Keyword.Reserved */ +.highlight .kt { color: #7F4707 } /* Keyword.Type */ +.highlight .ld { color: #7F4707 } /* Literal.Date */ +.highlight .m { color: #7F4707 } /* Literal.Number */ +.highlight .s { color: #163 } /* Literal.String */ +.highlight .na { color: #7F4707 } /* Name.Attribute */ +.highlight .nb { color: #7F4707 } /* Name.Builtin */ +.highlight .nc { color: #00749C } /* Name.Class */ +.highlight .no { color: #00749C } /* Name.Constant */ +.highlight .nd { color: #7F4707 } /* Name.Decorator */ +.highlight .ni { color: #163 } /* Name.Entity */ +.highlight .ne { color: #8045E5 } /* Name.Exception */ +.highlight .nf { color: #00749C } /* Name.Function */ +.highlight .nl { color: #7F4707 } /* Name.Label */ +.highlight .nn { color: #1E1E1E } /* Name.Namespace */ +.highlight .nx { color: #1E1E1E } /* Name.Other */ +.highlight .py { color: #00749C } /* Name.Property */ +.highlight .nt { color: #00749C } /* Name.Tag */ +.highlight .nv { color: #D71835 } /* Name.Variable */ +.highlight .ow { color: #8045E5 } /* Operator.Word */ +.highlight .pm { color: #1E1E1E } /* Punctuation.Marker */ +.highlight .w { color: #1E1E1E } /* Text.Whitespace */ +.highlight .mb { color: #7F4707 } /* Literal.Number.Bin */ +.highlight .mf { color: #7F4707 } /* Literal.Number.Float */ +.highlight .mh { color: #7F4707 } /* Literal.Number.Hex */ +.highlight .mi { color: #7F4707 } /* Literal.Number.Integer */ +.highlight .mo { color: #7F4707 } /* Literal.Number.Oct */ +.highlight .sa { color: #163 } /* Literal.String.Affix */ +.highlight .sb { color: #163 } /* Literal.String.Backtick */ +.highlight .sc { color: #163 } /* Literal.String.Char */ +.highlight .dl { color: #163 } /* Literal.String.Delimiter */ +.highlight .sd { color: #163 } /* Literal.String.Doc */ +.highlight .s2 { color: #163 } /* Literal.String.Double */ +.highlight .se { color: #163 } /* Literal.String.Escape */ +.highlight .sh { color: #163 } /* Literal.String.Heredoc */ +.highlight .si { color: #163 } /* Literal.String.Interpol */ +.highlight .sx { color: #163 } /* Literal.String.Other */ +.highlight .sr { color: #D71835 } /* Literal.String.Regex */ +.highlight .s1 { color: #163 } /* Literal.String.Single */ +.highlight .ss { color: #00749C } /* Literal.String.Symbol */ +.highlight .bp { color: #7F4707 } /* Name.Builtin.Pseudo */ +.highlight .fm { color: #00749C } /* Name.Function.Magic */ +.highlight .vc { color: #D71835 } /* Name.Variable.Class */ +.highlight .vg { color: #D71835 } /* Name.Variable.Global */ +.highlight .vi { color: #D71835 } /* Name.Variable.Instance */ +.highlight .vm { color: #7F4707 } /* Name.Variable.Magic */ +.highlight .il { color: #7F4707 } /* Literal.Number.Integer.Long */ +@media not print { +body[data-theme="dark"] .highlight pre { line-height: 125%; } +body[data-theme="dark"] .highlight td.linenos .normal { color: #aaaaaa; background-color: transparent; padding-left: 5px; padding-right: 5px; } +body[data-theme="dark"] .highlight span.linenos { color: #aaaaaa; background-color: transparent; padding-left: 5px; padding-right: 5px; } +body[data-theme="dark"] .highlight td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; } +body[data-theme="dark"] .highlight span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; } +body[data-theme="dark"] .highlight .hll { background-color: #404040 } +body[data-theme="dark"] .highlight { background: #202020; color: #D0D0D0 } +body[data-theme="dark"] .highlight .c { color: #ABABAB; font-style: italic } /* Comment */ +body[data-theme="dark"] .highlight .err { color: #A61717; background-color: #E3D2D2 } /* Error */ +body[data-theme="dark"] .highlight .esc { color: #D0D0D0 } /* Escape */ +body[data-theme="dark"] .highlight .g { color: #D0D0D0 } /* Generic */ +body[data-theme="dark"] .highlight .k { color: #6EBF26; font-weight: bold } /* Keyword */ +body[data-theme="dark"] .highlight .l { color: #D0D0D0 } /* Literal */ +body[data-theme="dark"] .highlight .n { color: #D0D0D0 } /* Name */ +body[data-theme="dark"] .highlight .o { color: #D0D0D0 } /* Operator */ +body[data-theme="dark"] .highlight .x { color: #D0D0D0 } /* Other */ +body[data-theme="dark"] .highlight .p { color: #D0D0D0 } /* Punctuation */ +body[data-theme="dark"] .highlight .ch { color: #ABABAB; font-style: italic } /* Comment.Hashbang */ +body[data-theme="dark"] .highlight .cm { color: #ABABAB; font-style: italic } /* Comment.Multiline */ +body[data-theme="dark"] .highlight .cp { color: #FF3A3A; font-weight: bold } /* Comment.Preproc */ +body[data-theme="dark"] .highlight .cpf { color: #ABABAB; font-style: italic } /* Comment.PreprocFile */ +body[data-theme="dark"] .highlight .c1 { color: #ABABAB; font-style: italic } /* Comment.Single */ +body[data-theme="dark"] .highlight .cs { color: #E50808; font-weight: bold; background-color: #520000 } /* Comment.Special */ +body[data-theme="dark"] .highlight .gd { color: #FF3A3A } /* Generic.Deleted */ +body[data-theme="dark"] .highlight .ge { color: #D0D0D0; font-style: italic } /* Generic.Emph */ +body[data-theme="dark"] .highlight .ges { color: #D0D0D0; font-weight: bold; font-style: italic } /* Generic.EmphStrong */ +body[data-theme="dark"] .highlight .gr { color: #FF3A3A } /* Generic.Error */ +body[data-theme="dark"] .highlight .gh { color: #FFF; font-weight: bold } /* Generic.Heading */ +body[data-theme="dark"] .highlight .gi { color: #589819 } /* Generic.Inserted */ +body[data-theme="dark"] .highlight .go { color: #CCC } /* Generic.Output */ +body[data-theme="dark"] .highlight .gp { color: #AAA } /* Generic.Prompt */ +body[data-theme="dark"] .highlight .gs { color: #D0D0D0; font-weight: bold } /* Generic.Strong */ +body[data-theme="dark"] .highlight .gu { color: #FFF; text-decoration: underline } /* Generic.Subheading */ +body[data-theme="dark"] .highlight .gt { color: #FF3A3A } /* Generic.Traceback */ +body[data-theme="dark"] .highlight .kc { color: #6EBF26; font-weight: bold } /* Keyword.Constant */ +body[data-theme="dark"] .highlight .kd { color: #6EBF26; font-weight: bold } /* Keyword.Declaration */ +body[data-theme="dark"] .highlight .kn { color: #6EBF26; font-weight: bold } /* Keyword.Namespace */ +body[data-theme="dark"] .highlight .kp { color: #6EBF26 } /* Keyword.Pseudo */ +body[data-theme="dark"] .highlight .kr { color: #6EBF26; font-weight: bold } /* Keyword.Reserved */ +body[data-theme="dark"] .highlight .kt { color: #6EBF26; font-weight: bold } /* Keyword.Type */ +body[data-theme="dark"] .highlight .ld { color: #D0D0D0 } /* Literal.Date */ +body[data-theme="dark"] .highlight .m { color: #51B2FD } /* Literal.Number */ +body[data-theme="dark"] .highlight .s { color: #ED9D13 } /* Literal.String */ +body[data-theme="dark"] .highlight .na { color: #BBB } /* Name.Attribute */ +body[data-theme="dark"] .highlight .nb { color: #2FBCCD } /* Name.Builtin */ +body[data-theme="dark"] .highlight .nc { color: #71ADFF; text-decoration: underline } /* Name.Class */ +body[data-theme="dark"] .highlight .no { color: #40FFFF } /* Name.Constant */ +body[data-theme="dark"] .highlight .nd { color: #FFA500 } /* Name.Decorator */ +body[data-theme="dark"] .highlight .ni { color: #D0D0D0 } /* Name.Entity */ +body[data-theme="dark"] .highlight .ne { color: #BBB } /* Name.Exception */ +body[data-theme="dark"] .highlight .nf { color: #71ADFF } /* Name.Function */ +body[data-theme="dark"] .highlight .nl { color: #D0D0D0 } /* Name.Label */ +body[data-theme="dark"] .highlight .nn { color: #71ADFF; text-decoration: underline } /* Name.Namespace */ +body[data-theme="dark"] .highlight .nx { color: #D0D0D0 } /* Name.Other */ +body[data-theme="dark"] .highlight .py { color: #D0D0D0 } /* Name.Property */ +body[data-theme="dark"] .highlight .nt { color: #6EBF26; font-weight: bold } /* Name.Tag */ +body[data-theme="dark"] .highlight .nv { color: #40FFFF } /* Name.Variable */ +body[data-theme="dark"] .highlight .ow { color: #6EBF26; font-weight: bold } /* Operator.Word */ +body[data-theme="dark"] .highlight .pm { color: #D0D0D0 } /* Punctuation.Marker */ +body[data-theme="dark"] .highlight .w { color: #666 } /* Text.Whitespace */ +body[data-theme="dark"] .highlight .mb { color: #51B2FD } /* Literal.Number.Bin */ +body[data-theme="dark"] .highlight .mf { color: #51B2FD } /* Literal.Number.Float */ +body[data-theme="dark"] .highlight .mh { color: #51B2FD } /* Literal.Number.Hex */ +body[data-theme="dark"] .highlight .mi { color: #51B2FD } /* Literal.Number.Integer */ +body[data-theme="dark"] .highlight .mo { color: #51B2FD } /* Literal.Number.Oct */ +body[data-theme="dark"] .highlight .sa { color: #ED9D13 } /* Literal.String.Affix */ +body[data-theme="dark"] .highlight .sb { color: #ED9D13 } /* Literal.String.Backtick */ +body[data-theme="dark"] .highlight .sc { color: #ED9D13 } /* Literal.String.Char */ +body[data-theme="dark"] .highlight .dl { color: #ED9D13 } /* Literal.String.Delimiter */ +body[data-theme="dark"] .highlight .sd { color: #ED9D13 } /* Literal.String.Doc */ +body[data-theme="dark"] .highlight .s2 { color: #ED9D13 } /* Literal.String.Double */ +body[data-theme="dark"] .highlight .se { color: #ED9D13 } /* Literal.String.Escape */ +body[data-theme="dark"] .highlight .sh { color: #ED9D13 } /* Literal.String.Heredoc */ +body[data-theme="dark"] .highlight .si { color: #ED9D13 } /* Literal.String.Interpol */ +body[data-theme="dark"] .highlight .sx { color: #FFA500 } /* Literal.String.Other */ +body[data-theme="dark"] .highlight .sr { color: #ED9D13 } /* Literal.String.Regex */ +body[data-theme="dark"] .highlight .s1 { color: #ED9D13 } /* Literal.String.Single */ +body[data-theme="dark"] .highlight .ss { color: #ED9D13 } /* Literal.String.Symbol */ +body[data-theme="dark"] .highlight .bp { color: #2FBCCD } /* Name.Builtin.Pseudo */ +body[data-theme="dark"] .highlight .fm { color: #71ADFF } /* Name.Function.Magic */ +body[data-theme="dark"] .highlight .vc { color: #40FFFF } /* Name.Variable.Class */ +body[data-theme="dark"] .highlight .vg { color: #40FFFF } /* Name.Variable.Global */ +body[data-theme="dark"] .highlight .vi { color: #40FFFF } /* Name.Variable.Instance */ +body[data-theme="dark"] .highlight .vm { color: #40FFFF } /* Name.Variable.Magic */ +body[data-theme="dark"] .highlight .il { color: #51B2FD } /* Literal.Number.Integer.Long */ +@media (prefers-color-scheme: dark) { +body:not([data-theme="light"]) .highlight pre { line-height: 125%; } +body:not([data-theme="light"]) .highlight td.linenos .normal { color: #aaaaaa; background-color: transparent; padding-left: 5px; padding-right: 5px; } +body:not([data-theme="light"]) .highlight span.linenos { color: #aaaaaa; background-color: transparent; padding-left: 5px; padding-right: 5px; } +body:not([data-theme="light"]) .highlight td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; } +body:not([data-theme="light"]) .highlight span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; } +body:not([data-theme="light"]) .highlight .hll { background-color: #404040 } +body:not([data-theme="light"]) .highlight { background: #202020; color: #D0D0D0 } +body:not([data-theme="light"]) .highlight .c { color: #ABABAB; font-style: italic } /* Comment */ +body:not([data-theme="light"]) .highlight .err { color: #A61717; background-color: #E3D2D2 } /* Error */ +body:not([data-theme="light"]) .highlight .esc { color: #D0D0D0 } /* Escape */ +body:not([data-theme="light"]) .highlight .g { color: #D0D0D0 } /* Generic */ +body:not([data-theme="light"]) .highlight .k { color: #6EBF26; font-weight: bold } /* Keyword */ +body:not([data-theme="light"]) .highlight .l { color: #D0D0D0 } /* Literal */ +body:not([data-theme="light"]) .highlight .n { color: #D0D0D0 } /* Name */ +body:not([data-theme="light"]) .highlight .o { color: #D0D0D0 } /* Operator */ +body:not([data-theme="light"]) .highlight .x { color: #D0D0D0 } /* Other */ +body:not([data-theme="light"]) .highlight .p { color: #D0D0D0 } /* Punctuation */ +body:not([data-theme="light"]) .highlight .ch { color: #ABABAB; font-style: italic } /* Comment.Hashbang */ +body:not([data-theme="light"]) .highlight .cm { color: #ABABAB; font-style: italic } /* Comment.Multiline */ +body:not([data-theme="light"]) .highlight .cp { color: #FF3A3A; font-weight: bold } /* Comment.Preproc */ +body:not([data-theme="light"]) .highlight .cpf { color: #ABABAB; font-style: italic } /* Comment.PreprocFile */ +body:not([data-theme="light"]) .highlight .c1 { color: #ABABAB; font-style: italic } /* Comment.Single */ +body:not([data-theme="light"]) .highlight .cs { color: #E50808; font-weight: bold; background-color: #520000 } /* Comment.Special */ +body:not([data-theme="light"]) .highlight .gd { color: #FF3A3A } /* Generic.Deleted */ +body:not([data-theme="light"]) .highlight .ge { color: #D0D0D0; font-style: italic } /* Generic.Emph */ +body:not([data-theme="light"]) .highlight .ges { color: #D0D0D0; font-weight: bold; font-style: italic } /* Generic.EmphStrong */ +body:not([data-theme="light"]) .highlight .gr { color: #FF3A3A } /* Generic.Error */ +body:not([data-theme="light"]) .highlight .gh { color: #FFF; font-weight: bold } /* Generic.Heading */ +body:not([data-theme="light"]) .highlight .gi { color: #589819 } /* Generic.Inserted */ +body:not([data-theme="light"]) .highlight .go { color: #CCC } /* Generic.Output */ +body:not([data-theme="light"]) .highlight .gp { color: #AAA } /* Generic.Prompt */ +body:not([data-theme="light"]) .highlight .gs { color: #D0D0D0; font-weight: bold } /* Generic.Strong */ +body:not([data-theme="light"]) .highlight .gu { color: #FFF; text-decoration: underline } /* Generic.Subheading */ +body:not([data-theme="light"]) .highlight .gt { color: #FF3A3A } /* Generic.Traceback */ +body:not([data-theme="light"]) .highlight .kc { color: #6EBF26; font-weight: bold } /* Keyword.Constant */ +body:not([data-theme="light"]) .highlight .kd { color: #6EBF26; font-weight: bold } /* Keyword.Declaration */ +body:not([data-theme="light"]) .highlight .kn { color: #6EBF26; font-weight: bold } /* Keyword.Namespace */ +body:not([data-theme="light"]) .highlight .kp { color: #6EBF26 } /* Keyword.Pseudo */ +body:not([data-theme="light"]) .highlight .kr { color: #6EBF26; font-weight: bold } /* Keyword.Reserved */ +body:not([data-theme="light"]) .highlight .kt { color: #6EBF26; font-weight: bold } /* Keyword.Type */ +body:not([data-theme="light"]) .highlight .ld { color: #D0D0D0 } /* Literal.Date */ +body:not([data-theme="light"]) .highlight .m { color: #51B2FD } /* Literal.Number */ +body:not([data-theme="light"]) .highlight .s { color: #ED9D13 } /* Literal.String */ +body:not([data-theme="light"]) .highlight .na { color: #BBB } /* Name.Attribute */ +body:not([data-theme="light"]) .highlight .nb { color: #2FBCCD } /* Name.Builtin */ +body:not([data-theme="light"]) .highlight .nc { color: #71ADFF; text-decoration: underline } /* Name.Class */ +body:not([data-theme="light"]) .highlight .no { color: #40FFFF } /* Name.Constant */ +body:not([data-theme="light"]) .highlight .nd { color: #FFA500 } /* Name.Decorator */ +body:not([data-theme="light"]) .highlight .ni { color: #D0D0D0 } /* Name.Entity */ +body:not([data-theme="light"]) .highlight .ne { color: #BBB } /* Name.Exception */ +body:not([data-theme="light"]) .highlight .nf { color: #71ADFF } /* Name.Function */ +body:not([data-theme="light"]) .highlight .nl { color: #D0D0D0 } /* Name.Label */ +body:not([data-theme="light"]) .highlight .nn { color: #71ADFF; text-decoration: underline } /* Name.Namespace */ +body:not([data-theme="light"]) .highlight .nx { color: #D0D0D0 } /* Name.Other */ +body:not([data-theme="light"]) .highlight .py { color: #D0D0D0 } /* Name.Property */ +body:not([data-theme="light"]) .highlight .nt { color: #6EBF26; font-weight: bold } /* Name.Tag */ +body:not([data-theme="light"]) .highlight .nv { color: #40FFFF } /* Name.Variable */ +body:not([data-theme="light"]) .highlight .ow { color: #6EBF26; font-weight: bold } /* Operator.Word */ +body:not([data-theme="light"]) .highlight .pm { color: #D0D0D0 } /* Punctuation.Marker */ +body:not([data-theme="light"]) .highlight .w { color: #666 } /* Text.Whitespace */ +body:not([data-theme="light"]) .highlight .mb { color: #51B2FD } /* Literal.Number.Bin */ +body:not([data-theme="light"]) .highlight .mf { color: #51B2FD } /* Literal.Number.Float */ +body:not([data-theme="light"]) .highlight .mh { color: #51B2FD } /* Literal.Number.Hex */ +body:not([data-theme="light"]) .highlight .mi { color: #51B2FD } /* Literal.Number.Integer */ +body:not([data-theme="light"]) .highlight .mo { color: #51B2FD } /* Literal.Number.Oct */ +body:not([data-theme="light"]) .highlight .sa { color: #ED9D13 } /* Literal.String.Affix */ +body:not([data-theme="light"]) .highlight .sb { color: #ED9D13 } /* Literal.String.Backtick */ +body:not([data-theme="light"]) .highlight .sc { color: #ED9D13 } /* Literal.String.Char */ +body:not([data-theme="light"]) .highlight .dl { color: #ED9D13 } /* Literal.String.Delimiter */ +body:not([data-theme="light"]) .highlight .sd { color: #ED9D13 } /* Literal.String.Doc */ +body:not([data-theme="light"]) .highlight .s2 { color: #ED9D13 } /* Literal.String.Double */ +body:not([data-theme="light"]) .highlight .se { color: #ED9D13 } /* Literal.String.Escape */ +body:not([data-theme="light"]) .highlight .sh { color: #ED9D13 } /* Literal.String.Heredoc */ +body:not([data-theme="light"]) .highlight .si { color: #ED9D13 } /* Literal.String.Interpol */ +body:not([data-theme="light"]) .highlight .sx { color: #FFA500 } /* Literal.String.Other */ +body:not([data-theme="light"]) .highlight .sr { color: #ED9D13 } /* Literal.String.Regex */ +body:not([data-theme="light"]) .highlight .s1 { color: #ED9D13 } /* Literal.String.Single */ +body:not([data-theme="light"]) .highlight .ss { color: #ED9D13 } /* Literal.String.Symbol */ +body:not([data-theme="light"]) .highlight .bp { color: #2FBCCD } /* Name.Builtin.Pseudo */ +body:not([data-theme="light"]) .highlight .fm { color: #71ADFF } /* Name.Function.Magic */ +body:not([data-theme="light"]) .highlight .vc { color: #40FFFF } /* Name.Variable.Class */ +body:not([data-theme="light"]) .highlight .vg { color: #40FFFF } /* Name.Variable.Global */ +body:not([data-theme="light"]) .highlight .vi { color: #40FFFF } /* Name.Variable.Instance */ +body:not([data-theme="light"]) .highlight .vm { color: #40FFFF } /* Name.Variable.Magic */ +body:not([data-theme="light"]) .highlight .il { color: #51B2FD } /* Literal.Number.Integer.Long */ +} +} \ No newline at end of file diff --git a/docs/_source/_build/html/_static/scripts/furo-extensions.js b/docs/_source/_build/html/_static/scripts/furo-extensions.js new file mode 100644 index 0000000..e69de29 diff --git a/docs/_source/_build/html/_static/scripts/furo.js b/docs/_source/_build/html/_static/scripts/furo.js new file mode 100644 index 0000000..87e1767 --- /dev/null +++ b/docs/_source/_build/html/_static/scripts/furo.js @@ -0,0 +1,3 @@ +/*! For license information please see furo.js.LICENSE.txt */ +(()=>{var t={856:function(t,e,n){var o,r;r=void 0!==n.g?n.g:"undefined"!=typeof window?window:this,o=function(){return function(t){"use strict";var e={navClass:"active",contentClass:"active",nested:!1,nestedClass:"active",offset:0,reflow:!1,events:!0},n=function(t,e,n){if(n.settings.events){var o=new CustomEvent(t,{bubbles:!0,cancelable:!0,detail:n});e.dispatchEvent(o)}},o=function(t){var e=0;if(t.offsetParent)for(;t;)e+=t.offsetTop,t=t.offsetParent;return e>=0?e:0},r=function(t){t&&t.sort(function(t,e){return o(t.content)=Math.max(document.body.scrollHeight,document.documentElement.scrollHeight,document.body.offsetHeight,document.documentElement.offsetHeight,document.body.clientHeight,document.documentElement.clientHeight)},l=function(t,e){var n=t[t.length-1];if(function(t,e){return!(!s()||!c(t.content,e,!0))}(n,e))return n;for(var o=t.length-1;o>=0;o--)if(c(t[o].content,e))return t[o]},a=function(t,e){if(e.nested&&t.parentNode){var n=t.parentNode.closest("li");n&&(n.classList.remove(e.nestedClass),a(n,e))}},i=function(t,e){if(t){var o=t.nav.closest("li");o&&(o.classList.remove(e.navClass),t.content.classList.remove(e.contentClass),a(o,e),n("gumshoeDeactivate",o,{link:t.nav,content:t.content,settings:e}))}},u=function(t,e){if(e.nested){var n=t.parentNode.closest("li");n&&(n.classList.add(e.nestedClass),u(n,e))}};return function(o,c){var s,a,d,f,m,v={setup:function(){s=document.querySelectorAll(o),a=[],Array.prototype.forEach.call(s,function(t){var e=document.getElementById(decodeURIComponent(t.hash.substr(1)));e&&a.push({nav:t,content:e})}),r(a)},detect:function(){var t=l(a,m);t?d&&t.content===d.content||(i(d,m),function(t,e){if(t){var o=t.nav.closest("li");o&&(o.classList.add(e.navClass),t.content.classList.add(e.contentClass),u(o,e),n("gumshoeActivate",o,{link:t.nav,content:t.content,settings:e}))}}(t,m),d=t):d&&(i(d,m),d=null)}},h=function(e){f&&t.cancelAnimationFrame(f),f=t.requestAnimationFrame(v.detect)},g=function(e){f&&t.cancelAnimationFrame(f),f=t.requestAnimationFrame(function(){r(a),v.detect()})};return v.destroy=function(){d&&i(d,m),t.removeEventListener("scroll",h,!1),m.reflow&&t.removeEventListener("resize",g,!1),a=null,s=null,d=null,f=null,m=null},m=function(){var t={};return Array.prototype.forEach.call(arguments,function(e){for(var n in e){if(!e.hasOwnProperty(n))return;t[n]=e[n]}}),t}(e,c||{}),v.setup(),v.detect(),t.addEventListener("scroll",h,!1),m.reflow&&t.addEventListener("resize",g,!1),v}}(r)}.apply(e,[]),void 0===o||(t.exports=o)}},e={};function n(o){var r=e[o];if(void 0!==r)return r.exports;var c=e[o]={exports:{}};return t[o].call(c.exports,c,c.exports,n),c.exports}n.n=t=>{var e=t&&t.__esModule?()=>t.default:()=>t;return n.d(e,{a:e}),e},n.d=(t,e)=>{for(var o in e)n.o(e,o)&&!n.o(t,o)&&Object.defineProperty(t,o,{enumerable:!0,get:e[o]})},n.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(t){if("object"==typeof window)return window}}(),n.o=(t,e)=>Object.prototype.hasOwnProperty.call(t,e),(()=>{"use strict";var t=n(856),e=n.n(t),o=null,r=null,c=document.documentElement.scrollTop;function s(){const t=localStorage.getItem("theme")||"auto";var e;"light"!==(e=window.matchMedia("(prefers-color-scheme: dark)").matches?"auto"===t?"light":"light"==t?"dark":"auto":"auto"===t?"dark":"dark"==t?"light":"auto")&&"dark"!==e&&"auto"!==e&&(console.error(`Got invalid theme mode: ${e}. Resetting to auto.`),e="auto"),document.body.dataset.theme=e,localStorage.setItem("theme",e),console.log(`Changed to ${e} mode.`)}function l(){!function(){const t=document.getElementsByClassName("theme-toggle");Array.from(t).forEach(t=>{t.addEventListener("click",s)})}(),function(){let t=0,e=!1;window.addEventListener("scroll",function(n){t=window.scrollY,e||(window.requestAnimationFrame(function(){var n;(function(t){t>0?r.classList.add("scrolled"):r.classList.remove("scrolled")})(n=t),function(t){t<64?document.documentElement.classList.remove("show-back-to-top"):tc&&document.documentElement.classList.remove("show-back-to-top"),c=t}(n),function(t){null!==o&&(0==t?o.scrollTo(0,0):Math.ceil(t)>=Math.floor(document.documentElement.scrollHeight-window.innerHeight)?o.scrollTo(0,o.scrollHeight):document.querySelector(".scroll-current"))}(n),e=!1}),e=!0)}),window.scroll()}(),null!==o&&new(e())(".toc-tree a",{reflow:!0,recursive:!0,navClass:"scroll-current",offset:()=>{let t=parseFloat(getComputedStyle(document.documentElement).fontSize);const e=r.getBoundingClientRect();return e.top+e.height+2.5*t+1}})}document.addEventListener("DOMContentLoaded",function(){document.body.parentNode.classList.remove("no-js"),r=document.querySelector("header"),o=document.querySelector(".toc-scroll"),l()})})()})(); +//# sourceMappingURL=furo.js.map \ No newline at end of file diff --git a/docs/_source/_build/html/_static/scripts/furo.js.LICENSE.txt b/docs/_source/_build/html/_static/scripts/furo.js.LICENSE.txt new file mode 100644 index 0000000..1632189 --- /dev/null +++ b/docs/_source/_build/html/_static/scripts/furo.js.LICENSE.txt @@ -0,0 +1,7 @@ +/*! + * gumshoejs v5.1.2 (patched by @pradyunsg) + * A simple, framework-agnostic scrollspy script. + * (c) 2019 Chris Ferdinandi + * MIT License + * http://github.com/cferdinandi/gumshoe + */ diff --git a/docs/_source/_build/html/_static/scripts/furo.js.map b/docs/_source/_build/html/_static/scripts/furo.js.map new file mode 100644 index 0000000..3b316f3 --- /dev/null +++ b/docs/_source/_build/html/_static/scripts/furo.js.map @@ -0,0 +1 @@ +{"version":3,"file":"scripts/furo.js","mappings":"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","sources":["webpack:///./src/furo/assets/scripts/gumshoe-patched.js","webpack:///webpack/bootstrap","webpack:///webpack/runtime/compat get default export","webpack:///webpack/runtime/define property getters","webpack:///webpack/runtime/global","webpack:///webpack/runtime/hasOwnProperty shorthand","webpack:///./src/furo/assets/scripts/furo.js"],"sourcesContent":["/*!\n * gumshoejs v5.1.2 (patched by @pradyunsg)\n * A simple, framework-agnostic scrollspy script.\n * (c) 2019 Chris Ferdinandi\n * MIT License\n * http://github.com/cferdinandi/gumshoe\n */\n\n(function (root, factory) {\n if (typeof define === \"function\" && define.amd) {\n define([], function () {\n return factory(root);\n });\n } else if (typeof exports === \"object\") {\n module.exports = factory(root);\n } else {\n root.Gumshoe = factory(root);\n }\n})(\n typeof global !== \"undefined\"\n ? global\n : typeof window !== \"undefined\"\n ? window\n : this,\n function (window) {\n \"use strict\";\n\n //\n // Defaults\n //\n\n var defaults = {\n // Active classes\n navClass: \"active\",\n contentClass: \"active\",\n\n // Nested navigation\n nested: false,\n nestedClass: \"active\",\n\n // Offset & reflow\n offset: 0,\n reflow: false,\n\n // Event support\n events: true,\n };\n\n //\n // Methods\n //\n\n /**\n * Merge two or more objects together.\n * @param {Object} objects The objects to merge together\n * @returns {Object} Merged values of defaults and options\n */\n var extend = function () {\n var merged = {};\n Array.prototype.forEach.call(arguments, function (obj) {\n for (var key in obj) {\n if (!obj.hasOwnProperty(key)) return;\n merged[key] = obj[key];\n }\n });\n return merged;\n };\n\n /**\n * Emit a custom event\n * @param {String} type The event type\n * @param {Node} elem The element to attach the event to\n * @param {Object} detail Any details to pass along with the event\n */\n var emitEvent = function (type, elem, detail) {\n // Make sure events are enabled\n if (!detail.settings.events) return;\n\n // Create a new event\n var event = new CustomEvent(type, {\n bubbles: true,\n cancelable: true,\n detail: detail,\n });\n\n // Dispatch the event\n elem.dispatchEvent(event);\n };\n\n /**\n * Get an element's distance from the top of the Document.\n * @param {Node} elem The element\n * @return {Number} Distance from the top in pixels\n */\n var getOffsetTop = function (elem) {\n var location = 0;\n if (elem.offsetParent) {\n while (elem) {\n location += elem.offsetTop;\n elem = elem.offsetParent;\n }\n }\n return location >= 0 ? location : 0;\n };\n\n /**\n * Sort content from first to last in the DOM\n * @param {Array} contents The content areas\n */\n var sortContents = function (contents) {\n if (contents) {\n contents.sort(function (item1, item2) {\n var offset1 = getOffsetTop(item1.content);\n var offset2 = getOffsetTop(item2.content);\n if (offset1 < offset2) return -1;\n return 1;\n });\n }\n };\n\n /**\n * Get the offset to use for calculating position\n * @param {Object} settings The settings for this instantiation\n * @return {Float} The number of pixels to offset the calculations\n */\n var getOffset = function (settings) {\n // if the offset is a function run it\n if (typeof settings.offset === \"function\") {\n return parseFloat(settings.offset());\n }\n\n // Otherwise, return it as-is\n return parseFloat(settings.offset);\n };\n\n /**\n * Get the document element's height\n * @private\n * @returns {Number}\n */\n var getDocumentHeight = function () {\n return Math.max(\n document.body.scrollHeight,\n document.documentElement.scrollHeight,\n document.body.offsetHeight,\n document.documentElement.offsetHeight,\n document.body.clientHeight,\n document.documentElement.clientHeight,\n );\n };\n\n /**\n * Determine if an element is in view\n * @param {Node} elem The element\n * @param {Object} settings The settings for this instantiation\n * @param {Boolean} bottom If true, check if element is above bottom of viewport instead\n * @return {Boolean} Returns true if element is in the viewport\n */\n var isInView = function (elem, settings, bottom) {\n var bounds = elem.getBoundingClientRect();\n var offset = getOffset(settings);\n if (bottom) {\n return (\n parseInt(bounds.bottom, 10) <\n (window.innerHeight || document.documentElement.clientHeight)\n );\n }\n return parseInt(bounds.top, 10) <= offset;\n };\n\n /**\n * Check if at the bottom of the viewport\n * @return {Boolean} If true, page is at the bottom of the viewport\n */\n var isAtBottom = function () {\n if (\n Math.ceil(window.innerHeight + window.pageYOffset) >=\n getDocumentHeight()\n )\n return true;\n return false;\n };\n\n /**\n * Check if the last item should be used (even if not at the top of the page)\n * @param {Object} item The last item\n * @param {Object} settings The settings for this instantiation\n * @return {Boolean} If true, use the last item\n */\n var useLastItem = function (item, settings) {\n if (isAtBottom() && isInView(item.content, settings, true)) return true;\n return false;\n };\n\n /**\n * Get the active content\n * @param {Array} contents The content areas\n * @param {Object} settings The settings for this instantiation\n * @return {Object} The content area and matching navigation link\n */\n var getActive = function (contents, settings) {\n var last = contents[contents.length - 1];\n if (useLastItem(last, settings)) return last;\n for (var i = contents.length - 1; i >= 0; i--) {\n if (isInView(contents[i].content, settings)) return contents[i];\n }\n };\n\n /**\n * Deactivate parent navs in a nested navigation\n * @param {Node} nav The starting navigation element\n * @param {Object} settings The settings for this instantiation\n */\n var deactivateNested = function (nav, settings) {\n // If nesting isn't activated, bail\n if (!settings.nested || !nav.parentNode) return;\n\n // Get the parent navigation\n var li = nav.parentNode.closest(\"li\");\n if (!li) return;\n\n // Remove the active class\n li.classList.remove(settings.nestedClass);\n\n // Apply recursively to any parent navigation elements\n deactivateNested(li, settings);\n };\n\n /**\n * Deactivate a nav and content area\n * @param {Object} items The nav item and content to deactivate\n * @param {Object} settings The settings for this instantiation\n */\n var deactivate = function (items, settings) {\n // Make sure there are items to deactivate\n if (!items) return;\n\n // Get the parent list item\n var li = items.nav.closest(\"li\");\n if (!li) return;\n\n // Remove the active class from the nav and content\n li.classList.remove(settings.navClass);\n items.content.classList.remove(settings.contentClass);\n\n // Deactivate any parent navs in a nested navigation\n deactivateNested(li, settings);\n\n // Emit a custom event\n emitEvent(\"gumshoeDeactivate\", li, {\n link: items.nav,\n content: items.content,\n settings: settings,\n });\n };\n\n /**\n * Activate parent navs in a nested navigation\n * @param {Node} nav The starting navigation element\n * @param {Object} settings The settings for this instantiation\n */\n var activateNested = function (nav, settings) {\n // If nesting isn't activated, bail\n if (!settings.nested) return;\n\n // Get the parent navigation\n var li = nav.parentNode.closest(\"li\");\n if (!li) return;\n\n // Add the active class\n li.classList.add(settings.nestedClass);\n\n // Apply recursively to any parent navigation elements\n activateNested(li, settings);\n };\n\n /**\n * Activate a nav and content area\n * @param {Object} items The nav item and content to activate\n * @param {Object} settings The settings for this instantiation\n */\n var activate = function (items, settings) {\n // Make sure there are items to activate\n if (!items) return;\n\n // Get the parent list item\n var li = items.nav.closest(\"li\");\n if (!li) return;\n\n // Add the active class to the nav and content\n li.classList.add(settings.navClass);\n items.content.classList.add(settings.contentClass);\n\n // Activate any parent navs in a nested navigation\n activateNested(li, settings);\n\n // Emit a custom event\n emitEvent(\"gumshoeActivate\", li, {\n link: items.nav,\n content: items.content,\n settings: settings,\n });\n };\n\n /**\n * Create the Constructor object\n * @param {String} selector The selector to use for navigation items\n * @param {Object} options User options and settings\n */\n var Constructor = function (selector, options) {\n //\n // Variables\n //\n\n var publicAPIs = {};\n var navItems, contents, current, timeout, settings;\n\n //\n // Methods\n //\n\n /**\n * Set variables from DOM elements\n */\n publicAPIs.setup = function () {\n // Get all nav items\n navItems = document.querySelectorAll(selector);\n\n // Create contents array\n contents = [];\n\n // Loop through each item, get it's matching content, and push to the array\n Array.prototype.forEach.call(navItems, function (item) {\n // Get the content for the nav item\n var content = document.getElementById(\n decodeURIComponent(item.hash.substr(1)),\n );\n if (!content) return;\n\n // Push to the contents array\n contents.push({\n nav: item,\n content: content,\n });\n });\n\n // Sort contents by the order they appear in the DOM\n sortContents(contents);\n };\n\n /**\n * Detect which content is currently active\n */\n publicAPIs.detect = function () {\n // Get the active content\n var active = getActive(contents, settings);\n\n // if there's no active content, deactivate and bail\n if (!active) {\n if (current) {\n deactivate(current, settings);\n current = null;\n }\n return;\n }\n\n // If the active content is the one currently active, do nothing\n if (current && active.content === current.content) return;\n\n // Deactivate the current content and activate the new content\n deactivate(current, settings);\n activate(active, settings);\n\n // Update the currently active content\n current = active;\n };\n\n /**\n * Detect the active content on scroll\n * Debounced for performance\n */\n var scrollHandler = function (event) {\n // If there's a timer, cancel it\n if (timeout) {\n window.cancelAnimationFrame(timeout);\n }\n\n // Setup debounce callback\n timeout = window.requestAnimationFrame(publicAPIs.detect);\n };\n\n /**\n * Update content sorting on resize\n * Debounced for performance\n */\n var resizeHandler = function (event) {\n // If there's a timer, cancel it\n if (timeout) {\n window.cancelAnimationFrame(timeout);\n }\n\n // Setup debounce callback\n timeout = window.requestAnimationFrame(function () {\n sortContents(contents);\n publicAPIs.detect();\n });\n };\n\n /**\n * Destroy the current instantiation\n */\n publicAPIs.destroy = function () {\n // Undo DOM changes\n if (current) {\n deactivate(current, settings);\n }\n\n // Remove event listeners\n window.removeEventListener(\"scroll\", scrollHandler, false);\n if (settings.reflow) {\n window.removeEventListener(\"resize\", resizeHandler, false);\n }\n\n // Reset variables\n contents = null;\n navItems = null;\n current = null;\n timeout = null;\n settings = null;\n };\n\n /**\n * Initialize the current instantiation\n */\n var init = function () {\n // Merge user options into defaults\n settings = extend(defaults, options || {});\n\n // Setup variables based on the current DOM\n publicAPIs.setup();\n\n // Find the currently active content\n publicAPIs.detect();\n\n // Setup event listeners\n window.addEventListener(\"scroll\", scrollHandler, false);\n if (settings.reflow) {\n window.addEventListener(\"resize\", resizeHandler, false);\n }\n };\n\n //\n // Initialize and return the public APIs\n //\n\n init();\n return publicAPIs;\n };\n\n //\n // Return the Constructor\n //\n\n return Constructor;\n },\n);\n","// The module cache\nvar __webpack_module_cache__ = {};\n\n// The require function\nfunction __webpack_require__(moduleId) {\n\t// Check if module is in cache\n\tvar cachedModule = __webpack_module_cache__[moduleId];\n\tif (cachedModule !== undefined) {\n\t\treturn cachedModule.exports;\n\t}\n\t// Create a new module (and put it into the cache)\n\tvar module = __webpack_module_cache__[moduleId] = {\n\t\t// no module.id needed\n\t\t// no module.loaded needed\n\t\texports: {}\n\t};\n\n\t// Execute the module function\n\t__webpack_modules__[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n\t// Return the exports of the module\n\treturn module.exports;\n}\n\n","// getDefaultExport function for compatibility with non-harmony modules\n__webpack_require__.n = (module) => {\n\tvar getter = module && module.__esModule ?\n\t\t() => (module['default']) :\n\t\t() => (module);\n\t__webpack_require__.d(getter, { a: getter });\n\treturn getter;\n};","// define getter functions for harmony exports\n__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n\t\tif(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n\t\t}\n\t}\n};","__webpack_require__.g = (function() {\n\tif (typeof globalThis === 'object') return globalThis;\n\ttry {\n\t\treturn this || new Function('return this')();\n\t} catch (e) {\n\t\tif (typeof window === 'object') return window;\n\t}\n})();","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","import Gumshoe from \"./gumshoe-patched.js\";\n\n////////////////////////////////////////////////////////////////////////////////\n// Scroll Handling\n////////////////////////////////////////////////////////////////////////////////\nvar tocScroll = null;\nvar header = null;\nvar lastScrollTop = document.documentElement.scrollTop;\nconst GO_TO_TOP_OFFSET = 64;\n\nfunction scrollHandlerForHeader(positionY) {\n if (positionY > 0) {\n header.classList.add(\"scrolled\");\n } else {\n header.classList.remove(\"scrolled\");\n }\n}\n\nfunction scrollHandlerForBackToTop(positionY) {\n if (positionY < GO_TO_TOP_OFFSET) {\n document.documentElement.classList.remove(\"show-back-to-top\");\n } else {\n if (positionY < lastScrollTop) {\n document.documentElement.classList.add(\"show-back-to-top\");\n } else if (positionY > lastScrollTop) {\n document.documentElement.classList.remove(\"show-back-to-top\");\n }\n }\n lastScrollTop = positionY;\n}\n\nfunction scrollHandlerForTOC(positionY) {\n if (tocScroll === null) {\n return;\n }\n\n // top of page.\n if (positionY == 0) {\n tocScroll.scrollTo(0, 0);\n } else if (\n // bottom of page.\n Math.ceil(positionY) >=\n Math.floor(document.documentElement.scrollHeight - window.innerHeight)\n ) {\n tocScroll.scrollTo(0, tocScroll.scrollHeight);\n } else {\n // somewhere in the middle.\n const current = document.querySelector(\".scroll-current\");\n if (current == null) {\n return;\n }\n\n // https://github.com/pypa/pip/issues/9159 This breaks scroll behaviours.\n // // scroll the currently \"active\" heading in toc, into view.\n // const rect = current.getBoundingClientRect();\n // if (0 > rect.top) {\n // current.scrollIntoView(true); // the argument is \"alignTop\"\n // } else if (rect.bottom > window.innerHeight) {\n // current.scrollIntoView(false);\n // }\n }\n}\n\nfunction scrollHandler(positionY) {\n scrollHandlerForHeader(positionY);\n scrollHandlerForBackToTop(positionY);\n scrollHandlerForTOC(positionY);\n}\n\n////////////////////////////////////////////////////////////////////////////////\n// Theme Toggle\n////////////////////////////////////////////////////////////////////////////////\nfunction setTheme(mode) {\n if (mode !== \"light\" && mode !== \"dark\" && mode !== \"auto\") {\n console.error(`Got invalid theme mode: ${mode}. Resetting to auto.`);\n mode = \"auto\";\n }\n\n document.body.dataset.theme = mode;\n localStorage.setItem(\"theme\", mode);\n console.log(`Changed to ${mode} mode.`);\n}\n\nfunction cycleThemeOnce() {\n const currentTheme = localStorage.getItem(\"theme\") || \"auto\";\n const prefersDark = window.matchMedia(\"(prefers-color-scheme: dark)\").matches;\n\n if (prefersDark) {\n // Auto (dark) -> Light -> Dark\n if (currentTheme === \"auto\") {\n setTheme(\"light\");\n } else if (currentTheme == \"light\") {\n setTheme(\"dark\");\n } else {\n setTheme(\"auto\");\n }\n } else {\n // Auto (light) -> Dark -> Light\n if (currentTheme === \"auto\") {\n setTheme(\"dark\");\n } else if (currentTheme == \"dark\") {\n setTheme(\"light\");\n } else {\n setTheme(\"auto\");\n }\n }\n}\n\n////////////////////////////////////////////////////////////////////////////////\n// Setup\n////////////////////////////////////////////////////////////////////////////////\nfunction setupScrollHandler() {\n // Taken from https://developer.mozilla.org/en-US/docs/Web/API/Document/scroll_event\n let last_known_scroll_position = 0;\n let ticking = false;\n\n window.addEventListener(\"scroll\", function (e) {\n last_known_scroll_position = window.scrollY;\n\n if (!ticking) {\n window.requestAnimationFrame(function () {\n scrollHandler(last_known_scroll_position);\n ticking = false;\n });\n\n ticking = true;\n }\n });\n window.scroll();\n}\n\nfunction setupScrollSpy() {\n if (tocScroll === null) {\n return;\n }\n\n // Scrollspy -- highlight table on contents, based on scroll\n new Gumshoe(\".toc-tree a\", {\n reflow: true,\n recursive: true,\n navClass: \"scroll-current\",\n offset: () => {\n let rem = parseFloat(getComputedStyle(document.documentElement).fontSize);\n const headerRect = header.getBoundingClientRect();\n return headerRect.top + headerRect.height + 2.5 * rem + 1;\n },\n });\n}\n\nfunction setupTheme() {\n // Attach event handlers for toggling themes\n const buttons = document.getElementsByClassName(\"theme-toggle\");\n Array.from(buttons).forEach((btn) => {\n btn.addEventListener(\"click\", cycleThemeOnce);\n });\n}\n\nfunction setup() {\n setupTheme();\n setupScrollHandler();\n setupScrollSpy();\n}\n\n////////////////////////////////////////////////////////////////////////////////\n// Main entrypoint\n////////////////////////////////////////////////////////////////////////////////\nfunction main() {\n document.body.parentNode.classList.remove(\"no-js\");\n\n header = document.querySelector(\"header\");\n tocScroll = document.querySelector(\".toc-scroll\");\n\n setup();\n}\n\ndocument.addEventListener(\"DOMContentLoaded\", main);\n"],"names":["root","g","window","this","defaults","navClass","contentClass","nested","nestedClass","offset","reflow","events","emitEvent","type","elem","detail","settings","event","CustomEvent","bubbles","cancelable","dispatchEvent","getOffsetTop","location","offsetParent","offsetTop","sortContents","contents","sort","item1","item2","content","isInView","bottom","bounds","getBoundingClientRect","parseFloat","getOffset","parseInt","innerHeight","document","documentElement","clientHeight","top","isAtBottom","Math","ceil","pageYOffset","max","body","scrollHeight","offsetHeight","getActive","last","length","item","useLastItem","i","deactivateNested","nav","parentNode","li","closest","classList","remove","deactivate","items","link","activateNested","add","selector","options","navItems","current","timeout","publicAPIs","querySelectorAll","Array","prototype","forEach","call","getElementById","decodeURIComponent","hash","substr","push","active","activate","scrollHandler","cancelAnimationFrame","requestAnimationFrame","detect","resizeHandler","destroy","removeEventListener","merged","arguments","obj","key","hasOwnProperty","extend","setup","addEventListener","factory","__webpack_module_cache__","__webpack_require__","moduleId","cachedModule","undefined","exports","module","__webpack_modules__","n","getter","__esModule","d","a","definition","o","Object","defineProperty","enumerable","get","globalThis","Function","e","prop","tocScroll","header","lastScrollTop","scrollTop","cycleThemeOnce","currentTheme","localStorage","getItem","mode","matchMedia","matches","console","error","dataset","theme","setItem","log","buttons","getElementsByClassName","from","btn","setupTheme","last_known_scroll_position","ticking","scrollY","positionY","scrollHandlerForHeader","scrollHandlerForBackToTop","scrollTo","floor","querySelector","scrollHandlerForTOC","scroll","setupScrollHandler","recursive","rem","getComputedStyle","fontSize","headerRect","height"],"sourceRoot":""} \ No newline at end of file diff --git a/docs/_source/_build/html/_static/searchtools.js b/docs/_source/_build/html/_static/searchtools.js new file mode 100644 index 0000000..e29b1c7 --- /dev/null +++ b/docs/_source/_build/html/_static/searchtools.js @@ -0,0 +1,693 @@ +/* + * Sphinx JavaScript utilities for the full-text search. + */ +"use strict"; + +/** + * Simple result scoring code. + */ +if (typeof Scorer === "undefined") { + var Scorer = { + // Implement the following function to further tweak the score for each result + // The function takes a result array [docname, title, anchor, descr, score, filename] + // and returns the new score. + /* + score: result => { + const [docname, title, anchor, descr, score, filename, kind] = result + return score + }, + */ + + // query matches the full name of an object + objNameMatch: 11, + // or matches in the last dotted part of the object name + objPartialMatch: 6, + // Additive scores depending on the priority of the object + objPrio: { + 0: 15, // used to be importantResults + 1: 5, // used to be objectResults + 2: -5, // used to be unimportantResults + }, + // Used when the priority is not in the mapping. + objPrioDefault: 0, + + // query found in title + title: 15, + partialTitle: 7, + // query found in terms + term: 5, + partialTerm: 2, + }; +} + +// Global search result kind enum, used by themes to style search results. +// prettier-ignore +class SearchResultKind { + static get index() { return "index"; } + static get object() { return "object"; } + static get text() { return "text"; } + static get title() { return "title"; } +} + +const _removeChildren = (element) => { + while (element && element.lastChild) element.removeChild(element.lastChild); +}; + +/** + * See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions#escaping + */ +const _escapeRegExp = (string) => + string.replace(/[.*+\-?^${}()|[\]\\]/g, "\\$&"); // $& means the whole matched string + +const _escapeHTML = (text) => { + return text + .replaceAll("&", "&") + .replaceAll("<", "<") + .replaceAll(">", ">") + .replaceAll('"', """) + .replaceAll("'", "'"); +}; + +const _displayItem = (item, searchTerms, highlightTerms) => { + const docBuilder = DOCUMENTATION_OPTIONS.BUILDER; + const docFileSuffix = DOCUMENTATION_OPTIONS.FILE_SUFFIX; + const docLinkSuffix = DOCUMENTATION_OPTIONS.LINK_SUFFIX; + const showSearchSummary = DOCUMENTATION_OPTIONS.SHOW_SEARCH_SUMMARY; + const contentRoot = document.documentElement.dataset.content_root; + + const [docName, title, anchor, descr, score, _filename, kind] = item; + + let listItem = document.createElement("li"); + // Add a class representing the item's type: + // can be used by a theme's CSS selector for styling + // See SearchResultKind for the class names. + listItem.classList.add(`kind-${kind}`); + let requestUrl; + let linkUrl; + if (docBuilder === "dirhtml") { + // dirhtml builder + let dirname = docName + "/"; + if (dirname.match(/\/index\/$/)) + dirname = dirname.substring(0, dirname.length - 6); + else if (dirname === "index/") dirname = ""; + requestUrl = contentRoot + dirname; + linkUrl = requestUrl; + } else { + // normal html builders + requestUrl = contentRoot + docName + docFileSuffix; + linkUrl = docName + docLinkSuffix; + } + let linkEl = listItem.appendChild(document.createElement("a")); + linkEl.href = linkUrl + anchor; + linkEl.dataset.score = score; + linkEl.innerHTML = _escapeHTML(title); + if (descr) { + listItem.appendChild(document.createElement("span")).innerHTML = + ` (${_escapeHTML(descr)})`; + // highlight search terms in the description + if (SPHINX_HIGHLIGHT_ENABLED) + // SPHINX_HIGHLIGHT_ENABLED is set in sphinx_highlight.js + highlightTerms.forEach((term) => + _highlightText(listItem, term, "highlighted"), + ); + } else if (showSearchSummary) + fetch(requestUrl) + .then((responseData) => responseData.text()) + .then((data) => { + if (data) + listItem.appendChild( + Search.makeSearchSummary(data, searchTerms, anchor), + ); + // highlight search terms in the summary + if (SPHINX_HIGHLIGHT_ENABLED) + // SPHINX_HIGHLIGHT_ENABLED is set in sphinx_highlight.js + highlightTerms.forEach((term) => + _highlightText(listItem, term, "highlighted"), + ); + }); + Search.output.appendChild(listItem); +}; +const _finishSearch = (resultCount) => { + Search.stopPulse(); + Search.title.innerText = _("Search Results"); + if (!resultCount) + Search.status.innerText = Documentation.gettext( + "Your search did not match any documents. Please make sure that all words are spelled correctly and that you've selected enough categories.", + ); + else + Search.status.innerText = Documentation.ngettext( + "Search finished, found one page matching the search query.", + "Search finished, found ${resultCount} pages matching the search query.", + resultCount, + ).replace("${resultCount}", resultCount); +}; +const _displayNextItem = ( + results, + resultCount, + searchTerms, + highlightTerms, +) => { + // results left, load the summary and display it + // this is intended to be dynamic (don't sub resultsCount) + if (results.length) { + _displayItem(results.pop(), searchTerms, highlightTerms); + setTimeout( + () => _displayNextItem(results, resultCount, searchTerms, highlightTerms), + 5, + ); + } + // search finished, update title and status message + else _finishSearch(resultCount); +}; +// Helper function used by query() to order search results. +// Each input is an array of [docname, title, anchor, descr, score, filename, kind]. +// Order the results by score (in opposite order of appearance, since the +// `_displayNextItem` function uses pop() to retrieve items) and then alphabetically. +const _orderResultsByScoreThenName = (a, b) => { + const leftScore = a[4]; + const rightScore = b[4]; + if (leftScore === rightScore) { + // same score: sort alphabetically + const leftTitle = a[1].toLowerCase(); + const rightTitle = b[1].toLowerCase(); + if (leftTitle === rightTitle) return 0; + return leftTitle > rightTitle ? -1 : 1; // inverted is intentional + } + return leftScore > rightScore ? 1 : -1; +}; + +/** + * Default splitQuery function. Can be overridden in ``sphinx.search`` with a + * custom function per language. + * + * The regular expression works by splitting the string on consecutive characters + * that are not Unicode letters, numbers, underscores, or emoji characters. + * This is the same as ``\W+`` in Python, preserving the surrogate pair area. + */ +if (typeof splitQuery === "undefined") { + var splitQuery = (query) => + query + .split(/[^\p{Letter}\p{Number}_\p{Emoji_Presentation}]+/gu) + .filter((term) => term); // remove remaining empty strings +} + +/** + * Search Module + */ +const Search = { + _index: null, + _queued_query: null, + _pulse_status: -1, + + htmlToText: (htmlString, anchor) => { + const htmlElement = new DOMParser().parseFromString( + htmlString, + "text/html", + ); + for (const removalQuery of [".headerlink", "script", "style"]) { + htmlElement.querySelectorAll(removalQuery).forEach((el) => { + el.remove(); + }); + } + if (anchor) { + const anchorContent = htmlElement.querySelector( + `[role="main"] ${anchor}`, + ); + if (anchorContent) return anchorContent.textContent; + + console.warn( + `Anchored content block not found. Sphinx search tries to obtain it via DOM query '[role=main] ${anchor}'. Check your theme or template.`, + ); + } + + // if anchor not specified or not found, fall back to main content + const docContent = htmlElement.querySelector('[role="main"]'); + if (docContent) return docContent.textContent; + + console.warn( + "Content block not found. Sphinx search tries to obtain it via DOM query '[role=main]'. Check your theme or template.", + ); + return ""; + }, + + init: () => { + const query = new URLSearchParams(window.location.search).get("q"); + document + .querySelectorAll('input[name="q"]') + .forEach((el) => (el.value = query)); + if (query) Search.performSearch(query); + }, + + loadIndex: (url) => + (document.body.appendChild(document.createElement("script")).src = url), + + setIndex: (index) => { + Search._index = index; + if (Search._queued_query !== null) { + const query = Search._queued_query; + Search._queued_query = null; + Search.query(query); + } + }, + + hasIndex: () => Search._index !== null, + + deferQuery: (query) => (Search._queued_query = query), + + stopPulse: () => (Search._pulse_status = -1), + + startPulse: () => { + if (Search._pulse_status >= 0) return; + + const pulse = () => { + Search._pulse_status = (Search._pulse_status + 1) % 4; + Search.dots.innerText = ".".repeat(Search._pulse_status); + if (Search._pulse_status >= 0) window.setTimeout(pulse, 500); + }; + pulse(); + }, + + /** + * perform a search for something (or wait until index is loaded) + */ + performSearch: (query) => { + // create the required interface elements + const searchText = document.createElement("h2"); + searchText.textContent = _("Searching"); + const searchSummary = document.createElement("p"); + searchSummary.classList.add("search-summary"); + searchSummary.innerText = ""; + const searchList = document.createElement("ul"); + searchList.setAttribute("role", "list"); + searchList.classList.add("search"); + + const out = document.getElementById("search-results"); + Search.title = out.appendChild(searchText); + Search.dots = Search.title.appendChild(document.createElement("span")); + Search.status = out.appendChild(searchSummary); + Search.output = out.appendChild(searchList); + + const searchProgress = document.getElementById("search-progress"); + // Some themes don't use the search progress node + if (searchProgress) { + searchProgress.innerText = _("Preparing search..."); + } + Search.startPulse(); + + // index already loaded, the browser was quick! + if (Search.hasIndex()) Search.query(query); + else Search.deferQuery(query); + }, + + _parseQuery: (query) => { + // stem the search terms and add them to the correct list + const stemmer = new Stemmer(); + const searchTerms = new Set(); + const excludedTerms = new Set(); + const highlightTerms = new Set(); + const objectTerms = new Set(splitQuery(query.toLowerCase().trim())); + splitQuery(query.trim()).forEach((queryTerm) => { + const queryTermLower = queryTerm.toLowerCase(); + + // maybe skip this "word" + // stopwords set is from language_data.js + if (stopwords.has(queryTermLower) || queryTerm.match(/^\d+$/)) return; + + // stem the word + let word = stemmer.stemWord(queryTermLower); + // select the correct list + if (word[0] === "-") excludedTerms.add(word.substr(1)); + else { + searchTerms.add(word); + highlightTerms.add(queryTermLower); + } + }); + + if (SPHINX_HIGHLIGHT_ENABLED) { + // SPHINX_HIGHLIGHT_ENABLED is set in sphinx_highlight.js + localStorage.setItem( + "sphinx_highlight_terms", + [...highlightTerms].join(" "), + ); + } + + // console.debug("SEARCH: searching for:"); + // console.info("required: ", [...searchTerms]); + // console.info("excluded: ", [...excludedTerms]); + + return [query, searchTerms, excludedTerms, highlightTerms, objectTerms]; + }, + + /** + * execute search (requires search index to be loaded) + */ + _performSearch: ( + query, + searchTerms, + excludedTerms, + highlightTerms, + objectTerms, + ) => { + const filenames = Search._index.filenames; + const docNames = Search._index.docnames; + const titles = Search._index.titles; + const allTitles = Search._index.alltitles; + const indexEntries = Search._index.indexentries; + + // Collect multiple result groups to be sorted separately and then ordered. + // Each is an array of [docname, title, anchor, descr, score, filename, kind]. + const normalResults = []; + const nonMainIndexResults = []; + + _removeChildren(document.getElementById("search-progress")); + + const queryLower = query.toLowerCase().trim(); + for (const [title, foundTitles] of Object.entries(allTitles)) { + if ( + title.toLowerCase().trim().includes(queryLower) + && queryLower.length >= title.length / 2 + ) { + for (const [file, id] of foundTitles) { + const score = Math.round( + (Scorer.title * queryLower.length) / title.length, + ); + const boost = titles[file] === title ? 1 : 0; // add a boost for document titles + normalResults.push([ + docNames[file], + titles[file] !== title ? `${titles[file]} > ${title}` : title, + id !== null ? "#" + id : "", + null, + score + boost, + filenames[file], + SearchResultKind.title, + ]); + } + } + } + + // search for explicit entries in index directives + for (const [entry, foundEntries] of Object.entries(indexEntries)) { + if (entry.includes(queryLower) && queryLower.length >= entry.length / 2) { + for (const [file, id, isMain] of foundEntries) { + const score = Math.round((100 * queryLower.length) / entry.length); + const result = [ + docNames[file], + titles[file], + id ? "#" + id : "", + null, + score, + filenames[file], + SearchResultKind.index, + ]; + if (isMain) { + normalResults.push(result); + } else { + nonMainIndexResults.push(result); + } + } + } + } + + // lookup as object + objectTerms.forEach((term) => + normalResults.push(...Search.performObjectSearch(term, objectTerms)), + ); + + // lookup as search terms in fulltext + normalResults.push( + ...Search.performTermsSearch(searchTerms, excludedTerms), + ); + + // let the scorer override scores with a custom scoring function + if (Scorer.score) { + normalResults.forEach((item) => (item[4] = Scorer.score(item))); + nonMainIndexResults.forEach((item) => (item[4] = Scorer.score(item))); + } + + // Sort each group of results by score and then alphabetically by name. + normalResults.sort(_orderResultsByScoreThenName); + nonMainIndexResults.sort(_orderResultsByScoreThenName); + + // Combine the result groups in (reverse) order. + // Non-main index entries are typically arbitrary cross-references, + // so display them after other results. + let results = [...nonMainIndexResults, ...normalResults]; + + // remove duplicate search results + // note the reversing of results, so that in the case of duplicates, the highest-scoring entry is kept + let seen = new Set(); + results = results.reverse().reduce((acc, result) => { + let resultStr = result + .slice(0, 4) + .concat([result[5]]) + .map((v) => String(v)) + .join(","); + if (!seen.has(resultStr)) { + acc.push(result); + seen.add(resultStr); + } + return acc; + }, []); + + return results.reverse(); + }, + + query: (query) => { + const [ + searchQuery, + searchTerms, + excludedTerms, + highlightTerms, + objectTerms, + ] = Search._parseQuery(query); + const results = Search._performSearch( + searchQuery, + searchTerms, + excludedTerms, + highlightTerms, + objectTerms, + ); + + // for debugging + //Search.lastresults = results.slice(); // a copy + // console.info("search results:", Search.lastresults); + + // print the results + _displayNextItem(results, results.length, searchTerms, highlightTerms); + }, + + /** + * search for object names + */ + performObjectSearch: (object, objectTerms) => { + const filenames = Search._index.filenames; + const docNames = Search._index.docnames; + const objects = Search._index.objects; + const objNames = Search._index.objnames; + const titles = Search._index.titles; + + const results = []; + + const objectSearchCallback = (prefix, match) => { + const name = match[4]; + const fullname = (prefix ? prefix + "." : "") + name; + const fullnameLower = fullname.toLowerCase(); + if (fullnameLower.indexOf(object) < 0) return; + + let score = 0; + const parts = fullnameLower.split("."); + + // check for different match types: exact matches of full name or + // "last name" (i.e. last dotted part) + if (fullnameLower === object || parts.slice(-1)[0] === object) + score += Scorer.objNameMatch; + else if (parts.slice(-1)[0].indexOf(object) > -1) + score += Scorer.objPartialMatch; // matches in last name + + const objName = objNames[match[1]][2]; + const title = titles[match[0]]; + + // If more than one term searched for, we require other words to be + // found in the name/title/description + const otherTerms = new Set(objectTerms); + otherTerms.delete(object); + if (otherTerms.size > 0) { + const haystack = `${prefix} ${name} ${objName} ${title}`.toLowerCase(); + if ( + [...otherTerms].some((otherTerm) => haystack.indexOf(otherTerm) < 0) + ) + return; + } + + let anchor = match[3]; + if (anchor === "") anchor = fullname; + else if (anchor === "-") anchor = objNames[match[1]][1] + "-" + fullname; + + const descr = objName + _(", in ") + title; + + // add custom score for some objects according to scorer + if (Scorer.objPrio.hasOwnProperty(match[2])) + score += Scorer.objPrio[match[2]]; + else score += Scorer.objPrioDefault; + + results.push([ + docNames[match[0]], + fullname, + "#" + anchor, + descr, + score, + filenames[match[0]], + SearchResultKind.object, + ]); + }; + Object.keys(objects).forEach((prefix) => + objects[prefix].forEach((array) => objectSearchCallback(prefix, array)), + ); + return results; + }, + + /** + * search for full-text terms in the index + */ + performTermsSearch: (searchTerms, excludedTerms) => { + // prepare search + const terms = Search._index.terms; + const titleTerms = Search._index.titleterms; + const filenames = Search._index.filenames; + const docNames = Search._index.docnames; + const titles = Search._index.titles; + + const scoreMap = new Map(); + const fileMap = new Map(); + + // perform the search on the required terms + searchTerms.forEach((word) => { + const files = []; + // find documents, if any, containing the query word in their text/title term indices + // use Object.hasOwnProperty to avoid mismatching against prototype properties + const arr = [ + { + files: terms.hasOwnProperty(word) ? terms[word] : undefined, + score: Scorer.term, + }, + { + files: titleTerms.hasOwnProperty(word) ? titleTerms[word] : undefined, + score: Scorer.title, + }, + ]; + // add support for partial matches + if (word.length > 2) { + const escapedWord = _escapeRegExp(word); + if (!terms.hasOwnProperty(word)) { + Object.keys(terms).forEach((term) => { + if (term.match(escapedWord)) + arr.push({ files: terms[term], score: Scorer.partialTerm }); + }); + } + if (!titleTerms.hasOwnProperty(word)) { + Object.keys(titleTerms).forEach((term) => { + if (term.match(escapedWord)) + arr.push({ files: titleTerms[term], score: Scorer.partialTitle }); + }); + } + } + + // no match but word was a required one + if (arr.every((record) => record.files === undefined)) return; + + // found search word in contents + arr.forEach((record) => { + if (record.files === undefined) return; + + let recordFiles = record.files; + if (recordFiles.length === undefined) recordFiles = [recordFiles]; + files.push(...recordFiles); + + // set score for the word in each file + recordFiles.forEach((file) => { + if (!scoreMap.has(file)) scoreMap.set(file, new Map()); + const fileScores = scoreMap.get(file); + fileScores.set(word, record.score); + }); + }); + + // create the mapping + files.forEach((file) => { + if (!fileMap.has(file)) fileMap.set(file, [word]); + else if (fileMap.get(file).indexOf(word) === -1) + fileMap.get(file).push(word); + }); + }); + + // now check if the files don't contain excluded terms + const results = []; + for (const [file, wordList] of fileMap) { + // check if all requirements are matched + + // as search terms with length < 3 are discarded + const filteredTermCount = [...searchTerms].filter( + (term) => term.length > 2, + ).length; + if ( + wordList.length !== searchTerms.size + && wordList.length !== filteredTermCount + ) + continue; + + // ensure that none of the excluded terms is in the search result + if ( + [...excludedTerms].some( + (term) => + terms[term] === file + || titleTerms[term] === file + || (terms[term] || []).includes(file) + || (titleTerms[term] || []).includes(file), + ) + ) + break; + + // select one (max) score for the file. + const score = Math.max(...wordList.map((w) => scoreMap.get(file).get(w))); + // add result to the result list + results.push([ + docNames[file], + titles[file], + "", + null, + score, + filenames[file], + SearchResultKind.text, + ]); + } + return results; + }, + + /** + * helper function to return a node containing the + * search summary for a given text. keywords is a list + * of stemmed words. + */ + makeSearchSummary: (htmlText, keywords, anchor) => { + const text = Search.htmlToText(htmlText, anchor); + if (text === "") return null; + + const textLower = text.toLowerCase(); + const actualStartPosition = [...keywords] + .map((k) => textLower.indexOf(k.toLowerCase())) + .filter((i) => i > -1) + .slice(-1)[0]; + const startWithContext = Math.max(actualStartPosition - 120, 0); + + const top = startWithContext === 0 ? "" : "..."; + const tail = startWithContext + 240 < text.length ? "..." : ""; + + let summary = document.createElement("p"); + summary.classList.add("context"); + summary.textContent = + top + text.substr(startWithContext, 240).trim() + tail; + + return summary; + }, +}; + +_ready(Search.init); diff --git a/docs/_source/_build/html/_static/skeleton.css b/docs/_source/_build/html/_static/skeleton.css new file mode 100644 index 0000000..467c878 --- /dev/null +++ b/docs/_source/_build/html/_static/skeleton.css @@ -0,0 +1,296 @@ +/* Some sane resets. */ +html { + height: 100%; +} + +body { + margin: 0; + min-height: 100%; +} + +/* All the flexbox magic! */ +body, +.sb-announcement, +.sb-content, +.sb-main, +.sb-container, +.sb-container__inner, +.sb-article-container, +.sb-footer-content, +.sb-header, +.sb-header-secondary, +.sb-footer { + display: flex; +} + +/* These order things vertically */ +body, +.sb-main, +.sb-article-container { + flex-direction: column; +} + +/* Put elements in the center */ +.sb-header, +.sb-header-secondary, +.sb-container, +.sb-content, +.sb-footer, +.sb-footer-content { + justify-content: center; +} +/* Put elements at the ends */ +.sb-article-container { + justify-content: space-between; +} + +/* These elements grow. */ +.sb-main, +.sb-content, +.sb-container, +article { + flex-grow: 1; +} + +/* Because padding making this wider is not fun */ +article { + box-sizing: border-box; +} + +/* The announcements element should never be wider than the page. */ +.sb-announcement { + max-width: 100%; +} + +.sb-sidebar-primary, +.sb-sidebar-secondary { + flex-shrink: 0; + width: 17rem; +} + +.sb-announcement__inner { + justify-content: center; + + box-sizing: border-box; + height: 3rem; + + overflow-x: auto; + white-space: nowrap; +} + +/* Sidebars, with checkbox-based toggle */ +.sb-sidebar-primary, +.sb-sidebar-secondary { + position: fixed; + height: 100%; + top: 0; +} + +.sb-sidebar-primary { + left: -17rem; + transition: left 250ms ease-in-out; +} +.sb-sidebar-secondary { + right: -17rem; + transition: right 250ms ease-in-out; +} + +.sb-sidebar-toggle { + display: none; +} +.sb-sidebar-overlay { + position: fixed; + top: 0; + width: 0; + height: 0; + + transition: width 0ms ease 250ms, height 0ms ease 250ms, opacity 250ms ease; + + opacity: 0; + background-color: rgba(0, 0, 0, 0.54); +} + +#sb-sidebar-toggle--primary:checked + ~ .sb-sidebar-overlay[for="sb-sidebar-toggle--primary"], +#sb-sidebar-toggle--secondary:checked + ~ .sb-sidebar-overlay[for="sb-sidebar-toggle--secondary"] { + width: 100%; + height: 100%; + opacity: 1; + transition: width 0ms ease, height 0ms ease, opacity 250ms ease; +} + +#sb-sidebar-toggle--primary:checked ~ .sb-container .sb-sidebar-primary { + left: 0; +} +#sb-sidebar-toggle--secondary:checked ~ .sb-container .sb-sidebar-secondary { + right: 0; +} + +/* Full-width mode */ +.drop-secondary-sidebar-for-full-width-content + .hide-when-secondary-sidebar-shown { + display: none !important; +} +.drop-secondary-sidebar-for-full-width-content .sb-sidebar-secondary { + display: none !important; +} + +/* Mobile views */ +.sb-page-width { + width: 100%; +} + +.sb-article-container, +.sb-footer-content__inner, +.drop-secondary-sidebar-for-full-width-content .sb-article, +.drop-secondary-sidebar-for-full-width-content .match-content-width { + width: 100vw; +} + +.sb-article, +.match-content-width { + padding: 0 1rem; + box-sizing: border-box; +} + +@media (min-width: 32rem) { + .sb-article, + .match-content-width { + padding: 0 2rem; + } +} + +/* Tablet views */ +@media (min-width: 42rem) { + .sb-article-container { + width: auto; + } + .sb-footer-content__inner, + .drop-secondary-sidebar-for-full-width-content .sb-article, + .drop-secondary-sidebar-for-full-width-content .match-content-width { + width: 42rem; + } + .sb-article, + .match-content-width { + width: 42rem; + } +} +@media (min-width: 46rem) { + .sb-footer-content__inner, + .drop-secondary-sidebar-for-full-width-content .sb-article, + .drop-secondary-sidebar-for-full-width-content .match-content-width { + width: 46rem; + } + .sb-article, + .match-content-width { + width: 46rem; + } +} +@media (min-width: 50rem) { + .sb-footer-content__inner, + .drop-secondary-sidebar-for-full-width-content .sb-article, + .drop-secondary-sidebar-for-full-width-content .match-content-width { + width: 50rem; + } + .sb-article, + .match-content-width { + width: 50rem; + } +} + +/* Tablet views */ +@media (min-width: 59rem) { + .sb-sidebar-secondary { + position: static; + } + .hide-when-secondary-sidebar-shown { + display: none !important; + } + .sb-footer-content__inner, + .drop-secondary-sidebar-for-full-width-content .sb-article, + .drop-secondary-sidebar-for-full-width-content .match-content-width { + width: 59rem; + } + .sb-article, + .match-content-width { + width: 42rem; + } +} +@media (min-width: 63rem) { + .sb-footer-content__inner, + .drop-secondary-sidebar-for-full-width-content .sb-article, + .drop-secondary-sidebar-for-full-width-content .match-content-width { + width: 63rem; + } + .sb-article, + .match-content-width { + width: 46rem; + } +} +@media (min-width: 67rem) { + .sb-footer-content__inner, + .drop-secondary-sidebar-for-full-width-content .sb-article, + .drop-secondary-sidebar-for-full-width-content .match-content-width { + width: 67rem; + } + .sb-article, + .match-content-width { + width: 50rem; + } +} + +/* Desktop views */ +@media (min-width: 76rem) { + .sb-sidebar-primary { + position: static; + } + .hide-when-primary-sidebar-shown { + display: none !important; + } + .sb-footer-content__inner, + .drop-secondary-sidebar-for-full-width-content .sb-article, + .drop-secondary-sidebar-for-full-width-content .match-content-width { + width: 59rem; + } + .sb-article, + .match-content-width { + width: 42rem; + } +} + +/* Full desktop views */ +@media (min-width: 80rem) { + .sb-article, + .match-content-width { + width: 46rem; + } + .sb-footer-content__inner, + .drop-secondary-sidebar-for-full-width-content .sb-article, + .drop-secondary-sidebar-for-full-width-content .match-content-width { + width: 63rem; + } +} + +@media (min-width: 84rem) { + .sb-article, + .match-content-width { + width: 50rem; + } + .sb-footer-content__inner, + .drop-secondary-sidebar-for-full-width-content .sb-article, + .drop-secondary-sidebar-for-full-width-content .match-content-width { + width: 67rem; + } +} + +@media (min-width: 88rem) { + .sb-footer-content__inner, + .drop-secondary-sidebar-for-full-width-content .sb-article, + .drop-secondary-sidebar-for-full-width-content .match-content-width { + width: 67rem; + } + .sb-page-width { + width: 88rem; + } +} diff --git a/docs/_source/_build/html/_static/sphinx_highlight.js b/docs/_source/_build/html/_static/sphinx_highlight.js new file mode 100644 index 0000000..a74e103 --- /dev/null +++ b/docs/_source/_build/html/_static/sphinx_highlight.js @@ -0,0 +1,159 @@ +/* Highlighting utilities for Sphinx HTML documentation. */ +"use strict"; + +const SPHINX_HIGHLIGHT_ENABLED = true; + +/** + * highlight a given string on a node by wrapping it in + * span elements with the given class name. + */ +const _highlight = (node, addItems, text, className) => { + if (node.nodeType === Node.TEXT_NODE) { + const val = node.nodeValue; + const parent = node.parentNode; + const pos = val.toLowerCase().indexOf(text); + if ( + pos >= 0 + && !parent.classList.contains(className) + && !parent.classList.contains("nohighlight") + ) { + let span; + + const closestNode = parent.closest("body, svg, foreignObject"); + const isInSVG = closestNode && closestNode.matches("svg"); + if (isInSVG) { + span = document.createElementNS("http://www.w3.org/2000/svg", "tspan"); + } else { + span = document.createElement("span"); + span.classList.add(className); + } + + span.appendChild(document.createTextNode(val.substr(pos, text.length))); + const rest = document.createTextNode(val.substr(pos + text.length)); + parent.insertBefore(span, parent.insertBefore(rest, node.nextSibling)); + node.nodeValue = val.substr(0, pos); + /* There may be more occurrences of search term in this node. So call this + * function recursively on the remaining fragment. + */ + _highlight(rest, addItems, text, className); + + if (isInSVG) { + const rect = document.createElementNS( + "http://www.w3.org/2000/svg", + "rect", + ); + const bbox = parent.getBBox(); + rect.x.baseVal.value = bbox.x; + rect.y.baseVal.value = bbox.y; + rect.width.baseVal.value = bbox.width; + rect.height.baseVal.value = bbox.height; + rect.setAttribute("class", className); + addItems.push({ parent: parent, target: rect }); + } + } + } else if (node.matches && !node.matches("button, select, textarea")) { + node.childNodes.forEach((el) => _highlight(el, addItems, text, className)); + } +}; +const _highlightText = (thisNode, text, className) => { + let addItems = []; + _highlight(thisNode, addItems, text, className); + addItems.forEach((obj) => + obj.parent.insertAdjacentElement("beforebegin", obj.target), + ); +}; + +/** + * Small JavaScript module for the documentation. + */ +const SphinxHighlight = { + /** + * highlight the search words provided in localstorage in the text + */ + highlightSearchWords: () => { + if (!SPHINX_HIGHLIGHT_ENABLED) return; // bail if no highlight + + // get and clear terms from localstorage + const url = new URL(window.location); + const highlight = + localStorage.getItem("sphinx_highlight_terms") + || url.searchParams.get("highlight") + || ""; + localStorage.removeItem("sphinx_highlight_terms"); + // Update history only if '?highlight' is present; otherwise it + // clears text fragments (not set in window.location by the browser) + if (url.searchParams.has("highlight")) { + url.searchParams.delete("highlight"); + window.history.replaceState({}, "", url); + } + + // get individual terms from highlight string + const terms = highlight + .toLowerCase() + .split(/\s+/) + .filter((x) => x); + if (terms.length === 0) return; // nothing to do + + // There should never be more than one element matching "div.body" + const divBody = document.querySelectorAll("div.body"); + const body = divBody.length ? divBody[0] : document.querySelector("body"); + window.setTimeout(() => { + terms.forEach((term) => _highlightText(body, term, "highlighted")); + }, 10); + + const searchBox = document.getElementById("searchbox"); + if (searchBox === null) return; + searchBox.appendChild( + document + .createRange() + .createContextualFragment( + '", + ), + ); + }, + + /** + * helper function to hide the search marks again + */ + hideSearchWords: () => { + document + .querySelectorAll("#searchbox .highlight-link") + .forEach((el) => el.remove()); + document + .querySelectorAll("span.highlighted") + .forEach((el) => el.classList.remove("highlighted")); + localStorage.removeItem("sphinx_highlight_terms"); + }, + + initEscapeListener: () => { + // only install a listener if it is really needed + if (!DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS) return; + + document.addEventListener("keydown", (event) => { + // bail for input elements + if (BLACKLISTED_KEY_CONTROL_ELEMENTS.has(document.activeElement.tagName)) + return; + // bail with special keys + if (event.shiftKey || event.altKey || event.ctrlKey || event.metaKey) + return; + if ( + DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS + && event.key === "Escape" + ) { + SphinxHighlight.hideSearchWords(); + event.preventDefault(); + } + }); + }, +}; + +_ready(() => { + /* Do not call highlightSearchWords() when we are on the search page. + * It will highlight words from the *previous* search query. + */ + if (typeof Search === "undefined") SphinxHighlight.highlightSearchWords(); + SphinxHighlight.initEscapeListener(); +}); diff --git a/docs/_source/_build/html/_static/styles/furo-extensions.css b/docs/_source/_build/html/_static/styles/furo-extensions.css new file mode 100644 index 0000000..2d74267 --- /dev/null +++ b/docs/_source/_build/html/_static/styles/furo-extensions.css @@ -0,0 +1,2 @@ +#furo-sidebar-ad-placement{padding:var(--sidebar-item-spacing-vertical) var(--sidebar-item-spacing-horizontal)}#furo-sidebar-ad-placement .ethical-sidebar{background:var(--color-background-secondary);border:none;box-shadow:none}#furo-sidebar-ad-placement .ethical-sidebar:hover{background:var(--color-background-hover)}#furo-sidebar-ad-placement .ethical-sidebar a{color:var(--color-foreground-primary)}#furo-sidebar-ad-placement .ethical-callout a{color:var(--color-foreground-secondary)!important}#furo-readthedocs-versions{background:transparent;display:block;position:static;width:100%}#furo-readthedocs-versions .rst-versions{background:#1a1c1e}#furo-readthedocs-versions .rst-current-version{background:var(--color-sidebar-item-background);cursor:unset}#furo-readthedocs-versions .rst-current-version:hover{background:var(--color-sidebar-item-background)}#furo-readthedocs-versions .rst-current-version .fa-book{color:var(--color-foreground-primary)}#furo-readthedocs-versions>.rst-other-versions{padding:0}#furo-readthedocs-versions>.rst-other-versions small{opacity:1}#furo-readthedocs-versions .injected .rst-versions{position:unset}#furo-readthedocs-versions:focus-within,#furo-readthedocs-versions:hover{box-shadow:0 0 0 1px var(--color-sidebar-background-border)}#furo-readthedocs-versions:focus-within .rst-current-version,#furo-readthedocs-versions:hover .rst-current-version{background:#1a1c1e;font-size:inherit;height:auto;line-height:inherit;padding:12px;text-align:right}#furo-readthedocs-versions:focus-within .rst-current-version .fa-book,#furo-readthedocs-versions:hover .rst-current-version .fa-book{color:#fff;float:left}#furo-readthedocs-versions:focus-within .fa-caret-down,#furo-readthedocs-versions:hover .fa-caret-down{display:none}#furo-readthedocs-versions:focus-within .injected,#furo-readthedocs-versions:focus-within .rst-current-version,#furo-readthedocs-versions:focus-within .rst-other-versions,#furo-readthedocs-versions:hover .injected,#furo-readthedocs-versions:hover .rst-current-version,#furo-readthedocs-versions:hover .rst-other-versions{display:block}#furo-readthedocs-versions:focus-within>.rst-current-version,#furo-readthedocs-versions:hover>.rst-current-version{display:none}.highlight:hover button.copybtn{color:var(--color-code-foreground)}.highlight button.copybtn{align-items:center;background-color:var(--color-code-background);border:none;color:var(--color-background-item);cursor:pointer;height:1.25em;right:.5rem;top:.625rem;transition:color .3s,opacity .3s;width:1.25em}.highlight button.copybtn:hover{background-color:var(--color-code-background);color:var(--color-brand-content)}.highlight button.copybtn:after{background-color:transparent;color:var(--color-code-foreground);display:none}.highlight button.copybtn.success{color:#22863a;transition:color 0s}.highlight button.copybtn.success:after{display:block}.highlight button.copybtn svg{padding:0}body{--sd-color-primary:var(--color-brand-primary);--sd-color-primary-highlight:var(--color-brand-content);--sd-color-primary-text:var(--color-background-primary);--sd-color-shadow:rgba(0,0,0,.05);--sd-color-card-border:var(--color-card-border);--sd-color-card-border-hover:var(--color-brand-content);--sd-color-card-background:var(--color-card-background);--sd-color-card-text:var(--color-foreground-primary);--sd-color-card-header:var(--color-card-marginals-background);--sd-color-card-footer:var(--color-card-marginals-background);--sd-color-tabs-label-active:var(--color-brand-content);--sd-color-tabs-label-hover:var(--color-foreground-muted);--sd-color-tabs-label-inactive:var(--color-foreground-muted);--sd-color-tabs-underline-active:var(--color-brand-content);--sd-color-tabs-underline-hover:var(--color-foreground-border);--sd-color-tabs-underline-inactive:var(--color-background-border);--sd-color-tabs-overline:var(--color-background-border);--sd-color-tabs-underline:var(--color-background-border)}.sd-tab-content{box-shadow:0 -2px var(--sd-color-tabs-overline),0 1px var(--sd-color-tabs-underline)}.sd-card{box-shadow:0 .1rem .25rem var(--sd-color-shadow),0 0 .0625rem rgba(0,0,0,.1)}.sd-shadow-sm{box-shadow:0 .1rem .25rem var(--sd-color-shadow),0 0 .0625rem rgba(0,0,0,.1)!important}.sd-shadow-md{box-shadow:0 .3rem .75rem var(--sd-color-shadow),0 0 .0625rem rgba(0,0,0,.1)!important}.sd-shadow-lg{box-shadow:0 .6rem 1.5rem var(--sd-color-shadow),0 0 .0625rem rgba(0,0,0,.1)!important}.sd-card-hover:hover{transform:none}.sd-cards-carousel{gap:.25rem;padding:.25rem}body{--tabs--label-text:var(--color-foreground-muted);--tabs--label-text--hover:var(--color-foreground-muted);--tabs--label-text--active:var(--color-brand-content);--tabs--label-text--active--hover:var(--color-brand-content);--tabs--label-background:transparent;--tabs--label-background--hover:transparent;--tabs--label-background--active:transparent;--tabs--label-background--active--hover:transparent;--tabs--padding-x:0.25em;--tabs--margin-x:1em;--tabs--border:var(--color-background-border);--tabs--label-border:transparent;--tabs--label-border--hover:var(--color-foreground-muted);--tabs--label-border--active:var(--color-brand-content);--tabs--label-border--active--hover:var(--color-brand-content)}[role=main] .container{max-width:none;padding-left:0;padding-right:0}.shadow.docutils{border:none;box-shadow:0 .2rem .5rem rgba(0,0,0,.05),0 0 .0625rem rgba(0,0,0,.1)!important}.sphinx-bs .card{background-color:var(--color-background-secondary);color:var(--color-foreground)} +/*# sourceMappingURL=furo-extensions.css.map*/ \ No newline at end of file diff --git a/docs/_source/_build/html/_static/styles/furo-extensions.css.map b/docs/_source/_build/html/_static/styles/furo-extensions.css.map new file mode 100644 index 0000000..68fb7fd --- /dev/null +++ b/docs/_source/_build/html/_static/styles/furo-extensions.css.map @@ -0,0 +1 @@ +{"version":3,"file":"styles/furo-extensions.css","mappings":"AAGA,2BACE,oFACA,4CAKE,6CAHA,YACA,eAEA,CACA,kDACE,yCAEF,8CACE,sCAEJ,8CACE,kDAEJ,2BAGE,uBACA,cAHA,gBACA,UAEA,CAGA,yCACE,mBAEF,gDAEE,gDADA,YACA,CACA,sDACE,gDACF,yDACE,sCAEJ,+CACE,UACA,qDACE,UAGF,mDACE,eAEJ,yEAEE,4DAEA,mHASE,mBAPA,kBAEA,YADA,oBAGA,aADA,gBAIA,CAEA,qIAEE,WADA,UACA,CAEJ,uGACE,aAEF,iUAGE,cAEF,mHACE,aC1EJ,gCACE,mCAEF,0BAEE,mBAUA,8CACA,YAFA,mCAKA,eAZA,cAIA,YADA,YAYA,iCAdA,YAcA,CAEA,gCAEE,8CADA,gCACA,CAEF,gCAGE,6BADA,mCADA,YAEA,CAEF,kCAEE,cADA,mBACA,CACA,wCACE,cAEJ,8BACE,UCzCN,KAEE,6CAA8C,CAC9C,uDAAwD,CACxD,uDAAwD,CAGxD,iCAAsC,CAGtC,+CAAgD,CAChD,uDAAwD,CACxD,uDAAwD,CACxD,oDAAqD,CACrD,6DAA8D,CAC9D,6DAA8D,CAG9D,uDAAwD,CACxD,yDAA0D,CAC1D,4DAA6D,CAC7D,2DAA4D,CAC5D,8DAA+D,CAC/D,iEAAkE,CAClE,uDAAwD,CACxD,wDAAyD,CAG3D,gBACE,qFAGF,SACE,6EAEF,cACE,uFAEF,cACE,uFAEF,cACE,uFAGF,qBACE,eAEF,mBACE,WACA,eChDF,KACE,gDAAiD,CACjD,uDAAwD,CACxD,qDAAsD,CACtD,4DAA6D,CAC7D,oCAAqC,CACrC,2CAA4C,CAC5C,4CAA6C,CAC7C,mDAAoD,CACpD,wBAAyB,CACzB,oBAAqB,CACrB,6CAA8C,CAC9C,gCAAiC,CACjC,yDAA0D,CAC1D,uDAAwD,CACxD,8DAA+D,CCbjE,uBACE,eACA,eACA,gBAGF,iBACE,YACA,+EAGF,iBACE,mDACA","sources":["webpack:///./src/furo/assets/styles/extensions/_readthedocs.sass","webpack:///./src/furo/assets/styles/extensions/_copybutton.sass","webpack:///./src/furo/assets/styles/extensions/_sphinx-design.sass","webpack:///./src/furo/assets/styles/extensions/_sphinx-inline-tabs.sass","webpack:///./src/furo/assets/styles/extensions/_sphinx-panels.sass"],"sourcesContent":["// This file contains the styles used for tweaking how ReadTheDoc's embedded\n// contents would show up inside the theme.\n\n#furo-sidebar-ad-placement\n padding: var(--sidebar-item-spacing-vertical) var(--sidebar-item-spacing-horizontal)\n .ethical-sidebar\n // Remove the border and box-shadow.\n border: none\n box-shadow: none\n // Manage the background colors.\n background: var(--color-background-secondary)\n &:hover\n background: var(--color-background-hover)\n // Ensure the text is legible.\n a\n color: var(--color-foreground-primary)\n\n .ethical-callout a\n color: var(--color-foreground-secondary) !important\n\n#furo-readthedocs-versions\n position: static\n width: 100%\n background: transparent\n display: block\n\n // Make the background color fit with the theme's aesthetic.\n .rst-versions\n background: rgb(26, 28, 30)\n\n .rst-current-version\n cursor: unset\n background: var(--color-sidebar-item-background)\n &:hover\n background: var(--color-sidebar-item-background)\n .fa-book\n color: var(--color-foreground-primary)\n\n > .rst-other-versions\n padding: 0\n small\n opacity: 1\n\n .injected\n .rst-versions\n position: unset\n\n &:hover,\n &:focus-within\n box-shadow: 0 0 0 1px var(--color-sidebar-background-border)\n\n .rst-current-version\n // Undo the tweaks done in RTD's CSS\n font-size: inherit\n line-height: inherit\n height: auto\n text-align: right\n padding: 12px\n\n // Match the rest of the body\n background: #1a1c1e\n\n .fa-book\n float: left\n color: white\n\n .fa-caret-down\n display: none\n\n .rst-current-version,\n .rst-other-versions,\n .injected\n display: block\n\n > .rst-current-version\n display: none\n",".highlight\n &:hover button.copybtn\n color: var(--color-code-foreground)\n\n button.copybtn\n // Align things correctly\n align-items: center\n\n height: 1.25em\n width: 1.25em\n\n top: 0.625rem // $code-spacing-vertical\n right: 0.5rem\n\n // Make it look better\n color: var(--color-background-item)\n background-color: var(--color-code-background)\n border: none\n\n // Change to cursor to make it obvious that you can click on it\n cursor: pointer\n\n // Transition smoothly, for aesthetics\n transition: color 300ms, opacity 300ms\n\n &:hover\n color: var(--color-brand-content)\n background-color: var(--color-code-background)\n\n &::after\n display: none\n color: var(--color-code-foreground)\n background-color: transparent\n\n &.success\n transition: color 0ms\n color: #22863a\n &::after\n display: block\n\n svg\n padding: 0\n","body\n // Colors\n --sd-color-primary: var(--color-brand-primary)\n --sd-color-primary-highlight: var(--color-brand-content)\n --sd-color-primary-text: var(--color-background-primary)\n\n // Shadows\n --sd-color-shadow: rgba(0, 0, 0, 0.05)\n\n // Cards\n --sd-color-card-border: var(--color-card-border)\n --sd-color-card-border-hover: var(--color-brand-content)\n --sd-color-card-background: var(--color-card-background)\n --sd-color-card-text: var(--color-foreground-primary)\n --sd-color-card-header: var(--color-card-marginals-background)\n --sd-color-card-footer: var(--color-card-marginals-background)\n\n // Tabs\n --sd-color-tabs-label-active: var(--color-brand-content)\n --sd-color-tabs-label-hover: var(--color-foreground-muted)\n --sd-color-tabs-label-inactive: var(--color-foreground-muted)\n --sd-color-tabs-underline-active: var(--color-brand-content)\n --sd-color-tabs-underline-hover: var(--color-foreground-border)\n --sd-color-tabs-underline-inactive: var(--color-background-border)\n --sd-color-tabs-overline: var(--color-background-border)\n --sd-color-tabs-underline: var(--color-background-border)\n\n// Tabs\n.sd-tab-content\n box-shadow: 0 -2px var(--sd-color-tabs-overline), 0 1px var(--sd-color-tabs-underline)\n\n// Shadows\n.sd-card // Have a shadow by default\n box-shadow: 0 0.1rem 0.25rem var(--sd-color-shadow), 0 0 0.0625rem rgba(0, 0, 0, 0.1)\n\n.sd-shadow-sm\n box-shadow: 0 0.1rem 0.25rem var(--sd-color-shadow), 0 0 0.0625rem rgba(0, 0, 0, 0.1) !important\n\n.sd-shadow-md\n box-shadow: 0 0.3rem 0.75rem var(--sd-color-shadow), 0 0 0.0625rem rgba(0, 0, 0, 0.1) !important\n\n.sd-shadow-lg\n box-shadow: 0 0.6rem 1.5rem var(--sd-color-shadow), 0 0 0.0625rem rgba(0, 0, 0, 0.1) !important\n\n// Cards\n.sd-card-hover:hover // Don't change scale on hover\n transform: none\n\n.sd-cards-carousel // Have a bit of gap in the carousel by default\n gap: 0.25rem\n padding: 0.25rem\n","// This file contains styles to tweak sphinx-inline-tabs to work well with Furo.\n\nbody\n --tabs--label-text: var(--color-foreground-muted)\n --tabs--label-text--hover: var(--color-foreground-muted)\n --tabs--label-text--active: var(--color-brand-content)\n --tabs--label-text--active--hover: var(--color-brand-content)\n --tabs--label-background: transparent\n --tabs--label-background--hover: transparent\n --tabs--label-background--active: transparent\n --tabs--label-background--active--hover: transparent\n --tabs--padding-x: 0.25em\n --tabs--margin-x: 1em\n --tabs--border: var(--color-background-border)\n --tabs--label-border: transparent\n --tabs--label-border--hover: var(--color-foreground-muted)\n --tabs--label-border--active: var(--color-brand-content)\n --tabs--label-border--active--hover: var(--color-brand-content)\n","// This file contains styles to tweak sphinx-panels to work well with Furo.\n\n// sphinx-panels includes Bootstrap 4, which uses .container which can conflict\n// with docutils' `.. container::` directive.\n[role=\"main\"] .container\n max-width: initial\n padding-left: initial\n padding-right: initial\n\n// Make the panels look nicer!\n.shadow.docutils\n border: none\n box-shadow: 0 0.2rem 0.5rem rgba(0, 0, 0, 0.05), 0 0 0.0625rem rgba(0, 0, 0, 0.1) !important\n\n// Make panel colors respond to dark mode\n.sphinx-bs .card\n background-color: var(--color-background-secondary)\n color: var(--color-foreground)\n"],"names":[],"sourceRoot":""} \ No newline at end of file diff --git a/docs/_source/_build/html/_static/styles/furo.css b/docs/_source/_build/html/_static/styles/furo.css new file mode 100644 index 0000000..a5b614d --- /dev/null +++ b/docs/_source/_build/html/_static/styles/furo.css @@ -0,0 +1,2 @@ +/*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */html{line-height:1.15;-webkit-text-size-adjust:100%}body{margin:0}main{display:block}h1{font-size:2em;margin:.67em 0}hr{box-sizing:content-box;height:0;overflow:visible}pre{font-family:monospace,monospace;font-size:1em}a{background-color:transparent}abbr[title]{border-bottom:none;text-decoration:underline;text-decoration:underline dotted}b,strong{font-weight:bolder}code,kbd,samp{font-family:monospace,monospace;font-size:1em}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}img{border-style:none}button,input,optgroup,select,textarea{font-family:inherit;font-size:100%;line-height:1.15;margin:0}button,input{overflow:visible}button,select{text-transform:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{border-style:none;padding:0}[type=button]:-moz-focusring,[type=reset]:-moz-focusring,[type=submit]:-moz-focusring,button:-moz-focusring{outline:1px dotted ButtonText}fieldset{padding:.35em .75em .625em}legend{box-sizing:border-box;color:inherit;display:table;max-width:100%;padding:0;white-space:normal}progress{vertical-align:baseline}textarea{overflow:auto}[type=checkbox],[type=radio]{box-sizing:border-box;padding:0}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}details{display:block}summary{display:list-item}[hidden],template{display:none}@media print{.content-icon-container,.headerlink,.mobile-header,.related-pages{display:none!important}.highlight{border:.1pt solid var(--color-foreground-border)}a,blockquote,dl,ol,p,pre,table,ul{page-break-inside:avoid}caption,figure,h1,h2,h3,h4,h5,h6,img{page-break-after:avoid;page-break-inside:avoid}dl,ol,ul{page-break-before:avoid}}.visually-hidden{height:1px!important;margin:-1px!important;overflow:hidden!important;padding:0!important;position:absolute!important;width:1px!important;clip:rect(0,0,0,0)!important;background:var(--color-background-primary);border:0!important;color:var(--color-foreground-primary);white-space:nowrap!important}:-moz-focusring{outline:auto}body{--font-stack:-apple-system,BlinkMacSystemFont,Segoe UI,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji;--font-stack--monospace:"SFMono-Regular",Menlo,Consolas,Monaco,Liberation Mono,Lucida Console,monospace;--font-stack--headings:var(--font-stack);--font-size--normal:100%;--font-size--small:87.5%;--font-size--small--2:81.25%;--font-size--small--3:75%;--font-size--small--4:62.5%;--sidebar-caption-font-size:var(--font-size--small--2);--sidebar-item-font-size:var(--font-size--small);--sidebar-search-input-font-size:var(--font-size--small);--toc-font-size:var(--font-size--small--3);--toc-font-size--mobile:var(--font-size--normal);--toc-title-font-size:var(--font-size--small--4);--admonition-font-size:0.8125rem;--admonition-title-font-size:0.8125rem;--code-font-size:var(--font-size--small--2);--api-font-size:var(--font-size--small);--header-height:calc(var(--sidebar-item-line-height) + var(--sidebar-item-spacing-vertical)*4);--header-padding:0.5rem;--sidebar-tree-space-above:1.5rem;--sidebar-caption-space-above:1rem;--sidebar-item-line-height:1rem;--sidebar-item-spacing-vertical:0.5rem;--sidebar-item-spacing-horizontal:1rem;--sidebar-item-height:calc(var(--sidebar-item-line-height) + var(--sidebar-item-spacing-vertical)*2);--sidebar-expander-width:var(--sidebar-item-height);--sidebar-search-space-above:0.5rem;--sidebar-search-input-spacing-vertical:0.5rem;--sidebar-search-input-spacing-horizontal:0.5rem;--sidebar-search-input-height:1rem;--sidebar-search-icon-size:var(--sidebar-search-input-height);--toc-title-padding:0.25rem 0;--toc-spacing-vertical:1.5rem;--toc-spacing-horizontal:1.5rem;--toc-item-spacing-vertical:0.4rem;--toc-item-spacing-horizontal:1rem;--icon-search:url('data:image/svg+xml;charset=utf-8,');--icon-pencil:url('data:image/svg+xml;charset=utf-8,');--icon-abstract:url('data:image/svg+xml;charset=utf-8,');--icon-info:url('data:image/svg+xml;charset=utf-8,');--icon-flame:url('data:image/svg+xml;charset=utf-8,');--icon-question:url('data:image/svg+xml;charset=utf-8,');--icon-warning:url('data:image/svg+xml;charset=utf-8,');--icon-failure:url('data:image/svg+xml;charset=utf-8,');--icon-spark:url('data:image/svg+xml;charset=utf-8,');--color-admonition-title--caution:#ff9100;--color-admonition-title-background--caution:rgba(255,145,0,.2);--color-admonition-title--warning:#ff9100;--color-admonition-title-background--warning:rgba(255,145,0,.2);--color-admonition-title--danger:#ff5252;--color-admonition-title-background--danger:rgba(255,82,82,.2);--color-admonition-title--attention:#ff5252;--color-admonition-title-background--attention:rgba(255,82,82,.2);--color-admonition-title--error:#ff5252;--color-admonition-title-background--error:rgba(255,82,82,.2);--color-admonition-title--hint:#00c852;--color-admonition-title-background--hint:rgba(0,200,82,.2);--color-admonition-title--tip:#00c852;--color-admonition-title-background--tip:rgba(0,200,82,.2);--color-admonition-title--important:#00bfa5;--color-admonition-title-background--important:rgba(0,191,165,.2);--color-admonition-title--note:#00b0ff;--color-admonition-title-background--note:rgba(0,176,255,.2);--color-admonition-title--seealso:#448aff;--color-admonition-title-background--seealso:rgba(68,138,255,.2);--color-admonition-title--admonition-todo:grey;--color-admonition-title-background--admonition-todo:hsla(0,0%,50%,.2);--color-admonition-title:#651fff;--color-admonition-title-background:rgba(101,31,255,.2);--icon-admonition-default:var(--icon-abstract);--color-topic-title:#14b8a6;--color-topic-title-background:rgba(20,184,166,.2);--icon-topic-default:var(--icon-pencil);--color-problematic:#b30000;--color-foreground-primary:#000;--color-foreground-secondary:#5a5c63;--color-foreground-muted:#6b6f76;--color-foreground-border:#878787;--color-background-primary:#fff;--color-background-secondary:#f8f9fb;--color-background-hover:#efeff4;--color-background-hover--transparent:#efeff400;--color-background-border:#eeebee;--color-background-item:#ccc;--color-announcement-background:#000000dd;--color-announcement-text:#eeebee;--color-brand-primary:#0a4bff;--color-brand-content:#2757dd;--color-brand-visited:#872ee0;--color-api-background:var(--color-background-hover--transparent);--color-api-background-hover:var(--color-background-hover);--color-api-overall:var(--color-foreground-secondary);--color-api-name:var(--color-problematic);--color-api-pre-name:var(--color-problematic);--color-api-paren:var(--color-foreground-secondary);--color-api-keyword:var(--color-foreground-primary);--color-api-added:#21632c;--color-api-added-border:#38a84d;--color-api-changed:#046172;--color-api-changed-border:#06a1bc;--color-api-deprecated:#605706;--color-api-deprecated-border:#f0d90f;--color-api-removed:#b30000;--color-api-removed-border:#ff5c5c;--color-highlight-on-target:#ffc;--color-inline-code-background:var(--color-background-secondary);--color-highlighted-background:#def;--color-highlighted-text:var(--color-foreground-primary);--color-guilabel-background:#ddeeff80;--color-guilabel-border:#bedaf580;--color-guilabel-text:var(--color-foreground-primary);--color-admonition-background:transparent;--color-table-header-background:var(--color-background-secondary);--color-table-border:var(--color-background-border);--color-card-border:var(--color-background-secondary);--color-card-background:transparent;--color-card-marginals-background:var(--color-background-secondary);--color-header-background:var(--color-background-primary);--color-header-border:var(--color-background-border);--color-header-text:var(--color-foreground-primary);--color-sidebar-background:var(--color-background-secondary);--color-sidebar-background-border:var(--color-background-border);--color-sidebar-brand-text:var(--color-foreground-primary);--color-sidebar-caption-text:var(--color-foreground-muted);--color-sidebar-link-text:var(--color-foreground-secondary);--color-sidebar-link-text--top-level:var(--color-brand-primary);--color-sidebar-item-background:var(--color-sidebar-background);--color-sidebar-item-background--current:var( --color-sidebar-item-background );--color-sidebar-item-background--hover:linear-gradient(90deg,var(--color-background-hover--transparent) 0%,var(--color-background-hover) var(--sidebar-item-spacing-horizontal),var(--color-background-hover) 100%);--color-sidebar-item-expander-background:transparent;--color-sidebar-item-expander-background--hover:var( --color-background-hover );--color-sidebar-search-text:var(--color-foreground-primary);--color-sidebar-search-background:var(--color-background-secondary);--color-sidebar-search-background--focus:var(--color-background-primary);--color-sidebar-search-border:var(--color-background-border);--color-sidebar-search-icon:var(--color-foreground-muted);--color-toc-background:var(--color-background-primary);--color-toc-title-text:var(--color-foreground-muted);--color-toc-item-text:var(--color-foreground-secondary);--color-toc-item-text--hover:var(--color-foreground-primary);--color-toc-item-text--active:var(--color-brand-primary);--color-content-foreground:var(--color-foreground-primary);--color-content-background:transparent;--color-link:var(--color-brand-content);--color-link-underline:var(--color-background-border);--color-link--hover:var(--color-brand-content);--color-link-underline--hover:var(--color-foreground-border);--color-link--visited:var(--color-brand-visited);--color-link-underline--visited:var(--color-background-border);--color-link--visited--hover:var(--color-brand-visited);--color-link-underline--visited--hover:var(--color-foreground-border)}.only-light{display:block!important}html body .only-dark{display:none!important}@media not print{body[data-theme=dark]{--color-problematic:#ee5151;--color-foreground-primary:#cfd0d0;--color-foreground-secondary:#9ca0a5;--color-foreground-muted:#81868d;--color-foreground-border:#666;--color-background-primary:#131416;--color-background-secondary:#1a1c1e;--color-background-hover:#1e2124;--color-background-hover--transparent:#1e212400;--color-background-border:#303335;--color-background-item:#444;--color-announcement-background:#000000dd;--color-announcement-text:#eeebee;--color-brand-primary:#3d94ff;--color-brand-content:#5ca5ff;--color-brand-visited:#b27aeb;--color-highlighted-background:#083563;--color-guilabel-background:#08356380;--color-guilabel-border:#13395f80;--color-api-keyword:var(--color-foreground-secondary);--color-highlight-on-target:#330;--color-api-added:#3db854;--color-api-added-border:#267334;--color-api-changed:#09b0ce;--color-api-changed-border:#056d80;--color-api-deprecated:#b1a10b;--color-api-deprecated-border:#6e6407;--color-api-removed:#ff7575;--color-api-removed-border:#b03b3b;--color-admonition-background:#18181a;--color-card-border:var(--color-background-secondary);--color-card-background:#18181a;--color-card-marginals-background:var(--color-background-hover)}html body[data-theme=dark] .only-light{display:none!important}body[data-theme=dark] .only-dark{display:block!important}@media(prefers-color-scheme:dark){body:not([data-theme=light]){--color-problematic:#ee5151;--color-foreground-primary:#cfd0d0;--color-foreground-secondary:#9ca0a5;--color-foreground-muted:#81868d;--color-foreground-border:#666;--color-background-primary:#131416;--color-background-secondary:#1a1c1e;--color-background-hover:#1e2124;--color-background-hover--transparent:#1e212400;--color-background-border:#303335;--color-background-item:#444;--color-announcement-background:#000000dd;--color-announcement-text:#eeebee;--color-brand-primary:#3d94ff;--color-brand-content:#5ca5ff;--color-brand-visited:#b27aeb;--color-highlighted-background:#083563;--color-guilabel-background:#08356380;--color-guilabel-border:#13395f80;--color-api-keyword:var(--color-foreground-secondary);--color-highlight-on-target:#330;--color-api-added:#3db854;--color-api-added-border:#267334;--color-api-changed:#09b0ce;--color-api-changed-border:#056d80;--color-api-deprecated:#b1a10b;--color-api-deprecated-border:#6e6407;--color-api-removed:#ff7575;--color-api-removed-border:#b03b3b;--color-admonition-background:#18181a;--color-card-border:var(--color-background-secondary);--color-card-background:#18181a;--color-card-marginals-background:var(--color-background-hover)}html body:not([data-theme=light]) .only-light{display:none!important}body:not([data-theme=light]) .only-dark{display:block!important}}}body[data-theme=auto] .theme-toggle svg.theme-icon-when-auto-light{display:block}@media(prefers-color-scheme:dark){body[data-theme=auto] .theme-toggle svg.theme-icon-when-auto-dark{display:block}body[data-theme=auto] .theme-toggle svg.theme-icon-when-auto-light{display:none}}body[data-theme=dark] .theme-toggle svg.theme-icon-when-dark,body[data-theme=light] .theme-toggle svg.theme-icon-when-light{display:block}body{font-family:var(--font-stack)}code,kbd,pre,samp{font-family:var(--font-stack--monospace)}body{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}article{line-height:1.5}h1,h2,h3,h4,h5,h6{border-radius:.5rem;font-family:var(--font-stack--headings);font-weight:700;line-height:1.25;margin:.5rem -.5rem;padding-left:.5rem;padding-right:.5rem}h1+p,h2+p,h3+p,h4+p,h5+p,h6+p{margin-top:0}h1{font-size:2.5em;margin-bottom:1rem}h1,h2{margin-top:1.75rem}h2{font-size:2em}h3{font-size:1.5em}h4{font-size:1.25em}h5{font-size:1.125em}h6{font-size:1em}small{font-size:80%;opacity:75%}p{margin-bottom:.75rem;margin-top:.5rem}hr.docutils{background-color:var(--color-background-border);border:0;height:1px;margin:2rem 0;padding:0}.centered{text-align:center}a{color:var(--color-link);text-decoration:underline;text-decoration-color:var(--color-link-underline)}a:visited{color:var(--color-link--visited);text-decoration-color:var(--color-link-underline--visited)}a:visited:hover{color:var(--color-link--visited--hover);text-decoration-color:var(--color-link-underline--visited--hover)}a:hover{color:var(--color-link--hover);text-decoration-color:var(--color-link-underline--hover)}a.muted-link{color:inherit}a.muted-link:hover{color:var(--color-link--hover);text-decoration-color:var(--color-link-underline--hover)}a.muted-link:hover:visited{color:var(--color-link--visited--hover);text-decoration-color:var(--color-link-underline--visited--hover)}html{overflow-x:hidden;overflow-y:scroll;scroll-behavior:smooth}.sidebar-scroll,.toc-scroll,article[role=main] *{scrollbar-color:var(--color-foreground-border) transparent;scrollbar-width:thin}body,html{height:100%}.skip-to-content,body,html{background:var(--color-background-primary);color:var(--color-foreground-primary)}.skip-to-content{border-radius:1rem;left:.25rem;padding:1rem;position:fixed;top:.25rem;transform:translateY(-200%);transition:transform .3s ease-in-out;z-index:40}.skip-to-content:focus-within{transform:translateY(0)}article{background:var(--color-content-background);color:var(--color-content-foreground);overflow-wrap:break-word}.page{display:flex;min-height:100%}.mobile-header{background-color:var(--color-header-background);border-bottom:1px solid var(--color-header-border);color:var(--color-header-text);display:none;height:var(--header-height);width:100%;z-index:10}.mobile-header.scrolled{border-bottom:none;box-shadow:0 0 .2rem rgba(0,0,0,.1),0 .2rem .4rem rgba(0,0,0,.2)}.mobile-header .header-center a{color:var(--color-header-text);text-decoration:none}.main{display:flex;flex:1}.sidebar-drawer{background:var(--color-sidebar-background);border-right:1px solid var(--color-sidebar-background-border);box-sizing:border-box;display:flex;justify-content:flex-end;min-width:15em;width:calc(50% - 26em)}.sidebar-container,.toc-drawer{box-sizing:border-box;width:15em}.toc-drawer{background:var(--color-toc-background);padding-right:1rem}.sidebar-sticky,.toc-sticky{display:flex;flex-direction:column;height:min(100%,100vh);height:100vh;position:sticky;top:0}.sidebar-scroll,.toc-scroll{flex-grow:1;flex-shrink:1;overflow:auto;scroll-behavior:smooth}.content{display:flex;flex-direction:column;justify-content:space-between;padding:0 3em;width:46em}.icon{display:inline-block;height:1rem;width:1rem}.icon svg{height:100%;width:100%}.announcement{align-items:center;background-color:var(--color-announcement-background);color:var(--color-announcement-text);display:flex;height:var(--header-height);overflow-x:auto}.announcement+.page{min-height:calc(100% - var(--header-height))}.announcement-content{box-sizing:border-box;min-width:100%;padding:.5rem;text-align:center;white-space:nowrap}.announcement-content a{color:var(--color-announcement-text);text-decoration-color:var(--color-announcement-text)}.announcement-content a:hover{color:var(--color-announcement-text);text-decoration-color:var(--color-link--hover)}.no-js .theme-toggle-container{display:none}.theme-toggle-container{display:flex}.theme-toggle{background:transparent;border:none;cursor:pointer;display:flex;padding:0}.theme-toggle svg{color:var(--color-foreground-primary);display:none;height:1.25rem;width:1.25rem}.theme-toggle-header{align-items:center;display:flex;justify-content:center}.nav-overlay-icon,.toc-overlay-icon{cursor:pointer;display:none}.nav-overlay-icon .icon,.toc-overlay-icon .icon{color:var(--color-foreground-secondary);height:1.5rem;width:1.5rem}.nav-overlay-icon,.toc-header-icon{align-items:center;justify-content:center}.toc-content-icon{height:1.5rem;width:1.5rem}.content-icon-container{display:flex;float:right;gap:.5rem;margin-bottom:1rem;margin-left:1rem;margin-top:1.5rem}.content-icon-container .edit-this-page svg,.content-icon-container .view-this-page svg{color:inherit;height:1.25rem;width:1.25rem}.sidebar-toggle{display:none;position:absolute}.sidebar-toggle[name=__toc]{left:20px}.sidebar-toggle:checked{left:40px}.overlay{background-color:rgba(0,0,0,.54);height:0;opacity:0;position:fixed;top:0;transition:width 0s,height 0s,opacity .25s ease-out;width:0}.sidebar-overlay{z-index:20}.toc-overlay{z-index:40}.sidebar-drawer{transition:left .25s ease-in-out;z-index:30}.toc-drawer{transition:right .25s ease-in-out;z-index:50}#__navigation:checked~.sidebar-overlay{height:100%;opacity:1;width:100%}#__navigation:checked~.page .sidebar-drawer{left:0;top:0}#__toc:checked~.toc-overlay{height:100%;opacity:1;width:100%}#__toc:checked~.page .toc-drawer{right:0;top:0}.back-to-top{background:var(--color-background-primary);border-radius:1rem;box-shadow:0 .2rem .5rem rgba(0,0,0,.05),0 0 1px 0 hsla(220,9%,46%,.502);display:none;font-size:.8125rem;left:0;margin-left:50%;padding:.5rem .75rem .5rem .5rem;position:fixed;text-decoration:none;top:1rem;transform:translateX(-50%);z-index:10}.back-to-top svg{height:1rem;width:1rem;fill:currentColor;display:inline-block}.back-to-top span{margin-left:.25rem}.show-back-to-top .back-to-top{align-items:center;display:flex}@media(min-width:97em){html{font-size:110%}}@media(max-width:82em){.toc-content-icon{display:flex}.toc-drawer{border-left:1px solid var(--color-background-muted);height:100vh;position:fixed;right:-15em;top:0}.toc-tree{border-left:none;font-size:var(--toc-font-size--mobile)}.sidebar-drawer{width:calc(50% - 18.5em)}}@media(max-width:67em){.content{margin-left:auto;margin-right:auto;padding:0 1em}}@media(max-width:63em){.nav-overlay-icon{display:flex}.sidebar-drawer{height:100vh;left:-15em;position:fixed;top:0;width:15em}.theme-toggle-header,.toc-header-icon{display:flex}.theme-toggle-content,.toc-content-icon{display:none}.mobile-header{align-items:center;display:flex;justify-content:space-between;position:sticky;top:0}.mobile-header .header-left,.mobile-header .header-right{display:flex;height:var(--header-height);padding:0 var(--header-padding)}.mobile-header .header-left label,.mobile-header .header-right label{height:100%;-webkit-user-select:none;-moz-user-select:none;user-select:none;width:100%}.nav-overlay-icon .icon,.theme-toggle svg{height:1.5rem;width:1.5rem}:target{scroll-margin-top:calc(var(--header-height) + 2.5rem)}.back-to-top{top:calc(var(--header-height) + .5rem)}.page{flex-direction:column;justify-content:center}}@media(max-width:48em){.content{overflow-x:auto;width:100%}}@media(max-width:46em){article[role=main] aside.sidebar{float:none;margin:1rem 0;width:100%}}.admonition,.topic{background:var(--color-admonition-background);border-radius:.2rem;box-shadow:0 .2rem .5rem rgba(0,0,0,.05),0 0 .0625rem rgba(0,0,0,.1);font-size:var(--admonition-font-size);margin:1rem auto;overflow:hidden;padding:0 .5rem .5rem;page-break-inside:avoid}.admonition>:nth-child(2),.topic>:nth-child(2){margin-top:0}.admonition>:last-child,.topic>:last-child{margin-bottom:0}.admonition p.admonition-title,p.topic-title{font-size:var(--admonition-title-font-size);font-weight:500;line-height:1.3;margin:0 -.5rem .5rem;padding:.4rem .5rem .4rem 2rem;position:relative}.admonition p.admonition-title:before,p.topic-title:before{content:"";height:1rem;left:.5rem;position:absolute;width:1rem}p.admonition-title{background-color:var(--color-admonition-title-background)}p.admonition-title:before{background-color:var(--color-admonition-title);-webkit-mask-image:var(--icon-admonition-default);mask-image:var(--icon-admonition-default);-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat}p.topic-title{background-color:var(--color-topic-title-background)}p.topic-title:before{background-color:var(--color-topic-title);-webkit-mask-image:var(--icon-topic-default);mask-image:var(--icon-topic-default);-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat}.admonition{border-left:.2rem solid var(--color-admonition-title)}.admonition.caution{border-left-color:var(--color-admonition-title--caution)}.admonition.caution>.admonition-title{background-color:var(--color-admonition-title-background--caution)}.admonition.caution>.admonition-title:before{background-color:var(--color-admonition-title--caution);-webkit-mask-image:var(--icon-spark);mask-image:var(--icon-spark)}.admonition.warning{border-left-color:var(--color-admonition-title--warning)}.admonition.warning>.admonition-title{background-color:var(--color-admonition-title-background--warning)}.admonition.warning>.admonition-title:before{background-color:var(--color-admonition-title--warning);-webkit-mask-image:var(--icon-warning);mask-image:var(--icon-warning)}.admonition.danger{border-left-color:var(--color-admonition-title--danger)}.admonition.danger>.admonition-title{background-color:var(--color-admonition-title-background--danger)}.admonition.danger>.admonition-title:before{background-color:var(--color-admonition-title--danger);-webkit-mask-image:var(--icon-spark);mask-image:var(--icon-spark)}.admonition.attention{border-left-color:var(--color-admonition-title--attention)}.admonition.attention>.admonition-title{background-color:var(--color-admonition-title-background--attention)}.admonition.attention>.admonition-title:before{background-color:var(--color-admonition-title--attention);-webkit-mask-image:var(--icon-warning);mask-image:var(--icon-warning)}.admonition.error{border-left-color:var(--color-admonition-title--error)}.admonition.error>.admonition-title{background-color:var(--color-admonition-title-background--error)}.admonition.error>.admonition-title:before{background-color:var(--color-admonition-title--error);-webkit-mask-image:var(--icon-failure);mask-image:var(--icon-failure)}.admonition.hint{border-left-color:var(--color-admonition-title--hint)}.admonition.hint>.admonition-title{background-color:var(--color-admonition-title-background--hint)}.admonition.hint>.admonition-title:before{background-color:var(--color-admonition-title--hint);-webkit-mask-image:var(--icon-question);mask-image:var(--icon-question)}.admonition.tip{border-left-color:var(--color-admonition-title--tip)}.admonition.tip>.admonition-title{background-color:var(--color-admonition-title-background--tip)}.admonition.tip>.admonition-title:before{background-color:var(--color-admonition-title--tip);-webkit-mask-image:var(--icon-info);mask-image:var(--icon-info)}.admonition.important{border-left-color:var(--color-admonition-title--important)}.admonition.important>.admonition-title{background-color:var(--color-admonition-title-background--important)}.admonition.important>.admonition-title:before{background-color:var(--color-admonition-title--important);-webkit-mask-image:var(--icon-flame);mask-image:var(--icon-flame)}.admonition.note{border-left-color:var(--color-admonition-title--note)}.admonition.note>.admonition-title{background-color:var(--color-admonition-title-background--note)}.admonition.note>.admonition-title:before{background-color:var(--color-admonition-title--note);-webkit-mask-image:var(--icon-pencil);mask-image:var(--icon-pencil)}.admonition.seealso{border-left-color:var(--color-admonition-title--seealso)}.admonition.seealso>.admonition-title{background-color:var(--color-admonition-title-background--seealso)}.admonition.seealso>.admonition-title:before{background-color:var(--color-admonition-title--seealso);-webkit-mask-image:var(--icon-info);mask-image:var(--icon-info)}.admonition.admonition-todo{border-left-color:var(--color-admonition-title--admonition-todo)}.admonition.admonition-todo>.admonition-title{background-color:var(--color-admonition-title-background--admonition-todo)}.admonition.admonition-todo>.admonition-title:before{background-color:var(--color-admonition-title--admonition-todo);-webkit-mask-image:var(--icon-pencil);mask-image:var(--icon-pencil)}.admonition-todo>.admonition-title{text-transform:uppercase}dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.glossary):not(.simple) dd{margin-left:2rem}dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.glossary):not(.simple) dd>:first-child{margin-top:.125rem}dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.glossary):not(.simple) .field-list,dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.glossary):not(.simple) dd>:last-child{margin-bottom:.75rem}dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.glossary):not(.simple) .field-list>dt{font-size:var(--font-size--small);text-transform:uppercase}dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.glossary):not(.simple) .field-list dd:empty{margin-bottom:.5rem}dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.glossary):not(.simple) .field-list dd>ul{margin-left:-1.2rem}dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.glossary):not(.simple) .field-list dd>ul>li>p:nth-child(2){margin-top:0}dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.glossary):not(.simple) .field-list dd>ul>li>p+p:last-child:empty{margin-bottom:0;margin-top:0}dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.glossary):not(.simple)>dt{color:var(--color-api-overall)}.sig:not(.sig-inline){background:var(--color-api-background);border-radius:.25rem;font-family:var(--font-stack--monospace);font-size:var(--api-font-size);font-weight:700;margin-left:-.25rem;margin-right:-.25rem;padding:.25rem .5rem .25rem 3em;text-indent:-2.5em;transition:background .1s ease-out}.sig:not(.sig-inline):hover{background:var(--color-api-background-hover)}.sig:not(.sig-inline) a.reference .viewcode-link{font-weight:400;width:4.25rem}em.property,span.property{font-style:normal}em.property:first-child,span.property:first-child{color:var(--color-api-keyword)}.sig-name{color:var(--color-api-name)}.sig-prename{color:var(--color-api-pre-name);font-weight:400}.sig-paren{color:var(--color-api-paren)}.sig-param{font-style:normal}div.deprecated,div.versionadded,div.versionchanged,div.versionremoved{border-left:.1875rem solid;border-radius:.125rem;padding-left:.75rem}div.deprecated p,div.versionadded p,div.versionchanged p,div.versionremoved p{margin-bottom:.125rem;margin-top:.125rem}div.versionadded{border-color:var(--color-api-added-border)}div.versionadded .versionmodified{color:var(--color-api-added)}div.versionchanged{border-color:var(--color-api-changed-border)}div.versionchanged .versionmodified{color:var(--color-api-changed)}div.deprecated{border-color:var(--color-api-deprecated-border)}div.deprecated .versionmodified{color:var(--color-api-deprecated)}div.versionremoved{border-color:var(--color-api-removed-border)}div.versionremoved .versionmodified{color:var(--color-api-removed)}.viewcode-back,.viewcode-link{float:right;text-align:right}.line-block{margin-bottom:.75rem;margin-top:.5rem}.line-block .line-block{margin-bottom:0;margin-top:0;padding-left:1rem}.code-block-caption,article p.caption,table>caption{font-size:var(--font-size--small);text-align:center}.toctree-wrapper.compound .caption,.toctree-wrapper.compound :not(.caption)>.caption-text{font-size:var(--font-size--small);margin-bottom:0;text-align:initial;text-transform:uppercase}.toctree-wrapper.compound>ul{margin-bottom:0;margin-top:0}.sig-inline,code.literal{background:var(--color-inline-code-background);border-radius:.2em;font-size:var(--font-size--small--2);padding:.1em .2em}pre.literal-block .sig-inline,pre.literal-block code.literal{font-size:inherit;padding:0}p .sig-inline,p code.literal{border:1px solid var(--color-background-border)}.sig-inline{font-family:var(--font-stack--monospace)}div[class*=" highlight-"],div[class^=highlight-]{display:flex;margin:1em 0}div[class*=" highlight-"] .table-wrapper,div[class^=highlight-] .table-wrapper,pre{margin:0;padding:0}pre{overflow:auto}article[role=main] .highlight pre{line-height:1.5}.highlight pre,pre.literal-block{font-size:var(--code-font-size);padding:.625rem .875rem}pre.literal-block{background-color:var(--color-code-background);border-radius:.2rem;color:var(--color-code-foreground);margin-bottom:1rem;margin-top:1rem}.highlight{border-radius:.2rem;width:100%}.highlight .gp,.highlight span.linenos{pointer-events:none;-webkit-user-select:none;-moz-user-select:none;user-select:none}.highlight .hll{display:block;margin-left:-.875rem;margin-right:-.875rem;padding-left:.875rem;padding-right:.875rem}.code-block-caption{background-color:var(--color-code-background);border-bottom:1px solid;border-radius:.25rem;border-bottom-left-radius:0;border-bottom-right-radius:0;border-color:var(--color-background-border);color:var(--color-code-foreground);display:flex;font-weight:300;padding:.625rem .875rem}.code-block-caption+div[class]{margin-top:0}.code-block-caption+div[class]>.highlight{border-top-left-radius:0;border-top-right-radius:0}.highlighttable{display:block;width:100%}.highlighttable tbody{display:block}.highlighttable tr{display:flex}.highlighttable td.linenos{background-color:var(--color-code-background);border-bottom-left-radius:.2rem;border-top-left-radius:.2rem;color:var(--color-code-foreground);padding:.625rem 0 .625rem .875rem}.highlighttable .linenodiv{box-shadow:-.0625rem 0 var(--color-foreground-border) inset;font-size:var(--code-font-size);padding-right:.875rem}.highlighttable td.code{display:block;flex:1;overflow:hidden;padding:0}.highlighttable td.code .highlight{border-bottom-left-radius:0;border-top-left-radius:0}.highlight span.linenos{box-shadow:-.0625rem 0 var(--color-foreground-border) inset;display:inline-block;margin-right:.875rem;padding-left:0;padding-right:.875rem}.footnote-reference{font-size:var(--font-size--small--4);vertical-align:super}dl.footnote.brackets{color:var(--color-foreground-secondary);display:grid;font-size:var(--font-size--small);grid-template-columns:max-content auto}dl.footnote.brackets dt{margin:0}dl.footnote.brackets dt>.fn-backref{margin-left:.25rem}dl.footnote.brackets dt:after{content:":"}dl.footnote.brackets dt .brackets:before{content:"["}dl.footnote.brackets dt .brackets:after{content:"]"}dl.footnote.brackets dd{margin:0;padding:0 1rem}aside.footnote{color:var(--color-foreground-secondary);font-size:var(--font-size--small)}aside.footnote>span,div.citation>span{float:left;font-weight:500;padding-right:.25rem}aside.footnote>:not(span),div.citation>p{margin-left:2rem}img{box-sizing:border-box;height:auto;max-width:100%}article .figure,article figure{border-radius:.2rem;margin:0}article .figure :last-child,article figure :last-child{margin-bottom:0}article .align-left{clear:left;float:left;margin:0 1rem 1rem}article .align-right{clear:right;float:right;margin:0 1rem 1rem}article .align-center,article .align-default{display:block;margin-left:auto;margin-right:auto;text-align:center}article table.align-default{display:table;text-align:initial}.domainindex-jumpbox,.genindex-jumpbox{border-bottom:1px solid var(--color-background-border);border-top:1px solid var(--color-background-border);padding:.25rem}.domainindex-section h2,.genindex-section h2{margin-bottom:.5rem;margin-top:.75rem}.domainindex-section ul,.genindex-section ul{margin-bottom:0;margin-top:0}ol,ul{margin-bottom:1rem;margin-top:1rem;padding-left:1.2rem}ol li>p:first-child,ul li>p:first-child{margin-bottom:.25rem;margin-top:.25rem}ol li>p:last-child,ul li>p:last-child{margin-top:.25rem}ol li>ol,ol li>ul,ul li>ol,ul li>ul{margin-bottom:.5rem;margin-top:.5rem}ol.arabic{list-style:decimal}ol.loweralpha{list-style:lower-alpha}ol.upperalpha{list-style:upper-alpha}ol.lowerroman{list-style:lower-roman}ol.upperroman{list-style:upper-roman}.simple li>ol,.simple li>ul,.toctree-wrapper li>ol,.toctree-wrapper li>ul{margin-bottom:0;margin-top:0}.field-list dt,.option-list dt,dl.footnote dt,dl.glossary dt,dl.simple dt,dl:not([class]) dt{font-weight:500;margin-top:.25rem}.field-list dt+dt,.option-list dt+dt,dl.footnote dt+dt,dl.glossary dt+dt,dl.simple dt+dt,dl:not([class]) dt+dt{margin-top:0}.field-list dt .classifier:before,.option-list dt .classifier:before,dl.footnote dt .classifier:before,dl.glossary dt .classifier:before,dl.simple dt .classifier:before,dl:not([class]) dt .classifier:before{content:":";margin-left:.2rem;margin-right:.2rem}.field-list dd ul,.field-list dd>p:first-child,.option-list dd ul,.option-list dd>p:first-child,dl.footnote dd ul,dl.footnote dd>p:first-child,dl.glossary dd ul,dl.glossary dd>p:first-child,dl.simple dd ul,dl.simple dd>p:first-child,dl:not([class]) dd ul,dl:not([class]) dd>p:first-child{margin-top:.125rem}.field-list dd ul,.option-list dd ul,dl.footnote dd ul,dl.glossary dd ul,dl.simple dd ul,dl:not([class]) dd ul{margin-bottom:.125rem}.math-wrapper{overflow-x:auto;width:100%}div.math{position:relative;text-align:center}div.math .headerlink,div.math:focus .headerlink{display:none}div.math:hover .headerlink{display:inline-block}div.math span.eqno{position:absolute;right:.5rem;top:50%;transform:translateY(-50%);z-index:1}abbr[title]{cursor:help}.problematic{color:var(--color-problematic)}kbd:not(.compound){background-color:var(--color-background-secondary);border:1px solid var(--color-foreground-border);border-radius:.2rem;box-shadow:0 .0625rem 0 rgba(0,0,0,.2),inset 0 0 0 .125rem var(--color-background-primary);color:var(--color-foreground-primary);display:inline-block;font-size:var(--font-size--small--3);margin:0 .2rem;padding:0 .2rem;vertical-align:text-bottom}blockquote{background:var(--color-background-secondary);border-left:4px solid var(--color-background-border);margin-left:0;margin-right:0;padding:.5rem 1rem}blockquote .attribution{font-weight:600;text-align:right}blockquote.highlights,blockquote.pull-quote{font-size:1.25em}blockquote.epigraph,blockquote.pull-quote{border-left-width:0;border-radius:.5rem}blockquote.highlights{background:transparent;border-left-width:0}p .reference img{vertical-align:middle}p.rubric{font-size:1.125em;font-weight:700;line-height:1.25}dd p.rubric{font-size:var(--font-size--small);font-weight:inherit;line-height:inherit;text-transform:uppercase}article .sidebar{background-color:var(--color-background-secondary);border:1px solid var(--color-background-border);border-radius:.2rem;clear:right;float:right;margin-left:1rem;margin-right:0;width:30%}article .sidebar>*{padding-left:1rem;padding-right:1rem}article .sidebar>ol,article .sidebar>ul{padding-left:2.2rem}article .sidebar .sidebar-title{border-bottom:1px solid var(--color-background-border);font-weight:500;margin:0;padding:.5rem 1rem}[role=main] .table-wrapper.container{margin-bottom:.5rem;margin-top:1rem;overflow-x:auto;padding:.2rem .2rem .75rem;width:100%}table.docutils{border-collapse:collapse;border-radius:.2rem;border-spacing:0;box-shadow:0 .2rem .5rem rgba(0,0,0,.05),0 0 .0625rem rgba(0,0,0,.1)}table.docutils th{background:var(--color-table-header-background)}table.docutils td,table.docutils th{border-bottom:1px solid var(--color-table-border);border-left:1px solid var(--color-table-border);border-right:1px solid var(--color-table-border);padding:0 .25rem}table.docutils td p,table.docutils th p{margin:.25rem}table.docutils td:first-child,table.docutils th:first-child{border-left:none}table.docutils td:last-child,table.docutils th:last-child{border-right:none}table.docutils td.text-left,table.docutils th.text-left{text-align:left}table.docutils td.text-right,table.docutils th.text-right{text-align:right}table.docutils td.text-center,table.docutils th.text-center{text-align:center}:target{scroll-margin-top:2.5rem}@media(max-width:67em){:target{scroll-margin-top:calc(2.5rem + var(--header-height))}section>span:target{scroll-margin-top:calc(2.8rem + var(--header-height))}}.headerlink{font-weight:100;-webkit-user-select:none;-moz-user-select:none;user-select:none}.code-block-caption>.headerlink,dl dt>.headerlink,figcaption p>.headerlink,h1>.headerlink,h2>.headerlink,h3>.headerlink,h4>.headerlink,h5>.headerlink,h6>.headerlink,p.caption>.headerlink,table>caption>.headerlink{margin-left:.5rem;visibility:hidden}.code-block-caption:hover>.headerlink,dl dt:hover>.headerlink,figcaption p:hover>.headerlink,h1:hover>.headerlink,h2:hover>.headerlink,h3:hover>.headerlink,h4:hover>.headerlink,h5:hover>.headerlink,h6:hover>.headerlink,p.caption:hover>.headerlink,table>caption:hover>.headerlink{visibility:visible}.code-block-caption>.toc-backref,dl dt>.toc-backref,figcaption p>.toc-backref,h1>.toc-backref,h2>.toc-backref,h3>.toc-backref,h4>.toc-backref,h5>.toc-backref,h6>.toc-backref,p.caption>.toc-backref,table>caption>.toc-backref{color:inherit;text-decoration-line:none}figure:hover>figcaption>p>.headerlink,table:hover>caption>.headerlink{visibility:visible}:target>h1:first-of-type,:target>h2:first-of-type,:target>h3:first-of-type,:target>h4:first-of-type,:target>h5:first-of-type,:target>h6:first-of-type,span:target~h1:first-of-type,span:target~h2:first-of-type,span:target~h3:first-of-type,span:target~h4:first-of-type,span:target~h5:first-of-type,span:target~h6:first-of-type{background-color:var(--color-highlight-on-target)}:target>h1:first-of-type code.literal,:target>h2:first-of-type code.literal,:target>h3:first-of-type code.literal,:target>h4:first-of-type code.literal,:target>h5:first-of-type code.literal,:target>h6:first-of-type code.literal,span:target~h1:first-of-type code.literal,span:target~h2:first-of-type code.literal,span:target~h3:first-of-type code.literal,span:target~h4:first-of-type code.literal,span:target~h5:first-of-type code.literal,span:target~h6:first-of-type code.literal{background-color:transparent}.literal-block-wrapper:target .code-block-caption,.this-will-duplicate-information-and-it-is-still-useful-here li :target,figure:target,table:target>caption{background-color:var(--color-highlight-on-target)}dt:target{background-color:var(--color-highlight-on-target)!important}.footnote-reference:target,.footnote>dt:target+dd{background-color:var(--color-highlight-on-target)}.guilabel{background-color:var(--color-guilabel-background);border:1px solid var(--color-guilabel-border);border-radius:.5em;color:var(--color-guilabel-text);font-size:.9em;padding:0 .3em}footer{display:flex;flex-direction:column;font-size:var(--font-size--small);margin-top:2rem}.bottom-of-page{align-items:center;border-top:1px solid var(--color-background-border);color:var(--color-foreground-secondary);display:flex;justify-content:space-between;line-height:1.5;margin-top:1rem;padding-bottom:1rem;padding-top:1rem}@media(max-width:46em){.bottom-of-page{flex-direction:column-reverse;gap:.25rem;text-align:center}}.bottom-of-page .left-details{font-size:var(--font-size--small)}.bottom-of-page .right-details{display:flex;flex-direction:column;gap:.25rem;text-align:right}.bottom-of-page .icons{display:flex;font-size:1rem;gap:.25rem;justify-content:flex-end}.bottom-of-page .icons a{text-decoration:none}.bottom-of-page .icons img,.bottom-of-page .icons svg{font-size:1.125rem;height:1em;width:1em}.related-pages a{align-items:center;display:flex;text-decoration:none}.related-pages a:hover .page-info .title{color:var(--color-link);text-decoration:underline;text-decoration-color:var(--color-link-underline)}.related-pages a svg.furo-related-icon,.related-pages a svg.furo-related-icon>use{color:var(--color-foreground-border);flex-shrink:0;height:.75rem;margin:0 .5rem;width:.75rem}.related-pages a.next-page{clear:right;float:right;max-width:50%;text-align:right}.related-pages a.prev-page{clear:left;float:left;max-width:50%}.related-pages a.prev-page svg{transform:rotate(180deg)}.page-info{display:flex;flex-direction:column;overflow-wrap:anywhere}.next-page .page-info{align-items:flex-end}.page-info .context{align-items:center;color:var(--color-foreground-muted);display:flex;font-size:var(--font-size--small);padding-bottom:.1rem;text-decoration:none}ul.search{list-style:none;padding-left:0}ul.search li{border-bottom:1px solid var(--color-background-border);padding:1rem 0}[role=main] .highlighted{background-color:var(--color-highlighted-background);color:var(--color-highlighted-text)}.sidebar-brand{display:flex;flex-direction:column;flex-shrink:0;padding:var(--sidebar-item-spacing-vertical) var(--sidebar-item-spacing-horizontal);text-decoration:none}.sidebar-brand-text{color:var(--color-sidebar-brand-text);font-size:1.5rem;overflow-wrap:break-word}.sidebar-brand-text,.sidebar-logo-container{margin:var(--sidebar-item-spacing-vertical) 0}.sidebar-logo{display:block;margin:0 auto;max-width:100%}.sidebar-search-container{align-items:center;background:var(--color-sidebar-search-background);display:flex;margin-top:var(--sidebar-search-space-above);position:relative}.sidebar-search-container:focus-within,.sidebar-search-container:hover{background:var(--color-sidebar-search-background--focus)}.sidebar-search-container:before{background-color:var(--color-sidebar-search-icon);content:"";height:var(--sidebar-search-icon-size);left:var(--sidebar-item-spacing-horizontal);-webkit-mask-image:var(--icon-search);mask-image:var(--icon-search);position:absolute;width:var(--sidebar-search-icon-size)}.sidebar-search{background:transparent;border:none;border-bottom:1px solid var(--color-sidebar-search-border);border-top:1px solid var(--color-sidebar-search-border);box-sizing:border-box;color:var(--color-sidebar-search-foreground);padding:var(--sidebar-search-input-spacing-vertical) var(--sidebar-search-input-spacing-horizontal) var(--sidebar-search-input-spacing-vertical) calc(var(--sidebar-item-spacing-horizontal) + var(--sidebar-search-input-spacing-horizontal) + var(--sidebar-search-icon-size));width:100%;z-index:10}.sidebar-search:focus{outline:none}.sidebar-search::-moz-placeholder{font-size:var(--sidebar-search-input-font-size)}.sidebar-search::placeholder{font-size:var(--sidebar-search-input-font-size)}#searchbox .highlight-link{margin:0;padding:var(--sidebar-item-spacing-vertical) var(--sidebar-item-spacing-horizontal) 0;text-align:center}#searchbox .highlight-link a{color:var(--color-sidebar-search-icon);font-size:var(--font-size--small--2)}.sidebar-tree{font-size:var(--sidebar-item-font-size);margin-bottom:var(--sidebar-item-spacing-vertical);margin-top:var(--sidebar-tree-space-above)}.sidebar-tree ul{display:flex;flex-direction:column;list-style:none;margin-bottom:0;margin-top:0;padding:0}.sidebar-tree li{margin:0;position:relative}.sidebar-tree li>ul{margin-left:var(--sidebar-item-spacing-horizontal)}.sidebar-tree .icon,.sidebar-tree .reference{color:var(--color-sidebar-link-text)}.sidebar-tree .reference{box-sizing:border-box;display:inline-block;height:100%;line-height:var(--sidebar-item-line-height);overflow-wrap:anywhere;padding:var(--sidebar-item-spacing-vertical) var(--sidebar-item-spacing-horizontal);text-decoration:none;width:100%}.sidebar-tree .reference:hover{background:var(--color-sidebar-item-background--hover);color:var(--color-sidebar-link-text)}.sidebar-tree .reference.external:after{color:var(--color-sidebar-link-text);content:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' fill='none' stroke='%23607d8b' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' viewBox='0 0 24 24'%3E%3Cpath stroke='none' d='M0 0h24v24H0z'/%3E%3Cpath d='M11 7H6a2 2 0 0 0-2 2v9a2 2 0 0 0 2 2h9a2 2 0 0 0 2-2v-5M10 14 20 4M15 4h5v5'/%3E%3C/svg%3E");margin:0 .25rem;vertical-align:middle}.sidebar-tree .current-page>.reference{font-weight:700}.sidebar-tree label{align-items:center;cursor:pointer;display:flex;height:var(--sidebar-item-height);justify-content:center;position:absolute;right:0;top:0;-webkit-user-select:none;-moz-user-select:none;user-select:none;width:var(--sidebar-expander-width)}.sidebar-tree .caption,.sidebar-tree :not(.caption)>.caption-text{color:var(--color-sidebar-caption-text);font-size:var(--sidebar-caption-font-size);font-weight:700;margin:var(--sidebar-caption-space-above) 0 0 0;padding:var(--sidebar-item-spacing-vertical) var(--sidebar-item-spacing-horizontal);text-transform:uppercase}.sidebar-tree li.has-children>.reference{padding-right:var(--sidebar-expander-width)}.sidebar-tree .toctree-l1>.reference,.sidebar-tree .toctree-l1>label .icon{color:var(--color-sidebar-link-text--top-level)}.sidebar-tree label{background:var(--color-sidebar-item-expander-background)}.sidebar-tree label:hover{background:var(--color-sidebar-item-expander-background--hover)}.sidebar-tree .current>.reference{background:var(--color-sidebar-item-background--current)}.sidebar-tree .current>.reference:hover{background:var(--color-sidebar-item-background--hover)}.toctree-checkbox{display:none;position:absolute}.toctree-checkbox~ul{display:none}.toctree-checkbox~label .icon svg{transform:rotate(90deg)}.toctree-checkbox:checked~ul{display:block}.toctree-checkbox:checked~label .icon svg{transform:rotate(-90deg)}.toc-title-container{padding:var(--toc-title-padding);padding-top:var(--toc-spacing-vertical)}.toc-title{color:var(--color-toc-title-text);font-size:var(--toc-title-font-size);padding-left:var(--toc-spacing-horizontal);text-transform:uppercase}.no-toc{display:none}.toc-tree-container{padding-bottom:var(--toc-spacing-vertical)}.toc-tree{border-left:1px solid var(--color-background-border);font-size:var(--toc-font-size);line-height:1.3;padding-left:calc(var(--toc-spacing-horizontal) - var(--toc-item-spacing-horizontal))}.toc-tree>ul>li:first-child{padding-top:0}.toc-tree>ul>li:first-child>ul{padding-left:0}.toc-tree>ul>li:first-child>a{display:none}.toc-tree ul{list-style-type:none;margin-bottom:0;margin-top:0;padding-left:var(--toc-item-spacing-horizontal)}.toc-tree li{padding-top:var(--toc-item-spacing-vertical)}.toc-tree li.scroll-current>.reference{color:var(--color-toc-item-text--active);font-weight:700}.toc-tree a.reference{color:var(--color-toc-item-text);overflow-wrap:anywhere;text-decoration:none}.toc-scroll{max-height:100vh;overflow-y:scroll}.contents:not(.this-will-duplicate-information-and-it-is-still-useful-here){background:rgba(255,0,0,.25);color:var(--color-problematic)}.contents:not(.this-will-duplicate-information-and-it-is-still-useful-here):before{content:"ERROR: Adding a table of contents in Furo-based documentation is unnecessary, and does not work well with existing styling. Add a 'this-will-duplicate-information-and-it-is-still-useful-here' class, if you want an escape hatch."}.text-align\:left>p{text-align:left}.text-align\:center>p{text-align:center}.text-align\:right>p{text-align:right} +/*# sourceMappingURL=furo.css.map*/ \ No newline at end of file diff --git a/docs/_source/_build/html/_static/styles/furo.css.map b/docs/_source/_build/html/_static/styles/furo.css.map new file mode 100644 index 0000000..db1dec1 --- /dev/null +++ b/docs/_source/_build/html/_static/styles/furo.css.map @@ -0,0 +1 @@ +{"version":3,"file":"styles/furo.css","mappings":"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,CAJE,gBAEJ,CAHI,iBAMA,yFAKA,aACA,eACA,cCxaJ,iBAEE,aADA,iBACA,6BAEA,kCAEA,SACA,UAIA,gCACA,CALA,SAEA,SAEA,CAJA,wEAEA,CAFA,OAKA,CAGA,mDACE,iBAGF,gCACE,CADF,UACE,aAEJ,iCAEE,CAFF,UAEE,wCAEA,WACA,WADA,UACA,CACA,4CAGA,MACA,CADA,KACA,wCACA,UAGA,CAJA,UAIA,6DAUA,0CACE,CAFF,mBAEE,wEACA,CAVA,YACA,CAMF,mBAJE,OAOA,gBAJJ,gCACE,CANE,cACA,CAHA,oBACA,CAGA,QAGJ,CAII,0BACA,CADA,UACA,wCAEJ,kBACE,0DACA,gCACE,kBACA,CADA,YACA,oEACA,2CAMF,mDAII,CALN,YACE,CANE,cAKJ,CACE,iBAII,kEACA,yCACE,kDACA,yDACE,+CACA,uBANN,CAMM,+BANN,uCACE,qDACA,4BAEE,mBADA,0CACA,CADA,qBACA,0DACE,wCACA,sGALJ,oCACA,sBACE,kBAFF,UAEE,2CACA,wFACE,cACA,kEANN,uBACE,iDACA,CADA,UACA,0DACE,wDAEE,iEACA,qEANN,sCACE,CAGE,iBAHF,gBAGE,qBACE,CAJJ,uBACA,gDACE,wDACA,6DAHF,2CACA,CADA,gBACA,eACE,CAGE,sBANN,8BACE,CAII,iBAFF,4DACA,WACE,YADF,uCACE,6EACA,2BANN,8CACE,kDACA,0CACE,8BACA,yFACE,sBACA,sFALJ,mEACA,sBACE,kEACA,6EACE,uCACA,kEALJ,qGAEE,kEACA,6EACE,uCACA,kEALJ,8CACA,uDACE,sEACA,2EACE,sCACA,iEALJ,mGACA,qCACE,oDACA,0DACE,6GACA,gDAGR,yDCvEA,sEACE,CACA,6GACE,gEACF,iGAIF,wFACE,qDAGA,mGAEE,2CAEF,4FACE,gCACF,wGACE,8DAEE,6FAIA,iJAKN,6GACE,gDAKF,yDACA,qCAGA,6BACA,kBACA,qDAKA,oCAEA,+DAGA,2CAGE,oDAIA,oEAEE,qBAEN,wDAEE,uCACE,kEAGJ,CACE,6CACA,uDAGF,CACE,mCAEF,yDAI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","sources":["webpack:///./node_modules/normalize.css/normalize.css","webpack:///./src/furo/assets/styles/base/_print.sass","webpack:///./src/furo/assets/styles/base/_screen-readers.sass","webpack:///./src/furo/assets/styles/base/_theme.sass","webpack:///./src/furo/assets/styles/variables/_fonts.scss","webpack:///./src/furo/assets/styles/variables/_spacing.scss","webpack:///./src/furo/assets/styles/variables/_icons.scss","webpack:///./src/furo/assets/styles/variables/_admonitions.scss","webpack:///./src/furo/assets/styles/variables/_colors.scss","webpack:///./src/furo/assets/styles/base/_typography.sass","webpack:///./src/furo/assets/styles/_scaffold.sass","webpack:///./src/furo/assets/styles/content/_admonitions.sass","webpack:///./src/furo/assets/styles/content/_api.sass","webpack:///./src/furo/assets/styles/content/_blocks.sass","webpack:///./src/furo/assets/styles/content/_captions.sass","webpack:///./src/furo/assets/styles/content/_code.sass","webpack:///./src/furo/assets/styles/content/_footnotes.sass","webpack:///./src/furo/assets/styles/content/_images.sass","webpack:///./src/furo/assets/styles/content/_indexes.sass","webpack:///./src/furo/assets/styles/content/_lists.sass","webpack:///./src/furo/assets/styles/content/_math.sass","webpack:///./src/furo/assets/styles/content/_misc.sass","webpack:///./src/furo/assets/styles/content/_rubrics.sass","webpack:///./src/furo/assets/styles/content/_sidebar.sass","webpack:///./src/furo/assets/styles/content/_tables.sass","webpack:///./src/furo/assets/styles/content/_target.sass","webpack:///./src/furo/assets/styles/content/_gui-labels.sass","webpack:///./src/furo/assets/styles/components/_footer.sass","webpack:///./src/furo/assets/styles/components/_sidebar.sass","webpack:///./src/furo/assets/styles/components/_table_of_contents.sass","webpack:///./src/furo/assets/styles/_shame.sass"],"sourcesContent":["/*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */\n\n/* Document\n ========================================================================== */\n\n/**\n * 1. Correct the line height in all browsers.\n * 2. Prevent adjustments of font size after orientation changes in iOS.\n */\n\nhtml {\n line-height: 1.15; /* 1 */\n -webkit-text-size-adjust: 100%; /* 2 */\n}\n\n/* Sections\n ========================================================================== */\n\n/**\n * Remove the margin in all browsers.\n */\n\nbody {\n margin: 0;\n}\n\n/**\n * Render the `main` element consistently in IE.\n */\n\nmain {\n display: block;\n}\n\n/**\n * Correct the font size and margin on `h1` elements within `section` and\n * `article` contexts in Chrome, Firefox, and Safari.\n */\n\nh1 {\n font-size: 2em;\n margin: 0.67em 0;\n}\n\n/* Grouping content\n ========================================================================== */\n\n/**\n * 1. Add the correct box sizing in Firefox.\n * 2. Show the overflow in Edge and IE.\n */\n\nhr {\n box-sizing: content-box; /* 1 */\n height: 0; /* 1 */\n overflow: visible; /* 2 */\n}\n\n/**\n * 1. Correct the inheritance and scaling of font size in all browsers.\n * 2. Correct the odd `em` font sizing in all browsers.\n */\n\npre {\n font-family: monospace, monospace; /* 1 */\n font-size: 1em; /* 2 */\n}\n\n/* Text-level semantics\n ========================================================================== */\n\n/**\n * Remove the gray background on active links in IE 10.\n */\n\na {\n background-color: transparent;\n}\n\n/**\n * 1. Remove the bottom border in Chrome 57-\n * 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari.\n */\n\nabbr[title] {\n border-bottom: none; /* 1 */\n text-decoration: underline; /* 2 */\n text-decoration: underline dotted; /* 2 */\n}\n\n/**\n * Add the correct font weight in Chrome, Edge, and Safari.\n */\n\nb,\nstrong {\n font-weight: bolder;\n}\n\n/**\n * 1. Correct the inheritance and scaling of font size in all browsers.\n * 2. Correct the odd `em` font sizing in all browsers.\n */\n\ncode,\nkbd,\nsamp {\n font-family: monospace, monospace; /* 1 */\n font-size: 1em; /* 2 */\n}\n\n/**\n * Add the correct font size in all browsers.\n */\n\nsmall {\n font-size: 80%;\n}\n\n/**\n * Prevent `sub` and `sup` elements from affecting the line height in\n * all browsers.\n */\n\nsub,\nsup {\n font-size: 75%;\n line-height: 0;\n position: relative;\n vertical-align: baseline;\n}\n\nsub {\n bottom: -0.25em;\n}\n\nsup {\n top: -0.5em;\n}\n\n/* Embedded content\n ========================================================================== */\n\n/**\n * Remove the border on images inside links in IE 10.\n */\n\nimg {\n border-style: none;\n}\n\n/* Forms\n ========================================================================== */\n\n/**\n * 1. Change the font styles in all browsers.\n * 2. Remove the margin in Firefox and Safari.\n */\n\nbutton,\ninput,\noptgroup,\nselect,\ntextarea {\n font-family: inherit; /* 1 */\n font-size: 100%; /* 1 */\n line-height: 1.15; /* 1 */\n margin: 0; /* 2 */\n}\n\n/**\n * Show the overflow in IE.\n * 1. Show the overflow in Edge.\n */\n\nbutton,\ninput { /* 1 */\n overflow: visible;\n}\n\n/**\n * Remove the inheritance of text transform in Edge, Firefox, and IE.\n * 1. Remove the inheritance of text transform in Firefox.\n */\n\nbutton,\nselect { /* 1 */\n text-transform: none;\n}\n\n/**\n * Correct the inability to style clickable types in iOS and Safari.\n */\n\nbutton,\n[type=\"button\"],\n[type=\"reset\"],\n[type=\"submit\"] {\n -webkit-appearance: button;\n}\n\n/**\n * Remove the inner border and padding in Firefox.\n */\n\nbutton::-moz-focus-inner,\n[type=\"button\"]::-moz-focus-inner,\n[type=\"reset\"]::-moz-focus-inner,\n[type=\"submit\"]::-moz-focus-inner {\n border-style: none;\n padding: 0;\n}\n\n/**\n * Restore the focus styles unset by the previous rule.\n */\n\nbutton:-moz-focusring,\n[type=\"button\"]:-moz-focusring,\n[type=\"reset\"]:-moz-focusring,\n[type=\"submit\"]:-moz-focusring {\n outline: 1px dotted ButtonText;\n}\n\n/**\n * Correct the padding in Firefox.\n */\n\nfieldset {\n padding: 0.35em 0.75em 0.625em;\n}\n\n/**\n * 1. Correct the text wrapping in Edge and IE.\n * 2. Correct the color inheritance from `fieldset` elements in IE.\n * 3. Remove the padding so developers are not caught out when they zero out\n * `fieldset` elements in all browsers.\n */\n\nlegend {\n box-sizing: border-box; /* 1 */\n color: inherit; /* 2 */\n display: table; /* 1 */\n max-width: 100%; /* 1 */\n padding: 0; /* 3 */\n white-space: normal; /* 1 */\n}\n\n/**\n * Add the correct vertical alignment in Chrome, Firefox, and Opera.\n */\n\nprogress {\n vertical-align: baseline;\n}\n\n/**\n * Remove the default vertical scrollbar in IE 10+.\n */\n\ntextarea {\n overflow: auto;\n}\n\n/**\n * 1. Add the correct box sizing in IE 10.\n * 2. Remove the padding in IE 10.\n */\n\n[type=\"checkbox\"],\n[type=\"radio\"] {\n box-sizing: border-box; /* 1 */\n padding: 0; /* 2 */\n}\n\n/**\n * Correct the cursor style of increment and decrement buttons in Chrome.\n */\n\n[type=\"number\"]::-webkit-inner-spin-button,\n[type=\"number\"]::-webkit-outer-spin-button {\n height: auto;\n}\n\n/**\n * 1. Correct the odd appearance in Chrome and Safari.\n * 2. Correct the outline style in Safari.\n */\n\n[type=\"search\"] {\n -webkit-appearance: textfield; /* 1 */\n outline-offset: -2px; /* 2 */\n}\n\n/**\n * Remove the inner padding in Chrome and Safari on macOS.\n */\n\n[type=\"search\"]::-webkit-search-decoration {\n -webkit-appearance: none;\n}\n\n/**\n * 1. Correct the inability to style clickable types in iOS and Safari.\n * 2. Change font properties to `inherit` in Safari.\n */\n\n::-webkit-file-upload-button {\n -webkit-appearance: button; /* 1 */\n font: inherit; /* 2 */\n}\n\n/* Interactive\n ========================================================================== */\n\n/*\n * Add the correct display in Edge, IE 10+, and Firefox.\n */\n\ndetails {\n display: block;\n}\n\n/*\n * Add the correct display in all browsers.\n */\n\nsummary {\n display: list-item;\n}\n\n/* Misc\n ========================================================================== */\n\n/**\n * Add the correct display in IE 10+.\n */\n\ntemplate {\n display: none;\n}\n\n/**\n * Add the correct display in IE 10.\n */\n\n[hidden] {\n display: none;\n}\n","// This file contains styles for managing print media.\n\n////////////////////////////////////////////////////////////////////////////////\n// Hide elements not relevant to print media.\n////////////////////////////////////////////////////////////////////////////////\n@media print\n // Hide icon container.\n .content-icon-container\n display: none !important\n\n // Hide showing header links if hovering over when printing.\n .headerlink\n display: none !important\n\n // Hide mobile header.\n .mobile-header\n display: none !important\n\n // Hide navigation links.\n .related-pages\n display: none !important\n\n////////////////////////////////////////////////////////////////////////////////\n// Tweaks related to decolorization.\n////////////////////////////////////////////////////////////////////////////////\n@media print\n // Apply a border around code which no longer have a color background.\n .highlight\n border: 0.1pt solid var(--color-foreground-border)\n\n////////////////////////////////////////////////////////////////////////////////\n// Avoid page break in some relevant cases.\n////////////////////////////////////////////////////////////////////////////////\n@media print\n ul, ol, dl, a, table, pre, blockquote, p\n page-break-inside: avoid\n\n h1, h2, h3, h4, h5, h6, img, figure, caption\n page-break-inside: avoid\n page-break-after: avoid\n\n ul, ol, dl\n page-break-before: avoid\n",".visually-hidden\n position: absolute !important\n width: 1px !important\n height: 1px !important\n padding: 0 !important\n margin: -1px !important\n overflow: hidden !important\n clip: rect(0,0,0,0) !important\n white-space: nowrap !important\n border: 0 !important\n color: var(--color-foreground-primary)\n background: var(--color-background-primary)\n\n:-moz-focusring\n outline: auto\n","// This file serves as the \"skeleton\" of the theming logic.\n//\n// This contains the bulk of the logic for handling dark mode, color scheme\n// toggling and the handling of color-scheme-specific hiding of elements.\n\n@use \"../variables\" as *\n\nbody\n @include fonts\n @include spacing\n @include icons\n @include admonitions\n @include default-admonition(#651fff, \"abstract\")\n @include default-topic(#14B8A6, \"pencil\")\n\n @include colors\n\n.only-light\n display: block !important\nhtml body .only-dark\n display: none !important\n\n// Ignore dark-mode hints if print media.\n@media not print\n // Enable dark-mode, if requested.\n body[data-theme=\"dark\"]\n @include colors-dark\n\n html & .only-light\n display: none !important\n .only-dark\n display: block !important\n\n // Enable dark mode, unless explicitly told to avoid.\n @media (prefers-color-scheme: dark)\n body:not([data-theme=\"light\"])\n @include colors-dark\n\n html & .only-light\n display: none !important\n .only-dark\n display: block !important\n\n//\n// Theme toggle presentation\n//\nbody[data-theme=\"auto\"]\n .theme-toggle svg.theme-icon-when-auto-light\n display: block\n\n @media (prefers-color-scheme: dark)\n .theme-toggle svg.theme-icon-when-auto-dark\n display: block\n .theme-toggle svg.theme-icon-when-auto-light\n display: none\n\nbody[data-theme=\"dark\"]\n .theme-toggle svg.theme-icon-when-dark\n display: block\n\nbody[data-theme=\"light\"]\n .theme-toggle svg.theme-icon-when-light\n display: block\n","// Fonts used by this theme.\n//\n// There are basically two things here -- using the system font stack and\n// defining sizes for various elements in %ages. We could have also used `em`\n// but %age is easier to reason about for me.\n\n@mixin fonts {\n // These are adapted from https://systemfontstack.com/\n --font-stack:\n -apple-system, BlinkMacSystemFont, Segoe UI, Helvetica, Arial, sans-serif,\n Apple Color Emoji, Segoe UI Emoji;\n --font-stack--monospace:\n \"SFMono-Regular\", Menlo, Consolas, Monaco, Liberation Mono, Lucida Console,\n monospace;\n --font-stack--headings: var(--font-stack);\n\n --font-size--normal: 100%;\n --font-size--small: 87.5%;\n --font-size--small--2: 81.25%;\n --font-size--small--3: 75%;\n --font-size--small--4: 62.5%;\n\n // Sidebar\n --sidebar-caption-font-size: var(--font-size--small--2);\n --sidebar-item-font-size: var(--font-size--small);\n --sidebar-search-input-font-size: var(--font-size--small);\n\n // Table of Contents\n --toc-font-size: var(--font-size--small--3);\n --toc-font-size--mobile: var(--font-size--normal);\n --toc-title-font-size: var(--font-size--small--4);\n\n // Admonitions\n //\n // These aren't defined in terms of %ages, since nesting these is permitted.\n --admonition-font-size: 0.8125rem;\n --admonition-title-font-size: 0.8125rem;\n\n // Code\n --code-font-size: var(--font-size--small--2);\n\n // API\n --api-font-size: var(--font-size--small);\n}\n","// Spacing for various elements on the page\n//\n// If the user wants to tweak things in a certain way, they are permitted to.\n// They also have to deal with the consequences though!\n\n@mixin spacing {\n // Header!\n --header-height: calc(\n var(--sidebar-item-line-height) + 4 *\n #{var(--sidebar-item-spacing-vertical)}\n );\n --header-padding: 0.5rem;\n\n // Sidebar\n --sidebar-tree-space-above: 1.5rem;\n --sidebar-caption-space-above: 1rem;\n\n --sidebar-item-line-height: 1rem;\n --sidebar-item-spacing-vertical: 0.5rem;\n --sidebar-item-spacing-horizontal: 1rem;\n --sidebar-item-height: calc(\n var(--sidebar-item-line-height) + 2 *#{var(--sidebar-item-spacing-vertical)}\n );\n\n --sidebar-expander-width: var(--sidebar-item-height); // be square\n\n --sidebar-search-space-above: 0.5rem;\n --sidebar-search-input-spacing-vertical: 0.5rem;\n --sidebar-search-input-spacing-horizontal: 0.5rem;\n --sidebar-search-input-height: 1rem;\n --sidebar-search-icon-size: var(--sidebar-search-input-height);\n\n // Table of Contents\n --toc-title-padding: 0.25rem 0;\n --toc-spacing-vertical: 1.5rem;\n --toc-spacing-horizontal: 1.5rem;\n --toc-item-spacing-vertical: 0.4rem;\n --toc-item-spacing-horizontal: 1rem;\n}\n","// Expose theme icons as CSS variables.\n\n$icons: (\n // Adapted from tabler-icons\n // url: https://tablericons.com/\n \"search\":\n url('data:image/svg+xml;charset=utf-8,'),\n // Factored out from mkdocs-material on 24-Aug-2020.\n // url: https://squidfunk.github.io/mkdocs-material/reference/admonitions/\n \"pencil\":\n url('data:image/svg+xml;charset=utf-8,'),\n \"abstract\":\n url('data:image/svg+xml;charset=utf-8,'),\n \"info\":\n url('data:image/svg+xml;charset=utf-8,'),\n \"flame\":\n url('data:image/svg+xml;charset=utf-8,'),\n \"question\":\n url('data:image/svg+xml;charset=utf-8,'),\n \"warning\":\n url('data:image/svg+xml;charset=utf-8,'),\n \"failure\":\n url('data:image/svg+xml;charset=utf-8,'),\n \"spark\":\n url('data:image/svg+xml;charset=utf-8,')\n);\n\n@mixin icons {\n @each $name, $glyph in $icons {\n --icon-#{$name}: #{$glyph};\n }\n}\n","@use \"sass:list\";\n// Admonitions\n\n// Structure of these is:\n// admonition-class: color \"icon-name\";\n//\n// The colors are translated into CSS variables below. The icons are\n// used directly in the main declarations to set the `mask-image` in\n// the title.\n\n// prettier-ignore\n$admonitions: (\n // Each of these has an reST directives for it.\n \"caution\": #ff9100 \"spark\",\n \"warning\": #ff9100 \"warning\",\n \"danger\": #ff5252 \"spark\",\n \"attention\": #ff5252 \"warning\",\n \"error\": #ff5252 \"failure\",\n \"hint\": #00c852 \"question\",\n \"tip\": #00c852 \"info\",\n \"important\": #00bfa5 \"flame\",\n \"note\": #00b0ff \"pencil\",\n \"seealso\": #448aff \"info\",\n \"admonition-todo\": #808080 \"pencil\"\n);\n\n@mixin default-admonition($color, $icon-name) {\n --color-admonition-title: #{$color};\n --color-admonition-title-background: #{rgba($color, 0.2)};\n\n --icon-admonition-default: var(--icon-#{$icon-name});\n}\n\n@mixin default-topic($color, $icon-name) {\n --color-topic-title: #{$color};\n --color-topic-title-background: #{rgba($color, 0.2)};\n\n --icon-topic-default: var(--icon-#{$icon-name});\n}\n\n@mixin admonitions {\n @each $name, $values in $admonitions {\n --color-admonition-title--#{$name}: #{list.nth($values, 1)};\n --color-admonition-title-background--#{$name}: #{rgba(\n list.nth($values, 1),\n 0.2\n )};\n }\n}\n","// Colors used throughout this theme.\n//\n// The aim is to give the user more control. Thus, instead of hard-coding colors\n// in various parts of the stylesheet, the approach taken is to define all\n// colors as CSS variables and reusing them in all the places.\n//\n// `colors-dark` depends on `colors` being included at a lower specificity.\n\n@mixin colors {\n --color-problematic: #b30000;\n\n // Base Colors\n --color-foreground-primary: black; // for main text and headings\n --color-foreground-secondary: #5a5c63; // for secondary text\n --color-foreground-muted: #6b6f76; // for muted text\n --color-foreground-border: #878787; // for content borders\n\n --color-background-primary: white; // for content\n --color-background-secondary: #f8f9fb; // for navigation + ToC\n --color-background-hover: #efeff4ff; // for navigation-item hover\n --color-background-hover--transparent: #efeff400;\n --color-background-border: #eeebee; // for UI borders\n --color-background-item: #ccc; // for \"background\" items (eg: copybutton)\n\n // Announcements\n --color-announcement-background: #000000dd;\n --color-announcement-text: #eeebee;\n\n // Brand colors\n --color-brand-primary: #0a4bff;\n --color-brand-content: #2757dd;\n --color-brand-visited: #872ee0;\n\n // API documentation\n --color-api-background: var(--color-background-hover--transparent);\n --color-api-background-hover: var(--color-background-hover);\n --color-api-overall: var(--color-foreground-secondary);\n --color-api-name: var(--color-problematic);\n --color-api-pre-name: var(--color-problematic);\n --color-api-paren: var(--color-foreground-secondary);\n --color-api-keyword: var(--color-foreground-primary);\n\n --color-api-added: #21632c;\n --color-api-added-border: #38a84d;\n --color-api-changed: #046172;\n --color-api-changed-border: #06a1bc;\n --color-api-deprecated: #605706;\n --color-api-deprecated-border: #f0d90f;\n --color-api-removed: #b30000;\n --color-api-removed-border: #ff5c5c;\n\n --color-highlight-on-target: #ffffcc;\n\n // Inline code background\n --color-inline-code-background: var(--color-background-secondary);\n\n // Highlighted text (search)\n --color-highlighted-background: #ddeeff;\n --color-highlighted-text: var(--color-foreground-primary);\n\n // GUI Labels\n --color-guilabel-background: #ddeeff80;\n --color-guilabel-border: #bedaf580;\n --color-guilabel-text: var(--color-foreground-primary);\n\n // Admonitions!\n --color-admonition-background: transparent;\n\n //////////////////////////////////////////////////////////////////////////////\n // Everything below this should be one of:\n // - var(...)\n // - *-gradient(...)\n // - special literal values (eg: transparent, none)\n //////////////////////////////////////////////////////////////////////////////\n\n // Tables\n --color-table-header-background: var(--color-background-secondary);\n --color-table-border: var(--color-background-border);\n\n // Cards\n --color-card-border: var(--color-background-secondary);\n --color-card-background: transparent;\n --color-card-marginals-background: var(--color-background-secondary);\n\n // Header\n --color-header-background: var(--color-background-primary);\n --color-header-border: var(--color-background-border);\n --color-header-text: var(--color-foreground-primary);\n\n // Sidebar (left)\n --color-sidebar-background: var(--color-background-secondary);\n --color-sidebar-background-border: var(--color-background-border);\n\n --color-sidebar-brand-text: var(--color-foreground-primary);\n --color-sidebar-caption-text: var(--color-foreground-muted);\n --color-sidebar-link-text: var(--color-foreground-secondary);\n --color-sidebar-link-text--top-level: var(--color-brand-primary);\n\n --color-sidebar-item-background: var(--color-sidebar-background);\n --color-sidebar-item-background--current: var(\n --color-sidebar-item-background\n );\n --color-sidebar-item-background--hover: linear-gradient(\n 90deg,\n var(--color-background-hover--transparent) 0%,\n var(--color-background-hover) var(--sidebar-item-spacing-horizontal),\n var(--color-background-hover) 100%\n );\n\n --color-sidebar-item-expander-background: transparent;\n --color-sidebar-item-expander-background--hover: var(\n --color-background-hover\n );\n\n --color-sidebar-search-text: var(--color-foreground-primary);\n --color-sidebar-search-background: var(--color-background-secondary);\n --color-sidebar-search-background--focus: var(--color-background-primary);\n --color-sidebar-search-border: var(--color-background-border);\n --color-sidebar-search-icon: var(--color-foreground-muted);\n\n // Table of Contents (right)\n --color-toc-background: var(--color-background-primary);\n --color-toc-title-text: var(--color-foreground-muted);\n --color-toc-item-text: var(--color-foreground-secondary);\n --color-toc-item-text--hover: var(--color-foreground-primary);\n --color-toc-item-text--active: var(--color-brand-primary);\n\n // Actual page contents\n --color-content-foreground: var(--color-foreground-primary);\n --color-content-background: transparent;\n\n // Links\n --color-link: var(--color-brand-content);\n --color-link-underline: var(--color-background-border);\n --color-link--hover: var(--color-brand-content);\n --color-link-underline--hover: var(--color-foreground-border);\n\n --color-link--visited: var(--color-brand-visited);\n --color-link-underline--visited: var(--color-background-border);\n --color-link--visited--hover: var(--color-brand-visited);\n --color-link-underline--visited--hover: var(--color-foreground-border);\n}\n\n@mixin colors-dark {\n --color-problematic: #ee5151;\n\n // Base Colors\n --color-foreground-primary: #cfd0d0; // for main text and headings\n --color-foreground-secondary: #9ca0a5; // for secondary text\n --color-foreground-muted: #81868d; // for muted text\n --color-foreground-border: #666666; // for content borders\n\n --color-background-primary: #131416; // for content\n --color-background-secondary: #1a1c1e; // for navigation + ToC\n --color-background-hover: #1e2124ff; // for navigation-item hover\n --color-background-hover--transparent: #1e212400;\n --color-background-border: #303335; // for UI borders\n --color-background-item: #444; // for \"background\" items (eg: copybutton)\n\n // Announcements\n --color-announcement-background: #000000dd;\n --color-announcement-text: #eeebee;\n\n // Brand colors\n --color-brand-primary: #3d94ff;\n --color-brand-content: #5ca5ff;\n --color-brand-visited: #b27aeb;\n\n // Highlighted text (search)\n --color-highlighted-background: #083563;\n\n // GUI Labels\n --color-guilabel-background: #08356380;\n --color-guilabel-border: #13395f80;\n\n // API documentation\n --color-api-keyword: var(--color-foreground-secondary);\n --color-highlight-on-target: #333300;\n\n --color-api-added: #3db854;\n --color-api-added-border: #267334;\n --color-api-changed: #09b0ce;\n --color-api-changed-border: #056d80;\n --color-api-deprecated: #b1a10b;\n --color-api-deprecated-border: #6e6407;\n --color-api-removed: #ff7575;\n --color-api-removed-border: #b03b3b;\n\n // Admonitions\n --color-admonition-background: #18181a;\n\n // Cards\n --color-card-border: var(--color-background-secondary);\n --color-card-background: #18181a;\n --color-card-marginals-background: var(--color-background-hover);\n}\n","// This file contains the styling for making the content throughout the page,\n// including fonts, paragraphs, headings and spacing among these elements.\n\nbody\n font-family: var(--font-stack)\npre,\ncode,\nkbd,\nsamp\n font-family: var(--font-stack--monospace)\n\n// Make fonts look slightly nicer.\nbody\n -webkit-font-smoothing: antialiased\n -moz-osx-font-smoothing: grayscale\n\n// Line height from Bootstrap 4.1\narticle\n line-height: 1.5\n\n//\n// Headings\n//\nh1,\nh2,\nh3,\nh4,\nh5,\nh6\n line-height: 1.25\n font-family: var(--font-stack--headings)\n font-weight: bold\n\n border-radius: 0.5rem\n margin-top: 0.5rem\n margin-bottom: 0.5rem\n margin-left: -0.5rem\n margin-right: -0.5rem\n padding-left: 0.5rem\n padding-right: 0.5rem\n\n + p\n margin-top: 0\n\nh1\n font-size: 2.5em\n margin-top: 1.75rem\n margin-bottom: 1rem\nh2\n font-size: 2em\n margin-top: 1.75rem\nh3\n font-size: 1.5em\nh4\n font-size: 1.25em\nh5\n font-size: 1.125em\nh6\n font-size: 1em\n\nsmall\n opacity: 75%\n font-size: 80%\n\n// Paragraph\np\n margin-top: 0.5rem\n margin-bottom: 0.75rem\n\n// Horizontal rules\nhr.docutils\n height: 1px\n padding: 0\n margin: 2rem 0\n background-color: var(--color-background-border)\n border: 0\n\n.centered\n text-align: center\n\n// Links\na\n text-decoration: underline\n\n color: var(--color-link)\n text-decoration-color: var(--color-link-underline)\n\n &:visited\n color: var(--color-link--visited)\n text-decoration-color: var(--color-link-underline--visited)\n &:hover\n color: var(--color-link--visited--hover)\n text-decoration-color: var(--color-link-underline--visited--hover)\n\n &:hover\n color: var(--color-link--hover)\n text-decoration-color: var(--color-link-underline--hover)\n &.muted-link\n color: inherit\n &:hover\n color: var(--color-link--hover)\n text-decoration-color: var(--color-link-underline--hover)\n &:visited\n color: var(--color-link--visited--hover)\n text-decoration-color: var(--color-link-underline--visited--hover)\n","// This file contains the styles for the overall layouting of the documentation\n// skeleton, including the responsive changes as well as sidebar toggles.\n//\n// This is implemented as a mobile-last design, which isn't ideal, but it is\n// reasonably good-enough and I got pretty tired by the time I'd finished this\n// to move the rules around to fix this. Shouldn't take more than 3-4 hours,\n// if you know what you're doing tho.\n\n// HACK: Not all browsers account for the scrollbar width in media queries.\n// This results in horizontal scrollbars in the breakpoint where we go\n// from displaying everything to hiding the ToC. We accomodate for this by\n// adding a bit of padding to the TOC drawer, disabling the horizontal\n// scrollbar and allowing the scrollbars to cover the padding.\n// https://www.456bereastreet.com/archive/201301/media_query_width_and_vertical_scrollbars/\n\n// HACK: Always having the scrollbar visible, prevents certain browsers from\n// causing the content to stutter horizontally between taller-than-viewport and\n// not-taller-than-viewport pages.\n@use \"variables\" as *\n\nhtml\n overflow-x: hidden\n overflow-y: scroll\n scroll-behavior: smooth\n\n.sidebar-scroll, .toc-scroll, article[role=main] *\n scrollbar-width: thin\n scrollbar-color: var(--color-foreground-border) transparent\n\n//\n// Overalls\n//\nhtml,\nbody\n height: 100%\n color: var(--color-foreground-primary)\n background: var(--color-background-primary)\n\n.skip-to-content\n position: fixed\n padding: 1rem\n border-radius: 1rem\n left: 0.25rem\n top: 0.25rem\n z-index: 40\n background: var(--color-background-primary)\n color: var(--color-foreground-primary)\n\n transform: translateY(-200%)\n transition: transform 300ms ease-in-out\n\n &:focus-within\n transform: translateY(0%)\n\narticle\n color: var(--color-content-foreground)\n background: var(--color-content-background)\n overflow-wrap: break-word\n\n.page\n display: flex\n // fill the viewport for pages with little content.\n min-height: 100%\n\n.mobile-header\n width: 100%\n height: var(--header-height)\n background-color: var(--color-header-background)\n color: var(--color-header-text)\n border-bottom: 1px solid var(--color-header-border)\n\n // Looks like sub-script/super-script have this, and we need this to\n // be \"on top\" of those.\n z-index: 10\n\n // We don't show the header on large screens.\n display: none\n\n // Add shadow when scrolled\n &.scrolled\n border-bottom: none\n box-shadow: 0 0 0.2rem rgba(0, 0, 0, 0.1), 0 0.2rem 0.4rem rgba(0, 0, 0, 0.2)\n\n .header-center\n a\n color: var(--color-header-text)\n text-decoration: none\n\n.main\n display: flex\n flex: 1\n\n// Sidebar (left) also covers the entire left portion of screen.\n.sidebar-drawer\n box-sizing: border-box\n\n border-right: 1px solid var(--color-sidebar-background-border)\n background: var(--color-sidebar-background)\n\n display: flex\n justify-content: flex-end\n // These next two lines took me two days to figure out.\n width: calc((100% - #{$full-width}) / 2 + #{$sidebar-width})\n min-width: $sidebar-width\n\n// Scroll-along sidebars\n.sidebar-container,\n.toc-drawer\n box-sizing: border-box\n width: $sidebar-width\n\n.toc-drawer\n background: var(--color-toc-background)\n // See HACK described on top of this document\n padding-right: 1rem\n\n.sidebar-sticky,\n.toc-sticky\n position: sticky\n top: 0\n height: min(100%, 100vh)\n height: 100vh\n\n display: flex\n flex-direction: column\n\n.sidebar-scroll,\n.toc-scroll\n flex-grow: 1\n flex-shrink: 1\n\n overflow: auto\n scroll-behavior: smooth\n\n// Central items.\n.content\n padding: 0 $content-padding\n width: $content-width\n\n display: flex\n flex-direction: column\n justify-content: space-between\n\n.icon\n display: inline-block\n height: 1rem\n width: 1rem\n svg\n width: 100%\n height: 100%\n\n//\n// Accommodate announcement banner\n//\n.announcement\n background-color: var(--color-announcement-background)\n color: var(--color-announcement-text)\n\n height: var(--header-height)\n display: flex\n align-items: center\n overflow-x: auto\n & + .page\n min-height: calc(100% - var(--header-height))\n\n.announcement-content\n box-sizing: border-box\n padding: 0.5rem\n min-width: 100%\n white-space: nowrap\n text-align: center\n\n a\n color: var(--color-announcement-text)\n text-decoration-color: var(--color-announcement-text)\n\n &:hover\n color: var(--color-announcement-text)\n text-decoration-color: var(--color-link--hover)\n\n////////////////////////////////////////////////////////////////////////////////\n// Toggles for theme\n////////////////////////////////////////////////////////////////////////////////\n.no-js .theme-toggle-container // don't show theme toggle if there's no JS\n display: none\n\n.theme-toggle-container\n display: flex\n\n.theme-toggle\n display: flex\n cursor: pointer\n border: none\n padding: 0\n background: transparent\n\n.theme-toggle svg\n height: 1.25rem\n width: 1.25rem\n color: var(--color-foreground-primary)\n display: none\n\n.theme-toggle-header\n display: flex\n align-items: center\n justify-content: center\n\n////////////////////////////////////////////////////////////////////////////////\n// Toggles for elements\n////////////////////////////////////////////////////////////////////////////////\n.toc-overlay-icon, .nav-overlay-icon\n display: none\n cursor: pointer\n\n .icon\n color: var(--color-foreground-secondary)\n height: 1.5rem\n width: 1.5rem\n\n.toc-header-icon, .nav-overlay-icon\n // for when we set display: flex\n justify-content: center\n align-items: center\n\n.toc-content-icon\n height: 1.5rem\n width: 1.5rem\n\n.content-icon-container\n float: right\n display: flex\n margin-top: 1.5rem\n margin-left: 1rem\n margin-bottom: 1rem\n gap: 0.5rem\n\n .edit-this-page, .view-this-page\n svg\n color: inherit\n height: 1.25rem\n width: 1.25rem\n\n.sidebar-toggle\n position: absolute\n display: none\n// \n.sidebar-toggle[name=\"__toc\"]\n left: 20px\n.sidebar-toggle:checked\n left: 40px\n// \n\n.overlay\n position: fixed\n top: 0\n width: 0\n height: 0\n\n transition: width 0ms, height 0ms, opacity 250ms ease-out\n\n opacity: 0\n background-color: rgba(0, 0, 0, 0.54)\n.sidebar-overlay\n z-index: 20\n.toc-overlay\n z-index: 40\n\n// Keep things on top and smooth.\n.sidebar-drawer\n z-index: 30\n transition: left 250ms ease-in-out\n.toc-drawer\n z-index: 50\n transition: right 250ms ease-in-out\n\n// Show the Sidebar\n#__navigation:checked\n & ~ .sidebar-overlay\n width: 100%\n height: 100%\n opacity: 1\n & ~ .page\n .sidebar-drawer\n top: 0\n left: 0\n // Show the toc sidebar\n#__toc:checked\n & ~ .toc-overlay\n width: 100%\n height: 100%\n opacity: 1\n & ~ .page\n .toc-drawer\n top: 0\n right: 0\n\n////////////////////////////////////////////////////////////////////////////////\n// Back to top\n////////////////////////////////////////////////////////////////////////////////\n.back-to-top\n text-decoration: none\n\n display: none\n position: fixed\n left: 0\n top: 1rem\n padding: 0.5rem\n padding-right: 0.75rem\n border-radius: 1rem\n font-size: 0.8125rem\n\n background: var(--color-background-primary)\n box-shadow: 0 0.2rem 0.5rem rgba(0, 0, 0, 0.05), #6b728080 0px 0px 1px 0px\n\n z-index: 10\n\n margin-left: 50%\n transform: translateX(-50%)\n svg\n height: 1rem\n width: 1rem\n fill: currentColor\n display: inline-block\n\n span\n margin-left: 0.25rem\n\n .show-back-to-top &\n display: flex\n align-items: center\n\n////////////////////////////////////////////////////////////////////////////////\n// Responsive layouting\n////////////////////////////////////////////////////////////////////////////////\n// Make things a bit bigger on bigger screens.\n@media (min-width: $full-width + $sidebar-width)\n html\n font-size: 110%\n\n@media (max-width: $full-width)\n // Collapse \"toc\" into the icon.\n .toc-content-icon\n display: flex\n .toc-drawer\n position: fixed\n height: 100vh\n top: 0\n right: -$sidebar-width\n border-left: 1px solid var(--color-background-muted)\n .toc-tree\n border-left: none\n font-size: var(--toc-font-size--mobile)\n\n // Accomodate for a changed content width.\n .sidebar-drawer\n width: calc((100% - #{$full-width - $sidebar-width}) / 2 + #{$sidebar-width})\n\n@media (max-width: $content-padded-width + $sidebar-width)\n // Center the page\n .content\n margin-left: auto\n margin-right: auto\n padding: 0 $content-padding--small\n\n@media (max-width: $content-padded-width--small + $sidebar-width)\n // Collapse \"navigation\".\n .nav-overlay-icon\n display: flex\n .sidebar-drawer\n position: fixed\n height: 100vh\n width: $sidebar-width\n\n top: 0\n left: -$sidebar-width\n\n // Swap which icon is visible.\n .toc-header-icon, .theme-toggle-header\n display: flex\n .toc-content-icon, .theme-toggle-content\n display: none\n\n // Show the header.\n .mobile-header\n position: sticky\n top: 0\n display: flex\n justify-content: space-between\n align-items: center\n\n .header-left,\n .header-right\n display: flex\n height: var(--header-height)\n padding: 0 var(--header-padding)\n label\n height: 100%\n width: 100%\n user-select: none\n\n .nav-overlay-icon .icon,\n .theme-toggle svg\n height: 1.5rem\n width: 1.5rem\n\n // Add a scroll margin for the content\n :target\n scroll-margin-top: calc(var(--header-height) + 2.5rem)\n\n // Show back-to-top below the header\n .back-to-top\n top: calc(var(--header-height) + 0.5rem)\n\n // Accommodate for the header.\n .page\n flex-direction: column\n justify-content: center\n\n@media (max-width: $content-width + 2* $content-padding--small)\n // Content should respect window limits.\n .content\n width: 100%\n overflow-x: auto\n\n@media (max-width: $content-width)\n article[role=main] aside.sidebar\n float: none\n width: 100%\n margin: 1rem 0\n","@use \"sass:list\"\n@use \"../variables\" as *\n\n// The design here is strongly inspired by mkdocs-material.\n.admonition, .topic\n margin: 1rem auto\n padding: 0 0.5rem 0.5rem 0.5rem\n\n background: var(--color-admonition-background)\n\n border-radius: 0.2rem\n box-shadow: 0 0.2rem 0.5rem rgba(0, 0, 0, 0.05), 0 0 0.0625rem rgba(0, 0, 0, 0.1)\n\n font-size: var(--admonition-font-size)\n\n overflow: hidden\n page-break-inside: avoid\n\n // First element should have no margin, since the title has it.\n > :nth-child(2)\n margin-top: 0\n\n // Last item should have no margin, since we'll control that w/ padding\n > :last-child\n margin-bottom: 0\n\n.admonition p.admonition-title,\np.topic-title\n position: relative\n margin: 0 -0.5rem 0.5rem\n padding-left: 2rem\n padding-right: .5rem\n padding-top: .4rem\n padding-bottom: .4rem\n\n font-weight: 500\n font-size: var(--admonition-title-font-size)\n line-height: 1.3\n\n // Our fancy icon\n &::before\n content: \"\"\n position: absolute\n left: 0.5rem\n width: 1rem\n height: 1rem\n\n// Default styles\np.admonition-title\n background-color: var(--color-admonition-title-background)\n &::before\n background-color: var(--color-admonition-title)\n mask-image: var(--icon-admonition-default)\n mask-repeat: no-repeat\n\np.topic-title\n background-color: var(--color-topic-title-background)\n &::before\n background-color: var(--color-topic-title)\n mask-image: var(--icon-topic-default)\n mask-repeat: no-repeat\n\n//\n// Variants\n//\n.admonition\n border-left: 0.2rem solid var(--color-admonition-title)\n\n @each $type, $value in $admonitions\n &.#{$type}\n border-left-color: var(--color-admonition-title--#{$type})\n > .admonition-title\n background-color: var(--color-admonition-title-background--#{$type})\n &::before\n background-color: var(--color-admonition-title--#{$type})\n mask-image: var(--icon-#{list.nth($value, 2)})\n\n.admonition-todo > .admonition-title\n text-transform: uppercase\n","// This file stylizes the API documentation (stuff generated by autodoc). It's\n// deeply nested due to how autodoc structures the HTML without enough classes\n// to select the relevant items.\n\n// API docs!\ndl[class]:not(.option-list):not(.field-list):not(.footnote):not(.glossary):not(.simple)\n // Tweak the spacing of all the things!\n dd\n margin-left: 2rem\n > :first-child\n margin-top: 0.125rem\n > :last-child\n margin-bottom: 0.75rem\n\n // This is used for the arguments\n .field-list\n margin-bottom: 0.75rem\n\n // \"Headings\" (like \"Parameters\" and \"Return\")\n > dt\n text-transform: uppercase\n font-size: var(--font-size--small)\n\n dd:empty\n margin-bottom: 0.5rem\n dd > ul\n margin-left: -1.2rem\n > li\n > p:nth-child(2)\n margin-top: 0\n // When the last-empty-paragraph follows a paragraph, it doesn't need\n // to augument the existing spacing.\n > p + p:last-child:empty\n margin-top: 0\n margin-bottom: 0\n\n // Colorize the elements\n > dt\n color: var(--color-api-overall)\n\n.sig:not(.sig-inline)\n font-weight: bold\n\n font-size: var(--api-font-size)\n font-family: var(--font-stack--monospace)\n\n margin-left: -0.25rem\n margin-right: -0.25rem\n padding-top: 0.25rem\n padding-bottom: 0.25rem\n padding-right: 0.5rem\n\n // These are intentionally em, to properly match the font size.\n padding-left: 3em\n text-indent: -2.5em\n\n border-radius: 0.25rem\n\n background: var(--color-api-background)\n transition: background 100ms ease-out\n\n &:hover\n background: var(--color-api-background-hover)\n\n // adjust the size of the [source] link on the right.\n a.reference\n .viewcode-link\n font-weight: normal\n width: 4.25rem\n\nem.property, span.property\n font-style: normal\n &:first-child\n color: var(--color-api-keyword)\n.sig-name\n color: var(--color-api-name)\n.sig-prename\n font-weight: normal\n color: var(--color-api-pre-name)\n.sig-paren\n color: var(--color-api-paren)\n.sig-param\n font-style: normal\n\ndiv.versionadded,\ndiv.versionchanged,\ndiv.deprecated,\ndiv.versionremoved\n border-left: 0.1875rem solid\n border-radius: 0.125rem\n\n padding-left: 0.75rem\n\n p\n margin-top: 0.125rem\n margin-bottom: 0.125rem\n\ndiv.versionadded\n border-color: var(--color-api-added-border)\n .versionmodified\n color: var(--color-api-added)\n\ndiv.versionchanged\n border-color: var(--color-api-changed-border)\n .versionmodified\n color: var(--color-api-changed)\n\ndiv.deprecated\n border-color: var(--color-api-deprecated-border)\n .versionmodified\n color: var(--color-api-deprecated)\n\ndiv.versionremoved\n border-color: var(--color-api-removed-border)\n .versionmodified\n color: var(--color-api-removed)\n\n// Align the [docs] and [source] to the right.\n.viewcode-link, .viewcode-back\n float: right\n text-align: right\n",".line-block\n margin-top: 0.5rem\n margin-bottom: 0.75rem\n .line-block\n margin-top: 0rem\n margin-bottom: 0rem\n padding-left: 1rem\n","// Captions\narticle p.caption,\ntable > caption,\n.code-block-caption\n font-size: var(--font-size--small)\n text-align: center\n\n// Caption above a TOCTree\n.toctree-wrapper.compound\n .caption, :not(.caption) > .caption-text\n font-size: var(--font-size--small)\n text-transform: uppercase\n\n text-align: initial\n margin-bottom: 0\n\n > ul\n margin-top: 0\n margin-bottom: 0\n","// Inline code\ncode.literal, .sig-inline\n background: var(--color-inline-code-background)\n border-radius: 0.2em\n // Make the font smaller, and use padding to recover.\n font-size: var(--font-size--small--2)\n padding: 0.1em 0.2em\n\n pre.literal-block &\n font-size: inherit\n padding: 0\n\n p &\n border: 1px solid var(--color-background-border)\n\n.sig-inline\n font-family: var(--font-stack--monospace)\n\n// Code and Literal Blocks\n$code-spacing-vertical: 0.625rem\n$code-spacing-horizontal: 0.875rem\n\n// Wraps every literal block + line numbers.\ndiv[class*=\" highlight-\"],\ndiv[class^=\"highlight-\"]\n margin: 1em 0\n display: flex\n\n .table-wrapper\n margin: 0\n padding: 0\n\npre\n margin: 0\n padding: 0\n overflow: auto\n\n // Needed to have more specificity than pygments' \"pre\" selector. :(\n article[role=\"main\"] .highlight &\n line-height: 1.5\n\n &.literal-block,\n .highlight &\n font-size: var(--code-font-size)\n padding: $code-spacing-vertical $code-spacing-horizontal\n\n // Make it look like all the other blocks.\n &.literal-block\n margin-top: 1rem\n margin-bottom: 1rem\n\n border-radius: 0.2rem\n background-color: var(--color-code-background)\n color: var(--color-code-foreground)\n\n// All code is always contained in this.\n.highlight\n width: 100%\n border-radius: 0.2rem\n\n // Make line numbers and prompts un-selectable.\n .gp, span.linenos\n user-select: none\n pointer-events: none\n\n // Expand the line-highlighting.\n .hll\n display: block\n margin-left: -$code-spacing-horizontal\n margin-right: -$code-spacing-horizontal\n padding-left: $code-spacing-horizontal\n padding-right: $code-spacing-horizontal\n\n/* Make code block captions be nicely integrated */\n.code-block-caption\n display: flex\n padding: $code-spacing-vertical $code-spacing-horizontal\n\n border-radius: 0.25rem\n border-bottom-left-radius: 0\n border-bottom-right-radius: 0\n font-weight: 300\n border-bottom: 1px solid\n\n background-color: var(--color-code-background)\n color: var(--color-code-foreground)\n border-color: var(--color-background-border)\n\n + div[class]\n margin-top: 0\n > .highlight\n border-top-left-radius: 0\n border-top-right-radius: 0\n\n// When `html_codeblock_linenos_style` is table.\n.highlighttable\n width: 100%\n display: block\n tbody\n display: block\n\n tr\n display: flex\n\n // Line numbers\n td.linenos\n background-color: var(--color-code-background)\n color: var(--color-code-foreground)\n padding: $code-spacing-vertical $code-spacing-horizontal\n padding-right: 0\n border-top-left-radius: 0.2rem\n border-bottom-left-radius: 0.2rem\n\n .linenodiv\n padding-right: $code-spacing-horizontal\n font-size: var(--code-font-size)\n box-shadow: -0.0625rem 0 var(--color-foreground-border) inset\n\n // Actual code\n td.code\n padding: 0\n display: block\n flex: 1\n overflow: hidden\n\n .highlight\n border-top-left-radius: 0\n border-bottom-left-radius: 0\n\n// When `html_codeblock_linenos_style` is inline.\n.highlight\n span.linenos\n display: inline-block\n padding-left: 0\n padding-right: $code-spacing-horizontal\n margin-right: $code-spacing-horizontal\n box-shadow: -0.0625rem 0 var(--color-foreground-border) inset\n","// Inline Footnote Reference\n.footnote-reference\n font-size: var(--font-size--small--4)\n vertical-align: super\n\n// Definition list, listing the content of each note.\n// docutils <= 0.17\ndl.footnote.brackets\n font-size: var(--font-size--small)\n color: var(--color-foreground-secondary)\n\n display: grid\n grid-template-columns: max-content auto\n dt\n margin: 0\n > .fn-backref\n margin-left: 0.25rem\n\n &:after\n content: \":\"\n\n .brackets\n &:before\n content: \"[\"\n &:after\n content: \"]\"\n\n dd\n margin: 0\n padding: 0 1rem\n\n// docutils >= 0.18\naside.footnote\n font-size: var(--font-size--small)\n color: var(--color-foreground-secondary)\n\naside.footnote > span,\ndiv.citation > span\n float: left\n font-weight: 500\n padding-right: 0.25rem\n\naside.footnote > *:not(span),\ndiv.citation > p\n margin-left: 2rem\n","//\n// Figures\n//\nimg\n box-sizing: border-box\n max-width: 100%\n height: auto\n\narticle\n figure, .figure\n border-radius: 0.2rem\n\n margin: 0\n :last-child\n margin-bottom: 0\n\n .align-left\n float: left\n clear: left\n margin: 0 1rem 1rem\n\n .align-right\n float: right\n clear: right\n margin: 0 1rem 1rem\n\n .align-default,\n .align-center\n display: block\n text-align: center\n margin-left: auto\n margin-right: auto\n\n // WELL, table needs to be stylised like a table.\n table.align-default\n display: table\n text-align: initial\n",".genindex-jumpbox, .domainindex-jumpbox\n border-top: 1px solid var(--color-background-border)\n border-bottom: 1px solid var(--color-background-border)\n padding: 0.25rem\n\n.genindex-section, .domainindex-section\n h2\n margin-top: 0.75rem\n margin-bottom: 0.5rem\n ul\n margin-top: 0\n margin-bottom: 0\n","ul,\nol\n padding-left: 1.2rem\n\n // Space lists out like paragraphs\n margin-top: 1rem\n margin-bottom: 1rem\n // reduce margins within li.\n li\n > p:first-child\n margin-top: 0.25rem\n margin-bottom: 0.25rem\n\n > p:last-child\n margin-top: 0.25rem\n\n > ul,\n > ol\n margin-top: 0.5rem\n margin-bottom: 0.5rem\n\nol\n &.arabic\n list-style: decimal\n &.loweralpha\n list-style: lower-alpha\n &.upperalpha\n list-style: upper-alpha\n &.lowerroman\n list-style: lower-roman\n &.upperroman\n list-style: upper-roman\n\n// Don't space lists out when they're \"simple\" or in a `.. toctree::`\n.simple,\n.toctree-wrapper\n li\n > ul,\n > ol\n margin-top: 0\n margin-bottom: 0\n\n// Definition Lists\n.field-list,\n.option-list,\ndl:not([class]),\ndl.simple,\ndl.footnote,\ndl.glossary\n dt\n font-weight: 500\n margin-top: 0.25rem\n + dt\n margin-top: 0\n\n .classifier::before\n content: \":\"\n margin-left: 0.2rem\n margin-right: 0.2rem\n\n dd\n > p:first-child,\n ul\n margin-top: 0.125rem\n\n ul\n margin-bottom: 0.125rem\n",".math-wrapper\n width: 100%\n overflow-x: auto\n\ndiv.math\n position: relative\n text-align: center\n\n .headerlink,\n &:focus .headerlink\n display: none\n\n &:hover .headerlink\n display: inline-block\n\n span.eqno\n position: absolute\n right: 0.5rem\n top: 50%\n transform: translate(0, -50%)\n z-index: 1\n","// Abbreviations\nabbr[title]\n cursor: help\n\n// \"Problematic\" content, as identified by Sphinx\n.problematic\n color: var(--color-problematic)\n\n// Keyboard / Mouse \"instructions\"\nkbd:not(.compound)\n margin: 0 0.2rem\n padding: 0 0.2rem\n border-radius: 0.2rem\n border: 1px solid var(--color-foreground-border)\n color: var(--color-foreground-primary)\n vertical-align: text-bottom\n\n font-size: var(--font-size--small--3)\n display: inline-block\n\n box-shadow: 0 0.0625rem 0 rgba(0, 0, 0, 0.2), inset 0 0 0 0.125rem var(--color-background-primary)\n\n background-color: var(--color-background-secondary)\n\n// Blockquote\nblockquote\n border-left: 4px solid var(--color-background-border)\n background: var(--color-background-secondary)\n\n margin-left: 0\n margin-right: 0\n padding: 0.5rem 1rem\n\n .attribution\n font-weight: 600\n text-align: right\n\n &.pull-quote,\n &.highlights\n font-size: 1.25em\n\n &.epigraph,\n &.pull-quote\n border-left-width: 0\n border-radius: 0.5rem\n\n &.highlights\n border-left-width: 0\n background: transparent\n\n// Center align embedded-in-text images\np .reference img\n vertical-align: middle\n","p.rubric\n line-height: 1.25\n font-weight: bold\n font-size: 1.125em\n\n // For Numpy-style documentation that's got rubrics within it.\n // https://github.com/pradyunsg/furo/discussions/505\n dd &\n line-height: inherit\n font-weight: inherit\n\n font-size: var(--font-size--small)\n text-transform: uppercase\n","article .sidebar\n float: right\n clear: right\n width: 30%\n\n margin-left: 1rem\n margin-right: 0\n\n border-radius: 0.2rem\n background-color: var(--color-background-secondary)\n border: var(--color-background-border) 1px solid\n\n > *\n padding-left: 1rem\n padding-right: 1rem\n\n > ul, > ol // lists need additional padding, because bullets.\n padding-left: 2.2rem\n\n .sidebar-title\n margin: 0\n padding: 0.5rem 1rem\n border-bottom: var(--color-background-border) 1px solid\n\n font-weight: 500\n\n// TODO: subtitle\n// TODO: dedicated variables?\n","[role=main] .table-wrapper.container\n width: 100%\n overflow-x: auto\n margin-top: 1rem\n margin-bottom: 0.5rem\n padding: 0.2rem 0.2rem 0.75rem\n\ntable.docutils\n border-radius: 0.2rem\n border-spacing: 0\n border-collapse: collapse\n\n box-shadow: 0 0.2rem 0.5rem rgba(0, 0, 0, 0.05), 0 0 0.0625rem rgba(0, 0, 0, 0.1)\n\n th\n background: var(--color-table-header-background)\n\n td,\n th\n // Space things out properly\n padding: 0 0.25rem\n\n // Get the borders looking just-right.\n border-left: 1px solid var(--color-table-border)\n border-right: 1px solid var(--color-table-border)\n border-bottom: 1px solid var(--color-table-border)\n\n p\n margin: 0.25rem\n\n &:first-child\n border-left: none\n &:last-child\n border-right: none\n\n // MyST-parser tables set these classes for control of column alignment\n &.text-left\n text-align: left\n &.text-right\n text-align: right\n &.text-center\n text-align: center\n","@use \"../variables\" as *\n\n:target\n scroll-margin-top: 2.5rem\n\n@media (max-width: $full-width - $sidebar-width)\n :target\n scroll-margin-top: calc(2.5rem + var(--header-height))\n\n // When a heading is selected\n section > span:target\n scroll-margin-top: calc(2.8rem + var(--header-height))\n\n// Permalinks\n.headerlink\n font-weight: 100\n user-select: none\n\nh1,\nh2,\nh3,\nh4,\nh5,\nh6,\ndl dt,\np.caption,\nfigcaption p,\ntable > caption,\n.code-block-caption\n > .headerlink\n margin-left: 0.5rem\n visibility: hidden\n &:hover > .headerlink\n visibility: visible\n\n // Don't change to link-like, if someone adds the contents directive.\n > .toc-backref\n color: inherit\n text-decoration-line: none\n\n// Figure and table captions are special.\nfigure:hover > figcaption > p > .headerlink,\ntable:hover > caption > .headerlink\n visibility: visible\n\n:target >, // Regular section[id] style anchors\nspan:target ~ // Non-regular span[id] style \"extra\" anchors\n h1,\n h2,\n h3,\n h4,\n h5,\n h6\n &:nth-of-type(1)\n background-color: var(--color-highlight-on-target)\n // .headerlink\n // visibility: visible\n code.literal\n background-color: transparent\n\ntable:target > caption,\nfigure:target\n background-color: var(--color-highlight-on-target)\n\n// Inline page contents\n.this-will-duplicate-information-and-it-is-still-useful-here li :target\n background-color: var(--color-highlight-on-target)\n\n// Code block permalinks\n.literal-block-wrapper:target .code-block-caption\n background-color: var(--color-highlight-on-target)\n\n// When a definition list item is selected\n//\n// There isn't really an alternative to !important here, due to the\n// high-specificity of API documentation's selector.\ndt:target\n background-color: var(--color-highlight-on-target) !important\n\n// When a footnote reference is selected\n.footnote > dt:target + dd,\n.footnote-reference:target\n background-color: var(--color-highlight-on-target)\n",".guilabel\n background-color: var(--color-guilabel-background)\n border: 1px solid var(--color-guilabel-border)\n color: var(--color-guilabel-text)\n\n padding: 0 0.3em\n border-radius: 0.5em\n font-size: 0.9em\n","// This file contains the styles used for stylizing the footer that's shown\n// below the content.\n@use \"../variables\" as *\n\nfooter\n font-size: var(--font-size--small)\n display: flex\n flex-direction: column\n\n margin-top: 2rem\n\n// Bottom of page information\n.bottom-of-page\n display: flex\n align-items: center\n justify-content: space-between\n\n margin-top: 1rem\n padding-top: 1rem\n padding-bottom: 1rem\n\n color: var(--color-foreground-secondary)\n border-top: 1px solid var(--color-background-border)\n\n line-height: 1.5\n\n @media (max-width: $content-width)\n text-align: center\n flex-direction: column-reverse\n gap: 0.25rem\n\n .left-details\n font-size: var(--font-size--small)\n\n .right-details\n display: flex\n flex-direction: column\n gap: 0.25rem\n text-align: right\n\n .icons\n display: flex\n justify-content: flex-end\n gap: 0.25rem\n font-size: 1rem\n\n a\n text-decoration: none\n\n svg,\n img\n font-size: 1.125rem\n height: 1em\n width: 1em\n\n// Next/Prev page information\n.related-pages\n a\n display: flex\n align-items: center\n\n text-decoration: none\n &:hover .page-info .title\n text-decoration: underline\n color: var(--color-link)\n text-decoration-color: var(--color-link-underline)\n\n svg.furo-related-icon,\n svg.furo-related-icon > use\n flex-shrink: 0\n\n color: var(--color-foreground-border)\n\n width: 0.75rem\n height: 0.75rem\n margin: 0 0.5rem\n\n &.next-page\n max-width: 50%\n\n float: right\n clear: right\n text-align: right\n\n &.prev-page\n max-width: 50%\n\n float: left\n clear: left\n\n svg\n transform: rotate(180deg)\n\n.page-info\n display: flex\n flex-direction: column\n overflow-wrap: anywhere\n\n .next-page &\n align-items: flex-end\n\n .context\n display: flex\n align-items: center\n\n padding-bottom: 0.1rem\n\n color: var(--color-foreground-muted)\n font-size: var(--font-size--small)\n text-decoration: none\n","// This file contains the styles for the contents of the left sidebar, which\n// contains the navigation tree, logo, search etc.\n\n////////////////////////////////////////////////////////////////////////////////\n// Brand on top of the scrollable tree.\n////////////////////////////////////////////////////////////////////////////////\n.sidebar-brand\n display: flex\n flex-direction: column\n flex-shrink: 0\n\n padding: var(--sidebar-item-spacing-vertical) var(--sidebar-item-spacing-horizontal)\n text-decoration: none\n\n.sidebar-brand-text\n color: var(--color-sidebar-brand-text)\n overflow-wrap: break-word\n margin: var(--sidebar-item-spacing-vertical) 0\n font-size: 1.5rem\n\n.sidebar-logo-container\n margin: var(--sidebar-item-spacing-vertical) 0\n\n.sidebar-logo\n margin: 0 auto\n display: block\n max-width: 100%\n\n////////////////////////////////////////////////////////////////////////////////\n// Search\n////////////////////////////////////////////////////////////////////////////////\n.sidebar-search-container\n display: flex\n align-items: center\n margin-top: var(--sidebar-search-space-above)\n\n position: relative\n\n background: var(--color-sidebar-search-background)\n &:hover,\n &:focus-within\n background: var(--color-sidebar-search-background--focus)\n\n &::before\n content: \"\"\n position: absolute\n left: var(--sidebar-item-spacing-horizontal)\n width: var(--sidebar-search-icon-size)\n height: var(--sidebar-search-icon-size)\n\n background-color: var(--color-sidebar-search-icon)\n mask-image: var(--icon-search)\n\n.sidebar-search\n box-sizing: border-box\n\n border: none\n border-top: 1px solid var(--color-sidebar-search-border)\n border-bottom: 1px solid var(--color-sidebar-search-border)\n\n padding-top: var(--sidebar-search-input-spacing-vertical)\n padding-bottom: var(--sidebar-search-input-spacing-vertical)\n padding-right: var(--sidebar-search-input-spacing-horizontal)\n padding-left: calc(var(--sidebar-item-spacing-horizontal) + var(--sidebar-search-input-spacing-horizontal) + var(--sidebar-search-icon-size))\n\n width: 100%\n\n color: var(--color-sidebar-search-foreground)\n background: transparent\n z-index: 10\n\n &:focus\n outline: none\n\n &::placeholder\n font-size: var(--sidebar-search-input-font-size)\n\n//\n// Hide Search Matches link\n//\n#searchbox .highlight-link\n padding: var(--sidebar-item-spacing-vertical) var(--sidebar-item-spacing-horizontal) 0\n margin: 0\n text-align: center\n\n a\n color: var(--color-sidebar-search-icon)\n font-size: var(--font-size--small--2)\n\n////////////////////////////////////////////////////////////////////////////////\n// Structure/Skeleton of the navigation tree (left)\n////////////////////////////////////////////////////////////////////////////////\n.sidebar-tree\n font-size: var(--sidebar-item-font-size)\n margin-top: var(--sidebar-tree-space-above)\n margin-bottom: var(--sidebar-item-spacing-vertical)\n\n ul\n padding: 0\n margin-top: 0\n margin-bottom: 0\n\n display: flex\n flex-direction: column\n\n list-style: none\n\n li\n position: relative\n margin: 0\n\n > ul\n margin-left: var(--sidebar-item-spacing-horizontal)\n\n .icon\n color: var(--color-sidebar-link-text)\n\n .reference\n box-sizing: border-box\n color: var(--color-sidebar-link-text)\n\n // Fill the parent.\n display: inline-block\n line-height: var(--sidebar-item-line-height)\n text-decoration: none\n\n // Don't allow long words to cause wrapping.\n overflow-wrap: anywhere\n\n height: 100%\n width: 100%\n\n padding: var(--sidebar-item-spacing-vertical) var(--sidebar-item-spacing-horizontal)\n\n &:hover\n color: var(--color-sidebar-link-text)\n background: var(--color-sidebar-item-background--hover)\n\n // Add a nice little \"external-link\" arrow here.\n &.external::after\n content: url('data:image/svg+xml,')\n margin: 0 0.25rem\n vertical-align: middle\n color: var(--color-sidebar-link-text)\n\n // Make the current page reference bold.\n .current-page > .reference\n font-weight: bold\n\n label\n position: absolute\n top: 0\n right: 0\n height: var(--sidebar-item-height)\n width: var(--sidebar-expander-width)\n\n cursor: pointer\n user-select: none\n\n display: flex\n justify-content: center\n align-items: center\n\n .caption, :not(.caption) > .caption-text\n font-size: var(--sidebar-caption-font-size)\n color: var(--color-sidebar-caption-text)\n\n font-weight: bold\n text-transform: uppercase\n\n margin: var(--sidebar-caption-space-above) 0 0 0\n padding: var(--sidebar-item-spacing-vertical) var(--sidebar-item-spacing-horizontal)\n\n // If it has children, add a bit more padding to wrap the content to avoid\n // overlapping with the

S*(W5XB=RhEpvaP+i*vGO;?8)=7jf@qu*{r9?11Y($pXGB=OqBZO ztYlnZu1Li*F5;H2anDj${ls-o#wi^aAoYtpwbVQr;6=R%!#UeYr2C!*`Tq_hR&|Bu zQGOng!J>cHMqlb)FI**#nZacas{XSKq<%to&6I#HWm}pQhHP? z_8D_%F)cS^Sk|Y$Q$sRjZ6@Y%d&k5uGy5BO)2+fR&+&f5`Uu)G*+wo)-tnESd22HG zDG_Mf;vAo2bY_SdyE7#~NaQa{BENjaW`G+NM3e^qvP~`h?2MhUs-VIhHcV0Z;m*D) ztEKV2G0!)<(l^v!D3bR=%eSm2s$!8|>>+u^uE>TvVPH%z1GH0cqUC(ly!)!! zG_cW^Gs*G^AXLl65;@97jMfJm;8_hpt#SzM53S)}=B(AOJMRTH&IL#9E-yT8x2h}W zT$q3V5Y%Lb9_vy6Jc@FluQydY{R|m2haL>~pYp5geJJ05Dpp@^O$(;c(dYP5{6DsQ zsdYt=_|G9P@+SNSj%0xe`7irOysr%#$EE^iU2X@Ue*PHUr`eV4(>$5)vtZA^*`t5C zy<0GivyNUzol0SG%4Y;;&&wGNbM38^oUQ2Znup+B|1s<4*+UjH0T$YE>@&TpM4-kO)$g$0vXcxTR-**w;EqyjOO)k$a`>&$#~AvrG8Vg_OL>1LAM zYUZ+@x4RYlPuHO;GK}0myzi+#Fg15}$^MGOQql&(^PsY14<}peqCOgdh)yoT=t~-z zAU$^^p_d$uwRZCn&B-arZ&`URJi%HdwJbFuT!3^JSt6w$#K zPHnzhw^C1zQsZ-;R!*M$!jTtsoEdu&NqDJQFY4HgeKf;<)svXfaMWWBq7V(IXK>@s zSNIcQ|6EHJNk8l#B|eqw)cn;a#_hFJ!-Y3%rc2D5#_`L{+p1*m4z0Fm?s0S9`#SQ4 zQ>eF?E0H@4#Es^l9rkbL0(3AuLq%I#bHN>@lxC_&trLUM?CoXVpk^s`O0s~S_4)pl zoA=--bEq6cU9@jUE}OjHv)`Dpus&ZAWzbD8oOH}X?;8(B?WT|rp{r<3(d|c(wmYr! z&W%D=j{xfPgXPDMmE!<&TG3!+61xnew&p{rFJ-cKf>ZM;l~5}$g2?xInfW=LnOE z8Wfygcc}tV=E9d_%hmKgsjS^IBaz>N#VZ*6_sPAwgbCS9{J}#Sb7Tu8g){o?F^-(Qe<$lr(LqB za+bnr_UowLBL#A5sq1oB<9&rnMV|CHBl)|v;i#w>xA*OjpQD&hosj}--fu+GSLFaYtq!R=ZD*bi73t*mHGbN5vrMHL?1 zX^y%~^bqI2&Z&__DinmU;+*oHvXWzXsb z<3?{D-7nUT2j<*C-3C-%B>~?Csb_bUrCu9s8WtOSATgOMM#EkCl1%u#V-v6`#LQ7-2&v>I0 zUZn62C%5FR&kybyUn&1s1f$~&Hk*&NmnpZ1w~FqWY<<2BZy%yGH3dk~nhN~{Y^(yL zFb)5=hh#e;V(;3TE)ytZ7FR^XPozaLu86?P5P%i#N-;7U+Kr_$jW`^VymBK=xWjWy z&GLFEb`)K>^2sRTsX^gggkMLaqdbi2!E?znFc7fHk&5O&>`8LDDVQwsSoa+$Yue%z-XkAV=T-rPOA`G=NeWWC9d^U#})gULUGlGFA!A3#Q zBf-ib=n)p0M>~po_5dyP#i{qr1i(-Q#%9;V)3xMP@Fv3C2RLPyod1F?`Soy0*S29C z?Bd>CK${oP@UQLk2E&$q>l5wpb)`LfK;s1}D`ZAFh%n{QZ+d+yG60F%Uz)?G)5q<7*VNg3X(tpyMX)lOAR4 zgvODQ0i1$kcvAx<^HWd-rEDNnQ@mBitaG;?Q)%G%NfggDu%JRDGFdrC4*?QbmhH{L z&`bAm>*fvC{sF16Wy{8M->6YzmTVbf+6Z|(I(aOeWo0nSabt%+$Qk}E$856cb6TVm87;NPLo zOoFGb6~VGvy^rEe$&aZWcUimt+Y0XcS%4zLtU>I^E7H@z9x8$V0!SZ(#iaq zyp4vQ<8S;>aJW7Vom}B^8r8uO-v_L6mFl4%LvQ8@MU~gBG2RY3Mf}_gZ2})NXV-ms zVJlnT_6GO6xn%fL_cvxmgw)ASFV+axIV^cqUsxu@wx&7HU|wimdEM`z=$azlzS}?6 zO2A6jvS-#8d9QHGY&Ym)cX!?`m#DYks)W#xOjI-6e_C1H@}&Y_eP}G?rOYE3X4#69 zDJh!nVUC5n!4uoqxgO&t6ZPWkf*L!SxBTUl6EYgR031l>fa!Q!eF$V zKZw#a^m+)tfq3yNY!Uydpjjy+iD=rS1R2z->R!tboP%i&5@-bE?^u>foExtJ-^c(_IiBBT`b~*L>YAthn1x6}4hmiI8tB)6p zLEXvt^6EE}6<6X$xAoa~JNvP0_9yPgw2Xu-!Q*R{Q5XfqMz!rr045l8BVM z?%fSNDm1|0AyO5d28*f7Fq}9G!Z604A!4Z@%#WQh%+~%UfpVgYO0yCv4iw;QRR^LU z#L&U>iJ0a`nIUtP#4QAwUxUKwFq9^lg!2?2$7Ioxf>K~@ytDrp1^J#T*gy#^_pFc- z>St-O<8k6z1B_!o`T!T%s-ixC*ow|or0!0R&}n4imT?pWXsWbK;SYT%smTgC(W!f? z!pB=QrousFeWp^_nhuosNoUEkSUTdQ@ul4)V4jR%#9JWymKJduSWi5Ise@&MSWa$qoji>d3mhKSEaKw2MOzV%LqZukYE5Kdp8QH;?vAZ zNukau?M$eZNS!pL&O&w1Bx`HOf#w+LNI8z2BjY>Ech_z#-wXk6Po9UQ!_%opZ5nqH zL{z81vnXHJbP?hE+VYr33%tpA6-_UM_U_X*P&JFdXw`csx7URuTo|BMYnC6MueiC- z4A!0P3{PeVe_%+w7aTE5cPT{S+ueS(6%zK11BhrMDS#6BiDSX%O-tD&vB${m)l`onKe! z(7PLDyUN@eHnl$iE#+m{WVP#9<%J277jVq(R6qT7lsnPuSK^%g)!dD^_OQ?C?Ux%p z&p^9Vr{jLEhUn4IQHVLzR~;lQs(wq+seKSRZwE*A0PBREb4wlX~8j1Z-xnuncz z2tcJCkzDKZ>loReDAAHq^Q5CyN+blW6GrIDL>RiL6TgpgO{E-nPJ`J=fWr}pRQyWX z3$(TIauB~tRnB6H00?f1ENznFT*pEw*~ROX+MyIT zk`DU__mc96TB}*+PXLBTAlaE@=Rd`ms9S?F7=c(>@2KV-!m!pSSEF504~bN}P%J>d z8*A1$vk~*$9@l2d32tqZ^O{s_Y)VO(@4Z&njBa=rHg>Mjs9Z|rsch06RyxRr#sFbB zvp2W}pke*gj0H^4IKvRbu_O)xDNSi}D(&(4mLtyyf0yI8M zJ>Gip3uwFd-!1C>ViGxwyM|05j;qrrp+ivFFX6dzAT(J_eaaevU{$0r;tgb6?lEsF z`aNTiIjr1^R&EgT8U0&4J>O(zb1HRQ1RB4#edPmJejpP@*0V_h`N8eGtIKPYyt{dG z`3@xpU~@W(+0nx_wj5=S(r!wTqi{H`;b-hCb&zo`0C`*E)7I3g9u!vtX`CN~b0o== zcZ854&n>6mU&gstym)x1i(iiT;$Z7!mrUM?72mx48rPf@jF64p@Jk5818Ei!HV1#O za`*ONgA7L`INB)2F=aZU@*2zNaI0%axMD78;T17os@y)JAhy(sAlMTAjZ2tWCUi;< zAtE^jDk3|?Fk@l%s=*jszC=ZYpN8Agq4PzDOH|lWN*=pHDeO!Z@lR}PO5*rgoNNK? zj^!^(faViUK%EmA%J^huXH19!W#NuIRCS`^LB4!$X2GDq2F-uFwKn4-n(qMENK zE<~#xjZd!oV-U=~TY-;)!Q)IiUdO{Af#P@Mep$*>L+S_0An{DEN})@|rC+UDv?^EU zwvg9FNe3dNoI=S`3UlK|hr>?|*DycL3K}DOert9m77E|=%4fbnYQRd+HQSlJ)877i z6loT{EFwp<^MxR3%Vr}btyZ~B4+cKwnaBiqZ#aAaxq-wGiDVB3|$Q>5a|pl z>#{lZUF#g4$fb62G}%eypaqqmnPaF_YYujPO_G(Ry{gwDc`_rpJqMlch4qMeX$BHZ zSYLOKns!z1OuPC=)1s;l>-XxjrXeVDCZ}%gF#oRUm@_Ro*qKP$`4S$QTaqt||2a(q za>|2t)NQ58R$?z&Rlc!l(c@le)cd<>*Xip@_Db5$J!{%0tP{4e-a3cVtGsC+HyvBY zx57=%Jv*a)I?C~pwnsi~`YiNXVye%yO$%Q(DeQ-fY#XKXqIYfI1$-QzT=2A+?d&b0 z!|bDIt?I@MRnO(+b*nBomcGWM1HUOJwo(jH8j84ip)OcS)$MKT6p_S)1UEJsXvmO@ zQg?@U+glqOj+0X63R3wn>6$U-2$$t3yWtXSI7dK?cE;l+<-n!;m z^hm1f@I$N=6M8FUa}wijojQXPUr>7NH*J@_j4_>}y{41pO|+5?7ec3So(BAkw4U@4-e z(j$9h^QN+Ze1;_mK-6}LrqTe6#W&G4F$9_{$`uG6MxWojxjJ}!0>`_xu97Pk<>!5} zHNEuVowe~B8c*6ZEr&6*+>3+X`vS$_>r3C~OqEe}N{vmJbMeH8Q@hlT*_Wb>O=Nta zFAKMVlE>0xXf9JVpjh>iq!IBs+mdflk0^!>BfK;ud{tGC;>rlPWvBdn`*VkK;kG50 zt+EQe4$((;wp_GVrAaK&_L~E*G4L7{(r+%Wt=+h`vaZcpk05AR#URzgw>Zhss-)=$^3_w{%e|37Ocy*6n! z0AzD901(o_@T-cdd+l4uoLft;Wf^eMx_S+}HNNB=7EEoyBXR-%(Fr$4T+;oBF-Mo$ zoBkqKBJLmw<*3-TbEiGW$j8&kP?~@9&HOe0>3=zoJ-;=4{`iH~g^DnJ$`Wb$>V|PG zF`e#m2zNqDabVp7LF4h{FQt@g_ZdJvrn#ubXgZ8UHFaO8n9{;DG4r)kRob-6vv5si z`smkK)#~|*gUevOKE-hR5k*S^GNjP zNR_4`BfBcqcL^KGA(SiR8%04vu8=yZzP1k)J0c|5ar>!}2{l%Uorg?2S~q6qKoh6s z@qUVw!>=v6Imx)m6ruoJeXYmXDL}YWM|q*XwBmUnys%7OOk4Ht2+GS>$q1xctA&Iw zrr+*Nk=K>!)|H3fpT7Qs?^CH#I=3P+h-cLMD`F=3_p1K=<)8coi3-9v2SuTXtH=3X zdk`c7s8QHfzdf2fq!b_YoF!7a;N)mqn_lMU5$YswT+i>8Sy3qDl;(R=xCz<(reqex zg62r{aq&X*ASDLr=*jj$r@%yOC`PKte0&z8i5M4lT^q@E@m?iTJjTcK2~vv3TdIAW z>f7r=Rm;(LmG;~}hgadyiQUe~9&Lsw!!jEsqRoIfCFZ!v1m8)HPx~M)*##X4Yl*T1 zY@F0jO8S(03Ujmn5OMRQ(Xiq_XTwc|$c8@@5Z_kRMTpXAJH^v%aR)D?!=;YaAzlpP zV>_H8Z)JpJ+b|me3_YlgxWk0)kqbdwVmdAlp%ae^X{70Oc$rQn;E24VPEDOIVX>E7 zU!u$s(ka*LTVO^F7|H9dc(v4wN)Oym33IVg)P#(IYItq`V7!A(az{Mk#ztk42lveb zmn6{CyImn>HzfYjHaQbfwi&t&LHE<%7}UD;80~I$=aCmFPiv+sujC}}0z_SzFpToX zT~%JdBkcoJ$i4ebl;x!=EDU&7eD>{xWmnNutg9!$U6yH7y-7U2WQxG)+w6Dj?C|Ac}#0;Or9UCz~AwA^h-N_Ul>A9@#Mf zzj7f*BimA+1XO&ma}pS00?e4ld9?lP3c{LPdDg?)-kXUmYD~^D>qe&rM$eA{s zUk|1LAP9D7awKARiGjr(V$z zC}^>4ZPh@;>x+YC94#y1!rZew*NP*lf0OWiRX#zIvQnc9>q{s%cgd&jf-nYt6j zajeRCnp0<^?&HT&gAGecfvPeyz%V;#O~x>W^qZUi`0?g82j6Dm7a zq5?u=3fna*`=OI+;_bir`BPjVvAkvwOw(ZWnBTvY444zSu(ZCe=9k;1oH3(=7PMFk+K9x@>|FgU%mw%RFLC!sAP~u& zSd|dD(a9^ZtXCFqQ=MJ83celBsd6UG7aCN86Q+c`tsU}NKbl}{lSYR&I^k^OVBiKETpB~cfD7zSEY*z?mQ5U27$EGq`ohz*y!DmvG zEG5xQ04r|nHS2u2hPk>}oKEW&uHz8VL|sA>uR>pHb2b!gEuHr`E#G&AsI9S0a~8?1 zpMc*qN?>mNsvjRS*|oZCJ=Dz09;AVs?}*5NR;hM|_yaQbP_)Wrx#4|?xY zH*W_OTvI-8pJjyO+a*-P6jSO=D&U#Ta?o+|VvbF*Mc~RIs%Jxvihs-3SN+c*XAS&w z!AG)Ao(UdY-|tQ$6n=oYUSzVWC=@XOOmQ(^j|!J-n(d9Y6`vg>#3huoNP&@GEtDwd zrRA|3ii%HPQGz5S&Z?%^x!$rRGYn}4c6)0=W;o&HzUgib6bKLfNmNI2S4djgBH&`C z)_lF_!jh@=Yn?kKDnGe#XZSmx+*?^1{_d@NX!&t+HD6mhh||u$Y&*D%wh_=DfwQicm1SvZdfl)+Kkz692LqO@o3&9RhN~9BtbH1 z{d8;+t_(f$6e~g66=`meF1aR^YmX*33rm3`$~u#a(a!+{ZT|fAF8|o1Kbz23S&`1R zkwfV~`L8_4*#*@HW)nWkF?H^KKB-`dGLp;U|Icv}xoT|kB_H1U;Ne$(8x8Dt(Z&gY z^Ln^203%Pjl^R8`*5_R4d@Igb)+AJRreyMDly7-72KqsB4v@w|ip3(fyIw1Nn zcFWc(Pi`-5!2HtH@6MZ^-Zc8kyuZDDgvQcYdK95rn41Kud6*5ry}TePqoTx~-2+qB zP|7@iEf|KaWv5j-1*xja!4%qTirbdV$usH+9jJbC<9t1Uwi8=x!@1N_?CNeeFVHMk zL>p&^nhiB>a{-CEJfG(iAY04=zhPSGt}W8S8!f7({xeF@AL$1UlC3H_BxCh7PTp6w z)bZ00K~8e`>rUO)+&$|K^TB+_)X%~fXr5VS=<2tCs+y*s@K`I%LWBQe<2C!nX6Va~ zId*QZZ`{vbqvdp%IAvqIa>RE``n5N&`Y_oC!K{2R#kVQ zow}}`%y!+e6(^ma1lrKVimw0vUTEcK28nEh&naIzcHy-FVz$@W-TsFU4u!`A8p_0Vfj;cJ9Re zl?!HOW1EE4cNFS8Q(YnVY?<}D&h3mn-%Evw91>=VF`W7&3Y(B+b35G3flh|R^th9*0!n#w70P8+o%caBF za;%WIv;U;I_*YXgn6y(r2G-`G~S)t!B9I4NCKI2Y)6_01rWqld^MH6j1FF(Xb_KrZ*# zUf&KFQ~c+X@w4-Gu1GKWkaPg&Di#`1U}OBnbwoJCne5DgmemEbHbk`gsdumeESgHC zSktJr!aos*rX5qQUUl%+ro#CgYS+eDW5_iaDO&Rm;A7u65RExr{x8AyI)dG7$lubzVDv@+D`Jg2NG!KWu(vwi-mbvh0KJZewztXikG`a6rJP-z-~ED@Sgn^d%J3)B>0~ zqm$%p83xu^2f~_SCFDf{1=1%hQ)VV7Je?mU3I6Le)RtaI`jH0a(JeNy3D=>S7nPF3 z)BK1F>}*9BQiXh-hFbe+Ki$xn@Z&EgUs3Cdwaiv&W(^6wVMs2ohPbcOP+N7DD*HwW`jjY;N^1mud{r81co(u>!nPZhOl)feTm?5l z^%)8!oJc70@ip>*cBh0+87sR9g!$E_U@vKk3sH#WG&6)2%3yrHsDmZu1>CCi%&3kM zHE{Ib)um1J7jn~KV@kQ7$zs}*TUGyK!<^L$;a3)=I2T>R##H{#&Jvn$dHjVUht=!J8aj=}t zO`MIpmt_S@ZrhEjm9iungMYM!IqQU^&yieCzTx2KAPoAdmHg}#@(l?hww3>gg-`** z*HY#81%y==KjQ%Bqn2s&-3Dd>b znQ$W!R6DhKchaSn+Fn~4%3cs`!l?~xY}mFIQ(wE9(g!)iWy*w0j0YY=gnX3{+gT1J z1lW!gHQ+7__BRM&-c=LxG5R`x=o8o?cIoTQYk}@w# zi8e4_%tlmgZ4P0)hCSp@e`-1t3(7e`v|9&KRLk+gB`?d)<42bsR4t1y6CIX6sum5~ zBaIq=SM4fIoZA*@JM*k+Uq!FdvihrP(`gqlWhS3=zO0kAb;*h85vSx3gnI#|HRY1i_SC>9}Yl{p2T98-+5zsORs-L%k_YB z+0f$SfBlW+zoWOmFh{%_UjH><&i%5$M$=8>0Cj;4SAjpbkZ zC7S+)kd-~jO1%6herfq{>E&NW380GA9Nf_^agvb}EL#1&Us`_io3#41j=1S)a^;)L zFVy5$XQFeW!N2;=! z{MXX}wZb;q^nQ8yd)6lQqJgEO&G&zK`EUO@`uVMVAtTN{|BY9;Rlbc6{_xK&|J(ZD zuXc565$4hGzx;E{TmRJWe|e;fG6T_n^_$=L#tE=&uTFqsd)Gc%|DbC+Uw&rq&ayUZ zc-orO;OGy2waQuGBYt@Zq*PDSzJ1yM(dYNR@eL9lECux=Mqu9@zU&;x@^9&22g$5N z;(1Peuy&lD$XCWPD~lMCmgIe15c%~t3ToqdBWEbWfYZp*J}768C*~P#Ln$|o2aqw9 zEhV@1`qt6zQ_tVxF%}^1$S@aKTf74$eJ0r-8PyMo$tY#{ zW11gb#<;cq6eppmw)gG9)$e6rqaO7e$ais5$$-YaJHGF8x9}~abOCAm$lu2ffQa$U zH-2H64c}H-t-T|q+Q5Z5lKYvVZw(Z`6WNp;8CLd;~P*1?PtoaVo98cPGEOep6x{m3S77>$VB@xXu*IaTZawH6-0D9$&YPN zn+oYA@mh(TGg69^Py+p{ZLdCU{5+#>Jgp5__#{A0RgRU_L3hByiI#}ac}qid_i|;h zMlqBPKA(DsC3iwwnGYhsIwl2tcK6ejhsu&tz5QKFdUB6hy?=j+Gk!`!CTJ{Pjom#l z5|oUD-Ul1r8WuoHd3ZQF&YNS~_2#TUi0zP472qOxFd=c50YNIDW@)Mx>{QbFU|`rF zccF!bmzx%zl8VUkE%c-;?~(@g3lK;5+*eo0WN`JJ@AM5_3=j794zE$xaXLPfYv)1! z0|&tKDTh(xQ1yq&5!L|*XYNbhg)g2o^IUR5q{yUXFHZ_%5Y`lAyKG=W#PI3(_+%W> zy(DFC5C*WMvUItl8v$&7KHgQf5C!N6>99O7sxE@NMp3()GX^TUNR0BB8K#>_cg4qk zDQoEV;I$6N*6I*@YgTthkTvD(g`XB|E&(Yxjl!3qe?TLpRCFX;$c;hc%Zy6ng)4rZ_#y-k^wYplv+u~&i4bW;3$U+z8 z_boY%2Lx~*j960wWq?Q-EoE_|gM$GhD*No5l?j+C-!9;@u{Tz+A(GaQ zNA3=;ofY<7m{U@uIYYq1p-*NwOo@<2yO1A~DW-FCQQC%DuUp%bwe%;ob?jrx%a4pm z2=RKAp3zi(eOMLKs~9KoD?8(Zr!WuEdfEP3q2NZOn;tp}7=kDISdG9#mT!@N-Q68!IkeQ^R4$m z8a+b@*#arm!|H09HVLCPMo$*1=_L#l!g}n`LZGne0*4Nn?av<_ZVujsXNg%;Ii{NR z{Q2_>EOi5(0IzHuZ0G)F-nc$n{L}I7qC!*7&p9n#Y6PD8mT;D$55bxUKJ6OWMt~@k z2QX#xg_JkhDo~D)<_*x4xn}~L1d2Af1v}}Ey(~SgM@N(7|AW z_+T;*h2S(=7hUJElkAiy4@RKD@>ym^u^xs47^WNHs(*fb@x~B*3rGJ<>lIP!q?&v@ zDlWEh{nUPhoC}uYg6|(4K&9Qv0{ zVj~kiDGBXSnRuZ^d34|*b)^huXi$La@!E4;sz5=0RGX2}FnwR-L?amXvbvV#VcrZFOOY09nT~h}IF_ddWAn8*=@~%(h4=xt)0)0fHs?alPGf%H``G%SpsM<#TFT)BDE8m=7dcO7O+PjZm!s=Kl3s?8$)x$%( ztAKT%TvW8DgdExeEsfApgXBKWG}m+^cHdKvp%*cFnROq*+Xm@dUG>4Z0LBPv1YI7D z8hLb)GOBpZ3?O^rsluI2pi1#<>EC+&y?u9?BGEtw&!V+1TL&u&5J@CIqCfz6y8c*R zV4EZIF!bI;J?W}iO5MB}AwLhs@T-VTBa0r>gkkd=`vOq_NW_M4>uu1B62*;eAdwWr zHtQ{VGg33@L_ddvY_cZJOdTN_h^B<#8dO%fNd4n<3@()Roq#4XuPnN4LBYVygeaRZ zaHj=0;x$Z`dQ8kr-(jz3azPdb!l<3)0rnYWX33ztnSI}h1n;n_k*lJ)qg9ShkwOl9 zT{{|ik`KpzZKqW-H=8rw$dBgr+kA<}tgj5KEVaSng=mOJwdzC1uDXf^cz8{>6=%=|gvmQQ$1T5;_PvEky)LA^emqysz zVm0w{UsA(-OZE;IwV~>aiPlJ!M>G1a{OyQ{rj-Nls2P4~FVknP(IwNaP(kFNg8 z!7P?vXBSn&!D9W#iA_12)R13io8^7k9;fA0kEE}y(Mi`LGqGE&k-ouU$8dn>qTV%M z75MSrf&u_cf%)@MgY%6;&AE2FuigxKb2+sqGT)P}$?(4WDP?VfE`XAv=Y-x5QDaN$ zRH7bNvHJJIhGYaSa)oJBrJ8buIeHf44t+851f8*-EL+(bn?kFoPz=YC)y?%CK0nD} z8qyKYC+MNVoL-47>%`maS`AYKn;KoNyT!mwfRMTlYix*n2ae@TROACw^wGyE)57Zuf}KWM`F0A z3nI+YD{T2#w$$>Ke-jHSdWi+&8e;hK3$~r=M6x=!e_!o zWZ&7Ke(TVbI1+DOxf7UHgS4!(GGT|C z1!ql)Rb*JKY^5rvO+hq3c~%)Lq-pD77Mv^GZPu5*6fA;MSX^BWENr{raxy?`!XxX2 zgG0d=RU|YVvLx;yB$(!R%zyp5qRAfaxCdy)u&|-GHkZI@4 zko}Rn5y{?U5?G58EU?#DuynK1C05A*S~SYEc){b_ckli1?$9Psr6@GpO{p@X%&+vA zyA1=jsS%!O%e@?m)3N(i?UAs#4K%yUvZ+Y(d4^&nHlI4xo)%;K7zJAmJEiQuz!OirYdT ziyega-R32`VC;u0Mo+3@f_+dYZ?HDK_6tY-+MI-6{>&iX3SEV){1sqf;|?q^S1|Y5 zNVl5PDcCn*epRKcDpWv0UGz%tyVn!i6X`U(V$4!QRZvtYx0H89{sm2xT8Lm%2hd(@ zgI?m_H_Jh$!ft84X+8PxU(|wT?`t)rR<-%=_}lAON1leXV_{YEQ&$$0wLw@yt0h{~ z(rW1%kvftJqNZ``JRKLUqI}&m#FV{frt*W`xqA6>oNczpaVc-^?ZPk~N_B{b2o>DP zqGV%>X>4isIp~OO$O>PvFsTGmRgP$l98NnBFsWqL2o1#1#+)-YDJ{MC%)MGByLwa@ z6~lfg!BG@bKg_VHA!ba_HY2ZWg;FN8${TXKHQ$=+p6JyAtgM#`25DapI_h1xFx}sy z8oNqc#b_5U1kp~*vQC1_HWpU&eT24O`{@ca{~Zb;pBQE+L$Nk5GNhP2+wr;6SGH5$ zAEsUu&50$cNY!Y6pXy=Rze5A6YLq;C#2Z^L!K@+hnBh2PVsw)dNYR;%5T$m5CjD>= zN29!66MmzQ!Cgwhm^UK|eq3M^Ww%`{+~dS8gDhSq4ah9akN!mrDWp?1mIslb!Ud3+ z601`yaZvTaAm8w`Oa$PAXMI9xq6v&Q*|xlMXS{qwMDD`_H$x?(JQ>C$P=&*QfYza= ztQY&bq#wq@vTv$de)q#Q!6cspP;vod@zLQ0GtSMwkD+~QvNs(a9gvc@bwCn?umoB^ zqu!Nwdbi)t`(n^S@+oOsHfYXK? zTOOt@ZJ!qjZ&kEUpI5snQ#!r_Udn2Ew7-vb!%wy-A>!WW2UO2>#%6WZ(2lFUZC*LA zukmwB4GIBsBEpcYy|zsizcWLW=+=b}F8v2soDT4BCglW7Zd#&eut$WkXKmCP%sL1SI# zdiM^VsXP$KS6COhWtG`6EY{lj$E($?9hvo=rG+4mnUEW*)o7VB#3-V6^+Rl@RY-Z^f)wPU|yi zYoUXF(qJLOZf}dCg>>SJ(Q;-^K@-y^*N%ryXoXhB#3(%35@5HMq)$@qBk?bF91#07 zk-iN7GZ%Yz_RX0p%|ibs;RG-*sv-T6wotaa4&{(tMl~Rl$knK2(Vn_blN^LztM?{@j%Yb9@irL6={ww zkxRBVK72NY0}Eb>3E^Afyn}OGH|T=dY>*Z~EZ!Cz;$Tw+vGD~v?tNQz3P3fC&D>$u z(6kyDy81D%n@$Ag#gkpLJb`WVtqFz=mg<=DT{7`{A6)8P%66&FJP~bUyaYi6{C9n< z#0}8q;lum)R_@&T=;M`YzZS(};&{g9_B}b}ye_7UInw;95?O%L`{a<~>Git-mxm*1hAU^-UY1m?}*yFwoF%7 zr_Tch{mTO(F>7qag6+38ICT9Y$E#=hWdnqx?TuY<-MwDuFef&)@Q$sTN>A(dwQ;i6 zA7kvYZD|A0HQM8y^ovOz_Q++B@+&%SM%f&XBon3{;!oQa2HQT`u<_zo-z_P`^rT5vn#WK<(M%zmgXuuDB5x$nk! zx*mM)hlW?+>r6wwy88Xzx3hrP-$Ygt{&JLqzlJp;-o;e0Fz1E^ZKt_=a>>{@+6URe zXoIyx$#D`LI6(`eO-33R8C4qFX`Zl`ce6iUmy;JO*~isu+gFsly)D9omx$P2G(_mP zDY#fKUBZjxuhF6TcCXcv4yzqWVeTTX4+~J;NRL!{I}o9wuQWxz=>hBAq}D>m-KOh%+eBHdz(Xf%xn~Pq22HSX{UF{eemS z=EQ$2hgRcA3H8Q`VYH8}dNRgkZ*{fW1?^K*@vgNyuy~k?;p@h@kWkZy;FoRg`JuRl zK5)Pq1lpRk+gog=Uc*Kd-2_O96qK-~DV#TM@fg$&jSV>%4}8DHKdMPY%2_9A{|B~A zZhT1pA=(5JpMD^yuYp#>Y-TSxwPM%zz0Aj(mj^ss7Ot~!qw8YWn0q;s?| zGwX^zbg({^aXnofv{3$(T?^tdQ8NZoDYP1>)uyFwL6Y* znm2nv8Ye~D*xkF>W63tP3d_~K?GR_M5$H2EV?z8k!3?uFQk*?kab$5M0#WfxZ1 z0Vg=VewP#T0df6KFQ60O@pFlbZ)3hC2`6T%ngu3f`7Pmj!iLpx_ROUPFf#4?3JnI-|Oj8FJe=#nH94l`sKg;6QaYG*>X$Zgh%upLS? z1zVwz4;{RTP|+P9k73b?EoFp#X&H>kWMkI$j&m0%%O(fg9)T;M5o_HW?Tmh^uhy|+ ziT`e!JgZpr$*J9jbous2PU}OR75yh=Q=|gwv|~(@+$BJCiNn zGk`0#fzy+tgDuHr86fQ{?q_Lf2JH?N-2Xl|a1S!EcC?|=4%*Aq6UG-@s*cf~k1R|K zHU>=thn2U+_LNREPD1qMz9^`BpTJ4iF=RW4&o9F8QV)P|M6Daatyvmjsdr}A>)q%| z$q}o$MBL{QSZfEUG>&h=AmbC5_=7zSE!FabQxU z)PUGu{q)nd)d8A~2_-GyZqBo}xHJ^#Ec!-=QLXJewzh6#lj$y`%FLTC&}eEs(yTHh z1OTO3rsEV%id!*b4M2Oo&4q=i0+k7IS9Sp7-z-)%VqIr=7C9pt10ue~cW;JI(R-V% zej%3y;tB*#eaUUHsVd-H1 zl&`=m0YxY2tI+uV$$x;l11w0_7$qb7igiT1WDzB$1jS^KtHt}Y-BR{3s*QueL&7d!A@?0R4E3z#ax7fIU16qrm< zx^yk#(wf>|vMIo&qonuLG%@($9w>yyGB@qQ5#qtXM*EI!?~OJFYs}X0**3GhUavQu zgteCnOM+j|63XZULA_6AOJcW9Vb89Cp&kcD9U4Fr$9Cyb&)sd);U=q+%Vn@4io`ff zmEr|W0vYz&7B7CHiZ_|iafuIbg|`Aw3y7-&nQ#hd8_U|KLk22RuiC-le};H{x%su; z6mCp^=_gM=$;#g2XRRv5n&4;1X1az98TW&MWbw>>lmX9C0W;qXC(1(of!S*$lh6mW zr)NC89hIhbuJ?Pf*+LK8tyv6IbJgNM4INe;WU?JpTk-E2JaNl@vKnlbEoH@L5YtUm z!0_4ksaBFwwS(t+H^~UY*jN9He6En0T!-M| zCQ+h!8KmtkM7f+xTBFKSirvhlxqfJ;`Hp!S)GknG@zHd+> zKt12{l4B)ypf4fbt>ZXhh}1gEu3BZmaINvhaEjODm>nH>mTj9WUPIdCJY&4qlkkbO ztlWRvfKqd#a^7h#PEh@6hqw1GVl!b3^)i6H-`?~d-?HB`1P1z|hBFPXo-m#|1R%Hf zM5e7B|87mngw#MkX=1Lm+k1Mof~?pE;hNN}yrp;Frys!G=S^cP`mueOxyy6c27LiG z%)42Mt(r*H80@N{^NRI4f94zHK#8)`H9b63b$7G{rJZk~Pgo88stHA89;R-daVi9X z!#xj@)e&S4BpCThW=R+`VX-8mShf>a3NRhu!Sz3mDe_IrVmEU?6MoB!1#o>id2SCY z&K|8Dl6WNIG2vrYXkc&iZ3CO+_yJpmo0!3#tE&^~xoC*$ zK-N0}jUL-nCIoi4N}W^;Z+bD%g0{p4}N8 z$V6pZ=2*9L%U-o%89SAYlg~%z&PmiumZjLYQ#HuBZ@aH$AM1*PY5z{#yFtg^S$57p zUxl}MPQu&o+E`R5Z<&X6G zub)n;qV@6{%M-Q!OS8^5(PI0J<^M`8e!UArMVtTTjpcu!Howto<5w~o{ZDT!|L-*N zq?bz#Kgvi(c_Q#x2Fgz0u{T{{V=qnu7<<_bD)#D?Kw_<40Up-oRKTznr-OtwIRO~- z?x;J#CW$wHqsj>NlcN!y6Ux;_>dimCVW~Ioqn{>IV|rmef$k~}%qat|GP_9vU4gkr z4|(pge%|ffC-QRKyMo?oSy?Pcxo8E%!Bh$IwK0(qYvKUrgWycLH<bs)>)kK%_C9 z1bCi|F$g^uE+7qK0E9UrE#n%~z@B0ED;vpN6N8VuDAa`u;-N-|$}+eBkLnqIhox)9-IDw;ND-)s+Z_0oEakxubzb}uUT-NP6u1rU?f_tLV=F(RUmjHY%% z$rocm>VaFA?%BU7ifen@{)93reDn4_mm8kUEgDSpU4y5lK6p?(DEFo#5k59 ze6{SEs@lqoz>fBHOdF_P_`U)oW&Bte{_fI)TOZz9dN90y@6N58KOXY?oev(0x7ZEf zxQd8oIYj-?1p|cH$;(Vc7qQ)((DOnd;zje%(Jqc+2h-8^ zz`e#~(ZwU^iSiIhX(~6keHThF4fGz~y8F>5cWyk$-{ai7OK=(LH@2MIK?aVPG7&Q) z0hx`CO`v!G!M*$U9<1EDclXAf_+DN#WVV*G8ipo1k*7?5RlY13DOM$ltU4=;O`!L1 z8J*|w?kCGbblL3JtrZtS*j^lS$fq_rykx9Ze-+=C-rMS8imGk5_oL_qO?&U=z2*Bi z9^6>D^}9>M_wRjzO1$m`$mEXTVsgwpVEN$J*ynfRd$ifT50`#et=@hOXCC?Qd_H<| zM1q!8xqoSV^8SsV#n<2E>*X7Ff86?fXS^{vVx#NNWdhUZmh==ecJ%NrJxK4{`pJh_ z-w>w1y{$gXTQNHLUTnaFrH_~HK4c5Lr|}nCB(1e$FxN$v++UTa30@FrvyQqF;1r5MvKL#&@q06%Xa=J|3Q zB2DI2MQpRq=I+$THYih`S6I2Y8D_8CaR~zC^5ls{{HUGAvFo9^PYB6?4UrBh{V-eU zr+2#`pUKTY@@aYP?%Em|)l7RfDv8pKDx~4!U#Wgg(n!E9L?ghU1*w$DLCe=LWNty$Dbq-3Cx5J;|Qw&ZawaBT7Z@O>Q+oF zl0cz9*&n+?afp{=+Q)g5&+$yef0YW!u}G24Yb$;-j8UI>NorBW~%d1Z31oQ}go0b@v=pP>taY_us~JgVxn`S2ke zfV4SWn2(*F;JhE)h3rExB%Xv+8y}%w6^kOE@a9G-vK{e6}5MyU{~2} zDgt}%=`IWknPG~p%9xu?!mR*M_v%SE&uvaf%)EdsuC5Lr5D7lK|KQfW2e(#!46!8V zrdX^g`BYhz_$-)wTKhF-C9j|R6g}MB%{w<9K6LU7oqh=2LWwe8aZsNF3@D1v^#(uZ zPv+{hh`Hwa7}H}r3n~i7+?t*ySKC<yH8O`4 zm7{|U1`R}kEiWB@p$G<#=fVf%NAu#--oLl(kVzA;d4Uxpzv zsyP|wlZY-=X7=dBQk0jX_Xz`I=9wXd?lv$s=J+afB6_zWni$Zkm%G~*S5(!)yYv&g*QzQYjZk-_VBnC=r zLSLWHwc-g0{-}3&c>l)A%F=_oI-N%bO$YOzuBB_+fA5-Iy%#c4*>C4RU5n$c+m(CQ zc%4|Y#>3#z8qcWk3e}iAn*Q|hxbfnNqyjifO=S1I-ud_VMYQJg$@tj||LV9orDyUB z<%`2Di;`&cCduY`#my(O8Z&jVY4#R) zZZ-h2F~ytc-FT6=Y38ZozR_1GMf}XWL(;jM6x(`-T&cD-lX|XNF7%O%)$+gmk+9Z} zQ+ieKLh@T_48{3rHTKMQ(BxZf;fz!ZpzCG#21?#-bgV+x$i0ncrsO~*Z9Gg8a^vBs zsHGau@j%64uen=vxI4Rt_@v756o$4nF`L98AxzD=Nzb5S2^)%{voUQuq%1J@!NYyB zh|gy5s(UY_I%v$=bO??Qcy1Uu8Qk;pQZ*7)LO*30U zfa3;kT4|?j;j@gW?L!iqlD@`*4kCr~A;g+Qj&8{~RW`p&?}J+(p+{;b7oV=# zZ@R;j2$ad|MRK-yVeA(Vq_=t@ll}|VGBrdSed+V}t{E#qYZ{=SI-mMZM73sF#6d~b z^*+i$4{0S=oOMP3=9uDhS74V8pY8D*J`qF|;%UwAZ}a=6VkNKjzO7%u-~9ScNDR}- z7yR`dUYJ^p-@nW6V+(}5)_a%VafQ_f-{V)95q`Tu_7@?Gd6*eAX?o%#kGHMsD;nK^ zUazhaxL0qkX5Inho1hc6LrS_A&R*H3h{QjC_ELD?lm-_3)!2l&$8&Ud>%s8ehs`4s zL!we^0k2K=kDdG&>EXjq?sR@9zwi{ltBcV7IEZ{xXQ)eE0dr9s3W7(6)O3^H@REMD zxZ+E&p9kZii2#?R6QpKd`~jl@M|;V0j9%jNBTD`4@gT(>-!L8e`@t!sdCW3zb#U0H zq__#?WkB%E!u((xA!YWJ&G)rF!o4?pRurIa?PKR~KjUY%f1m{9sn?pQf^&a{&-{d5 zYa}tMuQxXjA$qMr5`fr81|%ncZdkci85ln9QosXeb-RxH%ViUgG^obT=rfaU+7tuN zlFsMm&Y@IP6kFfug>zMgNR z(!&28T?2e;ytf^?DGnJ!icDSdr`tlT8>~+b){iEKRJOvY+34RY*VF&NIfU?6bL`~m z=7_RNQ6@dI`Rrie%g*gvGOvi+Qo;c~gy-7mrQQ|F;#Gr+$WA1K@rL4Tj9j{b%@S|$ zeZ}YFcoHI@>BAaJFfzKPMXz#(MzL4!6=#-}g92BKq(qJ00{p9Y-&}Jj zgR=k203Kk>@ezUhf((Rtw)xCML0iv~ARvB01X;{t z0^3GY%G2%T2RLg-z6zv4*XE%-#7hT(NkYgap!L$m9{(FpFX42138OjxM>nAUe?0F> zDLFZNFud!qj2Q$2R~qtqr6KxsF8MV~%_=>!NtAFIyq7Zv(%<`>475FA65Ltew(#2 zE^l92{pOd6wSn7f>PB9x%jTz5pAzF=tEXD-XHF)@zE%ef!IvH+`@L2NwXi52xH6@` zUPp~D>pgj2*#=&(uNFQ6N?7?7}LVr9hIGR60i zo@g((r;5I#ifvnokM=D|QsjKeMp*O@^pFmBUS>$}t#LM6WAf|3Ag;Ur5pMhY%J(Sc zK5p-0!teTSDz@0Ob8vl1RUkHSwhAOz)4*ftgW(7FmT%m;JG^oC=EwIQNGb1zzY2p2 z_lu1Ie-mv+O8Myv(sa}H(SgzSvxr=L`^m!>pM1LT@Y97CY@?jGoUcM5Aw{fMtQXo% z`HvpDPWLPwhgsK%3vwCq{nq$}W`j#zuo)c-T`%>AHv;_r)C@tV0R9u1qSTzmG8Z{dingP8_%!4 zWTjE*VYZpi`^7P9ctKDGRGd61Ta$fsPy{@ZEprz$fo5jsk30sXc0-d4au^24F4ww4 z6cu-YDS3-0Q!S+ohOv{>+{fMDmlX?!ce9Q-pE~**?B6xM2S?w!>A2 zZ>8Da8Os?l@9O)0N31hiNJV?x`{beZVsOrz^Jsryx44<)4?QFl*>Cf}21TZ}(&!-M z1rmeCdD!=@(W~>ciAWm8DIe)^S`D(xq|LH|mQq|Y{n``HO1DmxPyvYTuJ8>S&*DE? zd5YM#wq0p!47(r$xSMA-B`P?_5+bDYNivf4U<=RdFn16EdB0@v-uJ&gyBDj6LDSW8QYoo}~D8Ayz^tJ6(qE;Ur*^8JF=GD1m`cq6be5(R3}DaZ4(f zZrbon39Eeoy`g!E+Jth;+zCt}2``3YlMpIREaNCo7=)19a2a%buIpX7#o_89<^oFR zJWDt^AY}1|qy;7q8?dvMXHHR`acF@*Duyp#!WlikYpQW5;I7J!Xk3ZkfykHobauv zf_Zd7(-5ASs{EY-zRGQj3*&|nAyoY+Q>FXJi+4?v3pUuB(5NvD8p=P?;VU<38koA< zBp*uNe#jZOyKw&-2<`~3UcQmEo0VrCm041TGL5f)=i8K)?=yaCH7&P1xu4T`)`_ir z1@o>kP@SBj^dx!4h>VluP&qCsir*%U;jsb|q5~z{B6-fpQc|Kt1YchI$ta_j>B8X` zhd5E=AFyIvBsgoreD4M9oR3D z8lnf30!?sK-HFq5qP`*L{OUDTqe;PGsJ|h^lL*O`q+p@gguFUinst{U8IMN`BXIw3 za}Q!)_bCgVKmV8@ZOYu%S6zN%*SNQC_spFkp{iJqVTK6kLxGh5ogTFKcl~Oei^&Pw zcw+p0+`ae~B5xBWh<3ay?n`GN(JB3om2*{F86AkLv3Xnqk%~|70SgCk z)(LdtF!n>38Qpx_7r287aTG)iCY878M~SsG|6wU~BeVm2c;HwYY0fj}bs!#@liiWl zhl2{EIclkIPoc;=2wP|Pz?P!re1&*tXWJlLmB3c8jo7dYlWD%uAk7@Iw!07Y=n}CQM$_Ej>36|=Z(9( zXcx^0*UlL~?wHg|lf890$y z#HR7Zp(~#BR6l*LVE>7ij#30-J*vahw2!81v&Tz|+;dPVjD|XCVlO`pJ?{X$`Lg<~ zW+gMS;=6o@G9X9Nm4Hg+9jJHVu7xIg!awfL77{1&zd8GA<0C~Anni^OsUDH$qaWQ! zwTSMG`q#cV3$VmHtho%Puh;-Ceu#YsC;PZOSJ%?mG&e|HHB#|4`pO2Yca;&}VMN;ocRy~J8I1eQ2&Wht9J(u7W2UwAX|elFwA9g%^c;I&hlu22L@?<$kJ_ zp)%#sQx@t5b_zPzg_D})G7`p95*6>xv6zq~xe>u8hP4`#>jIEjQx7S2PQX!`x_e#Y z$O9TJthA?9^9q@trt8RERjQ6IHOI+D29pU~!&3=O^RK1drvS* zAlZ;>;{Wpl)oHIMQt+IIA^R6U>^c&9 zP8M2)ewc<-i8I344(1Wv{(wYs;QT(x@up*CsX)_WW*KHm8AB!iJia(*E}4U=*SZ+1 zdR;5O1!4KKDLR6FOUfg@ zX77Xk#nEO30b3=#8N{GSr3>ejs1E4v^0N93Oa8otM zqt&}tX0+gwP`67Kd`b>l6=ph&*uZ@_95m~NkV}c~FgmAV+sJDwV8wvaiU~GXfD1Nf zAC(4Ok66m@#0`2V+da@jV#<*LnBVABR&~_7xpJ$gR8Vufsv}H(VI`U0C(JOVDqwH$ zkMyWiGw>W7_o*WRiJKCojtoXR1(^Y^&#}^h3Qeo0-kRzcVE2Oq8DqmVW4OTAG>)F- z<{e2?PnDUS>@+GXIM>+T@AdlTW2f%4#k-&+Gpc*iU9J0L;kN@qID7pMuAG-X%xbuE zm}Ui36pBCyF>hH{bD-!+(411#2adcr2e0M%SOoPbm#mzb7L8s=8TlXH`)~#Cs-+LT zK-R~%?yj(U&BPGfTx7fVZ7=Qa-KG^D!K>xb`*-f$yuI`R&x7;Aa?X(GJ((1kH>zpA zerP%_f?L~@wK)u)SeH4OIfJu&=7Mj3HJa+Ykem}ZkmOJ%9{=F**dq3$?TuY(h~438 zf-69Oc?YV<_Xa^4MDY7p;qk>x6!(5-?}@Tz2#E2fSxmF>$kcfiKUBgnT%eLilhFW@ zZCSme^4RdrFbKzRdZY$`LHf!_ULqu!s;9SHtl{1!jH_IFhRRWt-rz8>J#IY76vR=+ zFjJ89iP5BrUl?%QM`|R&L!$arr3F64VCh@dab7 z1Oa#$gi!duj59A58i_JI%k&$e{1mX9oBNv?Z2ABgQEgGD$Pr5e<+#9t6>pZoFgFWh z!$tEGsSg|D4YX8lbTmiq<^{?4HGM>GQsl>h(64c`t44u2=sjV7yMJ+P^&?L=qKrx) zOlrm6^=iQ6^Th~(y@<@tAly55mKS;-bF-}0jiqzSSfi2a32w&*7j{c1upb!iyx}e3 zLKAm4fJ>_-0mths(&&gPFZMZpI7&+)iYDWy{i6J)X{{z*+0*pIQcab|+kRP;2$tKT zsqA`-pn*?TPw>rt-F%vYbyRc z%fzjyE|sxuK;k~=C+y@h4 zkAG@cN#EM_PnShuZJ3910#985kS;jM$(0Xe%h4;Wen!Q_i{idT_^vt56`BUQv%=L1 zeVvNGx6{lOKr5grVA~_4>RUD_1jFaGINcBcY3SAC-b`MXV z(^;kCTHK0WIPig((jOp~P* zm{~Ct{ao+C9{Ep<0AyL~TBgZ>7phq$97FzaPefd&woG+TtpGk1NO9RqjXm8Pa|%i# zT(|)oP(u$Ih=ZFVVrpP|aPQ92D}f0iltp(R6Nu3Lk|SzwW}$v5t1^iM1|LZ2;heYU zDmcqmu?KQwPF}Mwv>W3CoTI7m@q&~U6s7Jw9`R2?o*_}DOI?#SH?gH#Y>1ecZy{JG zM;$~Dm4=mF%ygsFU3}o~gwz47C}&IYI8{MFN9?O&`&PlZN%vRu1n#}4^nVTmLJS#q zB-KE#ckcoD*g0j;t)H?%NCGQdeLPgbBu6=`SQhng=`_SD(B3}2WOo8MTSuBFhNu#Z zk%JL%i&v+lcHKMsS~9B~ieOf?3^=&7$4RRlJu$F3z;YVOvlhBy@mvCwU>r^?Knmv7 zuqPnHLIr;YV@V91?Cr%~;8wTVP?J${}AqnDQ zj{=2XNo)v&KNNp3ZtAgtflQcO-dItg3~wy0%ft#^}HaWY0_7I#^Yr ziTm+IISXlveXkim@A*b znt8S84NCTw$M^_XqF-o;zOvs@>68XS^xhu@u^C3kTj99IF}(`8b*|e%O;V&IGi#&( z3Dx`=?+!=di85R}?*}YWg^kWq$c5*>-Rg3%4IgD3?ocRW=uawPeGfsD4cx(9S|*_d zp8zI6^MUnwn7Z0ja}_vdB(vb&`qB(WfmDP)X|nhXrc$MsT-SuE5152!vs~$>t}o7O z1;2&9T->e!mr0HT%bQHnMKsQL@2#NvGo6?9gc@FTyj4;rQrtOB765Z08mEIMj` zz)e|Zx5xNZcv|N~jlvZoVacE5YG$cHqoSF`=>!UG9qeOZ`BAAC!wIe#KJB^^w)5J3 zN}6&aUNMsZT|XKv!aO%b{pn+aN?!a&3{SBOkMP4{#5x2`!xXZc*=9PfOH7a z$~geTjqX|*ToITza;<|^kMt93DIH7hAJIfGZ@_N$9waXJ*=^m8qRO6ctexjc6Bs5d zzE61F@_@Pby@#nG=5DBn%Nlpik{hkBlQYq#6nhD-z~Sp??K8BChVglhw2NL@rEj!( zTzeC_xq|4UCqyRklG_iKz}FUC)?|+YriwkMTAfhqCkqcr{D3WmyNg+FU$x!)^Hy%} z&8fXWwX}82b0Qh^-P-YBd-RNalD(zf4QlJDaI1_0tGHJiqM`T`Q&1=bF;2>PVB^ZY3~s=(Y}KehacV_KK$hU-`3rlfAs0IPp6+Qd^&jZ@mufB+dI?; zA9TIr<&8TJVfY^`E#K0=?RAIlC*}IEs$%tZ-E=IP5=$1J7q6l3p%3fQ}@6J{RM1-Pq?`WX%RD< zkl+|V@Cki|yO8?+)4UBWNxDHxIzrW)|B%wrwYVqplo`F4dj)VNTIXDs44FcIl06}N zhFcQp3o2<^P1O&UHrIJZ-F#vnH}r4*5fw`m)l7}liK~$V4yH;1g!=-DWEZ0JZEJEp zV-t5(2Aet!*hMMWLAqZvtymO>2N5@rV4i~g((Eud46In%YQ91Fq4(*vvETSwMA7!e3tWN@B2xjF_&9B|Q=h84_1ngojRXR@v%ENnyN!Qtk=9Zs9ut;!X@@g>+ zX@kS?APMu4K(At}!+9{VNrl@Ch7u`UJ&;^Tm1Xg(HQs=)v~TGvL=#oAm4z!auYiAZnsL64U3m@el`hVwt#Ky;(8Y|K3^ZDC((!`g=RlHB?EAI=6O=rEjrwTN4 zT0Tqvz1fZ&;Oep=9ohbTMbZ%p@8T0?(owRtm@nLP@f5k zIxy$C8{IJpZxA#p;cTWjTe7z8l0=}PywYV0#Ux0>(v2t`-1afH*l-zEfHdA4*@&!U#AKv?9h1`~?njYN$>nZLOt;1x zFIYZeAiu<-&i9PpfBaUbp4-o+p={S)nKu?AOblDRnBe*CyTY$&fNsV42_2^Wv)m$I zMW>(#-vn2TtdjwQx*6Lq5Pe8~GUd*UHrNjmXiv!c@Wq)YYZ<~VpBLT7&fx{+IhPxv z1DB@7+W?Ej^`wKhS=-y&Zu2u%t7Wp;Lg(4oE)hFJXFdhHQh7@a&~<7J;BtGm92z7I zDpN$Z*w(7)Zn!Hb790vC$vTnnQ)>lX#O>Bv>f8RIsj_q_f9{-8oTt}1i~J>to|scb z$5w;O^G-js$_zacPYtfV^PQBi1!s+X0pY}yD|w-Jhm!YlP!UIGE2)C#$%094r^!#n zS7EIHWnd&PA~{w$bXU^oO^a=u-ACC)^lrj3_!_C3Fkl2N-@fQSFL8DD&FP*Nur+mX|=a>EkkiOMDbI*kE>8I!w zF}mo5%!oCU>_uKRY1g9mPx$;8}Q=o@HO%yE20{EIxJL2sTa0#e|FSi>kb^ zNq!}#22tOBEQN_ae|g>_0#0aqk*KqyaYZ9r?ULcjLle8ZwuNXu`Z@i3A1;4z^0*C^ z@XtDUS0`tlK|`4PS!dAI$(d)+K)FBb47xfw^9)R%Im9EWv6HV41t;`#(XCmX;1IW# zvEnz!Sso3uKROo4<}%E`m|yq|O;&$%{`u3Fizw6mo;-T`_@#3vPsMFdaYh|)^wZm> zTDygZqVqFhqPYCW*)`5%OOk~tJEnDdulb774eRtI^CnENc>>pnQ`_4vFB@Rie%XM4 z^l}CfQsdJ&Ntb&;9DF99L~s$-A!T_O9U$(ye@4oG7=q&`3W<=RXr_+ZTQ2>g!I;9= zlbY9E4Kuq6&bQMaACK2iJU8V&dEO@fWC%4_JaivcX`_KTn-VE>U0c>%c!shd=<|)& zF1E#o4QMayLi(`0CfK9#Ve=ejMud)paRbe(y=B03{wmDv=IhxJ<+Y#PGsgMTF84@5 z`|~rFFq$36eS%Zrx-`X;$C-_S6$daIa`>`iC{L6IU=x*a`jWIWDVOHVrsjm2r_NSg zG=lhNCxlJjc`_wYYM81Up3vOd zV_?p3M5B|y4XxU?5qKoVDe4QuD<(8q@ltk}{it4sMSUBm`_n^;FvN#5dD_Ox6i#eG z9k7M1TFLal07bq|=JnO){^OgCoU)6Atz(5LmWm6>J$|egzIwaR2)Q#Lgm){;-erIsyJM%9|_;=k_Zpv?=3&e693)ro+xG?I2 zpe>!zz;u7i@QJD&;tzD_sIbyxW-lc(kM=&Jlxk))(_%w|CN03KO<+x8g80zJ*vUCT zZu(LW7$ROjI^09XQ-aYgg;%Xx2Qcb6*d`|y#T2qj6%}i++J;}-Y3W`W7$gQgG4|TL z7Gz$qg!C5v6a%CnrIfL4x<)8e~cNgAnl0b`3Xe>8hvWTgfWnIce^b-mpg48Z1 zR>?2qx$|EkX@Ek+hlI3o1~J3MzXZxKmapz1H?}Q+x|qD;9Th^%)jU&g%`ZB-Y*6qs zb=mx)qss=Lai%VtUvzZY%}=MzGzgL`=I7RRF5MllyB`Wo`tG8{R43>BP865!MtKE? zI@lN~Vz^UA`~)fW-$@HFLvtGhqp9<)<4qRpj^``eq~@32nYLsxljElHL^GOC-eUSn zKkX=$#Y8Rrb=9?Ty^HhaaWyl1x>zMdWw8+R(p7F2UWs0sxua=2Ol9$elzMIaIWzry zbt<&IIB))s8ALR{+^#XR=}dpk%VS=QGi{o;!Ia@MZGsq9G-nZ4&l6gQnjMg5v zLsS;~eiZra=Py>81TAScTxIe3OXmypT0ez@6IZ@{xY!w^=577INtM1w}$w(tB5IPV>q1(*>xQ?d(*y0wHr`tzx-zm^GU9wr!(mL6n z6O-i7*fd}#wpcttrQJZ&>cO$cSAaxJ4m0*PRfsN7R9!p2ZuSc9;xv{q+bJ@hBHY#n z$YNVULa^oLEUPr$0{aMisB|H4N##-}@`M}|0$u`hrsRE^WnGCRvXTS|rJ9kpu9?s$ zb=BFa(@2XE(3ecCN&4#9HQp#NJZ98*e(F>jE!Bez9Wic`oYvzu-jrb*k53)8(Xu&e zlmDzoZM-R?HXffkYNI6`eCTF0EmyG`3Um!4zoZKGfPYIoO-Wi8l`H+CV+tWCu*LKDL@2a{M zT`Izvx$z)n0>~XSLF|+%l!mA_GcO(aCYebCXin*;(XPsJkZ06@gHt+cwDbH1xsNsj zY`##`%SFu}8CF6wcE0z6-j!1ZX|=CXCFHRr&ZMnArKdU%L`H-Oteun?YZWon4%o9K z#+81Lu-smx!rif;J0x$;;56tnTSwdzlX==ORW~T>n4Q6+RQzJNcR<{L+{ouOjcf+j zjqUo3bako?KiQcM#r@ky)kR1leWCU}uSvd}upPe18FtS;(WL$vMoi#vO6sBYadW!b zx08VKwTH^-JCbvqjpeC8v@iPEdenAydTf#ATNT4q!TMXjW+vp2qDC~ z9N?;_OkHom$P-1My^eo`G^1OqR;g%S+GK z!akY8j+*29wDf77U;}8*K0g@FDx!vsnVH%3G_$kAY{&E(Fnikc<}{3)B0m;NJ!G-iQLS9KdTH7SR-tXq#>m`52(Z? zf*zqXo{IBBF;sR>8vr#hjo^PFa{-pqN#>vA&|IA}V*hfv16o z)+aJ*ixncO5OiTg^IJ_g@&u4+A7oT)D#y*O4hu{ z&Eq8fa3%E5sB%2&F~em?&#u!E+k?qwv+&KeGl+IjKZbh@5mox)f{?02s@0tIVIpFS z>6bDQy`J$ASv1p30YXu=R+svwK~?;l#-ol;8fUoJ_^ZsR`tE01a`jO|EsZT8OI3{* zwRXRarR$H{??jl7c1;gdcae!y$PkMT2JOeyGSj)#I*5+L%FP+eW-4gYb3r z@Rz%_l+o%3Z!G_=TK$!i@L;t2@f*uWYWJ7Qc_tJcExw?qU;6zok6wP+pV>a;DE@4nVlghW^Q$r5r^#YP)TMg{#)w3Xcqr+POupz{{^Ii6q=Oxg2w2EZE?=Be+PlF9!jnh# z?`?PrS_SFvx{Qu`1-l&w$`F|Rywri#pECqow%uv(TRLW<`*v&*>{L(1-Fb!*>PQ(% z73t_;rW%%WAD9hL>GNdt)0Qaz$4Es{O*ufy1Xey}n=PAUgzk~C$p2LShNsgxaaCh{ zn1~vcnB#t-zFl6eO&x#mz7B+=(24km1{J;}_iC!H2C$)6!N|P29$G4#@+s=Tf-HB8 zK_E%Cp=}!gVPnpQ`j|KCA?y&xHqF6iO|q#r41KEtD};eHtyjKb_7Om$8c+cRcvm3a(*IP?VR7lzb5d?!G;E`!XRa#yjUr zD-O`^f^J57Y76Q0-yLjBc9>PbH`d!77vIY*ufKNfnZk{C(4`QIm11%1+DuVpDBBwU zX71evxBtLfA)R@RyQq($Br_9qLG%LrjCPe?`CDWudS;&|)Z$&lUp7#$KZ6O}i5si6 z)O&^@riBM6lhAR^hYnDSjR=gg1HSseWbqwCbJ3@EMzL?|N8V^VTzyjTkc?I6(mxK| z7azm_D}W`q8R1HA6=*S9N&e7Wcxpa`d4v7F$UoHF0$e!2K)kir5klGP?Lwp#2u5mH zS;f^{wSc5^%?Ve1{0bK{hctfwwDBVD1orZ93+Zb`*U#~w@|)m!FQW@`*d1sx(JIWB`*`$ZV%_9|S84h#yX+@6NX_MPIJmR!LRqpD~sHYv@ zCmOwDv^e$Q0J?H8CUcD?o07Z-APfmv>Z51_b2i=V$$7boLm>I@7vHqJ?6QE0IKL@$ zGlo7|ip)<|KExZ83rJJ7D3lv2CSbD6GLwVe4{7+WbUizy2X=h1w@!c;2o$nUF)5?D zM!T)PDWQ~PmW`wVXpqVP_>Mw|dsfzVuy)LzCQ>`SPIgl06xsPAH0w6Djag^Ml>hNuvT~9iLn7M)B@L( z1TrE(>)A21^y9nIScK@f*Fl*`m;EhO=LSofFQtL4E2u)x5O9#<(xz$Q5tBxV6hA}4 zh~tEGh9|_TSyY?CV~2vL{@&VWO_+!=^>Sf@u(7F{5arD7h#Q$&UTgjaPDqp^(CN=# zl+1cfDR)S#`PuPi(W8*L8)WW-O%^|xm>pN z%yCWQQ9?TLFs&y7?p&G1-BU!#$drf=S00dGE+f7msr!?Cv~!}=B832gr86Y6(8kev zz^E`l%zq*0JzHIsdmT4MKDE&`963Z*mSO`YBd(s(3}*vrNz+)yNhb0+5Is+oG3Zcc z51ge&8{8YgW{^T4aB{dkzO=Ttacs561x&Jt#VqkHU`vik|G4|a>cVT$HYx&jD=8r901rwEGH~G%9cGcr@9~A9LltJ)fQ^BbALEC)4JRgq zpoIkSjAf*+^IDXKn6>$FmNXiQ`Bu8MHNS<}^q9G^`vdsCUE<$CCS0E>x1}$B#ybY> z?^9*hG6~tlQe>4)2R{{n)i@n9@QtDziHB5@^NAhd=99@4H+=Xr-@48nG2EhiS`7>V zAwej&IQE6>KoG>GPYi9YLoq21l*d-Eb#q15hBj<;OZS=NG=syum!Ej0{iALG+i5|oN5HoQSf z1mJ{43CqBK^-bUYOo;q^>^+5OOf1_(fh%em-4H{%A2(vf;I7S9T8|PDMPk5_^Ty_q zBm0RW0n*j8-U6T4?8$+}P1zW)9X&C&-E;rY2LW61-N$c`;5@N9qbEmH^0={UUF4`Q z0kH`D>S|nW@hwlri*Ne*i5g0=q-&PS)_lu)2+*X$I2Q!&ChG9|88Lqga0jlCnMl9d z?mhR$0M?xqT?hS;*y|9A5G+Taw*$cC$sVh*D@l&w6oKnEz=19$Aw;uXaH?s?9Wl+P zo1L>n2zS}we3CJ)zPLQo6hm1o-?icPMO@(S4`P43`8j++#V7i1mBcy11Z1vK{x~TI z9N2q(z!XuGaEHl8IAk$A>2t}^xjSXU;iam|8+Y%0ur#d7Z)9Z-m3218gU_$1`3Aw- zYe$pqjY@H(*Kn5>zuBNkS!w|m4w1EuNA3uZDvIHg+xUzlW^$dvwdg90}c9WhH|pvFLV%3Y8pr zx_ezUWmH=~yiOmG8*y0n&9zO?`?b}4a6>y8@jk0U&E(dz38l;e@U($SK155Arsc{3 z*o&F4l*`}i{mCD_yKt3MBMB?<;O!7xjbORCgo4O{u*=CNPeT<;hP2C9Imd#fYmzOu ztwhr83U=^L>tG(Qa9}#{Bs3;-vI$SJ+%R17Glq^sbPU_ct5CI@+GHk!LQLNsp)VO} zyc8S)NYcw}fE-7piM5@lq<}ml#giUInGNkn3l^hSrN%VZiWGBm36$i_2Ps`d{M|IP z&7~o#Fz*waedY4PJ8_lO{|pGn2w0o<#6@ydH#l`xzH8?@*%^rLide@uxGAqsP&R=j z{5YuJX2X2D8m0pOv@r^UGPPx$uK`Nd42cxz#Xy7&8_pT3gB_NYQQ`kK=nfdLmZyzbq@an2z7vMm`DceQp0jYgQ>&LnS zkSMSc7u}|81JW~DrN6u&bzdJRIn(Oc#5=P*$kXy{!H=_;ZZkuO!v21K?8 zn`PZ5QXN#Sq^^?J*%M`XlEaoG)hhmk$P@@xOq@o=U!o>~38j$#BCNpR5?TxK;t!kL z_^pC#`O~Yo)`2NOYcpy|U9^Xdw4=)k zRiw_UM?No$n!y8cGiu(}yLArZNCn}o*q6wFXooK>DeX%>;TjVGjv^+YC@D>VOn_kD z^S7iMUv=WPIIeJ=(8aKMTyKwbL725fGRZVi^$=BF7|4JWA3Mv9;Cgx(XK`f-(?pIh zMA*bP`cf=QTDmq+nJMKpjHfm|nXXU;W(6euDyWP3CI(CU-+XFE(0tT9#+NhU@R^JF z$CM9BKI>z!O74A z&$u=rzkvMbB*)yRg67rBSHGhe|I6Q2>5{jrHQjH?6{wi2tdl2RBb&k7^W_S9QQEO)L_C?!ot2j zG;O{a8b=)46zx8vmSVnUI5>V2Fmf)#VZ*$W1KQc@tXoLuXjVBdvjRICMq52(VOGK2 z?v+g--5}c}nLkOBeq==YbUZ4DV_xz^R- zv32BOs2jH zq&j49&%arP-gnf~z?nJD#_DR5PitqiUzXj~G8QUC zdtz@GXuv_T!M|#5a=dJBUDv2+NI`D+gdlINGq5>JbZB-whCt;T(?N9g26TBT>mfYQ zZaK=XwwW}XwOPRBS@kwfm?0X^=jBrY6ZL(F_Ybhnhz*+Z_oMHdbit$V3xI#%^&3g_ zlISN0I1Hzvk4Xy6NZSw(Nw|=8*_7+hl-{jN_mHeM6!0Jobk9|zO{xWu zX<{P7W<;mV2L?YyY!3_zn&oWd?iV{yam0OOX|SQZW#k2-ufsrRw<;W5SSUnG1rRqp zi4E~|???M76&**JHz0=J-aGiGQuO^a-fa@J5z8;C~9y;Cvpk|8Cx*_2Hq zUcI#A7F#bj24xk1{PkC=q$!ubS8PBRE|{Lwv=P~l{`|s)3%&395Ec((cjgpNxxAYBoM{L$rw-VbGgo!v@+L@q=$diNEZ zlJ6V~uQ!Ms@)_y}y$cs^3J;Pm-jKpzpB#S5Y9Q3q>wk2ak8iHrvQzlpD+a6wsZk+a zWC{DK18E`R7 z*To^5)*}Qsyb55XxoO4~qvnyC%Xwo@2<7vSN!TjVX3G1^8Lfm-wGmt}gAk>@GVeb! z<~!?&Yrpm$$_^B4$Z!(C%#>u~1N}$=tH~rNzxB}OmbN=)0ldO@-T(w;pENH$_~|B< zpih+|Z_)%kj6P(M)y4-I;0<<8w@~K0d>v;g^tHl92T$NW1@z`5LY8WgSY6YKFwsYd zGup%;Sy*@CgagHD&sJ9-J@(eokJj9rs;S$~a80gUjxG#KCBt-{mrj+DzQvG*;M&j_ z0s;i6iQ|5i->PBIx(zxdi`=REUaIuY(zK_hhwoR;@ z`knF25x*{M_v$?;mcAWH$Me`r*t6a-FN1+Mn%4>sv%BpymIfG%Sy* z#-6216A|E}gjNPr%ZO%+^gz?r78tw`4|E#a-ufics8YH$@nnvw?T%b?xRT*?hGDA- zv(1QdQ3z*^yk?iLm>M0-m3*F6yIhxEYf83cD&}n>g5neGz@SLf7>-q&Lz<$HdI;32 zq&EfmVD240kzhWzI1M0>2b^VD5Wci z!%Cfxps?sVamCOJ%_Iw+*~EjFw`H9Ue64HQF$lM!<7tsyHNEf*ou&gbu-A2Jo})c3 zU%m`bZzd5bgT?f_Ioru%ETO9c0^+mTC4DIN!l<<~Oj>|L;^oCq` z@ixuQ-lspR7EN)RR?P>JtR98tz`kwWvv-`=ldSKz!*?r!k5=^UqBdNg0!TQq+8 z(_kc8cfd$nd(!MTK(k^~(}=&wbEy;)>{9htYmWlHjj!*-0Uh&xl+0lI%C@TN#rCTH z=nNZHH?LGrI&h9Laj~QaaQ%r+vx%s}mu6tg`0l`&6_ZtsNQwEB0=N>#lB9;eHj7YN zpTb~h+~>vYm?TPhb!su}XL@94sFk>``Z6P+>eKw}72gIcUws)*Ooepvm@ZQ_KLa2u z&DzP|`Y~4D#<^YPProMUWhP^Yqc@kuExfyg;DbI%Ye zv1pqEOHu;}Pz;WC4+o=-4IC_F5US_ilhMkUU-js0oCNz|j|;+S3akd^>`l$r=cQ}j zZR*ne+zDja_3~Rj^RCkh&?v3{lw!fW!QlQ1P1KKnf%vdoyK3z6u#KT~S{3&1!WmUR z&2xN3Uq2g;br7h=Y{0}CXl6rw= znVL#>sr^6KyO%P-gBgksQ??l=Im;Zvij?*}Zg=QiC8J8Q!arPJq8%(Kr7w=dLTC{J zajPcy7QIVNaF8Zfid>d_mHd7upSO-|j!9`4&S|lV->C}^k!6f*s}g6!gx+#ntQ{8P zd$Ta0(Ba9qdaYa(3*ouZJ**U1#Q;Q;>RHpY=h1*^*trn1ObsdB18fFI5{i)}-;gxV*&{3=Of0lhU!4 zb1)~068Nl_7FTSiU=H!|*=h<{7Ku@mHZhk23UTi}BibOYoPu2i#-=G(S1Je)-@lXm zQs9z|vdKE#>q9`p)fN>@a229^_STia=S0>`)CKVlOk^vz?(w@%H&aVn}ebIZbb(-Z`{=vj!W%2 z`L2%8F)7eqpn6XKX%OQX`kQt)iE-2!#oa$|x?T9_i=t_AAsJZo9)qkuy&g(qIYSC3 zVSod+rFuczv!}q>D5VfR=+x2;1in`d08P2-_#phwxt|&XpSqq(TSPhF#yt+fs%G|z zricBugm|v)O)E3mt}HBiu$h5)6@0*VO&0+Ryh@8ZlczxGU+Xlxw_^_v;zGp?2#sL% zs#g`eTR&}j1aOt-Ke_wSgL|Lc{b1>X@ENtkmm_)QAfSfMkp`=Z_o10w(l=)|xtF!X zUY*ra{dN!%U-Q5cm>Oq_w*MM*E(x4QfbuB%%TA*bo3atFMT?WSf92~``Cor$;i?sT z_4AJtmK(b?{E=}AvjPbOwvX}Q(b;3zvCFHu9US+GHwAP7Ve=xh9w7M2SSY)Vq1_A? zY76`mB5mBe#&K6Pm5Sst*w?0-G8CGP*>XoRu?a#8#9OCu=~N802q~-*Pl$UH{_q~K zL+wr|oLEfPTpC){o<(4Uw9Y_0_APsi_1^GL<}tu?j`{dST%fcK+bUzF0Ekp%Bw5Y5 zx4ut^39gA?#<%XSEZtqXb?@$tJ9mC8%Na4Y;U=$(o;J*80C#ce-Ah+4*DQvoeq6P! zp?j3S*ozItN8xGXvFvlnT7f4>_%6nZ(~xP%cEH`paB^o-s`6P!tK<#2)_XhIc1P}@ z;1OBg0D5+)ObNo5t2F>JBdcw02r73Lml$Wl>hcij_p1JVA;E0cfZH|M;Y0;ZCKq3Ah5eJjDF<+0M#*bALPA;!_4!MWaK zji61rzgj%f%fwybbU^t#N^&H}aw&|+)sP`GXEFBRmjzXDpI^n!fwP~@A=^(jN9$Tr zTCojWZ=iepvr`tI9_*pARDsG^O31;*7uq_|T8yYD35X?*<3S$s^U2gWUQG0YMDl}X#X~qQjY&0COhR!YNnXtjE&R5jZPwh#VEFFI)_u5;g2Ah!gz^H8*}Xx z!8lPupL(9-E_pwEB9#_(y_~!#HV4!LC%wKt-bZ~ILDrB9*Xx<6!p#si`R#}I?%K@{ zlqnUOd-DoyOPo(a%KyjR+r-9|WqE!s8)(3q>F(<8n(m&S9(PR0RScFCp^r>uRVhnZ zO;OBDHbqfIQk7NBl!HMsB(lV>iXbJiGP5ukV~hsI@M1iM4FfjdjXz+(#w-Syy$7&i zz^hpp@Ww#z40z+MSN{F~=id9?iwG)}^)awbRHY)~-FNS~_nv$1`99z>@p zsCte2x>oe`m&L>2jo(7*l;BXosof&6?mzjD{`r4G7CQcvVeN0!Xi_9#Te-3F9tqlh zcY+$Ehu>Sd%fqivnkCcIdn>y<{nKE_s?)25$V5D~JXrb9Y54~eZA6q(ga2aXf26^0 zH#ocW=zm`Q>}x#xMtate38KmBFTS?=&(!93nuwmB{`0S`{tKQu#oUakIHTK_Ou}tu zgYQR^fcwWwAojBLU8=-p3oeMV%KmkHV+IV0g2wl_j7L89nk7zB>vA#)zR=n3**4_iMv zxfq_~Y%_RGqTcsWf*6+g6W+@F(-WTLv>l<3t#&zA|7RyeI7jvv9^bijyXs#) zH>cIBw|XS6Q^)#)JsJ%N&)&P3EzGJ-&M{NbQdW39$e^wV>69#g;3#RfGVf!OAJhkq zwPhsaLl{rCSXNuMU9lc}kzpHY&R#J>@#fW|PE>3_DO$3!L#XV~9ihw1hYwe~CGQ+5 zEOv03#`~yDb$gqlS&Zi(2w>=NYPfi$3rl~@fc2Eu& zyVl_W;wP^9uI2Buw6GZ*6Qox&JiNf%LQe@!9mql_*u*Uawta zBh*DNJDlE2FO@~{Q%6_T4<$!u>uE^6vyOK_)tsZeVDmhy6H;}bYbJcw&hH_LXezfV0=&t- z8m5k3A!jQ(P^gaes0NUt#C!szgmI_vm8!qd+OF1L!5)d0&%O~W{HGd75f zAGwx_4?A-CA#US?1BmJ~`E!>svQ9a{03mkS5T&&s#p75UN$dO+$~GJvRm7+xuv>R- z-oA0?<~#iV-T6vkp(GT?ymkQjl{XC=Y(+{f>1FGO3--c5FNZOLG`2Xz-};`?488ZB z=OD5fej2)|BTJiI*Uix|Zb&Mk(nch56TlweX-*O+Wm!Qf5ka$fLn`H#SO>q_pxTlY zFwTqW3KKK-1a>+9$|!mnAHi<#<2(;vk_e~AbDxm=P@bqCa!g8*v&-E%(E5ae$#atX zS!j)7(!18Rk!=VC6mAd7%AfwJw^BCQn# zbsQ52lOYqZG`qX?}gP$gR>)cYRoieHFmM~iUKz?w zMwp22)}mo?eYk<*60h%lvh`qelu}g}V5{?sTQ_f#dH3cK8KDz76pR&UHP70sxV|gr zEi5J4%~MW+@;=*08mG7mg+C6f2Z>6XGf&|e0gvKnQ1nWuus{-7IZY)QymaEM((gmG z#k4}wa2}{FPPJl~Op*6Ep^#a4JgzQ%AE193BiSs9+V449&xF5IV-|CYRP9me+WX$u zzOm8u?dv3jy5|<@OYKlb_j+iyrRi&F&K}JO0ZSsVUbn*w?dZfrdUdW6npCkqEN=>5C`gM(YWT3v1;wdN9 zEJB?~{WUENLP3=Aas@cHtN9%h;Uj@2Lvue`Zz4%ndw8M%eh&rq_p9yQpsEe z+a=tG@FrO^r=)#T^4c;PF_K=rG6`~Kke=~Og3cCw2>y<8Ke-h(* ze&*sBal2-KlJ%>A%7x1Tz$PUfOX&jX>UfW|oYJ_YRQ{3cwo||o?#?@&7uzS}9V^#J z_B+yw!mdhAw$;>Y9UP8LeY-D#o&o^pkPbh1B8LL0$*C4^`*xT7Z#UR zu{yREKVDd0SlnD%uhEVA5zQwi?^)Z4gwfewl25l6uy>}~C1|=RXzQGyB5Sp0#!CQE(>pPCtq|3oZKk5DTht5-)bo1g;lEo(qy& zG}Q&4q{eZoGrLvRf1mq{ceo%vYcIyZ=x#z1kv7|@;JfscH*~byVfxbW2!i>1r9CUh zO4qJ0n?w-0ASftqvQTLp@=i1GgyVeyP2=eA+uuH_a3FqyZl+TVoRvx~Kh(db-~A~% ze6&^Gd|Gix^%tAghodkd@T>Uad;6TBXcz+Q^Cif0Sgu`i89k3vkLZrDY=8(z% zAdIWp^oT$|8h2{Ekg!01c^O}*)a=VLU&J%MKWhhKWx3~zDFZ=OX$~jDvpzi6-HOR; zQp(b|Kum(PphTQ~KD6quR~L1f)0*Nn1-mrPKpAwiNA&Vp2e`381OdF4{=FVdOqywh z9O^=UtfqSEh2V|-1rBB`qz6_F4}m;$&zNPnDRI3RCJGj1Lj&`nnf9wOL|f>)Wl) zZK!kZcY3kZq3^ApyX&M*XEzjyJvcs}o{!htF!#X*dybxio>TLd<0J68xvr}jO%jWv zmfQpTC$c)VpKjfJx|InT->M6uF$Cx;sU+km$-W!by+kDiF6dg^Y+lHSyiVFYv6sxz znm_pMN)Ke^&HJD>Wg3EmPbo2TH~LqnxTmSf`t=*czJK-mo@oJFH@)|o`sIkB6`Qq3 zoh0mrD#AO&LAU;5o#Vb4ilOSKBQo`5)16xrKYq!EJ_^esxja-!x!T0wkxN=;C-?E8 znLb`@Wj={tg)aPmcW17)(1K%nl!8cCC$3x=ghL%~kIy)k914iNk3rHRCd4log6@1e zNL`KM?BsR@CF1Axa|p}P&>P!n&(`qwCd{-EsV=D!P?P=^_#}%TU->4^4mBHpsxm+V?W}Z zYKNv##Vsy{$4|dxbKK^wS3#}MXSu83#PSE(i3JPOXm`ISwhlLzpZu2HST_8lO+i?l zS_}6VQT=|5ky%%3xJ6iRRZ3-tPnjeLlvqnv+(yS#u9ri0cnssp9L~-5ttK8 z6PFGd8Dy-nt3GaNQLyg{Suezb>v|23tM0-_%dMB+2{*PdIH8o`wm&;L!u>h;`E^qA zn}*+&&q)-(5hW3QO5HG&i+7damb+QwtkhU8j)FFJINCwRI%<)kR4!|U_NX)d1XifY zq*J!u3Hua_&~1JEll$v91L#kq;#FtG@eRDzUqfqhNDVd)X>>emv_sB=(S2@ZlT2e) z`BieFyF-O)`DHJu@*r1=kwJy*tglen+S)@@)6jAbAISy=`R%r<&sT2c8W=dZxN8oLzAiq|zMDXrVa`3~~E>~AaS-JLb9V5<+1|G28sgd6lqB z%0kTN<)>m5Ur=DpDrXmo86PeU*jwU1NkmM?hbWphYur_X#AjLPRY3E zA55%LYSA)xKcN(=3XQT16Y^?yAPB;E9}_urvBR>bHA2z4P)^;+$%~rVSxKX$vltC+ zG4VJ;oN5v?;gJ$93wffekQ&fP7E4iNbg=AY!%))jn}HZ9peoR%w^)pJHL2f%pV~=m z=AUHnn7|?(9Kc9(OI|r>rLp&DneYL`4T{Ca@I^njZ(92)?aLM$`m_?<<#uFd>fbCY zp040OUimv*)Bgs|(+~gF%C~fHH9LG=>HaC_xldim`}i!{Kz9{JL* z1M?@`mI(}hoP5)N7X$M_1_ zvE$plxj7PK>)P5di0FFLvFgm<*r)uLi{B{HIAtt%u_zhjYwlKzc)17DpSV^qrImqEv8J$VNijznK&a@&2;Hz3WHffi=9 zGBGZP;kwwX>#YX5LNohXo&M(9%F-izF0B6WfT#mIqxRN9_b&(CpFd6i-t2zw>9-MD z;-!tvwa1^Vtv`@|M$p^w@GO++*({`$!^cq-=A0`-_o0h>QTJnq{AB!xZ8XIK)mVR! z2}HsrN_snUfZX%pTtW|+*3Lu-iX&KS4`Q7<(5CT{d}P8mpMPLfPFfc#b#!u~OPtt* zLw@-wOo|6}L9ti+C(31qgNiwZSNj*LUz=?FCW2cI&r{C>gty*HWJCnW;x~+6|;_vDa6W9;1-VucYwb)thhgl zRRT6?n2pPq z@-cWR=pk*ma2Bnx5g%m8OQlyJjzeM)aeH~G@;^Af5QdL9pb-cF9N^n^71sQ;yu>I> z!4N-cJzRVA(bC3dUbGHm{dEj88j#ALyv1thyo3OQZzDnrbqp!@4s~uH_5OzhrruvzT}~#rp}q&h7`kfc)Cw+PdQqWTd=kLgNXc!Lw~AE z`P`;KQLZ_x1o$!enE2#}sFj2#OrDWtn6Zeg1qzwXB3ox?P83+HC$h%Br0eYQ0@#b! zj{EBRMpx~~y}2rVcM+wtOf1-`Z!9YX%sKA9?6=MUXEAF~HzdW&2ljCIQjWkza5;F1 zjmQq6A`5mZ)qTYK=2u=r*ulJ$SJ71l>0~r_Hzah?hBuwGbinGzE88FBmdj!PDH#Kl z;rEGLw73*FrXZw)18#72=dDF*7Sm9$66xEQlrPk$!9=9Wj4@;m8t*CHU3#h=7we@hy z(+s_+2|Ra`?lot$ou<5M)?`&vXltsjWaCM7Rz zk7W)>d`oaQQnX>mk@{(u%D(1!EG3xz;P$nU5#%$@SYc=#1Eq_}i{7}(;zV=t=(-6| zD)IDfuQTCwng*UN)0bN9z7n^)rE911?I6Vsu(h=?p)Mha=$Q$qi`MFHsX)q&MOt#} zam@-Teyva;f=8f~kOC?BI05huLgxf(hs}hoAXkQ*>Ql8IO$Aqmg!l#FgYqL1TCoND z>T=kbLMk(coJ`{I7!jkNV0SoP_vI!RLYdTbiBS~7)hQf2N;tw-s!e4Nf|+9iwfz_S zROSB(rmc*cSEwwfK;Z@0cP2`f7rbjDD`6)VA`|tnw>qw+5Ts%jn|;}ZSYC1ct7B#ojztvbh{IEOqW`L$+(p(1d zc$eIbO>mm8u?Ayk>~L?QyX(@YDD(1ls2-B#co@pYrZbuVy?e>1jTNnqa5?-{**?eeBphDcr8kg-4dB9$f83#^h zS%fkk6n>$j!|(LC%61|)sCEZ1ngeafWk;@nZ2? zTDwBNViBt)jyJ0zEGl*i`Ko9L8>F@$5a4X;Me&I=@b~!z4Aax^qnL_cYx-=hVg4D2 zXlF3<()v*bH*__ORbHU?3fkY)9(_X8y%B%{OB_k$dl;;NZGF{o6yz?w5!-SpED4qU zyaK(6%amw^p%Yh1_CK!e+%-rZaDX(VP^|L@7Q2#O2tJXh-ctgM6Ovir1c3;!AvhmB z=a7WG3h%&ZBo5p67YT;oO|!zdb$U*18@fnt=>i77I-EAxq^Qyo(T{!2r2HmKIv`3w zgiZ!2xtI<+o@{N;Yn@%=rsq~6;`kahOW``j(}%Ype11e}-9$WgG-u4GJNxVg!i&k`Ev^cKE|M+jy7v0DH@zN0FFkl! z&^-XfUHVM%%h01B=h?13afv8$#HApS0NB$Aw`$x7EPmQ}5tbxlw;o6V7_2x(2n8gZ zqK=kL>N&WijdPA{pS8f@oZbphE7E3(J=WoJvVqJjm%mEqJ?w?r2Cb0pyWa9gkJi?g z78f>_DjHH74zaN}KHuq(sA6Yt&^p2l*xvf=s3)`bY3Jtr7f%U*$n6s?1vO$rKd94$ z+(>iy>%aeBwn4M}lh=s1w4L7%Ec8}ZxRhIZGO~%VT-Tx>zno5OZpQTn-;8NPQqTP` z`E?qmfpi9J#Reehu;TWrY>A9jtP8!$iWC@IGwBtimO-#`xvp-|>bD77U-f{igCr6a zFAe)QTNkE-Q>ha%dDKjV2yyswg`(No2Mdo4gH94X)ypi+LT5^u037g2B}hC6?vzSZ z9C0u^>s^ZQEY1ZN6eKU3UO|To*c;^}O}T-+I%VbJwu6k4!~#W3g2Fvp2V@{@GJ+@32 zsh%OD9g)M3F1EK5Yck4fh7^K z^pi${(HR}pJYKV?u02dwm=_bLSB25mh`U;(gF#9LebXONqA;IojIvNm`RsrQ-1nPI zC88RA%cf|K*nWjlBLq28HzGOSTUNUhTHRLrWK>Td;bv#!U;{Z#{V9d9TI4@ZqB;@z zXN_@B|CxR?acJ&MeAf&NAxWeJS)}e)ux7KXitcI5+0OB*1D#yGWqj!kUk`Udh}oev z^&QI7(7zi?50@4<%SO~6>GN(6rIcX)P+A-*pRKjC3ETZ z@;7#lZr|ycPK>3^pN|)hUtIpiUIi-_$~U#M-fiZbKU`m14avo$YS3ph8`{zx;At6X zx7#Aa%x*Dlvo+7iRgLxg^7r%Fj`jYY-mlHUQ7d?HRI}1AGdug_f!S0@@8vx58%@5)$OoRak7#N$wc6kR%*Uyd%rA7O(ajg z`b)DTi1n&VVLO$JzU4nolpa*~a()oJT>h4cPGh#*Rnx~M?}{=0-e_y0THVv>xtBM< zyT%KAZ_j9Nyiv_LHCE}l8EumMd#~RVhwF|A9p0{;r8Y^`A%JX7=ow}#KFR=&RYgFD zWSEf28eV)y5rv(s;v#)NBpwerGI^mqCT&bbW%G)TQ4bF9b)8=!KskOP7_=b*Oy6{| zNj7(~2M60V@;T(LDh4OQ+pF)>i|xa!h4Y8WrEB7pE(Gf}g&}3Yo_)6R-|_7CYusKhxe)#IKkI+(Ut9TS zEB_bI|3>Y3@?`p_dSFkc=0p1`&Ft?|Po>`}4#9Ro#YyQO{OjSQE^RuoCg0^ET}>kYv82Q^S4(1nA7oF(Ig#=-_>tE80B}LiOV{g zJQi^VaNzsf&0{g{y~>#xI3fT0cYH!tm8d}(8(MP+)N||%iO}RZhyT+NB+;F5cs_>X z#)yZPzk5-&IYgJ;4_0*l`9b; z>(?x%Xc;VRlYU3@JizB&{}!<0s|k4e$UxVf#*PG-NL7lzD~c`jPLWR~jX>TOi3fZG zg2=SQgv8;#Res3i(#M)-4{WTjrX{jRA0F&v3hf7hfpYI)@#T#7If4hob1tw|sTZqO&e6qZ<{BZfv z$_(GaPq#kZ>TLZxpFaKc^Q)g8e>!@4ZNBq^yI12E|M2bkAMnekpZh1Z;0KyN#RKut z!s^n-s+WgGb3PU$stU%qcc_@^!!&gQz^AuaG+cL*WcbJwUxyOBZyt^%tVA zyr?{)(rIhj$Iyprg+fue*u|-6sMMmzwb(=QgCZ1%DMHh|-a4pwLY9E%4YPnI#FVq? zbG&tMcOuC|Q;vu(K4={@1&)a>cE+_%;uUGIv4GU3Ix)1Mtw7a7EjjS=X5n4+vyi3{ zb$!g@FzKymTd7rQKuw*~9!^jlUcBDoKdIhnW6awgGoc1!kSmWULFtwOB#(7W^9v1~#sTMYGr~I2GDs*&KxC+jEgv)VGp;AT&sMgylgDp8;mz zg5>U%1X3_do9d&}isNesc-7Y7*0k4}9ep{*j3niD)F`SQxYoT71cE#B8MpH^7ZFzv z=iXioC)6=K*+XL&W)8m)1VN1x-DsY;d{7#h3ACw(-lNSt1FQ^<(pw3YA$}8>tX5N~ zoc1f3^RzfV5Mh(iS2?TbO>!9+0R0v~oC-Y+nT>R5_^neCN1&_{MJ_MsB_Z3rS||GL zwAHQu6o~)L)@}7rGsUTC0u)e6uUZ*_mhrusOTsu?u=*6o#;dV^b`JkCZeU%dgm$nB zq&B&2K24k~$oE)@@LSuRm$$CJynP*JbpCqB|K&g1LRScmdls_9Es}2o8^a~ZCbZiK zQZB=`(Da&UyLSspg-fCGTFaTbE1Q(P!V{5!rpvAddA!rTbu)6m>Du6efqlw80E1C? z=OW&fuY;U8`JYj;N+c#;G|2#&%v%}a;kKq$fdx)l*J*0rK+>6LS+hr*9?x~=0$((H zq&F>F8~|;wPA&QAF@H?qa%T#cYmKK+dV>DaTdj4*6^$5(QC(hn^Q&2_)y%2s0r`=* zLb=((Ux9YX912#r7?_CE#3Uy=Y#f{ev>(UV#y*ABDLAed^mj0QcsMNwGj0gAZZ3h} zhmu7du`R~Y0fj}H8b!t{bljIvY6yzXTJz3Ho$Jl1ozOG=rGsgG9Lq+0B}AF1$@fA0 zgTpB(VqfwN+n>dnmAMF@7Bm}!XYEpoVdFv+Wc6Lwvu1_i-1=(k(UXS{r4u_pHdW^! zV{aKi$ms+&?yTkD)9D4!824HSQ!@$N(NlPq#%A-|)67}5ug}le3&Sbc>l8AB`jX+w z8ra;MO(#<@G*{D#H8AI8?;K84j`zX^%{$o^UQW+WXCHVQJ=ab}V_v@$5>GBp!qDq8 zR%OOH(3(uKIQr2C zQ^A^1ZbK{;sZ=;{ zE4X0A3WP!b^A#?~PWuzFSzP3Hco7GW+bT9BcVpjAE;_30TO9djkV8!6fGNQ?nBkOP(yJ?e zpg?u+L&D^oHPB&QXl&GfC_2Ouvn~AKJ(nsrP{RItIOr=~AI>*+LFni`t5#T@A<=DK zh~R32({?9GainE%bYM0s@5$vj76x1OV{sn%j)R0{bDxpw0OeK+#LsL;LK#R)avLi% z<0sF}!y1DE<>U>dtQ&-AZYcy65(gTypl_w#6uPbnbQZ|1S-zYG^V~k6Ar4+D|95wtToi%89ELHG<6}z zpe_aPD;~NI+$_PZ{yetDLR@VmwmNUcrIK8|mswI>{rQB1SAWDd^7d?LuhA~!EL&O; zhI)(qS(`4*m}K|zbNzeyMhE_0_Wqj>&*eSO8I^`f z&GlDnBnmcj$AY*`J(|tC7sAGpiAqmRRlPAYp+Xxm}Bdb}PX~UIJtB@&v+2z{e-EA&f0TqQw)n%E<)S9Ae z*Ka6`6(W)bn(iI|)g%iK)ve$${4DdX$vV_87Nd?lxs&!TB?OJ6ER|YCMvTO|Di(ys z*(H!&N1qt<-4>=KhWia5PHG3~gPkn5W~A^HAx_!=)bJ6Kt4K|pX_IT`t@%8$vQSLe zzW>ow%5Z<89SqJ`MzK!&?xX|Q)EQ2qKe1HLhlC@F0pK5nZ9G50F%6s;;(w1-ttIYC zdVH(`iF0W$>#e(pTZ*Ht1IEC-njosSLi;!c0iGgEG%q`7o#v6_opG_Hs!+eCAZF%z zi2=M7W#F0JtBGTFc%_2T8xn-?^0!524jy49` zJ*f}uLHQvrI5-7#LZB#fLgg$~V75GMFeL;RbN~)hk*g;X(>h$0iK)Mhclx}vd#stF@PB6w(XpBHXzwyI2qf6-uXNb(V4qPV$`V|8BGq!*8*xoD zIlXN*KA9-hUBR22NU3Q+t@_KSzVxHCr{lXfZg6IG3SBdzcQSf@L*H)HhVTw!Xq4u4 z3o0dn=WHrhfq>DUX(Gn>3{SmaAOfT${sID}n(#BYmBy+OW#2GDb&*|&PbX%LH|ycv zB%O_1oPYJ%p=y4u(KrIh`O^|lib&iAOpH_8BIHr zZn4hI*7xHy!Suy}74`EcewmScdTNCm-KuN-J!_ZZ6Q&cN8GQ~ z5r7cg#D6EYA!a@~DKTBv`4o~A1W!K8L0!nkBk~P8CTh zx9+}z2Y_W6jL80$)6PT!Bs3uMBf~DE9F0nNDT?eUX^69=$68+l7={!=L+VM@F|u4{ z<%)DEt`KC$FPsF=`UK4n>ZO7VtyASzr*{U##RsXnU2P!31@ATK#C@XWeH|QdcqCnK z-F&_DJsax(hySM9Tk0(-_s_?ht2hB+Za#zZ6Uv(U2o=8Y9h)slj=61$&P&|2rdON2 z(juh*2j@MA+7d+5rdWGz?cf#WF5XmtBO|TiT~FpQgJ0{34Q)k@l^oFkbV0iArJ5$; zbD$e+Vz+Zcb~}FzrdqdwHuJ0c#7VKnuEMtc{C3Y;Hc^7JQRKQe$?745CN5M?UhVmC z_*dgHt0r;i5NmeJPPBodKCmow=-DBe$_AqJnCh ztr-nIKKY<6KiXWIylHY5Q+#!PK*=!bY1Mk38vSJ~;`wP(SyA@&$E7nq7a|d37elS^-kMl|JQadh_{1`+ah@q!N46XdoQJ1|#O8{|1Zy3@p>= zDt9`<^+Q6OXl|rDaiSjah0(DXS`m<7s^bbnM9Ovy^;7*3`p%2W|7G7!uve~<%6aEl z_#vq>MZ%L@Q4yW02XBthEAz~MFK+qf*=n?>@k~QuZgeS*sey*N^zCvr*KbhxJ_{te zpR*+(F48DTu8b~IxT&EiUu1_0Es>37*?XcR-U99dZHkRFEIc(E$ce+cX{<|nQ$Jbq z%nqz_eYjS+#4>gEKotp3(D0-7OnCtXPW|ty?kDvZ^*On0Lv@7rRLfbH6_sc z0>3nsr2+! z7Hf{4Vr%68iESf?K>>gC|tA{4BPE9C9iup=_&4bccY8BY0hR`ke+K6UZt3lf~*nS3YP_ zPy#tyqkgAGd$h>`rIc1KcIB}Oh~KGfH9;9O0c!?}CY5-l$WzC<6%m;4>3BDv)HF&V zdewetw)6(y^M9KUj7RtU--!pps|Yr)9>`Ohd?9Eeq$DAE?GZ9571`y9!^wX&QW~dG zZ&G^?6|weyQk|bTjmz}-v%;jRIJaL-<64nhaZ@1muUC~?P@(wSaro%x!9=54pY zH4DBm%Mmq2A9hw2i9Y=Lq~mOQ`r*o7^7I?CgwxdG>B>K%#UJ%&Ye-U~|6t{RrP1$C z-wEmY|F-gf@ceI29>ao~soDR%`ggxZyFZ(1*Hmdm>(xK|+UlyB|LIio8qb&7u6=Fw zrP_XdvTcgT{6FJy1!1Bb6A-R`@wL@|*z6}YjDA*so}O17r6V!f(Legy>VMemC^bwS z{Z%}7i0BNU9W46g>*QwD>jl<{-^&f~<;-snfp!Djalbw^ZaqkTFad1w3Bxt&_$WVUUiZvMzRh1BD57caD zH>@tdaXff=@0Fe8rIbaP06#Qq=ffm018M*G!Oyi z+Q`Q?T3$)K=dvGIUiSi$!WzZNXz=`KfDs0^M_G~Fa~O1L?W+r@Z3IbnTa`H{AXqhs zxcRYE*H?P3vD9;6!y#ei=;Vlcjm;=jL_Ftr$-rk;=PN|4J|Q%?zwnXjm16`=W8War zL+@6rb1fS)@lS>MRMM~c_LWC#%NtAmNItW+zQKE)cHk@YoQl6#c=X};r1}vI)=z=F z`V`o#PXmQ#ps7t^LYxvp63D9F7dBUJEfz{SBf+j``HRY&tCoH0kcH6)|v*_?;p^igpxa8GDcGI`{+;=Y;9##Da)h$vBnA(6RaL% zFz9|zslGn986e>2_$Y65(!b@JExpzTX| zl(2kNH)9JbyrmfDQOW^pjlV7TxN0{xt&)1w<`{#GU3$4QgYuQf%uJN5~+Yli(lmZv~T?hY|zU+Jp({5 z)XC_cqm+YsMn>7#d4`%6yz9dlezWO}!t|$S;fKkF;LmC!@y#zJID{!Nu9f)Z@g>R( zk7^n`+sCT%%nH8%Fws}TQ&oVjytK4wgT{`v2U{ZbPwRF9{lIITL5~^~R6ZdLdhF2A zww}ZWwbABhbk{!XFRh(lXCVDco8ptzY5#OUXtZyryE;pxH8?yw@kcVl``@eW`3VG? z(m0af;^YvJfRJNV?t~s+9IhJGq8Ymqscli1(cZsza)(uWCgMj?2E69>Ai5^VP2cKE zrs+>Z>L7h>z$qEtd(TAsG6ot@>op>GJq9}ur`?<#+R4}W!ID3|Q zqllabubwj}H9-daDz0O^QgsnLfCNY)f0rg)$M#W9+h30L$-ZL~z}yR%G=H5~fRF1h zLWA=qR9$`{Yu75-&z7@mbo5^Bb0rh|@J))=o=jb=uB5b&A%u_N$u^v<;Y}WG3bs_t zXz*%IawW%m8~R}e^w}viVW324E4i!&C%XndLG~-dbT0Q=Ers+R)r3HCZvW-PzBt;b zdRX&Rf>)riGMcHx3Zb@hPeoszDpb`-66(YQ3wtaYWOTmZs- zKW+|3!{!g(?9w<5ORMy$`8dJcw?QiOTAJteeCBIBUvFL0`w;)lV8BH3P=L9=KeybS z3Mp!A=_JGxaph2XYxfWqTLOMuz{%;0TInurK>|81;wCm!cTZZ3W+HN>ZJeTu8dsE8 z4|M<^Ghlc(Ioc#RmTZ&HE)9@Z9e%wtSwx+qTp!2irc28|W=ngW^0pzXWqB(-SGv|% z1n=hcYTgwpHU&yM7JR9m-<}9&oO_F8u*MWt2G>#qH#ffbS(_p(qwd0UT9D48;wZnU zkW=jweuVxkeQCCMMs{P27e&|Yi?wRvD&f0^q}o39tW9AXgD9em)s{9}sFiL5scM_p zTvpxB`iMUiK_Yv-hcTMgPLI0De^b{)eo#b@{6qd%1B27iwJ%}-tu{0_)4yukvpmsf za*j_tpF|(EOEOAq(#M;dk1eN6&s}XV1$dVfIW~1@(6p<;CnQ4MRRi6ZFbmEyH`@Uu z$e;NxPDk`A654(ZRc!qH6#+!fVclwcI25GgCDH;aUoe1+FHFk#8daWNUeG}O!Gr3o z=>nS#O=yp4S{$;Y13eN{6NRI0yuKp z(iVMuyqEZxFK{o-zaS3aBU^K590|n&m*ct!((C<<9;*>p3Yt%G<3bj9lYo2!jh;Y+ znW#UF_Dm>1`Qk>vD1}Ikv#q8935gqid{xmn8x7t4Ys2f+{X3x&YBr+A_uPUh% z2`<#Z=rmLVfoQ_61|_dnQH^Jtvq=Ya5P5s6X|g+V5Icp%pIdp%?|;<1SSR#;D?eV@q0t{tG%8nj>S}N01+D(>M62edm6{%{{QX&@ zCc>Q>{ezW%Orzgv_Lo$j8+v9vV`EBI5l+3~U*7<|pMM$LmuMOH;TA)Wh?emWb6z`W z?(UF6TwMHQ%R$9>`}eG3d~hFx9_-z)*F2Z+A=rbDA6H*`gL_k+-+0)d-&+7@a3TyR zS3A>UB<6=bIrZeA>E!y%`zrq!-mr>6?}nGNGAJu(;81Bsq3GM&Q!qNo^0spMELfbd z30t+ZD7H!B(YtzQZ%-M6HKzh0MaL+6Hf|-aK(a$e+W0GY3(2VcS?Rk3r7X&e&x>1P~{&CC@`cORF;Jt=^I)4R$hs!{b7+u*xUwUCso}jD4F%^zX z0YcKpk}m)tsfj@F%+5u>(G5wsAs+(B-eM2Px4gMzKC|^LTp-ZSpqzfhQ-|chTRRolpx^0>#nbSXCK#(M1BOx0c=spuVz-HPx2RI#n@PG9iKp zVrZJHm(s2D?3o?T15|ri{CH_`McBmks!Zs3n}S}1=@>i-VtX%I@+DcQ<%0w;W zZX{VzEQ7f)e7%|A3s!jH@iH#VW44=KT+8$Du=pbo19U~+l zoLhTW)|VbGY%Z@o>aS3JCaE2xCX`qc3dE~yojz*24@VdJn8Uz|f^il$23xCBz_mS9 zp*#4`B#qS&(pP*uY+z>XccW%DKBaBWan6_O_y_Wj);_sb@-aZwxnwUTDh_x z8-eAhuGA37Er~MtGy}IK98{2<*|xIE3P)}Do1nby6h|8$a4ZTEacMKUm72Yfow zetYr`;!@gN%cr2+SmT=4cKescZ75P%leWf4ryNzAE-4Q6fQv4F7LznzeS+Cq!cp4Zz@d^fDo0`ufr z=Yc%F{s0T4MhYYl)jUEY8rKE03$!hisj*TOo&2hFRRd1Zum-}a#jl&bs?V5-K56?1 z3~0N?N@HHE%?~QN5=+8w>BBYo8P&-C^~Ukp5{`x|uS5x5?9$!TNhJeIxvGV(7l6q1 zzh|?~Z*#&Lv}5|D)oH-x2Msb3`^ug9fMgNk7oES!Jc{Dr#Erz&Pl=+sl)%a9=mt7T zz7XEf?d|%w+uI~kih~=1KvY}MbxHqn%RR#UPi&&!-DD)-kw3+r1f07(w@fe~bmIB* zi@IDOHx0=JBmf_{xY4TR0r%ssEp<_p4jyCz?t60~JIpZw!LPtNrQ)(^!N{qeEa_<^ z)d*JA7mQNmrU)J+^B6%E+DW*1A}2si zUPZV?@9hf=btc(NpR%<&kHTFG<4ShO9ETB_iGW>RfL$2xf^smU^)P-(-aF`nFl?oZ zP=Y+)x?SPG7@<95fYI$z{wUoN6YwssJ$ba*`L;{@kSNnDsjX>Wf8jsSrIN<`R1i_Ul4F%FG5Hel(sWXpkZ;Tq_mYa}k5?X` zBKkXT;1W{9k5)dV;UCVXbE!>#Wkj1ln1L>-!THMPN$GS6Ojabl85%da6pm0beSK0z z^G{~#mMr0*TRORE-4b{iqD$9eOInj8+YlmMDTP>Xlu%alK=dA;@1RKu8DF8%$os%iM9@_{42o-{JnGa0?5lMq3^)61Gb2 zbjn%}_Xp(OLi^=x>ezd(bnP!~0%$O{x2HCj4ny_|M_@)PmCZ?+5V{O-84C4tO8cVW z>CvmIgyO8_TP5NR4WvJg`=kM(*Unf8Fwk332ns_aCS7ujBK=h>N4Kt-9))DMRu*GL zSkSngQRay-#t4e)5M5Uq6nlM3Yv*O5A8I8^8iv8kjc-OsWRi7Xsi29H1ELi1xfrzG z>Am}%)vgR5QS^jfY?sVgC%I85;--LQPkGbQT!^IyW3+O!Bv}U0ZYv2)$jY50&Ym38 zeXwiuOmriPqEO2I0QbU!pNB4v9+L#_`_p;o?=nf0mN^q->*4wnc{?yyK%iEh;Y%xi zWJ!+-&62;3H-jsrkrC38tlqicQ2sd`T$)$Pb)WJnSpP?kOyz=2Qy2S;RDQ)>XT(ay zKOzgjG);|*hisdX%tV=|M1Ww|MP7e7A4$#Zau3L+51`c?*#QuImnJugBT4(`ebk|3 zua00eT5Z^pkr9JD2g=4H#T^*{f=5W2GZ5kA)p1)mMISHF+(y;Gj%0gq|G|A?L5I5o z`U0J#x)^p(_i<&^8C5A6E0cvY1Ku~*s_s0dkZ01nDkk)7Feb5$`jf^j%T`Nq zJUHxKSzKFvys*9$Ri@E{b-cTNF7nhaquhe{mtMfPAMSp^rl*QB4Q=>FVplkO(zOVVZQ;H-G_Tdl@cXr@=AX3q2Q|hUlt#+ zHUC#!SA4dcq_$_^f5^&Jg6>1Ve1u6=lXAl+|~Bom`fFq=&pTAGL-ioT9< zDH7Dd6MVb3w>pv{o2tK2> zUcKjsCp(?CCY*g1Gu@+7{eXD9j0&}vYKyF03->R{MP;=&&M9BTwePnpq)7{B-Y{_{ zhH(?7BXf3Tz|7FusvZVRv_Z7ob^>3Q1VvM(qw7w{+Y<*Xv0Y+E0Ku!x3Mrnk;@wdG z7%NG6_MEEPVjbLxvU6`dS#7y6vIYwV@Z|wq04EVoX-VS(wz`&k`BG+c1CkmC0x|^B zD0$+eH7szrR8Z2LHITIzueZVZq0e+1*J>{HK>#x13U1r9pe44m$9#lw5CWoHNHkCp zqtrpu${_H#9vV>A_U~SWfk|~F&BvF?i{6;)S{*Wl2Nkfexc98p5D}{lEFz+RxwIagTEX(BJ4mB_gAlzjW!Pymtj z<00FMfFJq)zWwd%p#n-4EDX5Ry>NX{EtX;pG8w|2r9|t4!!CY?FGO_^g2)uIPw4si zF-(dRvl}xDT04PCi6lc}Y4-7)Xw-f1=kSnJj&PGEi;7cyo)8@1Wn_AOAb}*|8An5$ z4ZrhS=gzw?2#yx@2%iS?V((t|x^F7wJ3 z!z5{H^WLW&w|u7xv0PqS9mo$W7g{0Ig0RcTw4%pdM4!<31?z#h>8m;YmZa@#iNmn? zfpmH9K$6T-xFdBo{g;^yw)HvkUt|O$t#?I`hY-D5My}~D76+%gS!2C-%!`T?z6$s0T$RB&a(OjKyYZ^%WD{k=8~g%oB-w4l$iR49`>lW&MtE1kakj8T$gSn zE`f-Vv;B+KU;lgmxOMw`Z|Ebx$eph}tUo9r;!lLlkPrpPryX9|l`oDWglZzaWR zlWlv$_{9%|Ly4Jrnupu-cD$hnc&Q?uX$sZB^@;asedFsRyZyL+e0Q+-(*f#5)HxBF zi0p==FEnlU4PB&z+yRGB9>5Imt7wwy#bya6pNsYI)j($g*DQ9>i*7okvuF`DpBM9q zLCyXZTwqx(liZE+$xL58!|Z+3ywUQDD&tXR&7=tu|)dbX#JFZ#gk2hmtSn$$4Fp-WWtm{GH z1x^7@{pqicC4!_eXR+&z4Uk7_6I&V`R(3^oT_0OXEEAj92~iM{!TG0m-tMIx%a8e` zLG=>ExwZ-kJ1175jT=NK~IE`ab zxC0+LjOh)HQ$8%}L#QjDwCcG(pR%&X&xLuVgXU(|H`1(nS!Ud{8V7vp>1Tr~BTTih z&xOBlJ6PGCnS<4zezr4fusmO{U)iGP%;9<2q$G&eCknruTwFNcQlB*X$r3wak50f$ z1{`>yS;>>FlG&%Y@uUhU(q)q6J8ut7U3(L1!KmeA4b)z8o>YCM@K!aipM-cTFU1Q< z`&pSQvZ;*&P)Sp2(u_Yy>-HJGSNi`J=B<zHb{YN*(qe&6pcnB;!>Zdm* zwIHYQewq{QtZ*^L(Puma-1Hn!rHl}`wmHYoN+tyHW1x!sr8%Sqx0piuc)R-ePWAEK zpzE-VL}+>+~!C>PCuDV28P8di>wbCQpG09 zWuY~PowgG$444Zh$qpByM*%DgT-?s8Ybm!!_AQmCl+qn$P_$awZ|Rvo7{x5FdyhayU0LemrmXQ(7(RQPiAc>~fYbW5e96G`5(?_uT09g5C z@1DtHJxxqH1FRpIB86A71ZnjKl-mkD9$nb-ljLX?_N4WTcW;tLZdb7YX?hB9#s`!Y zbaZd`;quB7!ueoCVo<76qU<^Vmn~VscA`sDQxr;(_aa>W=y+hsuuHLDMU=}T+`Dp> z4ptX_+<&yR{L#nv$yCvQOs`i-!zW=#vkO7mW;0n|@jajqM-F&?HmRb+aqO6gsq{HzXGoiU;3UqZih1Q(#v!1K z3OztG%v+4Ed{ukW4m!CvZcJzU=#^3I>ZfzOMx~O_7$P#5V@V0F0&HlpCnPfDu)I#2 zYn!m|UZ0J-R%r$$qs~r{j+h_g!XfrrYomkb2N>#-Rhkfi(B8;uoy-_n4?}TL*}7?g z{g-9hMbHmj0XTydFsrfvQ*VdbnNCjk2bkj`Lk@y8iDQrD&`)*V`;^SHQMiURs7#O_ z=_9a0jsr1>tCWmz16Pt5O=j90-n()Mrf`RR*U##!!;g2emuWf;WP*Yy>;@A^2WSPE@i_=SS(grvO4t6^Pzz7~3|k3vI|k3=Vv@7NpqsEGJ{5bphRJoRD`B~*xDRBD?E za-IS4%|bm~W1dX!ymb_5_hqmkb#h)?tnU<@ZHpnUn@5`BQ$j)lkQg^b|2+D ztWI7wZ6_;ai8?gRU`xPDVF+!?SsMneGv(-zoYrWnvy;)_s0C$PT2)l&{l zI&Z-BIn~WP+t`M!vk+ydL>ZEz*< zq^=ieF7=ceEzd;u$Hsek@wGv0q4LODAWqgAcL2VrLTymM+jqLXQ-bVgGYkZ zA+_ES3BYioa;8!Xa*Z5@*|!EsvH%kWY!-{AxV#Kr!%PpyGFPEk7l+30FOH$6N;xae zQ2^*K@pn@GYAT5rlMrM)7>vjt_(|4?FzaHEul3-#u2x6&b?~%1G=r+#W*0-^e~OJA zeA4yF5r^iV)LySMgssjqE)Catl@*bby>p=ZzP4;-wfpA5sT|{rl7riA#i_6L{ZOQ@ zay^ihD7HwSWI^Yt_fg;N5$9bhS1IeW?af!-byq#b&oyra-feP?Z4(D87rA!26tvo` zWeo}qNok~=^W7J0rgFfkVj=Z=x~>kItI=u$EW*VeRX}Wz$8Y)3(!>78h&=uEh4tml zpMX_W{QymY1%PmeYeyMdTijf*!mH?!yfE(_4vu#AaEZYws$iYmB%M+!U{0lK=IC(7{oD1)O*cyQLfJX$hQ@t`E>PZVp3c_Y=%y!{f8UrePLGTE3>57|r zEIicxApg%iX5buPcp$4-qG+c)nQ1R`U^?M7HfwVAvvno_(zi-!da2H}V#wg0_+Q4C z_Ye{_l7IyL(4 z%AeEdcPG5g(!<4-AM)_G8_MJKXmjO1=F#7*Z)JM&pRWAZJo$Q2rVc~Po1Xr+EB`%D zf2S$!r)U4m>erpwIHOEny?DI(2VYyg&U0rRxn$ms?3gih{65{Uf1d(Izn=g5Gb2EL zJBNkjq$2;*KXu?o1Vd0PlnV#L#`k*P#gqVp0DakTO$m9H9}bo7Fmx%a!_kYwVRzx9 z$}~(1DyIsCppZ?8gX4C6PW?BzjI$z{-l}2hojGXa>b9| zz(1HBxpkX=PYs_-ZakK--#ss4sNB?@cx%}D>%aP|)@O>x!zM_sOHo4nCzWs*EdzIu7_Pl9czJNXcc6GNFPA7E zN?tP`_64%5(ear9O@3E)*@N`IjFx;*s4oHxnP zq-;qEqnDMvks||}@nGr0g(nX;`w#B-A1`cv42hP-uD5@pWCYUO_tGhB>q|b7xYF|O z2F}i_3wjf+wFWJbXVt;-)~ZJMMF)Bo3`TdjHCm z#r35HQq*iN+<&;#TK>>JflEJL-q_qoYwz-u$+vDMmK`tfG#@%r-W!un5ID@#9# zJ2>ir`Prkj&DNtQ4Ev@G@dyp&^_~GOO z1M{j_Yt7E7l6}HDd-$>=8i~XtQY(wHSRa-S*5?h-7n+f#kiR>!UkqCQo7!WyS zDtdo#`_6l^4IP=%`&^p?DBY>BP5rNdB(V@F;e_)F)|&>hWrT{hCUA{L=}V(u!b5$y zT61ar<_cRf>s|d8>5Mw=fB8|XQ{KEjr?sBL5#D{&h$m$wPKk+1e`ybWh;#r73@H(h zZ4bF|{a-O^2q8vwGO&+wKd@o=ck)b%zBO>3OJ9#uU6ojUM+f z)h4B$NfZ$GW^TBYQ&YN=M9v)QA}*SQ1q8{NhItSqI12KjInbq!_kc8(*vvj&T6h2) zW|pwxEkEnZOw?Vqnfiv_=cf!tcjJHyl)CiTxo*CzA>>(^)q1$Js#t{c0NR3xo81Lr zu87{+z(|eA1?6v^a!@o@0TZGpX59ndVRN)NS{A6ey2#1Ul=lcZR_su#ZATfUi!u!+ z$Flow!G3tvdhNWKv#zbYJ0u=FJFVYd<$*X4;hT@t)I|nKf8M~x>Tr67T&%HosfRcO ze&i*J$!B_AXhE%6S}_ljP`&oFwt~5nc>3YmI)>>-x^hYPosnCUnQyHxeYmu~^k{Ku zW7YwPHlTFM*|4~$n6O?_caCMSE+RjC>Hui?Y?yc#nqB z0z4#(fh!7}!$6ZsEB7d{)R*~KRGWF->Rd`|;mPLO@*}9gs%lp#krx`aJ^3f>on!XH zxDIDw_hF8rdOICqHlRS6xE`H6pU@L@<$Ov?%`{JYz&lp^<-y1<55Wm5E&W(s4W4TW zuz_#F=QQ_D4nwc!a{@y;#41H&>X*U~1&|sTU}C-6a;Wk|WeRX-Sn*F3yK!jq4C79CXw)wo!CZ@gG8p}GB&vrBk_#0a<-GXiRQeNF-q{|MU)FOU;YHs%|9 z`Wrm8Uvihl_Vu-Vx)S4Sr>thW%9c5!!m7kKB2X!?yA!h42lpsUt{U)4X?N2ZJ*@+b zzIvsvH=%|qB77~4^Od@KUw z4pmQrBdBk9PQlaM?_%g5ijK2vTqp@t(eyDsaO2i5?%e#QBp4~9tjpF&fB;2;Rc0I@mYf&D5V3P14E{Pr>)V$XjG?}cIQ6fM1twCV^I*WrbI>XLgVCy_+{Sk;S(>>zPQ z-MOMOlH@)6ify2ISpi6ST4Z?60#s6qG~|==$}cIK%wV4K(DSWdP29230_aQRtnzu> zO$Lajc|xrJwWfw&iu^Oo9V~SiJf@V>B)zd_8b^h(Jr&*ulciJ?hKC0G)*DfYnHPjeT9{*)_MMT34}<|*s9(h$mri-nwIBg1!mphfjP-o`{|EL)0ekW4BPsbLL?!M7Vs= z)ssic+krm!L96|vbA))fr7ClPH9@(u_2$o`||6l`cDkE47? z^Xo}nD>!m5XY8GSp=rIhe8dK$>Ugrrszv+bDG5D$ro8s zGed*XXaKkR4AKh#NNftF^75HNiw)U3-{paHjS??T&JUeULs`r6?v|Yu?<$=UwRs4i z(FUq3H15ergwLIGA!>V~|Je4@)6Vb$ExX5u#lcT6qIV#{B=Hcg)1~$_Wabn>e6Bmf zi!iZ_+SNFmO!t$0&QwNPT#$Tr$N^l#pBkO$wV;Tsh=evnn&%od(O3}80hR;TXS3t4 zaMzW6G#w6BV($b>HjIVEN-?LUrMuh_=NL=C4LK#szTS7cx zHb+oW<+GAGqe|BUYjXQ|nOZRmcwEwks#+TO3YVafod=-|bq{5pDoT@ROTwLzY#I9} z5&_cRB{ad~c*eQmtbdb^bFy=jgg`8=ULnNwysO-N)z+W}71b)MeLbd^=>_{POPPFi zlOXnB;iI1F68HB8&qJEJmmY0OIisCL>_++mNx1S+zzAykks?oe$;?ZlVZo#j*=PBj zkdIF+_Yq-&H}a)%BQ}#fGPx^A0-g~VEvQyp0b|Kbin53r2GnYzVvjG4V#W?gi2Hg>NPycho_TfzpcvnO!;IOZjtf z3~aU@gI_7GHSP`PKkeSWdHcQY&3C(0>vS)THLdS-MO<=|B!gCs)I?UGFVQEnve_$3 zt71EA?KgXB)k|D_r5-I$NwqQ6;|vy&o@rRNgRU<)!gojt_^UsB7!R2>kjwQoJ-nCgq(3p~Y z&YJfzSrzMl`2wy9j!hd`Tue3S{C1P*g!v;{PQq;btB;sJvlzy2$;0y8AG3^l7DH7& zAdR8woU~BD*X-wkA{U?A?%0=sCViBV=JN>n_`DbpKPOSTM@p$K8(N+E02xv%RO*&i zX$Fn%lEdAVZR4f=q#RXy0MKO%O;7y#q?1M7mF$u67N;}zI!#FjslNH0`c#wQ=fk?k zB4HfQ@20r!OlFY7b;pkEac%#_8N}0Mt(o9$qAR~c<|m6;#F-W_bBo~H5a)X$<~ zFo#7!#mc$GOF)1*$R3$SCT{uH_R!bjl8I|be%Br)`5Oc2mLuvwRuh{}79B#UzLY}w zh6|n(9>f%qXOVjkW)`X{^NF}yUq(ros?OE{)ivILlNA`D-p$_&F-XW(+ucBkGo-cS zrmxal;?7L;ttMCSadvl;i%Iheou>{#JbVkXk>@?`mx)0;%CDXLYa$w}L+q(x8@723 zfnn_#D)o{gG-TzIQ>1^%X*MgAj5iM9&|RoKE;-SU)F)Ed*)|*x)SuW6QauQ*?4uBp z)Qx0zxRF)cwg!yN2)Kh_AV34kvQRj!b;=cvrvJG$E6;{p0tP5>oP@<(_)+Jgr`O+n zkE#V~_mFFn9@bj;yk~jKYS@zf2x%uHI`;~5Ru~tjAjQW;%D~X)H%VJ^1PP3jXal2j z@KU4Qf4FwP@+QjTPyEYB!@b*g?%eub>z&)w{~Wvua_WxGWq|nAI@;SW@VtFTucrZ0 zKM9;)sUJuB_Lba%iOnFc%aUbY(-d zL5HY4qz1H#3*}bU)o9Q8BNbxquuYEiHk?0UD?9JK%eOX6tnw^SwW0RI7dCnmQi6Hh zLXD&Rpj)_Mq#JU4K|*yYZWDS3IIRUdMY~x!0|`j_AZXMdtA-*DTr7*Ae*8BZ zXH&ZxpE}ttOD1+#wbm^hU#v$7@mv$XJ;z6V#ve2&f$x4o(BT?oTGr`j>pWa zuIx$@Z>k`b9B8=qH-VDVxrf)l`1k`e0=>`SDpgm8xB6#MGDL2sTwR3k1%pP0F@C^>05AWt+t*drw{;&6^s>X<+`&T5J>PA zL0f!0Z^EG9Jxx2Hc1>YO4rf|FW)Ra9f{G9VF0SkFLK7DqL}aD0zzdY@Iy^#4qkP(6 z$vGK>(xv{R<@HUBj59;rVl?4I>&eFQqmNpAx|6+rJeMHy6<#;KYb%KWg0COmyA@Bo zcqI9Qb)1v;5;UD;v%6@K-@7%J&)$QiQUYwyA@<)`uhNmM6f%$(1O?xvYo-fIeSogXVIRaP=}qUuxxEr2qpEtt^o*luJg z;JTZ$Ii#!zfhUGf^;FbBg3#+E$IH`!@yl2kX?X0qwu?+~8Oh`POY{&^MHL4rHWW!= zd~#kK(Y}y`6S_`QKP*2D>gSD!Rf_}SAOibhvhadCD|W`|+;<{w)p3!itSP+)<`R{f z4jAMUyN6AI5jb?Kdkf{>sbW&0WouqMK4Y~c{YEB7I%U>^r@g|o593#6VH>Bs@))(M zhrPb^_~F7LaipRT1&*NgG#_8t#;bH*rLWgUq z>Fi;bvHU6^#AmW9;S!2H^D34HwR9{xfuTlR7S&0@NdqePVzDfVKg+|V4Dq3@_9+XS zk?yWYx0XVu^ZJO>Cg3$c#hR^Tg{V85MM8srS|3KCwD1T7Fc=-GXgEFx_Dnlox80D) zqEY-ePP^}lm)E;kIDB!Z8n7(muR=71NBm)fsS%` zmR%k#{Ro50fMRO9zJ>F=Lq&(p&$olMe|*V`*IsMG*8;~$hIufPL@AKh7)K|^Zs4ek z2!AGA8Ol{koYa;m*kciu?EfsKzX(h$vpND3oRTyzRRm9oh?Hy)x~i0I%-}JSz1uJa zCElr4DkxLsgoS1O!9pCWL>sk7L0=>FOI{DpNeO?fuuu5o1rGga^h`A2Ax3ty5?S+= zCIH;2{*1Z`!x-2gn#SSg^1=fLs#XIwcsfj$yJ*f>T67ao++8f{a-@$Q)K`vW5Esmf zPA?dIiPC;Ti%pa@#gQzagLAx!z*R*qIm%GI<#qN+AzOrm3Rz)PS9EZn{agM90^-$*CqLt2PLtRBd>~1%A=~Bq8A8&&l zsZMt&cG=)WgCRT6fm)$%b)!8Kb#TFLQHHdP5Ed5+%CtpQXYvbKD6+ zmQ|($b2=HOsA_?`5FNi?jNHzcE7VK1zljD@jorC&5zn&MrKwYo1|>e{Aj`6l%En(7 zDr>^*EZcGMjgij)e=`*$F;YxoqKOrSje*mbto*CrRB#;%*^hEq=mGPIygru?2|gLs_iM9Yh{DKGe= zwMeZIo#s})Qt4Kp%`{^d;QaxFG@-tMCizCevdJKU9NAdg#7lUCM0F<_gSW6jWqeE9 zfKoO8QZO)>DAcN7qNB|(rtO;DRWM?2-Ip@~*xM!dUV)WA8FAkpJfRAkFcZ868YM-t zG=o|G5m!^#>aNOUqNt|W*cO2jE1tp*n`_s#1F{=mJ@Igzp}rLr#Megu)K1MIc#+(IOGrayOsPAJm*31}8x3SBRw zB~OOay4%{yETT8Iw_@4UiPlpPvc$%qm|)_5<#`y4+g#i}`KZ0=hA@C=cBpe|Djhf) zbjB32b~PkomDiOJgG43{iw(7!mwT!1V zcBs~Sw%^FZelJt+oW{vjK2k2J-eSDTT^ecc$keokMv^U+z~g&7bxspBXtGykTnfX# zlB?rc8UZ1SL_FqdcLj8lr1eY<-zRs%$df=}WZMy@F6<2H z;^!M$cUCUxr=BSl`Y$eioa3&Mb9OwT2(nqjO!Hph3TvRMy@mJn%D&vk}&KlcBgB9wy@^ZJZA%GgZSg6ss*B)1BcRS32oH5 z)+(_d`e^?!5tnP|wey!8)o`u2&nI8?wB+)sg@Byk<}5nGkr!MJm(Wc{sMpy(PS^4% zqwqjoq~k(5JVbIrxAVh?I7I}Al|OE4;lYE};@ZO}tB<5}TkG7KS8RTymvdyMJ%1fH z!E=siWKj=;r{;?x{aGg&7l#jOd~m>efgsh5}rThtjZFBDn?F5_d>KQ$qZU?$fK ztqf>TC3~lcMblhsE9;DTo)CWa@|sH|64jH${_r}Ma#+iUSQ$bOm%S|nwjL#q=AdQn z$_6V9q?A0{NlvN_Y9VPls=AK4FmzvFbUrC)(f66X*1RH6pkC{yQB|WI8 z!%Dzwj3Ga|p|rl4=rIi?9mK8v)mB?eLeWGm3f~jsc-%`QrJQ3ALM-~T6C9$83%ZeZ zzC9mR2DlL0)%@Ddfni4UklIKBK!1%>Uw+k-cFnn4oLW|G#>uE*S2ae6u~Dm2UFff! z1+&ZywCYh*t%=5Oy)6|Uu{BjELCQ4qd^Ue`^Ufno@mpo4H)jKuiNkLav^>UF1a69Q z{pMht8p_x+YsJ!Ba+uF=4y1{J-V&W1Rdfj=Pxfdc^HxDb?sYb5=b#m-`G0eZQ6J^f zt;vlPKl7Uh#Zfwvq3T#-qII?PraOk1BlNvQ9Hmt@G!{o-rgbB zlvhyX*|f2}vGj0>fLxf4C{`TYM<4k@Htk3|qEL-{bEeXBE$4%WuKz#necf+eS9YI0 zZZQdCcQR=vO_2gQxlF4|TfCC(aWf;E_D~`<)=-obNghv!7A`NzOX^zuntMq}99cn& z0{LjBKtJ4vJ_P7#02ojEj8~RDP zN#sF5#={-&(_s^G&X)6t4mWVq9#mLoQ5fc<5WQ*O^Bzhd%5@0@m^Uo|7;?6S(inqX z3IHcC;J7R_Tf{X|kER9ad%^FQcvlka&PC*ZvE4~MmAg}f5>DNqs{4J*{2aqN^Ked= z*#biSQsH&6zOM?zqO%;1Qx5Vo^rqQi6^oOR_zn~#*=wD!ZsLQSAz`IYstZH&ROd0nfJ`8*txiqO+WG|p zOQ3Prk83Q?w>FfxSmu3gG%T_sMUauXIa7wD`na?pl-XQsEedg=c0%hYEh_Tj=abzr zzxxAtQIG+FW}@Yk@~T{~kBn0)L9+F%Qrk$~kj|LsPR%nKYH!`3>=i;N4{(8*MLv7= z0>&a~s&I3IbESJU*pGPzQfo_Wn4+gJJMu@!wL!jz9Mc`4kNf*EhWhXrk}U~CAd{-vqM9p zSLT|8dwMERk}SY0JJTOR!G;ii-5T_xGdU^a;tLfU9ZbQ@!;Uvlyp@2ZxkOc4bTw5^ zbc2Q~Imw+8mjWOgu<7i{#*lP=K~F~dVip|>piF`asg7imheHGr%6!RAq1dDRK&C*` z;4{!JkUmiya%>yWNQxT~8Tfel%8D5(N*Rta7wv}X1%7KVIg(sqScPpCTPt!1R~sfz zBnb>!Jq+A;@K_ZRzAR{PoqXWLp#4&YaYapJWaR{4@QOhgS3C%XrzIA-Nsf zgZ3hI$H9J?%?mH4^dH-wA;}&4H&?*3CAwpKSjAC6iLx%N&iT)j`A}_thBS8(KEQll zgL3#O);y*E=SgG7={`>?JGRI1JaalbwWoa^n0c0zc5GiHCGdhxd|vKvRBxU;TUtAI z;CkJ*0i+Upp44{i&jOS9TkWUVnKaXoqb_c3?X%)fpRA3c>4nc5Dem~4$$crtEB3{? zn1!E@j2LW1$EDb;e%+-{beldidmTG^;S6^CI0>%&EBl!O%uM(GJn+nhnPO|nIu1dq zoJ~};XH(O!b;!m2c3(03*zet%quwcs@w5R=9koxP+}d!n|9taMaVST{`T)yeylxv{bqdc*)3xGxU8a4UQA){)+Wy-dl2w6*i;`d0y&YNgp z#OZvZKcN?1wa5|X_U~p-$zFcGX)Zq>d1XIQb9Lyu4!*u8k!PX}_;`%SaH9FkeWtz! z+wn`k&-HDVYOj96)22@$7M-QrH*a}VW8>p#-<)Rc7H5tkLW`@Y2Y9og`E~NvAX=R( zH&<7$-SyWfWr~Vu)w2Ep6Fr3#c5dIie*N;|m6fblWK^9DgED!lRM%90{{p4mV(@d! zNr<=&CYTJC2;=Q7zog}lgE0C1i!e@zuHLDMuaw=AIE+w`B(nw+5efhnej)1TtH`eM z)=)1T{j9QUv2v)G)IktWCAl(z?qC-Vu1(2yiug(yS^fNth_A(rQNn==J(plL=qLNT zqX(F+iPQ|2G@G2uz;vdCmy(xYT3-*W0!b~53;#%cq{rkS@YtMnGlMua6O6X!RaB7g z2;WnAiaDbnW~P*Iry~u;0ZbGxrT9FKf;26%MK7gzly{A)PazlKQ?h4#;y;D>lsNEd z>{}^iXYF4~@m{Yqh~W|R0n%;%zLetI&@hU~xfkB^!1JXPAFAidL+g1!_u^7~d1Kcy zN^_g@JGeLuFQxi;eKFU^OQ{|pNCFg5rITqUf3Z@1b0#?&!<6GW(aAx+)BwovLKPBZ z$0p?df6??bR~E3qG&$if=_PB3{8C#W(tkE>L6WDR!^dTsVcbJGGTy)h-d3mFAn_|~ zh009EbVRwm7SsW?X>cJ8#^+vj#{({O`MS*;CGX4_O)IL|?PZ4MpJD~w`Yg*cQY9h% zNfgIjQnWY?Hz;SuWHTav>QzE8ji}hRE)WeyTQ!1S2AUBIG{I+15jyZaLDDFsV?a(O z%MPt{2l(?L1XRh`OP3KWv%4K4lWNf+Ni`0S zTwyH}_)II>Z)O(K8?vgSx;agNNU((<4*B@AGkO9ccmlp8NW$EO#khax(hjdSX^E*0sj9gyoTfz;~yAS<-nzsiv42keTJzx$bomJ0y_8tHrx_7q5JbQ_E9jjqPIgPg3-!BYa|Cs3MMnPFodU|SS%18Jlzry5U? zrzS>F05T@+SP{@83JoiSs}^aE)} zf!(56$W9bS>0Cl4S)`A;)R~fyN_)cA&yj2@Wrm5Vy)bl4!K5zzXl9E@keCHz5a9yK zj4OZ+I9o_fYzkF$cywZ^b&xe07i7o~#&m)n%V)Je5sW;!ZyP`+K}$G285Wymn_y5z z0&4i_z`aXk4C>!|Sc+2(-hgn`og9kG2sF)Tp>0e?aMTgL-R?~8KN(%R`0m!z#BJuY z>uz`K#8pd+;3&v}epD^qsh+5Zr`V`2rqP`o_Eh2cA@VfLod=cT^!ej6?lIlt{#I9i zf`;+cZ2kCV$CZ@Af;@Fz5vZh$Mz~9Hy195%7O+0D%Nq&Vj;eTwabl@=HY|sl`B+IP zM3weNj}^8=Z>`aR#fpN@$}U{L&6(4kId~(Z2Awl@Ib2wF!-hsW>pm;gZ(t_epxh=! z;B6Wvt0nNz@u6}=BU8LoFppNyqP&z`a+;!&vvWRV}SwVE4d5&+3q;?e8Lf)S^|(K zgQvYG>h@_zTkI8JDR{4`-p4fBFBe|hy5vY0G?T6teWK%3c9%+(ZsuM5Cg2{P67r+0iHR<=5;($xbhd{=> zlLWKERlhL+il2a~V0a@A{9LS!^3nN<|C@6znIo)$K>%j&;pF2S7RRs}s6=Lk^nQZ- zPe+G2Iq=?*JMo@z2DT3c(V6)kRzUAIOdc5v$I99u>yVjtPPdR<1Is)>KESm==&#tt z2dqu(S1lp}4z1=Kj9-GoFHSuZv|tr5Zf-t^tX2-)?pZ=BPDVqdIOAv9?yu~4%ncas zPO^KmoKkdi_F($x;MV^fWoWwx8=o7Wbu^CLD6kl((2Befc_m9Rfh(^dxGfu#4%Qw) z-Vh34uR}gX<$?r@W1UI~p`M^9xxLI8f!ck~{exO)BCmAm|Yu3EZTeR2y-z;bnG z`L1u_0&X-G?nB}}tv6RLb<#-Kf!HoR&4^erL%^X+zvmwR19oCAP$xS?%oB(N9w``S zDn3rfLh{bKDHumcK_isG!|lWi#15SYh2Ri!_jG@G>G8M)XGz79buaA9wIkKd+e@$= zUH&H!d42-c`py-UXhLK}^|rBNr=n}>cskB%4PMn=?I(5xfvtF$!BB|mr`5o1jh)ln z8f_lok`O?Tjt_T-Yhpn4>pk5({%s=bSL8!(nv^tAuucf5a#jE#?kI(dKT$DZSXsp~ zmwQwcN1s8KKzcGpyMygrx1N|o428xS-;Q%lxsaNTaL$|Ltk*?`08ka2S6;( z_;lN)Cl(=t%I09)cV?V-w7YtxNi&azDw>H8ykz`_NWZ1C)x}=i=lK@LgUK)A53242 zq{CfbZiYl(U?i6b;2v+VzM;iywRZ;2a0}BuYH|w3FBr=}nugjN>S7U6sci)mhVw{N zY@9V&VC3iBLe($IFDDAp_~~%WEUfq(cknz)Mt~-PWZSVZPAZV+5mZ(nY`m>@M;kU2 zM|CtZd;v9Zk%jBVU$y0Hg1q|h638JyWqCQdR$ZU?vR}JUhY!~}eBZg3c*^@|=M(CI zf5Tcml^pj1lwOknD^B4dQR%Qz_j^XLx*I1TJ3Zc6_lJ*>T6Fj@lX6n4Fu5L*Izc_( z?HnI%&wmHk&rnIC7CN|H#|Jy0VNBpceNGrDAp|Gf!zf!Lmdwg#OHc+$Dt^cB6I=#BlIuQMl**dHQ_H97)v zgRr#g&oaJlQ39|uUmBbm{@PWO6pVa9_pG$~stbe&Az@b-F}puf-Y~1eI~GaBq~;G$ zU|pY~BFyFE-3OSQ6=Ot+y<;%H&~6KoEf>Qa5;SLY5V^>C3Xx^~F=i^&6-(4m56qev zaNh#?W(@@H`DqjYhYYoH8Y(6{TOjC)%U+%N-nZZMh9VKi&_|sL@SU}qdiGB}_vtiG zJM*cSs6Lt z4P~dsw#QF%ntfoj5qmZ{ovq`YAH|A4JZ3G$U1)@nIv+){QGXEEP-N1WX%I()H4p8y zS8oD=aaqoPNc>B>5uZ;1etZN$nawlF0SQL^auXxrCJk*;G_&1XRV{JWeXZ)t@OeWMbz{gCj*=5?v zjH}Paq^z+b{R=?nwBig?$(x6Mp3Z#v?_U3lSM>Ar%kIy<&NBk8^vloxqW|hEtN;Gh z)&KbFpM3eVzZ)}PS|{{S@FxH1)z$ySCchJ#1nf^W8ocTMd3E(SzlNrNKQ^sraPx+L z?`x~)+3@$LC-h2@(*DhbudP1hH|M5*Q^XYcXD44<{V&fLD*283H~;l(t8cu9p}tWw zhxqF^Ut7Jv*Kas1&5G|Y-+66yn=gMY6a4+v=(W{}x~<)N{`%o-tB?8mSAxFApFeqR z^^f#Cs4@KcKYMNUPx<_tjqBDM{P}CE|B4NMqscOOi+}st>VIa7*K;<^-~H8VtN)Gf z{x(c-M-zYe-(Oq(pLlp&qS9}__R1?Qz|!M7ko2$wjvi&Jw!hPA^>^DU^`dokdQ)4K zo`u!$kK>=c5lUpLaLkuSU;gaxgeOqifrtOH`=kH;{wuG5NxG)L;dyX~`s6UUq5ded zaqucKLmulu;}20i{$hR^{Owp;BM8VTspBPFbtw1DA@E=Eld|tGx!ICT7cGSIC}YJc zMKE+ju9RaUNEKvwXkusF3}M|HK6g)h=sx_Hey<);`m_x!z*BlAWX9`u$)$~ zc`#4_D4R#DlrX23~D;KmCA!1gbnHhiPB2V~}O0*e$&iD?H zwh1@K+r~#T*2J+kyf#Vd%HoZiH?Cb-yngM+i+ACE)JLJ+JNVZ)IZsI%pUo9L^|%GF z48{?mseaHGax=S4`m6jZplX=NlA|tMKnD9E(HnFlBys8tmIRJxA%MWmY?&R~l<$ss0EOkzpl^xw$3zm)w4O|j!;+PoeK%Whc4eD!;1NpMQ zvdcj3P&2_8f0@P7`**JWcp380I~Om4k^WxVT1#fLej2-I+C9S4ODeziBOl6Oq z6tKbW5xbXUF#~-K8q-bCts}_%+OBn*lM0Nnye&OosJb9+_M>utv~z#{5%z2h7drUQ z=#(m9=+b4>C!&2qU76L3K0Sj8$~dwY?*U|S8(MlMiw3Wb3UyT3!-QKcZnIbBM1hWU z6V==%$djzj>?+!Z$sZJ+$-dFiXIR?z5h8*`MKqc%4RL%#7G|>-s=SZq}7q6pA^#hdB8zNFQVEaO^*Mln% zuRIhm4~wd=q*vVn?S|V^tUBBa1NFkbo6nC*fKQI#kAk9;sw-UTXdG>UL>c`wx5439 z$ZX=dI5xD(5XY5~0&uR>T}u?YATub&EN!nA!_B4z5|7|_Vp+(zGkxL5r6=~N=WnQm zbf*;B;|%-N56_JpH+%)`SK0z*o3kNo0cz|^*GkM7>Z(wC_(K41NiW<>p- zdGCaNsY14sNEL_h9ZEZ}ilrVKAmGYv(;@`fi77ndqkxbwIvB~tRQu|-ua6zb`kgTi zaCjY#d!&A8%|e=9=&5>(i=_h69dH(b3n)RMW&v8Lw(WNLijTi_)U%9T@y2iK?puf$%BCX{e= zvkmpJpwc8-zCu|4$NfOKC%I3lLm8BYfPFg$p01?Efyh4i5Y98awctgZCna_^24KN;dlM<%>9ge2~R)h7|*a0MA18*se6RFFJK~Bo|>_ zW?awNdUV}WO~1(wT_LJ|T{qjlRk*hA>;IG0`7ESgjj3ek>`r~!qu>ZsTnXxnXbT2-im^?n?`+(H z4Wzj^D`Fb^-1Pt#EqSM-Q-|#oH|j6v42zNV9lQ zjF8tNHwflo-m{CqE`IO;iV|EuH0ObdBtr{Xgay#GOuy#L7ZQB)4OsDLwuNX9?aMKx zJkI?sv2~?~x-rdz78Jn1 zOC;(w)F|5U98kba6U!1e5X3ZUociqsJazS~J9f50(bX#f(m0C4%?Fq0%m!w@KxwSW z>!QhD|0DHI+$5IMfVc*N-zz?m)v`~cjd{&dU1i6O-vzgS;MMSGjRGt>=}(5c^sxvp zb(+iqg=9M%DZ9xWI(Y0VFgs{q1Hpm7ifT2LE#?Tfqupo_ zw+34fQLEL(AH@~VLSaH5^SZ+%zM2fSO+kl)=#fCKo?|S2>BLw(k!96UZ ztw4n_9X=l5V9+Mb{`R56gT4zf4=j5zW~tfu?LH`_X+hLhyu$CNTB7amPAk4fu-j_~Gr8rpCVfpS&%Nj~|f^?+-QAH4xxJp~F! zpTNvhGK|7yri+?SYe43s+3Kod^d14hQR12kX-86MG2&PpAwxTU$e(}*JrFdAmxJTo zBf872Mf)@t22UP>HhV}Q(fuj{cUC&{(Y|B3d7Y7?1n-AXFx1Kc2Tg^GscK;N#D#0o z0z4z6Hd$YQYKq2?t%Ju9VVeiA5$aH>#jyGu@gCT5yYdt9vQ+^iC^WUBcpNS4-~`vf zR3A2i%1HV%8o>_mtbR;u{j64G*PqoUx8deKoH#S?d&hYPNuh7HpMpixxnFXFPJL;b3-fNB z+6V=_5R26MI+qUGTbypO3hN2~)-71!dH!#t$ISuL&B+hSzj#bW(1z%$jUjmiq>&69 zvPlcwwwGeA3TCSTj^b^p<_WV;v}x*gvuWhY#8s3GHKZ+jYU1PC=$?z0(8UL9UU#$Q zjFrIPFtcF#g{caRzk2u1djQQA1ROUU?7|!?Nqz&KhBDDog@*HZc=CQ@^|QQs0Hr;W z`r%J#In`<>F|M8rt;OeC)w&|z z{@h^7>H>9>=IJx|anok$s(>kt=!=VH?Xy%j;Z71e36AWv>%*pNmLqwoTl;6;DEiK5 z113WOrAC9>XP-X9GDDRibfBJGKXuxdNf#*}jjV^~yP<5^P?DrtN0`M~?k)Q=osdfz z579pJr_IMn>SK2$YKIeHmrq3B+3MZ7>gF`vm3)cdCNpBWJh5{(9h37F!1bR3Mc z$_2YJ(3WrcQv~S5u37}R4mr8xDV1dcXEM-p}&Q6HjPZu8Xs9p z$kQ11WC(>PQxFA%6`P)i*J({$Ryu;MB4xv!JNgDg{SuwK?Uy{RIP@Q2VL&gDBcTFz zCovi&&413Fu~VA!BVh*Ol);O%CxtoN;_K1VVU=m}(^klqFSL|C9l$6#kAx{^jVL0z z+rS=Jk!jNbz_UC5D?!}*QRb(bmmovoz~ea3sboGQnA?_=&9}a)c$8Q2L z;x-L&2X64KaS8>p^PS1yalq$8kej!wYu~?d6A{YSZlG|M#%iTSlkuh_{uWg36c#~{ z@SA9nrooF4{5cZS93b#IMRIUL{ArKqXxpKIK?Ryx>{L;zEP1I+|Z*gC8yM z6FL#sVOHP$?sw-I6|iSM4oK!hJ8;k!;x3-Jtz(-mx>HO$66}f8h1Od$YN))ass&Q& z<=UtM&x|;`LbIJKhSBobT5S%Gz2yXQ#4YtUF(XTHfz~3AJg%l}(xR=d$quFZxh9kf zaFUBK#}?Hv@zZxpO#{-Ir;$kESv)e;5b-Q$&|Z4zdU8Dh8h+wQ7_!^t!hMj^G4B~C z$o0#{J^XIdpaj;e{9ERHBUb&71pOI$*rT9sD<4*sy`6D{8mrHY9N{bFOM zdYB>cg*(=+`e!#7r06LP#0BA=l0()wUT`dE$Z`W?PA#Dxj)4?Fzgwp>x*i1l8zzA zwZCwrwLP(MerYzf1wm7A1|GfBjSz{K!Rh>YLmqDvNjcjDL{Kl~-BJ?#lRj7u1R3>V z_dy~S$tvyaSd6WB8*Uc7TJn(TJNmj(M3!_NV4cT9&nh=`k2D;l1B6-;e~n3k!oVgG zd9hQXZYUNg(k6V=S9f*;afQI(d?OOZHHeTci_Uqe=H@%*MyhKn zvdq)40dY>yp`MnL;KA1pyM`$i*iriXngI&1SS!=9jMqANWod%pd|=ldVV_1!ek7Y0 z2~0BmlHeK3&q?rS^CH|^rJ+HSJUp$td2y}dukz$FSXlPWRJ#YfE@x(d+C9z)+K+j<3Hwri2FF*gIS6_K$Wp1VSCy4aECRXMS9mxH~ z+be&77jGDkf3n52cm7zr1!Q|lZ{s~fn&D$6hE1<8Wy5M+>086;x zlE6ShL_%Y@{Hl+2cvK?)Jk!6U={htIPHP}2;W1A8jZdy$KVQi#&dXy9Ua1J2>G6~s zalU?NA98pE+iTUf)0DTpDP4aX1B6cdUoWpw!V5Z|!$14(KdRQJpxJYtLa2&oqEDZBwU@SD? zOx<27lzMf92ykz?HAbAYEIz(x=EjVl0YWC-`-VBD4|(Y7O;XV zNPu!Q*d3lztU!Qrm;(^t3g!YEH4(-3@8=k14RtKh$3u^=fc3Dnx=Mx$q%1?NPYIAN z1B(NR4IO7Tqn~RawDu_slIL^4)`9c%9F*WlXRF)8d7&48$b&IpZ2Bc+@O%K+4v2F^ zDN9ohg&SC@3;CqCDmi+9Poi3;H*=Mkimn!_0JAl@XUqFEq!$dTB3I@ib;#as-zU+9 z0EF{*TJ}-;{CN3L05$&IAOMIW?53FxGTqG_!m_FqtT5L)x(jZzK=;T@SdvBTq zlo|K6yY)M8Mby?V93rWJ&@7xuivws2nl6N+{fd)+u#F`AOe_!5FR@{akwnh9x)7J~2*-m=8svo@ z4bS*B8gnV$Z}vo7@f4Fd*Dd*}@$_(I;Lq3^|pzwlF$tTQP-#95=g=)C@nO$7W4ItG95Gq@)f=VGjE}x8El; zv{8~8Bz#mLU@a(vXuW_+7C;`L>H?HT#p>B*7g~kl+$h*#t%LSZ0hI0YXxySB5ZW*u ztzoK)fFqv1Jhtd8Eni|}+G5x^(Gvc3 z`oub(7hF9~Dy9c_WLYqQhS$=)$E1_Tf?XgIG+XdBPglDD z#I;$)xw0?*&?9r3jGDITBVZew$YlD7?Y zydooh7WS|>n&J!%cFs1sP;jXVa>X;byW2@v4jOBhZ7Ii?T;zC7H5iC6%%aGVjo(R4 zSRxJrOvsIMI~Hgn3uz+tI>Vlhk&67U|MX8Ymsp70`v;G}y2dP5U?f=Xf!y-eL3BC9 zQzR`kHHKu$xVKtt-!x4yKTwzkH-02;f|GaEht;S{9A;;pM;XJ1 z>z<^9^OfQS>Xz)Pu4(OC$S}@bPJY`}%MAhxsE3)8e})K|F2i_B8@z$sojQy=uEi%& za(-;;{SqJm!cX`9po+<8aK7LvE7VmJ_;VwL(SpGnB^~@z0np@9(gIEeK!H+{7Sf00 zL>(T8S7t6-YTz5UaxG40aW+1Jw^bRnbf_xpMaX>S4LMAmxk|M3Xacdz7 zkX*T4g2le(y-eNPi2I~z%-w^7#f|pq*3U`?U;Ci$L~fU2w%9yLxdW$=_dVf6Hd$_* zb(5c!U@mYmfB7*BUQ#CseFD@a;EwhWeloaJp=RgBi*HM>7vxG5Be1;jyjX0BaoH_6 zo>KwtF!Dbkl9F1$!*O>w_f+2kzMA<|z-F+V)?p{?tW5$e9nW7pQlth_D$+LKV;_6pr8Y21c>td*#1ddSW95Uzkh;MAiA7dXH zkNK*D@@Ben1TY|8JO%_{B5-UQema)&GJFw0Hl;BXUDj>eF>8L);Aq0A{CBo`_}$)j zO6@U%UvT7G51f3~eFOLc(zj`z!g#_zyYV4 zz-v(#I{lm!B#Ivfl>mRQ;VOaN%|c!qkcK6==nwwynKZ=D)2ZQKw&#CC+Ksa;=2^4N zQn1v~rI`Cy)oSFGEo?tuENX^8ov!An-S0RWwcX+8IAb)jn=t1lBl{jZr-g}1`L4{TbjTvkauV{2V+&v zj%97HO|B1N$KT!^>`)OF=b;XEk!%Q(BLqsMXyh!GRX$msN8(dJMShGy2>h!1?mHS0 z5-7CyXijy7S;Wtl2AvloYmmt(7gJ$FSarjEd~_c1C#VW)4NK#FFb~emTwh+i+P`&s z`RcVFfv#?JKEtMTW^UYETCP2Pw=?tO<=Z#=A1~hdIJJc7>fLu{_^f|@`39cjFE0t| zCCT0dI68fo z_}Z0$)E{GSM0~{Y7HQ@Vpm;tm_$P66* zlK*N35X=V>XK`eiH-afyFn~InGRb%2B*CMQ_u`my^kIv;gFg5|;}>rdXNLmmVeBf(&I)asx&j)vUNx>Z418%w zoT}@@avmz)cr;9@bf4IPF6zi1!KG327fi6XbHy@!zWKDUy;ywq#L6SXpG1rKo=6kY zuirl~D+71NlG$$VBDTQhoq61dn!{BaH(edW2pBBk^6?1bxi(9eIJyW+Lh{p~dfwWa z4{Qo27g-sQqGCxl0iq~ysYtNP;e20xmT`Od%3*<3bZy5M*4FO1vYPMhVLLXfOl}y= zP8&Z7DLSW225C^?yUIH#5Xg}|>>|*~h&TO{%JZ5PCwxH%A`O5H#^*e%hOx}0d zFWd26z{fr~#H0cqY@v%PZvsM!qYfxCw)O4W2!<)Abce+RM%wcMsDiP|HhqMV_q$}6Lvep#AyS-pjWn{N#^x~p?JXjX8WMJ z$N;PCiL0tI0styiQ&lwv-ZmwY-Ih;MZ%+dbJ3h9|fzIot5qa{90kPb?cSi!jsIl>;KlW(s4g7Tp-zqoD4O!{vqza$tLD}+ix zhM*utw?piZx;9e=r&wcwQ@(Uz$q2rg!LI?G2xy6lYTO=s(F-0U>M6)@*sHMCbWB9i zwuU|5p7eqXPdyjc0Q>CmNs=Do?ln)ulurDyX;Rc%AsWZ8nAww362b1U)&u!sz>@=+ zMDV%^?7~s_2X}7Xm=B4!>8e43zbC3s1)coC1tT{wnZ2jCr|2t_65>7J_?bE25a7_i z**y7&r(=vj$*6A8&WL+LrcT%&v|5W_b0?lipv7ajumkWuK-KYW(+mIosV%Fy>9ND? zjC2UrI4Ay*&mHy~A-4gXOkba1?INs(|F&PXK+7dYzj%`Kfx*QPoco|pD`fwta|)86 z`)wZfGcmrW5duPaK`d)50l#GylEM{`%?!v3&_{H=i9IPA2EaQJh@c|uZxO*L-W!oC zN1d$M&Omh?NgXSKb@3u>&b=DZ_E^z5V5XSoup=c;{gJt=CW!wFW>v%R#3H zCD8P!n6{p@0HN{Rm#^ow1?pLSX?oaP6dxa_La2M9ZLE#@>!Cev54zheV;4?h0h*|lRtORfzJlboSvU|fA#9PzSqlv} z%N;0{7)o#KKd?wr*G=|jG_>0CEP216)8%w82dr43Oec|(uW ztL`F-PA!IGl)Gc8EHZcya8Odyb)fj6Fo)-A-618a_l72l=wk!2JqT zPRdUC2~eHHpg5}!A-9IX*4}7>!wyCM5$vtJyPrpUJ|2epp~nb;1TEq=d?j7_t?|Lp z0SxZX)a5NB|3lV-I@IFxW2FDY6SN6i%VICPNJRIb(%_as1vcsl{hn>S!y0*+IUb&jFj z3CaC4zq?a=upLA((9xj(cyAYb$KW&k1Ct#78+J~aHd|m9@xue6)`)BrEl*QBas`;@ z7(RNWD>I75v?BUIC@hsU|l(MiN$5hkf=Hy$RQ|; z`zgwM5HvYlEdYjLCQb(>aVkwColn>wi@usDNi~uAAyQVf`K67OG6R#lcS$%Jrg!(? z!EoQ_7&rdCx8IpR;)^)LZrU4r!ztn>%WooRHAkDUstCn9>bO%WV9<;^Sr=}5#+tBo zFgww@J3tK^MDJ9WZ!LqUVsKtv?&vmncrapRS3btbsT!6=ZG)mwl~upSY6c!%eaLNx zUgo*Nhi|*(hk)yYMIIgX`>tZsNRvK;1k|g=b1qc)F4H8w9`zWovWc;qFi zLT3cDvaR7m{y4s6>Q)<(LkkC0PcCU5Lq`N(mI$W3E3G$BCn5}b%|;R{-&%3U<^ZXn z6)YLpIIfKn^rSdXRz=79Krk$9(a2M1|H4EDgznX$nhO~Y5$iRcy*s#-7`1=J&RN9o z@O&P0XD4z{xDmS>NWFl6wMZm0MN&GJi{BkR7_z4IyC@`sES04FCbVg*0$%YNPDs_) zQG~Y&zz2#0e(MlAbx@t|M;|P#^?vW8dvl*n-s*m|u(mk=kY_!|FM=na zy#ub#tkUFt8>q1q8)Mtf&hgNlBU%6CiM$p zu)D@Dq_5{M!IBenOS#*2q;j}jVR9!t`Hya^`o>;YalA;iV9?~(J$eeVdJsOn%QN7g z#T$v|!}(&3KrIsghJLkZuc<_^`?~TLS&AqBKA>6{vbBp^Bk!eQ;@=K2Bw>NbYR~?j z0&|qx2;ySD(I%ZJP-!=H?Sz5mStOLrvE0>~Yt;^S&=G^so+N$-kToNB0 zw@9h z{Unpz(D_}-Dj*dhaSbBedezl~@yzw>t0oSBRxs@Ckmc_95D{lb_fd6yAA!B47YO2w z_lMvx-qh;eR9MRZ$~_aCMf4ciji)7qzDJ zoPgmheb@sqpl%^Zy8zf6K!J~-4n$UxYWo;DPSN`edZ%ZL*~1Uv7lW@ZFWy=1{}5>| zuHC$`zK(m3)FbR%#eLEftpwg;2#5yM&d2-HmhwD$ zF*$g?`7=YtzS$YYL=LHa9qjG^H;(S_fef*G)EH&H6e=sW;eeBykecc|ebqK$piRj#0U!M_{1(nTD20eNJ4afNK0=~+g|Ku22 znDzBJA|Q&PawVD0!pw0qrnT@b#9Zbr(7_ZKP>_6Qertr4QLCX!@xTZ2maKCWlFs7( znX$46)!qmQ&TV}^wZfbx4=_6>+5@u;C=@UG}Q<9hr7E3D)wdzv2vI>C3-N1NIAtk1ayF7 z_Nm9b$Ry$65ziF07FhTsA~w;M85tkL0Kbmnqy|Fy;qv68#Y3?gtn63r1ug zWDZc;@<7>!tqsME>H-@a4R(ktuJup|3yA=ISAKGQV8SMxI7WK_7{quYOQ!Dd~;nD>A>=k?^;9?Tu_5tq$&R{#tk@=18n ztJKa@GE`lh<@?8b8(+Nh-o?YmU!X%`7S{+ho<21A?O?LL2pvx$!pS*23PN{p=G&wU zVx-_$0IhnIQRVx_4MB<~B!e~|J3vbMH<4pd3dG_)96iLz)qr6eA!JlCs-I5);4>iW z2pM=rxM&9_5(iM*3AJ2#Jn?!1leK;xL+;wZdA)%Bz-h!Dj}bGcMk0&;?Z8A*Jmasy5bnXc(kxiW`1jQD^f$xeUVw`fYP!FiT> z$e(nee;rbJq?z-VKuJ1JA^7w^z0<$_30<=badEBs>7rCOA4d{n zSR8SmA0Q&&!}HY#w{Zu9<{oYKRIO&`z?Mp>o!tOk<#ou(_kf4kw?41qZeAFW;``CK zi|0N3e=b0xw|nqtIED%U;&2C3?SW=7uH6a%ZMA|=?KR7%GqW&!@(YMe)1d<3J1DU6QYnbw_-|MRDmusao{8nXZR^{zoEKVM4JdkpjGD* zi-cMEv2wHF^be&aKXgqJnx3!To`Y*&9sgp7+!vl*c@)%XZrMGXwjwBBPOTcAxcov2);8w;D1rE{dgJcIE42K|f+-(!7H?WxxoGSuiBWAN8U}%xuC)P~nk7m2GX5 zz|lAuPPrX?iXL}0oiCPb85C5wjy=%tU0kl~>r_I<*^}4=T9c6)-3-PAb2TP~yeW1F zwsKQxgVBOq9BtW@hO0XnRm`_&n6tw^tRR(go4P%>lYC?=iR zqXXxTL76*O4-RG_taU`p{jZ-UZk_jsOFL*ywRo3}a8Z!X1{Bxc_NqIE$%Z3iT%EfX zyFzFft3eALwu2WDEpoU@9_<6sabKkCkaT=@8XXUdFG%@pos?@kIjV1|T9*`?R{SE- zfUqOKWpK3OCBu%mK|MQgbSyuTdBBbm4^lp+^#wMj&cpDynq46_2bu))R9EwKi?0z; yCwatZsouZt40Tj}KY(`nn+@{kulHB}+||(OJLz}ZzNl$=!-;_-)A8{}@Bacgr(yj7 literal 0 HcmV?d00001 diff --git a/docs/_source/_build/html/.doctrees/index.doctree b/docs/_source/_build/html/.doctrees/index.doctree new file mode 100644 index 0000000000000000000000000000000000000000..bedb7c09d92c9c3cda646c339080ac7d07e39841 GIT binary patch literal 4856 zcmbtYZHp{N72dtO^R}}y`;ttEH+N+ajeBEuMj;<`zlDezHd!P{K;+t~>8_co-R`bV zclEuq5Q!IzWTC#uZC?;U1@*K31Al;sAo$rokUtPad`?yOOz+$~*MwZy%hah;r%s*o zoKsKrj~hS#=y1dSGyOpMxt3uzidDd~!n8>c@mLp+in|Ys9~H-@ld=by%2S^gW&;|& zkYSMWxVTpwiw)DtxUZ#(7Yjr~G)2ozHnh|suT7c3s}q&VOb=iE?(4(1_>{vEEYkuQ z+x{M()7I?pHg=lWLHgmS!^=6{0V0i>`P7MO<*`r^A5YbMJd=9N+?mGk zBpZ9qg|UnSJ|CqSygWL)l}~WI4%}w5lqI4blGAVVn5RthU^q=xG$bqVH=bo9L?{WF z&$FQxe3)sbr9X^RkcT`QMZw6$ZD2l&i87`*-OKKD=i-RMCO(f?i6Qdx1^j&xe=puE za&atP5_iO1oN2oX2+sBu2NuyVo!3;Xk(=zaa;_#>?)8mNw^y^a*9I`CqD19!Pz$32 zo!QG0A>;Xo1wjevmR7z_c^!pL_lXA-w@t%l4)DM!QfWbPd~SLyk>f0%AT>x;@zdhm zbgf7$vY;S0`9J7V*ICt4I|TR<{PY!R9+)zzC0A%)qVg=$horqxcm>@ZRQ@ssc3ABrE(r;5lt^eJJKtG_jM*y#fARo`Pk36e zI*PtkWz^XK;`kyVW>8kt2|{v`F1iG(ptw*NLSa}}C^6cB^(_Z6i&d(>oeHB>f7+`A z=J546kW^+Y4u+adDCV{$4W2l)gz-;48H}lSJgm9%oNWi)Ngjq=dm$k47?P>Cc4)?v znn$&1vv-OEpT0BWu?6Zo&eKH&ieFpL&&+PZajJOc&7og2P%3Pgri^WqtXe%fw_7_f z?aF$wJnNsoiMeT;rNr9DsoO+Y+eH!-e0hbD`eb zNby%sQ~X8E;v)(SGWyE}p2`%VQ$IOHf43?6U8OJF_>U`Nq@l7XV}!BybkDsPk zg`O14&@Wqd)tQMTn5JuNh1q<`GKQbkip93U8_oU@HA2nz1kLxPY`)7*U(MEAGpne` zYMV!2UFT9s48>jZEN<{P3&EvS>?Nt1r95-Qu%VU4y=^bTQpetlImKzy^!+>~+F3F@ zFo4}k;>f0HXIyJyZiP7@T572^NF6aE^u^}eEX;AWR1Md3Rj!j4hwwsn>ptFN>O^R;(h zX3~Lu&jU3k>V+VbUbd=AL)Gpg5Ma)+En67vm1~uVaI2$EbTBvxW(%HB$1Jbm`wF z(pO(WPWtK8UolUTrTG^t^YDjJ$z1YuB)Oj2JrIwv&{2rZI_R{h;(#6yZF7X0h`dE} zSRBC15<=*;+0U+G&E}qvGZEqs^|Ku+D!tt-Vkq=?b99vqF?+_2-Ovk_&)fsX9QgvT zUmxIc^^SnsaANgkp4g{JL?sX^=4zT=@RtS9gZD{*MsNi~c=-_N8~D(=^f)+T=;5hH z9o%kyP=1X7Y{RK*jn`(2$M@+=fN8s?gf0M3(yfCM)1IS@_A9`Fec(xr+QQv{*B9Lj z=J1BpeH(xn)~1UA(O3Gc0C|gq?)R~HU%Yqm3fjfR*N6a^4$TppwHJWPQB>D7~A?e;);-KB-SoP_GO(sKu>O9&`disVHT6)y5?h0m@C7uua07CY6h zcG2Mt`)J>(F3vX1VAWPRgBK;bijSu{(hlnGD?E7Y=OVPS)@!Bw5u)}%@fOgH?<1%a nyofU(!ELx`E;q#8h1e#uTfS-mo*8}3*$Jq3maW3E^U?nR4n$D` literal 0 HcmV?d00001 diff --git a/docs/_source/_build/html/_modules/aborist/cli.html b/docs/_source/_build/html/_modules/aborist/cli.html new file mode 100644 index 0000000..cad3123 --- /dev/null +++ b/docs/_source/_build/html/_modules/aborist/cli.html @@ -0,0 +1,4456 @@ + + + + + + + + aborist.cli - Aborist API Reference + + + + + + + + + + + + + + + + Contents + + + + + + Menu + + + + + + + + Expand + + + + + + Light mode + + + + + + + + + + + + + + Dark mode + + + + + + + Auto light/dark, in light mode + + + + + + + + + + + + + + + Auto light/dark, in dark mode + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Skip to content + + + +