agentleFS
foryouself83foryouself83/harness-tier/skills/doc-sync/SKILL.md

doc-sync

Skill10 starsChanged 30 days agoApache-2.0View on GitHub

Use when a change may have left the documentation drifted or inconsistent — after editing code that docs describe, after editing docs themselves, when verifying doc consistency, or when a module has no local CLAUDE.md. Also the /flow doc-sync gate.

  • Reads credentials

34 other projects use a version of this.

Adopted by

Most recently taken up by

Used with

Projects with it also use api-endpoint, perf-budget and 7 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.
  • tadoEngSkill

    api-endpoint

    Add or change a backend API endpoint on this product, keeping Pydantic as the single contract authority and regenerating the TypeScript client. Use when asked to add an endpoint, expose data to the frontend, change a request or response shape, or wire a new backend capability into a page.

    Also in 4 projects that use this

  • vindreshsinghSkill

    perf-budget

    Optimizes performance by measuring first and fixing the real bottleneck. Use when something is slow, before optimizing, when setting latency or bundle targets, or reviewing changes for performance traps — not for speculative micro-tuning.

    Also in 3 projects that use this

  • AnasX7Skill

    improve

    Survey any codebase as a senior advisor and produce prioritized, self-contained implementation plans for OTHER models/agents to execute. Strictly read-only on source code — never implements, fixes, or refactors anything itself. Use when asked to audit a codebase, find improvement opportunities (bugs, security, performance, test coverage, tech debt, migrations, DX), suggest features or where to take the project next (roadmap, product direction), or generate handoff plans for another agent to implement.

    Also in 3 projects that use this

  • dillonluiSkill

    design-review

    Review a view or flow for UX and UI issues. Provides severity-ranked, actionable findings grounded in established design heuristics. Use when the user asks for design feedback, UX review, or UI critique.

    Also in 3 projects that use this

  • Microsoft AzureSkill

    design

    Design rules and conventions for the API Center Portal. Use when editing detail pages, card components, badges, layout, navigation, sidebars, or headers. Covers badge styling, metadata placement, page navigation patterns, and layout alignment.

    Also in 3 projects that use this

  • NVIDIASkill

    research

    Before designing a feature, research how comparable libraries solve the problem, check best practices, known pitfalls, and upstream changes. Use when starting a new feature, investigating an unfamiliar area, or the user asks to research something.

    Also in 3 projects that use this

The file

We split this skill into the rules it gives an agent

