docguard-cli 0.27.0 → 0.29.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.es.md +102 -0
- package/README.md +65 -31
- package/README.pt-BR.md +101 -0
- package/STANDARD.md +20 -10
- package/cli/commands/agents.mjs +149 -0
- package/cli/commands/diff.mjs +6 -15
- package/cli/commands/explain.mjs +8 -6
- package/cli/commands/generate.mjs +14 -1001
- package/cli/commands/guard.mjs +149 -15
- package/cli/commands/init.mjs +23 -1
- package/cli/commands/llms.mjs +67 -5
- package/cli/commands/mcp.mjs +263 -0
- package/cli/commands/memory.mjs +115 -0
- package/cli/commands/score.mjs +76 -12
- package/cli/commands/sync-tests.mjs +272 -0
- package/cli/commands/sync.mjs +6 -0
- package/cli/commands/verify.mjs +67 -0
- package/cli/docguard.mjs +62 -5
- package/cli/findings.mjs +499 -0
- package/cli/scanners/agent-readability.mjs +202 -0
- package/cli/scanners/semantic-claims.mjs +160 -0
- package/cli/scanners/speckit.mjs +98 -28
- package/cli/shared-ignore.mjs +148 -16
- package/cli/shared.mjs +45 -1
- package/cli/validators/api-surface.mjs +182 -29
- package/cli/validators/architecture.mjs +91 -56
- package/cli/validators/canonical-sync.mjs +59 -28
- package/cli/validators/changelog.mjs +41 -17
- package/cli/validators/cross-reference.mjs +28 -11
- package/cli/validators/doc-quality.mjs +78 -44
- package/cli/validators/docs-coverage.mjs +90 -63
- package/cli/validators/docs-diff.mjs +63 -64
- package/cli/validators/docs-sync.mjs +48 -33
- package/cli/validators/drift.mjs +40 -34
- package/cli/validators/environment.mjs +67 -27
- package/cli/validators/freshness.mjs +12 -5
- package/cli/validators/generated-staleness.mjs +26 -10
- package/cli/validators/metadata-sync.mjs +28 -25
- package/cli/validators/metrics-consistency.mjs +89 -47
- package/cli/validators/schema-sync.mjs +37 -32
- package/cli/validators/security.mjs +7 -20
- package/cli/validators/spec-kit.mjs +3 -0
- package/cli/validators/structure.mjs +58 -23
- package/cli/validators/surface-sync.mjs +34 -15
- package/cli/validators/test-spec.mjs +87 -29
- package/cli/validators/todo-tracking.mjs +83 -74
- package/cli/validators/traceability.mjs +67 -39
- package/cli/writers/doc-generators.mjs +853 -0
- package/cli/writers/generate-io.mjs +142 -0
- package/cli/writers/sarif.mjs +129 -0
- package/commands/docguard.fix.md +56 -53
- package/commands/docguard.guard.md +53 -47
- package/commands/docguard.review.md +49 -31
- package/docs/ai-integration.md +133 -134
- package/docs/commands.md +49 -3
- package/docs/configuration.md +38 -0
- package/docs/faq.md +15 -0
- package/extensions/spec-kit-docguard/extension.yml +1 -1
- package/extensions/spec-kit-docguard/skills/docguard-fix/SKILL.md +2 -2
- package/extensions/spec-kit-docguard/skills/docguard-guard/SKILL.md +2 -2
- package/extensions/spec-kit-docguard/skills/docguard-review/SKILL.md +2 -2
- package/extensions/spec-kit-docguard/skills/docguard-score/SKILL.md +2 -2
- package/extensions/spec-kit-docguard/skills/docguard-sync/SKILL.md +2 -2
- package/package.json +1 -1
- package/schemas/docguard-config.schema.json +17 -0
- package/templates/ENVIRONMENT.md.template +5 -0
- package/templates/REQUIREMENTS.md.template +2 -0
- package/templates/SECURITY.md.template +6 -1
- package/templates/TEST-SPEC.md.template +5 -0
- package/templates/commands/docguard.fix.md +33 -10
- package/templates/commands/docguard.guard.md +40 -26
- package/templates/commands/docguard.init.md +23 -11
- package/templates/commands/docguard.review.md +25 -8
- package/templates/commands/docguard.update.md +14 -4
package/cli/docguard.mjs
CHANGED
|
@@ -44,9 +44,11 @@ import { runUpgrade } from './commands/upgrade.mjs';
|
|
|
44
44
|
import { runImpact } from './commands/impact.mjs';
|
|
45
45
|
import { runExplain } from './commands/explain.mjs';
|
|
46
46
|
import { runFeedback } from './commands/feedback.mjs';
|
|
47
|
+
import { runVerify } from './commands/verify.mjs';
|
|
47
48
|
import { runMemory } from './commands/memory.mjs';
|
|
48
49
|
import { runDemo } from './commands/demo.mjs';
|
|
49
50
|
import { runAgent } from './commands/agent.mjs';
|
|
51
|
+
import { runMcp } from './commands/mcp.mjs';
|
|
50
52
|
import { ensureSkills } from './ensure-skills.mjs';
|
|
51
53
|
|
|
52
54
|
// ── Shared constants (imported to break circular dependencies) ──────────
|
|
@@ -87,7 +89,9 @@ ${c.bold}Tools (situational, but day-to-day useful)${c.reset}
|
|
|
87
89
|
${c.green}generate${c.reset} Reverse-engineer canonical docs from existing code (${c.cyan}--plan${c.reset} for AI scan)
|
|
88
90
|
${c.green}agent${c.reset} One-shot agent task graph — ordered tasks, pre-filled code-truth, per-task verify (${c.cyan}--format json${c.reset})
|
|
89
91
|
${c.green}explain${c.reset} Explain a validator key, warning text, or finding code (${c.cyan}docguard explain SEC001${c.reset})
|
|
92
|
+
${c.green}verify${c.reset} Extract documented numbers/limits/enums for an agent to check vs code (${c.cyan}--semantic${c.reset})
|
|
90
93
|
${c.green}feedback${c.reset} Report likely false positives back to DocGuard (local-first + 1-click prefilled issue)
|
|
94
|
+
${c.green}mcp${c.reset} MCP server over stdio — guard/score/explain/verify/diagnose as agent tools
|
|
91
95
|
${c.green}memory${c.reset} Show what DocGuard remembers (${c.cyan}--diff${c.reset} drills into drift)
|
|
92
96
|
${c.green}trace${c.reset} Requirements traceability matrix (${c.cyan}--reverse${c.reset} for code→doc map)
|
|
93
97
|
${c.green}upgrade${c.reset} Migrate ${c.cyan}.docguard.json${c.reset} schema + CLI (${c.cyan}--apply --pr${c.reset} for team-wide PR)
|
|
@@ -232,13 +236,14 @@ const COMMAND_HELP = {
|
|
|
232
236
|
examples: ['docguard diff', 'docguard diff --since HEAD~5'],
|
|
233
237
|
},
|
|
234
238
|
sync: {
|
|
235
|
-
summary: 'Refresh code-truth doc sections (preview by default).',
|
|
236
|
-
usage: 'docguard sync [--write] [--since <ref>]',
|
|
239
|
+
summary: 'Refresh code-truth doc sections (preview by default). `--tests` reconciles the TEST-SPEC Source-to-Test Map from disk.',
|
|
240
|
+
usage: 'docguard sync [--write] [--since <ref>] [--tests]',
|
|
237
241
|
flags: [
|
|
238
242
|
['--write', 'Apply the refresh (default is a dry-run preview)'],
|
|
239
243
|
['--since <ref>', 'Only sync sections whose source files changed since <ref>'],
|
|
244
|
+
['--tests', 'Reconcile the TEST-SPEC Source-to-Test Map: drop ghost-source rows, append newly-covered source↔test pairs (report ghost tests). Pair with --write to apply.'],
|
|
240
245
|
],
|
|
241
|
-
examples: ['docguard sync', 'docguard sync --write'],
|
|
246
|
+
examples: ['docguard sync', 'docguard sync --write', 'docguard sync --tests', 'docguard sync --tests --write'],
|
|
242
247
|
},
|
|
243
248
|
fix: {
|
|
244
249
|
summary: 'Generate AI fix instructions for docs (or apply deterministic fixes).',
|
|
@@ -287,6 +292,15 @@ const COMMAND_HELP = {
|
|
|
287
292
|
flags: [['--format json', 'Machine-readable list of reportable findings + URLs']],
|
|
288
293
|
examples: ['docguard feedback'],
|
|
289
294
|
},
|
|
295
|
+
verify: {
|
|
296
|
+
summary: 'Extract the semantic claims in your canonical docs — documented numbers, limits, and enums (retention days, rate limits, GSI/role counts, status enums) — as a verification task list the agent checks against the code. This is the highest-value bug class (a doc value that drifted from code) and the one regex/AST cannot judge. DocGuard finds the claims; the LLM confirms them.',
|
|
297
|
+
usage: 'docguard verify [--semantic] [--format json]',
|
|
298
|
+
flags: [
|
|
299
|
+
['--semantic', 'Extract documented numbers/limits/enums to verify against code (the current — and default — mode)'],
|
|
300
|
+
['--format json', 'Machine-readable task list (the agent-executable artifact)'],
|
|
301
|
+
],
|
|
302
|
+
examples: ['docguard verify --semantic', 'docguard verify --semantic --format json'],
|
|
303
|
+
},
|
|
290
304
|
};
|
|
291
305
|
|
|
292
306
|
function printCommandHelp(command) {
|
|
@@ -355,6 +369,31 @@ async function main() {
|
|
|
355
369
|
flags.auto = true;
|
|
356
370
|
} else if (args[i] === '--write') {
|
|
357
371
|
flags.write = true;
|
|
372
|
+
} else if (args[i] === '--tests') {
|
|
373
|
+
// v0.28 (field report #10): `docguard sync --tests` reconciles the
|
|
374
|
+
// TEST-SPEC Source-to-Test Map from disk.
|
|
375
|
+
flags.tests = true;
|
|
376
|
+
} else if (args[i] === '--semantic') {
|
|
377
|
+
// v0.28 (field report #5): `docguard verify --semantic` extracts
|
|
378
|
+
// documented numbers/enums/limits for the agent to check against code.
|
|
379
|
+
flags.semantic = true;
|
|
380
|
+
} else if (args[i] === '--full') {
|
|
381
|
+
// v0.29: `docguard llms --full` emits llms-full.txt (inline doc bodies,
|
|
382
|
+
// the Mintlify-popularized companion to the llms.txt index).
|
|
383
|
+
flags.full = true;
|
|
384
|
+
} else if (args[i] === '--pack') {
|
|
385
|
+
// v0.29: `docguard memory --pack` writes .docguard/context-pack.md — a
|
|
386
|
+
// compact code-truth-stamped session-start context for AI agents.
|
|
387
|
+
flags.pack = true;
|
|
388
|
+
} else if (args[i] === '--sync') {
|
|
389
|
+
// v0.29: `docguard agents --sync` regenerates the agent-file family
|
|
390
|
+
// (CLAUDE.md, GEMINI.md, copilot-instructions, .cursor rules) from
|
|
391
|
+
// AGENTS.md — the canonical source. Kills hand-duplication drift.
|
|
392
|
+
flags.sync = true;
|
|
393
|
+
} else if (args[i] === '--check') {
|
|
394
|
+
// v0.29: `docguard agents --check` — CI staleness gate for the synced
|
|
395
|
+
// agent-file family (exit 2 when a variant is missing or stale).
|
|
396
|
+
flags.check = true;
|
|
358
397
|
} else if (args[i] === '--plan') {
|
|
359
398
|
flags.plan = true;
|
|
360
399
|
} else if (args[i] === '--since' && args[i + 1]) {
|
|
@@ -492,10 +531,13 @@ async function main() {
|
|
|
492
531
|
// touch" — so it joins the club to suppress the banner AND ensureSkills'
|
|
493
532
|
// .agent/.specify writes, which were a surprising side effect of a bare
|
|
494
533
|
// `generate --plan` (and were already suppressed for `--plan --write`).
|
|
495
|
-
|
|
534
|
+
// v0.29: 'sarif' joins 'json' — any machine format where stdout IS the
|
|
535
|
+
// artifact belongs here, or the banner corrupts the payload.
|
|
536
|
+
const jsonMode = flags.format === 'json' || flags.format === 'sarif';
|
|
496
537
|
// `agent` emits a machine task graph (JSON by default) — it must be banner-
|
|
497
538
|
// free and side-effect-free like the other read-only commands.
|
|
498
|
-
|
|
539
|
+
// `mcp`: stdout IS the JSON-RPC transport — any banner byte corrupts the stream.
|
|
540
|
+
const headless = jsonMode || flags.write || flags.checkOnly || flags.changedOnly || flags.quiet || flags.plan || command === 'agent' || command === 'mcp';
|
|
499
541
|
|
|
500
542
|
if (!headless) printBanner();
|
|
501
543
|
|
|
@@ -518,6 +560,10 @@ async function main() {
|
|
|
518
560
|
// feedback only writes its own .docguard/feedback/ — it must NOT scaffold
|
|
519
561
|
// skills or touch source, so it's gated out of ensureSkills like the rest.
|
|
520
562
|
'feedback',
|
|
563
|
+
// verify only reads docs and emits a task list — pure report.
|
|
564
|
+
'verify',
|
|
565
|
+
// mcp serves read-only tools over stdio — scaffolding writes are off-limits.
|
|
566
|
+
'mcp',
|
|
521
567
|
]);
|
|
522
568
|
|
|
523
569
|
// Silent auto-check: install skills/commands if missing. Skip entirely in
|
|
@@ -663,6 +709,17 @@ async function main() {
|
|
|
663
709
|
// redacted, capped GitHub issue URL. Opt-in; nothing filed automatically.
|
|
664
710
|
runFeedback(projectDir, config, flags);
|
|
665
711
|
break;
|
|
712
|
+
case 'verify':
|
|
713
|
+
// v0.28 (field report #5): extract documented numbers/limits/enums as a
|
|
714
|
+
// verification task list for the agent to check against code (semantic
|
|
715
|
+
// drift — the class regex/AST can't see). Read-only.
|
|
716
|
+
runVerify(projectDir, config, flags);
|
|
717
|
+
break;
|
|
718
|
+
case 'mcp':
|
|
719
|
+
// MCP stdio server — guard/score/explain/verify-claims/diagnose as tools
|
|
720
|
+
// for MCP clients. Long-lived; resolves when stdin closes.
|
|
721
|
+
await runMcp(projectDir, config, flags);
|
|
722
|
+
break;
|
|
666
723
|
case 'memory':
|
|
667
724
|
runMemory(projectDir, config, flags);
|
|
668
725
|
break;
|
package/cli/findings.mjs
CHANGED
|
@@ -89,6 +89,505 @@ export const CODES = {
|
|
|
89
89
|
help: 'The secret scan matched zero source files — usually a too-broad ignore config or a wrong sourceRoot. A scan that checks nothing is a dangerous false ✅.',
|
|
90
90
|
suppress: null,
|
|
91
91
|
},
|
|
92
|
+
// ── v0.29 findings-migration tranche (structure / changelog / metrics) ──
|
|
93
|
+
STR001: {
|
|
94
|
+
validator: 'structure',
|
|
95
|
+
title: 'Missing required file',
|
|
96
|
+
help: 'A file listed in requiredFiles (canonical doc, changelog, or drift log) does not exist. Create it from a template with `docguard init`, or remove it from `requiredFiles` in .docguard.json if your profile genuinely does not need it.',
|
|
97
|
+
suppress: null,
|
|
98
|
+
},
|
|
99
|
+
STR002: {
|
|
100
|
+
validator: 'structure',
|
|
101
|
+
title: 'Missing agent instructions file',
|
|
102
|
+
help: 'None of the configured agent files (AGENTS.md / CLAUDE.md) exist. AI agents working in this repo have no project contract. Create one with `docguard init` or write it by hand.',
|
|
103
|
+
suppress: null,
|
|
104
|
+
},
|
|
105
|
+
STR003: {
|
|
106
|
+
validator: 'structure',
|
|
107
|
+
title: 'Missing required doc section',
|
|
108
|
+
help: 'A canonical doc exists but lacks a section its document type requires. Add the section — or, if it is genuinely not applicable, own the absence with an inline marker: `<!-- docguard:section <slug> n/a — reason -->`.',
|
|
109
|
+
suppress: '<!-- docguard:section <slug> n/a — reason -->',
|
|
110
|
+
},
|
|
111
|
+
CHG001: {
|
|
112
|
+
validator: 'changelog',
|
|
113
|
+
title: 'Missing [Unreleased] section',
|
|
114
|
+
help: 'Keep a Changelog format expects an [Unreleased] section where in-progress work accumulates before each release. `docguard fix --write` inserts one.',
|
|
115
|
+
suppress: null,
|
|
116
|
+
},
|
|
117
|
+
CHG002: {
|
|
118
|
+
validator: 'changelog',
|
|
119
|
+
title: 'No version sections',
|
|
120
|
+
help: 'CHANGELOG.md has no `## [version]` headers — it does not follow Keep a Changelog format, so release tooling and readers cannot parse the history.',
|
|
121
|
+
suppress: null,
|
|
122
|
+
},
|
|
123
|
+
CHG003: {
|
|
124
|
+
validator: 'changelog',
|
|
125
|
+
title: 'Staged code without a CHANGELOG entry',
|
|
126
|
+
help: 'Code files are staged for commit but the changelog is not. Per STANDARD.md, a code change and its changelog entry travel in the same commit.',
|
|
127
|
+
suppress: null,
|
|
128
|
+
},
|
|
129
|
+
MET001: {
|
|
130
|
+
validator: 'metricsConsistency',
|
|
131
|
+
title: 'Documented count drifted from DocGuard meta-count',
|
|
132
|
+
help: 'A docguard-bound "N checks/validators" number in a doc no longer matches the tool\'s actual count. `docguard fix --write` rewrites it (fail-closed: only docguard-bound lines, with provenance).',
|
|
133
|
+
suppress: null,
|
|
134
|
+
},
|
|
135
|
+
MET002: {
|
|
136
|
+
validator: 'metricsConsistency',
|
|
137
|
+
title: 'Documented count drifted from a declared collection',
|
|
138
|
+
help: 'A doc states "N <noun>" for a noun declared in `config.collections`, but the collection glob matches a different number of files. Either the doc is stale (fix with `docguard fix --write`) or the code lost/gained members unintentionally — check which side is wrong before fixing.',
|
|
139
|
+
suppress: null,
|
|
140
|
+
},
|
|
141
|
+
FRS001: {
|
|
142
|
+
validator: 'freshness',
|
|
143
|
+
title: 'Doc has no freshness signal',
|
|
144
|
+
help: 'The doc exists but is not committed to git and carries no review marker, so its currency cannot be assessed. Commit it, or stamp it with `<!-- docguard:last-reviewed YYYY-MM-DD -->` (or `<!-- docguard:status approved -->` for a doc generated this session).',
|
|
145
|
+
suppress: '<!-- docguard:status approved -->',
|
|
146
|
+
},
|
|
147
|
+
FRS002: {
|
|
148
|
+
validator: 'freshness',
|
|
149
|
+
title: 'Code moved on since the doc was last updated',
|
|
150
|
+
help: '10+ code commits landed after the doc\'s last update/review — its code-truth sections are likely stale. Run `docguard sync --write` to refresh them in one pass, or review and stamp `<!-- docguard:last-reviewed YYYY-MM-DD -->` if it is still accurate.',
|
|
151
|
+
suppress: null,
|
|
152
|
+
},
|
|
153
|
+
FRS003: {
|
|
154
|
+
validator: 'freshness',
|
|
155
|
+
title: 'Doc predates the latest code change by 30+ days',
|
|
156
|
+
help: 'The doc\'s last update is more than 30 days older than the newest code commit. Review it against the current code, then update it or stamp it reviewed.',
|
|
157
|
+
suppress: null,
|
|
158
|
+
},
|
|
159
|
+
FRS004: {
|
|
160
|
+
validator: 'freshness',
|
|
161
|
+
title: 'CHANGELOG lagging behind code changes',
|
|
162
|
+
help: 'Code changed but CHANGELOG.md has not been updated in over a week. Add the missing entries under [Unreleased].',
|
|
163
|
+
suppress: null,
|
|
164
|
+
},
|
|
165
|
+
FRS005: {
|
|
166
|
+
validator: 'freshness',
|
|
167
|
+
title: 'DRIFT-LOG possibly stale',
|
|
168
|
+
help: 'Recent commits added `DRIFT:` comments but DRIFT-LOG.md has not kept pace. Log the new deviations (each DRIFT comment needs a DRIFT-LOG entry) or remove resolved markers.',
|
|
169
|
+
suppress: null,
|
|
170
|
+
},
|
|
171
|
+
DSY001: {
|
|
172
|
+
validator: 'docsSync',
|
|
173
|
+
title: 'Route not referenced in canonical docs',
|
|
174
|
+
help: 'A route file exists but neither its path nor its basename appears in any docs-canonical .md file. Reference the route in a canonical doc (e.g. ARCHITECTURE.md or an API doc) so the documented surface matches the code.',
|
|
175
|
+
suppress: null,
|
|
176
|
+
},
|
|
177
|
+
DSY002: {
|
|
178
|
+
validator: 'docsSync',
|
|
179
|
+
title: 'Service not referenced in canonical docs',
|
|
180
|
+
help: 'A service/lib file exists but neither its path nor its basename appears in any docs-canonical .md file. Reference the service in a canonical doc (e.g. ARCHITECTURE.md) so the documented surface matches the code.',
|
|
181
|
+
suppress: null,
|
|
182
|
+
},
|
|
183
|
+
DSY003: {
|
|
184
|
+
validator: 'docsSync',
|
|
185
|
+
title: 'Route file missing from OpenAPI spec',
|
|
186
|
+
help: 'A route file defines paths (or has a route-like filename) with no matching path in the detected OpenAPI/Swagger spec. Re-run your spec generator (e.g. zod-to-openapi) or add the paths to the spec by hand.',
|
|
187
|
+
suppress: null,
|
|
188
|
+
},
|
|
189
|
+
DDF001: {
|
|
190
|
+
validator: 'docsDiff',
|
|
191
|
+
title: 'Tech Stack drift',
|
|
192
|
+
help: 'The tech named in docs-canonical/ARCHITECTURE.md and the dependencies actually declared (package.json across the monorepo, Dockerfile, .tf files) disagree. Drift is two-sided — document the new tech or remove the stale entries after checking which side is wrong.',
|
|
193
|
+
suppress: null,
|
|
194
|
+
},
|
|
195
|
+
DDF002: {
|
|
196
|
+
validator: 'docsDiff',
|
|
197
|
+
title: 'Test Files drift',
|
|
198
|
+
help: 'The test files documented in docs-canonical/TEST-SPEC.md and the test files on disk disagree. Add entries for new tests or remove documented tests that no longer exist — TEST-SPEC.md entries may be glob patterns.',
|
|
199
|
+
suppress: null,
|
|
200
|
+
},
|
|
201
|
+
DCV001: {
|
|
202
|
+
validator: 'docsCoverage',
|
|
203
|
+
title: 'Undocumented config file',
|
|
204
|
+
help: 'A project-specific config/dotfile at the repo root is not mentioned in any documentation. Document its purpose in ARCHITECTURE.md or README.md, or add it to `ignore` in .docguard.json if it is genuinely internal.',
|
|
205
|
+
suppress: null,
|
|
206
|
+
},
|
|
207
|
+
DCV002: {
|
|
208
|
+
validator: 'docsCoverage',
|
|
209
|
+
title: 'Undocumented CLI bin command',
|
|
210
|
+
help: 'package.json declares a `bin` entry users can run, but no documentation mentions it. Document the command, typically in README.md under Usage.',
|
|
211
|
+
suppress: null,
|
|
212
|
+
},
|
|
213
|
+
DCV003: {
|
|
214
|
+
validator: 'docsCoverage',
|
|
215
|
+
title: 'Source directory not in ARCHITECTURE.md',
|
|
216
|
+
help: 'A directory under a source root is not referenced in ARCHITECTURE.md. Add it to the Component Map, or add an ignore pattern in .docguard.json if it is build output.',
|
|
217
|
+
suppress: null,
|
|
218
|
+
},
|
|
219
|
+
DCV004: {
|
|
220
|
+
validator: 'docsCoverage',
|
|
221
|
+
title: 'Code-referenced config not documented',
|
|
222
|
+
help: "Source code reads a config file (a resolve/readFileSync/existsSync call) that no documentation mentions. Describe the file's purpose and format in README.md or ARCHITECTURE.md.",
|
|
223
|
+
suppress: null,
|
|
224
|
+
},
|
|
225
|
+
DCV005: {
|
|
226
|
+
validator: 'docsCoverage',
|
|
227
|
+
title: 'README missing a standard section',
|
|
228
|
+
help: 'README.md lacks a section every well-documented project needs — Installation, Usage, or License (Standard README spec). Add the missing section.',
|
|
229
|
+
suppress: null,
|
|
230
|
+
},
|
|
231
|
+
DCV006: {
|
|
232
|
+
validator: 'docsCoverage',
|
|
233
|
+
title: 'IaC detected but no Infrastructure section',
|
|
234
|
+
help: 'An IaC tool (CDK, Terraform, Pulumi, SAM, or Serverless) was detected but ARCHITECTURE.md has no Infrastructure heading. Add an "Infrastructure" section covering the tool\'s layout — the warning names the exact marker file and directories to describe.',
|
|
235
|
+
suppress: null,
|
|
236
|
+
},
|
|
237
|
+
MDS001: {
|
|
238
|
+
validator: 'metadataSync',
|
|
239
|
+
title: 'extension.yml version out of sync',
|
|
240
|
+
help: 'An extension.yml declares a version that differs from package.json. `docguard fix --write` rewrites it to the current version.',
|
|
241
|
+
suppress: null,
|
|
242
|
+
},
|
|
243
|
+
MDS002: {
|
|
244
|
+
validator: 'metadataSync',
|
|
245
|
+
title: 'Stale version reference in docs',
|
|
246
|
+
help: 'A markdown file references an older version of this package in an actionable context (download URL, install command, or version: declaration). `docguard fix --write` replaces it with the current version; prose mentions of old versions are intentionally not flagged.',
|
|
247
|
+
suppress: null,
|
|
248
|
+
},
|
|
249
|
+
ENV001: {
|
|
250
|
+
validator: 'environment',
|
|
251
|
+
title: 'Missing setup section in ENVIRONMENT.md',
|
|
252
|
+
help: 'ENVIRONMENT.md lacks both a "## Prerequisites" and a "## Setup Steps" heading (H2/H3 anchored, not a TOC mention). Add a Setup Steps section describing how to get the project running from a fresh clone.',
|
|
253
|
+
suppress: null,
|
|
254
|
+
},
|
|
255
|
+
ENV002: {
|
|
256
|
+
validator: 'environment',
|
|
257
|
+
title: 'Missing Environment Variables section',
|
|
258
|
+
help: 'ENVIRONMENT.md has no "## Environment Variables" heading. Add the section and document each variable the app reads — backticked names or a pipe table both count.',
|
|
259
|
+
suppress: null,
|
|
260
|
+
},
|
|
261
|
+
ENV003: {
|
|
262
|
+
validator: 'environment',
|
|
263
|
+
title: 'Env vars used in code but undocumented',
|
|
264
|
+
help: "Variables read via process.env / import.meta.env were found in code but not in ENVIRONMENT.md or .env.example. Document each listed variable in the doc, or add it to .env.example — either counts as documentation.",
|
|
265
|
+
suppress: null,
|
|
266
|
+
},
|
|
267
|
+
ENV004: {
|
|
268
|
+
validator: 'environment',
|
|
269
|
+
title: 'ENVIRONMENT.md references a missing .env.example',
|
|
270
|
+
help: 'The doc mentions .env.example but the file does not exist. Create it with placeholder values, or remove the stale reference.',
|
|
271
|
+
suppress: null,
|
|
272
|
+
},
|
|
273
|
+
ENV005: {
|
|
274
|
+
validator: 'environment',
|
|
275
|
+
title: '.env exists without a .env.example template',
|
|
276
|
+
help: "A local .env (or .env.local / .env.development) exists but there is no .env.example, so new contributors won't know what vars to set. Create a .env.example listing every variable with a placeholder value.",
|
|
277
|
+
suppress: null,
|
|
278
|
+
},
|
|
279
|
+
TSP001: {
|
|
280
|
+
validator: 'testSpec',
|
|
281
|
+
title: 'Source declared ❌ (missing tests) in TEST-SPEC',
|
|
282
|
+
help: 'A Source-to-Test Map row declares its source as ❌ — the author has flagged missing tests. Write the tests, then update the row status to ✅.',
|
|
283
|
+
suppress: null,
|
|
284
|
+
},
|
|
285
|
+
TSP002: {
|
|
286
|
+
validator: 'testSpec',
|
|
287
|
+
title: 'Source declared ⚠️ (partial coverage) in TEST-SPEC',
|
|
288
|
+
help: 'A Source-to-Test Map row declares partial coverage for its source. Extend the tests, then update the row status to ✅.',
|
|
289
|
+
suppress: null,
|
|
290
|
+
},
|
|
291
|
+
TSP003: {
|
|
292
|
+
validator: 'testSpec',
|
|
293
|
+
title: 'Mapped source file not found on disk',
|
|
294
|
+
help: 'A Source-to-Test Map row points at a source file that no longer exists — usually a stale entry after a move or delete. Update or remove the row. If the flagged cell is prose rather than a real path, report it as a false positive.',
|
|
295
|
+
suppress: null,
|
|
296
|
+
},
|
|
297
|
+
TSP004: {
|
|
298
|
+
validator: 'testSpec',
|
|
299
|
+
title: 'Mapped test file not found on disk',
|
|
300
|
+
help: 'A Source-to-Test Map row declares a test file that does not exist. Create the test file, or point the row at the actual test path.',
|
|
301
|
+
suppress: null,
|
|
302
|
+
},
|
|
303
|
+
TSP005: {
|
|
304
|
+
validator: 'testSpec',
|
|
305
|
+
title: 'E2E journey declared ❌ (missing test)',
|
|
306
|
+
help: 'A Critical User Journeys / Critical CLI Flows row is marked ❌. Implement the journey test, then mark the row ✅.',
|
|
307
|
+
suppress: null,
|
|
308
|
+
},
|
|
309
|
+
TSP006: {
|
|
310
|
+
validator: 'testSpec',
|
|
311
|
+
title: 'E2E journey marked ✅ but test file missing',
|
|
312
|
+
help: 'A journey row claims ✅ but none of its referenced test paths exist on disk (globs and "(N suites)" annotations are honored). The glyph is a claim, the file is the proof — fix the path in the row or restore the missing test.',
|
|
313
|
+
suppress: null,
|
|
314
|
+
},
|
|
315
|
+
TSP007: {
|
|
316
|
+
validator: 'testSpec',
|
|
317
|
+
title: 'No tests found anywhere in the project',
|
|
318
|
+
help: 'TEST-SPEC.md maps nothing and no tests/ directory, co-located *.test.* files, or vitest/jest config were found. Add tests, then map them in a "## Source-to-Test Map" table so coverage claims stay verifiable.',
|
|
319
|
+
suppress: null,
|
|
320
|
+
},
|
|
321
|
+
DRF001: {
|
|
322
|
+
validator: 'drift',
|
|
323
|
+
title: 'DRIFT comment but no drift log file',
|
|
324
|
+
help: 'Code contains a // DRIFT: comment but the drift log (DRIFT-LOG.md) does not exist, so the deviation is unlogged. Create the drift log — `docguard init` scaffolds it — then record this deviation in it.',
|
|
325
|
+
suppress: null,
|
|
326
|
+
},
|
|
327
|
+
DRF002: {
|
|
328
|
+
validator: 'drift',
|
|
329
|
+
title: 'DRIFT comment not logged in DRIFT-LOG.md',
|
|
330
|
+
help: "A // DRIFT: comment's file has no matching entry in DRIFT-LOG.md. Add an entry naming the file and explaining why the code deviates from docs-canonical.",
|
|
331
|
+
suppress: null,
|
|
332
|
+
},
|
|
333
|
+
TRC001: {
|
|
334
|
+
validator: 'traceability',
|
|
335
|
+
title: 'Required canonical doc missing (no traceability)',
|
|
336
|
+
help: 'A doc listed in requiredFiles.canonical does not exist, so no doc-to-source link can be checked. Create it from a template with `docguard init` (the structure validator flags the missing file too).',
|
|
337
|
+
suppress: null,
|
|
338
|
+
},
|
|
339
|
+
TRC002: {
|
|
340
|
+
validator: 'traceability',
|
|
341
|
+
title: 'Unlinked canonical doc (no matching source)',
|
|
342
|
+
help: 'The doc exists but no source file matches its built-in path patterns. If the implementing code lives in a non-standard location, link it explicitly by adding a `// @doc <DOC-NAME>.md` annotation near the top of a source file that implements the doc.',
|
|
343
|
+
suppress: '// @doc <DOC-NAME>.md',
|
|
344
|
+
},
|
|
345
|
+
TRC003: {
|
|
346
|
+
validator: 'traceability',
|
|
347
|
+
title: 'Orphaned doc in docs-canonical/',
|
|
348
|
+
help: 'A doc exists in docs-canonical/ but is not listed in requiredFiles.canonical, so no validator checks it and it can silently rot. Delete it, or add it to requiredFiles.canonical in .docguard.json so it gets validated.',
|
|
349
|
+
suppress: null,
|
|
350
|
+
},
|
|
351
|
+
TRC004: {
|
|
352
|
+
validator: 'traceability',
|
|
353
|
+
title: 'Requirement ID without test coverage',
|
|
354
|
+
help: 'A requirement ID found in the docs (REQ-/FR-/SC-/T-style) has no matching reference in any test file. Add an `@req <ID>` comment to the test that verifies it. Requirement traceability is opt-in: it only activates once IDs appear in your docs.',
|
|
355
|
+
suppress: null,
|
|
356
|
+
},
|
|
357
|
+
TRC005: {
|
|
358
|
+
validator: 'traceability',
|
|
359
|
+
title: 'Orphaned test reference to unknown requirement',
|
|
360
|
+
help: 'A test references a requirement ID that no doc defines — the test claims to verify something the docs never specified. Remove the stale reference, or add the requirement to the documentation.',
|
|
361
|
+
suppress: null,
|
|
362
|
+
},
|
|
363
|
+
TDO001: {
|
|
364
|
+
validator: 'todoTracking',
|
|
365
|
+
title: 'Skipped test without explanation',
|
|
366
|
+
help: 'A test.skip / it.skip / xit (or similar) has no justification nearby. Add a `// REASON:` comment on the skip line or up to 3 lines above it explaining why the test is skipped (SKIP/NOTE/WHY/TODO/FIXME prefixes also count).',
|
|
367
|
+
suppress: '// REASON: <why this test is skipped>',
|
|
368
|
+
},
|
|
369
|
+
TDO002: {
|
|
370
|
+
validator: 'todoTracking',
|
|
371
|
+
title: 'Untracked TODO/FIXME annotation',
|
|
372
|
+
help: 'A TODO/FIXME/HACK/XXX/TEMP/WORKAROUND comment is not tracked in any tracking doc (ROADMAP.md, CURRENT-STATE.md, TODO.md, BACKLOG.md, or docs-canonical/ equivalents). Track it there with its file location, resolve it, or exclude the path via `todoIgnore` in .docguard.json.',
|
|
373
|
+
suppress: null,
|
|
374
|
+
},
|
|
375
|
+
TDO003: {
|
|
376
|
+
validator: 'todoTracking',
|
|
377
|
+
title: 'Additional untracked TODOs elided',
|
|
378
|
+
help: 'Guard reports only the first 5 untracked TODO/FIXME items to avoid noise; this line counts the remainder. Track or resolve the reported items and re-run guard to surface more, or exclude noisy paths via `todoIgnore` in .docguard.json.',
|
|
379
|
+
suppress: null,
|
|
380
|
+
},
|
|
381
|
+
SCH001: {
|
|
382
|
+
validator: 'schemaSync',
|
|
383
|
+
title: 'Database models found but no DATA-MODEL.md',
|
|
384
|
+
help: 'Schema definitions were detected (Prisma/Drizzle/TypeORM/Sequelize/Knex/Django/Rails) but docs-canonical/DATA-MODEL.md does not exist, so the schema is undocumented. Run `docguard init` to create it, then document the models.',
|
|
385
|
+
suppress: null,
|
|
386
|
+
},
|
|
387
|
+
SCH002: {
|
|
388
|
+
validator: 'schemaSync',
|
|
389
|
+
title: 'Model not documented in DATA-MODEL.md',
|
|
390
|
+
help: 'A model/table found in a schema file does not appear anywhere in DATA-MODEL.md (matching is case-insensitive and singular/plural tolerant). Add it to the Entity Definitions section.',
|
|
391
|
+
suppress: null,
|
|
392
|
+
},
|
|
393
|
+
ARC001: {
|
|
394
|
+
validator: 'architecture',
|
|
395
|
+
title: 'Forbidden layer import (layers config)',
|
|
396
|
+
help: 'A file imports from a layer its own layer may not import, per the `layers` map in .docguard.json. Remove the import or route it through an allowed layer — or update the layers config if the architecture genuinely changed.',
|
|
397
|
+
suppress: null,
|
|
398
|
+
},
|
|
399
|
+
ARC002: {
|
|
400
|
+
validator: 'architecture',
|
|
401
|
+
title: 'Circular dependency',
|
|
402
|
+
help: 'A load-time import cycle was detected between source files. Break it by converting one edge to a dynamic `import()` (runtime imports do not create load-time cycle edges) or by extracting the shared code into a third module both sides import.',
|
|
403
|
+
suppress: null,
|
|
404
|
+
},
|
|
405
|
+
ARC003: {
|
|
406
|
+
validator: 'architecture',
|
|
407
|
+
title: 'Layer boundary violation (ARCHITECTURE.md)',
|
|
408
|
+
help: 'An import crosses a boundary the Layer Boundaries table in docs-canonical/ARCHITECTURE.md forbids. Remove or invert the import — or update the table if the rule changed, so docs and code agree.',
|
|
409
|
+
suppress: null,
|
|
410
|
+
},
|
|
411
|
+
CSY001: {
|
|
412
|
+
validator: 'canonicalSync',
|
|
413
|
+
title: 'No surface docs to check',
|
|
414
|
+
help: "canonical-sync found neither README.md nor AGENTS.md, so DocGuard's own surface-count claims cannot be checked. Add a README.md (this check only runs in the docguard-cli repo).",
|
|
415
|
+
suppress: null,
|
|
416
|
+
},
|
|
417
|
+
CSY002: {
|
|
418
|
+
validator: 'canonicalSync',
|
|
419
|
+
title: 'Stale "ships N commands" claim',
|
|
420
|
+
help: 'A surface doc (README.md/AGENTS.md) claims a command count that does not match the real user-facing command count parsed from --help (or the cli/commands file count). Update the claim.',
|
|
421
|
+
suppress: null,
|
|
422
|
+
},
|
|
423
|
+
CSY003: {
|
|
424
|
+
validator: 'canonicalSync',
|
|
425
|
+
title: 'Stale "N validators" claim',
|
|
426
|
+
help: "A surface doc (README.md/AGENTS.md) states a validator count that does not match guard's actual count (validator files + the inlined Doc Sections validator). Update the claim.",
|
|
427
|
+
suppress: null,
|
|
428
|
+
},
|
|
429
|
+
CSY004: {
|
|
430
|
+
validator: 'canonicalSync',
|
|
431
|
+
title: 'Stale architecture-diagram counts',
|
|
432
|
+
help: 'The Commands (N) / Validators (N) labels in the README mermaid architecture diagram do not match code-truth — the exact drift that went unnoticed for 5 releases. Update the mermaid block.',
|
|
433
|
+
suppress: null,
|
|
434
|
+
},
|
|
435
|
+
SPK001: {
|
|
436
|
+
validator: 'specKit',
|
|
437
|
+
title: 'Spec Kit not detected',
|
|
438
|
+
help: 'No .specify/ directory, specs/ folders, constitution.md, or memory/ was found. Consider adopting spec-driven development with `specify init` (github.com/github/spec-kit), or disable the specKit validator in .docguard.json if it is not wanted.',
|
|
439
|
+
suppress: null,
|
|
440
|
+
},
|
|
441
|
+
SPK002: {
|
|
442
|
+
validator: 'specKit',
|
|
443
|
+
title: 'Spec Kit artifacts without .specify/ structure',
|
|
444
|
+
help: 'Legacy spec/constitution/memory artifacts exist but the standard .specify/ directory is missing. Run `specify init` to create the v3+ standard structure.',
|
|
445
|
+
suppress: null,
|
|
446
|
+
},
|
|
447
|
+
SPK003: {
|
|
448
|
+
validator: 'specKit',
|
|
449
|
+
title: 'spec.md quality issue',
|
|
450
|
+
help: 'A spec.md is missing a mandatory template element: a required section (User Scenarios, Requirements, Success Criteria), FR-/REQ- requirement IDs, or SC- success-criteria IDs. A defect spec can opt into the narrower bugfix shape (Root Cause + Fix required instead) with the inline marker.',
|
|
451
|
+
suppress: '<!-- docguard:spec-type bugfix -->',
|
|
452
|
+
},
|
|
453
|
+
SPK004: {
|
|
454
|
+
validator: 'specKit',
|
|
455
|
+
title: 'plan.md quality issue',
|
|
456
|
+
help: 'A plan.md is missing a mandatory section (Summary, Technical Context, or Project Structure) per spec-kit plan-template.md. Add the section.',
|
|
457
|
+
suppress: null,
|
|
458
|
+
},
|
|
459
|
+
SPK005: {
|
|
460
|
+
validator: 'specKit',
|
|
461
|
+
title: 'tasks.md quality issue',
|
|
462
|
+
help: 'A tasks.md lacks a phased breakdown ("Phase 1:", "Phase 2:", …) or task IDs (T001, T002, …) per spec-kit tasks-template.md.',
|
|
463
|
+
suppress: null,
|
|
464
|
+
},
|
|
465
|
+
SPK006: {
|
|
466
|
+
validator: 'specKit',
|
|
467
|
+
title: 'Spec Kit artifact unreadable',
|
|
468
|
+
help: 'A spec.md/plan.md/tasks.md exists but could not be read. Check file permissions and encoding.',
|
|
469
|
+
suppress: null,
|
|
470
|
+
},
|
|
471
|
+
SPK007: {
|
|
472
|
+
validator: 'specKit',
|
|
473
|
+
title: 'Constitution without AGENTS.md',
|
|
474
|
+
help: 'constitution.md exists but there is no AGENTS.md. AI agents look to AGENTS.md for project rules — create one (e.g. via `docguard init`) and reference the constitution from it.',
|
|
475
|
+
suppress: null,
|
|
476
|
+
},
|
|
477
|
+
XRF001: {
|
|
478
|
+
validator: 'crossReference',
|
|
479
|
+
title: 'Broken doc link',
|
|
480
|
+
help: 'A markdown link between canonical docs points to a file that does not exist (checked relative to the source doc and the project root, URL-decoded). Fix the target path or remove the dead link.',
|
|
481
|
+
suppress: null,
|
|
482
|
+
},
|
|
483
|
+
XRF002: {
|
|
484
|
+
validator: 'crossReference',
|
|
485
|
+
title: 'Broken doc anchor',
|
|
486
|
+
help: 'A `#anchor` link does not match any heading in the target doc (GFM slug rules). When exactly one near-miss heading exists (edit distance ≤ 2) the warning is marked [auto-fixable] and `docguard fix --write` rewrites it; otherwise pick the correct heading by hand.',
|
|
487
|
+
suppress: null,
|
|
488
|
+
},
|
|
489
|
+
GST001: {
|
|
490
|
+
validator: 'generatedStaleness',
|
|
491
|
+
title: 'Generated doc stuck in draft',
|
|
492
|
+
help: 'A docguard:generated doc has sat in `status: draft` beyond the staleness window (default 14 days; `draftStalenessDays` in .docguard.json). Draft the prose (e.g. `/docguard.fix --doc <name>`) and promote it to status:current, or delete the forgotten skeleton.',
|
|
493
|
+
suppress: null,
|
|
494
|
+
},
|
|
495
|
+
GST002: {
|
|
496
|
+
validator: 'generatedStaleness',
|
|
497
|
+
title: 'Code-truth section stale',
|
|
498
|
+
help: "A `source=code` section's body no longer matches what the scanner produces — code changed without `docguard sync --write`, or someone hand-edited a generated section. Run `docguard sync --write` (or `docguard fix --write`), or pin the section if it is intentionally hand-maintained.",
|
|
499
|
+
suppress: '<!-- docguard:section id=<id> source=code pinned="reason" -->',
|
|
500
|
+
},
|
|
501
|
+
SSY001: {
|
|
502
|
+
validator: 'surfaceSync',
|
|
503
|
+
title: 'Surface entry missing glob',
|
|
504
|
+
help: 'A surfaceSync.surfaces entry in .docguard.json has no `glob`, so the code-truth set cannot be discovered and the surface is skipped. Add a glob like "cli/commands/*.mjs".',
|
|
505
|
+
suppress: null,
|
|
506
|
+
},
|
|
507
|
+
SSY002: {
|
|
508
|
+
validator: 'surfaceSync',
|
|
509
|
+
title: 'Surface list drift',
|
|
510
|
+
help: "A doc's table/bullet inventory for a declared surface disagrees with the files its glob discovers — items exist in code but are missing from the doc, or the doc lists items with no file behind them. Update the list, or add intentional aliases/non-public items to the surface's `ignore` list.",
|
|
511
|
+
suppress: null,
|
|
512
|
+
},
|
|
513
|
+
API001: {
|
|
514
|
+
validator: 'apiSurface',
|
|
515
|
+
title: 'OpenAPI spec unparseable',
|
|
516
|
+
help: "The spec declares `paths:` but DocGuard's minimal parser extracted zero endpoints (unsupported YAML: $ref, anchors, folded scalars). Code scanning takes over, but the spec cannot serve as ground truth — validate it with a full OpenAPI linter.",
|
|
517
|
+
suppress: null,
|
|
518
|
+
},
|
|
519
|
+
API002: {
|
|
520
|
+
validator: 'apiSurface',
|
|
521
|
+
title: 'OpenAPI specs diverge',
|
|
522
|
+
help: 'Two or more specs in canonical locations disagree on their endpoint sets; the sourceRoot-nearest spec is treated as authoritative. Regenerate or delete the stale copy so they agree.',
|
|
523
|
+
suppress: null,
|
|
524
|
+
},
|
|
525
|
+
API003: {
|
|
526
|
+
validator: 'apiSurface',
|
|
527
|
+
title: 'Spec-declared endpoint has no registered route',
|
|
528
|
+
help: 'The OpenAPI spec declares an endpoint that no scanned route registers. Either the spec is stale (remove the endpoint) or the route is registered dynamically where the scanner cannot see it — flagged low-confidence for exactly that reason.',
|
|
529
|
+
suppress: null,
|
|
530
|
+
},
|
|
531
|
+
API004: {
|
|
532
|
+
validator: 'apiSurface',
|
|
533
|
+
title: 'Documented endpoint not found in code',
|
|
534
|
+
help: 'docs-canonical/API-REFERENCE.md documents an endpoint absent from the actual surface. Spec-confirmed absences are errors and `docguard fix --write` removes them; code-scan-only absences are low-confidence warnings ([code-scan — verify]) — verify before pruning.',
|
|
535
|
+
suppress: null,
|
|
536
|
+
},
|
|
537
|
+
API005: {
|
|
538
|
+
validator: 'apiSurface',
|
|
539
|
+
title: 'Undocumented endpoint in code',
|
|
540
|
+
help: 'A real endpoint exists in the spec/routes but is missing from docs-canonical/API-REFERENCE.md. Add a documentation block for it.',
|
|
541
|
+
suppress: null,
|
|
542
|
+
},
|
|
543
|
+
DQ001: {
|
|
544
|
+
validator: 'docQuality',
|
|
545
|
+
title: 'High passive voice ratio',
|
|
546
|
+
help: "More than 25% of the doc's prose sentences are passive (configurable via docQuality.passiveVoiceThreshold). Rewrite in active voice — or opt the doc out with the inline marker if passive is intentional (sequence/flow docs).",
|
|
547
|
+
suppress: '<!-- docguard:quality passive-voice off — your reason -->',
|
|
548
|
+
},
|
|
549
|
+
DQ002: {
|
|
550
|
+
validator: 'docQuality',
|
|
551
|
+
title: 'High ambiguous pronoun ratio',
|
|
552
|
+
help: 'Over 15% of words are ambiguous pronouns (it/this/that/they…). Replace them with the specific noun they refer to so statements stay verifiable.',
|
|
553
|
+
suppress: null,
|
|
554
|
+
},
|
|
555
|
+
DQ003: {
|
|
556
|
+
validator: 'docQuality',
|
|
557
|
+
title: 'Low atomicity (compound sentences)',
|
|
558
|
+
help: 'Over 35% of sentences are compound. Split them so each sentence carries one verifiable statement (IEEE 830 §4.1).',
|
|
559
|
+
suppress: null,
|
|
560
|
+
},
|
|
561
|
+
DQ004: {
|
|
562
|
+
validator: 'docQuality',
|
|
563
|
+
title: 'Very low Flesch reading ease',
|
|
564
|
+
help: 'The doc scores below 5/100 — effectively unreadable even for technical material (tech docs typically score 10-30). Shorten sentences and use simpler words.',
|
|
565
|
+
suppress: null,
|
|
566
|
+
},
|
|
567
|
+
DQ005: {
|
|
568
|
+
validator: 'docQuality',
|
|
569
|
+
title: 'Reading grade level too high',
|
|
570
|
+
help: 'Flesch-Kincaid grade above 22 (PhD+). Aim for grade 12-16 for technical docs by simplifying sentence structure and vocabulary.',
|
|
571
|
+
suppress: null,
|
|
572
|
+
},
|
|
573
|
+
DQ006: {
|
|
574
|
+
validator: 'docQuality',
|
|
575
|
+
title: 'Average sentence too long',
|
|
576
|
+
help: 'Average prose sentence exceeds 30 words. Break long sentences up — target 30 words or fewer.',
|
|
577
|
+
suppress: null,
|
|
578
|
+
},
|
|
579
|
+
DQ007: {
|
|
580
|
+
validator: 'docQuality',
|
|
581
|
+
title: 'High negation load',
|
|
582
|
+
help: 'Over 20% of sentences use negation (configurable via docQuality.negationLoadThreshold). Rephrase in positive terms ("must not fail" → "must succeed", IEEE 830 §4.3) — or opt the doc out with the inline marker (security/operational docs legitimately prohibit).',
|
|
583
|
+
suppress: '<!-- docguard:quality negation-load off — your reason -->',
|
|
584
|
+
},
|
|
585
|
+
DQ008: {
|
|
586
|
+
validator: 'docQuality',
|
|
587
|
+
title: 'High conditional load',
|
|
588
|
+
help: 'Over 30% of sentences are conditional (if/unless/when…). Split conditionals into separate, unconditional requirements.',
|
|
589
|
+
suppress: null,
|
|
590
|
+
},
|
|
92
591
|
};
|
|
93
592
|
|
|
94
593
|
/**
|