docs: clear all 39 cold-build Sphinx warnings (truly green)

A `make docs-api-clean && make docs-api` cold rebuild now succeeds
with zero WARNING/ERROR lines (was 39).

Docstring fixes (RST hygiene — no semantic change):
- arborist/qa/{keys,runner,query,verify,quantifier,metacognition,dag,
  evidence}.py — add blank lines around indented blocks, convert
  ad-hoc indented sections to literal blocks (`::`), avoid line-broken
  inline literals (e.g. UNKNOWN_EVIDENCE_ID), and replace nested
  bracket/quote literals with cleaner wording.
- arborist/concepts/__init__.py — wrap function-signature listing in
  a literal block so bare `*` (kwarg marker) doesn't trip docutils.
- arborist/store.py — blank line before bullet lists in module +
  connect docstrings.
- arborist/evict.py — replace ad-hoc `{ ... }` enum block with prose.

Surface fixes:
- docs/_source/_ext/makefile_targets.py — escape `*` in auto-
  generated Makefile target descriptions (covers `*-parallel`,
  `*.dot`, `*.db`, `π*`, etc.) so the generator emits clean RST.
- docs/_source/index.rst, concepts.rst — extend title underlines
  to match title length.
- docs/_source/concepts.rst, v8-fork-score.rst — widen first column
  of grid tables so cells no longer overflow into the column margin.
- docs/_source/merkle-agi-v7w-spatial-temporal.rst — switch
  pseudocode JSON block from `code-block:: json` to `text` (the
  `<int32 x 3>` placeholders aren't valid JSON tokens).

Verification:
- make docs-api-clean && make docs-api → build succeeded, 0 warnings
- make test → 1588 passed, 28 skipped
- make chain-check-shards → 0 breaks across all 7 shards
- import-time SyntaxWarning escalation on edited modules → clean
This commit is contained in:
russell@unturf.com 2026-05-09 18:00:15 -04:00
parent 69e0a957ad
commit aad24d3cfe
No known key found for this signature in database
16 changed files with 111 additions and 105 deletions

View file

@ -18,11 +18,12 @@ Architecture:
- ``seed.py`` One-time migration of the legacy frozensets to manual rows
Public API for retrieval-time use (matches the legacy
``arborist.qa.concepts`` shape, so call sites in ``query.py`` keep working):
``arborist.qa.concepts`` shape, so call sites in ``query.py`` keep
working)::
synonym_expand(tokens, *, shards_dir) -> set[str]
rivalry_excluded(tokens, *, shards_dir, compare_phrasing=False) -> set[str]
has_compare_phrasing(question) -> bool
synonym_expand(tokens, *, shards_dir) -> set[str]
rivalry_excluded(tokens, *, shards_dir, compare_phrasing=False) -> set[str]
has_compare_phrasing(question) -> bool
"""
from __future__ import annotations

View file

@ -126,10 +126,9 @@ def rehydrate(
) -> 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
}.
Returns a dict whose ``status`` is one of: ``unknown_document``,
``nothing_to_do``, ``source_not_rehydratable``, ``fetch_failed``,
``drift_detected``, or ``rehydrated``.
"""
doc_row = conn.execute(
"SELECT document_uri, source_type, chunking_version "

View file

@ -18,11 +18,11 @@ 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):
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
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)

View file

@ -192,11 +192,11 @@ def render_evidence_block_for_json(e: EvidenceObject) -> str:
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.
``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``);

View file

