docguard-cli 0.38.0 → 0.40.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 (63) hide show
  1. package/README.md +45 -22
  2. package/cli/commands/agent.mjs +47 -1
  3. package/cli/commands/explain.mjs +16 -0
  4. package/cli/commands/feedback.mjs +147 -6
  5. package/cli/commands/fix.mjs +13 -11
  6. package/cli/commands/generate.mjs +52 -18
  7. package/cli/commands/guard.mjs +13 -2
  8. package/cli/commands/mcp.mjs +22 -2
  9. package/cli/commands/score.mjs +13 -1
  10. package/cli/commands/specs.mjs +21 -2
  11. package/cli/commands/sync.mjs +20 -7
  12. package/cli/commands/verify.mjs +65 -2
  13. package/cli/config.mjs +3 -0
  14. package/cli/docguard.mjs +48 -16
  15. package/cli/evidence/adapters.mjs +200 -0
  16. package/cli/evidence/evaluate.mjs +185 -0
  17. package/cli/evidence/manifest.mjs +194 -0
  18. package/cli/evidence/markdown.mjs +107 -0
  19. package/cli/feedback-fixture.mjs +188 -0
  20. package/cli/findings.mjs +31 -0
  21. package/cli/repository-root.mjs +159 -0
  22. package/cli/scanners/py-ast.mjs +39 -2
  23. package/cli/scanners/task-context.mjs +312 -0
  24. package/cli/shared-doc-roles.mjs +44 -1
  25. package/cli/shared-source.mjs +101 -28
  26. package/cli/validators/architecture.mjs +186 -13
  27. package/cli/validators/environment.mjs +14 -1
  28. package/cli/validators/evidence.mjs +52 -0
  29. package/cli/validators/security.mjs +5 -4
  30. package/cli/validators/todo-tracking.mjs +45 -2
  31. package/cli/writers/doc-generators.mjs +31 -17
  32. package/cli/writers/mechanical.mjs +44 -14
  33. package/cli/writers/sections.mjs +31 -3
  34. package/docs/ai-integration.md +31 -6
  35. package/docs/commands.md +43 -5
  36. package/docs/configuration.md +11 -3
  37. package/docs/quickstart.md +1 -1
  38. package/extensions/spec-kit-docguard/commands/fix.md +4 -2
  39. package/extensions/spec-kit-docguard/commands/generate.md +6 -1
  40. package/extensions/spec-kit-docguard/commands/guard.md +3 -2
  41. package/extensions/spec-kit-docguard/commands/sync.md +1 -1
  42. package/extensions/spec-kit-docguard/extension.yml +1 -1
  43. package/extensions/spec-kit-docguard/skills/docguard-fix/SKILL.md +14 -3
  44. package/extensions/spec-kit-docguard/skills/docguard-guard/SKILL.md +16 -5
  45. package/extensions/spec-kit-docguard/skills/docguard-review/SKILL.md +8 -3
  46. package/extensions/spec-kit-docguard/skills/docguard-score/SKILL.md +3 -2
  47. package/extensions/spec-kit-docguard/skills/docguard-sync/SKILL.md +6 -3
  48. package/extensions/spec-kit-docguard/templates/github-workflows/docguard-autofix.yml +2 -2
  49. package/extensions/spec-kit-docguard/templates/github-workflows/docguard-guard.yml +4 -4
  50. package/package.json +3 -1
  51. package/schemas/docguard-agent-context-benchmark.schema.json +92 -0
  52. package/schemas/docguard-agent-context-result.schema.json +95 -0
  53. package/schemas/docguard-benchmark.schema.json +84 -0
  54. package/schemas/docguard-config.schema.json +1 -0
  55. package/schemas/docguard-evidence.schema.json +169 -0
  56. package/schemas/docguard-feedback-fixture.schema.json +54 -0
  57. package/schemas/docguard-task-context.schema.json +144 -0
  58. package/templates/AGENTS.md.template +9 -4
  59. package/templates/ci/github-actions.yml +4 -4
  60. package/templates/commands/docguard.guard.md +5 -1
  61. package/templates/commands/docguard.review.md +6 -1
  62. package/templates/evidence-manifest.json +21 -0
  63. package/templates/feedback-fixture.json +18 -0
