Commit graph

293 commits

Author SHA1 Message Date
1dfbe3a6bf
docs: add 'Solution: RAG pipeline for 10M docs, zero hallucination' (Google L5)
Graphviz DOT diagram of the arborist pipeline as the answer to the Google
L5 system-design prompt 'design a RAG pipeline for 10M docs with zero
hallucination'. Maps our components onto the canonical 10-box RAG design
and shows the three extensions that buy zero-hallucination + near-zero
cost: deterministic verifier (not a model confidence score) -> honest
UNGROUNDED; Merkle-bound cache that skips the GPU; measured energy COGS
(~$0.07-0.16/1k answers, non-reasoning). Includes the mapping table +
the 3.47M->10M scaling math (+77GB, sourcing/storage not redesign).

Enables sphinx.ext.graphviz (SVG output) + graphviz apt package on the
RTD build; adds the page to the Summary-pages toctree. Builds clean
(page renders, DOT validates via dot -Tsvg).
2026-05-21 14:55:01 -04:00
211bbb1daf
docs: draft COGS tweet — cost of a grounded answer (Hermes ~9c, Qwen ~16c per 1k)
Main tweet + follow-up (Merkle cache hit skips GPU, doesn't increment the
per-1k). Numbers are the measured claim_lattice figures from the energy
report; note attached to hold the arbitrage/forcing-function framing until
the value side is hardened (higher N + blinded judge).
2026-05-21 13:52:20 -04:00
105b890e41
docs(#000057): correct cost claim — <$0.10/1k-q is hermes-8B only, not qwen
$0.10/1k-q overstated the qwen-27B case. Honest range: ~$0.07-0.16 per
1,000 queries of GPU electricity — hermes-8B $0.07-0.09 (under a dime),
qwen-27B $0.12-0.16 (over a dime; claim_lattice dearer than quote from
more prefilled context). Fixes the §5.4 'either rig' claim.
2026-05-21 13:50:01 -04:00
53db4ad717
docs(#000057): add quality/value side + cross-model comparison to energy report
The report is now cost AND value (quality-per-dollar), not cost-only.

§5.5 quality delta: substrate-vs-solo (code judge, n=30) on numeral +
stale fixtures, hermes-8B vs qwen-27B-nothink. Substrate lifts both
2-13x and they nearly converge (hermes 18/21, qwen 19/26 grounded-
correct) — grounding comes from retrieval+verification, not parametric
size, so the base model matters far less. Bare-model failure styles
diverge (hermes abstains, qwen fabricates). Quality-per-dollar: ~18-26/30
grounded for $0.085-0.158/1k-q.

Honest caveats recorded: CORRECT=grounded-in-2010-corpus (not current);
the stale fixture is no longer post-corpus; the qwen thinking bug (39c040c)
that voided the first run and the judge strengthening (2d31866). §1
reframed; §8 repro + §9 next updated (post-2010 fixture, SOTA judge for
residue).
2026-05-21 13:44:56 -04:00
26e4db67d1
docs: corpus loaded is the 2010 Wikipedia snapshot, not 2003
fox 2026-05-21: two corpora exist (2003-05-16 + 2010); the 2010 one is
loaded in ~/.arborist/shards (verified: 866K docs/shard, has Barack
Obama / YouTube articles a 2003 dump can't). CLAUDE.md Live-endpoints and
the energy-COGS report now state 2010; fabrication-bait fixtures target
post-2010 events. Historical closed-ticket prose left as point-in-time
records.
2026-05-21 12:36:20 -04:00
b44e9255b2
docs(#000057): add 3090/Hermes-8B rig, dollars, quant/precision confound
- §2 now a two-rig table: 4090/Qwen-27B-Q4_K_XL/llama.cpp (isolated) vs
  3090/Hermes-8B-FP8-Dynamic/vLLM (live/public). Spells out that the
  cross-model rate gap confounds FOUR variables (params, quant/precision,
  engine, GPU) — not '8B vs 27B' alone.
- §5.4 hermes results under live traffic. Method finding: the watt_bench
  window integral is unusable on a contended card, but the slope
  calibration survives clean (cancels the variable shared-load baseline)
  — so on shared/public cards use watt_calibrate, not the window integral.
  Rates: hermes 0.109/4.40 J/tok vs qwen 0.175/6.16; decode 35-40x prefill.
- Per-query DOLLARS both rigs @$0.33/kWh: a grounded substrate answer is
  <$0.10 per 1000 queries (hermes $0.085, qwen $0.158); hermes ~half qwen.
- §5.2 budget confound corrected to flag Hermes-tuning honestly (was
  rationalized). §9: fixed-budget apples-to-apples re-run + per-model
  budget tuning added as next steps.
2026-05-21 12:17:43 -04:00
9d9e530466
docs(#000057): energy-COGS report — separated prefill/decode, n=30, Dav1d-ready
Full report for Dav1d: qwen-nothink on the dedicated 4090. Headline —
prefill 0.175 J/input-tok ($0.016/M) vs decode 6.157 J/output-tok
($0.564/M), decode 35x dearer per token. The substrate prefills ~6.6k
input tok/query (vs solo ~52, 127x): ~67% of its GPU energy is reading
the retrieved context, not generating. Per-query 1719 J (substrate-CL)
vs 95 J (solo) = $0.16 vs $0.009 per 1k queries; calibration predicts
measured within ~5%. Real cost is CPU latency, not GPU watts.

Documents the full methodology + the corrections that got here
(contamination -> isolation; blended mean-W -> measured states; gross
-> not-attributable; per-token -> separated input/output; len//4 ->
real usage), threats to validity, reproducibility (commits, config hash,
persisted samples), and next rigs (3090+Hermes, reasoning, prefill-cache
study).
2026-05-21 11:50:05 -04:00
32aeb37086
fix(#000057): GPU COGS = generation only — retrieval/verify don't touch the card
fox 2026-05-21: 'we dont touch card during retrieval'. Retrieval + verify
are CPU/SQLite on the orchestrator; the GPU is idle (at the shared, always-
on model-resident floor) during them. So the substrate does NOT 'hold the
card' through its wall-clock — the gross window integral over-counts by
charging that always-on floor for the seconds we spend retrieving (energy
that exists regardless of the query; the card serves other traffic then).

Correct attribution: the GPU cost of a query is its GENERATION energy only
(the marginal — burst above the serving floor). Relabel: marginal is the
headline GPU COGS; gross is demoted to a reference 'window total, not
query-attributable'. Print + energy_cogs docstring + stock-v1-config doc
updated. No math change (marginal was already right) — this corrects the
narration. Measured qwen-nothink/4090: substrate GPU COGS is LOW
(claim_lattice $0.21/M-tok, quote $0.83) — its real overhead is latency
(CPU retrieval), not GPU watts.
2026-05-21 11:07:37 -04:00
1aff09f021
feat(#000057): energy-COGS layer for watt_bench — marginal vs gross $/1k-tok
fox 2026-05-21: compute cost-of-goods-sold by kWh vs tokens, with the
three power states (idle / warm-idle / generation) MEASURED per
card×model×server — never hardcoded (his 40/127/380 W were illustrative
of one 3090). The only operator input is --price-per-kwh (default 0.33
USD/kWh, a configurable site rate).

energy_cogs() (pure, unit-tested) decomposes measured generation energy
against the measured warm-idle baseline:
  * gross    — all measured joules over the window (all-in, includes the
               warm-idle cost of keeping the model hot, amortized).
  * marginal — joules ABOVE warm-idle: what one more request's burst
               actually costs (clamped >=0).
kWh = J/3.6e6; $/1k-tok is the unit that compares to API pricing. Both
surface per cell + a COGS print line.

watt_bench's arborist arm now loads the frozen bench.stock_v1 policy
(--answer-mode, drift-guarded on non-reasoning) so cost is measured for
the SAME substrate the campaign grades. Cells record
window_start/end_unix so a post-hoc load_monitor queue-depth cross-ref
can flag organic-traffic contamination on the non-isolated single-slot
endpoints. 6 COGS tests; full suite 2534 passed.
2026-05-21 10:19:41 -04:00
1a7f8eb4ea
feat: STOCK V.1 two-mode config family + wire treatment arms to the pin
fox 2026-05-21: characterize substrate-ON under BOTH answer shapes, so
answer_mode is a swept axis, not a single pinned value.

stock_v1.py now exposes STOCK_V1_POLICIES{quote,claim_lattice} +
STOCK_V1_GOVERNANCE_HASHES (quote 5b6ca4c5..., claim_lattice 036a4c79...),
policy_for(mode), and assert_not_drifted(mode). Shared pins (crosslang
OFF, repair OFF, quantifier dry-run, metacognition label-only,
soft-preflight OFF, claim cap 12, v2-acronym-aware) are frozen
identically across modes.

Wire the treatment arms to the pin (the consumer-side step that makes
the freeze real):
  * control_ab    --answer-mode {quote,claim_lattice}
  * control_sweep --arborist-answer-mode {quote,claim_lattice}
Both default claim_lattice (prior behavior), call assert_not_drifted on
non-reasoning runs (halts the sweep if DEFAULT_QUERY_POLICY drifts), and
load the frozen policy_for(mode) instead of an inline
dict(DEFAULT_QUERY_POLICY, ...). Reasoning refs (phase 3) keep their
documented JSON overrides and skip the assert by design (different hash).

jaggedness is left standalone — it is a mode-agnostic retrieval
instrument, coupling it to the answer-policy freeze adds friction with no
correctness gain. Full suite 2528 passed.
2026-05-21 10:15:26 -04:00
e227bbc32a
feat: pin STOCK V.1 substrate — frozen substrate-ON config for the GPU campaign
Before the multi-day campaign (hermes 3090/4090 -> qwen 3090/4090 ->
reasoning variants) the substrate-ON treatment arm must NOT drift. It
previously inherited DEFAULT_QUERY_POLICY implicitly, so any mid-run
edit would silently change what 'substrate-ON' means.

bench/stock_v1.py snapshots DEFAULT_QUERY_POLICY + re-asserts the
load-bearing pins (answer_mode=quote, crosslang OFF, repair OFF,
quantifier caps dry-run, metacognition label-only, soft-preflight OFF,
claim ceiling 12, v2-acronym-aware), then hashes the whole effective
dict. assert_not_drifted() fails loudly if that hash ever changes —
re-pinning is a deliberate fox-gated V.2 bump, never silent. The whole
campaign is identified by one governance_policy_hash
(5b6ca4c5...aade4e). Non-reasoning + non-distributed are harness axes
(reasoning -> phase 3, mesh -> later fork), not policy fields.

docs/stock-v1-config.md documents V.1, substrate-OFF (control_ab arm A),
the campaign matrix, and the energy-COGS companion (#000057) — whose
power states (idle / warm-idle / generation) are MEASURED per
card+model+inference-server at runtime, never hardcoded; only $/kWh is
an operator flag.
2026-05-21 09:43:17 -04:00
9d0015b4d4
feat(#000060): bench/jaggedness.py — deterministic retrieval jaggedness instrument
v1 of the same-model substrate-delta harness's non-jagged metric.
For one corpus title, surface-perturb its question (numeral / accent /
hyphen / honorific / amp / brit) preserving the referent, then ask
whether retrieval surfaces the SAME target for canonical vs perturbed
phrasing. J_norm = XOR disagreement rate @k (lower = less jagged);
graded mean |Δrank| catches rank instability the binary metric misses.

Pure query --dry-run: no LLM, no verifier, no judge, no n=3 noise, no
5pp floor — the recall_at_k discipline. Reuses recall_at_k.probe +
mine_questions._surface_variant. Feeds #000012 ForkScore
ΔJaggednessReduction. A-vs-C answer-quality arm already exists under
#000057 (control_ab/control_sweep) — not rebuilt. Curvature + LLM-arm
jaggedness delta remain open (ticket §8).

make bench-jaggedness JAGGED_LIMIT=40 JAGGED_K=8
2026-05-21 08:38:07 -04:00
7a43ceb699
docs(#000059): bounded-ingestion hard constraint on the claim graveyard
fox: a graveyard that keeps every wrong answer forever grows unbounded
like cancer and is counter to constraint-optimization. Bake in the
bound:

- earn-to-enter (recurrence-gated) — a failure earns a tombstone only
  when its canonical claim-family re-fails; one-offs dropped.
- fingerprints not transcripts (UTXO-set analogy) — store
  canonical_claim_family|falsifier_root|failure_class, prune bulk text.
- decay/compact to steady-state — evicts like a surface, never a core.
- off the hot path — dedicated graveyard shard, bloom-filter burden
  check only.

Gossip-group falsifier admission inherits the same discipline:
difficulty-adjusted stable-rate ingestion (BTC block-rate target) +
per-window budget (#000036), enforced in #000012/mesh. BTC lesson is
bounded self-regulating ingestion, not store-everything. If it cannot
be bounded to a steady state, the graveyard is not built.
2026-05-20 19:28:48 -04:00
d4480cddb7
docs(#000058,#000059,#000060): ticketize Dav1dPrometheus protocol-layer report
Three tickets from the 2026-05-20 Dav1dPrometheus "Protocol-Layer AGI"
working report (held outside the repo; referenced not committed):

- #000058 cache_key_9 verifier-policy mandatory-vs-legible decision +
  doc reconcile. Records the five-step-#1 correction: verifier fields
  already fold into governance_policy_hash, so the 9th dim is audit
  legibility not a correctness gap.
- #000059 admission discipline: claim-graveyard burden-shift +
  self-providence quarantine (guards the existing ingest-self-providence
  self-confirmation loop).
- #000060 H-ABCDEFG same-model substrate-delta harness (jaggedness +
  curvature); curvature-aware ForkScore folded into #000012 Phase 2,
  not spawned as a sibling.

Reconciles CLAUDE.md cache_key invariant (8-dim -> 8 + optional 9th).
Next ID 000058 -> 000061.
2026-05-20 19:27:08 -04:00
69a9642296
docs(#000057): capture known-good serving invocations for the salt buildout
The exact llama.cpp (qwen/4090) and vLLM (hermes/3090) launch commands,
recon'd 2026-05-20, so the foxhop-states salt states can be written
accurately rather than guessed. Notes the convention (salt manages the
systemd unit; engine binaries + model artifacts stay manual on
/mnt/data as documented prereqs) and the live-hermes cutover constraint
(keep >=1 hermes online; qwen is expendable).
2026-05-20 15:20:34 -04:00
ab8df76792
feat(#000057): CPU wattage (RAPL) in watt_bench + expanded cost/quality matrix doc
Toward fox's next goal: score the full serving stack on quality AND
cost — {qwen, hermes} × {llama.cpp, vLLM} × {3090, 4090} × {solo,
arborist}, measuring CG% + GPU watts + CPU watts + joules/answer per
cell.

watt_bench.py — adds CpuSampler (Intel RAPL package energy via
/sys/class/powercap/intel-rapl:*/energy_uj). RAPL exposes a cumulative
microjoule counter, so energy-over-window is an end-minus-start diff
(handles wrap) — more accurate than integrating instantaneous power.
Sums multi-package. energy_uj is root-only by default (PLATYPUS /
CVE-2020-8694), so it degrades to available=False when locked;
--cpu-energy-cmd 'sudo cat {path}' supplies a privileged reader when a
sudo rule exists. Each cell now reports gpu/cpu/total joules-per-
question + gpu joules-per-token; the report records cpu_rapl_available.
Verified: graceful degradation when locked; RAPL diff math (1->4 MJ uJ
= 3.0 J, exact).

benchmark-matrix.md — expands the cost section to the full 16-cell
(model × engine × GPU × arm) design, the per-cell metric set (quality +
GPU + CPU energy), the serving-stack inventory from 2026-05-20 recon
(4090=qwen/llama.cpp, 3090=hermes/vLLM — each box has one engine + one
model today), and the buildout gap (vLLM+qwen, llama.cpp+hermes, cross-
GPU models). Notes idle-floor asymmetry (hermes/3090 ~127W vs
qwen/4090 ~20W) as a real optimizer input.

Harness is ready; the serving-config buildout + RAPL perm grant are the
remaining (ops, fox-directed) prerequisites to run the full matrix.
2026-05-20 14:45:49 -04:00
5260161e6f
feat(#000057): benchmark matrix doc (for David) + GPU wattage harness
Two deliverables for the cost/energy axis of the constraint optimizer.

docs/benchmark-matrix.md — shareable spec of the control experiment:
the question, fixture (386 office-holder Qs with corpus-vintage gold),
the 3-model × 3-framing × 2-arm matrix (18 cells), the verdict
vocabulary + two reads (accuracy vs grounding-fidelity), the
deterministic code judge + its Opus calibration, the results-so-far
table, and the NEW cost dimension (tokens / latency / GPU watts /
joules-per-answer measured per GPU tier). Self-contained — readable
cold by David.

bench/watt_bench.py — GPU wattage harness. Samples nvidia-smi
power.draw on the inference GPU while driving a small representative
subset, reports mean/peak watts, trapezoid-integrated joules,
joules-per-question, and joules-per-token. Tags the GPU
(--gpu-label 3090|4090) so the optimizer can compare hardware tiers.
Idle-baseline sampling separates load draw from idle. Does NOT grade
(energy is independent of correctness); saves answers + per-question
timing to JSONL for a later quality-per-joule pass via
score_with_code_judge.

Designed to run ON the GPU box (the orchestrator has no GPU; the
3090/4090 live on the inference boxes). Degrades gracefully when
nvidia-smi is absent (energy fields null) so it is testable anywhere.
Verified: PowerSampler graceful degradation + trapezoid integration
(synthetic 100->200->200W over 2s = 350 J, exact).

The headline cost finding the optimizer must weight: qwen-think
reasoning = 1300-3300 tokens/answer vs qwen-nothink ~50-100 (20-50x),
for a workload where arborist+qwen-nothink already lands 82% CG. The
energy numbers will quantify whether reasoning's premium is ever
justified — grounding-fidelity per joule, not per answer.
2026-05-20 12:33:58 -04:00
42f614a501
docs(#000057): Addendum 8 — control sweep retrieval × model × framing × reasoning
Durable record of the #000057 sweep in the bench journal. Captures:

- The question: is Hermes-8B's confident present-day-officeholder
  fabrication an 8B weakness, a framing artefact, or does retrieval
  fix it? Crosses {hermes, qwen-nothink, qwen-think} × {plain,
  source_relative, as_of_corpus} × {solo, arborist} on a 386-item
  office-holder fixture with corpus-vintage gold.

- The judge methodology: Opus headless judge burned quota (79.5%
  JUDGE_ERROR), replaced with the deterministic code judge
  (bench/judge_code.py), calibrated against Opus's gradeable records
  (CG agreement 13->47%, WRONG 56->89%, ABSTAINED 80->95%).

- Consolidated CG% scorecard, all arms on the identical final judge.

- Three findings:
  1. Retrieval dominates — arb/qwen-nothink/plain 82% vs 7% solo;
     no solo config approaches the retrieval arms.
  2. Reasoning does NOT improve raw correctness — qwen-think/as_of
     44% vs nothink 50%.
  3. Reasoning's real cost is broken honest-abstention —
     qwen-nothink/source_relative abstains 97% (clean); qwen-think
     only 61%, reasoning itself into wrong parametric answers.

- Production recommendation: arborist + qwen-nothink, plain framing,
  reasoning OFF (82% CG, ~0% abstain, 11% wrong-assert).

- Held cell noted: arborist+qwen-think running at write time, result
  to be appended.

Bench %s are point-in-time measurements (not repo-derived counts),
so no AUTOCOUNT tags — consistent with addenda 1-7. test_doc_counts
3/3.
2026-05-20 06:52:42 -04:00
981ba84f4a
modified: docs/diagrams/arborist-modules.png
modified:   docs/diagrams/mesh-epoch-lifecycle.svg
	modified:   docs/diagrams/query-pipeline.png
2026-05-19 17:05:16 -04:00
a4f3e126f7
feat(#000049 §7 #28): tinygrad NLI backend + deterministic engine-agreement A/B; ONNX-immunity rationale
Opt-in third NLI inference backend (ARBORIST_NLI_BACKEND=tinygrad) in
qa/nli/shadow.py, parallel to torch/onnx-int8, behind the #000049
cage: shadow-only, never an audit_mode input, never auto-preempts the
proven path (guarded so it cannot regress torch/onnx). Loads the ONNX
export through tinygrad's frontend wrapped to the existing
model(**enc).logits contract so _nli_batch is byte-unchanged.

bench/scripts/nli_backend_ab.py + make bench-nli-backends: deterministic
A/B, gate is numerical agreement with the torch reference first,
latency second (a divergent engine = a different shadow signal = a
different nli_policy_hash). Instrument is honest — reports a requested
backend as unavailable rather than relabelling a fallback's numbers.

First CPU-smoke run already quantified that the deployed §7 #22 int8
export diverges Δmax≈0.42 from torch — the immunity property made
measurable, not a defect. Real tinygrad numbers pending a producer-box
run (tinygrad not an arborist dep; frontend op-coverage for the large
MNLI checkpoints unverified by design).

docs/onnx-vendor-capture-immunity.md: why the model-in-proof-path cage
makes the inference engine an interchangeable sidecar, never a trust
dependency — public-domain positioning capital. Indexed in CLAUDE.md.

Full suite 2498 passed (identical to baseline); 24/24 NLI tests green.
2026-05-19 12:34:04 -04:00
1356459091
feat(#000057): control experiment harness — Hermes-solo vs Arborist, blinded Opus judge (smoke-verified)
bench/control_ab.py + `make control-ab` (gated on judge-self-test
as a make dependency — instrument gate cannot be skipped). Same
model both arms; gold = target-article text by target_root; Arborist
[E…] scaffolding stripped (blinding — format can't betray the arm);
Arborist UNGROUNDED credited as honest abstention; hermetic Opus
judge; deterministic aggregate; self-auditing JSONL; threats-to-
validity printed in the report.

N=2 smoke: clean end-to-end, 0 JUDGE_ERROR — and already surfaced a
case AGAINST the treatment (solo correctly ABSTAINED; Arborist
HYBRID-WRONG). The instrument can falsify the Arborist value claim;
that is the point. n=2 proves nothing (report says so) — verdict
needs a real N.
2026-05-19 08:58:38 -04:00
65fd9fad5d
feat(#000057): hermetic external judge instrument — built + verified 4/4 (make judge-self-test)
fox ruled judge = Opus via `claude -p`. bench/judge.py:
hermetic (`env -u CLAUDECODE claude -p`, fresh process, context =
only (Q, answer, gold) — no arm label, no Arborist context, no
session), blinded-by-caller, reference-grounded against the fixed
gold (ignore parametric knowledge), structured via FINAL_VERDICT=
sentinel parsed LAST-match.

Instrument-before-experiment gate worked: first cut parsed
first-match over the model's chain-of-thought → 0/3 self-test. The
judge REASONED correctly; the parser was the defect (+ two bad test
fixtures, my error). Hardened (sentinel contract + fixed fixtures),
re-verified: `make judge-self-test` = 4/4 on known-verdict triples
via real claude -p. The make target is the precondition gate; no
control run trusts the judge until it passes.

Threat to validity recorded, not hidden: same model family judging;
mitigated (blind + no-stake + reference-grounded) not eliminated —
different-family SOTA cross-check is the only full removal.

Next: bench/control_ab.py + `make control-ab` (Hermes-solo vs
Arborist, gold=target-article text, blinded, judged) — NOT yet
built; no broken make target shipped for it.
2026-05-19 08:44:47 -04:00
fa81b97c5c
docs(#000057): judge reference = fixed independent gold, not either arm's retrieval (fox Q)
fox: should the judge get the same docs, or the 8 retrieved/cited?
Neither. Per-arm retrieved docs (a) are undefined for Hermes-solo
(no retrieval → breaks A/B symmetry), (b) re-import circularity
(judging the treatment vs its own retrieval), (c) measure citation
self-consistency (Arborist's verifier already does that), not
truth. Judge's reference = the mined question's fixed ground-truth
target/gold, identical for both arms, independent of retrieval —
the ground-truth-carrying fixture supplies exactly this. Recorded a
distinct, non-headline faithfulness ablation (judge Arborist vs its
own context) so it is never conflated with the control delta.
Index row unchanged (skim surface; ticket body is the design log).
2026-05-19 08:36:30 -04:00
1fdae8830a
docs(#000057): correct judge design — strong SOTA external judge (fox), not deterministic-only
I over-applied a proof-path rule. "No LLM-as-judge" guards Arborist's
*verifier* (an LLM in the proof path = the circularity Arborist
kills; #000049's poor reliability is a proof-path-model constraint).
The control experiment's judge is external science — outside BOTH
arms, scoring post-hoc, touching neither system's internals — so it
cannot break the experiment. fox: use a strong SOTA model
(stronger than both systems under test), blinded + reference-
grounded + transcript-logged. This lifts the wrongly-imposed
atomic-fact-only limit (judge handles essay grounding; #000049's
exclusion was right for the proof path, wrong for external science);
deterministic gold-key demoted to a cheap atomic cross-check.
Still fox calls: fixture population, which SOTA judge (API
cost/egress), spend. Scaffold; no build past gate-1.
2026-05-19 08:33:36 -04:00
deb388a39b
docs(#000057): fold in fox's control-arm ruling — Hermes-solo vs Arborist, external deterministic gold-fact judge
The review's strongest point (§4.1) + fox: every measurement so far
is WITHIN Arborist — no control arm. Folded into #000057 (not a new
ticket): control = Hermes-solo; judge external/deterministic/
paraphrase-tolerant via a mined gold-fact answer key (resolves
circularity + no-LLM-judge + paraphrase at once); headline metric =
fabrication-vs-honest-abstention delta, not raw accuracy (common-
knowledge fixture would falsely show null — parametric memory).
Smallest-proof reorder: v1 = single-shot Hermes-solo vs Arborist on
a fabrication-bait atomic-fact fixture; recursive-drift loop is v2,
gated on v1. Atomic-fact only; essay-grounding = #000049's unsolved
NLI, OUT. Still fox calls: fixture population, gold-key shapes,
spend. Scaffold; no build past gate-1.
2026-05-19 08:26:14 -04:00
7100f7277b
docs(#000057): scaffold — minimal deterministic recursive-drift A/B (Hamming de-novo review)
The 2026-05-19 GPT-5.5 Hamming-framed review's ONE arborist-scoped,
ticket-worthy nugget: prove the Merkle-Providence-Reverse-RAG
whitepaper's headline claim (untracked evidence loss -> unbounded
recursive drift; witness-preserving state bounds it). Scaffold only,
awaiting fox go/no-go on scope.

Discipline encoded from the 2026-05-18 precedent (a grand target is
unfalsifiable until the instrument can resolve it — four hypotheses
died, only the deterministic mined-recall instrument broke it):
instrument-before-experiment, ONE task not eight, minimal ON/OFF
A/B, non-claims pinned (necessary substrate, NOT AGI).

Everything else in the review (rename, corpus hierarchy, IQ/talent,
ToE/Riemann/identity/geopolitics) deliberately NOT ticketed —
narrative/positioning, not arborist engineering; don't-proliferate.
Exactly one ticket. Next ID 000057 -> 000058 (same commit).
2026-05-19 08:14:04 -04:00
5d43fdc037
docs(#000056): firm cross-language numbers + correct the French figure
The fr-no-mask sweep (2026-05-18) corrected an over-pessimistic read:
French was reported 47% but that was the failed-mask artifact; honest
fr no-mask is 61%. §9 + index now carry the firmed n=1 table (EN 85%
· es-nomask 71% · es+mask 65% · fr-nomask 61% · fr+mask 47%), the
comparator-corrected verdict (sandwich is a ~0%→61-71% net win vs the
real no-support baseline; the −14/−24pp is vs native English, not a
regression), and the entity-mask lever's confirmed net-negative
status (default-OFF). Doc-only; no code change.
2026-05-18 14:23:49 -04:00
2c98fc964e
feat: cross-language Q&A (Operation Sandwich) + Windows quickstart — all default-OFF
Three workstreams, full suite 2482 passed, experimental paths default-OFF.

#000055 — Windows quickstart without make
  tasks.py (pure-stdlib runner) + make.bat shim + .gitattributes;
  README Windows section rewritten. Quickstart needs only Python
  3.10+ (no make/bzip2/curl/bash). Mirrors the Makefile quickstart
  subset; drift-pinned by tests/test_tasks_runner.py.

#000001 §7 Phase 0 — deterministic cross-language guard
  arborist/qa/crosslang.py: non-English signal (¿/¡/non-ASCII) + an
  es function-word stoppack. Fail-closed to UNGROUNDED before
  retrieval/LLM (mirrors the quantifier reject-DAG) when no content
  token survives, else strips es stopwords from the retrieval query
  only. English path byte-identical by construction. Default OFF
  (crosslang_guard_enabled). Measured: the anarcocapitalismo field
  case 10.4s -> 1.6s.

#000056 — Operation Sandwich (cross-language grounding)
  arborist/qa/mt/: opus-mt es/fr/ru<->en, lazy per-pair memoised
  singleton (fixes the 88%-engine-error concurrency defect),
  manifest-pinned, [mt] extra; entity_mask wrapper. Sandwich =
  translate query in (retrieval + LLM prompt) -> English answer ->
  UNTOUCHED verifier grounds English-vs-English -> translate the
  verified answer out as display-only (banner-labelled, zero
  grounding). question_hash + verifier_policy_hash invariant; MT
  engine identity binds into RetrievalPlan, not governance. CLI
  --crosslang-translate / make XLANG_MT=1. Default OFF; entity_mask
  default OFF (measured net-negative at bench scale). Fan-out bench
  (bench/*.py): Spanish ~0% -> 71% grounded vs the real no-support
  baseline; the round-trip predictor was tried and refuted; the
  entity-mask lever failed at scale (corpus-title anchoring untried).

CLAUDE.md: cross-language bright-line convention + module map.
Pre-existing modified diagram files are intentionally excluded.
2026-05-18 12:12:23 -04:00
b711215f11
docs: pagers — rename 'not grounded' → 'ungrounded' (agreed label set: grounded / partly grounded / ungrounded)
'not grounded' was a drift from the agreed three-label vocabulary. Single-word labels are cleaner in tables, diagrams, and prose.
2026-05-14 12:56:13 -04:00
42ed5c61a7
docs: pagers — point hermes link at /v1 (display) → /v1/models (href) so readers see the OpenAI-compatible base URL and can click through to the live model card
Previously linked to the bare domain, which serves a marketing page. The actual OpenAI-compatible endpoint is /v1; /v1/models is the clickable verification (returns the served model card on the live deployment).
2026-05-14 11:33:40 -04:00
3a9389f24b
docs: correct storage figures in pagers — actual per-shard target is ~10 GB, live deployment is 4 shards × ~9.6 GB ≈ 38 GB (was wrongly stated as ~2 GB)
Shard capacity convention is documented in arborist/search/fts5.py:113 ("~50ms cold per token on a 10GB shard"). The earlier "~2 GB for a Wikipedia-sized corpus" line in both pagers was a fabricated figure off by 20×. Replaced with the real numbers: per-shard ~10 GB design target, live deployment of four shards totalling ~38 GB and holding 3.5 M documents / 6.2 M chunks.
2026-05-14 11:16:20 -04:00
75ae470581
docs: rewrite arborist-one-pager + arborist-two-pager for external readers — drop ticket refs, schema versions, and internal vocabulary; reframe around user value (verified answers, fabricated-citation prevention, replay)
Old drafts read as internal substrate notes. Rewrites lead with what the system does for a consumer or evaluator and what it costs to run, with no references to internal tickets, table names, schema-version strings, governance hash dimensions, or per-record audit-mode tokens. Appendix diagrams updated in lockstep: friendly labels ("grounded / partly grounded / not grounded") replace the schema-column trichotomy, layer names paraphrased away from SURFACE/CORE/PROVIDENCE.
2026-05-14 10:02:08 -04:00
0aada29a8e
docs: arborist-one-pager + arborist-two-pager — Dav1d/fox-signoff summaries with letterhead, license, and 2 strategic appendix diagrams
1-pager (docs/_source/arborist-one-pager.rst, 1 page) for AI-literate readers: the trichotomy, the 8-dim cache key, CTI synthetic-elision-impossible, soft-channel separation, real-traffic bench numbers (mis-cite 100% @ 0% FP, warrant 92/92, quote 0.54 STRICT-rate).

2-pager (docs/_source/arborist-two-pager.rst, 3 pages = 2 body + 1 appendix) for technical reviewers: letterhead, Permacomputer Preamble license box, six numbered sections, plus appendix figures (pager-arch-stack 3-layer architecture, pager-verifier-flow question→pointer→verifier→trichotomy).

Both pages live under docs/_source/ so the same RST renders into the Sphinx readthedocs site (toctree caption "Summary pages" added to docs/_source/index.rst) AND into standalone PDFs via rst2pdf (docs/pager.style, lazy install into .venv).

Makefile targets: docs-one-pager, docs-two-pager, docs-pagers, docs-pagers-clean. Diagrams render through the existing DOT pipeline.
2026-05-14 09:48:50 -04:00
90d5c54c0a
docs: relevance-and-veto-synthesis-for-dav1d.md — single decision brief synthesizing #000049 + #000052 §3.1 + §3.2 for forward review
Synthesizes the bench-maxing work across:
  #000049 NLI recombination veto (bart-large-mnli/k=12/margin/θ=0.999
    → 48% real-haystack recall at 0/808 STRICT FP — partial closure,
    Phase-3 semantic candidate selector for full closure)
  #000052 §3.1 diagnose_coherence (lexical sidecar, advisory-only,
    1.1% real-STRICT FP after round-2 patch)
  #000052 §3.2 relevance reranker (bge-reranker-large + cleaned +
    θ ≤ -2.42 → 100% mis-cite / 55% deflection / 0% STRICT FP —
    motivating Zionist-shape failure fully covered)

The three are architecturally orthogonal (§3.2.2 step 3C verified:
combining lexical sidecars with the relevance reranker gives no
lift; each owns its own failure-shape slice). Three structurally
distinct demote-only signals layered on the binary verifier.

Three runtime-promotion decisions for fox+dav1d:
  - §3.1: keep advisory or wire policy hook? (probably advisory)
  - §3.2: promote at the fp=0 operating point? (sign-off folds
    relevance_policy_hash into governance_policy_hash)
  - #000049: promote at 48% partial closure, or wait for Phase 3
    semantic candidate selector?

Bench-maxing methodology codified in CLAUDE.md is the transferable
artifact: 'clean candidate-bench can mis-predict in BOTH directions
— real-data fixtures on both precision AND recall axes are the
only load-bearing measurement'. Eight instances across the two
arcs; the discipline applies to any future model-based addition.

Indexed in docs/TICKETS.md 'Distinction from other docs' section as
a non-ticket reference doc. Production verifier unchanged; nothing
in audit_mode; all work SHADOW pending sign-off.
2026-05-13 15:34:21 -04:00
9fc951592d
#000052 §3.2.2 step 2: relevance shadow sweep on 808 pooled bench-qa STRICT — universal walk-back, runtime veto NOT VIABLE on this design
All 6 swept rerankers (bge-large/base, MiniLM-L-2/L-4/L-6/L-12)
false-fire on 4.5–21.8% of real bench-qa STRICT at their
candidate-bench fp=0 θ. The smallest θ that yields fp=0 on real
STRICT is BELOW the candidate-bench NEG max for every model —
meaning at the runtime-safe θ, catch on the 12 candidate-bench NEG
= 0/12 across the board.

Structural reason: real bench-qa STRICT answers have a much wider
score distribution (bge-large STRICT: min -2.20, p10 +2.99, p50
+5.80, p90 +7.54) than the tight contrived candidate-bench POS
band. The bottom 10% of legitimate STRICT score below where the
candidate-bench NEG cases sat. Distributions overlap heavily; no
threshold separates them.

This is the §3.2 mirror of #000049 §7 #27's recall-side walk-back —
clean candidate-bench → fails real-pipeline gate. Same diagnosis:
lexical-candidate selection + cross-encoder scoring + hard threshold
doesn't survive real-pipeline heterogeneity.

Verdict: relevance reranker CANNOT be promoted to a runtime
demotion-only veto on this design. demote_below_score stays null;
manifest gains runtime_viability block documenting the negative
result + the still-viable advisory soft-signal uses (render-tail,
multi-signal advisory, contrastive Q→A vs claim→source delta).

bench/scripts/relevance_shadow_sweep.py + bench/results/
relevance-shadow-sweep-pooled808.json committed. Production
verifier unchanged; advisory only; no audit_mode effect.
2026-05-13 14:17:38 -04:00
5f4f4ceb1c
#000052: more tests for §3.1 + §3.2 — bench-max the detectors against real data
§3.1 diagnose_coherence (now 19 tests, +10 from the parallel session's 9):
- 3 more positive shapes (multi-sentence vacuous, named-entity circular,
  grammar-term phrase_component_reuse).
- 5 xfail regression tests for SHAPES THAT FALSE-FIRE on real bench-qa
  STRICT data (44/808 = 5.4% FP rate measured on the pooled n=1+3+5
  STRICT answers). Each xfail names the exact shape + why it should
  ideally be 'ok' + which rule needs tightening:
    * 'The chemical symbol for gold is Au.' → vacuous (short predicate)
    * 'Michael Jordan's Restaurant was a restaurant ... named after
      Michael Jordan.' → circular (named-after re-use)
    * 'The Western X was the western half of the X' → circular
    * 'The name <Phrase> is a translation ... of the <derivative>' →
      phrase_component_reuse (translation/etymology)
    * claim-lattice [E1 | … …"] tails → vacuous (truncated bracket
      fragment)
    * 'The term <X>' → phrase_component_reuse (idiomatic English)
- 1 load-bearing real-traffic test: FP rate on 808-cell pooled STRICT
  must stay ≤ 7% (current 5.4%) — fires loud if a future change
  regresses it. Skips on fresh-checkout (bench/qa_results/ gitignored).

§3.2 ShadowRelevance (now 20 tests, +7 from the round-1 scaffold):
- Manifest tests for round-2 primary (bge-reranker-large), the size
  spectrum coverage (50-560MB), the candidate-bench findings block
  (biggest-within-family / not-across-families / deeper-not-better /
  capacity-floor).
- Pair-kind distinction (question_answer vs claim_source recorded
  separately for downstream telemetry / governance hashing).
- Batch-order preservation (_score_batch must return scores in input
  order — load-bearing for downstream zip-back).
- Empty-input handling (Q empty, D empty, whitespace-only).
- Zionist-entity discriminator sanity (on-topic > off-topic logit).
- demote_below_score-stays-null invariant (the §7 #18→#27 discipline:
  no hardcoded threshold; must come from a real-traffic shadow sweep).

Total: 101 passed + 6 xfailed (5 §3.1 regressions documented + 1 from
parallel session). The 5 xfails are the bench-maxing receipts — they
document EXACTLY which shapes §3.1 false-fires on, with the rule that
needs tightening named in each reason.
2026-05-13 12:38:09 -04:00
c2c06c971e
#000054 index row: Phase-2 landed ce855db + bench result recorded 2026-05-13 10:28:19 -04:00
79ba3f99fb
#000054: record Phase-2 bench result (n=3 limit=5: 30/45 STRICT, 0 regressions on basics)
`make bench-qa BENCH_QA_N=3 BENCH_QA_LIMIT=5` (2026-05-13T14:24Z) on
the bench/qa_questions.txt set: 30/45 STRICT (67%), zero regressions
on mona lisa / capital of france / new london bridge (each 9/9 STRICT
across quote / pointer / lattice modes). The bench-qa-smoke n=1
flickers I saw ("dinosaurs" S→U, "soviet union" S→H) were LLM
stochasticity at n=1, not retrieval bugs. GNU-linux + python failures
look like genuine hard questions, not Phase-2 side effects.
2026-05-13 10:27:57 -04:00
ce855dbdad
#000054 Phase 2: synonym_expand cap-aware + strict view + retrieval-route surfacing
End-to-end gap-close from the Phase 1 extractor. Five interlocking
fixes; live-verified that `what is a CPU?` → "Central processing unit"
at #1, `what is a GPU?` → "Graphics processing unit" at #1
EVIDENCE-WARRANTED 1/1; Mount Kilimanjaro / Soviet Union queries
unchanged (no regression).

(a) `synonym_expand` over-cap path is now rank-and-truncate by
source-frequency (descending) instead of hard-skip. CPU has 13
legitimate homonym expansions across the corpus; the prior
MAX_NEIGHBORS_PER_TOKEN=8 cap contributed *zero* expansion → no
canonical-article surfacing. Now: keep the 8 dominant by per-(token,
target) source-root count via _load_neighbor_source_freq.

(b) `_search_titles` orders by FTS5 bm25 ASC instead of LENGTH(title)
ASC on the FTS5-MATCH path. The length-asc tie-break was correct for
the 2026-05-02 "Back to the Future" LIKE-substring case but
counter-productive on FTS5 (tokenized; no substring junk; length-asc
preferred "Unit" / "Unite" / "B unit" over "Graphics processing
unit"). LIKE fallback keeps length-asc since the substring issue
persists there.

(c) `accept_tokens` (feeds title-search, core-keyword, title-rerank)
uses the synonym-expanded set instead of qtokens-only. The Phase 1
expansion existed but was only used in the FTS5 OR-fallback; satellite
articles saturated the budget before the canonical article entered.

(d) ARCHITECTURAL: `synonym_expand_strict()` (new — high-trust
evidence-kind subset: manual + manual_legacy + acronym_parens,
**excludes** link_reciprocity) for use in the multiplicative
`_rerank_by_title_purity` and as the source for `accept_tokens`.
Reciprocal-wikilink edges express *topical adjacency*, not synonymy
(a `Dinosaurs` page reciprocally links to `Curious George Brigade` →
edge that should not amplify retrieval); a multiplicative ranker over
them blows up. Strict view preserves the acronym-parens surfacing
(those edges ARE the phrase=expansion identity) while keeping
link-reciprocity to additive retrieval-route boosts via the broad
synonym_expand (still wired to `or_synonym_pool` for the FTS5 OR
fallback).

(e) Extractor regex tightened `[A-Z]{2,6}` → `[A-Z]{3,6}` and purged
~21K 2-letter acronym edges from shards. 2-letter acronyms (AI/ML/OS/
US/UK/IT/PC/TV) homonym-collide too often with common 2-letter QUERY
tokens like `go`/`is`/`am` — without this, "why did the dinosaurs go
extinct?" pulled Curious George Brigade via GO-acronym edges. The
high-value acronyms (CPU/GPU/RAM/DNA/FBI/WHO/…) all clear 3 chars.

Also: CLAUDE.md gains a "prefer existing ticket; only split for
Dav1d-review audience" discipline note (saved as feedback memory) —
this work is itself an example: would have been #000055 + #000056 +
#000057 under the prior pattern; instead extends #000054.

Suite: 2531 passed (no regression). bench-qa in flight separately.
2026-05-13 10:23:36 -04:00
da5af2dfaa
#000052 §3.2.1 round-2: extend size spectrum to 7 models (30MB-560MB, ~20×) — real model science from a wider sweep
7 models on the 4090 against the 26-pair candidate-bench:

  bge-reranker-large    560MB  +6.285  ← new primary (most cushion)
  ms-marco-electra-base 110MB  +5.349  (cost alternate — 5× smaller, 87% the margin)
  MiniLM-L-4-v2          50MB  +3.187
  bge-reranker-base     280MB  +3.076
  MiniLM-L-6-v2          80MB  +3.053  (was primary before §3.2.1)
  MiniLM-L-12-v2        130MB  +2.663  (deeper ≠ better — same pattern as §7 #24)
  MiniLM-L-2-v2          30MB  -1.970  ← capacity floor (NOT separable, 10/12 catch)

Findings:
- Biggest is best WITHIN a family (bge-large > bge-base, 2× size → 2× margin).
- Across families: electra-base (110MB) beats bge-base (280MB) — 60%
  smaller, 75% more margin. Architecture/training corpus > parameter count.
- Depth non-monotonic within MS-MARCO MiniLM: L-4 > L-6 > L-12.
- Capacity floor between L-2 (30MB, fails) and L-4 (50MB, separates).
- 6 of 7 clean-separate the candidate-bench. The 'reranker catches
  Zionist-style mis-cites' claim is a property of competent rerankers
  as a class — once above the floor.

Manifest primary moves to bge-reranker-large for cushion. demote_below_score
STAYS null — clean candidate-bench doesn't predict real-pipeline behavior
(§7 #18→#27 = 6 verdict flips). Expect a walk-back at §3.2.2 step 2.
2026-05-13 10:05:56 -04:00
aeeef603a1
#000052 §3.2.1: candidate-bench landed (4 models × 26 pairs on the 4090 — proper bench, not the 6-pair smoke)
All 4 manifest candidates clean-separate (12/12 NEG catch at 0/14 POS FP),
so 'reranker discriminates Zionist-entity-style mis-cites' is a property
of MS-MARCO-trained rerankers as a class — not the specific L-6 I picked
first. Ranked by separation margin (per §7 #18: separation beats raw):
  ms-marco-electra-base   +5.349  ← new primary
  BAAI/bge-reranker-base  +3.076
  ms-marco-MiniLM-L-6-v2  +3.053  (previous primary, demoted)
  ms-marco-MiniLM-L-12-v2 +2.663  (worst — deeper ≠ better)

Manifest primary moved to electra-base for the cushion. demote_below_score
STAYS null — clean candidate-bench thresholds don't predict real-pipeline
behavior (the §7 #18→#27 history is 6 verdict flips on the NLI side);
§3.2.2 step 2 (real-traffic shadow sweep on pooled bench-qa STRICT) is
what sets it. Expect a walk-back. Reranker still doesn't catch the
Kilimanjaro/Mount-Kenya recombination (aboutness ≠ truth-of-attribution;
that's #000049 territory). fox's bench-maxing correction applied.
2026-05-13 09:57:26 -04:00
9532c47f0e
#000052 §3.2: SHADOW SCAFFOLD landed — arborist/qa/relevance/ mirrors arborist/qa/nli/; primary cross-encoder MS-MARCO-MiniLM-L-6-v2; Zionist-entity field case discriminated (+9.96 vs -9.04, 18-pt margin)
arborist/qa/relevance/ — manifest pins cross-encoder/ms-marco-MiniLM-L-6-v2
(~80MB, Apache) as primary; alternates: L-12, BAAI/bge-reranker-base,
ms-marco-electra-base. demote_below_score=null on purpose — the
#000049 §7 #18→#27 discipline (proved 6× that clean-eval thresholds
don't transfer to bench-qa data) requires the threshold to be set by a
shadow sweep against pooled real STRICT, not by a literature number.
ShadowRelevance class mirrors ShadowNLI (lazy [nli]-extra import, cuda
auto-detect via ARBORIST_RELEVANCE_DEVICE or ARBORIST_NLI_DEVICE,
batched _score_batch, graceful degrade-to-available=False). Two surface
methods: check_question_answer (deflection / Q-A drift) and
check_claim_source (topic-collision mis-cite). 13 tests.

Sanity on the motivating field case (Zionist entity): ON-topic +9.96
vs OFF-topic -9.04 → 18-pt margin. Mona Lisa Q→A deflection: on +10.45
vs deflect +3.56 → ~7-pt margin. The model CLEANLY discriminates the
failure modes #000052 §1 named. It does NOT catch the
recombination-where-the-different-entity-clause-also-mentions-the-target
case (Kilimanjaro/Mount Kenya) — and that's the right architectural
split: aboutness (#000052 §3.2) and entailment (#000049 NLI) are
orthogonal axes; the Kilimanjaro recombination case needs the semantic
candidate selector (#000050/#000051 vec hybrid).

Remaining: build candidate-bench eval (~20-30 deflection + mis-cite
fixtures), shadow-sweep θ over pooled bench-qa STRICT (expect another
walk-back per the #000049 lesson), recall-side realism check, then
fox+dav1d sign-off. Still SHADOW; production verifier unchanged.
2026-05-13 09:46:37 -04:00
658f269d2f
docs: bump warrant-substrate-cookbook AUTOCOUNT 20 -> 28 for #000054 tests
test_concepts_extract.py grew 20 -> 28 with the acronym_parens
extractor's 8 tests; the AUTOCOUNT discipline (CLAUDE.md) fires the
doc-counts regression on stale numeric claims.
2026-05-13 07:01:02 -04:00
58027e9760
#000054: acronym-parens concept extractor (closes abbreviation→expansion retrieval gap)
`arborist/concepts/extract.py:acronym_parens_synonym` — new
corpus-agnostic extractor. Scans each doc's lead chunk (first 4000
chars) for `<Multi-Word Phrase> (ACRO)` where the all-caps acronym's
letters strictly match the content-word initials of the phrase, in
order, after function-word filtering. Emits bidirectional synonym
edges between the lowercased acronym and each ≥3-char content token
of the phrase, evidence_kind="acronym_parens", anchored to that doc's
document_root. Idempotent like link_reciprocity_synonym.

Why this complements link_reciprocity: Wikipedia represents
abbreviation→expansion as a one-way *redirect* (CPU →
Central processing unit), which the ingest does not record as an
edge — so the existing reciprocal-link extractor never learned the
relation. The relation IS in body text by near-universal convention
("Central processing unit (CPU) is..."), which this extractor reads.
Corpus-agnostic: HTML, blogs, textbooks benefit equally.

Conservative: strict 1:1 acronym-to-atom match (rejects HTTP-shape,
where letters land mid-word), function words filtered, repeated
definitions deduped per doc, ≥3-char target floor. 8 new tests
covering CPU bidirectional emit, RAM idempotency, FBI function-word
filter, HTTP length-mismatch reject, XYZ initial-mismatch reject,
ROM hyphenated-word handling, per-doc dedupe, registry presence.

Retrieval-side only — synonym edges reshape FTS5 candidate selection
via synonym_expand at query time, never enter audit_mode / cache_key
/ audit_event_hash. No governance hash bump, no cache invalidation.

Closes #000050 §2a's CPU/GPU abbreviation rows *upstream* of vec;
the Orwell-shape conceptual-allusion row remains the genuine #000050
justification. Operational follow-up (not code): run on each shard
via `arborist concepts derive --extractor acronym_parens` (CLI
surface itself is aspirational in docstrings; extractors are called
programmatically today). Next ID 000054 -> 000055.
2026-05-13 07:00:25 -04:00
4352b84508
#000049 §7 #27: recall-side realism check — synthetic 28/28 was a 4x over-estimate; bart-large-mnli/k=12/max/θc=0.999 is the new fp=0 leader on real haystacks at 0.48 recall (vs §7 #26's claimed 28/28 → 0.24 on real)
Built bench/fixtures/5f/recombination-realcontext-v1.jsonl: 25 hand-built
recombination claims (deliberate re-attributions within real bench-qa
30 KB Wikipedia haystacks the pipeline produced — Mount Kenya into a
Kilimanjaro answer, Galileo onto all 63 Jupiter moons, Joshua Reynolds
onto the Mona Lisa, etc.). Ran the full 7-model × full-grid sweep vs
the 808 pooled STRICT. Result:

- bart-large-mnli / k=12 / max / θc=0.999 → 12/25 = 0.48 catch · 0/808 FP
  (the real-haystack fp=0 leader)
- deberta-large-mnli / k=3 / margin / θc=0.995 → 6/25 = 0.24 (§7 #26's
  'settled' config — 28/28 synthetic, 0.24 real-haystack: 4× over-estimate)
- roberta-large 0.12, MiniLM 0.08, deberta-base 0.04

So §7 #26's 'boundary closed' walks back to 'boundary PARTIALLY closed'
on real haystacks. The bottleneck is architectural: top-k by token
overlap misses the contradicting clause when it shares few subject-area
tokens with the answer (e.g. the Mount Kenya clause only shares 'Kenya'
with a Kilimanjaro claim — ranked low, NLI never sees it). Threshold
tuning doesn't lift the ceiling; a SEMANTIC candidate selector
(vec-driven, sibling of #000050/#000051's hybrid retrieval) does.

bart's pareto above fp=0: fp=0.011 catch=0.52, fp=0.057 catch=0.84,
fp=0.068 catch=0.92 — permissive operating points are on the menu if
fox+dav1d sign off. recommended_operating_point updated to
bart-large-mnli/k=12/max/θc=0.999; deberta-large/margin kept as the
synthetic-eval reference. Sixth meta-lesson instance: clean synthetic
eval doesn't predict bench-qa precision OR recall — neither contrived
dataset axis is load-bearing, only the real pipeline shape is.

Production verifier unchanged; falsification-hard stays 10/12. Still
SHADOW; runtime promotion fox+dav1d-decides.
2026-05-13 06:35:36 -04:00
d57e5c1435
#000049 §7 #26: mining for real recombinations + the pooled-808-STRICT check — verdict settles on margin@0.995
(a) Mined the pooled n=1+3+5 bench-qa runs (808 distinct STRICT answers)
for natural recombinations at lowered θc≥0.7 → 37 would-fires, ALL
token-collision FPs on inspection (Mount Kenya pulled into a Kilimanjaro
answer, Dalí into da Vinci, Donovan into Superman). ZERO genuine
recombination errors — the boundary is theoretical-in-practice; the
failure mode is the candidate selector (top-k by token overlap) pulling
different-entity same-subject-area clauses.

(b) Re-ran the grid against the 808-cell pooled STRICT set: the §7 #25
'max@0.96' was itself a small-sample artifact — the n=5 444-cell set
lacked the high-confidence spurious hits the pooled set has. On 808
cells θc goes back to ~0.995, and at θc=0.995 only agg=margin still
catches 28/28 (max gets 27/28). microsoft/deberta-large-mnli / k=3 /
agg=margin / θc=0.995 → 28/28 synthetic recombinations · 0/808 pooled
real STRICT FP · 0/26 synthetic legit — the ONLY config in the
7-model×full-grid sweep that hits 1.0/0.0 on 808 cells, held at n=3
too. recommended_operating_point reverted to margin@0.995.

Realistic next check: ~20-30 hand-built synthetic-recombination-vs-
real-bench-qa-context fixtures (real haystack, deliberate re-attribution).
Still SHADOW; runtime promotion fox+dav1d-decides. Production verifier
unchanged; falsification-hard stays 10/12.

Meta-lesson instance five: a bigger sample can vindicate a config a
smaller one made look unnecessary — re-confirm the config choice (not
just the threshold) each time the denominator grows.
2026-05-12 21:11:35 -04:00
4ec97bdfaf
#000050: add §2a — semantic-allusion fixture set (tracked cases)
Enumerates the concrete query-words-share-zero-tokens-with-target-title
cases the §2 gate's "semantic-allusion fixtures" must include, as a
running list: Orwell→Eastasia (genuine conceptual allusion — the case
that justifies the vec layer), "what is a CPU?"→Central processing
unit, "what is a GPU?"→Graphics processing unit (abbreviation→expansion
subclass — also fixable upstream by a concepts/ synonym edge; bench
records which fix closes each row). Field cases 2026-05-13, fox.
#000053 fixed the verifier's separate acronym blind spot but not this
retrieval gap.
2026-05-12 21:03:35 -04:00
d9760bc5bb
#000049 §7 #25: n=5 confirmation (444 STRICT cells) — verdict settles; the large models are the robust ones, MiniLM-cost-pick overturned
ARBORIST_NLI_SHADOW=1 make bench-qa BENCH_QA_N=5 → 1125 cells, 444 real
STRICT (5x n=1, 1.6x n=3). Re-ran the 7-model mega-grid: the lexical-
candidate NLI veto robustly clears the §7 #12 gate with
microsoft/deberta-large-mnli / k=2 / agg=max / guard=max_entail /
θc≈0.96 / θe=0.9 → 28/28 synthetic recombinations (incl. both fixtures)
· 0/444 real STRICT FP · 0/26 synthetic legit FP, ~4 pts θc headroom;
roberta-large-mnli equally good (k=2/max/θc=0.95). Resolved: agg=max +
max_entail guard is the robust score-shape (§7 #24's margin win was a
sample tie); the large checkpoints (~350-400M deberta-large-mnli /
roberta-large-mnli) hit 1.0/0.0, bart-large (similar size) only ~0.71,
deberta-base at the cliff (27/28 here, 11/28 at n=3), small models
(MiniLM-82M, deberta-v3-small) cap at ~0.82 — so §7 #18's 'MiniLM is
the cost-pick' is OVERTURNED by the proper-n evidence; k=2 consistent
winner; int8-ONNX costs ~1 catch. recommended_operating_point updated.
Remaining: a bench-qa-derived recombination set (the one check not
done); n=9 if dav1d wants more; still SHADOW; runtime promotion is
fox+dav1d-decides. Production verifier unchanged; falsification-hard
stays 10/12. This run is the worked example behind CLAUDE.md's new
bench-maxing line.
2026-05-12 19:42:55 -04:00
221b784a80
#000053: acronym-aware verifier content tokens
`arborist.qa.evidence._content_tokens` dropped every token under 4
chars, so a short all-caps acronym (CPU, GPU, DNA, FBI, USB…) never
registered as a content token — which defeated Rule 8
(_claim_title_overlap / TITLE_MISMATCH), the subject-tokens-absent
check (Rule 9), the bare-name-claim guard, and spotlight-excerpt token
selection whenever a question/claim's topic IS an acronym. The field
case: `what is a CPU?` cited to the "CPU design" article tripped
TITLE_MISMATCH even though claim and title both contain "CPU".

Fix: keep a token if it's an all-caps 2-3-char alpha run in the source
text; everything else unchanged. The change only ever ADDS tokens, so
TITLE_MISMATCH / SUBJECT_TOKENS_ABSENT / BARE_NAME_CLAIM can only stop
firing, never start — monotone toward fewer spurious demotes; no
STRICT→non-STRICT transition is possible from it.

Versioned: `content_token_rules: "v2-acronym-aware"` added to
runner.DEFAULT_POLICY + query.DEFAULT_QUERY_POLICY +
keys._VERIFIER_POLICY_FIELDS → folds into verifier_policy_hash, prior
cache records orphan on lookup (by design; same discipline as
base_version / hyphen_fold_v1). Does NOT touch the retrieval
abbreviation→expansion gap (CPU→Central processing unit — #000050 vec
hybrid / concepts/ synonym edges; the root cause of the satellite
retrieval). 8 new tests; full suite green (2502); bench-qa-smoke clean.
Next ID 000053 -> 000054.
2026-05-12 19:41:47 -04:00
824b1bc21c
#000049 §7 #24: n=3 confirmation — §7 #23 was a small-FP-sample artifact; the no-stone-unturned mega-grid found the config that survives
ARBORIST_NLI_SHADOW=1 make bench-qa BENCH_QA_N=3 → 275 real STRICT cells
(3x the n=1 sample). Re-ran the expanded grid (7 aggregations incl.
margin = max_clause(p_contra - p_entail), paired-entail guard variant,
θc to 0.999, --extra-models) over all manifest models + 4 extra
xsmall→large (microsoft/deberta-large-mnli, roberta-large-mnli,
nli-deberta-v3-small, deberta-v3-xsmall), synth-28 recombination vs the
275 STRICT cells. Result: the §7 #23 deberta-base/k=2/θc=0.99 config
does NOT survive — it catches only 11/28 at θc=0.995 (which the larger
STRICT sample forces). BUT the broader sweep found the config that does:
microsoft/deberta-large-mnli / k=3 / agg=margin / θc=0.995 → 28/28
synthetic recombinations (incl. both fixtures) + 8/12 falsification-hard,
0/275 real STRICT FP, 0/26 synthetic legit FP — a passing config at
proper n. Findings: margin is the right score-shape (single threshold,
folds the guard in); the specific checkpoint matters more than param
count (deberta-large-mnli wins clean, deberta-base collapses,
roberta/bart ~0.71-0.75 — no 'bigger is better' law). recommended_operating_point
updated. Still SHADOW; runtime promotion needs a bigger STRICT sample +
a bigger recombination set + fox/dav1d sign-off. Production verifier
unchanged; falsification-hard stays 10/12.

Meta-lesson sharpened twice: clean eval ≠ bench-qa precision (§7 #18→#20),
default config ≠ best config (§7 #22→#23), small FP sample ≠ large FP
rate (§7 #23→#24).
2026-05-12 18:38:43 -04:00