docguard-cli 0.9.11 → 0.10.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.
Files changed (36) hide show
  1. package/README.md +3 -2
  2. package/cli/commands/diagnose.mjs +23 -15
  3. package/cli/commands/diff.mjs +110 -137
  4. package/cli/commands/fix.mjs +39 -3
  5. package/cli/commands/generate.mjs +57 -27
  6. package/cli/commands/guard.mjs +45 -24
  7. package/cli/docguard.mjs +0 -0
  8. package/cli/scanners/api-doc.mjs +122 -0
  9. package/cli/scanners/doc-tools.mjs +1 -1
  10. package/cli/scanners/routes.mjs +45 -32
  11. package/cli/shared-source.mjs +247 -0
  12. package/cli/validators/api-surface.mjs +179 -0
  13. package/cli/validators/architecture.mjs +4 -3
  14. package/cli/validators/changelog.mjs +42 -2
  15. package/cli/validators/doc-quality.mjs +3 -2
  16. package/cli/validators/docs-coverage.mjs +9 -14
  17. package/cli/validators/docs-diff.mjs +117 -66
  18. package/cli/validators/docs-sync.mjs +30 -24
  19. package/cli/validators/drift.mjs +6 -2
  20. package/cli/validators/environment.mjs +43 -3
  21. package/cli/validators/freshness.mjs +4 -3
  22. package/cli/validators/metadata-sync.mjs +11 -6
  23. package/cli/validators/metrics-consistency.mjs +4 -2
  24. package/cli/validators/schema-sync.mjs +19 -10
  25. package/cli/validators/security.mjs +20 -7
  26. package/cli/validators/structure.mjs +8 -1
  27. package/cli/validators/test-spec.mjs +26 -17
  28. package/cli/validators/todo-tracking.mjs +21 -8
  29. package/cli/validators/traceability.mjs +61 -36
  30. package/commands/docguard.guard.md +5 -4
  31. package/docs/quickstart.md +1 -1
  32. package/extensions/spec-kit-docguard/README.md +1 -1
  33. package/extensions/spec-kit-docguard/commands/guard.md +6 -5
  34. package/extensions/spec-kit-docguard/skills/docguard-guard/SKILL.md +3 -2
  35. package/package.json +1 -1
  36. package/templates/commands/docguard.guard.md +3 -3
@@ -5,6 +5,7 @@
5
5
 
6
6
  import { existsSync, readFileSync, readdirSync, statSync } from 'node:fs';
7
7
  import { resolve } from 'node:path';
8
+ import { resolveSourceRoots } from '../shared-source.mjs';
8
9
 
9
10
  export function validateTestSpec(projectDir, config) {
10
11
  const results = { name: 'test-spec', errors: [], warnings: [], passed: 0, total: 0 };
@@ -43,6 +44,9 @@ export function validateTestSpec(projectDir, config) {
43
44
  // Skip template/example rows and italic placeholder rows
44
45
  if (sourceFile.startsWith('<!--') || sourceFile === 'Source File' || sourceFile.startsWith('*')) continue;
45
46
 
47
+ // Author-declared gaps (❌/⚠️) are surfaced as warnings. A ✅ glyph is the
48
+ // author's CLAIM, not proof — it is NOT counted as a pass. The real pass
49
+ // comes from the file-existence checks below (code truth, not the glyph).
46
50
  if (status && status.includes('❌')) {
47
51
  results.total++;
48
52
  results.warnings.push(
@@ -53,9 +57,6 @@ export function validateTestSpec(projectDir, config) {
53
57
  results.warnings.push(
54
58
  `TEST-SPEC declares ${sourceFile} as ⚠️ — partial coverage`
55
59
  );
56
- } else if (status && status.includes('✅')) {
57
- results.total++;
58
- results.passed++;
59
60
  }
60
61
 
61
62
  // ── File existence checks ───────────────────────────────────────
@@ -122,34 +123,41 @@ export function validateTestSpec(projectDir, config) {
122
123
  results.warnings.push(
123
124
  `E2E Journey #${num} (${journey}) — missing test: ${testFile}`
124
125
  );
125
- } else if (status && status.includes('✅')) {
126
+ continue;
127
+ }
128
+
129
+ // For a ✅ journey, verify the referenced test file actually exists
130
+ // rather than trusting the glyph.
131
+ const cleanTest = testFile ? testFile.replace(/`/g, '').trim() : '';
132
+ if (cleanTest && cleanTest !== '—' && !cleanTest.includes('N/A')) {
126
133
  results.total++;
127
- results.passed++;
134
+ if (existsSync(resolve(projectDir, cleanTest))) {
135
+ results.passed++;
136
+ } else {
137
+ results.warnings.push(
138
+ `E2E Journey #${num} (${journey}) marked ✅ but test file not found: ${cleanTest}`
139
+ );
140
+ }
128
141
  }
129
142
  }
130
143
  }