@@ -0,0 +1,169 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://raccioly.github.io/docguard/schemas/docguard-evidence.schema.json",
4
+ "title": "DocGuard evidence-scoped verification manifest",
5
+ "type": "object",
6
+ "additionalProperties": false,
7
+ "required": ["$schema", "schemaVersion", "declarations"],
8
+ "properties": {
9
+ "$schema": { "const": "https://raccioly.github.io/docguard/schemas/docguard-evidence.schema.json" },
10
+ "schemaVersion": { "const": 1 },
11
+ "declarations": {
12
+ "type": "array",
13
+ "minItems": 1,
14
+ "maxItems": 128,
15
+ "items": { "$ref": "#/$defs/declaration" }
16
+ }
17
+ },
18
+ "$defs": {
19
+ "safePath": {
20
+ "type": "string",
21
+ "minLength": 1,
22
+ "maxLength": 512,
23
+ "pattern": "^(?!/)(?!.*(?:^|/)\\.\\.(?:/|$))(?!.*(?:^|/)\\.local(?:/|$))(?!.*(?:^|/)\\.env(?:\\.|/|$))[^\\\\\\u0000:]+$"
24
+ },
25
+ "declaration": {
26
+ "type": "object",
27
+ "additionalProperties": false,
28
+ "required": ["id", "applicability", "target", "source", "predicate"],
29
+ "properties": {
30
+ "id": { "type": "string", "pattern": "^[a-z0-9][a-z0-9._-]{2,127}$" },
31
+ "applicability": {
32
+ "type": "object",
33
+ "additionalProperties": false,
34
+ "required": ["mode"],
35
+ "properties": { "mode": { "const": "always" } }
36
+ },
37
+ "target": {
38
+ "type": "object",
39
+ "additionalProperties": false,
40
+ "required": ["document", "heading", "statement"],
41
+ "properties": {
42
+ "document": { "$ref": "#/$defs/safePath" },
43
+ "heading": { "type": "string", "minLength": 1, "maxLength": 200 },
44
+ "statement": { "type": "string", "minLength": 1, "maxLength": 1000 }
45
+ }
46
+ },
47
+ "source": {
48
+ "oneOf": [
49
+ { "$ref": "#/$defs/jsonSource" },
50
+ { "$ref": "#/$defs/collectionSource" },
51
+ { "$ref": "#/$defs/oasdiffSource" },
52
+ { "$ref": "#/$defs/bufSource" }
53
+ ]
54
+ },
55
+ "predicate": {
56
+ "oneOf": [
57
+ { "$ref": "#/$defs/equalsPredicate" },
58
+ { "$ref": "#/$defs/setPredicate" },
59
+ { "$ref": "#/$defs/countPredicate" },
60
+ { "$ref": "#/$defs/noFindingsPredicate" }
61
+ ]
62
+ }
63
+ }
64
+ },
65
+ "jsonSource": {
66
+ "type": "object",
67
+ "additionalProperties": false,
68
+ "required": ["adapter", "path", "pointer"],
69
+ "properties": {
70
+ "adapter": { "const": "json-pointer" },
71
+ "path": { "$ref": "#/$defs/safePath" },
72
+ "pointer": { "type": "string", "maxLength": 512, "pattern": "^(?:$|/)" }
73
+ }
74
+ },
75
+ "collectionSource": {
76
+ "type": "object",
77
+ "additionalProperties": false,
78
+ "required": ["adapter", "glob", "allowEmpty"],
79
+ "properties": {
80
+ "adapter": { "const": "collection-count" },
81
+ "glob": { "$ref": "#/$defs/safePath" },
82
+ "allowEmpty": { "type": "boolean" }
83
+ }
84
+ },
85
+ "input": {
86
+ "type": "object",
87
+ "additionalProperties": false,
88
+ "required": ["path", "sha256"],
89
+ "properties": {
90
+ "path": { "$ref": "#/$defs/safePath" },
91
+ "sha256": { "type": "string", "pattern": "^sha256:[0-9a-f]{64}$" }
92
+ }
93
+ },
94
+ "reportBase": {
95
+ "type": "object",
96
+ "required": ["adapter", "adapterVersion", "path", "producerVersion", "command", "inputs"],
97
+ "properties": {
98
+ "adapterVersion": { "type": "integer", "minimum": 1, "maximum": 100 },
99
+ "path": { "$ref": "#/$defs/safePath" },
100
+ "producerVersion": { "type": "string", "minLength": 1, "maxLength": 80 },
101
+ "inputs": {
102
+ "type": "array",
103
+ "minItems": 1,
104
+ "maxItems": 32,
105
+ "items": { "$ref": "#/$defs/input" }
106
+ }
107
+ }
108
+ },
109
+ "oasdiffSource": {
110
+ "allOf": [
111
+ { "$ref": "#/$defs/reportBase" },
112
+ {
113
+ "type": "object",
114
+ "additionalProperties": false,
115
+ "properties": {
116
+ "adapter": { "const": "oasdiff" },
117
+ "adapterVersion": {}, "path": {}, "producerVersion": {}, "inputs": {},
118
+ "command": { "type": "string", "minLength": 1, "maxLength": 40 }
119
+ }
120
+ }
121
+ ]
122
+ },
123
+ "bufSource": {
124
+ "allOf": [
125
+ { "$ref": "#/$defs/reportBase" },
126
+ {
127
+ "type": "object",
128
+ "additionalProperties": false,
129
+ "properties": {
130
+ "adapter": { "const": "buf" },
131
+ "adapterVersion": {}, "path": {}, "producerVersion": {}, "inputs": {},
132
+ "command": { "type": "string", "minLength": 1, "maxLength": 40 }
133
+ }
134
+ }
135
+ ]
136
+ },
137
+ "equalsPredicate": {
138
+ "type": "object",
139
+ "additionalProperties": false,
140
+ "required": ["kind", "valueType"],
141
+ "properties": {
142
+ "kind": { "const": "equals" },
143
+ "valueType": { "enum": ["string", "number", "boolean", "null"] }
144
+ }
145
+ },
146
+ "setPredicate": {
147
+ "type": "object",
148
+ "additionalProperties": false,
149
+ "required": ["kind", "itemType", "separator"],
150
+ "properties": {
151
+ "kind": { "const": "set-equals" },
152
+ "itemType": { "const": "string" },
153
+ "separator": { "type": "string", "minLength": 1, "maxLength": 16 }
154
+ }
155
+ },
156
+ "countPredicate": {
157
+ "type": "object",
158
+ "additionalProperties": false,
159
+ "required": ["kind"],
160
+ "properties": { "kind": { "const": "count-equals" } }
161
+ },
162
+ "noFindingsPredicate": {
163
+ "type": "object",
164
+ "additionalProperties": false,
165
+ "required": ["kind"],
166
+ "properties": { "kind": { "const": "no-findings" } }
167
+ }
168
+ }
169
+ }
@@ -0,0 +1,54 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://raccioly.github.io/docguard/schemas/docguard-feedback-fixture.schema.json",
4
+ "title": "DocGuard synthetic feedback fixture",
5
+ "type": "object",
6
+ "additionalProperties": false,
7
+ "required": ["$schema", "schemaVersion", "classification", "detector", "parserTier", "config", "expectedIdentity", "interestingness", "fixture", "oppositeControl", "provenance"],
8
+ "properties": {
9
+ "$schema": { "const": "https://raccioly.github.io/docguard/schemas/docguard-feedback-fixture.schema.json" },
10
+ "schemaVersion": { "const": 1 },
11
+ "classification": { "enum": ["false_positive", "false_negative", "unsupported_syntax", "ambiguous", "policy_disagreement"] },
12
+ "detector": {
13
+ "type": "object", "additionalProperties": false, "required": ["code", "validator"],
14
+ "properties": { "code": { "type": "string", "pattern": "^[A-Z]{3}[0-9]{3}$" }, "validator": { "type": "string", "pattern": "^[A-Za-z][A-Za-z0-9]{1,63}$" } }
15
+ },
16
+ "parserTier": { "enum": ["js-ast", "py-ast", "regex-fallback", "fallback-language", "mixed", "not-applicable"] },
17
+ "config": { "type": "object" },
18
+ "expectedIdentity": { "type": "string", "pattern": "^[A-Z]{3}[0-9]{3}@.+$" },
19
+ "interestingness": {
20
+ "type": "object", "additionalProperties": false, "required": ["predicate"],
21
+ "properties": { "predicate": { "enum": ["finding_present", "finding_absent", "validator_unsupported"] } }
22
+ },
23
+ "fixture": { "$ref": "#/$defs/fileSet" },
24
+ "oppositeControl": { "$ref": "#/$defs/fileSet" },
25
+ "provenance": {
26
+ "type": "object", "additionalProperties": false, "required": ["synthetic", "redactionAttested"],
27
+ "properties": { "synthetic": { "const": true }, "redactionAttested": { "const": true } }
28
+ },
29
+ "contribution": {
30
+ "type": "object", "additionalProperties": false, "required": ["testOnly", "scopeDocumented", "benchmarkDelta"],
31
+ "properties": {
32
+ "testOnly": { "const": true }, "scopeDocumented": { "const": true },
33
+ "benchmarkDelta": {
34
+ "type": "object", "additionalProperties": false,
35
+ "required": ["falsePositives", "falseNegatives", "unsupportedCases", "abstainedSupportedCases"],
36
+ "properties": {
37
+ "falsePositives": { "type": "integer", "minimum": 0 }, "falseNegatives": { "type": "integer", "minimum": 0 },
38
+ "unsupportedCases": { "type": "integer", "minimum": 0 }, "abstainedSupportedCases": { "type": "integer", "minimum": 0 }
39
+ }
40
+ }
41
+ }
42
+ }
43
+ },
44
+ "$defs": {
45
+ "fileSet": {
46
+ "type": "object", "additionalProperties": false, "required": ["files"],
47
+ "properties": { "files": { "type": "array", "minItems": 1, "maxItems": 16, "items": { "$ref": "#/$defs/file" } } }
48
+ },
49
+ "file": {
50
+ "type": "object", "additionalProperties": false, "required": ["path", "content"],
51
+ "properties": { "path": { "type": "string", "minLength": 1 }, "content": { "type": "string", "maxLength": 131072 } }
52
+ }
53
+ }
54
+ }
@@ -0,0 +1,144 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://raccioly.github.io/docguard/schemas/docguard-task-context.schema.json",
4
+ "title": "DocGuard task-specific context packet",
5
+ "type": "object",
6
+ "additionalProperties": false,
7
+ "required": ["schemaVersion", "kind", "task", "provenance", "assurance", "selection", "excerpts", "pointers", "verification", "navigation", "limitations", "coreDigest"],
8
+ "properties": {
9
+ "schemaVersion": { "const": 1 },
10
+ "kind": { "const": "docguard.task-context" },
11
+ "task": {
12
+ "type": "object",
13
+ "additionalProperties": false,
14
+ "required": ["digest", "characters"],
15
+ "properties": {
16
+ "digest": { "$ref": "#/$defs/digest" },
17
+ "characters": { "type": "integer", "minimum": 1, "maximum": 2000 }
18
+ }
19
+ },
20
+ "provenance": {
21
+ "type": "object",
22
+ "additionalProperties": false,
23
+ "required": ["git", "registry"],
24
+ "properties": {
25
+ "git": {
26
+ "type": "object",
27
+ "additionalProperties": false,
28
+ "required": ["revision", "dirty", "status"],
29
+ "properties": {
30
+ "revision": { "type": ["string", "null"], "pattern": "^[a-f0-9]{40,64}$" },
31
+ "dirty": { "type": ["boolean", "null"] },
32
+ "status": { "enum": ["snapshot", "unknown"] }
33
+ }
34
+ },
35
+ "registry": { "enum": ["snapshot", "unavailable"] }
36
+ }
37
+ },
38
+ "assurance": {
39
+ "type": "object",
40
+ "additionalProperties": false,
41
+ "required": ["scope", "factualAccuracy", "verification"],
42
+ "properties": {
43
+ "scope": { "const": "retrieval-only" },
44
+ "factualAccuracy": { "type": "null" },
45
+ "verification": { "const": "unverified" }
46
+ }
47
+ },
48
+ "selection": {
49
+ "type": "object",
50
+ "additionalProperties": false,
51
+ "required": ["status", "threshold", "candidatesConsidered", "selectedExcerpts", "omittedCandidates", "excludedLifecycleDocuments", "limits", "truncated"],
52
+ "properties": {
53
+ "status": { "enum": ["targeted", "abstained"] },
54
+ "threshold": { "type": "integer", "minimum": 1 },
55
+ "candidatesConsidered": { "type": "integer", "minimum": 0 },
56
+ "selectedExcerpts": { "type": "integer", "minimum": 0, "maximum": 6 },
57
+ "omittedCandidates": { "type": "integer", "minimum": 0 },
58
+ "excludedLifecycleDocuments": { "type": "integer", "minimum": 0 },
59
+ "limits": { "$ref": "#/$defs/limits" },
60
+ "truncated": { "type": "boolean" }
61
+ }
62
+ },
63
+ "excerpts": { "type": "array", "maxItems": 6, "items": { "$ref": "#/$defs/excerpt" } },
64
+ "pointers": { "type": "array", "maxItems": 8, "items": { "$ref": "#/$defs/pointer" } },
65
+ "verification": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/verification" } },
66
+ "navigation": {
67
+ "type": "object",
68
+ "additionalProperties": false,
69
+ "required": ["canonicalDocs", "activeSpecs"],
70
+ "properties": {
71
+ "canonicalDocs": { "type": "array", "uniqueItems": true, "items": { "$ref": "#/$defs/path" } },
72
+ "activeSpecs": {
73
+ "type": "array",
74
+ "items": {
75
+ "type": "object",
76
+ "additionalProperties": false,
77
+ "required": ["specId", "path"],
78
+ "properties": { "specId": { "$ref": "#/$defs/specId" }, "path": { "$ref": "#/$defs/path" } }
79
+ }
80
+ }
81
+ }
82
+ },
83
+ "limitations": { "type": "array", "minItems": 2, "uniqueItems": true, "items": { "type": "string", "minLength": 1 } },
84
+ "coreDigest": { "$ref": "#/$defs/digest" }
85
+ },
86
+ "$defs": {
87
+ "digest": { "type": "string", "pattern": "^sha256:[a-f0-9]{64}$" },
88
+ "path": { "type": "string", "pattern": "^(?!/)(?!.*(?:^|/)\\.\\.(?:/|$))(?!.*\\\\).+" },
89
+ "specId": { "type": "string", "pattern": "^[a-z0-9][a-z0-9._/-]{2,127}$" },
90
+ "limits": {
91
+ "type": "object",
92
+ "additionalProperties": false,
93
+ "required": ["taskChars", "documents", "chunks", "selectedExcerpts", "linesPerExcerpt", "totalChars", "pointers"],
94
+ "properties": {
95
+ "taskChars": { "const": 2000 },
96
+ "documents": { "const": 32 },
97
+ "chunks": { "const": 256 },
98
+ "selectedExcerpts": { "const": 6 },
99
+ "linesPerExcerpt": { "const": 16 },
100
+ "totalChars": { "const": 6000 },
101
+ "pointers": { "const": 8 }
102
+ }
103
+ },
104
+ "excerpt": {
105
+ "type": "object",
106
+ "additionalProperties": false,
107
+ "required": ["path", "kind", "specId", "heading", "startLine", "endLine", "fileHash", "excerptHash", "score", "reasons", "content"],
108
+ "properties": {
109
+ "path": { "$ref": "#/$defs/path" },
110
+ "kind": { "enum": ["canonical", "active-spec", "project-rules"] },
111
+ "specId": { "anyOf": [{ "$ref": "#/$defs/specId" }, { "type": "null" }] },
112
+ "heading": { "type": "string", "minLength": 1 },
113
+ "startLine": { "type": "integer", "minimum": 1 },
114
+ "endLine": { "type": "integer", "minimum": 1 },
115
+ "fileHash": { "$ref": "#/$defs/digest" },
116
+ "excerptHash": { "$ref": "#/$defs/digest" },
117
+ "score": { "type": "integer", "minimum": 1 },
118
+ "reasons": { "type": "array", "minItems": 1, "uniqueItems": true, "items": { "type": "string", "minLength": 1 } },
119
+ "content": { "type": "string", "maxLength": 6000 }
120
+ }
121
+ },
122
+ "pointer": {
123
+ "type": "object",
124
+ "additionalProperties": false,
125
+ "required": ["path", "kind", "requirements", "reasons", "hash"],
126
+ "properties": {
127
+ "path": { "$ref": "#/$defs/path" },
128
+ "kind": { "enum": ["task-path", "cited-source", "implementation", "test"] },
129
+ "requirements": { "type": "array", "uniqueItems": true, "items": { "type": "string", "pattern": "^[a-z0-9][a-z0-9._/-]{2,127}#(?:FR|SC|NFR)-[0-9]{3}$" } },
130
+ "reasons": { "type": "array", "minItems": 1, "uniqueItems": true, "items": { "type": "string", "minLength": 1 } },
131
+ "hash": { "$ref": "#/$defs/digest" }
132
+ }
133
+ },
134
+ "verification": {
135
+ "type": "object",
136
+ "additionalProperties": false,
137
+ "required": ["command", "purpose"],
138
+ "properties": {
139
+ "command": { "type": "string", "minLength": 1 },
140
+ "purpose": { "type": "string", "minLength": 1 }
141
+ }
142
+ }
143
+ }
144
+ }
@@ -52,10 +52,15 @@ npx docguard fix --format prompt
52
52
  When working on this project, follow this workflow:
