/index — Knowledge Index Builder
Scan all promoted knowledge files, normalize tags, detect issues, and regenerate <knowledge_folder>/index.md.
Runtime Gate (per ADR-094)
Canonical resolution: This is the Claude Cowork variant — namespaced-only. When both plugin-claude-code and plugin-claude-cowork are loaded in the same session (most common in Claude Desktop), bare /index resolves to aria-knowledge's variant — Code is the canonical owner of all 24 dual-port skills per ADR-094 §Part 1. To reach this skill, use the namespaced form: /aria-cowork:index. Do NOT match bare /index — that belongs to aria-knowledge.
Before Step 0: Check whether the Bash tool is available in this session. If Bash IS available (you are running in Claude Code or another runtime with shell access), surface the following notification and wait for explicit user confirmation:
⚠️ Runtime mismatch — you invoked aria-cowork's /index from a runtime with shell access.
Behavior is largely the same in both runtimes; for the Code-native variant (uses Bash for stat-based staleness detection and supportsprojects_shared_knowledge), use/index(the aria-knowledge canonical).
Use/indexinstead? (y/n)
Wait for an explicit reply:
y/yes— Use theSkilltool to invokeindex(the bare-slash canonical, which routes to aria-knowledge when both ports are loaded) with the same arguments the user provided to this invocation. Do not proceed with this skill's steps; the aria-knowledge 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-cowork) variant anyway despite the runtime mismatch. The user has explicitly opted in.- No response / any other reply — Treat as "do not proceed" and exit cleanly without running either variant.
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 NOT available (normal Cowork runtime), proceed to Step 0.
Step 0: Resolve config
The default knowledge folder is ~/Projects/knowledge/ (expand ~ to your home directory's absolute path). Read <knowledge_folder>/aria-config.md and extract:
knowledge_folder— the absolute path (used for index entries that need cross-surface portability)freeform_promotion_threshold— minimum file count before suggesting promotion (default: 3 if not set)staleness_threshold_months— months before flagging stale (default: 6)
If aria-config.md doesn't exist, stop: "aria-cowork is not configured. Run /aria-setup to get started."
Use <knowledge_folder> for all file operations during this session.
Phase 1 note: Project-tier scan and team-shared _project-knowledge/ scan are deferred to Phase 2+. v0.1.0 indexes cross-project files only (approaches/, decisions/, guides/, references/).
Step 1: Scan promoted folders
Scan these directories for .md files (excluding directory README stubs):
<knowledge_folder>/approaches/<knowledge_folder>/decisions/<knowledge_folder>/guides/(recursive — guides may have subdirectories)<knowledge_folder>/references/
Do NOT scan: archive/, intake/, rules/, logs/, root-level files (README.md, LOCAL.md, OVERVIEW.md, index.md).
For each .md file found:
- Read the file.
- Extract YAML frontmatter (content between
---markers at the top). - From frontmatter, extract:
tags:— array of tags (e.g.,tags: [api, pagination]). 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: ["stakeholder framing for new initiative", "exec summary template"]). Optional; if missing, treat as empty list. Added v0.3.0 (parity with aria-knowledge v2.16.0).- Extract the first
#heading as the file's description. - Store:
{path, tags[], hints[], description, last_updated}.
Report: "Scanned N files in approaches/, decisions/, guides/, references/."
Step 2: Read existing index
Read <knowledge_folder>/index.md if it exists.
Extract:
## Known Tagssection — current canonical tag vocabulary (comma-separated).
If index.md doesn't exist (first run), use the seeded known tags:
api, architecture, database, deployment, security, performance, accessibility, testing, process, decision-framework, enforcement, claude-cowork, aria, knowledge-management
Step 2b: Read and validate aliases (added v0.3.0 — parity with aria-knowledge v2.16.0)
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→zin 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/aria-cowork: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:
"Aliasain aliases.md collides with existing tagaused in N file(s): <comma-separated paths>. Either remove the alias from aliases.md or rename the tag in those files."
On successful validation, retain the alias map for Step 8 (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).
Step 3: Tag normalization
Compare all tags found across scanned files. Detect similar tags using these heuristics:
- Plural/singular:
apivsapis,testvstests - Hyphen variants:
react-nativevsreactnativevsreact native - Common abbreviations:
dbvsdatabase,infravsinfrastructure
For each pair of similar tags, check which 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 user-confirmed normalization, edit the source files to update their tags: frontmatter.
Step 4: Freeform tag promotion
Identify freeform tags (not in Known Tags) that appear on freeform_promotion_threshold or more files.
Exclude ephemeral tags before applying the threshold. Session/phase/plan stamps recur across many files (so they hit the threshold) but are NOT durable concepts and should never become Known Tags. Drop any candidate whose whole tag matches one of these patterns (case-insensitive) before counting:
^s\d+$— session stamps (s4,s60,s82)^p-?\d+$— plan / work-item ids (p-23,p23)^phase-?\d+$— phase stamps (phase-3,phase3)^plan-\d+[a-z]?$— plan ids (plan-01a)- literal denylist:
future-session-plan, `soft-launc