docs-sync
Skill2 starsChanged 9 days agoMITView on GitHub
Sync docs with code changes: diffs branch, maps to affected docs, spawns parallel update agents. (repo)
46 other projects use a version of this.
Adopted by
Most recently taken up by
- julianosirtori/skillstheir own version, first seen Nov 8, 2026
- voyager67/AgentFieldkittheir own version, first seen Nov 8, 2026
- uwuclxdy/agenticattheir own version, first seen Nov 8, 2026
- kekzl/imptheir own version, first seen Nov 7, 2026
- sunholo-data/ailangtheir own version, first seen Nov 6, 2026
- yasik/agentlanetheir own version, first seen Nov 1, 2026
Used with
Projects with it also use tdd, code-review and 1 more.
Other files people use alongside this one.
Files found in the same public projects as a version of this one, more often than they turn up anywhere else. Each project counts once, large collections count for less, and this file's own repository is left out.
GoogleSkilltdd
Test-driven development. Use when the user wants to build features or fix bugs test-first, mentions "red-green-refactor", or wants integration tests.
Also in 4 projects that use this
GoogleSkillcode-review
Adversarial systems, concurrency, memory-model, and architecture code review protocol. Use this skill whenever asked to review code, PRs, diffs, or branches in Filament.
Also in 5 projects that use this
MicrosoftSkillhandoff
Compact the current conversation into a handoff document for another agent to pick up.
Also in 4 projects that use this
Other versions46 projects use a version of this.
Word for word · 0
None found.
Edited · 0
None found.
Wrote their own version · 46
- openai/openai-agents-python★ 31ksame name
- redis/node-redis★ 18ksame name
- redis/ioredis★ 15ksame name
- fossasia/visdom★ 10ksame name
- Kiln-AI/Kiln★ 5.3ksame name
- danielmeppiel/apm★ 4.2ksame name
- microsoft/apm★ 4.2ksame name
- openai/openai-agents-js★ 4ksame name
- pnp/powershell★ 912same name
- strands-agents/box★ 503same name
36 more not listed
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
The file
Show its rules and text
We split this skill into the rules it gives an agent
17 rules. 0 are common, 10 are distinctive, and 7 are very specific to this project.
0
Common
Most of the 36 edited versions we read keep these.
10
Distinctive
This author's own choices. Worth a look.
7
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 52
Before using the config above, run a lightweight drift check (advisory only.
- Very specific: line 55
If EITHER differs, count the intervening commits (git rev-list --count <generated-commit>..HEAD 2>/dev/null) and surface one line, then …
- Distinctive: line 57
If the generated commit is unreachable (history rewritten) or the manifest set changed, surface the nudge regardless of commit count.
- Very specific: line 64
If this command was invoked via a local config wrapper (you see a ## Repo Config section earlier in the prompt), use that config to …
- Very specific: line 70
If the config overlay date is more than 90 days old, mention: "Your /docs-sync config is over 90 days old — consider running /jacked-setup …
- Very specific: line 72
If no ## Repo Config section is present, run all discovery steps normally.
- Distinctive: line 78
Run these commands to gather context (all safe, read-only):
- Distinctive: line 121
If Repo Config or the user targets an alias, redirect the dispatch to the canonical target.
- Distinctive: line 122
If CLAUDE.md and AGENTS.md exist as two separate, non-symlinked files, audit both independently AND diff their content — flag any …
- Distinctive: line 148
If there are no changes (empty diff), do not stop — proceed to Step 2.5 in case stale docs need auditing.
- Very specific: line 166
Use git's last-commit timestamp throughout (filesystem mtime is unreliable — it changes on checkout, with a stat fallback for untracked …
- Very specific: line 319
Use the SYMBOL-DRIFT output two ways:
- Very specific: line 339
If
## Change-to-Doc Mapexists in Repo Config: Use the table to determine which doc files are affected. - Distinctive: line 341
If no map exists (runtime discovery): Use this default mapping:
- Distinctive: line 355
If the combined set (branch-affected ∪ audit queue) is empty, say: "Changes don't affect any docs, and no stale or symbol-drifted docs …
- Distinctive: line 533
After agents complete, check if the changes introduced anything with no existing doc coverage:
- Distinctive: line 604
Test-only changes (unless they change how to run tests)
“Common” is measured: kept by at least 6 in 10 of the 36 edited versions of this file we could read. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Generated by /jacked-setup - 2026-11-03 | Template v2 | Engine: jacked v0.110.2
Standalone - no dependencies. Commit this file. To update: uv tool install --upgrade claude-jacked && jacked install && /jacked-setup docs-sync
Repo Config
- Project: claude-jacked
- Base Branch: master
- Stack: Python (FastAPI CLI + background service); vanilla JS/HTML/CSS dashboard under
jacked/data/web/ - Doc style: README, SECURITY.md and other user-facing docs use ASD-STE100 Simplified Technical English (active voice, one instruction per sentence, short sentences) and carry no em-dashes. Docstrings follow the same STE rules. Internal design docs and plans are exempt from the em-dash ban.
Doc Inventory
README.md(sections: What you get, Quick start, Your dashboard, Table of Contents, What's Included, Web Dashboard (Remote Access, Account switching, Plans and usage windows), Background Service and Tray Icon, Upgrading (the upgrade is a transaction),/recover,/whats-nextambition, Built-in Reviewers and Commands (Skills, Skill Packs, Skill Listing Budget, DCR Review Engine, Memory Vault, Open work at session start, Hook and settings integrity, Statusline, QA Browser Testing, Asana in/whats-next), Sound Notifications, FAQ, Uninstall / Troubleshooting, Version History, Advanced / Technical Reference)CLAUDE.md(Project Rules, Environment: the uv-only + test-running rules)JACKED_GUARDRAILS.md(Quality Gates, Size Limits, Structure, Error Handling, Testing, Security, Hook and Memory Integrity (MemoryTrap): case study, posture rules, what jacked does, limit of the threat model; Naming, Git, Python-Specific)SECURITY.md(Report a vulnerability, Supported versions, What jacked protects, How releases are built)lessons.md(recurring pitfalls; a Claude-instruction file, stays Markdown)docs/architecture/(oauth-and-credential-flows.md,auto-swap-system.md,work-ledger.html: where rules, issues and PRs each belong)docs/(design/plans/research/lockdown: internal design notes, not user-facing; touch only when a plan they describe actually changes)jacked/data/commands/goal-maker.md## Ledger contractandjacked/data/skills/whats-next/SKILL.md(shipped skill text that defines the ledger; tests pin it:tests/unit/test_long_run_ledger_contract.py)x-article.md(launch post draft; marketing copy, not a reference doc)- No
_wiki/; no separateCHANGELOG.md(the changelog lives in README's "Version History" table) - Doc dirs:
docs/(md + html, depth 3 incl.architecture/,design/,plans/,lockdown/,research/,superpowers/),design/(md + html, incl. memory-vault and skill-diet design docs),.claude/research/(local html research reports, gitignored)
Change-to-Doc Map
| Change Category | Affected Docs |
| Pipeline/Architecture | docs/architecture/*; README.md (Web Dashboard / Background Service) |
SessionStart hook steps (jacked/data/hooks/session_start.py, git_reality.py, issue_queue.py, load budget) | README.md (Open work at session start, Memory Vault, Hook and settings integrity); docs/architecture/work-ledger.html |
Integrity tripwire / quarantine (jacked/integrity*.py, jacked/memory/quarantine.py, injection_shapes.py) | README.md (Hook and settings integrity); JACKED_GUARDRAILS.md (MemoryTrap section); SECURITY.md (What jacked protects) |
Git guard / untrusted-checkout reads (jacked/git_guard.py) | SECURITY.md (What jacked protects); JACKED_GUARDRAILS.md (Security) |
Issue queue / work ledger (jacked/service/issue_queue_refresh.py, jacked/issues_cli.py, goal-maker Ledger contract, whats-next) | docs/architecture/work-ledger.html; README.md (Open work at session start, /whats-next ambition) |
| Configuration / Env / Install | README.md (Quick start, Your dashboard, Upgrading); CLAUDE.md (Environment) |
Commands/CLI (jacked/cli.py, integrity_cli.py, issues_cli.py) | README.md (What's Included, Quick start, Commands, Hook and settings integrity) |
| Dependencies | README.md (Quick start install lines); pyproject.toml; uv.lock |
CI / release workflows (.github/workflows/) | SECURITY.md (How releases are built); README.md if user-visible |
UI/Frontend (jacked/data/web/) | README.md (Web Dashboard, Your dashboard) |
Models/Schemas (jacked/web/database.py) | docs/architecture/*; README.md if user-visible |
Memory Vault (jacked/memory/, jacked/data/hooks/memory_*.py) | README.md (Memory Vault section); design/memory-vault-design.html + design/memory-vault-implementation-plan.html if the design itself changed |
Guardrails / size limits (tests/unit/test_module_size_ratchet.py) | JACKED_GUARDRAILS.md (Size Limits) |
| Tests | CLAUDE.md (test-running rules) |
| Release / version bump | README.md (Version History) |
<!-- Staleness fingerprint - the engine compares these against the live repo on each run -->- Generated at commit: 68e95e00cc2ee874418c3fa016919e13152d3f39
- Detected stack: pyproject.toml
Config Staleness Check
Before using the config above, run a lightweight drift check (advisory only; never block on it):
git rev-parse HEADand compare to Generated at commit above.ls package.json pyproject.toml go.mod Cargo.toml setup.py Gemfile pom.xml build.gradle composer.json mix.exs 2>/dev/nulland compare the manifest set to Detected stack above.- If EITHER differs, count the intervening commits (
git rev-list --count <generated-commit>..HEAD 2>/dev/null) and surface one line, then continue:⚠️ This
/docs-syncconfig was generated N commits ago and the stack/paths may have drifted. Re-run/jacked-setup docs-syncto refresh. If the generated commit is unreachable (history rewritten) or the manifest set changed, surface the nudge regardless of commit count. Never stop or skip the run on a staleness mismatch.
<!-- ENGINE - DO NOT EDIT BELOW THIS LINE -->Config Override
If this command was invoked via a local config wrapper (you see a ## Repo Config section earlier in the prompt), use that config to accelerate sync:
- Base Branch specified? → Use it instead of auto-detecting in Step 1
- Doc Inventory listed? → Skip doc discovery in Step 1, use the listed files (validate with
lsfirst, skip missing). This also seeds Step 2.5's staleness/symbol-drift sweep — if the inventory names living-doc locations outside the default set (root*.md,docs/,_wiki/,CLAUDE.md/AGENTS.md), e.g.specs/,documentation/,guides/,adr/, you MUST add them toDOC_CANDIDATESthere. A config-declared source-of-truth doc must never be silently skipped by the sweep. - Change-to-Doc Map specified? → Use it in Step 3 instead of the default mapping
- Staleness Defaults specified (age / drift days)? → Use them as the repo-wide defaults in Step 2.5 (a per-doc
ttl_daysfrontmatter contract still wins over the repo default). To make this actually take effect, substitute the configured values inline into the Step 2.5a bash: replaceDEFAULT_AGE_DAYS=${DOCS_SYNC_AGE_DAYS:-90}with the configured age (e.g.DEFAULT_AGE_DAYS=60) andDEFAULT_DRIFT_DAYS=${DOCS_SYNC_DRIFT_DAYS:-30}with the configured drift, OR exportDOCS_SYNC_AGE_DAYS/DOCS_SYNC_DRIFT_DAYSbefore running that block so the${VAR:-default}expansion picks them up. The90/30literals are field fallbacks only — when the config supplies values, they must override.
If the config overlay date is more than 90 days old, mention: "Your /docs-sync config is over 90 days old — consider running /jacked-setup docs-sync to refresh it."
If no ## Repo Config section is present, run all discovery steps normally.
Step 1: Discover Repo Context
Skip this step entirely if
## Repo Configwas found above.
Run these commands to gather context (all safe, read-only):
REPO_ROOT=$(git rev-parse --show-toplevel 2>/dev/null || pwd)
echo "REPO_ROOT=$REPO_ROOT"
echo "REPO_NAME=$(basename "$REPO_ROOT")"
# Detect base branch
git symbolic-ref refs/remotes/origin/HEAD 2>/dev/null | sed 's|refs/remotes/origin/||' || echo "main"
# Doc files at repo root
ls README.md CONTRIBUTING.md CHANGELOG.md LICENSE.md AGENTS.md 2>/dev/null
# Wiki structure
ls -d _wiki 2>/dev/null
ls _wiki/*.md 2>/dev/null | head -30
# Agent-instruction files (CLAUDE.md / AGENTS.md) sections
grep -n "^#" CLAUDE.md 2>/dev/null | head -20
grep -n "^#" AGENTS.md 2>/dev/null | head -20
# docs/ and specs/ directories (this project defaults human docs to HTML; sweep both,
# and go deep — a real spec tree lives at docs/superpowers/specs/, depth 3)
find docs specs \( -name "*.md" -o -name "*.html" \) 2>/dev/null | head -30
# Other root-level markdown
ls *.md 2>/dev/null
# Symlink map — CLAUDE.md is frequently a symlink to AGENTS.md (cross-tool compat).
# Editing the alias leaves the canonical file stale, or silently forks the two.
ls -la *.md 2>/dev/null
for f in *.md; do
[ -L "$f" ] && echo "SYMLINK: $f -> $(readlink -f "$f" 2>/dev/null || readlink "$f")"
doneBuild a doc inventory from the results, checked for completeness against the three doc layers — a whole missing layer is itself a gap worth surfacing:
- User-facing — README.md, docs/ guides, quick-starts, SDK/usage docs. What a consumer reads.
- Contributor-facing — CONTRIBUTING.md, architecture docs, _wiki/. How to build, test, and extend.
- Agent-facing — CLAUDE.md and AGENTS.md. Instructions coding agents (Claude, Cursor, Codex, Copilot) read. AGENTS.md is a first-class surface now — never skip it.
Symlink resolution (do this before any dispatch). From the ls -la / SYMLINK output, resolve every root-level markdown symlink to its canonical target:
- Record each canonical (real) file and its aliases. Dispatch exactly ONE audit agent per canonical file — never against an alias. Editing the alias path leaves the canonical agent-instructions file stale, or silently forks the two.
- If Repo Config or the user targets an alias, redirect the dispatch to the canonical target.
- If CLAUDE.md and AGENTS.md exist as two separate, non-symlinked files, audit both independently AND diff their content — flag any divergence (a rule present in one but not the other) for human review in Step 6.
- Carry the canonical↔alias map forward to Step 6 so the relationship is reported.
Step 2: Diff Analysis
Diff the current branch against the base branch:
# Get base branch (from Repo Config or detected above)
BASE_BRANCH=$(git symbolic-ref refs/remotes/origin/HEAD 2>/dev/null | sed 's|refs/remotes/origin/||' || echo "main")
# Diff against the MERGE-BASE, not the moving base-branch tip. On long-lived
# branches the base tip advances independently, so diffing against it re-flags
# changes already merged to main and inflates false drift. merge-base is the
# stable fork point — use it as the reference for the diff AND for any downstream
# age-delta comparison.
MERGE_BASE=$(git merge-base origin/${BASE_BRANCH} HEAD 2>/dev/null || git merge-base ${BASE_BRANCH} HEAD 2>/dev/null)
echo "MERGE_BASE=${MERGE_BASE}"
DIFF_REF=${MERGE_BASE:-${BASE_BRANCH}}
# Summary of changes
git diff ${DIFF_REF}...HEAD --stat 2>/dev/null || git diff ${DIFF_REF}..HEAD --stat
git diff ${DIFF_REF}...HEAD --name-only 2>/dev/null || git diff ${DIFF_REF}..HEAD --name-only
git log ${DIFF_REF}..HEAD --oneline 2>/dev/nullIf there are no changes (empty diff), do not stop — proceed to Step 2.5 in case stale docs need auditing. Otherwise, categorize changes below.
Categorize all changes into these buckets:
| Category | Signals |
| Pipeline/Architecture | New entry points, changed main flows, new modules, renamed directories |
| Configuration | New env vars, changed settings, new config files |
| Commands/CLI | New flags, changed usage, new subcommands, changed arguments |
| Models/Schemas | New models, changed fields, migration files |
| Tests | New test patterns, changed test commands, new test utilities |
| Dependencies | New requirements, changed versions, new package managers |
| UI/Frontend | New pages, changed components, route changes |
Step 2.5: Stale Doc Detection (mandatory)
Documentation rots silently when PRs forget to run /docs-sync. Catch that drift here. A doc joins the audit queue if it is stale by age/TTL (2.5a) OR has symbol drift (2.5b) — regardless of whether the current branch touches it.
Use git's last-commit timestamp throughout (filesystem mtime is unreliable — it changes on checkout, with a stat fallback for untracked files).
Run the three bash blocks in this step in a single shell session (concatenate them into one Bash call). Blocks 2.5a and 2.5b reuse
DOC_CANDIDATESand theis_excluded/doc_ttl_dayshelpers defined here — a fresh shell would lose them and silently stop excluding changelogs.
NOW=$(date +%s)
# Collect candidate doc files (root markdown, docs/, _wiki/, agent-instruction files).
# IMPORTANT: if the Repo Config ## Doc Inventory (or any doc's `sources:` frontmatter)
# names living-doc locations OUTSIDE this default set — e.g. specs/, documentation/,
# guides/, adr/ — add a matching `find` line below BEFORE running, so those docs are
# swept for staleness AND symbol drift too. Step 1 and Step 3 already honor the
# inventory; this sweep MUST match it, or config-declared source-of-truth docs are
# silently skipped (the #1 reported gap).
DOC_CANDIDATES=$(
{
# Sweep .html alongside .md: this project defaults human docs to HTML, and
# several repos keep canonical docs in specs/ or an all-.html docs/ tree —
# an .md-only sweep silently skips them.
ls *.md *.html 2>/dev/null
find docs \( -name "*.md" -o -name "*.html" \) 2>/dev/null
find _wiki \( -name "*.md" -o -name "*.html" \) 2>/dev/null
find specs \( -name "*.md" -o -name "*.html" \) 2>/dev/null
find . -maxdepth 4 \( -name "CLAUDE.md" -o -name "AGENTS.md" \) 2>/dev/null
# + config-declared doc dirs from ## Doc Inventory — add one per repo, e.g.:
# find documentation \( -name "*.md" -o -name "*.html" \) 2>/dev/null
} | sort -u
)
# Changelogs / historical / migration docs legitimately reference deleted code and
# old versions — exclude them from BOTH staleness and symbol-drift. A doc may also
# opt out with `freshness: { exclude: true }` (or `freshness_exclude: true`) in frontmatter.
is_excluded() {
case "$(basename "$1" | tr 'A-Z' 'a-z')" in
changelog.md|changelog*.md|history.md|changes.md|releases.md|migration*.md|upgrading.md) return 0;;
esac
case "$1" in
*/migrations/*|*/changelog/*|*/history/*) return 0;;
esac
head -20 "$1" 2>/dev/null | grep -qiE '(freshness_)?exclude:[[:space:]]*true' && return 0
return 1
}2.5a — Staleness (age + TTL)
One global 30-day cutoff over-flags slow-moving architecture docs and under-flags fast-moving quick-starts. Use tiered thresholds instead (docvet field defaults: age 90d, drift 30d):
- Per-doc TTL — if the doc declares
ttl_days: N(orfreshness: { ttl_days: N }) in frontmatter, that wins. - Repo-wide default — else the Repo Config overlay's staleness default (
DOCS_SYNC_AGE_DAYS), if set. - Field default — else 90 days.
A doc is also flagged if its declared sources: globs were edited >30d more recently than the doc itself (drift), even when the doc is younger than its TTL.
If the Repo Config overlay specified Staleness Defaults, substitute those values inline here before running: set
DEFAULT_AGE_DAYS/DEFAULT_DRIFT_DAYSto the configured numbers (or exportDOCS_SYNC_AGE_DAYS/DOCS_SYNC_DRIFT_DAYSahead of this block). The:-90/:-30literals below are the field fallback used only when no config value is supplied.
DEFAULT_AGE_DAYS=${DOCS_SYNC_AGE_DAYS:-90}
DEFAULT_DRIFT_DAYS=${DOCS_SYNC_DRIFT_DAYS:-30}
doc_ttl_days() { # per-doc ttl_days frontmatter, else repo default
local t
t=$(head -20 "$1" 2>/dev/null | grep -iE 'ttl_days:' | head -1 | grep -oE '[0-9]+' | head -1)
[ -n "$t" ] && echo "$t" || echo "$DEFAULT_AGE_DAYS"
}
# Iterate with `while read` (not `for doc in $DOC_CANDIDATES`): unquoted `$var`
# word-splits in bash but NOT in zsh, so a `for` over a multiline var iterates
# once on the whole blob under zsh (the default macOS shell). A here-string is
# shell-agnostic.
STALE_DOCS=()
while IFS= read -r doc; do
[ -z "$doc" ] && continue
[ -f "$doc" ] || continue
is_excluded "$doc" && { echo "SKIP (changelog/historical/excluded): $doc"; continue; }
TS=$(git log -1 --format=%ct -- "$doc" 2>/dev/null)
[ -z "$TS" ] && TS=$(stat -f %m "$doc" 2>/dev/null || stat -c %Y "$doc" 2>/dev/null)
[ -z "$TS" ] && continue
DAYS_OLD=$(( (NOW - TS) / 86400 ))
TTL=$(doc_ttl_days "$doc")
reason=""
[ "$DAYS_OLD" -gt "$TTL" ] && reason="${DAYS_OLD}d old > ${TTL}d ttl"
# drift: newest commit touching any declared `sources:` glob vs the doc's own
# last edit. Hand the pathspec to git (quoted) so git does the glob match —
# avoids shell glob-expansion, which differs across bash/zsh.
newest=0
globs=$(awk 'NR==1&&/^---/{fm=1;next} fm&&/^---/{exit} fm&&/^sources:/{s=1;next} fm&&/^[^[:space:]-]/{s=0} fm&&s&&/^[[:space:]]*-[[:space:]]/{sub(/^[[:space:]]*-[[:space:]]*/,"");sub(/[[:space:]]+$/,"");print}' "$doc" 2>/dev/null)
while IFS= read -r glob; do
[ -z "$glob" ] && continue
sts=$(git log -1 --format=%ct -- "$glob" 2>/dev/null)
[ -n "$sts" ] && [ "$sts" -gt "$newest" ] && newest=$sts
done <<< "$globs"
if [ "$newest" -gt 0 ]; then
DELTA=$(( (newest - TS) / 86400 ))
[ "$DELTA" -gt "$DEFAULT_DRIFT_DAYS" ] && reason="${reason:+$reason; }sources ${DELTA}d newer than doc (drift)"
fi
if [ -n "$reason" ]; then
echo "STALE: $doc ($reason)"
STALE_DOCS+=("$doc")
fi
done <<< "$DOC_CANDIDATES"2.5b — Symbol drift (deterministic pre-pass)
The field's #1 cheap drift signal: a 2024 study found 28.9% of repos document a symbol that no longer exists (wrong for 4.7 years on average). Before any LLM call, extract the identifiers each doc references and confirm they still exist in the codebase.
# Search only CODE for symbols. Exclude *.md so a symbol surviving only in prose
# (not code) still reads as missing — otherwise the doc's own backtick matches
# itself and hides the drift. Use a function (not a flags-in-a-variable) so it is
# shell-agnostic: unquoted `$VAR` word-splits in bash but NOT in zsh, which would
# pass the whole flag string as one bogus argument and silently skip the exclude.
code_grep() {
grep -rqwI --exclude='*.md' \
--exclude-dir=.git --exclude-dir=node_modules --exclude-dir=vendor \
--exclude-dir=dist --exclude-dir=build --exclude-dir=.venv "$@"
}
SYMBOL_DRIFT_DOCS=()
while IFS= read -r doc; do # while-read, not `for in $var` (zsh-safe)
[ -z "$doc" ] && continue
[ -f "$doc" ] || continue
is_excluded "$doc" && continue
MISSING=()
TOKENS=$(grep -oE '`[^`]+`' "$doc" 2>/dev/null | tr -d '`' | sort -u)
while IFS= read -r tok; do
[ -z "$tok" ] && continue
word=$(echo "$tok" | awk '{print $1}' | tr -d '()[]{},;:') # first word, strip call punctuation
[ -z "$word" ] && continue
case "$word" in
*/*|*.py|*.js|*.ts|*.tsx|*.go|*.rs|*.java|*.rb|*.json|*.yaml|*.yml|*.toml) # file path
[ -e "$word" ] || git ls-files --error-unmatch "$word" >/dev/null 2>&1 || MISSING+=("path:$word");;
--*) # CLI flag
code_grep -- "$word" . 2>/dev/null || MISSING+=("flag:$word");;
*.*) # dotted Cls.method — present only if EVERY component resolves
ok=1
for part in $(echo "$word" | tr '.' ' '); do
code_grep -- "$part" . 2>/dev/null || { ok=0; break; }
done
[ "$ok" = 0 ] && MISSING+=("symbol:$word");;
*[a-zA-Z]*) # bare identifier / env var
code_grep -- "$word" . 2>/dev/null || MISSING+=("symbol:$word");;
esac
done <<< "$TOKENS"
if [ "${#MISSING[@]}" -gt 0 ]; then
echo "SYMBOL-DRIFT: $doc -> ${MISSING[*]}"
SYMBOL_DRIFT_DOCS+=("$doc")
fi
done <<< "$DOC_CANDIDATES"The regex-on-backticks pass above is the starter. For polyglot repos where backtick-grep is too noisy, the upgrade path is tree-sitter / LSP (SCIP) symbol indexing for precise function/class/signature resolution — swap it in there.
Use the SYMBOL-DRIFT output two ways:
- Queue expansion — any doc with one or more missing symbols joins the audit queue (Step 4) even if it is fresh and untouched by the branch.
- Concrete Pass-2 worklist — pass that doc's missing-symbol list verbatim into its agent prompt as a
## Symbol worklistsection. This turns Pass 2 from "notice every claim unprompted" into "clear this concrete list."
False-positive guards (mandatory):
- A dotted
Cls.methodcounts as PRESENT if every component resolves — only flag when a component is genuinely gone. - Backticked English words, shell builtins, and literals (
true,null,cd,ls) are not symbols. The agent must not "fix" them. - The grep is a worklist, not a verdict — the agent confirms each before editing or removing.
- Excluded docs (changelog/historical/migration,
freshness: exclude) are skipped here too.
Assemble the audit queue
The audit queue = STALE_DOCS ∪ SYMBOL_DRIFT_DOCS. These docs go through the full audit pipeline in Step 4 even if the current branch doesn't touch their related code.
- Queue empty AND no branch changes → say "No branch changes, no stale docs, no symbol drift. Nothing to sync." Stop.
- Queue empty but branch changes exist → proceed to Step 3 with branch-driven mapping only.
- Otherwise the queued docs merge into Step 4 dispatch: stale docs get the
fresh-auditflag (no diff context — verify the whole doc against current code); symbol-drift docs carry their missing-symbol worklist into the prompt; a doc in both modes gets both.
Step 3: Map Changes to Docs
If ## Change-to-Doc Map exists in Repo Config: Use the table to determine which doc files are affected. Validate each target path still exists before including it — skip missing ones silently.
If no map exists (runtime discovery): Use this default mapping:
| Change Category | Likely Affected Docs |
| Pipeline/Architecture | README.md (architecture section), CLAUDE.md / AGENTS.md |
| Configuration | README.md (env vars / config section) |
| Commands/CLI | README.md (usage section) |
| Dependencies | README.md (install / requirements section) |
| UI/Frontend | README.md (features section) |
| Models/Schemas | _wiki/ pages if they exist, CLAUDE.md / AGENTS.md |
| Tests | README.md (testing section) |
Filter to only doc files that actually exist. Merge with the audit queue (STALE_DOCS ∪ SYMBOL_DRIFT_DOCS) from Step 2.5.
If the combined set (branch-affected ∪ audit queue) is empty, say: "Changes don't affect any docs, and no stale or symbol-drifted docs found." Stop.
Step 4: Spawn Audit Agents (Multi-Pass Verification)
Spawn one agent per doc file in the combined set. Agents run in parallel - send all Agent tool calls in a single message. Tiered dispatch: doc auditing/writing from vetted material is volume work - on a Fable-class session (any session model above Opus), spawn every doc agent with explicit model: "opus" and keep the one-agent-per-doc shape (the shape follows the model the agents run on; Opus agents doing one focused doc each beats fewer consolidated ones). The parent loop keeps the judgment: reading the agents' reports and deciding what ships. On Opus and below, spawn with the session's model (never below Opus).
Every agent runs a 3-pass verification protocol (described inside the agent prompt). This is non-negotiable. Single-pass updates produce confident-sounding-but-wrong docs that mislead future readers.
Dispatch modes:
branch-driven— doc is in the branch-change map. Agent gets diff context.fresh-audit— doc is inSTALE_DOCS. Agent gets NO diff (might be stale in ways nobody flagged). Must audit the entire file against current code from scratch.both— doc is in both. Agent does fresh-audit AND incorporates branch changes.symbol-drift— doc is inSYMBOL_DRIFT_DOCS(Step 2.5b found backticked references that no longer resolve). Combinable with any mode above. The agent gets the missing-symbol worklist and must verify/fix each.
Symbol worklist. When a doc carries symbol drift, add a ## Symbol worklist section to its prompt listing the exact path:/symbol:/flag: entries from Step 2.5b, with this instruction: "These backticked references could not be located in the codebase. Verify each — a backticked prose word or literal (true, null, cd) is NOT a symbol and must be left alone — then fix or remove the genuinely-dead ones. Pass 2 must clear this list."
Use the appropriate template below. Each template embeds the 3-pass protocol verbatim — do not summarize or shorten it when constructing the agent prompt.
The 3-Pass Verification Protocol (embedded in every agent prompt)
You will run THREE passes over this doc. Do not skip passes. Do not collapse them. Each pass has a different lens — running them separately catches different failure modes.
PASS 1 — UPDATE
1. Read the entire target doc file from line 1 to EOF. Do not skim. Do not jump to "the relevant section" — you do not yet know what is relevant.
2. Read every source file referenced in your Context section, fully. If the doc mentions a file, function, env var, CLI flag, or directory, locate it in the codebase and read it. Do not trust the doc's description over the code.
3. Make edits. Update factual claims that are wrong. Update examples that no longer run. Update file paths that have moved. Update version numbers, env var names, and command syntax that have drifted. Do not rewrite voice, structure, or tone.
PASS 2 — CROSS-CHECK (the "lying detector" pass)
After Pass 1, re-read the doc you just edited. For EVERY factual claim that remains in the doc — including ones you didn't touch — verify it against the current code:
- Every file path mentioned: does the file exist at that path right now? Run ls or Read to confirm.
- Every function/class/method named: does it exist with that signature? Grep to confirm.
- Every env var: is it actually read by the code? Grep for it.
- Every CLI flag, subcommand, or argument: does the current CLI accept it? Read the argparse/click definitions.
- Every code example or snippet: would it actually run today? Trace it mentally against the current code.
- Every cross-reference to another doc or section: does the target still exist?
For each claim that fails verification, fix it. If you cannot verify a claim with reasonable effort, mark it: insert an HTML comment <!-- docs-sync: unable to verify --> next to it and note it in your final report. Do not silently leave unverifiable claims.
PASS 3 — MISDIRECTION AUDIT (the "fresh reader" pass)
Re-read the doc one more time, this time as if you were a developer encountering this codebase for the first time. For each section ask:
- If I followed these instructions literally, would I succeed, or would I hit an error?
- Does this section accurately describe what the code does, or does it describe what it USED to do, or what someone WANTED it to do?
- Are there critical setup steps, dependencies, or gotchas not mentioned that the code clearly requires?
- Is anything dangerously misleading — wrong defaults, wrong order of operations, wrong assumptions about state?
Fix anything that would misdirect a fresh reader. Misdirection is worse than absence — silence is honest, wrong instructions are not.
OUTPUT
At the end, report:
- Sections updated and why
- Verification failures discovered in Pass 2 (and how you fixed them)
- Misdirection issues caught in Pass 3 (and how you fixed them)
- Any claims left marked as unverifiable and whyREADME Agent — branch-driven or fresh-audit:
You are a README auditor and updater. Your job is to make README.md perfectly accurate against the current codebase. Future readers will rely on this doc — every wrong claim is a trap.
## Mode
<branch-driven | fresh-audit | both>
## Context (branch-driven or both)
Base branch: <base>
Changes summary:
<paste git diff --stat output>
Changed files:
<paste git diff --name-only output>
Commit messages:
<paste git log --oneline output>
## Context (fresh-audit or both)
This doc is past its freshness window (its `ttl_days`, or the 90-day field default). The codebase has likely drifted. Audit the entire README against the current code. Do not assume any claim is correct just because it has been there for a while.
## Symbol worklist (symbol-drift mode only)
<paste this doc's missing-symbol list from Step 2.5b, with the "verify or remove" instruction>
## Style constraints
- Match existing voice, formatting, and structure
- Do not add emojis unless the existing README uses them
- Do not rewrite sections that are still accurate, even if you would phrase them differently
- If a new feature exists with no README coverage, add a minimal section in the appropriate location
## Verification protocol
<paste the entire 3-Pass Verification Protocol above, verbatim>Wiki Agent — branch-driven or fresh-audit:
You are a wiki page auditor and updater for pages under _wiki/. Your job is to make these pages perfectly accurate against the current codebase.
## Mode
<branch-driven | fresh-audit | both>
## Target pages
<list specific pages — one agent per page if pages are large, otherwise group related pages>
## Context (branch-driven or both)
Base branch: <base>
Changes summary:
<paste git diff --stat output>
## Context (fresh-audit or both)
This page is past its freshness window (its `ttl_days`, or the 90-day field default). Audit the entire page against the current code from scratch.
## Symbol worklist (symbol-drift mode only)
<paste this page's missing-symbol list from Step 2.5b, with the "verify or remove" instruction>
## Style constraints
- Match existing wiki formatting and structure
- If _wiki/_Sidebar.md exists and you added/removed pages, update the sidebar
- Cross-link to related wiki pages when natural; check those links resolve
## Verification protocol
<paste the entire 3-Pass Verification Protocol above, verbatim>Agent-instruction Agent (CLAUDE.md / AGENTS.md) — branch-driven or fresh-audit:
You are an agent-instruction auditor and updater for <CLAUDE.md | AGENTS.md>. Your job is to make these project instructions factually accurate against the current codebase. These files are read by coding agents (Claude, Cursor, Codex, Copilot) — a wrong instruction misdirects every future agent run.
## Target file
<the CANONICAL path resolved in Step 1 — never an alias/symlink>
## Mode
<branch-driven | fresh-audit | both>
## Context (branch-driven or both)
Base branch: <base>
Changes summary:
<paste git diff --stat output>
## Context (fresh-audit or both)
This file is past its freshness window (its `ttl_days`, or the 90-day field default). Audit the entire file against the current codebase.
## Symbol worklist (symbol-drift mode only)
<paste this file's missing-symbol list from Step 2.5b, with the "verify or remove" instruction>
## Divergence check (only if CLAUDE.md and AGENTS.md both exist as separate files)
The repo carries CLAUDE.md and AGENTS.md as two independent (non-symlinked) files. Compare them: any rule present in one but absent or contradictory in the other is divergence — flag it for human review with an HTML comment; do NOT unilaterally reconcile them.
## Scope constraints
- Update factual descriptions: architecture, testing commands, env vars, file paths, build steps
- Do NOT add new behavioral rules or instructions on your own
- Do NOT remove existing rules unless they unambiguously reference deleted code
- If a rule references a removed file/function, update it to reference the replacement (if there is one) or flag it for human review with an HTML comment
## Verification protocol
<paste the entire 3-Pass Verification Protocol above, verbatim>Generic Doc Agent — for any other markdown file in the stale audit queue (e.g., docs/architecture.md, CONTRIBUTING.md):
You are a documentation auditor for <doc path>. Your job is to make this doc perfectly accurate against the current codebase.
## Mode
<fresh-audit (past its freshness window) | symbol-drift | both>
## Symbol worklist (symbol-drift mode only)
<paste this doc's missing-symbol list from Step 2.5b, with the "verify or remove" instruction>
## Style constraints
- Match existing voice, formatting, and structure
- Preserve intentional formatting choices (callouts, tables, code blocks)
## Verification protocol
<paste the entire 3-Pass Verification Protocol above, verbatim>Step 5: Suggest New Docs
After agents complete, check if the changes introduced anything with no existing doc coverage:
- New env vars with no env var table in README
- New CLI flags with no usage section
- New major features with no feature description
- New dependencies with no install instructions
For each gap found, suggest (but do NOT auto-create):
Suggestion: <description> — consider adding a section to <doc file>Step 6: Stage and Report
Aggregate every agent's verification report. Show a structured summary:
## docs-sync complete
**Freshness summary** (advisory — does not gate; a trackable signal for a human or future CI wrapper)
| Doc | Status | Missing symbols | Days since edit |
|-----|--------|-----------------|-----------------|
| README.md | drifted→fixed | 0 | 12 |
| docs/architecture.md | drifted→fixed | 0 | 95 |
| CONTRIBUTING.md | needs-human | 2 | 412 |
**Branch-driven updates:**
- README.md: updated <sections>
- _wiki/page.md: updated <sections>
**Stale-doc audits (past freshness window):**
- docs/architecture.md (95d > 90d ttl): <fixes applied>
- CONTRIBUTING.md (412d): <fixes applied>
**Symbol drift (Step 2.5b):**
- <doc>: <missing symbol> → <fixed | removed | confirmed-real false positive>
**Verification findings (Pass 2 cross-check):**
- <claim that was wrong> → <how it was fixed>
- <claim left unverifiable> → flagged with <!-- docs-sync: unable to verify -->
**Misdirection caught (Pass 3 fresh-reader audit):**
- <misleading instruction> → <correction>
**Agent-instruction divergence (CLAUDE.md vs AGENTS.md):**
- <rule present in one but not the other> → flagged for human review
**Symlinks resolved:**
- <alias> → <canonical> (audited the canonical file only)
**Suggestions:**
- <any new doc suggestions from Step 5>The freshness summary stays advisory — never block on it. If any agent left <!-- docs-sync: unable to verify --> markers, or any CLAUDE.md↔AGENTS.md divergence was flagged, list them explicitly so the human can resolve them before merging.
Stage the changed doc files (use the CANONICAL paths from Step 1, never aliases):
git add README.md CLAUDE.md AGENTS.md CONTRIBUTING.md _wiki/ docs/ 2>/dev/null
git status --shortSay: "Doc changes staged. Review the diffs and commit when ready."
What NOT to Update
- Internal-only refactors with no user-facing impact
- Auto-generated docs (check for generation scripts first — e.g.,
docs/api/with a Makefile) - Changelogs, release notes, historical/migration docs (CHANGELOG.md, HISTORY.md,
migrations/,UPGRADING.md) — they legitimately reference removed code and old versions, so scoring them like living docs flags every "replaced X with Y" line as false drift. Step 2.5 already excludes them from the staleness and symbol-drift queues; honor afreshness: { exclude: true }opt-out for any other doc that should be frozen. - Scratch/debug scripts
- Unfinished/WIP features unless explicitly asked
- Test-only changes (unless they change how to run tests)
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