53
53
 
54
54
  1. **Before any work**: Run `npx docguard guard` to understand current compliance state
55
- 2. **After making changes**: Run `npx docguard fix --format prompt` to find remaining issues
56
- 3. **Fix what DocGuard reports**: Each issue includes an `ai_instruction` telling you exactly what to do
57
- 4. **Run guard again**: Verify all issues are resolved before committing
58
- 5. **Update CHANGELOG.md**: All changes need a changelog entry
55
+ 2. **Check declared facts**: If `.docguard-evidence.json` exists, run `npx docguard verify --evidence --format json`; a pass covers only its selected statement
56
+ 3. **After making changes**: Run `npx docguard fix --format prompt` to find remaining issues
57
+ 4. **Fix what DocGuard reports**: Each issue includes an `ai_instruction` telling you exactly what to do
58
+ 5. **Run guard again**: Verify all issues are resolved before committing
59
+ 6. **Update CHANGELOG.md**: All changes need a changelog entry
60
+
61
+ Preserve the five evidence states. Review approved intent before changing either
62
+ side of a contradiction. Undeclared prose and whole-document accuracy remain
63
+ unverified.
59
64
 
60
65
  ### Auto-Fix Available Issues
61
66
 
@@ -21,17 +21,17 @@ jobs:
21
21
  echo "DOCGUARD_REPORT=$RUNNER_TEMP/docguard-report.json" >> "$GITHUB_ENV"