131
144
  }
132
145
 
133
- // If no test spec entries parsed, check if tests exist anywhere
146
+ // If TEST-SPEC.md declared no service-to-test mappings, there is nothing to
147
+ // verify against. Do NOT manufacture a 1/1 pass just because tests exist
148
+ // somewhere — that rendered a confident green ✅ for a doc that mapped nothing.
134
149
  if (results.total === 0) {
135
- results.total = 1;
136
-
137
150
  // 1. Check top-level test dirs
138
151
  const commonTestDirs = ['tests', 'test', '__tests__', 'spec'];
139
152
  const hasTestDir = commonTestDirs.some(d =>
140
153
  existsSync(resolve(projectDir, d))
141
154
  );
142
155
 
143
- // 2. Check co-located tests (src/**/__tests__/, src/**/*.test.*)
156
+ // 2. Check co-located tests (honors config.sourceRoot + workspaces)
144
157
  let hasColocated = false;
145
158
  if (!hasTestDir) {
146
- const sourceRoots = ['src', 'app', 'lib', 'packages'];
147
- for (const root of sourceRoots) {
148
- const rootPath = resolve(projectDir, root);
149
- if (existsSync(rootPath) && hasTestFilesRecursive(rootPath)) {
150
- hasColocated = true;
151
- break;
152
- }
159
+ for (const rootPath of resolveSourceRoots(projectDir, config)) {
160
+ if (hasTestFilesRecursive(rootPath)) { hasColocated = true; break; }
153
161
  }
154
162
  }
155
163
 
@@ -161,7 +169,8 @@ export function validateTestSpec(projectDir, config) {
161
169
  }
162
170
 
163
171
  if (hasTestDir || hasColocated || hasConfigTests) {
164
- results.passed = 1;
172
+ // Tests exist but the spec maps none of them → not applicable, not a pass.
173
+ results.note = 'TEST-SPEC.md declares no service-to-test mappings';
165
174
  } else {
166
175
  results.warnings.push(
167
176
  'No test directory or co-located test files found. ' +
@@ -67,7 +67,7 @@ export function validateTodoTracking(projectDir, config) {
67
67
  results.passed += skipResults.passed;
68
68
  results.total += skipResults.total;
69
69
 
70
- // ── Part 2: Untracked TODOs/FIXMEs ──
70
+ // ── Part 2: Untracked Annotations ──
71
71
  const todoResults = checkUntrackedTodos(projectDir, config);
72
72
  results.errors.push(...todoResults.errors);
73
73
  results.warnings.push(...todoResults.warnings);
@@ -105,6 +105,10 @@ function checkSkippedTests(projectDir, config) {
105
105
  let content;
106
106
  try { content = readFileSync(fullPath, 'utf-8'); } catch { continue; }
107
107
 
108
+ // Fast early-return: skip expensive string split if no skip patterns exist
109
+ const hasSkip = SKIP_PATTERNS.some(p => p.test(content));
110
+ if (!hasSkip) continue;
111
+
108
112
  const lines = content.split('\n');
109
113
 
110
114
  for (let i = 0; i < lines.length; i++) {
@@ -151,7 +155,7 @@ function checkSkippedTests(projectDir, config) {
151
155
  return { errors, warnings, passed, total };
152
156
  }
153
157
 
154
- // ──── Untracked TODOs ──────────────────────────────────────────────────────
158
+ // ──── Untracked Annotations ────────────────────────────────────────────────
155
159
 
156
160
  /**
157
161
  * Scan source files for TODO/FIXME annotations and check if they appear
@@ -183,15 +187,19 @@ function checkUntrackedTodos(projectDir, config) {
183
187
  for (const todo of todos) {
184
188
  // Check if the TODO is tracked in documentation
185
189
  // Improved matching: check full text AND file location context
190
+ // ⚡ Bolt: Precompute string lowercasing and trimming once per TODO
191
+ // instead of inside the trackingContent.some loop
192
+ const todoTextLower = todo.text.toLowerCase().trim();
193
+ const searchText = todoTextLower.length > 20
194
+ ? todoTextLower.substring(0, 40)
195
+ : todoTextLower;
196
+
186
197
  const isTracked = trackingContent.some(doc => {
187
198
  const content = doc.content;
188
- const contentLower = content.toLowerCase();
189
- const todoTextLower = todo.text.toLowerCase().trim();
199
+ // Bolt: use the precomputed lowercased content
200
+ const contentLower = doc.contentLower;
190
201
 
191
202
  // Match 1: Full TODO text appears in the doc (at least 20 chars or full text)
192
- const searchText = todoTextLower.length > 20
193
- ? todoTextLower.substring(0, 40)
194
- : todoTextLower;
195
203
  const hasText = contentLower.includes(searchText);
196
204
 
197
205
  // Match 2: File location appears nearby in the doc
@@ -240,7 +248,9 @@ function loadTrackingDocs(projectDir, config) {
240
248
  const fullPath = resolve(projectDir, file);
241
249
  if (existsSync(fullPath)) {
242
250
  try {
243
- docs.push({ file, content: readFileSync(fullPath, 'utf-8') });
251
+ const content = readFileSync(fullPath, 'utf-8');
252
+ // ⚡ Bolt: Precompute lowercased content during file load to avoid N*M overhead
253
+ docs.push({ file, content, contentLower: content.toLowerCase() });
244
254
  } catch { /* ignore */ }
245
255
  }
246
256
  }
@@ -306,6 +316,9 @@ function findTodos(rootDir, dir, todos, config) {
306
316
  let content;
307
317
  try { content = readFileSync(full, 'utf-8'); } catch { continue; }
308
318
 
319
+ // Fast early-return: skip expensive string split if no TODO patterns exist
320
+ if (!TODO_PATTERN.test(content)) continue;
321
+
309
322
  const lines = content.split('\n');
310
323
 
311
324
  for (let i = 0; i < lines.length; i++) {
@@ -130,13 +130,16 @@ export function validateTraceability(projectDir, config) {
130
130
  }
131
131
 
132
132
  // Count matching source files
133
- let totalSources = 0;
133
+ // Bolt: Fast early return using .some() instead of .filter()
134
+ let hasSource = false;
134
135
  for (const pattern of traceInfo.sourcePatterns) {
135
- const matches = projectFiles.filter(f => pattern.glob.test(f));
136
- totalSources += matches.length;
136
+ if (projectFiles.some(f => pattern.glob.test(f))) {
137
+ hasSource = true;
138
+ break;
139
+ }
137
140
  }
138
141
 
139
- if (totalSources > 0) {
142
+ if (hasSource) {
140
143
  passed++;
141
144
  } else {
142
145
  warnings.push(`${docName} — exists but no matching source code found (unlinked doc)`);
@@ -186,6 +189,46 @@ function validateRequirementTraceability(projectDir, config, projectFiles) {
186
189
  : DEFAULT_REQ_PATTERNS;
187
190
 
188
191
  // ── Step 1: Collect requirement IDs from documentation ──
192
+ const reqIds = collectRequirementIds(projectDir, config, patterns);
193
+
194
+ // If no requirement IDs found, silently pass — this project doesn't use them
195
+ if (reqIds.size === 0) {
196
+ return { errors, warnings, passed, total };
197
+ }
198
+
199
+ // ── Step 2: Scan test files for requirement ID references ──
200
+ const testRefs = scanTestFilesForReferences(projectDir, projectFiles, patterns);
201
+
202
+ // ── Step 3: Report traceability results ──
203
+
204
+ // Check each documented requirement has at least one test reference
205
+ for (const [reqId, location] of reqIds) {
206
+ total++;
207
+ if (testRefs.has(reqId)) {
208
+ passed++;
209
+ } else {
210
+ warnings.push(
211
+ `Requirement ${reqId} (${location.file}:${location.line}) has no test coverage. ` +
212
+ `Add @req ${reqId} comment to the test that verifies this requirement`
213
+ );
214
+ }
215
+ }
216
+
217
+ // Check for orphaned test refs (tests referencing non-existent requirements)
218
+ for (const [reqId, refs] of testRefs) {
219
+ if (!reqIds.has(reqId)) {
220
+ total++;
221
+ warnings.push(
222
+ `Test references ${reqId} (${refs[0].file}:${refs[0].line}) but no requirement ` +
223
+ `with this ID exists in documentation. Remove the reference or add the requirement to docs`
224
+ );
225
+ }
226
+ }
227
+
228
+ return { errors, warnings, passed, total };
229
+ }
230
+
231
+ function collectRequirementIds(projectDir, config, patterns) {
189
232
  const reqIds = new Map(); // reqId → { file, line }
190
233
  const docSearchPaths = getRequirementDocPaths(projectDir, config);
191
234
 
@@ -193,6 +236,11 @@ function validateRequirementTraceability(projectDir, config, projectFiles) {
193
236
  if (!existsSync(docPath)) continue;
194
237
 
195
238
  const content = readFileSync(docPath, 'utf-8');
239
+
240
+ // Fast early-return: skip expensive string split if no requirement patterns exist
241
+ const hasMatch = patterns.some(p => { p.lastIndex = 0; return p.test(content); });
242
+ if (!hasMatch) continue;
243
+
196
244
  const lines = content.split('\n');
197
245
  const docName = relative(projectDir, docPath);
198
246
 
@@ -211,12 +259,10 @@ function validateRequirementTraceability(projectDir, config, projectFiles) {
211
259
  }
212
260
  }
213
261
 
214
- // If no requirement IDs found, silently pass — this project doesn't use them
215
- if (reqIds.size === 0) {
216
- return { errors, warnings, passed, total };
217
- }
262
+ return reqIds;
263
+ }
218
264
 
219
- // ── Step 2: Scan test files for requirement ID references ──
265
+ function scanTestFilesForReferences(projectDir, projectFiles, patterns) {
220
266
  const testFiles = projectFiles.filter(f =>
221
267
  /\.(test|spec)\.(mjs|cjs|[jt]sx?)$/.test(f) ||
222
268
  /__tests__\//.test(f) ||
@@ -231,6 +277,11 @@ function validateRequirementTraceability(projectDir, config, projectFiles) {
231
277
 
232
278
  let content;
233
279
  try { content = readFileSync(fullPath, 'utf-8'); } catch { continue; }
280
+
281
+ // Fast early-return: skip expensive string split if no requirement patterns exist
282
+ const hasMatch = patterns.some(p => { p.lastIndex = 0; return p.test(content); });
283
+ if (!hasMatch) continue;
284
+
234
285
  const lines = content.split('\n');
235
286
 
236
287
  for (let i = 0; i < lines.length; i++) {
@@ -246,33 +297,7 @@ function validateRequirementTraceability(projectDir, config, projectFiles) {
246
297
  }
247
298
  }
248
299
 
249
- // ── Step 3: Report traceability results ──
250
-
251
- // Check each documented requirement has at least one test reference
252
- for (const [reqId, location] of reqIds) {
253
- total++;
254
- if (testRefs.has(reqId)) {
255
- passed++;
256
- } else {
257
- warnings.push(
258
- `Requirement ${reqId} (${location.file}:${location.line}) has no test coverage. ` +
259
- `Add @req ${reqId} comment to the test that verifies this requirement`
260
- );
261
- }
262
- }
263
-
264
- // Check for orphaned test refs (tests referencing non-existent requirements)
265
- for (const [reqId, refs] of testRefs) {
266
- if (!reqIds.has(reqId)) {
267
- total++;
268
- warnings.push(
269
- `Test references ${reqId} (${refs[0].file}:${refs[0].line}) but no requirement ` +
270
- `with this ID exists in documentation. Remove the reference or add the requirement to docs`
271
- );
272
- }
273
- }
274
-
275
- return { errors, warnings, passed, total };
300
+ return testRefs;
276
301
  }
277
302
 
278
303
  /**
@@ -1,5 +1,5 @@
1
1
  ---
2
- description: Run DocGuard guard validation — check project documentation against CDD standards with 19 validators
2
+ description: Run DocGuard guard validation — check project documentation against CDD standards with 20 validators
3
3
  handoffs:
4
4
  - label: Fix All Issues
5
5
  agent: docguard.fix
@@ -23,14 +23,14 @@ Run the DocGuard CLI to validate all documentation against Canonical-Driven Deve
23
23
  npx docguard-cli guard
24
24
  ```
25
25
 
26
- 2. **Parse the output**. Each of the 19 validators reports ✅ (pass), ⚠️ (warning), or ❌ (fail):
26
+ 2. **Parse the output**. Each of the 20 validators reports ✅ (pass), ⚠️ (warning), ❌ (fail), or ➖ (N/A — nothing to validate). **A ➖ N/A is NOT a pass**: it means the validator found nothing to check (e.g. no API-REFERENCE.md, no DB schema, no layer boundaries declared). Don't read N/A as "healthy" — read it as "not assessed".
27
27
 
28
28
  | Validator | What It Checks |
29
29
  |-----------|---------------|
30
30
  | Structure | Required CDD files exist |
31
31
  | Doc Sections | Canonical docs have required sections |
32
32
  | Docs-Sync | External doc references are valid |
33
- | Drift | Code deviations logged in DRIFT-LOG.md |
33
+ | Drift-Comments | `// DRIFT:` code comments logged in DRIFT-LOG.md |
34
34
  | Changelog | CHANGELOG.md is maintained |
35
35
  | Test-Spec | Tests match TEST-SPEC.md rules |
36
36
  | Environment | Environment documentation |
@@ -39,6 +39,7 @@ npx docguard-cli guard
39
39
  | Freshness | Docs updated within commit window |
40
40
  | Traceability | Requirements trace to tests |
41
41
  | Docs-Diff | Doc changes match code changes |
42
+ | API-Surface | API-REFERENCE.md endpoints match the real API surface (OpenAPI spec / routes) |
42
43
  | Metadata-Sync | Metadata headers are consistent |
43
44
  | Docs-Coverage | All config files documented |
44
45
  | Doc-Quality | Readability, IEEE 830 compliance |
@@ -49,7 +50,7 @@ npx docguard-cli guard
49
50
 
50
51
  3. **Triage findings by severity**:
51
52
  - **CRITICAL**: Structure, Security, Test-Spec failures
52
- - **HIGH**: Doc Sections, Drift, Changelog, Traceability failures
53
+ - **HIGH**: Doc Sections, Drift-Comments, Changelog, Traceability, API-Surface (documented-but-absent endpoint) failures
53
54
  - **MEDIUM**: Freshness, Docs-Coverage, Doc-Quality, Metrics-Consistency warnings
54
55
  - **LOW**: TODO-Tracking, Schema-Sync, Spec-Kit, Metadata-Sync warnings
55
56
 
@@ -68,7 +68,7 @@ diagnose → AI reads prompts → AI fixes docs → guard verifies
68
68
  ## Verify
69
69
 
70
70
  ```bash
71
- npx docguard-cli guard # Pass/fail check (19 validators)
71
+ npx docguard-cli guard # Pass/fail check (20 validators)
72
72
  npx docguard-cli score # 0-100 maturity score
73
73
  ```
74
74
 
@@ -4,7 +4,7 @@ Enterprise-grade Canonical-Driven Development (CDD) enforcement for [Spec Kit](h
4
4
 
5
5
  ## Features
6
6
 
7
- - **19 Validators** — Structure, Security, Doc Quality, Test-Spec, Drift, Freshness, and 13 more
7
+ - **20 Validators** — Structure, Security, Doc Quality, Test-Spec, Drift-Comments, API-Surface, Freshness, and 13 more
8
8
  - **4 AI Skills** — Enterprise-grade AI behavior protocols (not just step-lists)
9
9
  - **3 Bash Scripts** — JSON-output orchestration for AI consumption
10
10
  - **Workflow Chaining** — YAML handoffs enable guard → fix → review → score flows
@@ -14,7 +14,7 @@ handoffs:
14
14
 
15
15
  # DocGuard Guard
16
16
 
17
- Validate your project against its canonical documentation. Runs 160+ automated checks across 19 validators.
17
+ Validate your project against its canonical documentation. Runs 160+ automated checks across 20 validators.
18
18
 
19
19
  ## User Input
20
20
 
@@ -31,11 +31,11 @@ You **MUST** consider the user input before proceeding (if not empty).
31
31
  npx --yes docguard-cli@latest guard $ARGUMENTS
32
32
  ```
33
33
 
34
- 2. Parse each validator's result and build a severity-ranked findings table.
34
+ 2. Parse each validator's result and build a severity-ranked findings table. Status glyphs: ✅ pass, ⚠️ warning, ❌ fail, ➖ N/A (nothing to validate — NOT a pass; the dimension was not assessed).
35
35
 
36
36
  3. **Triage by severity**:
37
37
  - **CRITICAL**: Structure, Security, Test-Spec failures → fix immediately
38
- - **HIGH**: Doc Sections, Drift, Changelog, Traceability → fix before commit
38
+ - **HIGH**: Doc Sections, Drift-Comments, Changelog, Traceability, API-Surface → fix before commit
39
39
  - **MEDIUM**: Freshness, Docs-Coverage, Doc-Quality, Metrics → fix this sprint
40
40
  - **LOW**: TODO-Tracking, Schema-Sync, Spec-Kit, Metadata → fix when convenient
41
41
 
@@ -43,14 +43,14 @@ npx --yes docguard-cli@latest guard $ARGUMENTS
43
43
 
44
44
  5. Re-run guard after fixes. Iterate until all checks pass (max 3 iterations).
45
45
 
46
- ## Validators (19 total)
46
+ ## Validators (20 total)
47
47
 
48
48
  | Validator | What It Checks |
49
49
  |-----------|---------------|
50
50
  | Structure | Required CDD files exist |
51
51
  | Doc Sections | Canonical docs have required sections |
52
52
  | Docs-Sync | External doc references are valid |
53
- | Drift | `// DRIFT:` comments have DRIFT-LOG entries |
53
+ | Drift-Comments | `// DRIFT:` comments have DRIFT-LOG entries |
54
54
  | Changelog | CHANGELOG.md is maintained |
55
55
  | Test-Spec | TEST-SPEC.md matches actual test files |
56
56
  | Environment | Environment docs and .env.example exist |
@@ -59,6 +59,7 @@ npx --yes docguard-cli@latest guard $ARGUMENTS
59
59
  | Freshness | Docs updated after recent code changes |
60
60
  | Traceability | Canonical docs linked to source code |
61
61
  | Docs-Diff | Entity/route/field drift between code and docs |
62
+ | API-Surface | API-REFERENCE.md endpoints match the real API surface (OpenAPI spec / routes) |
62
63
  | Metadata-Sync | Metadata headers are consistent |
63
64
  | Docs-Coverage | All config files documented |
64
65
  | Doc-Quality | Readability, IEEE 830 compliance |
@@ -78,7 +78,8 @@ Classify every non-passing check using this priority matrix:
78
78
 
79
79
  **HIGH (fix before commit)**:
80
80
  - Doc Sections failures (missing required sections)
81
- - Drift detection (undocumented code deviations)
81
+ - Drift-Comments (a `// DRIFT:` comment without a DRIFT-LOG.md entry)
82
+ - API-Surface (API-REFERENCE.md documents an endpoint that no longer exists in code)
82
83
  - Changelog gaps
83
84
  - Traceability breaks
84
85
 
@@ -138,7 +139,7 @@ For each finding, provide a **specific, actionable fix** — not "fix the issue"
138
139
 
139
140
  Based on the triage results:
140
141
 
141
- - **If all PASS**: "All 19 validators passed. Project is CDD-compliant. Ready to commit."
142
+ - **If all PASS**: "All 20 validators passed. Project is CDD-compliant. Ready to commit."
142
143
  - **If only MEDIUM/LOW warnings**: "Non-blocking warnings found. Safe to commit, but consider running `/docguard.fix` for automated remediation."
143
144
  - **If HIGH or CRITICAL failures**: "Blocking issues found. Fix these before committing. Suggest running `/docguard.fix --doc [most impactful doc]` next."
144
145
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "docguard-cli",
3
- "version": "0.9.11",
3
+ "version": "0.10.0",
4
4
  "description": "The enforcement tool for Canonical-Driven Development (CDD). Audit, generate, and guard your project documentation.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -1,5 +1,5 @@
1
1
  ---
2
- description: Run DocGuard guard validation — check all 19 validators and fix any issues
2
+ description: Run DocGuard guard validation — check all 20 validators and fix any issues
3
3
  handoffs:
4
4
  - label: Fix Issues
5
5
  agent: docguard.fix
@@ -19,12 +19,12 @@ You are an AI agent enforcing Canonical-Driven Development (CDD) compliance usin
19
19
  npx docguard-cli guard
20
20
  ```
21
21
 
22
- Read the output. It shows pass (✅), warn (⚠️), or fail (❌) for each of the 19 validators:
22
+ Read the output. It shows pass (✅), warn (⚠️), or fail (❌) for each of the 20 validators:
23
23
 
24
24
  | Priority | Validators |
25
25
  |----------|-----------|
26
26
  | CRITICAL | Structure, Security, Test-Spec |
27
- | HIGH | Doc Sections, Drift, Changelog, Traceability |
27
+ | HIGH | Doc Sections, Drift-Comments, Changelog, Traceability, API-Surface |
28
28
  | MEDIUM | Freshness, Docs-Coverage, Doc-Quality, Metrics-Consistency |
29
29
  | LOW | TODO-Tracking, Schema-Sync, Spec-Kit, Metadata-Sync |
30
30