From doc-wiki
Manage a documentation wiki — generate, ingest sources, query, lint, fix, promote, refresh. Triggers on requests about documentation, knowledge bases, archived queries, ORM mapping, or database schemas, including phrasings like "promote last query", "lint the wiki", or "fix the auth page".
npx claudepluginhub narailabs/narai-claude-plugins --plugin doc-wikiThis skill uses the workspace's default tool permissions.
You are an orchestrator for a multi-skill documentation ecosystem. Your job is to route `/doc-wiki:*` commands to the right combination of TypeScript scripts and sub-agents, compile wiki pages from multiple sources, and maintain the wiki's quality over time.
evals/evals.jsonreferences/autonomy.mdreferences/code-locality.mdreferences/compilation.mdreferences/operations.mdreferences/quality.mdscripts/_cli_args.jsscripts/_cli_args.tsscripts/_frontmatter.jsscripts/_frontmatter.tsscripts/_optional.jsscripts/_optional.tsscripts/_wiki_fs.jsscripts/_wiki_fs.tsscripts/apply_config.jsscripts/apply_config.tsscripts/atlas_gitlog.jsscripts/atlas_gitlog.tsscripts/atlas_orchestrator.jsscripts/atlas_orchestrator.tsCreates new Angular apps using Angular CLI with flags for routing, SSR, SCSS, prefixes, and AI config. Follows best practices for modern TypeScript/Angular development. Use when starting Angular projects.
Generates Angular code and provides architectural guidance for projects, components, services, reactivity with signals, forms, dependency injection, routing, SSR, ARIA accessibility, animations, Tailwind styling, testing, and CLI tooling.
Executes ctx7 CLI to fetch up-to-date library documentation, manage AI coding skills (install/search/generate/remove/suggest), and configure Context7 MCP. Useful for current API refs, skill handling, or agent setup.
You are an orchestrator for a multi-skill documentation ecosystem. Your job is to route /doc-wiki:* commands to the right combination of TypeScript scripts and sub-agents, compile wiki pages from multiple sources, and maintain the wiki's quality over time.
/doc-wiki:* command (or describes what they want in natural language)wiki.config.yaml to understand the wiki's configurationnode) for deterministic operationsAll TypeScript scripts live at: {skill_path}/scripts/ and are compiled to .js siblings via npm run build.
Before first use, install dependencies and build:
npm install
npm run build
Requires Node 20.
Create the directory scaffold and initial configuration.
node {skill_path}/scripts/init_wiki.js --path <wiki-root> --domain "<domain>" --name "<wiki-name>"
This creates: wiki/, raw/, graph/, audit/, log/, outputs/, .wiki-cache/, .wiki-ignore, and a default wiki.config.yaml.
After running the script, create initial files:
wiki/index.md — master catalog (empty, will populate during ingest)wiki/summaries.md — enriched summary index (empty initially)wiki/overview.md — evolving big-picture synthesisInteractive setup that detects the codebase ecosystem and configures wiki infrastructure. This is YOUR reasoning — not a script. Uses parse_config.ts for config I/O and dispatches wiki-orm-agent for ORM/database detection.
Phase 1 — Auto-detect language/framework:
Scan the project root for build files and infer the stack:
| Marker file | Detection |
|---|---|
pom.xml, build.gradle | Java (Maven / Gradle) |
requirements.txt, pyproject.toml, setup.py | Python |
package.json | Node.js / TypeScript |
Gemfile | Ruby |
*.csproj, *.sln | .NET / C# |
go.mod | Go |
Cargo.toml | Rust |
Present findings and ask user to confirm or correct.
Phase 2 — Detect ORM:
Dispatch wiki-orm-agent (via Agent tool) to scan for entity definitions matching shipped ORM profiles:
@Entity, @Table, @Column annotations in .java/.kt filesdeclarative_base(), Base = declarative_base(), mapped_column in .py filesmodels.Model subclasses in models.py / models/ directoriesschema.prisma file with model definitions@Entity(), @Column() decorators in .ts filesDbContext subclasses, [Table] attributes in .cs filesApplicationRecord or ActiveRecord::Base subclasses in .rb filesPresent detected ORM profile and entity count. Ask user to confirm.
Phase 3 — Detect database:
Detect the database engine yourself by reading these files (no subagent dispatch needed):
docker-compose.yml, compose.yaml): image names like postgres:, mysql:, mongo:.env, application.properties, database.yml, settings.py)DATABASES dict in Django, spring.datasource.url in Spring Boot)When live introspection is needed (verify schema matches code), run gather({ prompt: "describe schema for <db>", consumer: "doc-wiki" }) — the db connector inside narai-primitives handles it via the policy gate. Present detected database(s) and connection details (redacted credentials). Ask user to confirm.
Phase 4 — External services Q&A:
Ask the user about each external source integration:
For each "yes", record the connector ID (e.g. jira, confluence) — these go into the enabled allowlist for consumers.doc-wiki in Phase 4b.
Phase 4b — Set up connector access:
/doc-wiki:ingest step 7 calls gather() from narai-primitives, which reads ~/.connectors/config.yaml (user-global) and ./.connectors/config.yaml (repo overlay) to know which connectors are enabled and how to authenticate. If neither file exists yet, walk the user through creating one.
Check existence:
ls -1 ~/.connectors/config.yaml ./.connectors/config.yaml 2>/dev/null
If both are missing — bootstrap from the example:
~/.connectors/config.yaml to access the external services you enabled. I'll generate a starter from .connectors/config.example.yaml."~/.aws/credentials / IAM role)? Or a specific profile?"~/.connectors/config.yaml. Include only the enabled connectors and a consumers.doc-wiki block listing them.connectors keys (no need to invoke loadResolvedConfig() from a one-shot script — a bad YAML file will be obvious).If at least one already exists — just confirm the enabled connectors line up with the user's Phase 4 answers. Suggest edits if there's a gap (e.g., user said "yes Confluence" but no confluence: block exists). Never edit an existing config without explicit confirmation.
Once the file is in place, the user's /doc-wiki:ingest <source> calls will resolve credentials automatically via the connector's own credential loader — doc-wiki never reads or stores the secrets directly.
Phase 5 — Choose autonomy mode:
Present the four autonomy modes and ask user to choose:
Default: balanced.
Phase 6 — Install hooks + scaffold:
Phase 6b — Optional multimodal deps (Q&A):
Ask the user once, before writing the config:
"Your wiki may ingest audio/video files (
.mp4,.mp3,.wav, ...) or YouTube URLs later. The extraction uses two optional tools that aren't installed by default:
faster-whisperfor local audio transcription (≈100 MB model on first use)yt-dlpfor downloading YouTube audio (single binary)Shall I help you set these up?
- Yes, both → record
ecosystem.multimodal.enabled: onand print exact install commands for the user's OS- Yes, yt-dlp only → record
on; still print theyt-dlpinstall command (whisper will be skipped when triggered)- No, skip for now → record
ecosystem.multimodal.enabled: optional(default); multimodal ingests will warn-and-skip until the user installs the tools later- Never ask again → record
ecosystem.multimodal.enabled: off; multimodal ingests are silenced entirely"
When the user says yes, print the exact commands (but DO NOT run them — Claude cannot assume a package manager):
brew install yt-dlp and pipx install faster-whisperpipx install yt-dlp faster-whisper (or the distro's package manager)pipx install yt-dlp faster-whisperwiki.config.yaml with all detected settings (including the ecosystem.multimodal.enabled choice from Phase 6b):
node {skill_path}/scripts/parse_config.js --config <wiki-root>/wiki.config.yaml
/doc-wiki:init automatically:
node {skill_path}/scripts/init_wiki.js --path <wiki-root> --domain "<detected-domain>" --name "<project-name>"
Output: A fully configured wiki.config.yaml with language, framework, ORM profile, database, external sources, autonomy mode, and multimodal preference. Wiki scaffold created if it did not already exist.
Generate a comprehensive wiki for the entire codebase in one orchestrated pass: discover topics, ingest curated sources per topic × facet, synthesize global aggregation pages, validate existing content against current source state, produce drift/cost audit artifacts.
This is a meta-orchestrator over /doc-wiki:ingest. It does not replace the per-source ingest workflow — it batches it across all detected topics and facets, then runs a synthesis pass for the three global pages (wiki/overview.md, wiki/integrations.md, wiki/deploy.md) that aggregate per-topic content.
Synopsis:
/doc-wiki:atlas [--facets <list>] [--scope <topic>] [--yes] [--dry-run]
[--max-cost <usd>] [--since <duration>]
[--validate-mode shallow|full] [--resume]
[--wiki-root <path>]
| Flag | Default | Purpose |
|---|---|---|
--facets <list> | architecture,data-model,environments,api,operations | Per-topic facets to generate. Additive — never deletes pages outside this set from prior runs. |
--scope <topic> | (all detected) | Restrict to one topic for incremental runs. |
--yes | off | Skip phase confirmation gates (CI/unattended). |
--dry-run | off | Show planned ingests + cost estimate, write nothing. Validation pass still runs (read-only). |
--max-cost <usd> | 200.00 | Abort pre-write if estimate exceeds. Re-run with explicit higher value to override. |
--since <duration> | Smart default: timestamp of last op: atlas event in events.jsonl; else all-time (no git log --since). | Window for the gitlog drift scan. |
--validate-mode shallow|full | shallow | shallow: structural + gitlog + semantic on sampled pages. full: semantic on every existing atlas page. |
--resume | off | Continue from .wiki-checkpoint.json (opName "atlas") without prompting. |
Phases:
Detect state — call node {skill_path}/scripts/atlas_orchestrator.js detect-state --wiki-root <root>. Output JSON ({state, atlas_pages, all_pages, last_run_id}) drives the branch:
state == "fresh" → wiki is empty or has < 3 atlas-tagged pages and no prior op: atlas event. Skip Phase 5.state == "existing" → wiki has ≥ 3 atlas pages AND prior atlas event. Run all phases.state == "hybrid" → pages exist but no prior atlas event (manual ingests only). Existing-mode discovery; Phase 5's semantic check skips non-atlas pages (those lacking atlas_run_id frontmatter).Discover topics — union five signals into a deduplicated list:
src/, app/, services/, etc. Skip vendor / node_modules / .git.wiki-orm-agent and group entities into topic candidates (e.g., User → auth; Invoice → billing).wiki/<topic>/ subdirectories (excluding wiki/outputs/ and similar).node {skill_path}/scripts/atlas_gitlog.js classify --wiki-root <root> --since <window> --topics <csv> flags paths whose changes haven't propagated.domain: tooling in wiki.config.yaml AND a top-level commands/ directory): also enumerate commands/*.md slugs as topic candidates so each slash-command can have its own per-command architecture page. The four audience-flavor pages (commands / configuration / getting-started / troubleshooting) are emitted as Phase 7 globals regardless — this signal only adds per-command topic depth.Canonicalize each topic name: lowercase-kebab-case, strip -service, -svc, -module suffixes. Deduplicate by canonical name.
Confirm topics — present the merged list with provenance (which signals contributed each topic). Under balanced+, ask "Generate atlas pages for these topics? [Y/n/edit]". Under auto/autonomous, proceed silently. With --yes, skip the prompt.
Estimate cost:
Plan JSON: { topics, facets, entries: [{topic, facet, sources, output}], created_at }. Source heuristics: architecture → src/<topic>/; data-model → ORM model files; environments → .env*, config/<topic>*; api → controllers/routes; operations → runbooks if present.node {skill_path}/scripts/atlas_orchestrator.js estimate-cost --wiki-root <root> --plan '<plan-json>'.total_estimated_usd > --max-cost, abort with a clear hint to re-run with a higher --max-cost.Validate existing (skip when state == "fresh"):
node {skill_path}/scripts/atlas_validate.js structural --wiki-root <root> --page <page>.node {skill_path}/scripts/atlas_gitlog.js classify --wiki-root <root> --since <since> --topics <csv> returns {stale_pages, uncovered_files, unrelated_files}.--validate-mode shallow, all if full), compute pageHash = sha256(body) and sourceHash = sha256(concat(sources)). Probe atlas_validate.js cache-check; on miss, read page + sources and ask yourself: "Does this page still accurately describe the source(s)? List divergences." Store the result via atlas_validate.js cache-store.wiki/outputs/atlas/<run-id>/drift-report.md.Bootstrap / refresh — for each plan entry not cached:
atlas_orchestrator.js save-plan --wiki-root <root> --run-id <id> --plan '<json>'. The snapshot drives --resume so re-discovery doesn't change scope mid-run.entry.facet == "data-model": dispatch wiki-orm-agent and write the result to entry.output with atlas frontmatter./doc-wiki:ingest <source-list> --output <entry.output> --no-crosslink --no-tag-harmonize (defer post-op hooks to Phase 8)./doc-wiki:refresh --source <source>./doc-wiki:ingest <file> --output <inferred>.scripts/checkpoint.ts with opName: "atlas" to record completed (topic, facet) pairs as <topic>:<facet>. On --resume, load the snapshot via load-plan and skip recorded pairs.Synthesize globals — always regenerated, regardless of --facets and --scope. Seven global pages, in this order; each carries atlas_facet: <slug> plus the run id in frontmatter, and a default audience derived from the slug (see references/compilation.md "Additional frontmatter for atlas pages"):
wiki/overview.md (audience: contributor): node agents/lib/atlas_synthesize.js overview --wiki-root <root> returns a JSON bundle ({sources, text, notes}) prefixed with an audience-routing table. LLM-synthesize the master architecture narrative.wiki/integrations.md (audience: integrator): atlas_synthesize.js integrations --wiki-root <root>. Integration-keyword detection is data-driven from BUILTIN_PATTERNS (in agents/lib/source_registry.ts) plus a curated SaaS list — adding a connector via wiki.config.yaml's ecosystem.agents.custom automatically extends the scan. LLM-synthesize the external-services map.wiki/deploy.md (audience: integrator): atlas_synthesize.js deploy --wiki-root <root>. Hand the bundle to /doc-wiki:ingest <synthetic-source> --output wiki/deploy.md.wiki/commands.md (audience: operator): atlas_synthesize.js commands --repo-root <root> walks commands/*.md plus ### / headings from any SKILL.md. LLM-synthesize a synopsis-table-per-command operator reference.wiki/configuration.md (audience: operator): atlas_synthesize.js configuration --repo-root <root> walks top-level config files (wiki.config.yaml, *.config.*, .env.example, pyproject.toml, …) plus config/ and .connectors/ directories. LLM-synthesize a configuration schema reference.wiki/getting-started.md (audience: new-user): atlas_synthesize.js getting-started --repo-root <root> walks README + package.json scripts + bootstrap files (setup.sh, Makefile, …). LLM-synthesize a numbered first-run walkthrough.wiki/troubleshooting.md (audience: debugger): atlas_synthesize.js troubleshooting --wiki-root <root> walks recent error events from events.jsonl plus the latest atlas drift report. LLM-synthesize symptom → cause → fix triplets.Finalize:
/doc-wiki:lint (no --fix) and append findings to the drift report.node {skill_path}/scripts/atlas_validate.js cross-doc --wiki-root <root> flags pairs of architecture pages that share both ≥1 source path AND ≥1 Mermaid diagram title. Surface as drift findings — one page should own each shared concept (mirrors the "Cross-doc concerns" registry pattern in docs/README.md).node {skill_path}/scripts/atlas_orchestrator.js gap-report --wiki-root <root> --plan '<json>' --run-id <id> --gitlog '<json>' writes wiki/outputs/atlas/<run-id>/gap-report.md enumerating topics-without-pages, facets-without-coverage, source-files-with-no-page, gitlog-uncovered-files, and external-services-without-documentation. Always emitted; non-empty sections are actionable items for a follow-up --scope ingest.wiki/index.md (re-list all atlas pages by facet).node {skill_path}/scripts/event_logger.js log --op atlas --wiki-root <root> --details '<json>' with fields: atlas_run_id, phase_durations, total_cost_usd, pages_generated, pages_refreshed, pages_drifted, topics_covered.clearCheckpoint(wikiRoot, "atlas").wiki/outputs/atlas/<run-id>/cost-report.md with the planned breakdown from estimate-cost plus actual costs from this run's events.Atlas frontmatter conventions — every atlas-generated page carries two extra fields beyond the standard set:
atlas_facet: one of architecture, data-model, environments, api, operations, overview, integrations, deploy.atlas_run_id: timestamp of the generating atlas run (YYYY-MM-DDTHH-MM-SS).These let atlas recognize its own pages on re-runs and skip semantic-cache invalidation when nothing changed.
Page template — every atlas page targets 300–800 lines, splits to sibling subpages beyond, starts with a TL;DR, and ends with auto-managed cross-links. The body section is facet-conditional so each audience gets the structure it needs.
---
<frontmatter incl. atlas_facet, atlas_run_id, sources, summary, audience>
---
# <Title>
## TL;DR
<3–5 sentences>
<body sections — see facet table below>
## How to Go Deeper
<links to deeper sources or sibling pages>
## Related Pages
<auto-managed by crosslink hook>
Body sections by facet (the LLM should follow these structural conventions; they mirror the patterns documented in docs/architecture.md, docs/commands.md, docs/troubleshooting.md):
| Facet | Audience | Body sections (mandatory unless noted) |
|---|---|---|
architecture | contributor | A layered model section + Mermaid flowchart or sequenceDiagram + ## Architecture contracts (numbered load-bearing invariants) |
data-model | contributor | Summary-metrics table + entity↔table mapping + erDiagram (mandatory) + unmapped-tables list |
environments | contributor | Per-env table + secret-resolution rules + network topology |
api | integrator | Per-endpoint synopsis + request/response samples + sequenceDiagram (recommended) |
operations | operator | Runbook with triggers + recovery steps + escalation contacts |
commands | operator | Per-command ## /<command>:<sub> with synopsis + args table + examples (shell blocks) |
configuration | operator | One ## <filename> heading per config file (with a field | type | default | meaning table). Then a top-level ## Credential reference grammar heading (table mapping schemes — env:, keychain:, file:, cloud:aws-secret/, cloud:gcp-secret/ — to resolution targets). Then a top-level ## Resolution order heading (numbered list, most-specific-wins). Then a top-level ## Worked example. Subsections like "credential grammar" must NOT live inside the per-file headings — keep them top-level so readers can link directly. |
getting-started | new-user | Numbered prereq → install → first-command walkthrough |
troubleshooting | debugger | ### Symptom / ### Cause / ### Fix triplets, one per common failure mode |
overview | contributor | Audience-routing table at top, then a layered architecture narrative |
integrations | integrator | Per-service subsection: credentials + actions + sample CLI |
deploy | integrator | Per-target build/deploy sequence + environment matrix |
The audience frontmatter drives the section choice; the atlas_facet drives which Mermaid diagrams are mandatory (per quality_score.ts MERMAID_EXPECTED_TAGS). When an existing page contradicts this template (e.g., an architecture page with ### Symptom headings), Phase 5 surfaces it as a structural drift finding.
Additive re-runs invariant: pages from prior runs are NEVER deleted by a smaller---facets re-run. Validation (Phase 5) runs on every existing atlas page regardless of current --facets. (Re-)generation (Phase 6) only touches facets in the current --facets set that are stale or missing.
Drift handling honors autonomy.mode from wiki.config.yaml:
| Autonomy | Stale (gitlog) | Structural | Semantic | Uncovered files |
|---|---|---|---|---|
conservative | Ask before refresh | Report only | Report only | Ask before ingest |
balanced (default) | Auto-refresh | Auto-fix safe; report structural | Report; ask | Auto-ingest if matches current topic; else report |
autonomous / auto | Auto-refresh | Auto-fix all | Auto-fix; ask on conflicts | Auto-ingest |
Cost ceiling: pre-run estimate aborts if over --max-cost. Mid-run, if cumulative actual exceeds 1.5 × --max-cost, finish the current page, save checkpoint, abort gracefully.
Partial failures — continue, don't halt: gather() already isolates per-step errors; /doc-wiki:ingest errors on a single source are skipped (logged to drift report); LLM timeouts retry once with backoff. Only disk/permission errors hard-abort. Always save the checkpoint before any abort.
Cancellation (Ctrl+C): in-flight LLM call finishes (can't kill cleanly); checkpoint saved; resume hint printed. Re-run /doc-wiki:atlas --resume to continue.
Ingest sources into the wiki. The source can be a file, URL, folder, or pasted text.
Parse config: node {skill_path}/scripts/parse_config.js --config <wiki-root>/wiki.config.yaml
Check cache: node {skill_path}/scripts/cache_manager.js check --path <source-path> --cache-dir <wiki-root>/.wiki-cache/
Extract (if binary): node {skill_path}/scripts/extract_binary.js --input <file> --output <raw-dir>/extracted/ for .pdf / .docx / .pptx. For image / audio / video / YouTube inputs, call node {skill_path}/scripts/extract_multimodal.js <input> --enabled <from-config> instead. When it returns format: "skipped", surface the warning verbatim to the user (it names the missing tool and the exact install command) and continue with the rest of the ingest — do NOT abort the batch. For format: "vision", use the Read tool directly on the image path and write notes to raw/<topic>/images/<name>.md. For format: "audio_video" and "youtube", the dispatcher tells you which tool to invoke next (faster-whisper, or yt-dlp | faster-whisper); run it with the domain-aware prompt seeded from graph_ops.godNodes().
Security check: node {skill_path}/scripts/security_check.js --url <url> (for URL sources)
Read the source fully — no skipping sections
Surface 3-5 takeaways + entity list — your reasoning
Gather context via narai-primitives — a single library call replaces per-agent dispatch:
import { gather } from "narai-primitives";
import { applyMermaid } from "../agents/lib/mermaid_augment.js";
const { plan, results } = await gather({
prompt: "<takeaways + entity list from step 6>",
consumer: "doc-wiki",
});
const augmented = results.map(applyMermaid);
The hub reads ~/.connectors/config.yaml (with consumers.doc-wiki overrides applied), asks the Claude Agent SDK for a plan over the enabled connectors, and dispatches each step in parallel as a connector-CLI subprocess. Errors are isolated per step — results[i].error carries a structured { code, message } instead of throwing. applyMermaid (in agents/lib/mermaid_augment.ts) walks each result and, for the seven structural-action connectors (aws, gcp, jira, confluence, notion, github, db), augments the envelope with a mermaid: { type, title, code } block — exactly the same shape the per-agent wrappers used to produce. The augmented results array is what step 8 consumes.
Per-call setup lives in ~/.connectors/config.yaml; doc-wiki-specific overrides go under consumers.doc-wiki (e.g. enabled connector allowlist, per-connector option overrides). No code change is needed to add or disable a connector — just edit the config.
Compile into wiki page(s) — read references/compilation.md for rules on frontmatter, linking, code locality, claims extraction. --output <relative-path> flag: when present, write the compiled page to the given wiki-relative path verbatim instead of inferring a topic/slug from content. Used by /doc-wiki:atlas to pin per-topic destinations (e.g., wiki/auth/architecture.md) and by direct calls like /doc-wiki:ingest Dockerfile --output wiki/deploy.md. Backward compatible — content-based inference remains the default when the flag is absent.
Auto-generate Mermaid diagrams — write the augmented envelopes from step 7 to a temp JSON file (one envelope per array entry, same mermaid: {type, title, code} shape as before) and splice each into the compiled page:
node {skill_path}/scripts/mermaid_inject.js --page <wiki-page.md> --agents <agent-outputs.json> --in-place
The injector is idempotent — wraps blocks in <!-- wiki-mermaid: <title> start/end --> markers so a second ingest replaces stale diagrams in place instead of stacking duplicates. Envelopes whose applyMermaid step did not attach a mermaid field are skipped silently.
Generate "How to Go Deeper" section — from the page's final sources: frontmatter:
node {skill_path}/scripts/how_to_go_deeper.js \
--sources '<JSON-array-of-source-strings>' \
--enabled <csv-of-enabled-agent-ids>
Classifies each source against the agent registry (builtin + custom agents) and emits one bullet per entry with the exact agent command to run. Pass the enabled agents from wiki.config.yaml so disabled-agent hints are suppressed. Custom agents registered in ecosystem.agents.custom are included automatically. Elides when sources are all local raw/... already in the wiki body.
Update indexes + summaries.md — rebuild wiki/summaries.md deterministically:
node {skill_path}/scripts/summaries_rebuild.js --wiki-root <wiki-root>
Walks every page on disk, reads its frontmatter, emits one ~50-token summary per page, and splices the ## Anti-repetition Memory section from banlist.js. Content outside the <!-- wiki-managed: summaries start/end --> markers is preserved. You still update wiki/index.md yourself (add a bullet to the new page's section).
Log: node {skill_path}/scripts/event_logger.js --op ingest --source <source> --wiki-root <wiki-root> --details '<json>'. When the op dispatched sub-agents, include them in details.agent_calls[] with shape {agent, model, tokens_in, tokens_out, cost_usd, elapsed_ms, status} — event_logger fills in total_tokens_in, total_tokens_out, and total_cost_usd automatically, and /doc-wiki:stats aggregates per-agent cost from those entries.
Run post-operation hooks (crosslink + tag-harmonize) — see below
Folder-source batches (checkpointing): when the source is a folder (many files processed in a loop), use scripts/checkpoint.ts to make the batch resumable:
import { readCheckpoint, recordUnit, clearCheckpoint } from "{skill_path}/scripts/checkpoint.js";
const cp = readCheckpoint(wikiRoot, "ingest");
const done = new Set(cp?.completedIds ?? []);
for (const file of files) {
if (done.has(file)) continue; // resume: skip already-processed units
// ... run steps 2–12 for this file ...
recordUnit(wikiRoot, "ingest", file);
}
clearCheckpoint(wikiRoot, "ingest");
The checkpoint file is <wikiRoot>/.wiki-checkpoint.json, keyed by opName. If the batch is interrupted, re-running /doc-wiki:ingest <same-folder> picks up where it stopped.
Two modes — picked by argument shape:
<question>): the default flow, steps 1–8 below.--from <a> --to <b> instead of a question): shortest-path traversal over graph/edges.jsonl. Skips steps 1–6.wiki/summaries.md (one file, ~50 tokens per page)outputs/queries//doc-wiki:promoteLog token efficiency: node {skill_path}/scripts/event_logger.js --op query --wiki-root <wiki-root> --details '{"tokens_in": N, "tokens_out": M, "reduction_ratio": R}'
node {skill_path}/scripts/graph_ops.js path --from "<concept-a>" --to "<concept-b>" --edges <wiki-root>/graph/edges.jsonl
Returns the typed-edge chain connecting two concepts. Supports --max-hops, --via, --all-paths. Read-only — no autonomy gate, no archive, no synthesis.
Run structural checks via script, then LLM-driven checks yourself:
node {skill_path}/scripts/lint_checks.js --wiki-root <wiki-root>
The script reports: broken links, missing frontmatter (including page-type enum), orphan pages, isolated nodes, code-ref drift, provenance completeness, stale content (>90 days via --stale-days N). Then YOU do: factual contradictions, terminology consistency, missing coverage, query absorption.
Query absorption: after the structural pass, scan outputs/queries/*.md (skipping outputs/queries/.promoted/ and outputs/queries/.deleted/) for archived answers that contain insights not yet captured in any wiki page. For each novel insight, propose (per autonomy mode) either (a) a /doc-wiki:fix on the most relevant existing page, or (b) a /doc-wiki:promote of the archived query. For a focused archive-only triage flow (without the rest of lint), use /doc-wiki:promote --review — same coverage rule, different entry point.
Anti-repetition memory: run node {skill_path}/scripts/summaries_rebuild.js --wiki-root <root> — the rebuilder pulls deprecated claims' failure_reason fields via banlist.buildBanlistSection() and splices them into wiki/summaries.md under ## Anti-repetition Memory. This prevents future ingests from re-exploring abandoned directions. (For the section in isolation, banlist.js build --wiki-root <root> still prints it to stdout.)
Read references/quality.md for scoring rules and references/autonomy.md for how to decide what to auto-fix vs ask the user.
Two modes — picked by argument shape:
--review): bulk-triage many archived answers in one pass with per-item approval.Resolve the target argument with the first matching rule:
| Input form | Resolution |
|---|---|
last, latest, last query, latest query | Most-recent outputs/queries/*.md by mtime |
Bare positive integer N | Nth most-recent (1-indexed; 1 == latest) |
| Existing path (relative or absolute) | Use as-is |
| Single token, no path | Match by filename substring; if 0 or >1 match, list candidates and ask |
| Empty | List recent + prompt the user to pick |
Pick by mtime via ls -1t <wiki-root>/outputs/queries/*.md. Always exclude outputs/queries/.promoted/ and outputs/queries/.deleted/ — these subdirs hold archives that were already triaged.
The slash form /doc-wiki:promote last query is the canonical, deterministic phrasing. The bare form (typed without the slash, e.g. promote last query) is best-effort — the skill description's keyword set covers it, but ambiguous contexts may need a clarifying turn.
wiki/<topic>/<slug>.md (--topic overrides; otherwise infer from content).wiki/index.md and wiki/summaries.md.outputs/queries/.promoted/<filename> so it is not re-suggested by --review or by /doc-wiki:lint query-absorption.--review)/doc-wiki:promote --review [--since <duration>] [--limit <N>] [--topic <directory>]
Bulk archive triage with per-item approval. --since filters by mtime (e.g. 7d, 24h); --limit caps candidates; --topic overrides topic for every promotion in this batch.
For each candidate (oldest first, skipping .promoted/ and .deleted/):
/doc-wiki:lint query-absorption uses: is this insight already on a wiki page?conservative, ask "Already covered by <page>. Promote anyway?").[P]romote / [S]kip / [D]elete archive / [A]bort batch.P → run the single-mode flow (steps 1-7 above) for this archive.D → move to outputs/queries/.deleted/<filename>. Never rm — preserve for audit.A → stop, summarize what was done so far.End the run with one line: <X> promoted, <Y> skipped, <Z> deleted, <W> already-covered.
| Mode | Per-archive prompt | "Already covered" |
|---|---|---|
conservative | Always ask P/S/D/A | Ask before promoting anyway |
balanced (default) | Always ask P/S/D/A | Auto-skip |
autonomous | Auto-promote novel; ask only on conflicts | Auto-skip |
auto | Auto-promote novel; auto-skip everything | Auto-skip |
balanced is the "individual user approval" workflow.
For interactive balanced/conservative use, schedule a reminder with the /schedule skill rather than an unattended run:
/schedule "Run /doc-wiki:promote --review --since 7d" "every Monday at 9am"
For unattended pipelines, set autonomy to auto and schedule the command directly — the orchestrator will batch-promote novel archives without prompting.
See also: /doc-wiki:lint query-absorption (above) — same coverage rule, different entry point.
Re-fetch previously-ingested sources, diff against stored versions, re-compile changed pages.
Batch resumption: use scripts/checkpoint.ts with opName "refresh" the same way /doc-wiki:ingest uses it for folder sources — each source URL becomes a unit, and an interrupted refresh picks up at the next unfinished source on re-invocation. See /doc-wiki:ingest above for the pattern.
node {skill_path}/scripts/event_logger.js stats --wiki-root <wiki-root> --since 7d
Shows running averages, p50/p95 reduction ratios, total spend, per-agent cost breakdown. Per-agent cost sums top-level agent fields as well as every agent_calls[] sub-entry on every event, so parent-op events that dispatched sub-agents are fully accounted for.
After any write operation (ingest, fix, promote, refresh), run BOTH hooks if the wiki has >= 3 pages:
Crosslink pass: Read ALL wiki pages. Find meaningful relationships. Add 2-5 inline links per page. Add/update ## Related Pages section on every page.
Tag-harmonize pass: Build tag vocabulary from all frontmatter. Scan each page's body. Add existing tags where missing. Only suggest new tags for concepts on 2+ pages. Enforce content-only tag philosophy (no structural/temporal/metadata tags). Target: 4-8 concept tags per page.
Skip hooks with --no-crosslink or --no-tag-harmonize flags.
After lint, compute quality scores:
node {skill_path}/scripts/quality_score.js --wiki-root <wiki-root>
Scores each page 0.0-1.0 based on word count, frontmatter completeness, link density, tags, source citations, god-node degree bonus (+0.1), isolation penalty (-0.2).
/doc-wiki:ingest step 7 dispatches via narai-primitives's gather() — one library call plans and spawns the bundled connector CLIs in parallel. There are no per-service wrapper scripts or subagents in doc-wiki; the legacy wiki-<svc>-agent folders were removed because they only duplicated the hub's CLI resolution and the mermaid_augment.ts decoration. Add a new builtin connector by adding an entry to BUILTIN_PATTERNS in source_registry.ts. Add an out-of-tree connector via wiki.config.yaml's ecosystem.agents.custom block.
Read these as needed — don't load them all upfront:
references/operations.md — Detailed specs for each operation, onboarding flow, edge casesreferences/compilation.md — Compilation rules: frontmatter schema, link enrichment, cross-referencing, code locality, claims extraction, "How to Go Deeper" generationreferences/quality.md — Quality scoring rules, tag philosophy, content-only tags, Mermaid lintreferences/autonomy.md — 4 autonomy modes (conservative/balanced/autonomous/auto), per-category overrides, decision flowreferences/code-locality.md — When to reference code vs copy it, content_hash drift detection