oma-docs - Documentation Drift Detector
Scheduling
Goal
Detect broken references in docs/**/*.md (verify mode) and propose LLM-generated patch proposals for docs affected by recent code changes (sync mode). Both modes run on-demand; sync is always interactive.
Intent signature
- User asks to check if docs are up to date, find broken doc links, verify file paths referenced in docs, or detect documentation drift.
- User asks to update docs after a code change, propose doc patches for a git diff, or sync affected docs.
- A workflow hook checks
docs.auto_verify: true and runs oma docs verify --json at completion.
When to use
- After a refactor, rename, or file deletion, to find stale references in docs.
- Before a release, to confirm that CLI commands, file paths, and config keys in docs still exist.
- After a significant git diff, to discover which docs reference the changed files and may need updating.
- Routine drift check on any docs-heavy repo.
When NOT to use
- Generating docs from scratch for undocumented features → v2 create mode.
- Multilingual translation of docs → use
oma-translator.
- Symbol-level semantic drift (function signature changes not reflected in prose) → v2 L3 mode.
- CI-blocking enforcement → v2 block mode (v1 is warn-only).
Expected inputs
verify mode: Optional glob path (default **/*.md), optional --json flag, optional --report-file <path>.
sync mode: Optional git diff range (default --cached, fallback HEAD~1..HEAD).
Expected outputs
verify mode:
- Markdown drift report to stdout (default), or raw JSON with
--json, or full markdown written to file with --report-file.
- Exit code 0 if clean, 1 if any broken refs found.
sync mode:
- Per-doc patch proposals drafted by the host LLM from the CLI's candidate-doc list, confirmed per doc (
[y] apply [n] skip [d] diff [s] full proposal style).
- Docs modified only on explicit user approval;
doc-refs.json regenerated after applies.
Dependencies
cli/commands/docs/extract.ts: markdown AST + L2 pattern extractor.
cli/commands/docs/resolve.ts: deterministic broken-ref checker.
cli/commands/docs/reporter.ts: deterministic markdown/JSON report renderer (no LLM call; host LLM does narrative synthesis).
cli/commands/docs/sync-propose.ts: git diff intake, reverse lookup, candidate-doc selector with secret redaction (no LLM call; host LLM drafts patches).
docs/generated/doc-refs.json: single-direction reference index (git-tracked, regenerated on every verify run).
docs/generated/url-drift.json: lychee-produced URL drift report (written by background lychee spawn; gitignored or tracked at user discretion).
lychee: external Rust tool for URL link checking. Detected on PATH; install via brew install lychee or see https://github.com/lycheeverse/lychee#installation. Optional but recommended.
.agents/oma-config.yaml: docs.auto_verify (workflow hook opt-in) and docs.check_urls (URL checking on/off, default true) toggles.
Control-flow features
- Mode is selected from the first argument:
verify or sync.
- verify: extract → resolve → report (fully deterministic CLI; host LLM adds narrative summary on top of the JSON/markdown output).
- sync: git diff → reverse lookup → candidate list (CLI) → host-LLM patch proposals → interactive accept/reject.
- Branches on
--json, --report-file, LLM availability, and network reachability.
- Never blocks workflow completion in v1 (warn-only hook policy).
Structural Flow
Entry
- Read first argument to select mode (
verify | sync). If absent, print help and exit.
- Load
oma-config.yaml to check docs.auto_verify when invoked from a workflow hook.
- Confirm required CLI dependencies (
oma docs verify, oma docs sync) are on PATH.
Scenes
- PREPARE: Determine mode, resolve path/diff-range arguments, confirm tool availability.
- ACQUIRE: Run extractor (
extract.ts) to regenerate doc-refs.json from docs/**/*.md (verify) or build in-memory reverse index from existing doc-refs.json (sync).
- REASON: Resolve each reference deterministically (verify) or correlate changed files to candidate docs via reverse lookup (sync).
- ACT: Render the deterministic drift report (verify) or list candidate docs with matched refs (sync). Host LLM does any natural-language synthesis or patch drafting on top of this output.
- VERIFY: Confirm output shape is valid (JSON schema check for
--json; structured candidate list for sync).
- FINALIZE: Print to stdout, write report file if requested, emit exit code.
Transitions
- verify mode: PREPARE → ACQUIRE (extract) → REASON (resolve) → ACT (report) → FINALIZE.
- sync mode: PREPARE → ACQUIRE (reverse index) → REASON (candidate matching) → ACT (LLM proposals) → VERIFY (interactive) → FINALIZE (apply approved).
- If LLM is unavailable in verify: skip reporter summary, emit raw JSON drift report.
- If LLM is unavailable in sync: emit candidate-list-only output (no patch proposals); user reviews manually.
- If
doc-refs.json is stale or missing in sync: run extractor first, then continue.
Failure and recovery
- Extractor parse error on a single doc: skip doc + warn, continue with remaining docs.
- lychee unavailable or URL check incomplete: print install hint, skip URL checking, continue (core check is unaffected).
- Host-LLM context limit exceeded while drafting patches: process candidate docs in smaller batches.
oma docs CLI not found: skip with installation hint (workflow hook: skip silently).
doc-refs.json write failure: abort and report the write error; do not emit partial index.
Exit
- Success (verify): drift report emitted; exit 0 if clean, exit 1 if broken refs found.
- Success (sync): approved patches applied;
doc-refs.json regenerated; session summary printed.
- Partial success: extractor or resolver errors are explicit in the report; no silent failures.
Logical Operations
Actions
| Action |
SSL primitive |
Notes |
| Parse CLI args and mode |
READ |
First arg selects verify or sync |
| Extract refs from docs |
CALL_TOOL |
extract.ts: remark AST + L2 patterns → doc-refs.json |
| Check broken refs |
RESOLVE |
resolve.ts: file, url, cli, script, env, config checks |
| Build reverse index |
INFER |
sync-propose.ts: in-memory map from doc-refs.json |
| Match diff to candidate docs |
RESOLVE |
sync-propose.ts: git diff + reverse lookup |
| Redact secrets from diff |
VALIDATE |
Exclude .env*, *.pem, *.key, id_rsa*; sanitize content |
| Generate patch proposals |
INFER |
Host LLM drafts patches from sync-propose.ts candidate output (no CLI LLM call) |
| Render drift report |
RENDER |
reporter.ts: markdown (default), JSON (--json), file (--report-file) |
| Apply approved patches |
WRITE |
git apply on user-confirmed patches only |
| Notify hook summary |
NOTIFY |
1-3 line stdout summary for workflow hooks |
Tools and instruments
cli/commands/docs/extract.ts: remark + unified markdown AST, L2 pattern extraction, escape hatch filter, docs/generated/doc-refs.json writer.
cli/commands/docs/resolve.ts: case-sensitive file existence, which for CLI tokens, package.json scripts lookup, ripgrep/git grep for env vars, oma-config.yaml deep-path check. Per-target dedupe caches (cli by first token, env, config) and per-directory listing cache for file resolution. URL kind is filtered out by the verify command and delegated to lychee.
cli/commands/docs/reporter.ts: deterministic markdown + JSON renderer. No LLM call. Friendly summary, severity tagging, fix prioritization are the host LLM's responsibility.
cli/commands/docs/sync-propose.ts: git diff intake, reverse index build, secret-pattern + gitignore file exclusion. Returns candidate docs with matched refs only. No LLM call. Patch synthesis is the host LLM's responsibility.
- External:
lychee (background URL link checking; install via brew install lychee).
Host-LLM contract
This skill follows the OMA pattern (mirroring oma-scholar): the CLI emits structured data; the host LLM (the agent runtime that invoked the skill) does any natural-language synthesis or judgment.
After oma docs verify --json:
- Read the JSON drift report.
- Group findings by severity / urgency (host-LLM judgment).
- Suggest fixes per finding, prioritizing files most central to the project.
- If the user asks for natural-language summary, host LLM produces it from the JSON, never from cached prose.
After oma docs sync <range> --json:
- Read the candidate doc list (each entry:
{ doc, changedFiles, matchedRefs }).
- For each candidate doc: read the doc itself, read
git diff for changedFiles, draft a unified-diff patch reflecting the code change.
- Present patches to the user for review. Never auto-apply.
- On user approval, apply via
git apply or by writing the doc directly.
Canonical command path
verify mode runs a drift check against the current codebase:
# Default: scan all docs/**/*.md, render markdown to stdout.
# URL link checking is delegated to lychee in the background
# (install: `brew install lychee`). Core check ~8s on a 1k-doc repo.
oma docs verify
# Narrow to a path or glob (uses minimatch)
oma docs verify "docs/**/*.md"
oma docs verify cli/README.md
# Machine-readable output for CI / hooks
oma docs verify --json
# Persist full markdown report to a file
oma docs verify --report-file ./drift-report.md
# Skip URL checking entirely (when lychee is run separately, or as a
# one-off override of docs.check_urls=true in oma-config.yaml)
oma docs verify --no-urls
# Block until lychee finishes (CI scenarios needing complete URL data)
oma docs verify --urls-sync
# Exit code: 0 = clean, 1 = broken refs found in core check.
# URL drift, if any, is reported separately at docs/generated/url-drift.json
# and does NOT affect this exit code.
sync mode proposes patches for docs affected by a git diff (always interactive, never auto-applies):
# Default: staged changes (--cached), fallback HEAD~1..HEAD
oma docs sync
# Explicit range
oma docs sync HEAD~5..HEAD
oma docs sync main..feature-branch
# The CLI emits the candidate-doc list; the host LLM drafts patches and
# confirms per doc ([y] apply / [n] skip / [d] diff / [s] full proposal).
# Sync regenerates docs/generated/doc-refs.json after applying any patches.
Workflow hook (opt-in) runs verify automatically at workflow completion when docs.auto_verify: true in oma-config.yaml:
# Hook command emitted by /scm, /work, /ultrawork
oma docs verify --json
# Hook policy: warn-only in v1; non-zero exit does NOT block workflow completion
Resource scope
| Scope |
Resource target |
LOCAL_FS read |
docs/**/*.md (extractor input), docs/generated/doc-refs.json (index), .env.example, package.json, .agents/oma-config.yaml |
LOCAL_FS write |
docs/generated/doc-refs.json (regenerated each verify run), approved sync patches |
CODEBASE read-only |
Existence checks for file/cli/script/env/config refs; git diff intake |
PROCESS |
git diff, git apply, which, background lychee spawn |
NETWORK |
URL checking delegated to lychee (no internal HEAD fallback; see Guardrail 6) |
Preconditions
docs/ directory exists at repo root.
cli/commands/docs/ is built and oma binary is on PATH (or invoked directly via bun run).
- For sync mode: a git diff is available (
--cached stage or recent commits).
Effects and side effects
- verify: regenerates
docs/generated/doc-refs.json (always overwrites).
- sync: modifies docs files only on user approval; regenerates
doc-refs.json after applies.
- Both modes: stdout output (summary or full report).
- No
.agents/ files are ever modified.
Guardrails
- Never modify
.agents/: CLAUDE.md SSOT protection applies in all modes.
- Never auto-apply sync patches: sync is always interactive;
[y] confirm required per doc.
- LLM unavailable → graceful degradation: verify falls back to raw JSON; sync falls back to candidate-list-only (no proposals). Neither mode blocks on LLM availability.
- Response language follows
oma-config.yaml language: user-facing report text is localized; code, paths, JSON keys, and CLI commands stay in English.
- Secret-bearing files excluded from sync output:
.env*, *.pem, *.key, id_rsa*, and gitignored files never appear in candidate changedFiles lists. Host LLM never sees secret file paths.
- URL link checking delegated to lychee: when
docs.check_urls=true (default), URL refs are checked by lychee running in the background; results land in docs/generated/url-drift.json. If lychee is missing, an install hint is printed and URL checking is skipped (no internal HEAD fallback).
- No direct LLM API calls from the CLI: the CLI never imports vendor SDKs, never reads API keys, never makes outbound LLM requests. All synthesis, patch drafting, and natural-language framing is the host LLM's responsibility (mirrors
oma-scholar's pattern). This makes oma-docs vendor-agnostic: works identically under Claude Code / Codex / Gemini / Qwen / Antigravity.
- Hook is warn-only in v1: broken refs never block workflow completion;
docs.auto_verify: false by default (explicit opt-in required).
- Escape hatch respected:
<!-- oma-docs:ignore-start --> / <!-- oma-docs:ignore-end --> blocks and frontmatter oma-docs: skip are honored; no ref extraction from ignored regions.
v1 scope note
v1 covers verify and sync (broken-only classification, L2 ref extraction). The following are explicitly deferred to v2: create mode (generate missing docs), multilingual sync (deeper oma-translator integration), L3 symbol-level extraction (Tree-sitter/LSP), GitHub Action wrapper, block hook mode.
References
- Design doc:
docs/plans/designs/008-oma-docs.md (full architecture, schema spec, decision log, edge cases).
- Schema spec:
doc-refs.json v1 schema defined in design doc § doc-refs.json Schema.
- Workflow hook integration: design doc § Workflow Hook Integration.
- Migration:
deepinit Step 6 retirement, design doc § Migration: deepinit Step 6.
- Adjacent skills:
oma-translator (v2 multilingual), oma-skill-creator (SSL-lite validation).
1---2name: oma-docs3description: Verify documentation references against the current codebase and propose updates for diff-affected docs. Use to check if docs still match reality (broken file paths, CLI commands, config keys, env vars, scripts) and to surface docs that may need updating after code changes.4---5
6# oma-docs - Documentation Drift Detector
7
8## Scheduling
9
10### Goal
11Detect broken references in `docs/**/*.md` (verify mode) and propose LLM-generated patch proposals for docs affected by recent code changes (sync mode). Both modes run on-demand; sync is always interactive.
12
13### Intent signature
14- User asks to check if docs are up to date, find broken doc links, verify file paths referenced in docs, or detect documentation drift.
15- User asks to update docs after a code change, propose doc patches for a git diff, or sync affected docs.
16- A workflow hook checks `docs.auto_verify: true` and runs `oma docs verify --json` at completion.
17
18### When to use
19- After a refactor, rename, or file deletion, to find stale references in docs.
20- Before a release, to confirm that CLI commands, file paths, and config keys in docs still exist.
21- After a significant git diff, to discover which docs reference the changed files and may need updating.
22- Routine drift check on any docs-heavy repo.
23
24### When NOT to use
25- Generating docs from scratch for undocumented features → v2 create mode.
26- Multilingual translation of docs → use `oma-translator`.
27- Symbol-level semantic drift (function signature changes not reflected in prose) → v2 L3 mode.
28- CI-blocking enforcement → v2 block mode (v1 is warn-only).
29
30### Expected inputs
31
32**verify mode**: Optional glob path (default `**/*.md`), optional `--json` flag, optional `--report-file <path>`.
33
34**sync mode**: Optional git diff range (default `--cached`, fallback `HEAD~1..HEAD`).
35
36### Expected outputs
37
38**verify mode**:
39- Markdown drift report to stdout (default), or raw JSON with `--json`, or full markdown written to file with `--report-file`.
40- Exit code 0 if clean, 1 if any broken refs found.
41
42**sync mode**:
43- Per-doc patch proposals drafted by the host LLM from the CLI's candidate-doc list, confirmed per doc (`[y] apply [n] skip [d] diff [s] full proposal` style).
44- Docs modified only on explicit user approval; `doc-refs.json` regenerated after applies.
45
46### Dependencies
47- `cli/commands/docs/extract.ts`: markdown AST + L2 pattern extractor.
48- `cli/commands/docs/resolve.ts`: deterministic broken-ref checker.
49- `cli/commands/docs/reporter.ts`: deterministic markdown/JSON report renderer (no LLM call; host LLM does narrative synthesis).
50- `cli/commands/docs/sync-propose.ts`: git diff intake, reverse lookup, candidate-doc selector with secret redaction (no LLM call; host LLM drafts patches).
51- `docs/generated/doc-refs.json`: single-direction reference index (git-tracked, regenerated on every verify run).
52- `docs/generated/url-drift.json`: lychee-produced URL drift report (written by background lychee spawn; gitignored or tracked at user discretion).
53- `lychee`: external Rust tool for URL link checking. Detected on PATH; install via `brew install lychee` or see https://github.com/lycheeverse/lychee#installation. Optional but recommended.
54- `.agents/oma-config.yaml`: `docs.auto_verify` (workflow hook opt-in) and `docs.check_urls` (URL checking on/off, default true) toggles.
55
56### Control-flow features
57- Mode is selected from the first argument: `verify` or `sync`.
58- verify: extract → resolve → report (fully deterministic CLI; host LLM adds narrative summary on top of the JSON/markdown output).
59- sync: git diff → reverse lookup → candidate list (CLI) → host-LLM patch proposals → interactive accept/reject.
60- Branches on `--json`, `--report-file`, LLM availability, and network reachability.
61- Never blocks workflow completion in v1 (warn-only hook policy).
62
63## Structural Flow
64
65### Entry
661. Read first argument to select mode (`verify` | `sync`). If absent, print help and exit.
672. Load `oma-config.yaml` to check `docs.auto_verify` when invoked from a workflow hook.
683. Confirm required CLI dependencies (`oma docs verify`, `oma docs sync`) are on PATH.
69
70### Scenes
711. **PREPARE**: Determine mode, resolve path/diff-range arguments, confirm tool availability.
722. **ACQUIRE**: Run extractor (`extract.ts`) to regenerate `doc-refs.json` from `docs/**/*.md` (verify) or build in-memory reverse index from existing `doc-refs.json` (sync).
733. **REASON**: Resolve each reference deterministically (verify) or correlate changed files to candidate docs via reverse lookup (sync).
744. **ACT**: Render the deterministic drift report (verify) or list candidate docs with matched refs (sync). Host LLM does any natural-language synthesis or patch drafting on top of this output.
755. **VERIFY**: Confirm output shape is valid (JSON schema check for `--json`; structured candidate list for sync).
766. **FINALIZE**: Print to stdout, write report file if requested, emit exit code.
77
78### Transitions
79- verify mode: PREPARE → ACQUIRE (extract) → REASON (resolve) → ACT (report) → FINALIZE.
80- sync mode: PREPARE → ACQUIRE (reverse index) → REASON (candidate matching) → ACT (LLM proposals) → VERIFY (interactive) → FINALIZE (apply approved).
81- If LLM is unavailable in verify: skip reporter summary, emit raw JSON drift report.
82- If LLM is unavailable in sync: emit candidate-list-only output (no patch proposals); user reviews manually.
83- If `doc-refs.json` is stale or missing in sync: run extractor first, then continue.
84
85### Failure and recovery
86- Extractor parse error on a single doc: skip doc + warn, continue with remaining docs.
87- lychee unavailable or URL check incomplete: print install hint, skip URL checking, continue (core check is unaffected).
88- Host-LLM context limit exceeded while drafting patches: process candidate docs in smaller batches.
89- `oma docs` CLI not found: skip with installation hint (workflow hook: skip silently).
90- `doc-refs.json` write failure: abort and report the write error; do not emit partial index.
91
92### Exit
93- Success (verify): drift report emitted; exit 0 if clean, exit 1 if broken refs found.
94- Success (sync): approved patches applied; `doc-refs.json` regenerated; session summary printed.
95- Partial success: extractor or resolver errors are explicit in the report; no silent failures.
96
97## Logical Operations
98
99### Actions
100| Action | SSL primitive | Notes |
101|--------|---------------|-------|
102| Parse CLI args and mode | `READ` | First arg selects verify or sync |
103| Extract refs from docs | `CALL_TOOL` | `extract.ts`: remark AST + L2 patterns → `doc-refs.json` |
104| Check broken refs | `RESOLVE` | `resolve.ts`: file, url, cli, script, env, config checks |
105| Build reverse index | `INFER` | `sync-propose.ts`: in-memory map from `doc-refs.json` |
106| Match diff to candidate docs | `RESOLVE` | `sync-propose.ts`: git diff + reverse lookup |
107| Redact secrets from diff | `VALIDATE` | Exclude `.env*`, `*.pem`, `*.key`, `id_rsa*`; sanitize content |
108| Generate patch proposals | `INFER` | Host LLM drafts patches from `sync-propose.ts` candidate output (no CLI LLM call) |
109| Render drift report | `RENDER` | `reporter.ts`: markdown (default), JSON (`--json`), file (`--report-file`) |
110| Apply approved patches | `WRITE` | `git apply` on user-confirmed patches only |
111| Notify hook summary | `NOTIFY` | 1-3 line stdout summary for workflow hooks |
112
113### Tools and instruments
114- `cli/commands/docs/extract.ts`: `remark` + `unified` markdown AST, L2 pattern extraction, escape hatch filter, `docs/generated/doc-refs.json` writer.
115- `cli/commands/docs/resolve.ts`: case-sensitive file existence, `which` for CLI tokens, `package.json` scripts lookup, ripgrep/git grep for env vars, `oma-config.yaml` deep-path check. Per-target dedupe caches (cli by first token, env, config) and per-directory listing cache for file resolution. URL kind is filtered out by the verify command and delegated to lychee.
116- `cli/commands/docs/reporter.ts`: deterministic markdown + JSON renderer. **No LLM call.** Friendly summary, severity tagging, fix prioritization are the host LLM's responsibility.
117- `cli/commands/docs/sync-propose.ts`: git diff intake, reverse index build, secret-pattern + gitignore file exclusion. Returns candidate docs with matched refs only. **No LLM call.** Patch synthesis is the host LLM's responsibility.
118- External: [`lychee`](https://github.com/lycheeverse/lychee) (background URL link checking; install via `brew install lychee`).
119
120### Host-LLM contract
121
122This skill follows the OMA pattern (mirroring `oma-scholar`): **the CLI emits structured data; the host LLM (the agent runtime that invoked the skill) does any natural-language synthesis or judgment.**
123
124After `oma docs verify --json`:
1251. Read the JSON drift report.
1262. Group findings by severity / urgency (host-LLM judgment).
1273. Suggest fixes per finding, prioritizing files most central to the project.
1284. If the user asks for natural-language summary, host LLM produces it from the JSON, never from cached prose.
129
130After `oma docs sync <range> --json`:
1311. Read the candidate doc list (each entry: `{ doc, changedFiles, matchedRefs }`).
1322. For each candidate doc: read the doc itself, read `git diff` for `changedFiles`, draft a unified-diff patch reflecting the code change.
1333. Present patches to the user for review. **Never auto-apply.**
1344. On user approval, apply via `git apply` or by writing the doc directly.
135
136### Canonical command path
137
138**verify mode** runs a drift check against the current codebase:
139
140```bash
141# Default: scan all docs/**/*.md, render markdown to stdout.
142# URL link checking is delegated to lychee in the background
143# (install: `brew install lychee`). Core check ~8s on a 1k-doc repo.
144oma docs verify
145
146# Narrow to a path or glob (uses minimatch)
147oma docs verify "docs/**/*.md"
148oma docs verify cli/README.md
149
150# Machine-readable output for CI / hooks
151oma docs verify --json
152
153# Persist full markdown report to a file
154oma docs verify --report-file ./drift-report.md
155
156# Skip URL checking entirely (when lychee is run separately, or as a
157# one-off override of docs.check_urls=true in oma-config.yaml)
158oma docs verify --no-urls
159
160# Block until lychee finishes (CI scenarios needing complete URL data)
161oma docs verify --urls-sync
162
163# Exit code: 0 = clean, 1 = broken refs found in core check.
164# URL drift, if any, is reported separately at docs/generated/url-drift.json
165# and does NOT affect this exit code.
166```
167
168**sync mode** proposes patches for docs affected by a git diff (always interactive, never auto-applies):
169
170```bash
171# Default: staged changes (--cached), fallback HEAD~1..HEAD
172oma docs sync
173
174# Explicit range
175oma docs sync HEAD~5..HEAD
176oma docs sync main..feature-branch
177
178# The CLI emits the candidate-doc list; the host LLM drafts patches and
179# confirms per doc ([y] apply / [n] skip / [d] diff / [s] full proposal).
180# Sync regenerates docs/generated/doc-refs.json after applying any patches.
181```
182
183**Workflow hook (opt-in)** runs verify automatically at workflow completion when `docs.auto_verify: true` in `oma-config.yaml`:
184
185```bash
186# Hook command emitted by /scm, /work, /ultrawork
187oma docs verify --json
188# Hook policy: warn-only in v1; non-zero exit does NOT block workflow completion
189```
190
191### Resource scope
192| Scope | Resource target |
193|-------|-----------------|
194| `LOCAL_FS` read | `docs/**/*.md` (extractor input), `docs/generated/doc-refs.json` (index), `.env.example`, `package.json`, `.agents/oma-config.yaml` |
195| `LOCAL_FS` write | `docs/generated/doc-refs.json` (regenerated each verify run), approved sync patches |
196| `CODEBASE` read-only | Existence checks for file/cli/script/env/config refs; git diff intake |
197| `PROCESS` | `git diff`, `git apply`, `which`, background `lychee` spawn |
198| `NETWORK` | URL checking delegated to `lychee` (no internal HEAD fallback; see Guardrail 6) |
199
200### Preconditions
201- `docs/` directory exists at repo root.
202- `cli/commands/docs/` is built and `oma` binary is on PATH (or invoked directly via `bun run`).
203- For sync mode: a git diff is available (`--cached` stage or recent commits).
204
205### Effects and side effects
206- verify: regenerates `docs/generated/doc-refs.json` (always overwrites).
207- sync: modifies docs files only on user approval; regenerates `doc-refs.json` after applies.
208- Both modes: stdout output (summary or full report).
209- No `.agents/` files are ever modified.
210
211### Guardrails
212
2131. **Never modify `.agents/`**: CLAUDE.md SSOT protection applies in all modes.
2142. **Never auto-apply sync patches**: sync is always interactive; `[y]` confirm required per doc.
2153. **LLM unavailable → graceful degradation**: verify falls back to raw JSON; sync falls back to candidate-list-only (no proposals). Neither mode blocks on LLM availability.
2164. **Response language follows `oma-config.yaml` `language`**: user-facing report text is localized; code, paths, JSON keys, and CLI commands stay in English.
2175. **Secret-bearing files excluded from sync output**: `.env*`, `*.pem`, `*.key`, `id_rsa*`, and gitignored files never appear in candidate `changedFiles` lists. Host LLM never sees secret file paths.
2186. **URL link checking delegated to lychee**: when `docs.check_urls=true` (default), URL refs are checked by `lychee` running in the background; results land in `docs/generated/url-drift.json`. If `lychee` is missing, an install hint is printed and URL checking is skipped (no internal HEAD fallback).
2197. **No direct LLM API calls from the CLI**: the CLI never imports vendor SDKs, never reads API keys, never makes outbound LLM requests. All synthesis, patch drafting, and natural-language framing is the host LLM's responsibility (mirrors `oma-scholar`'s pattern). This makes `oma-docs` vendor-agnostic: works identically under Claude Code / Codex / Gemini / Qwen / Antigravity.
2208. **Hook is warn-only in v1**: broken refs never block workflow completion; `docs.auto_verify: false` by default (explicit opt-in required).
2219. **Escape hatch respected**: `<!-- oma-docs:ignore-start -->` / `<!-- oma-docs:ignore-end -->` blocks and frontmatter `oma-docs: skip` are honored; no ref extraction from ignored regions.
222
223### v1 scope note
224v1 covers `verify` and `sync` (broken-only classification, L2 ref extraction). The following are explicitly deferred to v2: `create` mode (generate missing docs), multilingual sync (deeper `oma-translator` integration), L3 symbol-level extraction (Tree-sitter/LSP), GitHub Action wrapper, `block` hook mode.
225
226## References
227- Design doc: `docs/plans/designs/008-oma-docs.md` (full architecture, schema spec, decision log, edge cases).
228- Schema spec: `doc-refs.json` v1 schema defined in design doc § doc-refs.json Schema.
229- Workflow hook integration: design doc § Workflow Hook Integration.
230- Migration: `deepinit` Step 6 retirement, design doc § Migration: deepinit Step 6.
231- Adjacent skills: `oma-translator` (v2 multilingual), `oma-skill-creator` (SSL-lite validation).