| name | repo-wiki-planner |
| description | Generate a wiki skill (agent-loadable) from repo-intelligence analysis artifacts into the per-repo store at $ARTIFACTS_DIR/skills/{repo-slug}-wiki/ and install it via npx skills add. Also generates viewer.html on demand from ~/.wicked-understanding/ data. Trigger on: "generate wiki", "build wiki", "document this repo", "create the wiki skill", "build docs", "show me the wiki", "open the viewer". Requires analysis artifacts from repo-analyst.
|
repo-wiki-planner
{repo-slug} = the repo name lowercased, with every run of non-[a-z0-9-]
chars replaced by a single hyphen, trimmed of leading/trailing hyphens (e.g.
acme_app → acme-app). The wiki installs as a folder named {repo-slug}-wiki,
and its frontmatter name MUST equal that folder (agentskills rule). This is also
the sibling folder the forge's task skills load via ../{repo-slug}-wiki/refs/....
The assembler (assemble_wiki_skill.py) derives this slug itself for the
frontmatter; use the same {repo-slug} for the staging folder so they match.
Two modes:
| User intent | What happens |
|---|
| "generate wiki", "build the wiki" | Full wiki generation → $ARTIFACTS_DIR/skills/{repo-slug}-wiki/, installed via npx skills add |
| "show me the wiki", "open the viewer" | On-demand viewer only → reads from ~/.wicked-understanding/ |
Mode 1: Generate wiki skill
Input
Scripts ship in their skill's scripts/ directory — invoke them by the path to
the installed skill (no $CLAUDE_PLUGIN_ROOT). Store keying is owned by
repo-analyst's init_understanding.py: use the ARTIFACTS_DIR that repo-analyst
passes when it orchestrates you; if run standalone, repo-analyst installs
alongside this skill — invoke
python3 ../repo-analyst/scripts/init_understanding.py path --repo-root "$REPO_ROOT"
(path relative to this skill's directory):
ARTIFACTS_DIR=$(python3 ../repo-analyst/scripts/init_understanding.py \
path --repo-root "$REPO_ROOT")
Artifacts in $ARTIFACTS_DIR use bare names: survey.md, architecture.md,
domain.md, technical.md, ops.md.
Output location
$ARTIFACTS_DIR/skills/{repo-slug}-wiki/ ← staged in the per-repo store
One location — a sibling of the forge's task-skill folders under
$ARTIFACTS_DIR/skills/, so the task skills' ../{repo-slug}-wiki/refs/... links
resolve. The pipeline installs from here via npx skills add (see Step 4);
nothing is written into the analyzed repo's tree.
mkdir -p "$ARTIFACTS_DIR/skills/{repo-slug}-wiki/refs"
Steps
Step 1 — Read artifacts and write the plan
Read all artifacts from $ARTIFACTS_DIR. Decide the article set (read
references/article-types.md):
Always: product-overview, onboarding-maintainer
Always if domain.md has ≥ 1 Core Entity: domain-reference
If ≥ 2 components: architecture-overview
If API found: api-reference
If ≥ 3 operations (cap 5): capability per feature
If ≥ 3 glossary terms (cap 5): concept-explanation per term
If multi-step ops (cap 3): runbook
The count thresholds above are the first draft of the set. Do not confirm
it with the user — this pipeline must run unattended (CLAUDE.md Mandate: "a
stranger can run it unattended and trust the output"). The set is right-sized by
the agent plan-reviewer in Step 1.5, and a deterministic ceiling
(--max-articles, Step 3) is the runaway backstop underneath it. There is no
human prompt in the normal path.
Write the plan to /tmp/{repo}-wiki-plan.json. Both downstream scripts read it:
{
"repo": "<repo-name>",
"stack": "<primary stack>",
"type": "<service|cli|library|...>",
"generated_at": "<ISO datetime>",
"articles": [
{
"type": "product-overview",
"slug": "<repo>-overview",
"ref_file": "overview.md",
"title": "<Title Case>",
"audience": "both",
"priority": 1,
"source_artifacts": ["survey.md", "domain.md"],
"subject": ""
}
]
}
slug is the article's wiki-system identity (frontmatter + canonical IDs).
ref_file is the stable on-disk filename the wiki SKILL.md and the generated
task skills load — assign it from this table:
| Article type | ref_file |
|---|
| product-overview | overview.md |
| architecture-overview | arch.md |
| api-reference | api.md |
| onboarding-maintainer | onboard.md |
| domain-reference | domain.md |
| capability | cap-{feature-kebab}.md |
| concept-explanation | concept-{term-kebab}.md |
| design-pattern | patterns.md (or pattern-{name}.md if > 1) |
| runbook | ops.md (or runbook-{op}.md if > 1) |
| agent-roster | agents.md |
Step 1.5 — Review the plan for comprehensiveness (agent-judged; replaces the old human confirm)
This is the comprehensiveness gate. It is LLM judgment, not a script —
deterministic mechanics can't decide whether an article set covers a repo or
whether two articles overlap, so this stays an agent step (the repo's hard rule:
agents do judgment, scripts do mechanics). It runs before generating any ref
file (cheap to re-plan; expensive to re-generate) and before the assembler.
No user is asked anything — the agent decides and proceeds.
Re-read the 4 lens artifacts (architecture.md, domain.md, technical.md,
ops.md) plus survey.md, and score the proposed articles[] against them on
three axes. Be brutally honest (CLAUDE.md Voice) — the goal is a set a stranger
can trust, not a long set:
-
COVERAGE — does the set represent everything the lenses actually
discovered? Walk each lens's findings and confirm each is reachable from some
article:
- architecture.md components / entry points / layers →
architecture-overview
(and capability for the load-bearing flows);
- domain.md Core Entities + Core Operations →
domain-reference + the
capability articles for the highest-impact operations;
- technical.md API surface →
api-reference;
- ops.md multi-step procedures →
runbook;
- domain.md Glossary terms that confuse a newcomer →
concept-explanation.
A discovered subsystem/entry-point/domain with no article that covers it
is a coverage gap → EXPAND (add the missing article, assign its ref_file
from the table above and a priority).
-
REDUNDANCY / right-sizing — would two articles say largely the same thing,
or is an article too thin to warrant its own ref (e.g. a capability whose
whole story is two sentences already told in domain-reference)? Merge thin or
overlapping articles → TRIM (drop the redundant one, or fold its unique
point into the survivor as a ## See also link). Prefer one well-grounded
article over two thin ones. Right-sizing is the point — not hitting a number.
-
EVIDENCE-WARRANT — is each article backed by enough findings to clear
its confidence rubric (references/article-types.md)? An article whose primary
source artifact is missing or whose section mapping would be mostly inferred
(would land < 0.65) is not warranted yet → TRIM it, or downgrade it to a
## See also mention inside a warranted article. Don't ship an article that
would publish at LOW confidence just to pad the set.
Apply the verdict — APPROVE (no change), TRIM (remove articles), or
EXPAND (add articles) — by editing articles[] in the plan before writing
it. Right-size first; the --max-articles ceiling (Step 3) is only a backstop
for a pathological count, not the mechanism you rely on here.
After any TRIM you MUST reconcile cross-references — this is load-bearing.
Removing an article removes its canonical ID, so any surviving article whose
## See also (or frontmatter references:) points at a trimmed canonical ID
would fail the broken_reference lint (references/wiki-contract.md lint table)
and break the unattended run. So, for every article you trim:
- note its canonical ID (
{REPO}-{PURPOSE}-{NOUN}, e.g. {REPO}-CAP-REFUND);
- when you generate the surviving articles in Step 2, instruct each subagent
not to emit a
## See also row or references: entry pointing at a trimmed
ID (give it the trimmed-ID list in its brief);
- if you fold a trimmed article's point into a survivor, the survivor links the
survivor's IDs only — never the dropped one.
The forge's task skills link only the 7 fixed stable refs
(
overview/arch/api/onboard/domain/patterns/ops.md) and never cap-*/concept-*,
so trimming a capability/concept-explanation can only dangle an intra-wiki
See also — that is exactly what this reconciliation closes.
Record the verdict in your generation log (not in any article): the final article
count, what you EXPANDED/TRIMMED and why (cite the lens finding), and the trimmed
canonical IDs you reconciled. If --max-articles later trims more (Step 3), it
writes a *.trim-report.json with the same trimmed_canonical_ids shape — apply
the same See also reconciliation to those before the lint in Step 5.
Step 2 — Generate article ref files (dispatch one agent per article)
Articles are independent — dispatch one subagent per article, in a single
batch when parallel subagents are available; otherwise generate them yourself
in priority order. Give each subagent this brief:
Generate the `{type}` wiki article titled "{title}"{ for subject "{subject}"}.
Read the format contract FIRST (bundled with this skill — paths relative to
this skill's directory):
references/wiki-contract.md
Then the content mapping for this type:
references/article-types.md (§ {type})
Ground every section in these artifacts (the ONLY source — no memory/search):
{for each source_artifact}: {ARTIFACTS_DIR}/{artifact}
Write the finished article (frontmatter + body + closer) to:
$ARTIFACTS_DIR/skills/{repo-slug}-wiki/refs/{ref_file}
Pass all 5 lint self-checks (log to your output, not into the article).
Use only [src: file:{path}] citations.
The wiki batch is exactly these canonical IDs: {list every article's canonical
ID that survived Step 1.5}. Your `## See also` rows and frontmatter
`references:` MUST only reference IDs in that list. Do NOT reference any of these
TRIMMED IDs (they were removed from the plan and would fail the broken_reference
lint): {trimmed_canonical_ids from Step 1.5, or "(none)"}.
Step 3 — Assemble the wiki SKILL.md router
Read references/wiki-skill-template.md, then run the deterministic assembler
(it extracts the quick-reference tables from artifacts and templates the router).
assemble_wiki_skill.py is bundled with this skill — invoke it relative to this
skill's directory:
python3 scripts/assemble_wiki_skill.py \
--plan-file /tmp/{repo}-wiki-plan.json \
--skill-staging "$ARTIFACTS_DIR/skills/{repo-slug}-wiki" \
--artifacts-dir "$ARTIFACTS_DIR" \
--max-articles 8
--max-articles (default 8) is the deterministic runaway backstop, not the
primary gate — the agent reviewer in Step 1.5 already right-sized the set, so in
the normal path this caps nothing. It fires only if a pathological run still
proposed more than the ceiling; then it deterministically drops the
lowest-priority capability/concept-explanation articles (never an always-on
or structural one) and writes /tmp/{repo}-wiki-plan.trim-report.json listing the
trimmed_canonical_ids. If that file appears, reconcile it like a Step-1.5
trim before the Step 5 lint: drop any surviving article's ## See also /
references: row pointing at a trimmed ID. Pass --max-articles 0 to disable the
backstop, or --interactive to have it print the over-cap set for an operator
(off by default — the pipeline runs unattended).
Step 3.5 — Validate the package installs
Before installing, prove the real tool accepts every skill in the package. A
skill whose frontmatter npx skills can't parse is silently dropped (exit
0, never installed) — most often a plain-scalar description: containing :
("Nested mappings are not allowed in compact mappings"). The assembler emits the
wiki's description: as a folded block scalar (>) for exactly this reason, but
the forge's sibling task skills must too — so check the whole package. This count
check is mandatory before npx skills add … --all:
npx -y skills add "$ARTIFACTS_DIR/skills" --list
Confirm the "Found N skill(s)" it reports EQUALS the number of skill folders
under $ARTIFACTS_DIR/skills/ (count them:
ls -d "$ARTIFACTS_DIR"/skills/*/ | wc -l). If N is fewer, the package has
invalid frontmatter — FAIL loudly, name which folder(s) were dropped (the
ones absent from the --list output) and fix that frontmatter (make
description: a folded block scalar >) before installing. Do not install
a partial package.
Step 4 — Install via npx skills add
The assembled wiki skill is installed alongside the forge's task skills. The
orchestrator runs this once after forge + wiki both complete; when this skill
runs standalone, run it here (after the Step 3.5 count check passes). The user
is not asked to run it:
npx skills add "$ARTIFACTS_DIR/skills" --all
Step 5 — Lint and confirm
Lint self-check (from references/wiki-contract.md) across the generated refs:
- No duplicate
canonical_for IDs
broken_reference: every references entry / ## See also row resolves to a
canonical ID present in this batch. This is where a missed trim
reconciliation surfaces — if Step 1.5 trimmed an article, or
--max-articles wrote a *.trim-report.json (Step 3), verify no surviving
article still references a trimmed canonical ID. Fix any that do by deleting
the dangling ## See also row and its references: entry, then re-lint. This
must be clean before you confirm the run — a dangling ref is the load-bearing
failure class the trim path exists to avoid.
- Pages > 80 lines have ≥ 3
references
- Every
canonical_for page has ## Purpose
Tell the user:
Wiki skill written to $ARTIFACTS_DIR/skills/{repo-slug}-wiki/ and installed via
`npx skills add "$ARTIFACTS_DIR/skills" --all`.
{N} articles. Run "show me the wiki" to open the viewer.
Mode 2: On-demand viewer
When the user says "show me the wiki", "open the viewer", or "view the docs":
generate_viewer.py is bundled with this skill — invoke it relative to this
skill's directory:
python3 scripts/generate_viewer.py \
--skill-dir "$ARTIFACTS_DIR/skills/{repo-slug}-wiki" \
--output "$ARTIFACTS_DIR/viewer.html"
Then open $ARTIFACTS_DIR/viewer.html for the user (present the file, or
print the path for them to open in a browser).
The viewer is always generated fresh from the latest refs — it is never
stored in the repo itself, only in ~/.wicked-understanding/.
Refresh mode
When analysis artifacts have been updated:
- Re-run only articles whose source artifacts changed
- Re-run
assemble_wiki_skill.py to update the SKILL.md quick reference
- Re-install with
npx skills add "$ARTIFACTS_DIR/skills" --all
- Regenerate viewer on next view request