From aad24d3cfe17ee76d2cb3244af09a493c22cd46a Mon Sep 17 00:00:00 2001 From: "russell@unturf.com" Date: Sat, 9 May 2026 18:00:15 -0400 Subject: [PATCH] docs: clear all 39 cold-build Sphinx warnings (truly green) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 `` 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 --- arborist/concepts/__init__.py | 9 +-- arborist/evict.py | 7 +- arborist/qa/dag.py | 4 +- arborist/qa/evidence.py | 10 +-- arborist/qa/keys.py | 8 +-- arborist/qa/metacognition.py | 12 ++-- arborist/qa/quantifier.py | 14 ++-- arborist/qa/query.py | 12 ++-- arborist/qa/runner.py | 12 ++-- arborist/qa/verify.py | 71 +++++++++---------- arborist/store.py | 10 +-- docs/_source/_ext/makefile_targets.py | 11 ++- docs/_source/concepts.rst | 14 ++-- docs/_source/index.rst | 2 +- .../merkle-agi-v7w-spatial-temporal.rst | 2 +- docs/_source/v8-fork-score.rst | 18 ++--- 16 files changed, 111 insertions(+), 105 deletions(-) diff --git a/arborist/concepts/__init__.py b/arborist/concepts/__init__.py index db38360..f877c63 100644 --- a/arborist/concepts/__init__.py +++ b/arborist/concepts/__init__.py @@ -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 diff --git a/arborist/evict.py b/arborist/evict.py index 38ded75..82d67c3 100644 --- a/arborist/evict.py +++ b/arborist/evict.py @@ -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 " diff --git a/arborist/qa/dag.py b/arborist/qa/dag.py index ff704db..32f3968 100644 --- a/arborist/qa/dag.py +++ b/arborist/qa/dag.py @@ -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) diff --git a/arborist/qa/evidence.py b/arborist/qa/evidence.py index 632195e..67c114d 100644 --- a/arborist/qa/evidence.py +++ b/arborist/qa/evidence.py @@ -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``); diff --git a/arborist/qa/keys.py b/arborist/qa/keys.py index 514d73a..3663471 100644 --- a/arborist/qa/keys.py +++ b/arborist/qa/keys.py @@ -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( diff --git a/arborist/qa/metacognition.py b/arborist/qa/metacognition.py index 247fa11..d40fc12 100644 --- a/arborist/qa/metacognition.py +++ b/arborist/qa/metacognition.py @@ -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 diff --git a/arborist/qa/quantifier.py b/arborist/qa/quantifier.py index 1ccdd04..b1b5f74 100644 --- a/arborist/qa/quantifier.py +++ b/arborist/qa/quantifier.py @@ -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) diff --git a/arborist/qa/query.py b/arborist/qa/query.py index 513cad1..4d572a9 100644 --- a/arborist/qa/query.py +++ b/arborist/qa/query.py @@ -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). diff --git a/arborist/qa/runner.py b/arborist/qa/runner.py index a582985..0c70bd3 100644 --- a/arborist/qa/runner.py +++ b/arborist/qa/runner.py @@ -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 diff --git a/arborist/qa/verify.py b/arborist/qa/verify.py index 9cb47bd..7a69991 100644 --- a/arborist/qa/verify.py +++ b/arborist/qa/verify.py @@ -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, diff --git a/arborist/store.py b/arborist/store.py index 959ad51..0f2b168 100644 --- a/arborist/store.py +++ b/arborist/store.py @@ -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) diff --git a/docs/_source/_ext/makefile_targets.py b/docs/_source/_ext/makefile_targets.py index 1c09b13..4a40f2c 100644 --- a/docs/_source/_ext/makefile_targets.py +++ b/docs/_source/_ext/makefile_targets.py @@ -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") diff --git a/docs/_source/concepts.rst b/docs/_source/concepts.rst index ce8c39a..36462c3 100644 --- a/docs/_source/concepts.rst +++ b/docs/_source/concepts.rst @@ -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: diff --git a/docs/_source/index.rst b/docs/_source/index.rst index cf809a5..d048bcc 100644 --- a/docs/_source/index.rst +++ b/docs/_source/index.rst @@ -1,5 +1,5 @@ Arborist API Reference -===================== +====================== Generated from docstrings. Replaces the static modules.md. diff --git a/docs/_source/merkle-agi-v7w-spatial-temporal.rst b/docs/_source/merkle-agi-v7w-spatial-temporal.rst index 99ac549..67d1d0f 100644 --- a/docs/_source/merkle-agi-v7w-spatial-temporal.rst +++ b/docs/_source/merkle-agi-v7w-spatial-temporal.rst @@ -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", diff --git a/docs/_source/v8-fork-score.rst b/docs/_source/v8-fork-score.rst index e32c415..d30e0ec 100644 --- a/docs/_source/v8-fork-score.rst +++ b/docs/_source/v8-fork-score.rst @@ -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).