--- name: config-audit:knowledge-refresh description: Keep the best-practices register fresh — flag stale entries, poll sources for new/changed practices, with human-approved writes only argument-hint: "[--stale-after N] [--no-candidates]" allowed-tools: Read, Write, Edit, Bash, WebSearch, WebFetch model: opus --- # Config-Audit: Knowledge Refresh The "living" part of the living knowledge base. The optimization lens (`/config-audit optimize`) is only as good as the best-practices register it reads — and Claude Code moves fast. This command keeps `knowledge/best-practices.json` current in two ways: - **Stale check (deterministic):** every CONFIRMED entry carries a `source.verified` date. An entry older than the threshold (default **90 days**) is flagged for re-verification — its source may have changed since. - **Candidate poll (web):** scan the CC changelog + the Anthropic "Steering Claude Code" docs/blog for *new* best-practices the register doesn't yet hold, or *changed* guidance that contradicts an existing entry. **The Iron rule (Verifiseringsplikt): nothing is ever auto-written.** Every change — a bumped `verified` date, an updated claim, a brand-new entry — is presented to the user and applied only on explicit approval, and only after the live source has actually been re-read. No unverified claim enters the register. ## Implementation ### Step 1: Parse arguments From `$ARGUMENTS`: - `--stale-after N` → override the staleness threshold (integer days; default 90). - `--no-candidates` → run the deterministic stale check only; skip the web poll. Tell the user what's happening: ``` ## Knowledge Refresh Checking the best-practices register for stale entries (sources that may need re-verification) and polling for new Claude Code practices... ``` ### Step 2: Run the stale-check CLI ```bash TODAY=$(date +%F) STALE_AFTER="" if echo "$ARGUMENTS" | grep -qE -- '--stale-after'; then STALE_AFTER="--stale-after $(echo "$ARGUMENTS" | sed -nE 's/.*--stale-after[ =]+([0-9]+).*/\1/p')" fi node ${CLAUDE_PLUGIN_ROOT}/scanners/knowledge-refresh-cli.mjs \ --reference-date "$TODAY" $STALE_AFTER \ --output-file ~/.claude/config-audit/sessions/knowledge-refresh.json 2>/dev/null; echo $? ``` Exit code **0** = all fresh, **1** = some stale (advisory, normal), **3** = real error → "The refresh check couldn't run — the register file may be missing or invalid." ### Step 3: Read the payload + present stale entries Read `~/.claude/config-audit/sessions/knowledge-refresh.json` with the Read tool. It has `counts {total, stale, fresh}`, a `stale[]` array (each: `id, verified, ageDays, url, claim`), `referenceDate`, and `staleAfterDays`. Present the stale entries as a markdown table (per the UX rules — never show the raw JSON): | Entry | Claim (short) | Verified | Age (days) | Source | |-------|---------------|----------|------------|--------| If `counts.stale === 0`, say so plainly: "✓ All N register entries were re-verified within the last {staleAfterDays} days." Then continue to the candidate poll (unless `--no-candidates`). ### Step 4: Candidate + source-change poll (web — skip if `--no-candidates`) Tell the user this takes a moment ("Polling the changelog + Anthropic docs, ~20-40s..."). 1. **Re-verify each stale entry.** `WebFetch` the entry's `source.url` and check whether the claim it backs is **still accurate**. Three outcomes: - *Still holds* → propose bumping `source.verified` to today (no claim change). - *Changed* → propose an updated `claim`/`recommendation` quoting the new source text. - *Cannot verify* (page gone, paywalled, contradicts) → propose **nothing**; flag it "needs manual review" (Verifiseringsplikt: never bump a date you couldn't confirm). 2. **Look for new practices.** `WebSearch` the CC changelog and the "Steering Claude Code" blog/docs for steering/config guidance not already represented by an entry's `lensCheck`. For each genuine new practice, draft a **candidate** entry (next free `BP--NNN` id, `confidence: "confirmed"` only if a primary source confirms it — otherwise mark `inferred` and do **not** present it as user-facing). ### Step 5: Present everything for approval — write nothing yet Group the proposals and ask the user to approve per item: - **Re-verify (date bump):** "{id} — source re-read, claim still holds → bump verified to {today}?" - **Update (claim drift):** show the old vs. new claim + the quoted source line. - **New candidate:** show the drafted entry (id, claim, mechanism, recommendation, source). - **Needs manual review:** list, with why it couldn't be auto-verified. (No write offered.) Be explicit: **"I will not change any file until you approve specific items."** ### Step 6: Apply approved writes (only the approved ones) For each approved item: 1. Edit `knowledge/best-practices.json` — bump `source.verified`, update the `claim`/ `recommendation`, or append the new entry. Keep the file's 2-space JSON formatting. 2. If a `knowledge/*.md` mirror states the same fact, update it too so the human-readable mirror doesn't drift from the register. 3. **Validate before declaring done** — re-run the register schema check and confirm zero errors: ```bash node --test ${CLAUDE_PLUGIN_ROOT}/tests/lib/best-practices-register.test.mjs 2>&1 | tail -5 ``` If validation fails, revert that edit and report it — never leave the register invalid. Report exactly what changed (ids + fields), and what was deferred to manual review. ### Step 7: Next steps - `/config-audit optimize` — the lens now reads the refreshed register; re-run it to pick up any new or changed mechanism-fit rules. - Re-run `/config-audit knowledge-refresh --no-candidates` anytime for a quick staleness scan without the web poll. - Commit the register change (`knowledge/best-practices.json` + any `.md` mirror) with a `chore(knowledge):` message so the provenance bump is in git history. ## Notes - **Deterministic core, web-driven shell.** The stale classification is byte-stable and unit-tested (`tests/lib/knowledge-refresh.test.mjs`, `tests/scanners/knowledge-refresh-cli.test.mjs`); the candidate poll + writes are web/judgment-driven and deliberately **not** byte-stable (mirrors `/config-audit optimize`). - **Read-only CLI.** `knowledge-refresh-cli.mjs` never writes the register; all writes happen here, in the command, after approval. - The `-cli` suffix keeps it out of the scan-orchestrator, so the scanner count and the snapshot suite are unaffected.