/improve Proposal: Deterministic I12 Heading Validation in the Process-Newsletter WATCH Path
Status: Awaiting founder greenlight
Notion task: https://app.notion.com/p/38ef7d4936d181cb9ebaf86d75676a64
Source: Review 16 (2026-06-28) + /improve autonomous run 2026-06-29
Problem statement
The watch-mode subagent (Mode 4) keeps emitting curation/hybrid notes whose body section uses an invented heading synonym instead of the two canonical headings that the I12 audit invariant requires:
## Curation section## Issue contents
Examples from Review 16 (2026-06-28):
2026-06-23-alphasignal-composer3-*.md— used## Stories covered2026-06-24-every-ai-judgment-*.md— used## Main Essay+## Digest Items
Recurrence history (5+ cycles):
- 2026-05-08 —
/improveadded canonical-schema pre-write checklist to Mode 4 subagent prompt - 2026-06-01 — value-list sync fix applied
- 2026-06-24 — explicit I12 compliance rule added to Step 5 body guide AND Mode 4 checklist (2nd wording fix)
- 2026-06-28 (Review 16) — still recurs; 5 entries in the 2-week window still fail I12
Why wording fixes don't converge: The subagent, under instruction load, substitutes a semantically reasonable synonym (## Stories covered, ## Main Essay, ## Digest Items) that no enumerated list anticipated. The space of plausible synonyms is unbounded. Two prior /improve wording fixes prove the approach doesn't converge. The durable fix must be deterministic and mechanical — run the audit script as a gate, not post-hoc.
Why this is in the vault
Documents the structural /improve proposal for wiring audit-newsletter-outputs.py I12 check into the watch loop's write path. Preserves the rationale for Option A (pre-write gate) vs alternatives, and serves as the greenlight artifact for the SKILL.md edit.
Proposed fix: Option A — Pre-write I12 gate in the watch orchestrator
Mechanism
After each subagent writes its vault note and returns its one-line summary, the watch parent orchestrator runs a targeted I12 check on that specific file before proceeding to the next. If I12 fails, the orchestrator re-dispatches the subagent with the specific failure message to rewrite the note — not a general re-process, just a targeted heading correction.
This wires audit-newsletter-outputs.py (which already computes I12 correctly and deterministically) into the write-time path rather than the days-later post-hoc review path.
Why this is the right level
- Subagent self-check is too weak — that's what the pre-write checklist already is; it still fails because the model substitutes synonyms under instruction load
- Post-hoc audit is too late — it catches failures days later in
/self-review, requiring manual/self-review --fixrepair - Pre-write parent gate is the right level — the parent orchestrator is mechanically reliable (no synonym substitution), can read the written file, run the deterministic Python script, and re-dispatch with a pinned failure message
Implementation detail
The audit script already supports --strict (exits 1 on any violation) and --since (restricts to a date window). The parent can call it scoped to the single new file using --since <file-date> or by passing a single-file check variant.
Simpler approach: Rather than calling the full audit script with --since, the parent can inline the I12 check directly (read the written file, check if newsletter_format is curation or hybrid, verify the heading pattern exists). This avoids the 7-day window ambiguity and makes the check surgical.
SKILL.md diff — proposed change to Mode 4
The change is to Step 3 of Mode 4 (the watch orchestrator loop), adding a post-write I12 gate between "subagent returns" and "parent collects summary lines."
Current text (lines 96–110 of SKILL.md, Mode 4 Step 3 and Step 4)
3. **Spawn one subagent per remaining message** (max 3 concurrent) using the Agent tool with `subagent_type: general-purpose`. Each subagent:
- Receives the message ID and the sender slug
- Follows the **"Process one message"** steps 1-6 for exactly that ID — including the full body fetch, classification, sponsor detection, optional link follows, and writing the vault note
- **MUST satisfy this canonical-schema pre-write checklist before writing the vault note** (added 2026-05-08 ...)
[... full checklist ...]
- Returns ONLY a one-line summary: `<filename> | <format> | <mapping-strength: strong/medium/weak/skip> | <one-sentence why>`
**Subagent-depth fallback:** [...]
4. **Parent collects summary lines.** The full message bodies never enter parent context. Even at 4-8 messages per watch run that's 30-100KB saved per cycle.
5. **Report**: aggregate the summaries, flag any tracked-author candidates or new sponsor patterns surfaced.
Proposed replacement (insert new Step 3b between Step 3 and Step 4)
3. **Spawn one subagent per remaining message** (max 3 concurrent) using the Agent tool with `subagent_type: general-purpose`. Each subagent:
- Receives the message ID and the sender slug
- Follows the **"Process one message"** steps 1-6 for exactly that ID — including the full body fetch, classification, sponsor detection, optional link follows, and writing the vault note
- **MUST satisfy this canonical-schema pre-write checklist before writing the vault note** (added 2026-05-08 ...)
[... full checklist unchanged ...]
- Returns ONLY a one-line summary: `<filename> | <format> | <mapping-strength: strong/medium/weak/skip> | <one-sentence why>`
**Subagent-depth fallback:** [...]
**3b. I12 gate — parent validates each written note before collecting its summary.**
After each subagent returns, the parent orchestrator runs a deterministic I12 check on the written file. This runs the audit script scoped to only that file:
```bash
~/.claude/scripts/graph-db-venv/bin/python3 \
~/.claude/scripts/audit-newsletter-outputs.py \
--since <file-date> --strict --json
Or inline (faster, no date-window ambiguity): read the written file, check frontmatter newsletter_format, if curation or hybrid then verify that the body contains ## Curation section or ## Issue contents (case-insensitive level-2 markdown heading).
If I12 passes: collect the subagent's summary line and continue.
If I12 fails: re-dispatch the same subagent with a targeted correction prompt:
"The note at
<filepath>was just written but fails the I12 structural invariant:newsletter_formatis<curation|hybrid>but the body has no## Curation sectionor## Issue contentsheading. Rename the existing curation/digest/stories section heading to exactly## Curation section(or## Issue contentsif the note enumerates issue items). Do not rewrite the content — only fix the heading. Return the same one-line summary once the heading is corrected."
This is a surgical heading rename, not a full reprocess. The re-dispatch should take < 1 turn for the subagent.
Cap: max 1 re-dispatch per note. If I12 still fails after the re-dispatch, log the failure and continue (parent includes I12-FAIL in the summary line so the report surfaces it). Do NOT loop.
- Parent collects summary lines (after I12 gate passes or 1-retry exhausted). The full message bodies never enter parent context.
- Report: aggregate the summaries. Any
I12-FAILlines become a "DECISION NEEDED" item since they represent a note that may need manual repair.
---
## Why not the alternatives
**Option B — Write a `06-reference/` filesystem hook:** A pre-commit or inotify hook that runs the audit before any file write. Pros: catches ALL write paths (not just watch mode). Cons: requires OS-level hook infrastructure, more complex to install/maintain, not portable across Claude Code sessions. Given the recurrence is concentrated in watch mode, Option A is the right minimum viable gate.
**Option C — Patch the subagent prompt a third time:** Already tried twice (2026-05-08, 2026-06-24). Wording enumeration against an unbounded synonym space does not converge. The improve/SKILL.md Recurrence Guardrail (step 2b, added 2026-06-29) explicitly disallows a third wording fix for this pattern.
**Option D — Run audit post-write but before reporting (current Step 8):** Already exists (Mode 4 Step 8 runs the full audit post-hoc). The problem is Step 8 is informational — it surfaces failures without blocking or auto-fixing. The gap is the absence of a write-time gate with auto-correct. Option A adds the gate at the right moment.
---
## Acceptance criterion
A fresh watch-mode curation/hybrid note passes `audit-newsletter-outputs.py --strict` I12 on first write (or after the one automatic re-dispatch), with zero `/self-review --fix` I12 repairs needed over a 2-week observation window (2 Review cycles).
---
## Mapping against Ray Data Co
This is a RDCO operations harness improvement. The `process-newsletter` skill is a core ingestion pipeline; I12 failures degrade vault quality and require manual repair in self-review. Fixing the gate moves RDCO from a reactive-repair loop to a write-time prevention pattern — consistent with the `audit-newsletter-outputs.py` philosophy ("zero LLM calls, cannot hallucinate a pass").
The parent-gate pattern also generalizes: any invariant that is cheap to check deterministically should run at write time, not 7 days later in self-review. This proposal pilots that pattern for I12; future `/improve` runs can extend it to I8/I9 if heading drift ever appears there.
---
## Related
- [[2026-04-19-newsletter-output-invariants]] — full I1-I13 spec
- [[2026-06-24-improve-process-newsletter-run]] — the last `/improve` run that added the 2nd wording fix (now superseded by this proposal)
- [[2026-04-11-garry-tan-thin-harness-fat-skills]] — source framework for thin harness, fat skills / skill self-improvement loop