codebase-mapping-forge
Skill1 starsChanged 14 days agoMITView on GitHub
Forge a grounded "<project>-mapping" skill from a codebase — the subsystem map, glossary and reality-ledger that say what things are really called in the running system, every name carrying file:line evidence or marked UNVERIFIED. Use when the user wants a mapping/vocabulary skill for a project, wants an agent to learn a codebase's real step names and statuses (routes and integrations are model-curated, not scanned), or to ground business terms before speccing. Always available — it reads code and needs no doc corpus, so it is the default adapt output and the grounding companion the spec skill uses. It fans out one mapper per repo, counts against the code, and audits its own claims before shipping. Triggers "map this codebase", "what is X really called", "build the mapping skill", "ground the names in code". Do NOT use to learn a team's spec-writing style (that is spec-style-forge), edit an existing mapping skill (that is skill-editor), or run the structural gate alone (that is conformance-lint).
In this repository15 other files it gives its agents.
- conformance-lintSkill
- skill-editorSkill
- spec-style-forgeSkill
- honesty-vocabularySkill
- karpathy-guidelinesSkill
- reuse-before-createSkill
- simplicity-firstSkill
- small-diff-surgical-changeSkill
- surface-assumptionsSkill
- trace-to-consumerSkill
- verification-before-advanceSkill
- adversarial-review-loopSkill
- blind-evalSkill
- sandbox-isolationSkill
- skill-improvement-loopSkill
The file
We split this skill into the rules it gives an agent
9 rules. About 0 are common, 3 are distinctive, and 6 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈3
Distinctive · estimate
This author's own choices. Worth a look.
6
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 47
Before any curation, scaffold the names table with the stdlib scan ${CLAUDE_PLUGIN_ROOT}/core/lib/mapping_scan.py — the testable, no-LLM …
- Distinctive: line 98
Keep it a FLOOR, exactly like the names scan:
- Distinctive: line 126
Put this line in every brief: *"You are performing one bounded task for a larger pipeline.
- Very specific: line 144
Start from the scan, enrich by hand: Run ${CLAUDE_PLUGIN_ROOT}/core/lib/mapping_scan.py on the repo first to scaffold the grounded name | …
- Distinctive: line 149
Cite, don't summarize: If it is going in the skill, it came from the code and you can point at the line.
- Very specific: line 165
Count the things you assert: If you are about to write "all", "every", or "8 of 11", run the count yourself with one line of grep.
- Very specific: line 167
Never invent a name: If you cannot find it, the skill says "not found in code — verify before use".
- Very specific: line 177
Write the mapping skill's files from the verified content.
- Very specific: line 189
Conformance-lint (mapping-kind mode): Run node ${CLAUDE_PLUGIN_ROOT}/scripts/conformance-lint.mjs <skill-dir> --repo <repo> — one --repo …
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Codebase mapping forge
You are building a skill that says what a project's systems are really called — a
<project>-mapping skill — by reading the code, not by guessing. It is the always-available half
of adapt: it needs only a checkout, so it runs for every project, and its output is the grounding
companion that spec-style-forge delegates to.
The thing that makes a mapping skill worth having is that every noun it teaches is a real, verified
name in the running system. A skill that confidently asserts a wrong step name is worse than no
skill: it launders a hallucination into every downstream use of it. So this pipeline is built around
one idea: ground every name in file:line, count don't estimate, then try to break your own work
before shipping it. The dominant failure mode is not outright invention — it is confident
restatement with the provenance, the denominator, or the exact bytes stripped out. Nearly every rule
below puts one of those three back.
The forged skill conforms to ${CLAUDE_PLUGIN_ROOT}/core/schema/SKILL.schema.md (house shape, progressive disclosure, the
mahoraga: {kind: mapping, grounding: file-line} block, a provenance: regenerate command).
What the mapping skill contains
A self-contained skill directory the team uses in any future conversation. Its natural contents:
| File | What it holds |
references/subsystem-map.md | The vocabulary index — scaffolded by ${CLAUDE_PLUGIN_ROOT}/core/lib/mapping_scan.py then curated: the canonical name | kind | evidence table (every row a file:line or UNVERIFIED) covering repo inventory · screens/routes · steps/states · status enums (verbatim, complete) · parameters · jobs · integrations, plus a ⚠️ aliases & traps section (display name vs identifier, near-duplicate names — the most expensive defect class) |
references/oracle-library.md | The behavioural-oracle floor — scaffolded by ${CLAUDE_PLUGIN_ROOT}/core/lib/oracle_scan.py: the oracle | expected | tier | evidence table of real assertions mined from the repo's own tests, each WITNESSED at a test-file:line, stubs classified out, headed by the counted Behavioural grounding: denominator (real / total / files). A different table from subsystem-map.md (one fact, one home) — see the behavioural-oracle floor below |
references/glossary.md | Domain terms defined operationally (how the system computes the thing, not a dictionary gloss), each with evidence; where a term has a business meaning and a code meaning, give both |
templates/reality-ledger.md | The grounding worksheet: business term → real name → kind → exists? → file:line evidence |
scripts/ (optional) | A thin wrapper so the map rebuilds in one command; the canonical regenerate command is python3 ${CLAUDE_PLUGIN_ROOT}/core/lib/mapping_scan.py <repo> --lang <lang>, which becomes the skill's frontmatter provenance |
SKILL.md is a short router (< 500 lines) whose Grounding step is the point of the whole skill. Keep
one fact, one home (every fact in exactly one file; others cross-link, never restate) and one
level deep (every reference links directly from the router).
The deterministic grounding scan (do this first)
Before any curation, scaffold the names table with the stdlib scan ${CLAUDE_PLUGIN_ROOT}/core/lib/mapping_scan.py — the
testable, no-LLM floor the whole skill stands on:
python3 ${CLAUDE_PLUGIN_ROOT}/core/lib/mapping_scan.py <repo> --lang <lang> --format md > references/subsystem-map.mdIt walks the repo (git-tracked + unignored files in a work tree, minus build-artifact dirs; Python via stdlib
ast, TS/JS/Java/Go by pattern) and emits every defined name — functions, classes, methods,
UPPER_CASE constants, enums and their members, types — each with a real file:line, plus the
Regenerate: line that becomes the skill's provenance and a Coverage: line naming any recognised
language — or unparseable file — this run did not scan. That output is exactly the
name | kind | evidence table the mapping-kind lint validates, so the map is grounded by
construction: the scan cannot emit a name it did not read.
If it exits 3 — the dominant or requested language has no extractor (UNSUPPORTED), the requested
one has no files, or the requested one is under 10% of the repo's source (PARTIAL) — do not
hand-write a table to fill the gap. Either scan the part it can read (--lang <scannable language>
--allow-partial, as the error suggests) and record the rest as unscanned in
## Confidence and coverage, or rerun with --lang <lang> --allow-generic and audit every row:
that grep skips keywords and common type/modifier words but is low precision (local variables and
build-script constants appear).
Curate on top of the scan, never under it. The scan gives verified defined names; you add what a
pure scan cannot — the ⚠️ aliases & traps, the operational glossary, the enum-completeness audit, and
the referenced-but-undefined integrations (marked UNVERIFIED). Curation may reorder, group and
annotate rows, but must never weaken an evidence cell: a row the scan grounded stays grounded. The
scan is deterministic (no timestamps/random), so re-running it to refresh the floor diffs cleanly.
The behavioural-oracle floor
Names are not the only thing an agent guesses; it also guesses what the code is supposed to do —
and "there are tests" is not the same as knowing what they pin down. So scaffold a second grounded
table beside the names table — the behavioural-oracle library — from the repo's own tests with the
stdlib scan ${CLAUDE_PLUGIN_ROOT}/core/lib/oracle_scan.py:
python3 ${CLAUDE_PLUGIN_ROOT}/core/lib/oracle_scan.py <repo> --lang <lang> --format md > references/oracle-library.mdIt walks the repo's test files and emits, per test, one oracle | expected | tier | evidence
row: a real assertion becomes a WITNESSED oracle carrying the asserted literal in expected and
the test-file:line it was read at; a test with no concrete assertion (empty, pass, assert True,
existence-only matchers) is classified STUB and does not count. The table is headed by the
Behavioural grounding: line — <real> real / <total> tests / <files> files (stubs: <stub>).
That counted denominator is the honest measure of behavioural grounding — read it, don't skip it. A repo can be thick with test files and still ground very little real behaviour; the denominator is what stops "there are tests" from being mistaken for "the behaviour is pinned down." Report it the way you report the names count: with its population and denominator, never an estimate.
Keep it a FLOOR, exactly like the names scan:
- Witnessed literals +
file:lineonly. A WITNESSED row is a literal the scan actually read in an assertion at a line it can point at — nothing inferred. - STUB is a counted absence, not a verdict. It records "no real assertion found", not a judgement about test quality.
- The interpretation stays agent-time. The scan never writes what a test proves; that inference is authored by the agent at ticket time, against this floor, never baked into the skill.
- A different table, its own home.
oracle-library.mdsits alongsidesubsystem-map.md, does not replace it, and leaves the mapping-kind conformance lint unchanged — that lint still validates the names table, not this one (one fact, one home).
Pipeline
Phase 0 Recon — ONE repo tour by hand. Fix the territory before any fan-out. ⛔ GATE
Phase 1 Map — one mapper subagent per repo; deliverable is VOCABULARY with file:line
Phase 2 Converge — resolve contradictions; count things yourself ⛔ code beats analysis
Phase 3 Synthesise — write the mapping skill from verified content
══ FREEZE #1: snapshot + hashes. The audit reads the snapshot, not the live tree.
Phase 4 Verify — adversarial claim audit against the snapshot; conformance-lint ⛔ GATE
Phase 4b Fix — apply findings per FACT, in one pass; re-snapshot (FREEZE #2)
Phase 4c Re-audit — against snapshot #2, at most TWO rounds, then ship with open items named
Phase 5 Ship — report + record what is known-unverifiedWork in your scratchpad, not the team's repo. Expected subagent count for a normal run: 1 mapper per repo, capped at ~3 — map the repos the project actually spans; do not fan out further. Put this line in every brief: "You are performing one bounded task for a larger pipeline. Do not invoke a forge skill and do not spawn subagents of your own." (this skill's own description is pushy and self-triggering — the recursion guard matters).
Phase 0 — Recon (do this yourself) ⛔ GATE
A wrong assumption here poisons every downstream mapper. For each repo the project spans (from
PROJECT.yaml repos[]): identify its territory — by package/route/table-name prefix or directory —
and confirm it is checked out locally. A slice of a monolith is common: scope every grep to the
slice and say so. Note the default branch and how current the checkout is. Do not fan out until you
can state, in one paragraph, which repos are in scope and how you will scope each one.
Phase 1 — Map (one mapper per repo)
Fan out, one agent per repo. The deliverable is vocabulary: the real step names, statuses,
parameters, screens, tables, jobs, document types, enum values — each with a file:line. Rules
that make it trustworthy:
- Start from the scan, enrich by hand. Run
${CLAUDE_PLUGIN_ROOT}/core/lib/mapping_scan.pyon the repo first to scaffold the groundedname | kind | evidencetable, and${CLAUDE_PLUGIN_ROOT}/core/lib/oracle_scan.pyto scaffold the behavioural-oracle floor (references/oracle-library.md); hand-grounding then begins where the scans stop (aliases, complete enum families, integrations), never by re-deriving what they already grounded, and never by inferring what a test proves. - Cite, don't summarize. If it is going in the skill, it came from the code and you can point at the line. A summary is a receipt, not evidence.
- Complete the enumerable families. Status enums, step/state inventories and parameters go in
verbatim and complete, with the shell command that regenerates them (verify the glob covers the
whole tree; quote
--includeglobs). - Flag aliases and traps hard. Display name vs identifier, near-duplicate names, delegating aliases — the most expensive defect class.
- Vocabulary shared with the platform layer (forms, grids, workflow primitives) belongs in the map too, marked platform-wide.
Phase 2 — Converge ⛔ code beats analysis
The mappers will disagree with each other and with your notes. You resolve it, and the code wins.
- Code beats analysis. A subagent's map is secondary evidence — if it asserts a route the router contradicts, the router is right. Verify any claim before you put it in the skill.
- Count the things you assert. If you are about to write "all", "every", or "8 of 11", run the
count yourself with one line of
grep. Never assert a count you did not run. - Never invent a name. If you cannot find it, the skill says "not found in code — verify before
use". An honest gap beats a confident fabrication. Mark each name EXISTING (
file:line) / NEW / UNVERIFIED. - No local checkout for a repo? Its slice of the map is built from documentation and marked
UNVERIFIEDthroughout, and the skill's grounding step becomes "verify against the running system or ask". Say plainly this is a materially weaker skill. The documentation-only degraded mode is not generalized yet.
Phase 3 — Synthesise → FREEZE #1
Write the mapping skill's files from the verified content. One fact, one home; one level deep;
a ## Contents TOC on any reference over ~100 lines; cite file:line on everything; mark the
unverified. Prescription vs description: where the skill instructs something the code does only
some of the time, label it "improves on observed practice" — never present a prescription as an
observed convention. Then freeze: snapshot the skill + record hashes; the audit reads the snapshot
so nothing moves under it.
Phase 4 — Verify ⛔ GATE
- Adversarial claim audit. A second agent (not the author) checks every factual claim against
the code and reports
CONFIRMED / OVERSTATED / FALSE / UNSUPPORTEDwith evidence. Brief it to be hostile; expect it to find defects — that is the healthy outcome, not a sign something broke. - Conformance-lint (mapping-kind mode). Run
node ${CLAUDE_PLUGIN_ROOT}/scripts/conformance-lint.mjs <skill-dir> --repo <repo>— one--repoper repo for a multi-repo map (seeconformance-lint). Because the forged skill's frontmatter ismahoraga: {kind: mapping, grounding: file-line}, the linter selects its mapping-kind mode (real, not aspirational — it skips the spec-blueprint manifest and instead checks: thename | kind | evidencetable exists inSKILL.mdorreferences/subsystem-map.md; every data row's evidence matchespath:lineor is exactlyUNVERIFIED; everypath:lineresolves under--repoto a real line carrying the row's name; aRegenerate:/provenancecommand is present; ≥3 data rows). It must pass before ship — a curated row whose evidence drifted fails here.
Fix per fact, not per file. For each finding, grep -rF the whole skill for the claim and fix
every instance — that one discipline prevents most second-round defects. Gate: do not ship while
any FALSE claim about a system name survives — those are the ones that turn into wrong code.
Convergence: apply everything (round 1), then only FALSE name/number/citation findings (round 2),
then stop — anything still open goes into the skill's ## Confidence and coverage section as a
named, unresolved item. An honest partial skill is usable; one polished in an unbounded loop is just
expensive.
Phase 5 — Ship
Report: where the skill is and its file inventory; audit numbers (claims checked, defects found,
defects fixed); and what remains unverified, plainly. Place the skill where the work happens — if
the project spans several repos, in their common parent so it is reachable from any of them; a skill in
the wrong directory is invisible. Offer the obvious next step: forge the spec skill on top of it with
spec-style-forge, or run the mapping skill on a live lookup.
Guardrails
- Read-only on the team's code (
security.forge_read_only) — this pipeline never writes to the project's repos, tracker, or docs. - Never let a summary become evidence, never assert a count you did not run, never invent a name — mark it EXISTING / NEW / UNVERIFIED.
- Do not ship without the audit and a green conformance-lint.
Related skills
spec-style-forge— the doc-corpus half; its Grounding phase delegates to the mapping skill this forge produces.skill-editor— surgically edit a mapping skill after it ships.conformance-lint— the structural + mapping-kind gate this forge runs before shipping.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

