ViskaRes · Audit of Data Deliverables

Daily Signal Engine & Reviewer Pipeline

Full audit of the August 2026 corpus: parcel consistency across both layouts, signal-graph engine correctness, contract conformance, and the state of every deliverable the downstream consumers read.

2026-08-24T20:15Zcorpus 2,704 parcels August batches 22main @ 129939c1
PASS

The engine is correct and the corpus is consistent. The three-region conversion moves no payload: six August days re-emitted from the converted corpus are byte-identical in nodes, edges and counts. All 2,704 parcels pass conformance across both layouts, and all 1,191 reviewed parcels read identically through every reader class. Downstream payloads are present, digest-consistent and internally agreeing.

Seven defects found, all bounded. One was fixed and mutation-proven during this audit; the rest are reported with owners rather than silently patched. None blocks the daily run.

Scorecard

2704/2704
parcels conformant
both layouts
1191/1191
reader-equivalent
zero disagreements
6/6
days byte-identical
on re-emit
71/71
quotes in document
batch 08-23
471/471
cites resolve
batch 08-23
2/35
documents unread
batch 08-23

1 · Corpus consistency — August

The corpus holds two parcel layouts at once. That is the intended migration state, and the audit's first job was to prove the split is clean rather than assume it.

LaneTotalThree-regionOld-shapeConformance
broker2,5521,1911,3612552 / 0 failed
substack1220122conformant
internal30030conformant

The 1,191 converted parcels are exactly the 1,191 reviewed parcels; the 1,361 old-shape are exactly the unreviewed. The layout boundary and the review boundary are the same boundary — there is no parcel that is reviewed but unconverted, or converted but unreviewed.

Reader equivalence

Every converted parcel was read through the independent reader classes and compared on findings, sources, review_run, contract_version and review_state:

converted parcels checked: 1191 reader disagreements: 0 converted parcels where parcel_writer.read() sees NO findings key: 0

This is the property that failed before the read-half fix landed — a converted parcel reported findings ABSENT, and absent is how OKF encodes "never reviewed". It now holds corpus-wide.

2 · The step function nobody should read as decay

Aggregate source-anchoring across the reviewed corpus is 27.3%. Read as a quality metric that looks alarming. It is not a quality metric — it is two contract regimes averaged together.

SOURCES CARRYING A VERIFIABLE ANCHOR — % BY BATCH DAY
08-01
08-02
08-03
08-04
08-05
08-06
08-07
08-09
08-10
08-11
08-12
08-13
08-14
08-15
08-16
08-17
08-18
08-19
08-20
08-21
08-22
08-23
pre-v2.3 — 0% anchored (9,845 sources, key absent by contract) v2.3+ — 100% anchored (3,702 sources)

Every day before 2026-08-13 is 0%. Every day from 08-13 is 100%. There is no partial day and no decay: the anchor key was introduced by contract v2.3 and adopted completely on the first batch that ran under it. The two source shapes in the corpus are exactly (id, resource, title) ×9,845 and (anchor, id, resource, title) ×3,702 — no third shape, no half-populated records.

Reporting the 27.3% aggregate without this decomposition would describe a clean contract migration as a two-thirds grounding failure. The mean of a step function is not a measurement of anything.

The same shape appears in findings density

Findings-per-document drops from ~26 to ~4.2 at the v2.4 → v3.5/3.6 boundary. This is the signal-or-nothing contract change working as designed — a no-signal document now earns the index layer only and is a complete record — not reviewers doing less work.

Regimecontractdocsfindings/docquotes/docreading
08-01 → 08-07pre-2.244225.940.60quotes key arrives mid-band (08-07)
08-09 → 08-142.2 – 2.433815.112.05quotes + anchors arrive
08-15 → 08-233.5 – 3.83664.242.23signal-or-nothing

3 · Signal-graph engine correctness

The load-bearing question: does the parcel conversion change what the engine produces? Answered by re-emitting real August days from the converted corpus and comparing section by section against what shipped.

Batchnodesedgescountsedges on disk / re-emit
2026-08-17identicalidenticalidentical59 / 59
2026-08-19identicalidenticalidentical37 / 37
2026-08-20identicalidenticalidentical26 / 26
2026-08-21identicalidenticalidentical79 / 79
2026-08-22identicalidenticalidentical20 / 20
2026-08-23identicalidenticalidentical28 / 28

