Corpus ingestion
Skill omaralmansoori/claude-sdlc-kit/skills/corpus-ingestion
Convert a multi-format BRD/FRD/spec corpus (.docx/.pptx/.pdf/.xlsx/.vsdx, often bilingual or scanned) into an agent-searchable markdown knowledge base. Use at the start of a "from BRD to tested app" build, when the requirements arrive as Office documents and you need a grep-able, provenance-tagged KB that downstream agents can cite. Also use when adding a new source document to an existing KB. Do NOT use for ordinary code or single-file conversions.From its SKILL.md
npx -y skills add omaralmansoori/claude-sdlc-kit --skill corpus-ingestionAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 3 stars3 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.
SKILL.md
5.5 KB, as published. Nobody here has run it
corpus-ingestion
The first pillar of the kit. A build can only be as good as the requirements
agents can actually read. This skill turns a pile of binary Office documents
into a mirrored tree of grep-able markdown that any sub-agent can search by
native requirement ID and cite with file:line provenance — the substrate the
whole "BRD to tested app" methodology stands on.
The tooling lives in ../../toolkit/ingestion/. This skill is the method; the
scripts are the implementation. Don't reimplement them inline — invoke them.
When you (Claude) invoke this skill
You have a directory of source requirements (.docx, .pptx, .pdf, .xlsx,
.vsdx, maybe .html), and the next step in the build needs agents to read and
cite those requirements. Produce the KB first, then proceed to bootstrapping the
development contract.
The format-to-tool map (why a router, not one tool)
No single tool reads everything. The router (toolkit/ingestion/ingest.py)
dispatches each file by extension:
| Source | Tool | Notes |
|---|---|---|
.docx .pptx .pdf .html | markitdown | Pinned 0.1.6 on Python 3.13 (3.14 has wheel gaps). Inlines images as base64 data: URIs — the router strips them automatically. |
.xlsx .xls | extractors/xlsx_to_md.py | markitdown does not split workbooks per-sheet cleanly. One markdown table per sheet. |
.vsdx | extractors/vsdx_to_md.py | markitdown cannot read Visio. Recovers shape text + an edge list. |
.md .txt | passthrough | e.g. flow step text. |
| images | copied as-is | dual-capture renders kept beside their .md. |
The procedure
Invoke every script with the extractor venv's interpreter
(toolkit/ingestion/.venv/bin/python), NOT a bare python3: the .xlsx/.vsdx
extractors import openpyxl/vsdx, which are installed only into that venv.
The default KB location is docs/kb/ (the path /kit-bootstrap records in the
generated CLAUDE.md).
- Set up once. Run
toolkit/ingestion/setup.sh. It installs markitdown into an isolated pipx venv (pinned, Python 3.13) and builds a local venv for theopenpyxl/vsdxextractors. - Convert. Run
.venv/bin/python ingest.py CORPUS docs/kb/. It mirrors the corpus tree, dispatches each file, writes a> Source:provenance line atop every generated.md, strips base64 image blobs from markitdown output, and logs a one-line-per-file manifest plus anINGEST-MANIFEST.tsv. It is idempotent and incremental (--forceto rebuild,--dry-runto preview). - Index. Run
.venv/bin/python gen_index.py docs/kb/ --write-manifests. It scaffoldsINDEX.md(one row per document, with detected requirement-ID families) and a per-area_manifest.mdstub (conversion method + a quality-caveats checklist). - Curate by hand what tooling cannot decide: confirm the Excluded/dedup
choices, and fill in each
_manifest.mdquality caveat (degraded OCR, bilingual/RTL). - Verify (the stage-1 → stage-2 gate). Run
.venv/bin/python gen_index.py docs/kb/ --check. It hard-fails on any.mdmissing a> Source:line and warns on docs with no detected requirement-ID family and on_manifest.mdstubs still unfilled. Do not move on to the development contract until it exits clean.
The conventions that make a KB agent-searchable
These are non-negotiable — they are what let a later sub-agent find and cite a requirement with no human relaying context:
- Mirror the source tree so a corpus path maps cleanly to a KB path.
- Preserve native requirement IDs verbatim (
ORG-CM-ACA-BR001,DC_007,FCS-CMD-PRC-1.1) as headings and grep targets. Never rename or normalise. > Source:line atop every generated.md— the provenance anchor.INDEX.md+ per-area_manifest.md— the section map and the conversion record with quality caveats.- Dual-capture process flows: keep the ordered step text + edge list AND the
rendered
.png/.pdf(which preserves branch topology the text loses). Cite both. - Excluded / dedup: skip stale or superseded originals (
*-OLD*,*Old.docx); when a document appears twice, pick one canonical copy and record the choice. Never cite excluded or stale material.
Caveats to flag, never to silently trust
- OCR'd scans mangle numbers and non-Latin scripts. Treat any OCR'd numeric
or clinical value as "verify against the canonical source," and note it in the
area
_manifest.md. - Bilingual / RTL content: confirm text order survived conversion before relying on it.
Adding one document later
Drop it into the corpus, re-run ingest.py (only the new/changed file is
converted), then re-run gen_index.py to refresh INDEX.md. Update the area
_manifest.md if the new document carries a caveat.
Hand-off
When the KB exists with INDEX.md, _manifest.md stubs filled, and native IDs
grep-able, ingestion is done. The build moves to the development contract
(acceptance-criteria ledger, modules registry, design specs, build plan) — see
toolkit/conventions/ and toolkit/contract/.