@ -81,10 +81,10 @@ def canonical_question(
``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.
The choice of mode flows through the ``question_dedup`` policy
field into ``governance_policy_hash`` so two agents under different
modes write records under different ``cache_key`` values they
coexist in parallel namespaces, never collide.
"""
if mode not in QUESTION_DEDUP_MODES:
raise ValueError(

View file

@ -246,13 +246,13 @@ _FALSE_PREMISE_PATTERNS = [
def detect_false_premise(question: str) -> tuple[dict, ...]:
"""Return tuple of presupposition dicts surfacing the implied
relation. Each dict carries:
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
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

View file

@ -11,7 +11,7 @@ Pure function. No I/O. No model call. No retrieval call. Folds into
``governance_policy_hash`` via ``classifier_version`` (added to
``arborist.qa.keys._VERIFIER_POLICY_FIELDS`` in Phase 2).
Intensity rungs (highest wins for multi-quantifier questions):
Intensity rungs (highest wins for multi-quantifier questions)::
1. ABSENT universal-negation, single-claim shape
2. SINGULAR one-fact wh / definite reference
@ -22,21 +22,21 @@ Intensity rungs (highest wins for multi-quantifier questions):
7. MANY medium set, vague (`many`, `numerous`)
8. ALL universal quantifier (`all`, `every`)
9. COMPREHENSIVE exhaustive request (`complete list of`,
`tell me everything`)
`tell me everything`)
10. OPEN_REQUEST verb-driven enumeration (`tell me about`,
`describe`, `explain`)
`describe`, `explain`)
Returns a dict with:
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
None otherwise
is_broad True for ALL / COMPREHENSIVE / OPEN_REQUEST
operational_shape mnemonic for downstream policy (e.g.
"universal_enumeration", "exhaustive_request")
"universal_enumeration", "exhaustive_request")
scope_bound_hint "bounded" | "unbounded" | "unknown"
(see ticket §10.1 bounded unbounded
(see ticket §10.1 -- bounded != unbounded
universals; classifier defaults to "unknown"
when intensity is broad and no domain anchor
is present)

View file

@ -16,12 +16,12 @@ The flow:
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
faithfulness check (``verify_quotes``) every double-quoted span
in the answer is verbatim-matched against the assembled context.
Result classifies the answer as STRICT (every quote >=1 verified
against context), HYBRID (some claims sourced, some emergent /
training-derived), or 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).

View file

@ -1,12 +1,12 @@
"""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).
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.
- Cache hit -> persisted audit_mode (STRICT/HYBRID/UNGROUNDED).
- Cache miss -> call ChatClient, run faithfulness check, classify,
store record, audit event.
"""
from __future__ import annotations

View file