Compared as canonicalized JSON, section by section — nodes, edges, counts, axes, layout, quadrants, vendorable all hash equal. The conversion moves no payload.

A digest difference that is not a payload difference

The content_digest does differ between shipped and re-emitted payloads. Three causes, all provenance, none content:

This is the one place in the audit where a naive check produces a false alarm. A digest comparison alone would have reported the conversion as corrupting six days of shipped payloads. Section-level comparison shows the opposite.

4 · Findings

F1 · A gate counted a failure it could not name — fixed & mutation-proven

verify_grounding.py:463 · RES · fixed this session, commit 23b7ec14

thesis_uncited is a member of GATE_KEYS and is set by check_parcel, but the failure-reporting block had no print branch for it. A parcel failing on that property alone was counted in "N parcels FAIL the gate" and then named nothing — every property line above it reading ok.

BEFORE quotes 71/71 ok · sources 216/216 ok · cites 471/471 ok "1 parcels FAIL the gate in batch 2026-08-23:" (empty body — no parcel, no property, no remedy) AFTER sha1:63703215a294deb059e9.md THESIS UNCITED no citation marks

Mutation-proven in both directions on the live batch: with the fix deleted the silent failure returns; restored, the parcel is named. Reporting only — no gate semantics changed, no parcel edited, self-check PASS.

F2 · Batch 08-23 shipped with two documents unread

check_batch_coverage.py · corpus 35, reviewed 33 · owner: N8N (S2 reader loop)

The only coverage hole in August. Every other measurable day is complete (08-16 13/13, 08-17 68/68, 08-18 55/55, 08-19 80/80).

sha1:5043eed6e9d7c490c3f1 unread 'MS - Our Views After Treasury Announced Larger Buybacks.pdf' 19pp sha1:a8feebd4b2cfe3102d57 unread 'Bessent's Bailout Brings Big Week For Bonds…' 21pp

The graph for 08-23 was therefore built from 31 of 35 available documents. Additive by construction, so re-reading these two only adds — no rebuild of prior days is implied.

F3 · 160 tracked events state a date sharper than their declared precision

check_contract.py · batches 08-15 → 08-23 · owner: N8N (S2 reviewer contract)

The dominant live-contract violation class by an order of magnitude, and the contract is explicit that a date must be neither sharpened nor blurred from what the document gave.

expected_at '2026-11-15' vs declared precision 'quarter' expected_at '2026-12-31' vs declared precision 'quarter' expected_at 'next Wednesday' vs declared precision 'day' expected_at 'September' vs declared precision 'month' ← blurred, not sharpened

Both directions appear, so this is not a single formatting habit — the reviewer is filling expected_at and date_precision independently rather than deriving one from the other.

F4 · 38 parcels carry empty or non-string entities

check_contract.py · concentrated in batch 08-17 · owner: N8N (S2)

Entity lists containing empty or non-string members — up to 13 in a single parcel. Contained to one batch band, which suggests a single reader run rather than a standing contract gap.

F5 · Two findings carry classes outside the closed nine

sha1:cf8a8b53… (regime) · sha1:f392e3d2… (eureka) · both batch 08-13, contract v2.3

Both are legacy v2.3 records. The gate catches them correctly — this is not a gate hole, it is unrepaired history. eureka is a legitimate top-level synthesis key, which is likely how it migrated into a finding's class slot.

Two records out of 18,126 August findings. Repair is a two-record edit, not an arc.

F6 · The schema file declares v3.6; the shipped contract is v3.8

research/analysis/CONTRACT-v2.md:3 vs docs/contracts/hrafn-reviewer-profile.md

The live contract hashes to the approved v3.8 sha, so leg 2b passes and the daily run is unaffected. But verified_run.py — the operator's one-verified-run proof — reads the stale string and reports link 2 as NO on a batch where the reviewer correctly held v3.8.

contract declares version: 3.6 (CONTRACT-v2.md) parcel carries: 3.8 (written by the reader) match: NO ← false negative; the parcel is right, the schema file is stale

Severity per existing ruling, not re-derived: N8N-SIGNAL-GRAPH-PROTOCOL.md:547 already rules this low — CONTRACT-v2's header is an artifact of the retired ledger lane, declared_version() lives only in the manual proof tool and reaches no daily run. Flagged here because that manual tool is precisely what the operator reads to approve a batch, so the false negative lands in front of a human.