10 rules. 0 are common, 4 are distinctive, and 6 are very specific to this project.

  • 0

    Common

    Most of the 27 edited versions we read keep these.

  • 4

    Distinctive

    This author's own choices. Worth a look.

  • 6

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Distinctive:

    If the project has a wiki, run A → B → W in order.

    line 69
  2. Very specific:

    Update: Read each file → locate the target section (#### Request Body, env table, etc.) → replace via Edit to match the code change.

    line 81
  3. Distinctive:

    When docs change, harmonize the consistency of the whole doc set.

    line 86
  4. Distinctive:

    Check every target; track the index by following its links.

    line 101
  5. Very specific:

    If harness is not installed for this project (no docs/code-style/ dir and no sibling module already has a local CLAUDE.md — the same signal …

    line 125
  6. Distinctive:

    If a module already has one, audit it against that reference's quality criteria (commands work, architecture explained, gotchas captured, …

    line 137
  7. Very specific:

    Every sds node with no code mapped — the absent key, the valueless key, and the sources: {} a greenfield design shipped before its code …

    line 240
  8. Very specific:

    Every mode above rewrites prose, which is where substance goes missing.

    line 292
  9. Very specific:

    Only when .claude/harness-tier/config/flow-config.yaml lists codex under harnesses.

    line 317
  10. Very specific:

    Keep the same fact only in its SSOT (e.g.

    line 361

“Common” is measured: kept by at least 6 in 10 of the 27 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.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

doc-sync

Analyze both code and documentation changes, update the related docs, and harmonize the whole doc set for consistency.

When

  • Called by /flow at the Docs gate (doc-only changes) and the Dev gate (after superpowers completes) → on pass, record .claude/harness-tier/.flow/doc-sync.done.
  • Whenever you need to verify documentation consistency after a code/doc change.

0. Read the caller's note

$ARGUMENTS is everything the caller said. This skill runs in a forked subagent with no conversation history, so nothing else carries their intent in — an empty value is normal and means the change itself is the whole brief.

Two things it can carry, and they are exclusive. A value that is exactly preview means plan only. Anything else — including a sentence with the word preview somewhere in it — is context for Mode A: what changed and why, which the diff shows the what of but never the why, so a caller who names the intent narrows the keyword extraction step 1 of Mode A would otherwise derive from the diff alone. Match the whole value, never a substring: "I reworked the preview pane, check the docs" is a request to sync, and reading it as the mode would answer a sync with a plan and leave no marker, which is this skill declining to run without saying so.

Plan only means the tree is left as found. No Edit, and none of the writes that are not Edits either: no git add, and no wiki_graph.py --build, which overwrites graph.yaml and is pre-approved above so nothing will stop you. Skip §2's marker, and say in the Report that you skipped it.

1. Determine the change scope

git diff HEAD                                   # the change itself — hunks per file
git diff --name-only HEAD                       # the complete file list — a large refactor's
                                                # diff can be truncated by tool-output caps,
                                                # and a file dropped here is a file never
                                                # classified into Mode A/B
git ls-files --others --exclude-standard        # new files, which the diff does not show

Classify changed files into two tracks (if both, run A → B in order):

  • Code changes (.py / .js / .ts / config / router …) → Mode A
  • Doc changes (.md: the index doc, the doc dirs, the rule dir) → Mode B
  • If the project has a wiki, run A → B → W in order.

Mode A — code → doc sync

Reflect code changes into the related docs.

  1. Extract keywords: class names, field names, type annotations, Field(description=...), env-var names/defaults, route paths, function names, summary.
  2. Find related docs: Grep **/*.md by keyword (files_with_matches). Select by relevance score ≥ 0.6: score = keyword_freq×0.4 + file_type×0.3 + context_match×0.2 + path_pattern×0.1
  3. Update: Read each file → locate the target section (#### Request Body, env table, etc.) → replace via Edit to match the code change.

Mode B — doc → doc harmonization

When docs change, harmonize the consistency of the whole doc set.

Reference targets (read from flow-config.doc_sync)

Resolve the targets to check from the project's .claude/harness-tier/config/flow-config.yaml, not from a hardcoded list:

  • doc_sync.index — the documentation index / SSOT (e.g. the root CLAUDE.md): the service-map table + the Auto-loaded Rules table. Links fan out from here to each service/rule doc.
  • doc_sync.service_docs (glob) — the per-service local docs linked from the index.
  • doc_sync.dirs (globs) — the guide / operations / standards doc dirs and the auto-loaded rule dir.

Check every target; track the index by following its links.

Check items

  1. Cross-reference integrity — does every file/link/rule a doc points to exist (including paths/anchors broken by the change)?
  2. Factual consistency (SSOT) — do two docs record the same value (model name, port, path, policy, version) differently? Keep the value in a single source of truth and reduce the rest to links. Which one is the source is not a vote. The artifact the system reads at runtime wins over every document describing it — the code, then the config it loads (.env.example, a settings file), then the index, then the per-service doc. Two docs agreeing against the code are two stale docs, not a majority. And correcting the code to match the docs is never the fix here: this skill's subject is the documentation.
  3. Index sync — does the index's rule/service tables match the actual file set (the rule dir, the service dirs)?
  4. Hierarchy consistency — do the per-service docs contradict the index's higher-level rules?
  5. Module CLAUDE.md template compliance — take the module dirs from flow-config.modules[].path (the authoritative module list — same one used for per-module pre-checks) that fall under the service_docs glob's directory (e.g. services/*/), since the glob itself only matches files that already exist and can't surface a missing one.
    • If harness is not installed for this project (no docs/code-style/ dir and no sibling module already has a local CLAUDE.md — the same signal flow-init uses to decide "harness installed"), do not create one — creating it here would falsely trip that detection for a project that never ran /harness-init. Note the gap in the Report and move to the next check item — this branch ends check 5, not the skill; §1b and the marker still run.
    • Otherwise, if a module has no local CLAUDE.md, generate one from module-claude-md-template.md by reading the module's actual code (entry points, build/test/lint commands, key deps) to fill each section — do not leave placeholders unfilled.
    • If a module already has one, audit it against that reference's quality criteria (commands work, architecture explained, gotchas captured, concise, current, actionable) and fix only what falls short — preserve existing project-specific content, do not rewrite wholesale.
  6. Translation parity — for each changed .md, look for sibling files whose name is the same stem plus a language tag (README.md → README.ko.md, docs/guide.md → docs/guide.ja.md). A repo with none skips this entirely. Where one exists it is a translation of the file you changed, so the same change belongs in it: carry it over and note it in the Report. Do not create a translation that does not already exist, and do not rewrite one wholesale — port the delta. Nothing else catches this: a translation drifts silently, staying valid markdown while describing a version of the product that no longer exists.

Action

On a mismatch, harmonize the related docs via Edit and record what changed and why in the Report. If a new rule/doc was added but is missing from the index, add the index row. A newly generated module CLAUDE.md also gets an index row (service-map table) if the index doesn't already list that module.

Mode W — wiki sync

Runs only when the project has an LLM Wiki (flow-config.wiki present and enabled). Without it, skip this whole mode — the commands below no-op and exit 0.

  1. Find what the code change made stale:
python3 .claude/harness-tier/scripts/wiki_graph.py --stale

Each JSON entry names a wiki node whose recorded sources value no longer matches the file — recorded and current are working-tree blob hashes (git hash-object), so history rewrites (squash/rebase promotions) cannot fake staleness. An entry with a migrated key carries a legacy commit-sha marker: rewrite sources[path] to the migrated value — it is the meaning-preserving conversion (git rev-parse <old>:<path>), needs no re-reading, and the verify gate accepts it without a body edit. If migrated equals current, that rewrite is the whole fix; if it differs (or is null), the node is also genuinely stale — sync the body, then stamp. An entry with "missing": true is a different problem: that source path no longer exists (the file was renamed or deleted). Fix the path — or drop the entry — in the node's front matter. Do not stamp a sha on it: --verify warns on the missing path itself, and a fresh sha leaves the problem exactly where it was.

  1. Narrow the harmonize set. For each stale node, ask the graph for its neighbourhood instead of guessing — run wiki_graph.py --neighbors once per stale node, substituting that node's own id from step 1's JSON (the id key of the JSON entry — the graph's node id, which is what the document's wiki_id becomes): python3 .claude/harness-tier/scripts/wiki_graph.py --neighbors auth.jwt. (Not shown as a copyable block on purpose: there is no id to hardcode, and an id the graph does not know exits non-zero with the reason on stderr.)

    Mode A keyword-greps every markdown file and scores relevance. Where a wiki exists the graph already holds those relations, so this is a lookup, not an estimate.

  2. Update the bodies, then stamp sources[path] with the file's working-tree blob hash — the current value from step 1's JSON (equivalently git hash-object -- <path>), never a commit sha — only for nodes whose body you changed. A stale node you did not touch stays stale and goes in the Report — do not stamp its sha. Stamping without reading the code behind it turns the marker into a lie, and the gate now enforces this mechanically: a commit whose only change to a node is its sources sha is blocked by --verify, so a bulk refresh does not merely violate prose — it fails. Two swaps stay allowed: step 1's migrated rewrite, and a stamp whose body edit landed in the immediately preceding commit (so stamping the sync you committed, or amending it in, works — including when that commit also renamed the document, which the gate follows). A stale node you read and found still accurate (the code change was cosmetic) is deliberately the same case: leave the marker alone and report it as "verified accurate, still stale" — the marker only ever moves with a body edit, and it clears naturally the next time the body genuinely changes.
  3. Give any new .md under the wiki root its front matter — get wiki_id from one derivation call for all the new documents, substituting their real paths (e.g. python3 .claude/harness-tier/scripts/wiki_graph.py --derive-id docs/auth/jwt.md docs/auth/session.md; each stdout line is path<TAB>id, a failure names its path on stderr and the call exits nonzero, though every path that succeeded still prints its line — fix that path and re-run; rationale in wiki-init Step 5). No --root here, unlike wiki-init's: this mode runs only with the wiki enabled, so the call reads the configured root itself, and a hardcoded one would be wrong for every root that is not docs. A defect document is the exception: its wiki_id follows the defect.<slug> convention in defect-template.md, not this derivation. Then title, the sources it documents, and tags: [sds] on a design document — that tag is what step 5 and --verify read to find it. Never write used_by or defects; they are generated. Wire the new node to the nodes it belongs with (related/depends_on on either side) so it is reachable from the index through real edges; add it to the index's related: only when it genuinely is a top-level entry (wiki-init Step 6) — orphan detection reads front-matter edges only, never markdown links, so a node wired to nothing reports as an orphan forever even if some body links it in prose.
  4. Backfill the sources a node never got:
python3 .claude/harness-tier/scripts/wiki_graph.py --unmapped

An unrecognized arguments exit 2 here means the host copy of the script predates this flag: say so, tell the user to re-run /flow-init, and skip this step — the rest of the mode is unaffected.

Every sds node with no code mapped — the absent key, the valueless key, and the sources: {} a greenfield design shipped before its code existed. --verify warns on the first two but is silent on the third, so this is the only list that holds all three. Read each one's Module Overview and record the real code paths, sha left null — step 3 stamps it on the next body sync. Nothing else fills them: step 1 builds its list from recorded paths, step 4 only touches documents this change created, and /wiki-init never revisits a document that already carries a wiki_id. Where the code still does not exist, leave sources: {} and say so in the Report — an invented path is what this prevents.

  1. Split any node over max_lines. --verify (below) warns on this but nothing acts on the warning — /wiki-init refuses to re-offer a document that already carries a wiki_id, so the migration wizard never revisits it either. Split it exactly as wiki-init Steps 4-5 direct, including their zero- and one-H2 branches — do not assume an H2 split always applies. Record the outcome in the Report. An SRS document is the exception — never split it mechanically; see What this skill does not own below.
  2. Stage new documents, then rebuild and verify. A document joins the wiki by being in git — the graph is built from the index, not the filesystem, so an unstaged new .md is not yet a node and a rebuild would omit it. git add the new documents first, then:
python3 .claude/harness-tier/scripts/wiki_graph.py --build
python3 .claude/harness-tier/scripts/wiki_graph.py --verify

--verify must exit 0 before the gate marker is written — the commit gate runs the same command and will block otherwise. A structure violation (wiki_id format/duplicate · missing title · dangling depends_on · cycle · front matter that does not parse while carrying a wiki_id) is not fixed by --build; fix the document's front matter instead. --verify reads the working tree, so docs/graph/graph.yaml must be staged alongside the documents it was built from — otherwise the commit records the new front matter beside the old graph and the drift goes unnoticed until someone else's next session commit. If a merge left conflict markers in graph.yaml, never resolve them by hand — take either side and re-run --build (wiki-init Step 8).

What this skill does not own

Structure is recorded before the code, by /flow's Dev increment steps: module overview, Mermaid nodes, integration-point contracts, FR back-links. This skill runs after the code and reconciles: sources shas, stale nodes, splits, orphans. One fact, one place — a design decision written here would be written twice.

An SRS document is never split mechanically. Step 6's H2 split would break the anchors the SDS links (#nfr-perf, #c-003) and dead-link every FR reference. When one grows past max_lines, promote a whole section to its own file and fix the links with it — an explicit migration, not a mechanical split.

1b. Prove the rewrite lost nothing

Every mode above rewrites prose, which is where substance goes missing. Before the marker, check each .md you touched against what HEAD holds:

python3 .claude/harness-tier/scripts/doc_style_check.py --verify-git <changed .md paths>

An error names what disappeared — a heading, a fenced block, a URL, an inline-code span. Restore it, or state in the Report why the removal was the point. Warnings (bullet count, paths) are advisory. A file HEAD never had is skipped; a repo with no doc_style_check.py yet has nothing to run and this step is skipped whole.

This asks about the rewrite this run made, not about prose style, so it does not read flow-config.doc_style and a repo that never enabled doc-style still runs it. A file this run did not touch says nothing either way — the answer comes from comparing against HEAD.

Prose itself follows doc-style.md. Half of that rule is patterns and half is judgement, so run both over every file the change touched within the project's doc-style scope — code comments and docstrings too where that scope names code, as it does by default, with doc_style off or absent. Invoke skill prose-review with no paths: it reads the change's own list from git and narrows it. It reports what it would change; apply what survives review before the marker, since an edit after the marker voids it.

1c. Codex's copy of the instructions

Only when .claude/harness-tier/config/flow-config.yaml lists codex under harnesses. Codex reads neither CLAUDE.md nor .claude/rules/, only a block generated from them in the root AGENTS.md, so after any edit to either, regenerate it and confirm it matches:

python3 .claude/harness-tier/scripts/harness/codex/instructions.py render
python3 .claude/harness-tier/scripts/harness/codex/instructions.py render --check

A non-zero exit from --check is a finding: report its line under [B]. Never edit the block by hand — the next render overwrites it. When the script is absent, the host's copies predate this step: skip it, not a finding, and tell the user to re-run /flow-init.

2. Gate marker

Unless step 0 asked for a preview, leave the gate evidence — the commit is blocked without it, and "was I called by /flow?" is not a question a fork can answer, so it is not asked: the marker records that doc-sync passed on this tree, which is true whoever called it.

mkdir -p .claude/harness-tier/.flow && touch .claude/harness-tier/.flow/doc-sync.done

3. Report

doc-sync result:
- [A] services/<svc>/README.md — added priority field to env table
- [B] <index> ↔ services/<svc>/CLAUDE.md — harmonized model-name mismatch (SSOT: .env.example)
- [B] <index> rule index — missing risk-tiers.md row → added
- [B] services/<svc>/CLAUDE.md — generated from module-claude-md-template.md (Commands/Architecture/Gotchas filled from source); added to index service map
- [B] README.ko.md — ported the same change from README.md (translation parity)
- fixed 1 cross-reference (broken link)
- [W] docs/auth/jwt.md — sources sha refreshed; graph.yaml rebuilt (12 nodes)
- [W] docs/auth/session.md — still stale, body not updated (needs a human call)
- [W] docs/api/auth.md — split by H2 into 3 nodes (over max_lines); original kept as a node with related back-links

Tips

  • Writing Pydantic Field(description=...) improves Mode A keyword-extraction accuracy.
  • Unifying markdown section headers at the #### level makes section replacement stable.
  • Keep the same fact only in its SSOT (e.g. .env.example, a service's local doc) and link from other docs — this prevents Mode B mismatches at the root.
  • To preview the plan only, pass preview as the argument (step 0) — the word has to reach $ARGUMENTS, since a fork never sees the sentence it was asked in.
  • The module template (module-claude-md-template.md) covers only a single module's usage info (commands/architecture/gotchas). It is a different artifact from the harness root CLAUDE.md(skills/harness-authoring/templates/claude-md.template.md), which carries project-wide baseline principles managed by /harness-init — do not conflate the two or generate baseline-principle content here.

Download now (ZIP)

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
What did you use it for? e.g. Reviewing pull requests in a Rails app

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.