← Corpus / augment-it / plan
First-Pass Corpus Quality Scan for reach-edu — a measured before/after baseline of the RAG corpus
Before wiring RAG/grounding over the reach-edu corpus, take a read-only baseline of what's actually there — 517 markdown files across 57 funder dirs (140 still in inbox). A fresh Claude Code session inventories, scores, and reports corpus quality so 'after' is comparable to 'before.' Diagnostic only — it changes nothing.
- Path
- plans/First-Pass-Corpus-Quality-Scan-for-reach-edu.md
- Authors
- Michael Staton
- Augmented with
- Claude Code on Claude Opus 4.8 (1M context)
- Tags
- Plan · Augment-It · Corpus · RAG · Quality-Baseline · reach-edu · Diagnostic · Before-After
First-Pass Corpus Quality Scan for reach-edu
For the executing Claude Code session: this is a read-only diagnostic. Do NOT edit corpus files, write to SurrealDB, fetch URLs, or build the RAG index. Your only output is a baseline report written under
clients/reach-edu/corpus-quality/. The point is to measure quality now so the same scan re-run after the corpus + RAG work shows the delta.
Why this plan exists
The reach-edu corpus is about to become the grounding source for two things: the funder-fit RAG/KAG cycle and the reach-edu deck (slides grounded in cited evidence). Before investing in retrieval and grounding, the operator wants to see corpus quality before and after — a measured baseline, not a vibe. This session produces that baseline: an honest, quantified picture of what the 517 files actually are, where the gaps and junk live, and a per-funder quality read — written so it can be re-run later and diffed.
Read these three explorations first for the why and the quality dimensions (they define the model this scan measures against):
context-v/explorations/Funder-Fit-Engine-Org-Corpora-and-the-Story-Unlock-Cycle.md— Problem A (filesystem↔DB convergence/sync, the Venn), Problem B (corpus-class: publisher/thin/private/noise), first-party vs third-party.context-v/explorations/Best-Way-to-RAG-Over-the-Corpus.md— what retrieval needs from the corpus (metadata facets, chunk identity, freshness).context-v/explorations/The-Moat-Is-Grounded-Deliverable-Production-Not-Chat.md— the corpus grounds the deck; citations must trace back to source, so citation-readiness is a quality metric.
What’s there right now (validated 2026-06-18 — confirm, don’t trust)
- Path:
clients/reach-edu/corpus/— 58 dirs (57 funder/org slugs +inbox/), 517.mdfiles. inbox/holds 140 files — the single largest bucket, and likely holds more research than any funder dir (unfiled, not lesser). There’s some junk (*_access-denied.md), but treat it as a primary content source, not a cleanup queue.- Heaviest funders: arthur-blank-foundation (22), jff (15), upmobility-foundation-urban-institute (14), arnold-ventures (14), annie-e-casey (14), stand-together-trust (13), charles-koch-foundation (12), walton-family-foundation (11).
- Per-file frontmatter (varies):
title,exact_url,fetched_at,published_at(present on some, not all),record_id,record_uuid,response_id,client_id,funder_slug,pack_id,tags,extra_metadata.{jina_status, content_length_bytes}. Noorg_slug/ SurrealDB link yet (the convergence gap). - ~5 files with
jina_status != 200(failed fetches). - The pipeline funder list is
clients/reach-edu/inputs/2026-06-10_Master-Pipeline-Tracker--Active-Pipeline_v10.csv(~100 funders) — the coverage denominator.
Scope
In: read-only scan of clients/reach-edu/corpus/**; cross-reference the inputs CSV for coverage; produce a baseline report + machine-diffable metrics.
Out (do none of these): editing/deleting/moving corpus files; writing to SurrealDB; fetching any URL; building embeddings or a vector index; triaging the inbox; the reconcile pass. Those are later plans — this one only measures and recommends.
The metrics to compute (define them now so before/after diffs cleanly)
Compute these by parsing frontmatter + bodies with a script (node/python/bash — your choice; read-only). Report each overall and per-funder-dir. Treat inbox/ as a first-class content bucket, not a sidecar — it’s the largest single pile and probably the richest (see metric 9); give it the same scrutiny as the richest funder.
- Inventory — file count, total content bytes,
fetched_atandpublished_atdate ranges. - Metadata completeness — % of files with each of:
exact_url,published_at,record_uuid, non-emptytags,jina_status == "200",content_length_bytes. - Citation-readiness — % of files that could emit a
reach-edu-hubSources.astroCitation(needs at minimumtitle+exact_url; bonuspublished_atfor the date). This is the moat metric — ungrounded files can’t be cited in the deck. - Coverage / the Venn — of the ~100 funders in the inputs CSV, how many have a corpus dir, how many have none; which corpus dirs have no matching CSV funder (orphans). (Read-only report of the Venn; do not reconcile.)
- Depth + corpus-class pre-score — per funder, suggest
publisher | thin | private | noisefrom signals: file count, total content length, recency, presence of a datable stream. Suggestion only — flag it as needing operator confirmation (web-research isn’t auto-accept; the operator drives classification). - Freshness —
published_atdistribution; share older than 12/24 months; share with no date at all. - First-party vs third-party — derive each file’s
exact_urldomain; compare to the funder’s own domain (best-effort). Report the first-party / third-party / unknown split. (Both matter — third-party is not second-class — but the mix is a quality signal.) - Junk / integrity — count:
jina_status != 200; near-empty bodies (e.g. body < ~500 chars after frontmatter); likely duplicates (sameexact_urlacross ≥2 files); PDFs stored as binaries with thin extracted text (binary_assetpresent + tiny body). - Inbox as a primary research store (NOT just “debt”) —
inbox/(140 files) is the largest bucket and likely holds more research than any funder dir — unfiled, not lesser. Assess it on equal footing: run metrics 1–8 over it, AND profile what it covers — the topics / entities / funders its files relate to (from titles,exact_urldomains, body skim) — so we know what it could ground and where it might later be attributed. Separately count the genuine junk subset (access-denied / error / near-empty). The deliverable here is “here’s the research sitting in inbox and what it’s about,” not “here’s a cleanup queue.” - Qualitative substance sample — actually read a small sample (≈2–3 files from each of the top ~10 funders, a generous sample from
inbox/since it’s the biggest and likely richest bucket, plus a random tail sample). For each, judge: is this substantive (real priorities/strategy/grants/research) or noise (nav boilerplate, generic PR, cookie/consent text, washed marketing)? Summarize the substantive-vs-noise read per bucket. This is the human-judgment layer the numbers can’t capture.
Output (what to write)
Write to a visible folder (not dot-prefixed): clients/reach-edu/corpus-quality/.
clients/reach-edu/corpus-quality/2026-06-18_baseline.md— the human-readable report:- One-paragraph headline verdict (is this corpus RAG-ready, mostly-ready, or needs cleanup first?).
- Overall metrics table.
- Per-funder table (the metrics above, one row per funder).
- The Venn (covered / uncovered funders / orphan dirs).
- Top integrity issues, with example file paths.
- The qualitative substance read.
- Recommended fixes before RAG — ordered, each tagged to a later plan (reconcile/convergence, inbox triage, dedup, thin-org third-party sourcing, metadata backfill). Do not perform them.
clients/reach-edu/corpus-quality/2026-06-18_metrics.json(or.csv) — the same numbers, machine-readable, so a future re-run diffs numerically. Include agenerated_atand acorpus_file_countso drift is visible.
Keep the report honest and specific (name the worst offenders by path). Length is not a factor — enough to convince + enough to act on.
The before/after discipline (the operator’s actual ask)
This baseline is “before.” Define “after” as: re-run this exact scan after the corpus cleanup + RAG grounding lands. To make that trivial:
- Put the metric-computation in a small committed script (e.g.
scripts/scan-corpus-quality.mjs) so “after” is one command, not a re-derivation. - The script writes a new dated report + metrics file into
corpus-quality/; comparison is a diff of two*_metrics.json. - Headline deltas to watch later: citation-readiness %, metadata-completeness %, junk count, inbox research surfaced/attributed (not “inbox emptied” — the goal is using it, not clearing it), publisher-class coverage of the active pipeline.
(Corpus quality is the input baseline. A complementary “after” measure — retrieval quality — belongs to the RAG build itself: a small JSONL of operator-curated query→expected-source pairs, per Best-Way-to-RAG-Over-the-Corpus.md §eval. Note it as a forward pointer; it’s not in this plan’s scope.)
Suggested session flow
- Read the three explorations above (context for the quality model).
- Confirm the validated numbers (file/dir/inbox counts) against the live tree.
- Write
scripts/scan-corpus-quality.mjs(read-only) computing metrics 1–9; run it. - Do metric 10 (qualitative sampling) by hand — read real files, write the substance read.
- Assemble the baseline report + metrics file under
corpus-quality/. - End with the ordered “recommended fixes before RAG,” each pointing at the plan that should do it. Stop — do not execute fixes.
Open questions (surface in the report; don’t decide unilaterally)
- corpus-class thresholds (what file-count / recency makes a funder “publisher” vs “thin”?). Pre-score with a stated heuristic; let the operator tune.
inbox/is in-scope and likely the single richest source — the question isn’t whether to include it but how to attribute/surface its research (it spans many funders/topics, unfiled). Report what it covers so attribution can happen later; never treat it as junk-by-default.- First-party domain detection is heuristic (a funder’s own domain may differ from its slug). Report confidence; don’t overstate.
See also
context-v/explorations/Funder-Fit-Engine-Org-Corpora-and-the-Story-Unlock-Cycle.md— the quality model (Venn, corpus-class, first/third-party, the filesystem↔DB convergence this scan measures but does not fix).context-v/explorations/Best-Way-to-RAG-Over-the-Corpus.md— what retrieval needs; the retrieval-quality eval that complements this corpus-quality baseline.context-v/explorations/The-Moat-Is-Grounded-Deliverable-Production-Not-Chat.md— why citation-readiness is a first-class corpus metric (the deck cites the corpus).context-v/plans/Download-PDFs-into-Corpus-Inbox.md— the inbox/binary-asset shape the scan will encounter.clients/reach-edu/corpus/— the target.clients/reach-edu/inputs/2026-06-10_Master-Pipeline-Tracker--Active-Pipeline_v10.csv— the coverage denominator.