Fill the empty Purpose cells of a directory `AGENTS.md` tree with one-line LLM summaries (one subagent per file, plan-then-confirm, cap 50 rows/run). Use for a path-only `kb dox init` tree, or when asked to "describe the tree", "fill AGENTS.md purposes", or "populate the kb corpus".
Install
npx skillscat add blackbelttechnology/pi-agent-dashboard/dox-describe Install via the SkillsCat registry.
dox-describe
Turn a path-only directory AGENTS.md tree into a searchable kb corpus. A freshkb dox init tree carries rows shaped | `file.ts` | | — the Purpose cell is
empty, so the agents retrieval lane (the one file-lookup queries depend on)
finds nothing. This skill fills those cells with one-line, caveman-style
purposes, one subagent per AGENTS.md.
Read-only first: the CLI enumerates empty rows; the LLM only ever writes a
Purpose cell. The parent never edits an AGENTS.md itself, and a subagent edits
only the single file it was assigned.
Step 1 — enumerate the empty rows
kb dox describe --list --jsonParse { groups: [{ agentsPath, subjects: string[] }], total }. Each group is
one AGENTS.md; each subject is a path whose Purpose cell is empty. Nothing to
do when total === 0 — say so and stop.
Step 2 — present the plan and confirm
Show the user, then WAIT (ask_user, confirm) for approval before any write:
- number of
AGENTS.mdfiles (groups) and number of rows (total); - a rough cost estimate (≈ rows × one short file read, plus one subagent per
group; state it is a rough bound, not a promise); - the per-run cap: 50 rows. Rows beyond the cap are DEFERRED to a re-run
(the walk is empty-cells-only, so a re-run is resumable by construction); - any row whose subject file is missing or unreadable (report, do not assign).
Never start fan-out without an explicit yes.
Step 3 — fan out ONE subagent per AGENTS.md
Cap concurrency at 2 in flight (the extension schedules a debounced reindex
on every markdown write, and every subagent contends on the single SQLite index;
≤2 keeps SQLITE_BUSY recoverable — the parent's final reindex is
authoritative). Skip groups whose rows are entirely past the cap.
Spawn with an inline Agent label (write-capable, parent defaults) andmodel: "@fast" — one-line summaries do not need the parent's model. Do NOT useExplore — it is read-only and cannot fill cells.
Each subagent's task must include:
- the absolute
AGENTS.mdpath and its assigned subjects (cap 50 total across
all groups for this run); - must read every file it describes — never guess from the filename;
- the row rules:
- ONE line per row, exactly the schema
| `file` | purpose |; - purpose ≤ 200 chars, caveman style: short declarative fragments, drop
articles/copulas, subject → verb → object; - name key exports / contracts / params verbatim (
symbolName, paths, env
vars); concrete tokens over prose; - CONDENSE, never promote to a
<File>.AGENTS.mdsidecar — sidecar splitting
is the parent's/scripts/split-large-agents.mjsjob; - edit ONLY its own
AGENTS.md; do not touch any other file; - write the purpose into the EXISTING row (same line, same path cell) — do not
add, delete, or reorder rows; - a subject file that cannot be read (missing, binary, 0-byte) → leave its
Purpose cell EMPTY and report it back; never invent a purpose.
- ONE line per row, exactly the schema
Step 4 — verify, report, reindex
kb dox lint— must be clean. On a finding, hand it back to the subagent
that owns thatAGENTS.mdto repair or revert its OWN file (the parent never
edits a tree file). Re-run lint after the repair.- One final reindex so the new purposes are searchable:
(The extension's debounced reindex is best-effort under contention; thiskb index
explicit pass is authoritative.) - Report to the user: rows filled, rows deferred (cap), unreadable rows left
empty, and — when deferred > 0 — "rundox-describeagain to fill the rest".
Re-running is idempotent: --list returns only rows still empty, so a second
run writes nothing when everything is filled.
Headless escape hatch
For very large trees (well past the 50-row cap), the plan-then-confirm loop is
boring to babysit. You may instead drive workers with parallel headless pi
processes (pi -p --model <fast-ref> "<task>", where <fast-ref> is thefast role's provider/id from list_roles — the CLI takes no @role), one
per AGENTS.md, then run steps 4.1–4.3
yourself. This is an escape hatch, not the default: it skips the interactive
confirm, so the CALLER owns the cap and the kb dox lint gate.
Pitfalls
- Do NOT let a subagent "improve" neighbouring cells or reformat the table — the
parent's--listwalk andkb dox lintboth depend on the exact row shape. - Do NOT fan out more than 2 at once — concurrent reindex writes can hit
SQLITE_BUSY. - A wrong-but-non-empty purpose is NOT revisited in v1 (no correctness oracle);
a--stalerefresh mode is a follow-up. Read the file before describing it. - Never write a Purpose for a file you could not open — an empty cell is honest,
a guessed one is rot.