@ -1,28 +1,27 @@
"""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
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.
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)
- **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
``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 `arborist emergent`.
@ -528,18 +527,17 @@ def verify_quotes(
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.
``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'
}
Returns a dict with these keys::
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(
@ -1139,7 +1137,7 @@ def verify_claim_lattice(
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:
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
@ -1147,25 +1145,24 @@ def verify_claim_lattice(
AND claim text non-empty
audit_mode STRICT / HYBRID / UNGROUNDED
unverified_quotes claim texts that didn't reach
EVIDENCE_LINKED kept under that name
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
pointer_ids, status, reasons[]}; status in
{EVIDENCE_LINKED, EVIDENCE_LINKED_PARTIAL,
UNKNOWN_EVIDENCE_ID,
SOURCE_ROLE_BLOCKED,
CITATION_MISMATCH,
NO_EVIDENCE_POINTER, SCHEMA_INVALID}
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``
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.
content-addressed evidence_ids
(run-stable form). Used to thread the
parsed lattice into the run-DAG.
"""
from arborist.qa.evidence import (
evidence_map_by_pointer_id as _by_pointer,

View file

@ -1,9 +1,10 @@
"""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)
- 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
@ -501,6 +502,7 @@ 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).
@ -508,7 +510,7 @@ def connect(db_path: Path | str = DEFAULT_DB_PATH) -> sqlite3.Connection:
- mmap_size=256 MB lets reads come from page-cache without read() syscalls.
Migration probes (executescript(SCHEMA_SQL) + 7 forward migrations)
run once per (physical file, process). Subsequent `connect()` calls
run once per (physical file, process). Subsequent ``connect()`` calls
on the same shard skip migration entirely see #000026 Phase 1.
"""
p = Path(db_path)

View file

@ -133,6 +133,13 @@ def parse_makefile(makefile_path: Path) -> dict[str, str]:
return targets
def _escape_rst(text: str) -> str:
# Bare `*` in description text (e.g. ``*-parallel``, ``*.db``,
# ``π*``) trips the docutils inline-emphasis scanner. Escape every
# asterisk so it renders literally.
return text.replace("*", r"\*")
def generate_rst(all_targets: dict[str, str], output_path: Path) -> None:
"""Write a single RST page grouping every target by workflow phase."""
lines = [
@ -174,7 +181,7 @@ def generate_rst(all_targets: dict[str, str], output_path: Path) -> None:
lines.append(" - Description")
for name, desc in present:
lines.append(f" * - ``make {name}``")
lines.append(f" - {desc}")
lines.append(f" - {_escape_rst(desc)}")
lines.append("")
# Surface anything we forgot to categorize so it shows up in review.
@ -196,7 +203,7 @@ def generate_rst(all_targets: dict[str, str], output_path: Path) -> None:
lines.append(" - Description")
for name, desc in sorted(leftover):
lines.append(f" * - ``make {name}``")
lines.append(f" - {desc}")
lines.append(f" - {_escape_rst(desc)}")
lines.append("")
output_path.write_text("\n".join(lines), encoding="utf-8")

View file

@ -7,7 +7,7 @@ documents. This page is the orientation: what the system is, the
core abstractions you'll see in code and docs, and how they compose.
What arborist is
---------------
----------------
A reference implementation of two papers stacked:
@ -103,13 +103,13 @@ Every answer carries two stacked labels.
**Schema layer** — v9.8 trichotomy, persisted, drives cache lookups
and the audit chain:
============= =============================================================
============== =============================================================
``audit_mode`` meaning
============= =============================================================
STRICT every evidence unit verifies against context
HYBRID some claims source-grounded, some emerged from training
UNGROUNDED no evidence, or none verifies — purely emergent
============= =============================================================
============== =============================================================
STRICT every evidence unit verifies against context
HYBRID some claims source-grounded, some emerged from training
UNGROUNDED no evidence, or none verifies — purely emergent
============== =============================================================
**Display layer** — four-rung ladder for claim-lattice modes only;
renderer-only transformation, schema unchanged:

View file

@ -1,5 +1,5 @@
Arborist API Reference
=====================
======================
Generated from docstrings. Replaces the static modules.md.

View file

@ -167,7 +167,7 @@ Transform commitment shape (4×4 SE(3) homogeneous matrix,
rotational components quantized via SO(3) → axis-angle integer
encoding):
.. code-block:: json
.. code-block:: text
{
"kind": "frame_transform",

View file

@ -44,15 +44,15 @@ landed under the 2026-05-08 ``fbd99a8`` review:
Verdict thresholds
------------------
========================== ================== ============
Score / flags Verdict CLI exit
========================== ================== ============
``score >= SIGNAL_FLOOR`` **ACCEPT** ``0``
``[0, SIGNAL_FLOOR)`` **MARGINAL** ``0``
``score < 0`` **REJECT** ``1``
hard-regression flag **REJECT** ``1``
``NEG_INF_REGRESSION`` flag **REJECT** ``1``
========================== ================== ============
============================ ================== ============
Score / flags Verdict CLI exit
============================ ================== ============
``score >= SIGNAL_FLOOR`` **ACCEPT** ``0``
``[0, SIGNAL_FLOOR)`` **MARGINAL** ``0``
``score < 0`` **REJECT** ``1``
hard-regression flag **REJECT** ``1``
``NEG_INF_REGRESSION`` flag **REJECT** ``1``
============================ ================== ============
``SIGNAL_FLOOR`` defaults to ``0.05`` (5pp; matches
:file:`docs/bench-maxing.md`'s noise floor).