F7 · The gate that retires daily.yml has never been run

_handoff/2026-08-21_…-signal-graph-protocol-to-n8n.md:46 · owner: unassigned

daily.yml is still on origin/main, now workflow_dispatch: only — no schedule: or cron: anywhere in the file. It is kept deliberately, not forgotten: the handoff that hands the pipeline to n8n makes its removal conditional.

"Byte-parity with `daily.yml` is the acceptance test." N8N 2026-08-23 23:20Z "I have no record of that comparison being run." RES 2026-08-24 00:05Z "I hold no such record, and I am not claiming one."

RES's stated condition for closing it was that the first unattended n8n run happen first. That run fired and landed today3a316f51, batch 08-23, automated bare emit, 11:45Z. The precondition is now met, and running the comparison is assigned to no one.

5 · Deliverable inventory

What actually exists on disk, per August day, against what the pipeline contract describes.

Deliverabledays presentstatereader
graph-<batch>.json22 / 22completeFE, DB, STRAT
conviction-payload.json17 / 22gapsSTRAT
plot-payload.json6 / 22stops 08-06FE
daily-<batch>.json2 / 2208-07, 08-10 onlyFE / Slack
DAILY-CLOSE-<batch>.md0 / 22none in repoleg 1 arbiter

The DAILY-CLOSE absence was checked with a positive control — find resolves other names in the same tree, so the search could see. Zero files exist repo-wide under that name, and check_folder_complete.py names it as a leg-1 requirement. These are seat-only legs that read the local Dropbox corpus, so a gap here does not necessarily mean the day failed — but it does mean the artifact the contract names as the close is not in the repo for any August day.

Index and manifest agree with disk

disk graph days 23 index count 21 manifest vendorable 21 + withdrawn 30 on disk not in index 2026-08-01, 2026-08-09 ← both hold days, correctly excluded index vs file digest disagreements none

The two excluded days are the insufficient_corpus holds, which the engine marks vendorable: false with a stated reason rather than shipping an unexplained empty graph. Correct behaviour. One nit: the manifest header still declares payload_schema: viska.signal-graph/1.0 while its contents are 1.1 and 1.4.

6 · Reviewer pipeline

Gatebatch 08-23note
quotes in document71 / 71byte-exact against source, no model in the loop
sources anchored216 / 216every anchor a verifiable span
cites resolve471 / 471each names a declared source
values in body186 / 186flag tier, never a gate
review substance33 / 33every reviewed parcel carries substance
narratives supported73 / 95flag — no finding-to-narrative edge exists to satisfy
thesis uncited1 parcelnow named — see F1

The A1 anchor halt is substantially resolved: the class-B elision trims landed, and 08-23 now carries zero unanchored sources and zero missing quotes. The remaining gate failure is the single uncited thesis.

Two open A1 classes

Reviewer model spelling drift

August reviews name 16 distinct model strings for roughly 8 actual models — sonnet-5 beside claude-sonnet-5, mimo-v2.5 beside xiaomi-mimo-v2.5, four spellings of Haiku 4.5. The 33 OpenRouter provider-prefix records were repaired this cycle; the remaining variance is reviewer-side spelling, and it makes any per-model quality comparison unreliable until normalized.

7 · What was verified, and how

Claimtiermethod
2,704 parcels conformant, both layoutslive-verifiedparcel_conformance.py over all three lanes
Conversion moves no payloadlive-verified6 days re-emitted, section-level JSON hash comparison
1,191 parcels reader-equivalentlive-verifiedevery converted parcel through each reader class
Anchor step function at 08-13live-verifiedper-day anchored/bare census over reviewed corpus
F1 gate fix worksmutation-provenreal → names parcel; fix deleted → silent
No DAILY-CLOSE artifact existslive-verifiedfind repo-wide + positive control
F6 severity is lowfile-sourcedcites existing ruling rather than re-deriving
What this audit does not establish. It proves the machinery is correct and the corpus is consistent — not that the findings are right. Whether a reviewer read a document well is outside every gate here; these check that quotes exist, cites resolve, anchors are real spans and the engine is deterministic. Coverage for five August days could not be measured because those legs read a local Dropbox corpus not present on this seat; they are reported as unmeasured, not as passing.

8 · Recommended order