Pilolcura ingest, and two contract bugs

The first real use of the pipeline built on 2026-09-01. Three parts, 34 idea units, every one of them marked destination: note. Eight notes created in Inbox/. The ledger is ingested-dumps.md.

The dumps arrived in the wrong place

They were written to the repository root, untracked but not ignored. Moved to private/dumps/ before anything else. The root is outside the vault, so nothing was ever at risk of publishing, but the root is not gitignored and private/ is.

The lint gate fired, and it was half wrong

13 errors on the first run. Three classes, and only classifying them made the run possible:

ClassCountVerdict
Idea carries only context quotes6Real. All six are origin: claude.
author quotes count disagrees with Coverage3Real, and the linter was right.
Cites an input declared in an earlier part4The linter’s bug.

The third class is the interesting one. check_inputs resolved input ids per file, so part 3 citing part 1’s i1 read as undeclared. The same bug ran through related and supersedes, where it produced 24 warns on legitimate cross-part references. format.md is explicit that ids are conversation-global: “a later part can reference an earlier part’s id in related or supersedes with no namespacing.” The skill tells the agent to pass every part in one invocation because “some checks only work across parts”, and those checks did not.

Fixed by moving both resolutions into a new conversation-level pass, check_cross_part_refs. An input declared in a sibling part is now a warn that names the real problem (the part does not stand alone) rather than an error. Errors went 13 to 9 and the warn noise dropped by 24 lines.

The other two classes were the producing side

The count mismatch was not a linter bug, which took a check to establish. The reference example states author quotes: 3 and holds three pull-quote lines plus one context quote, so the contract means pull quotes only. The producing model counted both, identically in all three parts.

The quote class was a genuine gap in the written contract. format.md said every idea carries “at least one blockquote line, or the exact line no quotable line from the author”. A context quote is a blockquote line, so the six ideas satisfied the rule as written while failing the rule as enforced. The linter was enforcing the right thing for the right reason: the vault side never copies a context quote, so those ideas reach the vault with nothing of the author’s.

Both gaps closed in format.md rather than in the linter, since the fix belongs where the producing model reads it.

What the vault said that the dump could not

The dump named no existing note, carried no may extend, and proposed 34 new ones. The vault overrode that in three ways:

  • A stub for this race already exists in Journal/Free form/, holding a self-instruction to write it section by section. The race narrative is the author’s to write, so the five race-specific units were skipped rather than filed.
  • Notes/Negative split already covers the subject of one unit, so that one became an append proposal rather than a note. It is publish: true, so it waits for approval.
  • Six units are field-data analysis the author had explicitly parked for a separate thread, which the dump recorded in ## Threads as dropped.

Decisions worth keeping

  • Cap the creations below the cap. The skill allows 8. The Inbox held 47 and the vault records roughly 20 Inbox-to-Notes promotions in its whole history. Six were recommended; the author took all eight.
  • A coined term never becomes a title. Two of the eight units carried only (coined here) concepts. The note that came from one of them is titled with the claim instead, so nothing imitates an atomic note that does not exist.
  • Two origin: claude units were filed at the author’s explicit direction, after being named as such. One of them has no author quote at all, so its body is Claude’s prose and is flagged for him to cut.