Skip to content
Back to skills

Knowledge Ref Scan

ASecurity

Dead paths, symbols, commands, ADR ids and anchor markers in the AI knowledge layer (CLAUDE.md, ai/, anchors).

  • 2 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added October 20, 2026
ai-agentspythongorubyphpshellbashsqlreactnodegit

Works with

  • claude code
  • cursor
  • cli
  • api

Security analysis

A100/100

Pro scans all 3 files and shows the line behind each finding

Scanned October 20, 2026

npx -y skills add adnanmokhtar/refract --skill knowledge-ref-scan --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Knowledge Ref Scan?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Knowledge Ref Scan
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/adnanmokhtar-knowledge-ref-scan/badge)](https://www.skillsdirectory.com/skills/adnanmokhtar-knowledge-ref-scan)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: knowledge-ref-scan
description: Dead paths, symbols, commands, ADR ids and anchor markers in the AI knowledge layer (CLAUDE.md, ai/, anchors).
kind: skill
pack: learning
allowed-tools: [Read, Grep, Glob, Bash]
---

# Skill: knowledge-ref-scan

## Premise

The AI knowledge layer is read by an agent that acts on it without a human in between. A path that no longer exists is a file the agent opens, edits or re-creates. A renamed class is a symbol it imports. A package script that was removed is a command that errors. A slash command that is not installed is a step that silently does nothing. A pattern or ADR id with no file is a rule the agent is told to follow and cannot find. A corrupted `project-specific` marker makes the next setup run eat or duplicate content.

DOCER (Tan, Wagner, Treude, EMSE 2024) found an outdated code-element reference at HEAD in 28.9% of the top-1000 repositories, and ReCite (ASE 2026) found 869 stale function references in one kernel release. The same defect in an agent's context is one notch worse: it is loaded every session (precedents § Reading the gates).

`scripts/knowledge-refs.py` (this skill) owns six learning classes: §1 dead path (KN-01), §2 dead symbol (KN-02), §3 dead command, script, skill or agent (KN-03), §4 dead knowledge cross-reference (KN-04), §5 framework path leaked into an installed artifact (KN-05), §6 marker corruption (KN-15). The shared reader `scripts/kn_common.py` is imported by the other four learning detectors, so they agree on scope and resolution.

**Every finding cites the knowledge `file:line` + the reference as written + how it failed to resolve (RENAMED → the successor, DELETED in `<sha>`, never installed, uninstalled command) + the edit that closes it.** A regex hit is never a finding by itself, and "references clean" is never printed without the class-coverage block (§ Output).

## The rule

A reference is a finding when all four hold ([`precedents/learning.md`](../../../../snippets/precedents/learning.md), the claim restated):

1. **It is a live project claim.** The file loads or an agent is told to read it, and the line sits outside history (§ 3), outside an HTML block comment (§ 21), outside a `_template` (§ 4), and — in an installed pack artifact — inside the live anchor block (§ 10).
2. **It does not resolve.** Not exact, not relative to the citing file, not through a tsconfig `paths` alias or a workspace package name, not extension-less, not a unique tracked suffix (§ 6), not present on disk as an ignored or untracked output (§ 1, § 25).
3. **It once resolved here, or it names something the project must have.** Git history says RENAMED or DELETED (DOCER's filter). A path or symbol that never existed is Unconfirmed (§ 5, § 7), and another codebase's path is not a claim (§ 8).
4. **The fix is mechanical or named.** RENAMED → repoint to the successor; DELETED → delete the line or repoint by hand; uninstalled → install, or remove the instruction.

## Boundaries

- **Human docs** — README, `docs/**`, runbooks written for people, diagrams, external links — belong to documentation `doc-drift-scan` when the documentation pack is installed; it can call this engine with its own corpus (`--corpus=`), and the two runs dedupe by `file:line` (owner decision O-1). Without the documentation pack those files are out of scope here, listed as `N/A (owner pack documentation not installed)`.
- **A fact that is wrong but resolves** (MySQL where the lockfile says Postgres, a citation whose line moved) → `knowledge-fact-scan` (KN-07, 13, 14). **A citation inside a memory entry** → `memory-hygiene-scan` §1 (KN-20). **An ADR's own status and supersede links** → `decision-record-scan`. **An oracle file that was never written** (`_extracted-*.md`) is reported here as one KN-19 group and graded by `context-load-scan` §4.
- **A convention the code no longer follows** (KN-10) → align `convention-oracle` AL-04, when the align pack is installed; without it `/detect-drift`'s fallback agent.
- **Dead code** found while resolving → code-quality `dead-code-scan`, not a reference row.

## Adapt to the codebase — the resolution lanes

The engine needs no tool beyond `git` and Python 3.8. Read which lanes resolved what from the ledger (stderr), never assume.

| Lane | What resolves a reference | Read from | Trap |
|---|---|---|---|
| **Any repo** | `git ls-files` (case-sensitive), every parent directory, unique tracked suffix | the index, read-only (`GIT_OPTIONAL_LOCKS=0`) | no git → `census=find` (os.walk minus build dirs): RENAMED/DELETED cannot be classified, rows print `no-history` |
| **JS / TS monorepo** (pnpm, npm, yarn, bun workspaces; Nx, Turborepo) | every tracked `tsconfig*.json` / `jsconfig.json` `paths` (relative `extends` followed), workspace package names from every `package.json` | JSONC read by a string-aware scanner | a regex comment-stripper reads the `/*` in `"@/*"` as a comment and loses the whole alias table |
| **Python, Go, Ruby, PHP, JVM, .NET** | tracked paths and suffixes; symbols by tokenising every tracked source file | the tree | package import paths (`github.com/x/y`) are not repo paths unless the module path maps to a directory |
| **Commands** | `package.json` `scripts` of every workspace; `Makefile` / `justfile` targets; `.claude/{commands,skills,agents}`; `~/.claude/{commands,skills,agents}` and plugin manifests (P-23); Claude Code built-ins; the Refract pack catalog under `~/.claude/templates/packs` | disk | `--no-global` drops the global sets: a global command then reads as unknown, so use it only on a machine with no Refract install |
| **ADR ids** | the detected ADR home (an index's declaration, else the directory with most `NNNN-*.md`) | `kn_common.adr_home` | a hard-coded `ai/decisions/` reads 0 ADRs on a repo whose home is `docs/decisions/` (KN-29) |

## Pre-flight

Run as **one** bash script from the repo root. Step **N** feeds detector **§N**. Every `rg` names its paths (`"${ROOTS[@]}"`, built from the knowledge files that exist); any `rg` exit 2 is `blocked`, never zero hits. Includes first, exclusions last.

```bash
[ -n "${BASH_VERSION:-}" ] || { echo "pre-flight: run it with bash (arrays and PIPESTATUS are bash-only)"; exit 2; }
KS="${KS:-.claude/skills}"        # installed engines; in the Refract repo itself: templates/packs/learning/skills
RUN="${RUN:-$(mktemp -d "${TMPDIR:-/tmp}/knowledge.XXXXXX")}"; mkdir -p "$RUN"; echo "RUN=$RUN"
export GIT_OPTIONAL_LOCKS=0 DO_NOT_TRACK=1 CI=true
ROOTS=(); for p in CLAUDE.md CLAUDE.local.md AGENTS.md GEMINI.md ai .claude/rules .claude/agents .claude/commands .claude/skills \
  .claude/codebase-profile.md .cursor .github/copilot-instructions.md .github/instructions; do [ -e "$p" ] && ROOTS+=("$p"); done
[ ${#ROOTS[@]} -gt 0 ] || { echo "§1-§6 N/A: no knowledge layer (no CLAUDE.md, AGENTS.md, ai/ or .claude/)"; exit 0; }
H=(-g '!**/ai/audits/**' -g '!**/ai/incidents/**' -g '!**/ai/runs/**' -g '!**/ai/migration/**' -g '!**/*_history.md' -g '!**/CHANGELOG*' -g '!**/node_modules/**')

# 1-6. The engine: scope (P-3, P-10, P-21), resolution (P-6), history (DOCER, ReCite), commands (P-23), markers.
python3 -I "$KS/knowledge-ref-scan/scripts/knowledge-refs.py" . > "$RUN/refs.tsv" 2> "$RUN/refs.ledger"
echo "knowledge-refs exit $? (0 clean · 1 rows · 2 blocked)"; cat "$RUN/refs.ledger"; cut -f1-8 "$RUN/refs.tsv"
#    Per-site rows for the fix command, and the info rows (abbreviations, outputs, ambiguous suffixes) for a reviewer:
python3 -I "$KS/knowledge-ref-scan/scripts/knowledge-refs.py" . --expand --all > "$RUN/refs-sites.tsv" 2>/dev/null

# Cross-checks: the engine must not be quieter than a plain search.
# 5. Framework paths written into installed artifacts (the anchor header names Refract's apply-anchors.sh).
rg -n --pcre2 '`(?:scripts/[\w.-]+\.(?:sh|py)|\.claude/_codebase-scan\.md|templates/[\w./-]+)`' -g '*.md' "${ROOTS[@]}" "${H[@]}" > "$RUN/g5.txt"
echo "rg 5 exit $? ($(wc -l < "$RUN/g5.txt" | tr -d ' ') lines; each must be a KN-05 site or a path the project really has)"
# 6. Marker lines per file, fenced examples included: a file whose count is not 2 is read against the engine's §6 rows.
rg -c '^<!-- project-specific:(start|end) -->' -g '*.md' "${ROOTS[@]}" "${H[@]}" > "$RUN/g6.txt"
echo "rg 6 exit $?"; awk -F: '$NF != 2' "$RUN/g6.txt"
# 3. Backticked package-manager commands and slash commands the engine resolves.
rg -n --pcre2 '`(?:pnpm|npm|yarn|bun)\s+(?:run\s+)?[A-Za-z][\w:.-]*' -g '*.md' "${ROOTS[@]}" "${H[@]}" > "$RUN/g3.txt"
echo "rg 3 exit $? ($(wc -l < "$RUN/g3.txt" | tr -d ' ') script lines)"
```

Read the ledger first. It prints the census (`git` or `find`), the corpus by scope (live, pack-body anchor regions, history excluded, sinks handed to `memory-hygiene-scan`), the command universe (project, global, pack catalog; `global NOT READ` when `~/.claude` is absent) and, per lane, how references resolved. A lane that resolved nothing is `N/A` or `blocked`, never clean.

**Measured** (2026-10-19), read-only on a real NestJS + React monorepo (13,620 tracked files, 657 knowledge files; `find -newer` on a start stamp: 0 files written). A naive "every backticked path, `test -e`" prototype returned 15,173 dead-reference candidates. The engine scanned 478 files (124 live, 354 anchor-only; 164 history and 11 sink files excluded) in 7.8 s:
- 13,655 path references: 7,800 exact, 4,161 abbreviations (P-6), 219 relative, 35 ambiguous suffixes (INFO), a handful through aliases and workspace packages; 1,440 unresolved.
- Of those: 169 name the V1 codebase (P-8), 9 are outputs a command will write (P-7), 49 are bare file names never in history — naming examples (P-4) — 297 sites cite oracle files never written (8 KN-19 groups), 690 sites carry framework paths (8 KN-05 groups — `apply-anchors.sh` under Refract's scripts dir and `.claude/_codebase-scan.md` in 341 anchor headers each), 9 sites DELETED in history (6 KN-01 groups, e.g. a deleted `bulk-status-change.test.ts` named by 3 anchors), 6 KN-04 sites (5 `ai/patterns/*.md` listed in the patterns README and never installed), and 211 never-existed sites in 91 groups (Unconfirmed; 123 are anchor "Where this applies" lines naming files that were never committed).
- 734 symbols: 660 present, 72 never in history (P-5, dropped), 2 DELETED (KN-02).
- §3: 217 script references, 1 dead (`bun run scripts/…` first read as a script until the engine learned that a path argument runs a file); 941 slash tokens, 79 route-like and ignored, 1 unknown command (Unconfirmed).
- §6: 2 files — 6 live anchor blocks in one skill (5 holding a literal `...content...` placeholder) and a nested start in another.
- Cross-checks: rg 5 returned 527 lines — 341 anchor headers (the KN-05 group) and 186 lines that are pack-generic bodies outside an anchor (P-10) or paths that resolve (the project's own deploy script; `templates/snippets/*.md`, which resolve by suffix to the installed `.claude/templates/snippets/`). rg 6 listed the same 2 files the engine flagged (a 14-line and an 8-line count, fenced examples included).

On `benchmarks/fixtures/*` (24 trees, none carries a full knowledge layer; `port-pair` has 42 `ai/` files): 0 rows on 23 of them (`convention-drift` first returned 4 Unconfirmed rows — `.store.ts`, `OrderRow.tsx` — naming examples in its conventions doc, now P-4 INFO); `launch-gaps` returned 1 row — `/define-success` cited from 2 `ai/product/success/*.md` files, a product-pack command that is not installed in that tree (a true row for a tree that is not an install). The self-test seeds 15 rows across the six classes (with a case-only rename, a script named with its `--filter` flag, and a dead path in an untracked subtree whose census is the walk) and 16 decoys (abbreviation, alias, history file, sink, HTML comment, placeholder, global command, route, external symbol, pack-generic body, workspace script, fenced marker, output, V1 path, naming example, a gitignored `dist/` directory).

On `stale-knowledge` (the seeded fixture, staged with its 15-commit history; `--global-dir` a scratch dir linking the checkout's `commands`, `scripts` and `templates`): 45 files (23 live, 10 anchor-only, 1 history, 9 sinks handed off); 165 paths, 17 symbols, 18 scripts, 18 slash tokens → 16 grouped rows (22 with `--expand`), all on seed sites: **16 seeds printed** (the fixture totals 58 of its 59 learning seeds across the five detectors) — RENAMED and DELETED paths, a case-only rename (`ApiClient.ts` → `apiClient.ts`, read case-exactly on a case-insensitive disk), a renamed and a deleted symbol, a renamed script, an uninstalled catalog command, a renamed skill (Unconfirmed), an uninstalled pattern, an ADR id with no file, the framework-path header (one group, 5 anchors), a nested and an unclosed marker, plus the never-written idioms oracle as one KN-19 group. Decoys: 0 of 26 rows (`--all` reads `apps/web/dist/` as `ignored` through the `dist/` pattern). On the one-commit copy (no history) both KN-02 seeds vanish and three dead paths drop to `never-existed` (Unconfirmed).

## The 3,000-hit path

A repo with years of `ai/` notes can return thousands of unresolved references. Triage in this order and record every step in the coverage block:

1. **Group by root cause.** Rows already collapse by (class, reference, resolution) with `sites=N`. One anchor header line copied into 341 files is one row; fix the generator (`apply-anchors.sh`, IR-1), not 341 files.
2. **Rank by load.** Files loaded every session (`CLAUDE.md` and its imports, rules without `paths:`, anchor blocks) first, then `ai/*` files commands read by name, then the rest.
3. **Take the classified rows first.** RENAMED rows carry their successor: a mechanical repoint. DELETED rows need one decision per group.
4. **Read the top 30 Unconfirmed groups fully.** A never-existed path is a typo, a planned file (P-7), another codebase (P-8) or an uncommitted local file named by a generator.
5. **Ledger the rest** as `Live, unreviewed (k groups / n sites)` with the command that continues them (`knowledge-refs.py . --expand --classes=1`). Never `checked`.

## Scans for

| § | Class | Default |
|---|---|---|
| 1 | KN-01 dead path reference (link, backtick, fence, `@import`) | M; H in a file loaded every session or an anchor block |
| 2 | KN-02 dead symbol (class, function, constant named in a claim) | M; H in an anchor |
| 3 | KN-03 dead command: package script, make/just target, slash command, skill, agent | H in a loaded file, else M |
| 4 | KN-04 dead knowledge cross-reference: `ai/patterns/x.md`, `ai/runbooks/…`, `ADR-NNNN` with no file | M |
| 5 | KN-05 framework-only path in an installed artifact | M |
| 6 | KN-15 managed-marker corruption: nested start, start without end, duplicate live blocks | M |

### 1. Dead path reference (KN-01)

```
BAD:   CLAUDE.md:2        Billing lives in `apps/api/src/old-name.service.ts`.        (renamed to billing.service.ts)
       .claude/commands/x.md:22 (anchor)  `apps/web/…/bulk-status-change.test.ts`       (deleted in 2b2db317)
GOOD:  `shared/persistence/page-query.ts`  — one tracked file ends with it (P-6)
       `@/shared/api/client` — tsconfig `paths` alias · `ai/align/ledger.md` — an output the command writes (P-7)
```
**Read the code:** Is the reference inside a live region (the engine's scope) — or a history file, a template, a block comment? Did it ever resolve (`RENAMED`/`DELETED` in the resolution column) or never (Unconfirmed)? For RENAMED, open the successor: is it still the same responsibility, or was it split? Is the path generated or gitignored (`--all` shows `ignored`)? Does the line describe another codebase (P-8)? **Finding when** a live claim names a path that resolved once and resolves to nothing now. **Proof:** tier S — the line quoted, the `git log` commit that deleted or renamed it; after the fix, `knowledge-refs.py . --only=<file>:<line>` is quiet (V490).

### 2. Dead symbol (KN-02)

```
BAD:   Call `LegacyBillingService` (renamed BillingService) · `formatLegacyCents` (deleted) · `applyOrdersDelta` (deleted 0f8dfbff)
GOOD:  `ExternalThing` — never in this history: an external or framework symbol (P-5)
```
**Read the code:** Is the symbol the project's (removed in a commit here) or external (never in history: dropped)? Does it survive only in a comment (P-12: still dead)? For RENAMED, does the successor keep the signature the claim describes? `Class.method` with a plain lowercase member is not checked: the receiver carries the claim. **Finding when** the symbol once existed in tracked non-doc source and exists in none now. **Proof:** tier S + V491 — the successor named, or the deletion commit; the engine re-run on the line is quiet.

### 3. Dead command, script, skill or agent (KN-03)

```
BAD:   `pnpm run build:all` (no workspace defines it) · run `/eval` (in the pack catalog, not installed) · dispatch `@style-judge`
GOOD:  `pnpm test:e2e` (defined in apps/api) · `/setup-project` (global, P-23) · serves `/orders` (a route, no command cue)
       `bun run tools/load-check.ts` (runs a file) · `# this just died` in a shell comment (prose, P-33)
```
**Read the code:** Which workspace runs the command (`--filter`, `cd`)? Is the slash name installed globally, by a plugin, or a Claude Code built-in? Is it a renamed skill (a 2026-10-18 rename moved `detect-drift`'s engine to `align-detect`)? Is the `@name` an npm scope or a user mention? **Finding when** a command an agent is told to run resolves nowhere, or resolves only in the Refract catalog (uninstalled). **Proof:** tier S + V492 — the manifest or command set that lacks it; after the fix, the command resolves (the engine is quiet) and the documented invocation runs.

### 4. Dead knowledge cross-reference (KN-04)

```
BAD:   ai/patterns/README.md:17  `project-structure.md` → ai/patterns/project-structure.md was never installed
       CLAUDE.md:10  "follow ADR-0007" — no 0007-*.md in the ADR home (docs/decisions)
GOOD:  ADR-0042 inside a pack-generic body (P-10) · ADR-0001 with a file, even if superseded (decision-record-scan §3 owns that)
```
**Read the code:** Which ADR home did the engine detect (ledger line), and does the index agree? Was the pattern pack-installed and later pruned, or never shipped? **Finding when** a live line names a pattern, runbook or ADR id with no file. **Proof:** tier S + V490 — the home listing without the id; after the fix the id resolves or the line is gone.

### 5. Framework-only path (KN-05)

```
BAD:   > Auto-populated by `<refract>/apply-anchors.sh` from `.claude/codebase-profile.md` + `.claude/_codebase-scan.md`.   (341 anchors)
       `frontend/rules/migration-frontend.md` — a Refract pack path; the installed copy is .claude/rules/migration-frontend.md
GOOD:  `bin/deploy.sh` — the project's own script (it resolves)
```
**Read the code:** Does the project really have that file (then it resolves and never reaches this class)? Does `~/.claude/<path>` exist (the ledger says so — the path belongs to the framework)? Is the line generated (an anchor header)? **Finding when** an installed artifact tells the agent to read or run a path that exists only in the Refract repository. **Proof:** tier S + V490; the fix lands in the generator (`apply-anchors.sh`, IR-1), and a regenerate-twice run is byte-identical (tier U, V493).

### 6. Managed-marker corruption (KN-15)

```
BAD:   <!-- project-specific:start --> … <!-- project-specific:start --> … <!-- project-specific:end -->   (nested)
       six live blocks in one skill, five holding `...content...`
GOOD:  one column-0 start/end pair outside fences · a marker shown inside a ``` example (not live)
```
**Read the code:** Is the extra marker fenced (an example: not live)? Which block is the generator's current one? Does `audit-anchoring.sh has_live_anchor` read the same file the same way? **Finding when** a file has more than one live block, a start with no end, an end with no start, or a nested start. **Proof:** tier U + V493 — after `apply-anchors.sh` re-runs, one live pair remains, and a second run changes no byte.

## Proof

Oracles: [`proof-oracles.md`](../../../../snippets/proof-oracles.md) § Learning — V490 (re-resolve: the row fires on the seeded reference and is quiet after the fix; decoys quiet), V491 (symbol rename with successor), V492 (command resolves and runs), V493 (marker repair, regenerate twice). The engine's `--only=<file>:<line>` is the before/after probe `/refresh-knowledge --from-audit` records.

## Output

```
knowledge-ref-scan — census git (13,620 files) · corpus 478 scanned (124 live, 354 anchor-only; 164 history, 11 sinks excluded)
Lanes: paths (tsconfig aliases 1, workspace packages 4) · symbols (tokenised 12,215 files) · commands (project 147, global, catalog 161) · ADR home docs/decisions

1. .claude/commands/audit-distributed-tx.md:22 (+2 anchors)               [report-with-fix]   high
   §1 KN-01 — `apps/web/src/features/orders/list/lib/bulk-status-change.test.ts` DELETED in 2b2db317.
   Fix: regenerate the anchors (apply-anchors.sh) so "Where this applies" names a live file. Proof: --only quiet.
2. .claude/agents/*.md:15 (341 sites)                                      [report-with-fix]   medium
   §5 KN-05 — Refract's `apply-anchors.sh` path and `.claude/_codebase-scan.md` in every anchor header: framework paths.
   Fix: apply-anchors.sh stops writing them (IR-1); regenerate twice, byte-identical.
3. ai/references/tool-parity.md:114                                         [report-flagged]    medium
   §3 KN-03 — `/db-migration` resolves in no command set; no catalog entry either. Unproven: a renamed command?

Verification: 31 candidates → 18 findings · 9 unconfirmed · 2 hardening · 0 pre-existing · 2 refuted

Class coverage:
  §1  KN-01 dead path          checked (13,655 refs → 6 groups DELETED; 91 never-existed groups Unconfirmed; 169 P-8, 9 P-7, 49 P-4)
  §2  KN-02 dead symbol        checked (734 → 2 DELETED; 72 never in history, P-5)
  §3  KN-03 dead command       checked (217 scripts, 941 slash tokens → 1 unconfirmed)
  §4  KN-04 knowledge xref     checked (258 ADR ids, 6 pattern refs → 6)
  §5  KN-05 framework path     checked (8 groups, 690 sites)
  §6  KN-15 markers            checked (343 files with markers → 2)
```

`[report-with-fix]`: the reference resolved once and history names the successor or the deletion, and the fix is a repoint, a deleted line, or a regenerated derived file. `[report-flagged]`: one link is open (never in history, an ambiguous suffix, a command that may be renamed), and the row names it. The coverage block lists **all six** classes on every run: `checked (k → m)` only when the lane ran; `N/A (<reason>)` when the repo has no such surface (no knowledge layer, no ADR home); `blocked (<reason>)` when the engine or an `rg` exited 2.

## False positives / precedents

The verifier reads [`precedents/learning.md`](../../../../snippets/precedents/learning.md) and [`refute-before-report.md`](../../../../snippets/refute-before-report.md) § 10. The ones this skill meets most: § 1 generated targets, § 3 history, § 4 placeholders and templates, § 5 external symbols, § 6 abbreviations and aliases, § 7 outputs and plans, § 8 another codebase, § 10 pack-generic bodies, § 12 comment-only survivors, § 21 HTML comments, § 23 global commands, § 32 an oracle never written, § 33 commands in shell comments.

## When to run

- On any diff that renames, moves or deletes files, symbols, package scripts, commands, skills, agents, patterns or ADRs, or edits `CLAUDE.md`, `AGENTS.md`, `ai/**`, `.claude/rules/**` or an anchor block: the `/audit-knowledge` dispatch signal.
- On every whole-repo `/audit-knowledge`, reporting all six classes.
- After `/setup-project --refresh` or `apply-anchors.sh`: a regenerated anchor set must not carry a framework path or a doubled block.

## Halt conditions

- Do not report a row as confirmed until a verifier other than the run that found it has passed it through [`refute-before-report.md`](../../../../snippets/refute-before-report.md) (§ 10, with [`precedents/learning.md`](../../../../snippets/precedents/learning.md)). Under `/audit-knowledge` that happens in its verification phase; run standalone, apply the protocol as a separate second pass, tag those rows `self-verified`, and list the rest as Unconfirmed, Hardening, Pre-existing or Refuted. Never drop them.
- Halt on any row without the knowledge `file:line`, the reference as written, and its resolution.
- Never edit a derived file (an anchor block, an index) by hand to close a row: fix the generator and regenerate (tier U).
- Never write into the scanned repository: the engine reads, runs read-only git, and writes only under `$RUN`.
- Never print "references clean" without the coverage block. A lane that did not run (no git, no global dir) is `blocked` or `N/A`, never zero.
- Do not re-derive a class another skill owns (§ Boundaries). Cross-link it.

## Related

- `scripts/knowledge-refs.py` (this skill): §1–§6, `--only`, `--corpus`, `--expand`, `--all`, `--global-dir`, `--no-history`, `--self-test`. `scripts/kn_common.py`: the census, corpus, regions, resolver, ADR home and lockfile reader the other four learning engines import. Stdlib only, `python3 -I` safe; nothing is written under the scanned root.
- `knowledge-fact-scan` grades facts and citations that resolve; `memory-hygiene-scan` grades sink entries; `decision-record-scan` grades ADR lifecycle; `context-load-scan` grades what loads. `/audit-knowledge` dispatches all five; `/refresh-knowledge --from-audit` closes the rows with the engine re-run as proof.
- documentation `doc-drift-scan` (when installed) owns human docs and may call this engine with its own corpus. `apply-anchors.sh` (Refract) is where KN-05 and KN-15 are fixed.

Files in this skill

  • SKILL.md25.4 KB
  • scripts/kn_common.py30.7 KB
  • scripts/knowledge-refs.py47.9 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.