Quality assurance for automated wiki ingestion pipelines — wikilink verification, subagent timeout recovery, log consolidation. Companion to youtube-content and any bulk wiki creation workflow.
After any automated wiki page creation pipeline (youtube-content extraction, bulk concept creation, multi-subagent write operations). The youtube-content skill handles creation; this skill handles verification and recovery — the quality gate between "subagents ran" and "wiki is correct."
consume/ and produce/ replace the old flat structure. See references/wiki-consume-produce-architecture.md. Do NOT update skill paths until the restructure executes.delegate_task batch returns with any status=timeoutlog.md entryreferences/bulk-blog-concept-extraction.md for the full inventory→cluster→extract→QA patternreferences/theme-discovery-and-product-ideation.md for the concepts→themes→products pipelinereferences/single-agent-manual-extraction.md for the simpler read→check-dup→extract→verify→finalize pattern (validated on 76 and 116 post clusters)write_file resolved paths; subagents sometimes write to wiki/concepts/ instead of wiki/writing/concepts/ or vice versaHTTP 401: Model X is not supported) — subagent may have read all posts but created zero pages; re-dispatch neededreferences/chat-export-batch-extraction.md for the manifest→batch→extract pipeline with dual corpus handling, plus the Phase 6 review & reorganize workflow (discard stale, move novel frameworks, synthesise into existing files, merge active execution references)references/podcast-audio-fallback.md for RSS feed discovery, Whisper binary location, and highlights-only modeAfter any bulk creation, verify that the anchor page's wikilinks resolve to actual files on disk. This is the single highest-signal quality check — broken wikilinks mean the subagent used wrong filenames.
For highlights pages specifically, see references/highlights-post-write-qa.md which covers timestamp drift, composite quote detection, wikilink reconciliation with sibling-created concept pages, and sibling log corruption cleanup.
from hermes_tools import search_files
import re, os
WIKI = "/opt/data/wiki"
ANCHOR_PAGE = "concepts/four-s-curves-2017.md" # the page with many outbound links
Read the anchor page and extract all [[wikilinks]]
with open(f"{WIKI}/{ANCHOR_PAGE}") as f:
content = f.read()
links = re.findall(r'\[\[([^\]]+)\]\]', content)
concept_links = [l for l in links if l.startswith("concepts/")]
Check each one
broken = []
for link in concept_links:
slug = link.split("/", 1)[1]
result = search_files(pattern=slug, path=f"{WIKI}/concepts", target="files")
if not result["total_count"]:
broken.append(link)
if broken:
print(f"BROKEN WIKILINKS ({len(broken)}):")
for b in broken:
print(f" ✗ {b}")
print("\nLikely matches on disk:")
for b in broken:
slug = b.split("/", 1)[1]
# Try partial match
result = search_files(pattern=slug[:20], path=f"{WIKI}/concepts", target="files")
for f in result.get("files", []):
print(f" → {f}")
| Situation | Action |
|---|---|
| 0 broken links | ✅ Pass — no action |
| 1-2 broken with close matches | Fix the wikilinks in the anchor page (patch) |
| 3+ broken | Offer the user a re-extraction — the subagent fundamentally misnamed things |
When multiple subagents update index.md during the same ingestion (the entity, concepts, and highlights subagents each write their own entries), three failure modes commonly emerge:
Each subagent may insert the same page independently. The entity subagent adds entities/timothy-keller to the Entities section, and the concepts subagent also adds it — resulting in two identical lines.
index.md fully (not paginated). Count occurrences of each new page slug. Any slug appearing more than once is a duplicate.
Fix: Use patch with the duplicate line pair as old_string and the single line as new_string.
Subagents often insert entries at the top of a section (prepending) instead of the alphabetically-correct position. Example: a highlights page with slug your-plans-gods-plans-timothy-keller inserted before 10-year-futures-vs-whats-happening-now instead of after tony-fadell-lenny-podcast.
[[...]] after the last slash. Any entry out of order is misplaced.
Fix: Use patch to remove the misplaced entry from its wrong position, then patch again to insert it between the two correct neighboring entries.
If three subagents each bump the count independently, the total may be too high — or one subagent bumps by its count while another already accounted for shared pages (e.g., the entity page counted by both entity and highlights subagents).
Detection: The header count (Total pages: N) should equal previous_total + count_of_files_actually_written_to_disk. Use search_files with the ingest date or slug pattern to count actual new files.
Fix: Patch the header line with the recalculated count.
1. Read index.md fully — no pagination, read the complete file in one call
2. Check for duplicates — scan for repeated wikilinks; fix with patch
3. Check alphabetical order — scan each section; fix misplaced entries
4. Verify page count — count on-disk pages and reconcile with header
5. Re-read index.md after all patches to confirm final state
When a delegate_task batch returns status=timeout for any child (especially the concepts subagent), it means partial completion: some pages were created but index.md was not updated. Treat this as recoverable, not a failure.
from hermes_tools import search_files
import os
Find all concept pages sourcing from this transcript slug
result = search_files(
path=f"{WIKI}/concepts",
pattern="TRANSCRIPT_SLUG", # e.g., "10-year-futures-vs-whats-happening-now"
target="content",
output_mode="files_only"
)
existing = sorted([os.path.basename(f).replace(".md", "") for f in result["files"]])
print(f"Found {len(existing)} existing concept pages")
Step 2 — Integrate into index.md:
The subagent created pages but didn't update index.md. Add entries manually using execute_code:
index.md lines## ConceptsCreate a targeted subagent with explicit lists:
ALREADY CREATED (do NOT recreate):
- concepts/page1.md
- concepts/page2.md
...
CREATE THESE:
1. concepts/missing-concept-1.md — description
2. concepts/missing-concept-2.md — description
Step 4 — Finalize:
After re-dispatch, run wikilink verification + log consolidation on the complete set.
When 3 subagents each write their own log.md entry, the result is a fragmented log. The parent MUST consolidate.
After all subagents complete (including any re-dispatched ones):
1. Read log.md to find the separate entries (they'll be at the top, most recent)
2. Delete the individual subagent entries
3. Prepend ONE unified entry:
## [YYYY-MM-DD] ingest | [Video Title]
- Cost: $Z.ZZ (starting: $A.AA → ending: $B.BB)
- Created: [list all pages by category: entity, highlights, concepts...]
- Updated: index.md (+N pages)
Use patch with old_string matching the first fragmented entry and new_string being the full consolidated block.
index.md independently: (a) they can insert the same page twice, (b) they often prepend entries at the top of a section instead of inserting alphabetically, (c) the total page count is usually wrong. Always run the Index.md Collision Detection checklist above after subagents finish.wiki/concepts/ instead of wiki/writing/concepts/). After every batch, run search_files across BOTH wiki roots to catch misplaced pages. Fix with a simple mv from the wrong directory to the correct one. This pattern bit us on the Finance cluster — 15 pages went to the root wiki's concepts/ instead of writing/concepts/.references/chat-export-batch-extraction.md for the full manifest→batch→extract pipeline. Key: always dispatch with conversation UUIDs, not titles; regenerate manifests before each batch; handle dual corpus (ChatGPT + Claude) formats.HTTP 401: Model <name> is not supported or similar provider error, it may have read all posts but created zero pages. Re-dispatch that single cluster with tighter scope. This happened on the Writing cluster (30 posts) — re-dispatch with explicit duplicate-avoidance instructions worked.execute_code tool has different read_file semantics. Inside execute_code, from hermes_tools import read_file returns a dict with keys like status/message/content_returned, NOT a plain content key. The outer read_file tool is different from the inner Python SDK. When batch-reading files from execute_code, prefer terminal('cat <path>') for reliability — it doesn't deduplicate and the output format is predictable./opt/data/cache/delegation/subagent-summary-<N>-<timestamp>.txt for the complete list.search_files(pattern='<slug>', path='WIKI_PATH/log.md') and delete any corrupted entries — the highlights agent's entry is authoritative.read_file deduplicates within a session. Re-reading the same file path returns status: unchanged with no content. When batch-processing a file list inside execute_code, use from hermes_tools import read_file inside the Python loop — this bypasses session-level dedup and returns full content. The outer read_file tool is affected; the Python SDK function is not.