22
22
  echo "DOCGUARD_LOG=$RUNNER_TEMP/docguard-stderr.log" >> "$GITHUB_ENV"
23
23
 
24
- - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0
24
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
25
25
  with:
26
26
  fetch-depth: 0 # Freshness needs the complete commit history.
27
27
  persist-credentials: false
28
28
 
29
- - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
29
+ - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
30
30
  with:
31
31
  node-version: '20'
32
32
 
33
33
  - name: Install DocGuard
34
- run: npm install --global --ignore-scripts docguard-cli@0.38.0
34
+ run: npm install --global --ignore-scripts docguard-cli@0.40.0
35
35
 
36
36
  - name: Run DocGuard
37
37
  shell: bash
@@ -70,7 +70,7 @@ jobs:
70
70
 
71
71
  - name: Upload Report
72
72
  if: always()
73
- uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
73
+ uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
74
74
  with:
75
75
  name: docguard-report
76
76
  path: |
@@ -28,6 +28,7 @@ Read the JSON contract — do not parse prose:
28
28
  | `nextStep` | The single suggested follow-up command (`null` on PASS) |
29
29
  | `reportable[]` | Low-confidence findings (possible false positives) — verify before acting |
30
30
  | `coverage` | Markdown tier map: `canonical / tracked / ignored / unclassified[]` |
