"Ingest source files into the wicked-estate knowledge store as cited chunks. Handles text files (md, txt, csv, html, json, code) with deterministic chunking and binary documents (pdf, docx, pptx, xlsx, png, jpg, gif, webp) via LLM vision — the agent extracts and chunks, estate persists and ranks. Use when: dispatched by the wicked-garden-mem skill's ingest action, or directly for 'ingest this file', 'add this document to the knowledge base', 'index this directory', 'learn from this pdf'."
Install
npx skillscat add mikeparcewski/wicked-garden/wicked-garden-mem-ingest Install via the SkillsCat registry.
Mem Ingest Worker
This skill is designed to run as an isolated worker; when your harness cannot fork, run it inline and keep its output separate from the caller's.
You ingest source files into the wicked-estate knowledge store so laterknowledge.recall / cited-answer calls can return them with source
citations. This ports the brain-era ingest pipeline (FOLD-2, Phase 5-S7)
onto estate: you read, extract, and chunk (DEC-R: the agent is the
reasoner); the engine writes and ranks (knowledge.ingest /knowledge.write — deterministic, never calls a model). Estate's embedded
method card skill://knowledge-ingest/SKILL.md is the chunking doctrine
this pipeline follows.
Runtime
Script-backed steps use the wicked-garden launcher: wicked-garden run <plugin-root-relative path, e.g. scripts/…> [args]. It is on PATH after npm i -g wicked-garden; otherwise use npx wicked-garden run …; inside a wicked-crew run it is "$WICKED_GARDEN_ROOT/scripts/wicked-garden".
If none of these is available, or Python 3 is missing, skip the script-backed step, say so, and follow the manual alternative where one is given next to it — never invent the script's output.
Relative paths in this skill are relative to the directory that contains this SKILL.md.
Parameters
- source (required): path to a file or directory
- scope (optional): estate scope, default
project:<cwd-basename> - title (optional): document title, default derived from the filename
The write seam
All writes go through the mem backend (stdio shim → estate MCP):
wicked-garden run \
scripts/mem/estate_memory.py ingest -with a JSON body on stdin (chunks are long — never inline them in argv):
{"title": "<doc title>", "chunks": ["<chunk 1>", "<chunk 2>"],
"scope": "<scope>", "source": "<absolute-or-repo-relative source path>"}Rules that make chunks worth storing:
- Self-contained — one idea per chunk (a section, a slide, a sheet, a
table row group). Recall returns chunks verbatim; a fragment that needs
its neighbours is a bad chunk. - Source provenance always —
sourceis what a cited answer cites. An
uncited chunk cannot backwicked-garden-search answer. Never omit it. - For a single standalone fact, use the
writeaction instead
({"content": ..., "class": "concept", "source": ...}).
Step 1 — assess the source
- Single file → Step 2 (text) or Step 3 (binary) by extension.
- Directory → Step 4 (batch).
- Health check when in doubt:
... estate_memory.py health '{}'— on"ok": false, stop and report the degrade (estate binary missing or
store unreachable). Do not fake success.
Text extensions: .md .txt .csv .html .htm .json .py .js .jsx .ts .tsx .sh .rs .go .java .yaml .yml .toml. Binary (vision) extensions: .pdf .docx .pptx .xlsx .png .jpg .jpeg .gif .webp.
Step 2 — TEXT files (deterministic chunking)
- Read the file.
- Split:
- Markdown: on H1/H2 headings; sub-split any section over ~800 words
at paragraph breaks. - Code: one chunk per file (small files) or per top-level
class/function group; prepend a one-linepath — what it isheader so
the chunk stands alone. - CSV/other text: paragraph groups of ~800 words; for CSV keep the
header row with every chunk.
- Markdown: on H1/H2 headings; sub-split any section over ~800 words
- Send title + chunks + scope + source through the write seam (one
ingest
call per file).
Step 3 — BINARY files (LLM vision)
You receive the document natively via Read — examine it visually and
extract content as markdown. This is the one genuinely agent-only stage of
the pipeline; everything around it stays deterministic.
- PDF: one chunk per logical section (or every 3–5 pages).
ReadPDFs
with thepagesparameter for long documents. - PPTX: one chunk per slide or tight slide group; capture speaker-note
intent, not just visible text. - DOCX: one chunk per section heading.
- XLSX: one chunk per sheet; render data as markdown tables (downsample
huge sheets: header + representative rows + totals). - Images: one chunk describing the visual content, plus any legible
text verbatim.
Preserve numbers, names, and tables exactly — a cited answer will quote
them. Then write through the same seam as Step 2, source = the original
binary's path.
Step 4 — directories (batch)
Do NOT ingest files one-by-one in conversation. Write a small Python batch
script to the session scratch dir that walks the tree (skip dotdirs,node_modules, __pycache__, lockfiles), applies the Step-2 chunking to
each text file, and pipes one ingest JSON per file intowicked-garden run scripts/mem/estate_memory.py ingest -. Run it, then:
- Report
files → chunkscounts from its output. - List the binary files it found and vision-ingest the important ones
yourself (Step 3), or hand the list back for the caller to choose.
Step 5 — verify (seeded recall)
Pick 1–2 distinctive phrases from the ingested content and confirm they
come back cited:
wicked-garden run \
scripts/mem/estate_memory.py sources '{"query":"<distinctive phrase>"}'The matching chunk must appear with the right source. If it doesn't,
say so — never report an unverified ingest as done.
Step 6 — report
{N} files ingested, {M} chunks written, scope {scope}- doc_ids returned by the backend
- binary files pending vision ingest (if any were deferred)
- verification: which seeded phrases came back, with their
source