- name
- lore-ingest
- description
- Grade a quarantined lore piece and promote it into canon — Rhea pass sends it to BOTH NotebookLM and bay-tribune, a fail sends it to the local rejection log and nowhere else. The gate half of pipeline.59; the generation half is /lore-writer.
- version
- 1.0
- updated
- 2026-08-20T00:00:00.000Z
- tags
- ["canon","lore","notebooklm","supermemory","active"]
- effort
- medium
- disable-model-invocation
- true
# lore-ingest — Promote or Reject a Quarantined Lore Piece
## What this is
The gate between `output/lore-quarantine/` and canon. `scripts/loreWriter.js` (pipeline.56) generates; this grades and branches. Nothing sits ungoverned on disk once graded — a piece either enters both canon stores or lands in the rejection log.
**Grading is never delegated to agy — Rhea/Claude only.** `scripts/loreIngest.js` does not grade at all: it takes a verdict you produce here and executes the mechanical branch. That split is the guardrail, so no lower-tier model can decide what enters canon (`docs/MODEL_HIERARCHY.md` §4, goal-substitution risk).
## Steps
1. **Read the piece.** Every named person, place, org, and number is a claim.
2. **Verify the claims against the ledger** — `mcp__godworld__lookup_citizen` / `queryLedger.js citizen <POPID>` for people, `lookup_business` / `lookup_cultural` / `search_canon` for the rest. Texture (weather, mood, dialogue, scenes) is invented freely and is not a claim. The test for any sentence: could a ledger query contradict it? If yes, it must be verified.
3. **Run the Rhea gate** — the `rhea-morgan` agent, same as an edition. Fail conditions: an invented family member, career, or household; a citizen rendered as someone the ledger contradicts; a cycle reference that puts an event where the ledger does not.
- **Ledger numbers in lore are facts to verify, never a fail on their own** (builder ruling 2026-09-06, S429 — reverses the S420 "fail on sight" rule). Citizens are open-book: lore's job is to start the ledger's facts into canon and tell the story on top of them. Income, net worth, years in a career, household/lineage ids, a wealth band — check each against the ledger; a match passes, a mismatch fails. The `feedback_canon-is-color-not-data-echo` rule is a NEWS rule (an article restating an engine number is a data echo); it does not govern lore. What still fails: a number the ledger contradicts, an invented person/career/household, malformed cycle math.
- **Engine/system words and IDs are NOT contamination (builder ruling 2026-09-20, S426 — retracts the "engine vocabulary" fail condition this line used to carry).** A POPID, household ID, lineage ID, or a real mechanic (the Heritage_Ledger founding a lineage, a wealth tier) described in ordinary civic-flavor prose — "the municipal registry certified the Corliss name under lineage LIN-00001" — is texture around a real, ledger-verified event, not fabricated machinery. Don't gate on "is this institution named in `docs/canon/INSTITUTIONS.md`" — that doc tracks recurring named institutions, not every generic office a piece can invent in passing (the same license a real newsroom takes citing "case number 2024-CV-1102"). A past AUTOSAVE grade wrongly stripped three such sentences from a Mags Corliss piece under this reasoning; all three were reverted (`4a453252`).
- **Check the cycle math, don't trust the tag.** `n = floor((cycle-1)/52)+1`, `m = ((cycle-1)%52)+1` — cycle 103 is `Y2C51`, and `m` can never exceed 52. `Y2C103` is malformed no matter where it was copied from; `editions/cycle_pulse_c103.txt` carries it too. A calendar year in a bio (Vinnie's 2031 championship) is a YEAR, not a cycle.
4. **Pick the cycle tag.** `Y<n>C<m>` for where the piece is PLACED, not the first one its body happens to mention — a lore piece legitimately names several cycles. Placement is a judgment call made here and passed as `--tag`; it is authoritative downstream.
5. **Branch.**
```
# PASS — both canon stores, then the source id is recorded in the policy
node scripts/loreIngest.js --file output/lore-quarantine/<piece>.md --verdict pass --tag Y2C103
# FAIL — local rejection log only, neither store is touched
node scripts/loreIngest.js --file output/lore-quarantine/<piece>.md --verdict fail --reason "<what Rhea failed it on>"
# Prove the wiring without touching either store
node scripts/loreIngest.js --file <piece> --verdict pass --tag Y2C103 --dry-run
```
6. **After a pass, re-validate the source policy:**
```
node scripts/notebooklmSourceInventory.js # refresh the inventory from the live notebook
node scripts/notebooklmCanonSourcesValidate.js # fail_closed check over every bucket
```
The validator is fail-closed: a lore source id must be in the regenerated inventory AND carry a `decisions` entry, both of which `loreIngest.js` handles. Any *other* unclassified source it reports is a pre-existing canon-gate question for research-build, not something to classify from this skill.
## What lands where
| Verdict | NotebookLM (canon authority) | bay-tribune (Supermemory) | Local |
|---|---|---|---|
| pass | `Lore: <slug> (Y<n>C<m>)` in the GodWorld notebook (`config/notebooklm.json` → `notebookId`, NOT `newsroomNotebookId`) | `type=lore`, `cycle=<engine cycle>`, container `bay-tribune` | source id → `allowedLoreSourceIds`, and a leak-stripped copy staged to `output/cron-compare/staged/lore_c<cycle>_<slug>.staged.md` |
| fail | never | never | `output/lore-quarantine/_rejected.log` |
The staged copy is what puts a passed piece in front of the desk staging lane and inside `notebooklmDailyNews.js`'s collector — that script walks `output/cron-compare/staged/` for `*.staged.md`, keys on a `_c<cycle>_` in the filename, and only takes files newer than its lookback window (36h). Same door the desk articles come through, so no separate wiring.
**Cycle math, both directions.** The tag's C number is the cycle-within-year, not the engine cycle: `Y<n>C<m>` → engine cycle `(n-1)*52 + m`. Y2C51 is cycle **103**, not 51. `loreIngest.js` converts before it hands `--cycle` to `ingestEdition.js`; getting this wrong files the piece under a cycle fifty-two behind where it belongs.
Audio overviews are always off for lore (quota is for editions). The notebook summary is opt-in and writes to a slug-named path, so a lore push can never overwrite an edition's `output/nlm_summary_c<N>.md`.
## Known texture
- Lore pieces have no `## INTAKE` block, so `ingestEdition.js` warns and ingests as legacy content. Do not pass `--require-intake`.
- The metadata strip drops a trailing `**NAMES INDEX**` / `**CITIZEN USAGE LOG**` block (bold form) but keeps a plain `NAMES INDEX` one. Both are harmless; the body prose is never touched.
## Full spec
`docs/archive/plans/2026-08-17-lore-canon-ingest-pipeline.md` (pipeline.59). Generation half: `.claude/skills/lore-writer/SKILL.md` (pipeline.56).
View on GitHub