31
+ | `evidence` | Exact declaration states and their explicit scope limitation |
31
32
  | `semanticClaims.count` | Documented counts/limits/enums NOT yet verified against code |
32
33
  | `validators[]` | Per-validator results, including `na` (nothing to validate ≠ pass) |
33
34
 
@@ -53,7 +54,10 @@ Read the JSON contract — do not parse prose:
53
54
  validator not-applicable in a doc:
54
55
  `<!-- docguard:validator <key> n/a — reason -->`. Always include the reason.
55
56
  Never suppress to silence a real issue.
56
- 4. If `semanticClaims.count > 0`, offer to run `npx docguard-cli verify --semantic`
57
+ 4. If `evidence.configured`, resolve every contradiction/stale/inconclusive/
58
+ unsupported declaration with `npx docguard-cli verify --evidence --format json`.
59
+ A verified declaration covers only its selected statement.
60
+ 5. If `semanticClaims.count > 0`, run `npx docguard-cli verify --semantic`
57
61
  and check each extracted claim against the code — a green guard asserts
58
62
  structure, not the truth of documented numbers.
59
63
 
@@ -27,10 +27,15 @@ Findings carry stable codes — `npx docguard-cli explain <CODE>` when unclear.
27
27
  ## Step 2: Verify Documented Claims Against Code
