Help us improve
Share bugs, ideas, or general feedback.
From aria-knowledge
Scans promoted knowledge files, normalizes tags, flags untagged files, suggests freeform-to-known promotions, detects stale files, suggests cross-references, and regenerates the knowledge index. Invoked via "/index" or "rebuild index".
npx claudepluginhub mikeprasad/aria-knowledge --plugin aria-knowledgeHow this skill is triggered — by the user, by Claude, or both
Slash command
/aria-knowledge:indexThis skill is limited to the following tools:
The summary Claude sees in its skill listing — used to decide when to auto-load this skill
Scan all promoted knowledge files, normalize tags, detect issues, and regenerate `{knowledge_folder}/index.md`.
Loads relevant knowledge files by tag query, enabling on-demand retrieval of promoted context documents.
Upgrades existing Knowledge Base to latest Claude plugin practices: Obsidian graph-view links, structured 'When to Load' format, CLAUDE.md preamble, index schema, frontmatter health. Safe, preview-first, re-runnable.
Compiles deep context on topics via 4-phase retrieval combining semantic search, relationship traversal, tag expansion, and gap filling. Use for tracing connections across knowledge entries, sessions, and notes.
Share bugs, ideas, or general feedback.
Scan all promoted knowledge files, normalize tags, detect issues, and regenerate {knowledge_folder}/index.md.
Canonical resolution: This is the Claude Code variant. When both plugin-claude-code and plugin-claude-cowork are loaded in the same session (most common in Claude Desktop), bare /index resolves to this skill — aria-knowledge (Code) is the canonical owner of all 24 dual-port skills per ADR-094 §Part 1. The Cowork variant is namespaced-only: /aria-cowork:index.
Before Step 0: Check that the Bash tool is available in this session. If Bash is NOT available (you are running in Claude Cowork or another non-Code runtime), surface the following notification and wait for explicit user confirmation:
⚠️ Runtime mismatch — you invoked aria-knowledge's
/indexfrom a non-Code runtime.This variant supports
projects_enabled/projects_shared_knowledgeconfig keys not present in Cowork'saria-config.md. For the Cowork-native variant (simpler index, no shared-knowledge tier), use/aria-cowork:index.Use
/aria-cowork:indexinstead? (y/n)
Wait for an explicit reply:
y / yes — Use the Skill tool to invoke aria-cowork:index with the same arguments the user provided to this invocation. Do not proceed with this skill's steps; the cowork variant takes over and runs to completion. This is the default-yes path — auto-redirect is the helpful action.n / no — Proceed with this (aria-knowledge) variant anyway despite the runtime mismatch. The user has explicitly opted in.This gate applies even when mode = auto per ADR-094 §Part 3. Auto mode's "implicit-yes on all gates" rule is suspended for the runtime-mismatch check — auto trusts that the user invoked the correct variant, and this gate enforces that precondition. All other auto-mode gates remain bypassed. The friction cost is now low: on y, the auto-redirect runs the correct variant with the original args.
If Bash is available, proceed to Step 0.
Read ~/.claude/aria-knowledge.local.md and extract:
knowledge_folder — base path for all operationsfreeform_promotion_threshold — minimum file count before suggesting promotion (default: 3)staleness_threshold_months — months before a file is flagged stale (default: 6)projects_enabled — default false; controls whether project tier is scanned and indexedprojects_list — default empty; comma-separated tag:path pairs; only relevant if projects_enabled: trueprojects_promotion_threshold — default 2; minimum projects sharing a similar pattern to surface as a cross-project promotion candidateprojects_shared_knowledge — default empty; comma-separated list of project tags enabled for shared knowledge. When non-empty, scan each listed project's _project-knowledge/ folder for team-shared knowledge. Tags not in this list are skipped (their _project-knowledge/ folders, if any exist on disk, are NOT indexed).If the config file doesn't exist, stop: "aria-knowledge is not configured. Run /setup to get started."
Scan these directories for .md files (excluding directory README stubs that only contain a few lines of boilerplate):
{knowledge_folder}/approaches/{knowledge_folder}/decisions/{knowledge_folder}/guides/ (recursive — includes subdirectories){knowledge_folder}/references/Do NOT scan: archive/, intake/, rules/, top-level logs/*.md (audit-log files like config-audit-log.md, knowledge-audit-log.md, hook-debug.log), or root-level files (README.md, LOCAL.md, OVERVIEW.md, index.md).
Carve-out for review reports: the two subfolders logs/prospect/ and logs/retrospect/ ARE scanned as a separate "reviews tier" — see the dedicated sub-step below. Review reports use the same frontmatter scanning convention as cross-project files (tags, Last updated, first heading).
For each .md file found:
--- markers at the top of the file)tags: — array of tags (e.g., tags: [api, pagination, django]). If missing, record as untagged.Last updated: — date string (YYYY-MM-DD). If missing, record as unknown.semantic-hints: — array of free-form phrases (e.g., semantic-hints: [cursor pagination, keyset pagination]). Optional; if missing, treat as empty list. Added 2.16.0.# heading as the file's description{path, tags[], hints[], description, last_updated, source: "cross-project"}Report: "Scanned N files in approaches/, decisions/, guides/, references/."
After the cross-project scan, scan logs/prospect/ and logs/retrospect/ for review reports written by the /prospect and /retrospect skills.
For each .md file found in either subfolder:
tags: — array of tags. Always includes prospect or retrospect plus the scope keyword. If missing (legacy reports written before the structured-frontmatter format), record as untagged and emit a soft warning (one-line) suggesting the file be re-run or hand-tagged.Last updated: — fall back to date: if Last updated: is absent (review reports use date: for the report-creation date).type: — prospect or retrospect. Used to bucket the file under "Retrospects" or "Prospects" in the ## Review Index section of index.md (see Step 9).scope: — the scope keyword (e.g., release, deployment, commit, plan).tickets: — for cross-reference enrichment (consumed by /context).# heading as the file's description (typically "/prospect — " or "/retrospect — ").{path, tags[], description, last_updated, source: "review", review_type: <prospect|retrospect>, scope: <keyword>, tickets: [...]}Report: "Scanned R review reports across logs/prospect/ and logs/retrospect/ (P prospect, Q retrospect)."
If neither subfolder exists yet on disk, skip this sub-step silently (first run before any /prospect or /retrospect has been invoked).
projects_enabled: true and projects_list is non-empty)After the cross-project scan, scan the project tier:
For each tag:path pair in projects_list:
{knowledge_folder}/projects/{tag}/**/*.md recursivelyprojects/{tag}/README.md (per-project navigation, not knowledge content)projects/README.md (the projects/ tier README, plugin-managed){tag} to the file's tag set even if not in YAML frontmatter. The union of YAML tags + path tag is what gets indexed. This means project files don't have to manually include the project tag in their frontmatter.{path, tags[], description, last_updated, source: "project-specific", project: tag}Report: "Scanned M files across N project subdirectories: [project tags]."
If projects_enabled: false or projects_list is empty, skip this sub-step entirely. Project tier files (if any exist on disk) won't be indexed.
projects_shared_knowledge list is non-empty)After the project tier scan, scan each enabled project's _project-knowledge/ folder. Only projects whose tags appear in projects_shared_knowledge are scanned — non-listed projects are skipped, even if their _project-knowledge/ folders exist on disk.
For each tag in projects_shared_knowledge (parsed as comma-separated list):
projects_list to get its path, then resolve to ~/Projects/<path>. If the tag is not present in projects_list, log a warning and skip (config inconsistency — /setup validation should catch this, but defensive).projects_groups entry (multi-repo project):
projects_groups[tag]): scan <project-root>/_project-knowledge/ directly.projects_groups[tag] is set): the project-root is a container, not a repo. Iterate the role:sub-repo pairs in projects_groups[tag] (preserving declaration order), and for EACH sub-repo, scan <project-root>/<sub-repo>/_project-knowledge/. Skip sub-repos whose path doesn't exist on disk (sub-repo not yet cloned)._project-knowledge/. If the folder doesn't exist, skip that location (no team-shared knowledge yet there). Continue to next location (don't bail on the whole tag — sibling sub-repos may have content).<scan-location>/_project-knowledge/**/*.md recursively.<scan-location>/_project-knowledge/README.md (auto-generated convention explainer, not knowledge content).<scan-location>/_project-knowledge/*.md (top level), categorize as team-shared with project: <tag> (always the parent project tag from projects_shared_knowledge, NOT the sub-repo name — sub-repo identity is captured in the absolute path stored in step 9).<scan-location>/_project-knowledge/cross/*.md, categorize as team-shared-cross with project: cross._project-knowledge/IDEAS-BACKLOG.md and _project-knowledge/cross/IDEAS-BACKLOG.md as single files (don't try to split them into entries for indexing). Index them as one file each, tagged with the project tag (or cross).{path: <absolute-path-from-home>, tags[], description, last_updated, source: "team-shared", project: <tag>, scope: "repo" | "cross"}.Report: "Scanned T team-shared files across P enabled projects: [project tags from projects_shared_knowledge with non-empty _project-knowledge/ folders]."
If projects_shared_knowledge is empty/missing, skip this sub-step entirely. Team-shared files (if any exist on disk) won't be indexed.
Read {knowledge_folder}/index.md if it exists.
Extract:
## Known Tags section — the current canonical tag vocabulary (comma-separated list)## Projects section — current project-to-tag mappingsIf index.md doesn't exist (first run), use the seeded known tags:
api, architecture, css, database, deployment, django, react, nextjs, react-native, tailwind, testing, infrastructure, performance, security, accessibility, stripe, linear, supabase, figma, claude-code, process, decision-framework, enforcement, aria
And leave the Projects section empty (will be populated in Step 6).
Read {knowledge_folder}/aliases.md if it exists.
Parse the alias map: each line matching the pattern - `<alias>` → `<canonical>` contributes one entry. The alias and canonical are the backtick-quoted strings; whitespace around the arrow is tolerated; non-matching lines (headers, comments, blank lines) are ignored.
If the file doesn't exist OR contains no parseable entries, treat the alias map as empty and continue to Step 3.
Chain check (internal to the alias map): if any canonical name in the parsed map ALSO appears as an alias key in another entry of the same map, abort /index with:
"Alias chain detected: \x` → `y` → `z` in aliases.md. Aliases must point directly to a canonical tag, not to another alias. Fix the chain (typically: rewrite the intermediate alias to point at the final canonical) and re-run /index."`
Collision check (against Step 1's per-file tag data): for each alias a in the parsed map, scan the per-file tags[] arrays collected in Step 1. If any file declares a in its tags: frontmatter, abort /index with:
"Alias \a` in aliases.md collides with existing tag `a` used in N file(s): . Either remove the alias from aliases.md or rename the tag in those files."`
On successful validation, retain the alias map for Step 9 (Known Tags annotation). The map is also consumed by /context Step 2.5 (which reads it from the ## Known Tags section's [aliases: ...] annotations, not from aliases.md directly).
Compare all tags found across scanned files. Detect similar tags using these heuristics:
api vs apis, test vs testsreact-native vs reactnative vs react nativedb vs database, infra vs infrastructureFor each pair of similar tags, check which one is in the Known Tags set. If one is known and the other isn't, the known one is the normalization target.
If both are unknown, prefer the more common one (appears on more files).
Present conflicts to user:
## Tag Normalization
Found similar tags:
1. `apis` (1 file) → normalize to `api` (4 files)? [y/n]
2. `reactnative` (1 file) → normalize to `react-native` (2 files)? [y/n]
For each approved normalization:
If no similar tags found, skip this step silently.
Identify tags that are NOT in the Known Tags set but appear on {freeform_promotion_threshold} or more files (default: 3).
Present suggestions:
## Freeform Tag Promotion
These freeform tags appear frequently:
1. `webhooks` — 4 files. Promote to known tags? [y/n]
2. `authentication` — 3 files. Promote to known tags? [y/n]
For each approved promotion:
If no tags qualify, skip this step silently.
For each file with no tags: in its frontmatter:
Present list and offer to fix:
## Untagged Files
Found N files without tags:
1. guides/claude/environment-architecture.md — "Environment Architecture"
Suggested tags: [claude-code, architecture, infrastructure]
2. approaches/combo-class-pattern.md — "Combo Class Pattern"
Suggested tags: [css, tailwind, df]
Add suggested tags? (all / numbers / skip)
For each file the user approves:
--- markers), add tags: [tag1, tag2] as a new line inside it---
Last updated: YYYY-MM-DD
tags: [tag1, tag2]
---
(Use the file's existing Last updated date if found in the body, or today's date if none exists)Tag suggestions are based on:
api-pagination → api, pagination)guides/claude/ → suggest claude-code)Determine the authoritative project list using this priority:
projects_enabled: true and projects_list is non-empty: use projects_list as the project enumeration. Each tag:path pair contributes a project entry where the tag is the project key and the path is the project location. This is the configured set of projects ARIA recognizes.projects_enabled: false): read the root project CLAUDE.md to find a project table. Look for the closest ancestor directory containing a CLAUDE.md with a project table.For each project (from either source):
cs/CLAUDE.md, ss/CLAUDE.md) if it exists at the configured pathprojects/{tag}/** from Step 1's project tier scan) to the project's relevant tag setBuild a mapping:
proj-a — Project A: api, django, react, react-native, css, tailwind, stripe, supabase, database, deployment
proj-b — Project B: api, django, nextjs, stripe, supabase, database, deployment
proj-c — Project C: css, tailwind, accessibility
aria — ARIA: claude-code, process, decision-framework, enforcement
Compare against existing mappings (from Step 2). If any changed:
## Project Mapping Updates
- proj-a: added `supabase` (found in proj-a/CLAUDE.md tech stack)
- proj-b: no changes
If this is the first run (no existing mappings), present the full initial mapping for confirmation.
For each scanned file, compare its Last updated date against today's date.
If the file's age exceeds {staleness_threshold_months} months (default: 6):
This data is used when generating the ## Stale Files section in Step 9. No user interaction here — just collection.
Steps 8 (Cross-Reference Pass), 8b (Entity Detection), 8c (Skill Connection Discovery), and 8d (Cross-Project Promotion Candidates) require body content scans of every promoted knowledge file — substantially more expensive than the frontmatter-only scan that powers Steps 1-7. For a 500+ file knowledge base, expect ~3 minutes wall-clock and meaningful token cost.
These steps were silently skipped in the first 35+ /index passes (added to the spec but never invoked at routine pass cost). v2.20.0+ makes the cost explicit and gates the heavy work behind user confirmation.
Prompt:
Routine
/indexindexes via frontmatter (tags, dates, descriptions). Heavy-pass Steps 8.x run additional body-content scans for:
- Step 8 — Cross-reference suggestions (pairs of files sharing ≥2 tags with no mutual
## Relatedlink, plus reverse-link gaps)- Step 8b — Entity detection (tools/services/frameworks appearing in ≥2 files)
- Step 8c — Skill-knowledge connection discovery (skill names referenced in knowledge files; name-overlap matching)
- Step 8d — Cross-project promotion candidates (similar patterns across ≥2 projects in
projects_list)Cost: ~3 min wall-clock for N files (N = scanned count from Step 1) + meaningful token spend. Output: enriched
index.mdsections.Run heavy-pass Steps 8.x? (y / n / partial)
y — proceed with Steps 8, 8b, 8c, 8d as defined belown — skip Steps 8.x entirely; proceed to Step 9 with frontmatter-only data; resulting index.md will omit the ## Cross-Reference Suggestions, ## Entities, ## Skill Connections, ## Cross-Project Promotion Candidates sectionspartial: <substep-list> — run a subset (e.g., partial: 8d runs only cross-project; partial: 8,8d runs cross-reference + cross-project, skips entity detection + skill connections). Useful when one substep is the user's actual interest and the other three are noise for this pass./index is called from /audit-knowledge Step 7bIf /index is being invoked as part of /audit-knowledge's Step 7b rebuild (not stand-alone), the heavy-pass gate still fires — the audit user is the same human; ask them once. If the user declines or chose partial, the audit's Step 5b drift-detection capabilities are degraded (skill-knowledge drift relies on Step 8c output, cross-project candidate detection relies on Step 8d). Surface this degradation explicitly in /audit-knowledge Step 6's "Integrity Issues" section with a "Limited by Steps 8.x skip" note.
/index accepts an optional argument:
/index — default; prompt at Step 7b/index --deep — pre-authorize all of Steps 8.x (treat the gate as auto-y)/index --shallow — pre-authorize skip of all Steps 8.x (treat the gate as auto-n)/index --partial=8d — pre-authorize partial run (same syntax as the prompt's partial: response)When pre-authorized, skip the prompt and proceed accordingly. Audit-time invocations should typically run shallow or partial (audit is the long-flow already); explicit /index --deep is the right shape for periodic baseline refreshes (every 1-2 weeks, or when a major batch of new files lands).
Steps 8.x were defined in the spec from v1.0 but never invoked because routine /index calls treated them as frontmatter-tier work. 35+ passes silently skipped. v2.20.0 (2026-05-20) introduces this gate after the 37th-pass /audit-knowledge first invoked Steps 8.x via parallel agent (one-time baseline) and the resulting agent output ran ~3 min producing 599 lines of findings — Mike confirmed the cost-value gate-explicit pattern over routine-silent-skip.
For each pair of promoted files, compute tag overlap:
## Related section for existing cross-referencesAlso check for reverse link gaps: if file A's ## Related links to file B, but file B's ## Related doesn't link to file A.
Present suggestions:
## Cross-Reference Suggestions
1. approaches/api-pagination.md <-> decisions/003-cursor-vs-offset.md
Shared tags: api, pagination
Neither references the other — add cross-links? [y/n]
2. references/stripe-webhook-patterns.md <-> guides/payments/checkout-flow.md
Shared tags: stripe, cs
checkout-flow.md links to stripe-webhook-patterns.md but not the reverse — add reverse link? [y/n]
For each approved cross-reference:
## Related section, append the new link:
- [Target File Title](../relative/path/to/target.md)
## Related section, add one at the end of the file:
## Related
- [Target File Title](../relative/path/to/target.md)
If no suggestions, skip this step silently.
Scan all promoted files for recurring proper nouns — tool names, service names, API names, framework names, and other named entities that appear across multiple knowledge files.
How to detect entities:
Build an entity map:
Stripe → approaches/payment-flow.md, references/stripe-webhook-patterns.md, decisions/003-payment-provider.md
Supabase → guides/infrastructure/supabase-setup.md, decisions/005-builder-architecture.md
Django → approaches/api-pagination.md, guides/api-auth.md
This data is used when generating the ## Entities section in Step 9. No user interaction here — just collection.
Scan for connections between the plugin's skills and knowledge files. This enables /audit-knowledge to detect when a skill evolves but its related knowledge docs haven't been updated.
Scan skill files:
${CLAUDE_PLUGIN_ROOT}/skills/*/SKILL.md (or use the plugin's own skill directory)~/.claude/plugins/**/skills/*/SKILL.mdname from frontmatter or directory name, extract description, scan for ## Related sectionsAuto-discover connections using these heuristics (in priority order):
/codemap appears in an approach doc). Grep promoted files for /skillname.## Related section: Skill file explicitly references knowledge files. Parse relative paths.codebase-documentation). Use fuzzy matching — strip hyphens and compare.Present discoveries for user confirmation:
## Skill Connections
Discovered N connections between skills and knowledge files:
1. /codemap → approaches/codebase-documentation.md
Match: skill name referenced in file content
Relationship: [auto-suggest or ask user]
2. /codemap → decisions/007-codebase-documentation-structure.md
Match: "/codemap" mentioned in decisions backlog clear comment
Relationship: [auto-suggest or ask user]
3. /extract → decisions/002-knowledge-extraction-architecture.md
Match: name overlap ("extract" ↔ "extraction")
Relationship: [auto-suggest or ask user]
Add connections? (all / numbers / skip / add manual)
For "add manual": let the user specify skill → file → relationship for connections the heuristics missed.
Relationship types (suggest the most likely, let user override):
documents the approach this skill implementsrecords decisions that shaped this skillprovides reference data used by this skilldefines rules enforced by this skillguides usage patterns for this skillStore approved connections for Step 9 output.
Skip this step entirely if projects_enabled: false or projects_list has fewer than 2 entries.
Scan files indexed under the project tier (from Step 1's project tier scan) for patterns that may represent the same concept across multiple projects.
Detection heuristics (compute pairwise across all project-tier files):
state-management-patterns.md in projects/proj-a/patterns/ AND projects/proj-b/patterns/). Use case-insensitive equality of stem (filename without .md) as the primary match; allow minor variants (-patterns vs -pattern, plural vs singular).# heading) shares 3+ significant terms (excluding stop words and project names).Threshold: if a pattern (i.e., a similar file) appears in ≥projects_promotion_threshold projects (default 2), surface as a candidate.
For each candidate group, collect:
approaches/{descriptive-name-derived-from-shared-tags-or-title}.md)This data is used when generating the ## Cross-Project Promotion Candidates section in Step 9. No user interaction at this step — just collection. Promotion itself happens in /audit-knowledge Step 5e (Phase 3 of the project knowledge feature).
Rationale for surfacing in the index: the index is a regularly-rebuilt artifact. Detecting candidates here means users see them whenever they look at the index, not only when they explicitly run /audit-knowledge. Lower-friction discovery, same downstream promotion workflow.
index.mdGenerate {knowledge_folder}/index.md with this structure:
# Knowledge Index
Last rebuilt: YYYY-MM-DD
## Projects
### [project_key] — [project_name]
Relevant tags: tag1, tag2, tag3
Project-tier files: N (decisions: D, patterns: P, other: O)
Last project-tier update: YYYY-MM-DD
Promotion candidates: M (see below — same pattern appears in ≥`projects_promotion_threshold` projects)
(repeat for each project. If `projects_enabled: false`, the per-project metrics lines after "Relevant tags:" are omitted — just the project key and tag mapping appear, mirroring v2.7.x format.)
(For projects with zero project-tier files, show `Project-tier files: 0` and omit "Last project-tier update" — Decision #8: list configured projects even if empty so the user sees what's available.)
## Known Tags
tag1, tag2 [aliases: alt1, alt2], tag3, tag4, ...
(Canonical tags with aliases declared in `aliases.md` are annotated inline: `tag [aliases: alias1, alias2]` enumerates all aliases pointing to that canonical. Tags with no aliases appear without annotation. The flat tag list is comma-separated. `/context` reads these annotations to build its alias→canonical map at query time. Added 2.16.0.)
## Tag Index
### [known_tag]
- relative/path/to/file.md — File description
(repeat for each known tag that has matching files, sorted alphabetically)
## Other Tags
### [freeform_tag]
- relative/path/to/file.md — File description
(repeat for each freeform tag, sorted alphabetically)
## Semantic Hints Index
### [hint phrase]
- relative/path/to/file.md
(Repeat for each unique hint phrase declared across promoted files, sorted alphabetically by phrase. Each file appears under every hint it declares. Hint phrases are stored verbatim from frontmatter — `/context` does the case-insensitive + hyphen-normalized substring match at query time. Omit this section entirely if no files declare `semantic-hints:`. Added 2.16.0.)
## Team-Shared Tag Index
### [tag]
- ~/Projects/<path>/_project-knowledge/2026-04-28-init-foo.md — File description [project: proj-a, scope: repo]
- ~/Projects/<path>/_project-knowledge/cross/2026-04-28-init-bar.md — File description [project: cross, scope: cross]
(repeat for each tag matching team-shared files, sorted alphabetically. File paths are absolute-from-home so /context can distinguish them from knowledge-folder-relative paths in the regular Tag Index. The trailing `[project: ..., scope: ...]` annotation lets /context render team-shared results with their origin info. Omit this section entirely if `projects_shared_knowledge` is empty/missing or no team-shared files exist.)
## Review Index
### Retrospects
- YYYY-MM-DD [scope] — Goal text (truncated to ~60 chars) [LINEAR-123, LINEAR-456] → outcome
- YYYY-MM-DD [scope] — Goal text [tickets] → outcome
### Prospects
- YYYY-MM-DD [scope] — Goal text [tickets] → verdict
- YYYY-MM-DD [scope] — Goal text [tickets] → verdict
(Sourced from files indexed under the reviews tier — `logs/retrospect/*.md` and `logs/prospect/*.md`. Within each subsection, sort descending by `date:` from frontmatter (newest first — most actionable for catch-up). Each entry shows: ISO date, scope keyword in brackets, truncated goal, ticket list (if any), and the report's overall_outcome (retrospects: closed / partial / unresolved / mixed) or overall_verdict (prospects: PROCEED / PROCEED-WITH-CHANGES / HOLD / KILL). The ticket list links to the ticket reference if Linear MCP is available; otherwise shows the bare IDs.
Path is relative to the knowledge folder root: `logs/retrospect/YYYY-MM-DD-scope-slug.md`. Use the file path as the link target so the user can click through to the full report.
If no review reports exist (first run before any /prospect or /retrospect was invoked), omit this section entirely.
If reviews lack frontmatter `overall_outcome` / `overall_verdict` (legacy reports written before the structured-frontmatter format), substitute "[no verdict recorded]" rather than omitting the entry.)
## Stale Files
### relative/path/to/file.md
Last updated: YYYY-MM-DD (N months ago) — threshold: M months
(repeat for each stale file. Omit this section entirely if no stale files.)
## Untagged Files
- relative/path/to/file.md — File description (no tags in frontmatter)
(Omit this section entirely if no untagged files remain after Step 5.)
## Entities
### [Entity Name]
- relative/path/to/file1.md
- relative/path/to/file2.md
(Repeat for each entity appearing in 2+ files, sorted alphabetically. Omit this section entirely if no entities detected or all are already covered by tags.)
## Skill Connections
| Skill | Related knowledge | Relationship |
|-------|------------------|-------------|
| /skillname | relative/path/to/file.md | documents the approach this skill implements |
(Repeat for each approved connection from Step 8c, sorted by skill name. Omit this section entirely if no connections discovered or approved.)
## Cross-Project Promotion Candidates
### [shared-tag-or-title-derived-name]
- Appears in: projects/{tag1}/patterns/file.md, projects/{tag2}/patterns/file.md
- Shared tags: tag-a, tag-b, tag-c
- Suggested location: approaches/{descriptive-name}.md
- Run `/audit-knowledge` Step 5e to promote (synthesizes content + adds `originally_at:` provenance)
(Repeat for each candidate group from Step 8d, sorted by number of projects involved descending then alphabetically. Omit this section entirely if `projects_enabled: false` or no candidates detected.)
File paths in the index are relative to the knowledge folder root (e.g., approaches/api-pagination.md, not the absolute path).
Tag Index entries are sorted: known tags alphabetically, then other tags alphabetically. Within each tag, files are sorted alphabetically by path.
A file appears under every tag it carries. If api-pagination.md has tags: [api, pagination, django], it appears under all three tag headings.
Index rebuilt successfully.
Files: N scanned, M tagged, K untagged
Tags: L unique (J known, F freeform)
Normalizations: P applied
Promotions: Q tags promoted to known
Stale files: S (threshold: T months)
Cross-references: R suggested, X added
Entities: E detected (across 2+ files)
Skill connections: C discovered, D approved
Project mappings: updated/unchanged