Ingest
对话式 agent(Claude Code / Codex)驱动的本地知识库编译器:把 PDF/DOCX/PPTX/Markdown 增量编译进一个去重、互联、可复现的 Obsidian 学习知识库。
npx -y skills add Iabstergo1/pdf-to-study-kb --skill ingestAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
End-to-end add a new external source (PDF/DOCX/PPTX/Markdown), deterministically adopt an already-populated Obsidian vault baseline, or register selective reuse from another published pipeline vault. Use for "add/ingest/index/weave this source", "adopt/onboard this existing vault", or "reuse this published source". Normal ingest preprocesses and writes proposed pages; legacy adoption and external-vault reuse are separate zero-LLM branches. Read-only requests like "summarize/explain/translate this" must never trigger it.
SKILL.md
19.7 KB, as published. Nobody here has run it
ingest — weave, adopt, or reuse a source (normal ingest is the only LLM write step)
You are the maintainer of the knowledge base. Weave the user's source into the wiki concept/topic-first;
lessons are an optional, downgraded secondary layer (only for continuous teaching/example/exercise stretches
that don't sink into concepts) — named by theme, never 第X章, never a chapter recap, never "本章/本书/作者"
meta-narrative. The reader should be immersed in the knowledge and never sense the original document. Work under
the work-order transaction protocol the whole way. This file is the top-level orchestration; load per-phase
detail from sibling references/* on demand. Project truth: AGENTS.md / CLAUDE.md. Engineering format: docs/skill-runtime/skill-standard.md.
If the request is to adopt an already-populated vault, take the dedicated zero-LLM adopt-vault branch in §6
before any work-order, window or LLM writing step; that branch does not use the normal ingest transaction protocol.
If the request is to register selective reuse from another pipeline vault whose source is already published, take
the zero-LLM reuse-source branch in §6; target merge pages/source_refs must already exist and are never written by it.
Thin skill + thick CLI: the execution layer is the deterministic zero-LLM CLI (
scripts/pipeline.py); this skill carries no business code, only orchestrates it.<src>= this source's source_id; run commands from the project root with the study-kb interpreter (on Windows: pwsh +$env:PYTHONUTF8=1).
1. Triggers / Non-triggers
- Triggers: "add this book/PDF to the KB", "ingest <source>", "index this document", "weave this file into the wiki", "adopt/onboard this existing Obsidian vault", "reuse this source from the published vault".
- Non-triggers (never fire): "summarize this", "explain this", "translate this", "answer a trivia question", "what is this PDF about" (a question, not an ingest request).
2. Inputs
- The user gives: file path
<path>, domain<domain>; format<fmt>is inferred from the extension (pdf/md/docx/pptx);<src>is derived from the filename (lowercase, hyphenated). Confirm<src>and<domain>once with the user. - For existing-vault adoption, instead require
<src>,<title>,<domain>, a baseline archive path and its independently recorded 64-hex SHA-256. Confirm all five inputs; do not silently calculate a new expected hash and treat it as prior baseline evidence. - For cross-vault reuse, require
<src>/<title>/<domain>, the current PDF path + independently expected SHA-256, a disjoint read-only<origin-root>+ matching<origin-source>, and an explicit mapping JSON (v1 or v2 — both supported). The mapping's covered origin-concept set must equal the set the origin actually owns, so nothing is missed, duplicated or double-mapped; target count and the non-empty/zero-mapping split are the mapping's own shape, not a gate. A v2 mapping adds a symmetrictopic_targetsdimension so topic pages that legitimately aggregate this source can declare it; unlike concepts, origin topics need not be covered exhaustively — only referenced ones must exist and must not be referenced twice. Non-empty targets in either dimension already carry this source_ref, while explicit zero-mapping targets must not. This branch verifies the merge; it never performs it. Existing v1 mappings and frozen v1 evidence need no migration: a v1 run is byte-identical to before. - Read:
wiki/_meta/purpose.mdfirst — it is the authority on writing style, structure, depth and terminology (the user's learning goals / teaching preference). The deterministic layer only guards order/safety/provenance; form is purpose-driven, not template-driven. Then readdocs/skill-runtime/{schema,concept-resolution}.md,templates/*(suggested scaffolds, not mandatory skeletons), and the phase references.
3. Outputs
- Normal-ingest vault writes are always
status: proposed+managed_by: pipeline: lessons / concepts / topics / comparisons / synthesis /sources/<src>.md/overview.md. - Adoption exception:
adopt-vault --applyadds only a deterministic canonicalsources/<src>.mdwithformat: legacy-vault,status: published, plus immutable evidence/state; it never automatically rewrites existing knowledge pages. - Reuse exception:
reuse-source --applylikewise adds a deterministic canonical source page withformat: external-vault-reuse,status: published, plus immutable origin/mapping/first-target evidence andreused/publishedstate; it never writes any mapped target page. - Derived files (
_registry.yaml/index.generated.md) are not written by this skill — the finishing CLI rebuilds them.aliases.mdis retired (B2): English aliases live only in the concept page'saliases:frontmatter (Obsidian reads them natively for search/autocomplete).
4. Dependencies
- CLI:
scripts/pipeline.py(commands per phase). - Protocols:
docs/skill-runtime/schema.md(page types / per-type frontmatter contract; section titles are no longer mandatory — structure is purpose-driven),concept-resolution.md(resolution + home-domain routing). - Phase references:
references/preflight.md,references/arbitrate.md,references/content-routing.md,references/write-pages.md,references/synthesis.md,references/finish-lint.md.
5. Persisted artifacts
pipeline-workspace/staging/<src>/:source.md,blocks.jsonl,chapters.json(deterministic chapter map / navigation spine),reconciliation.json+evidence.json(PyMuPDF×MinerU dual-audit + per-page evidence model),arbitration/{queue,decisions,audit}.json,windows.jsonl,workorder.yaml, hard-page PNGs,digest.md(cross-window rolling digest with a## RESUMEblock).ingest_progress(per-window accounting, machine state). Rollback snapshots inpipeline-workspace/snapshots/.- Adoption branch only:
pipeline-workspace/adoptions/<src>/manifest.json+ verbatim page bytes underfiles/, one canonical source page and oneadoption_evidenceartifact; no staging/workorder/window ledgers. - Reuse branch only:
pipeline-workspace/reuses/<src>/{manifest.json,mapping.json,origin-state.json,origin-files/**,target-files/**}, one canonical source page and onereuse_evidenceartifact; no staging/workorder/window ledgers. - Reuse reseal only:
pipeline-workspace/reuse-reseals/<src>/<operation-id>/keeps the canonical transition, old/new source bytes and the full old evidence generation; exact retries reuse this archive.
6. CLI commands (orchestration order)
legacy vault (zero LLM) adopt-vault --source <src> --title <title> --domain <domain> --baseline-archive <archive> --baseline-sha256 <sha256> [--apply]
published source reuse (zero LLM) reuse-source --source <src> --title <title> --domain <domain> --path <pdf> --sha256 <sha256> --origin-root <root> --origin-source <src> --mapping <mapping.json> [--expect-concepts N --expect-topics N] [--apply]
reuse evidence v1→v2 reseal (zero LLM) reseal-source --source <src> --mapping <mapping-v2.json> --from-manifest-sha256 <old-manifest-sha256> [--apply]
preprocess + auto-arbitration init-vault → add-source → profile → source-convert → source-audit →[ arbitration-status → if pending: agent arbitrates queue → arbitration-apply ]→ windows → workorder
start / per-window (LLM) ingest-start → read chapters.json (build whole-book understanding) → write per-chapter content-routing table into digest (advisory; references/content-routing.md)
→[ in chapter order: window-start → show-window → write pages per routing orientation (read hard-page source images as evidence; re-express natively — never embed them; deviations logged) → window-done --writes ]×N
synthesis (LLM) phase E: update overview + build topic/comparison/synthesis (into some window's --writes) — first-class, lint blocks if missing
finish (zero LLM) ingest-done → lint
incremental reopen reopen → ingest-start →[ per-window backfill ]→ ingest-done → lint
legacy-vault adoption: run the command first without
--apply; this is a strict byte-zero-write dry-run that proves the pre-adoption ZIP and live adoptable-page set/bytes match. Legacywiki_gatecontent debt is warning-only here—the hard stop is limited to safety/readability/published status and archive/evidence/source/ state/ledger integrity. After explicit review, rerun with--apply. It takes the vault lock, writes immutable evidence + the canonical source page, rebuilds derived artifacts, and only then recordslegacy-vaultasadopted/published, with all three ingest ledgers at zero. A fully verified exact repeat is a whole-tree byte no-op. Later live-page evolution only reportspost-adoption-live-drift; it never rewrites the historical manifest/evidence or fails adoption. Archive, evidence, source-page, adoption metadata or state drift still fails closed. Usevault-lint/graph-lintafterward to pay down the warning-only legacy content debt.
published-source reuse: before both dry-run and apply, set
PYTHONDONTWRITEBYTECODE=1and invokepython -B scripts/pipeline.py reuse-source ...; the origin may also be this CLI code repository, so ordinary imports are not allowed to update itsscripts/__pycache__. Run without--applyfirst. The origin state DB must use a non-WAL rollback journal and have no-wal/-shmsidecar. The plan must report the expected PDF hash, read-only originlint/publishedstate, canonical source page, the published concept/topic counts it found, and a mapping (v1 or v2) whose covered origin-concept set equals the origin's own set (hence exactly once each). Target count is the mapping's shape, not a gate;--expect-concepts/--expect-topicsare optional confirmations. A v2 mapping also reports itstopic_targetsdimension — topic coverage is deliberately partial, so only referenced origin topics must exist and must not repeat. Non-empty target pages in either dimension must already carry this source_ref; zero-mapping targets must not. Replaying frozen v1 evidence stays a byte no-op; mixing a v1 evidence set with a v2 mapping (or vice versa) fails closed rather than silently upgrading. Apply takes only the target vault lock, freezes origin state/pages, raw mapping and the first target merge bytes, rebuilds every derived layer, then recordsexternal-vault-reuseasreused/published; all three ingest ledgers remain zero. Exact repeat is whole-tree byte/mtime no-op only after registry/index/graph/quiz/propositions are recomputed and verified; missing or corrupt derived output is rebuilt under the target lock. Later target live evolution ispost-reuse-target-live-driftwarning-only; origin/PDF/mapping/ evidence/source/state drift fails closed. The temporary mapping path is not identity: after success, replay with the immutable evidencemapping.jsonand remove the temporary input.
reuse evidence reseal: existing v1 evidence normally needs no migration. Use the independent
reseal-sourceonly when a legitimate topic attribution cannot be represented by frozen v1 evidence; ordinaryreuse-sourcemust never enter this branch. SetPYTHONDONTWRITEBYTECODE=1and usepython -B; the same read-only origin and non-WAL checks still apply. Run without--applyfirst. The old evidence must pass its full manifest/file/live-origin/PDF validation. Source/domain/title/format/evidence version/PDF/origin are derived from that manifest and have no override flags; concept targets, counts andtarget_pagesmust also remain identical. Only a non-empty v2topic_targetsdimension and its derived evidence may change. Apply holds the target vault lock, durably stages one deterministic operation, demotes state toreused/running, archives the whole v1 evidence generation, activates v2 evidence, replaces the source page only if its bytes still equal the old canonical page, rebuilds derived artifacts, then atomically changes reused-stage/artifact hashes and republishes. A crash at any boundary rolls forward by rerunning the exact command; published state exists only with a matching old or new generation, and an exact completed repeat is a whole-tree byte/mtime no-op. Do not use reseal to cover damaged evidence or to retire a source. Known limitation:retract-sourcedoes not supportadopted/publishedorreused/publishedterminal states; do not call it for either branch. If an OS-level kill leaves a stale vault lock, follow the normalunlockprotocol before rerunning the same reseal operation.
Backend selection / dual-audit / reading windows:
source-convertdefaults to--backend auto— Markdown / born-digital PDF take the lightweight PyMuPDF path; scanned / low-text PDF, DOCX / PPTX take MinerU (fail-closed if absent, never a silent fallback).source-auditruns the MinerU structural review of every PDF and writesreconciliation.json(PyMuPDF thresholds are deliberately broad and are not a single source of truth); production / strict acceptance requires the dual-audit to pass. When the dual-audit flags a structural page PyMuPDF missed, the auto-arbitration sub-step (references/arbitrate.md) automatically decides render/ignore/needs_human and the CLI materializes it into the windows — an un-closed disagreement blocks strict acceptance. When writing each window, read it viashow-window(output carries heading_path / page range / block_ids / risk_flags / assets); do not guess ranges fromsource.mdchar offsets. Block-mode (MinerU / structured) pages keep traceableblock_ids/source_refs/assets.
reopen (incremental backfill of a published source): to add synthesis / native KaTeX re-expressions of formula pages / worked examples to an already-finished source, first
python scripts/pipeline.py reopen --source <src>— it rebuilds the work order against the current vault and resets the state machine toworkorder_ready; theningest-startas usual. lint only promotes this round's new/editedproposedpages; existingpublishedpages stay. New topic/comparison/synthesis/ overview pages carrysource_refsfor ownership, but ownership never substitutes for accounting — put them in some window's--writesor lint blocks them asunaccounted-write.
7. Workflow (load references on demand)
| Phase | File | Responsibility |
|---|---|---|
| A preprocess | references/preflight.md | deterministic chain + dual-audit acceptance (needs_vision / degraded warnings / reconciliation / window coverage) |
| A.5 auto-arbitration | references/arbitrate.md | when the dual-audit flags un-closed disagreements, the agent auto-decides render/ignore/needs_human (structured only); the CLI materializes → the windows carry the assets |
| B0 content routing | references/content-routing.md | after reading chapters.json, route each chapter to a content type (理论/方法/案例/参考/观点) → per-chapter ## 路由表 in digest; advisory — deviations written as [routing-deviation] markers (revision evidence for skill-evolve); purpose.md supreme |
| B+C+D per-window writing | references/write-pages.md | start guard + read chapters.json for whole-book understanding + per-window sub-units U1–U7 + read source images as evidence & re-express natively (never embed) + writing discipline + lint hard rules |
| E synthesis | references/synthesis.md | incremental overview/topic/comparison/synthesis |
| F finish | references/finish-lint.md | ingest-done + lint promote/rollback + derived rebuild |
8. Failure stops / recovery
Any preprocessing step errors; check-write DENY (out of scope / overwrite protection); lint fails;
managed_by: human page conflict; cross-domain promotion candidate; the vault lock is held. Recovery:
after an interruption, re-read chapters.json + the digest ## RESUME block, and re-read
references/write-pages.md before writing any page — an interrupted session has lost the writing
contracts (prose organization, self-test nesting, accounting), and a fresh page's seed scaffold never
substitutes for the contract file; then resume from the next unfinished window (pipeline.py next is
the machine anchor; next --source <src> --resume-packet hands you the structured RESUME_PACKET —
ledger-decided next window + write boundary + digest RESUME + resume-critical excerpt — and fail-closes
on a stale RESUME instead of emitting a half-true packet); otherwise auto-advance and report progress.
9. Acceptance criteria
Scope: these are pipeline completion criteria (structure / order / safety / provenance-accounting). Content acceptance is not this session's call: it requires an independent kb-qa content-fidelity pass plus a human decision on its report (
references/finish-lint.md); the ingesting session reports "published, pending content acceptance" and never declares acceptance for its own writing.
- Preprocess:
workorder.yamlgenerated;ingest-starttook the lock + the stale-registry check passed; for PDFs,source-auditproducedreconciliation.json+evidence.json, every dual-audit disagreement was arbitrated + materialized, and strictpreflight-evalpasses bothdual_auditandcheck_evidence_bundle(the windows carry the source images for arbitrated pages). - Writing: every page follows
check-write → edit(existing-page ALLOW atomically preserves the first baseline;window-doneandlintverify it), page_rules self-check 0 violations, every non-source page in awindow-done --writes. - Synthesis (phase E mandatory): overview updated (not a bare link list) + at least one topic/comparison/synthesis, all in
--writes; otherwiselintreportsL7-synthesis-missingand rolls back. - Finish:
lintpasses (promoted into the index), or failures land inReview-Queue/and the round is rolled back. - Adoption alternative: dry-run reports
byte-zero-write; integrity violations must be zero, while legacywiki_gatecontent debt may remain visible as warnings. Apply rebuilds derived artifacts before recordingadopted/published, preserves existing knowledge-page bytes, and reports all three ingest-ledger counts as zero. A fully verified exact rerun is a whole-tree byte no-op; later live-page drift is warning-only and leaves the historical manifest/evidence unchanged, while archive/evidence/source/adoption-state drift remains a hard stop. - Reuse alternative: dry-run is byte-zero-write and proves origin read-only published truth, PDF SHA, every
concept/topic page hash, the set-equal exactly-once mapping and the zero-mapping non-attributions. Apply preserves every
existing target-page byte, rebuilds derived artifacts before
reused/published, and keeps all three ingest ledgers at zero. Exact replay (including from evidence mapping) is whole-tree byte no-op; target live drift is warning-only, while origin/mapping/evidence/source/reuse-state drift is a hard stop. - Reporting: quote the promoted count from
lintseparately; useingest-stats --jsonpage_inventory.total/by_typefor the complete delivered inventory — never usepages_estimateas the delivery total.
Gives 0 of the 12 instructions most note taking skills give
Counted across 686 of the 876 authors here whose files we hold, read 2026-08-06
- include a visual element on every slidein 44 of 686, across 13 files
- use wikilinks for internal vault linksin 35 of 686, across 11 files
- commit to a single visual motif across every slidein 34 of 686, across 9 files
- read pptxgenjs guide before creating presentations from scratchin 30 of 686, across 6 files
- keep 0.5 inch minimum marginsin 30 of 686, across 7 files
- use subagents to visually inspect rendered slidesin 30 of 686, across 6 files
- re-verify affected slides after every fixin 27 of 686, across 5 files
- run content QA checks before declaring successin 26 of 686, across 3 files
- Use Markdown links for external URLs onlyin 26 of 686, across 10 files
- pick a bold topic specific color palettein 24 of 686, across 2 files
- read editing guide before editing existing presentationsin 23 of 686, across 1 file
- use one dominant color across all slidesin 23 of 686, across 1 file
Said here and by no other author read
- organize the source concept-first
- use the work-order transaction protocol
- confirm source id and domain with the user
- run commands from the project root
- process windows sequentially in chapter order
- read hard-page source images as evidence
Grouped from the skills themselves: near-identical wordings counted once, and counted by distinct author, so one author publishing three of these counts once.