28
28
 
29
29
  ```bash
30
+ npx docguard-cli verify --evidence --format json
30
31
  npx docguard-cli verify --semantic
31
32
  ```
32
33
 
33
- This extracts every checkable claim in the canonical docs counts, limits,
34
+ Review exact declaration states first. A contradiction may indicate a code
35
+ regression from approved intent; stale evidence requires regenerating the saved
36
+ upstream report. A scoped pass does not verify its containing document.
37
+
38
+ The semantic command then extracts remaining checkable claims in the canonical docs — counts, limits,
34
39
  rate numbers, retention windows, status enums — as a task list with the nearest
35
40
  cited code path. **You perform each verification**: read the cited code, compare
36
41
  the value, and report every mismatch with both values. This is the highest-value
@@ -0,0 +1,21 @@
1
+ {
2
+ "$schema": "https://raccioly.github.io/docguard/schemas/docguard-evidence.schema.json",
3
+ "schemaVersion": 1,
4
+ "declarations": [
5
+ {
6
+ "id": "policy.retention-days",
7
+ "applicability": { "mode": "always" },
8
+ "target": {
9
+ "document": "docs-canonical/SECURITY.md",
10
+ "heading": "Data retention",
11
+ "statement": "Audit records are retained for {{value}} days."
12
+ },
13
+ "source": {
14
+ "adapter": "json-pointer",
15
+ "path": "config/policy.json",
16
+ "pointer": "/retentionDays"
17
+ },
18
+ "predicate": { "kind": "equals", "valueType": "number" }
19
+ }
20
+ ]
21
+ }
@@ -0,0 +1,18 @@
1
+ {
2
+ "$schema": "https://raccioly.github.io/docguard/schemas/docguard-feedback-fixture.schema.json",
3
+ "schemaVersion": 1,
4
+ "classification": "false_positive",
5
+ "detector": { "code": "SEC001", "validator": "security" },
6
+ "parserTier": "js-ast",
7
+ "config": { "profile": "starter", "diskCache": false, "validators": { "security": true } },
8
+ "expectedIdentity": "SEC001@src/case.js",
9
+ "interestingness": { "predicate": "finding_present" },
10
+ "fixture": { "files": [{ "path": "src/case.js", "content": "const password = \"validation message with several words\";\n" }] },
11
+ "oppositeControl": { "files": [{ "path": "src/case.js", "content": "const password = \"real-looking-password\";\n" }] },
12
+ "provenance": { "synthetic": true, "redactionAttested": true },
13
+ "contribution": {
14
+ "testOnly": true,
15
+ "scopeDocumented": true,
16
+ "benchmarkDelta": { "falsePositives": 0, "falseNegatives": 0, "unsupportedCases": 0, "abstainedSupportedCases": 0 }
17
+ }
18
+ }