Claude Code Skill

/ingest-wiki

Build and maintain a source-grounded, AI-native wiki by ingesting books, articles, and notes into a structured tree of canonical source pages and topic pages — under strict invariants around identity, evidence, and safe mutation, and with a measured multi-agent architecture that stays inside every model's context budget.

Default mode review
Patterns Single-pass · Multi-pass
Canonical layout sources/* · topics/* · _ingest/<run>

What the skill produces

The wiki separates four stores. Two are canonical and authored. Two are derived and disposable. That separation is what lets the skill mutate canonical state safely.

sources/*.md canonical

Normalised source records — one per ingested book/article/excerpt with stable source_id, locators, chunk IDs, and source-bound observations. Topic pages cite these.

topics/*.md canonical

Synthesised topic pages with stable claim IDs, tensions, and open questions. Each claim resolves to a chunk on a source page.

_ingest/<run-id>/ run-local

Per-run artifacts: summary.md, proposed/, validation-report.md, candidate-ledger.md, plus dispatch plans and contributions for multi-agent runs. Never canonical.

_generated/ derived

Indexes, backlinks, embeddings, rendered views. Regenerable. Never the source of truth unless the repo explicitly says so.

Seven invariants the skill enforces

The skill is built around contracts a future ingest can rely on. Everything else — the multi-agent architecture, the math, the validation gates — exists to keep these intact.

Where each piece of evidence ends up

Once material is extracted from a chunk, the skill answers two questions: does this belong on the source page or a topic page, and if topic-bound, does it match an existing claim or introduce a new one?

Step 1 — primary disposition

DispositionUsed for
source_only Narrow details, one-off examples, weakly-supported interpretations, local terminology, material whose reuse value is unclear. The default when in doubt.
topic_bound Reusable, durable claims that synthesise across sources. Promoted to a topic page only when scope and reuse are clear.

Step 2 — same-meaning test

A new candidate matches an existing claim only when every one of these stays materially the same. If any change, do not reuse the old claim ID — the meaning has shifted, and the old ID would silently start carrying new meaning.

predicates compared same_meaning(cnew, cold) ≡
  subjectpredicateobject
  ∧ scopequalifiersmodality
  ∧ time/contextcausal_direction

Step 3 — match class

ClassMeaning
supports_existing_claimAdds evidence to a claim with the same meaning.
qualifies_existing_claimNarrows or conditions a claim. Add a qualifying claim or support_note; do not rewrite the original statement.
contradicts_existing_claimDisagrees. Stays visible as a tension; never collapse live disagreement.
introduces_new_claimA distinct, in-scope claim. New claim ID, append-only.
suggests_new_topicTopic-worthy but no safe target. Default to source_only retention plus a deferred candidate.

What patches are allowed without review

The skill draws a hard line between additive changes that preserve old meaning and structural changes that rewrite identity. Everything in the right column requires review regardless of mode.

Low risk · auto-allowed

Additive, append-only

Add support to an existing claim · add a new in-scope supported claim · add a tension · add an open question · refresh summary to reflect changed records · add a relation with a resolvable target · supersede with a new claim ID when evidence is clear and disagreement is preserved.

High risk · review required

Identity-changing, in-place

Deletion · merge · split · rename · widening page scope · removing support · semantically rewriting an existing claim · materially changing claim meaning without a new ID · collapsing live contradictions · uncertain supersession · patching legacy or unversioned pages · changing the canonical source of truth.

Three passes, three review gates

Single-pass is the default — narrow sources, predefined topics, idempotent re-ingests. Multi-pass is used when the source is book-length and topic coverage is not obvious, or when topic creation must be approved before any canonical writes.

Pass A

Discovery

Read the source, normalise it, chunk it, propose topic candidates with scope, rationale, and supporting chunks.

No canonical writes. Output is proposed-topics.md awaiting user approval.

Pass B

Extraction

Run the single-pass workflow restricted to Pass A's approved topics. Create or patch pages, route candidates, validate, propose final files.

New topic candidates that surface here are deferred — never silently promoted.

Pass C

Audit

Re-read source against canonical wiki. Verify every quote verbatim. Flag missing claims, drift, and overlapping topics.

Audit-driven changes follow the same low-risk patch rules as single-pass.

Why chapter-agent fan-out beats topic-writer fan-out

For book-length initial extraction, the skill defaults to one subagent per chapter, not per topic. The reason is read economy and view bias.

Topic-writer fan-out · expensive

One agent per topic

Each topic-writer reads every chunk its topic cites. When a chapter supports 5–7 topics, that chapter is read 5–7 times — each pass with a narrow, topic-coloured view that misses cross-chapter patterns.

Chapter-agent fan-out · default

One agent per chapter

Each chapter is read once, in full. Recurrences across chapters surface naturally. A coordinator extracts per-topic fragments from the contributions and dispatches assembly subagents to compose final pages.

Coordinator pipeline (post-extraction)

  1. Collect contribution metadata only — paths and pass/fail signals, never bodies.
  2. Fragment extraction — slice claim-draft blocks per topic out of every contribution using grep + awk; concatenate into per-cluster briefs.
  3. Dispatch assembly-subagents — one per topic cluster. Each writes the finished pages and returns paths.
  4. Dispatch the relation-linker — receives a compact claim-statement index across all new pages; patches relations: fields in place.
  5. Aggregate observations and deferred candidates — small structured records appended to the source page and ledger.
  6. Write summary and validation — using paths and metadata only; never page bodies.

Context budget & load distribution

Every pass involves subagents whose context windows are bounded. The skill picks decomposition by measuring real bytes, not by guessing from chapter or topic counts. All formulas below operate on the currently-running model's window — there are no fixed token constants.

40%
subagent budget cap of context window
60–70%
coordinator practical ceiling (driver-only)
~4 ch
≈ 1 token (English prose); +10–25% for transliterated CJK / Sanskrit / Tibetan
4/3
LPT bin-packing approximation ratio

Subagent budget

Budget B = 0.40 × model_context_window

# Reserve 60% for reasoning, scratchwork, and unexpected output growth.

Per-chapter load (Pass B chapter-agent)

Load formula Lc = Cc + Σ Ti + F
  • Cc — chapter tokens, measured with wc -c ÷ 4 (never by opening the file)
  • Ti — tokens of each topic the chapter touches; full canonical page if it exists, Pass A scope brief if it doesn't
  • F — fixed per-agent overhead: page-format spec + instructions + reserved expected-output budget; measured once per template

When a chapter overflows

ConditionAction
Lc ≤ BOne chapter-agent receives all topics for that chapter.
Lc > B and Cc+F < BSplit topics across N agents reading the same chapter, different topic subsets.
Cc+F ≈ BChapter leaves no room for topics — fall back to topic-writer fan-out: each agent reads chapter + 1 topic.
Cc+F > BChapter itself overflows — split structurally on ## headings; recurse.

Minimum agent count when splitting

Lower bound N = ⌈ Σ Ti / ( BCcF ) ⌉

# The denominator is the room left in one agent after the chapter and overhead.
# Ceiling guarantees no single agent exceeds the budget.

LPT bin-packing for topic distribution

Once N is known, topics are distributed across the N bins using Longest-Processing-Time-first. Topics vary in size by an order of magnitude, so count-based slicing produces unbalanced loads ("one agent at 39%, the other at 5%"). LPT is a one-pass greedy algorithm provably within 4/3 of optimal.

LPT sort(topics) by Ti descending
for each topic in that order:
  assign to bin with currently-lowest total load

# Worst case ≤ 4/3 × OPT. Single pass, no iteration.

Assembly cluster count

After contributions return, fragments are sliced per topic. St is the total fragment size for topic t (plus the merge target's bytes if Pass A decided merge_into). Cluster count M uses the same logic as chapter dispatch:

Assembly M = ⌈ Σ St / ( BFassembly ) ⌉

# Topics distributed by LPT bin-packing into M clusters.
# Similarity-based clustering is explicitly rejected — relations are the linker's job.

Coordinator invariant

The coordinator orchestrates an entire run. To stay bounded, its steady-state context must not depend on source size:

Invariant coordinator_context(steady_state) = O(1) in source size

# A 5-chapter book and a 100-chapter book produce the same coordinator working set.
# Achieved by file-as-memory: write derived artifacts to disk, drop raw inputs from context.

What it holds, what it must not

The 40% subagent rule only works because every subagent runs to completion in a fresh, bounded context. The coordinator earns its higher 60–70% practical ceiling by being a disciplined driver — never a content-holder.

Coordinator holds

Measurements manifest (paths + numbers) · dispatch plan · approved topic list (slugs + scopes) · subagent ids and return statuses · "topic → path written" confirmations · aggregated structured observation records (small, bounded by chunk count).

Coordinator must NOT hold

Chapter bodies · contribution bodies (beyond grep/awk byte ranges) · finished topic page bodies · evidence, quotes, or claim-statement content beyond the relation-linker brief · any subagent's internal reasoning or scratchwork.

Slug-by-slug assembly by the coordinator is prohibited. A coordinator loop that reads one topic's fragments, writes its page, then moves to the next accumulates every fragment and every page across the loop. Assembly must be delegated to subagents in fresh contexts; the coordinator only ever receives written-path confirmations.

Why structural splits beat semantic ones

When something needs to be split — a chapter, an audit, a cluster — the skill always splits mechanically (by chapter, section, claim) rather than semantically (by "topic cluster", "doctrinal theme", "related concepts").

The gate before canonical writes

Every run produces a parseable validation-report.md. Modes determine what blocking failures cost.

ModeOn hard failureOn warningsOn zero-diff
review Stay in proposal; mark blockers in summary. Same — review is the human gate. Successful run; no proposed changes.
auto Block publish. Default to publish nothing unless the user explicitly enabled safe-subset auto. Publish allowed if every change is auto-safe and validated. Successful run; wiki already reflects the source.