docguard-cli 0.14.0__tar.gz → 0.15.1__tar.gz

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 (300) hide show
  1. {docguard_cli-0.14.0/extensions/spec-kit-docguard → docguard_cli-0.15.1/.agent}/skills/docguard-fix/SKILL.md +2 -2
  2. {docguard_cli-0.14.0/extensions/spec-kit-docguard → docguard_cli-0.15.1/.agent}/skills/docguard-guard/SKILL.md +2 -2
  3. {docguard_cli-0.14.0/extensions/spec-kit-docguard → docguard_cli-0.15.1/.agent}/skills/docguard-review/SKILL.md +2 -2
  4. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/.agent/skills/docguard-score/SKILL.md +2 -2
  5. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/.agent/skills/docguard-sync/SKILL.md +1 -1
  6. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/CHANGELOG.md +89 -0
  7. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/PKG-INFO +1 -1
  8. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/cli/commands/guard.mjs +1 -1
  9. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/cli/commands/init.mjs +4 -0
  10. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/cli/scanners/memory-plan.mjs +46 -1
  11. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/cli/scanners/schemas.mjs +37 -12
  12. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/cli/validators/cross-reference.mjs +43 -5
  13. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/cli/validators/drift.mjs +26 -11
  14. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/cli/validators/metrics-consistency.mjs +28 -4
  15. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/cli/validators/todo-tracking.mjs +52 -41
  16. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/cli/writers/mechanical.mjs +33 -0
  17. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/extensions/spec-kit-docguard/extension.yml +1 -1
  18. {docguard_cli-0.14.0/.agent → docguard_cli-0.15.1/extensions/spec-kit-docguard}/skills/docguard-fix/SKILL.md +2 -2
  19. {docguard_cli-0.14.0/.agent → docguard_cli-0.15.1/extensions/spec-kit-docguard}/skills/docguard-guard/SKILL.md +2 -2
  20. {docguard_cli-0.14.0/.agent → docguard_cli-0.15.1/extensions/spec-kit-docguard}/skills/docguard-review/SKILL.md +2 -2
  21. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/extensions/spec-kit-docguard/skills/docguard-score/SKILL.md +2 -2
  22. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/extensions/spec-kit-docguard/skills/docguard-sync/SKILL.md +1 -1
  23. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/package.json +2 -1
  24. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/pyproject.toml +1 -1
  25. docguard_cli-0.15.1/schemas/docguard-config.schema.json +155 -0
  26. docguard_cli-0.15.1/tests/anchor-autofix.test.mjs +144 -0
  27. docguard_cli-0.15.1/tests/metrics-dedup.test.mjs +112 -0
  28. docguard_cli-0.15.1/tests/scoping-extended.test.mjs +90 -0
  29. docguard_cli-0.15.1/tests/stress-test.test.mjs +111 -0
  30. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/.agent/commands/speckit.analyze.md +0 -0
  31. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/.agent/commands/speckit.checklist.md +0 -0
  32. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/.agent/commands/speckit.clarify.md +0 -0
  33. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/.agent/commands/speckit.constitution.md +0 -0
  34. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/.agent/commands/speckit.implement.md +0 -0
  35. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/.agent/commands/speckit.plan.md +0 -0
  36. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/.agent/commands/speckit.specify.md +0 -0
  37. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/.agent/commands/speckit.tasks.md +0 -0
  38. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/.agent/commands/speckit.taskstoissues.md +0 -0
  39. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/.agent/skills/speckit-analyze/SKILL.md +0 -0
  40. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/.agent/skills/speckit-checklist/SKILL.md +0 -0
  41. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/.agent/skills/speckit-clarify/SKILL.md +0 -0
  42. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/.agent/skills/speckit-constitution/SKILL.md +0 -0
  43. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/.agent/skills/speckit-implement/SKILL.md +0 -0
  44. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/.agent/skills/speckit-plan/SKILL.md +0 -0
  45. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/.agent/skills/speckit-specify/SKILL.md +0 -0
  46. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/.agent/skills/speckit-tasks/SKILL.md +0 -0
  47. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/.agent/skills/speckit-taskstoissues/SKILL.md +0 -0
  48. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/.docguard.json +0 -0
  49. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/.docguardignore +0 -0
  50. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
  51. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
  52. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/.github/dependabot.yml +0 -0
  53. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/.github/scripts/patch-catalog.py +0 -0
  54. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/.github/workflows/ci.yml +0 -0
  55. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/.github/workflows/release.yml +0 -0
  56. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/.github/workflows/supply-chain.yml +0 -0
  57. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/.github/workflows/sync-speckit-catalog.yml +0 -0
  58. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/.gitignore +0 -0
  59. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/.jules/bolt.md +0 -0
  60. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/.jules/palette.md +0 -0
  61. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/.jules/sentinel.md +0 -0
  62. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/.npmignore +0 -0
  63. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/.npmrc +0 -0
  64. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/.specify/extensions/.cache/catalog-ebf165086500aab1-metadata.json +0 -0
  65. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/.specify/extensions/.cache/catalog-ebf165086500aab1.json +0 -0
  66. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/.specify/extensions/.cache/catalog-metadata.json +0 -0
  67. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/.specify/extensions/.cache/catalog.json +0 -0
  68. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/.specify/init-options.json +0 -0
  69. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/.specify/memory/constitution.md +0 -0
  70. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/.specify/scripts/bash/check-prerequisites.sh +0 -0
  71. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/.specify/scripts/bash/common.sh +0 -0
  72. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/.specify/scripts/bash/create-new-feature.sh +0 -0
  73. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/.specify/scripts/bash/setup-plan.sh +0 -0
  74. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/.specify/scripts/bash/update-agent-context.sh +0 -0
  75. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/.specify/templates/agent-file-template.md +0 -0
  76. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/.specify/templates/checklist-template.md +0 -0
  77. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/.specify/templates/constitution-template.md +0 -0
  78. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/.specify/templates/plan-template.md +0 -0
  79. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/.specify/templates/spec-template.md +0 -0
  80. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/.specify/templates/tasks-template.md +0 -0
  81. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/AGENTS.md +0 -0
  82. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/CODE_OF_CONDUCT.md +0 -0
  83. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/COMPARISONS.md +0 -0
  84. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/CONTRIBUTING.md +0 -0
  85. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/DRIFT-LOG.md +0 -0
  86. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/LICENSE +0 -0
  87. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/PHILOSOPHY.md +0 -0
  88. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/README.md +0 -0
  89. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/ROADMAP.md +0 -0
  90. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/SECURITY.md +0 -0
  91. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/STANDARD.md +0 -0
  92. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/SUPPLY-CHAIN-AUDIT.md +0 -0
  93. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/SUPPORT.md +0 -0
  94. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/action.yml +0 -0
  95. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/cli/commands/agents.mjs +0 -0
  96. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/cli/commands/badge.mjs +0 -0
  97. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/cli/commands/ci.mjs +0 -0
  98. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/cli/commands/diagnose.mjs +0 -0
  99. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/cli/commands/diff.mjs +0 -0
  100. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/cli/commands/fix.mjs +0 -0
  101. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/cli/commands/generate.mjs +0 -0
  102. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/cli/commands/hooks.mjs +0 -0
  103. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/cli/commands/impact.mjs +0 -0
  104. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/cli/commands/llms.mjs +0 -0
  105. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/cli/commands/publish.mjs +0 -0
  106. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/cli/commands/score.mjs +0 -0
  107. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/cli/commands/setup.mjs +0 -0
  108. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/cli/commands/sync.mjs +0 -0
  109. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/cli/commands/trace.mjs +0 -0
  110. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/cli/commands/upgrade.mjs +0 -0
  111. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/cli/commands/watch.mjs +0 -0
  112. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/cli/docguard.mjs +0 -0
  113. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/cli/ensure-skills.mjs +0 -0
  114. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/cli/scanners/api-doc.mjs +0 -0
  115. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/cli/scanners/cdk.mjs +0 -0
  116. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/cli/scanners/doc-tools.mjs +0 -0
  117. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/cli/scanners/frontend.mjs +0 -0
  118. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/cli/scanners/iac.mjs +0 -0
  119. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/cli/scanners/integrations.mjs +0 -0
  120. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/cli/scanners/project-type.mjs +0 -0
  121. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/cli/scanners/routes.mjs +0 -0
  122. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/cli/scanners/speckit.mjs +0 -0
  123. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/cli/shared-git.mjs +0 -0
  124. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/cli/shared-ignore.mjs +0 -0
  125. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/cli/shared-source.mjs +0 -0
  126. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/cli/shared.mjs +0 -0
  127. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/cli/validators/api-surface.mjs +0 -0
  128. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/cli/validators/architecture.mjs +0 -0
  129. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/cli/validators/changelog.mjs +0 -0
  130. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/cli/validators/doc-quality.mjs +0 -0
  131. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/cli/validators/docs-coverage.mjs +0 -0
  132. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/cli/validators/docs-diff.mjs +0 -0
  133. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/cli/validators/docs-sync.mjs +0 -0
  134. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/cli/validators/environment.mjs +0 -0
  135. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/cli/validators/freshness.mjs +0 -0
  136. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/cli/validators/generated-staleness.mjs +0 -0
  137. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/cli/validators/metadata-sync.mjs +0 -0
  138. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/cli/validators/schema-sync.mjs +0 -0
  139. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/cli/validators/security.mjs +0 -0
  140. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/cli/validators/structure.mjs +0 -0
  141. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/cli/validators/test-spec.mjs +0 -0
  142. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/cli/validators/traceability.mjs +0 -0
  143. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/cli/writers/api-reference.mjs +0 -0
  144. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/cli/writers/fix-memory.mjs +0 -0
  145. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/cli/writers/sections.mjs +0 -0
  146. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/commands/docguard.fix.md +0 -0
  147. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/commands/docguard.guard.md +0 -0
  148. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/commands/docguard.review.md +0 -0
  149. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/commands/docguard.score.md +0 -0
  150. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/configs/fastify.json +0 -0
  151. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/configs/generic.json +0 -0
  152. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/configs/nextjs.json +0 -0
  153. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/configs/python.json +0 -0
  154. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/docguard_cli/__init__.py +0 -0
  155. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/docguard_cli/wrapper.py +0 -0
  156. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/docs/ai-integration.md +0 -0
  157. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/docs/commands.md +0 -0
  158. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/docs/configuration.md +0 -0
  159. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/docs/doc-sections.md +0 -0
  160. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/docs/faq.md +0 -0
  161. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/docs/installation.md +0 -0
  162. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/docs/profiles.md +0 -0
  163. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/docs/quickstart.md +0 -0
  164. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/docs-canonical/ARCHITECTURE.md +0 -0
  165. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/docs-canonical/CI-RECIPES.md +0 -0
  166. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/docs-canonical/DATA-MODEL.md +0 -0
  167. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/docs-canonical/ENVIRONMENT.md +0 -0
  168. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/docs-canonical/SECURITY.md +0 -0
  169. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/docs-canonical/TEST-SPEC.md +0 -0
  170. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/examples/01-express-api/README.md +0 -0
  171. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/examples/01-express-api/package.json +0 -0
  172. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/examples/01-express-api/server.js +0 -0
  173. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/examples/02-python-flask/README.md +0 -0
  174. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/examples/02-python-flask/app.py +0 -0
  175. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/examples/02-python-flask/docs-canonical/ARCHITECTURE.md +0 -0
  176. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/examples/02-python-flask/requirements.txt +0 -0
  177. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/examples/03-spec-kit-project/CHANGELOG.md +0 -0
  178. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/examples/03-spec-kit-project/README.md +0 -0
  179. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/examples/03-spec-kit-project/docs-canonical/ARCHITECTURE.md +0 -0
  180. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/examples/03-spec-kit-project/docs-canonical/TEST-SPEC.md +0 -0
  181. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/examples/03-spec-kit-project/package.json +0 -0
  182. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/examples/03-spec-kit-project/src/index.js +0 -0
  183. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/examples/03-spec-kit-project/tests/basic.test.js +0 -0
  184. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/examples/README.md +0 -0
  185. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/extensions/spec-kit-docguard/LICENSE +0 -0
  186. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/extensions/spec-kit-docguard/README.md +0 -0
  187. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/extensions/spec-kit-docguard/commands/diagnose.md +0 -0
  188. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/extensions/spec-kit-docguard/commands/fix.md +0 -0
  189. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/extensions/spec-kit-docguard/commands/generate.md +0 -0
  190. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/extensions/spec-kit-docguard/commands/guard.md +0 -0
  191. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/extensions/spec-kit-docguard/commands/init.md +0 -0
  192. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/extensions/spec-kit-docguard/commands/score.md +0 -0
  193. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/extensions/spec-kit-docguard/commands/sync.md +0 -0
  194. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/extensions/spec-kit-docguard/commands/trace.md +0 -0
  195. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/extensions/spec-kit-docguard/scripts/bash/common.sh +0 -0
  196. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/extensions/spec-kit-docguard/scripts/bash/docguard-check-docs.sh +0 -0
  197. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/extensions/spec-kit-docguard/scripts/bash/docguard-init-doc.sh +0 -0
  198. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/extensions/spec-kit-docguard/scripts/bash/docguard-suggest-fix.sh +0 -0
  199. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/extensions/spec-kit-docguard/templates/extensions.yml +0 -0
  200. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/extensions/spec-kit-docguard/templates/github-workflows/docguard-autofix.yml +0 -0
  201. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/extensions/spec-kit-docguard/templates/github-workflows/docguard-guard.yml +0 -0
  202. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/pr_description.md +0 -0
  203. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/specs/001-fix-ignore-validators/plan.md +0 -0
  204. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/specs/001-fix-ignore-validators/spec.md +0 -0
  205. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/specs/001-fix-ignore-validators/tasks.md +0 -0
  206. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/specs/002-fix-test-discovery/plan.md +0 -0
  207. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/specs/002-fix-test-discovery/spec.md +0 -0
  208. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/specs/002-fix-test-discovery/tasks.md +0 -0
  209. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/specs/003-v011-false-positives/plan.md +0 -0
  210. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/specs/003-v011-false-positives/spec.md +0 -0
  211. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/specs/003-v011-false-positives/tasks.md +0 -0
  212. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/templates/ADR.md.template +0 -0
  213. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/templates/AGENTS.md.template +0 -0
  214. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/templates/ARCHITECTURE.md.template +0 -0
  215. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/templates/CHANGELOG.md.template +0 -0
  216. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/templates/CURRENT-STATE.md.template +0 -0
  217. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/templates/DATA-MODEL.md.template +0 -0
  218. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/templates/DEPLOYMENT.md.template +0 -0
  219. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/templates/DRIFT-LOG.md.template +0 -0
  220. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/templates/ENVIRONMENT.md.template +0 -0
  221. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/templates/KNOWN-GOTCHAS.md.template +0 -0
  222. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/templates/REQUIREMENTS.md.template +0 -0
  223. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/templates/ROADMAP.md.template +0 -0
  224. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/templates/RUNBOOKS.md.template +0 -0
  225. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/templates/SECURITY.md.template +0 -0
  226. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/templates/TEST-SPEC.md.template +0 -0
  227. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/templates/TROUBLESHOOTING.md.template +0 -0
  228. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/templates/VENDOR-BUGS.md.template +0 -0
  229. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/templates/ci/github-actions.yml +0 -0
  230. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/templates/commands/docguard.fix.md +0 -0
  231. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/templates/commands/docguard.guard.md +0 -0
  232. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/templates/commands/docguard.init.md +0 -0
  233. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/templates/commands/docguard.review.md +0 -0
  234. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/templates/commands/docguard.update.md +0 -0
  235. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/test-draft.js +0 -0
  236. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/test-metrics.js +0 -0
  237. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/tests/api-doc.test.mjs +0 -0
  238. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/tests/api-surface.test.mjs +0 -0
  239. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/tests/api-write.test.mjs +0 -0
  240. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/tests/architecture.test.mjs +0 -0
  241. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/tests/backup-failure.test.mjs +0 -0
  242. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/tests/cdk-detection.test.mjs +0 -0
  243. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/tests/changed-only-scoping.test.mjs +0 -0
  244. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/tests/changed-only.test.mjs +0 -0
  245. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/tests/changelog.test.mjs +0 -0
  246. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/tests/commands.test.mjs +0 -0
  247. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/tests/cross-reference.test.mjs +0 -0
  248. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/tests/doc-quality.test.mjs +0 -0
  249. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/tests/docguardignore.test.mjs +0 -0
  250. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/tests/docs-coverage.test.mjs +0 -0
  251. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/tests/docs-diff.test.mjs +0 -0
  252. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/tests/docs-sync.test.mjs +0 -0
  253. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/tests/drift.test.mjs +0 -0
  254. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/tests/environment.test.mjs +0 -0
  255. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/tests/fix-memory.test.mjs +0 -0
  256. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/tests/fix-suppression.test.mjs +0 -0
  257. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/tests/fixture-projects.test.mjs +0 -0
  258. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/tests/freshness.test.mjs +0 -0
  259. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/tests/frontend-deep.test.mjs +0 -0
  260. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/tests/frontend.test.mjs +0 -0
  261. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/tests/generated-staleness.test.mjs +0 -0
  262. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/tests/guard-classify.test.mjs +0 -0
  263. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/tests/guard-no-throw.test.mjs +0 -0
  264. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/tests/hooks.test.mjs +0 -0
  265. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/tests/i18n.test.mjs +0 -0
  266. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/tests/impact.test.mjs +0 -0
  267. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/tests/integrations.test.mjs +0 -0
  268. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/tests/mechanical.test.mjs +0 -0
  269. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/tests/memory-plan.test.mjs +0 -0
  270. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/tests/metadata-sync.test.mjs +0 -0
  271. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/tests/metrics-consistency.test.mjs +0 -0
  272. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/tests/monorepo-scanning.test.mjs +0 -0
  273. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/tests/multi-spec.test.mjs +0 -0
  274. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/tests/patch-0.11.2.test.mjs +0 -0
  275. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/tests/profile-flag.test.mjs +0 -0
  276. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/tests/project-type.test.mjs +0 -0
  277. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/tests/regenerate-section.test.mjs +0 -0
  278. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/tests/routes-multilang.test.mjs +0 -0
  279. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/tests/schema-sync.test.mjs +0 -0
  280. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/tests/schemas-multilang.test.mjs +0 -0
  281. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/tests/schemas.test.mjs +0 -0
  282. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/tests/sections.test.mjs +0 -0
  283. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/tests/security.test.mjs +0 -0
  284. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/tests/severity.test.mjs +0 -0
  285. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/tests/shared-git.test.mjs +0 -0
  286. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/tests/shared-source.test.mjs +0 -0
  287. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/tests/structure.test.mjs +0 -0
  288. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/tests/sweep-nudge.test.mjs +0 -0
  289. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/tests/sync-since.test.mjs +0 -0
  290. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/tests/sync.test.mjs +0 -0
  291. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/tests/test-spec.test.mjs +0 -0
  292. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/tests/todo-tracking.test.mjs +0 -0
  293. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/tests/trace-reverse.test.mjs +0 -0
  294. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/tests/traceability.test.mjs +0 -0
  295. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/tests/upgrade-pr.test.mjs +0 -0
  296. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/tests/upgrade.test.mjs +0 -0
  297. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/vscode-extension/.vscodeignore +0 -0
  298. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/vscode-extension/README.md +0 -0
  299. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/vscode-extension/extension.js +0 -0
  300. {docguard_cli-0.14.0 → docguard_cli-0.15.1}/vscode-extension/package.json +0 -0
@@ -6,10 +6,10 @@ description: AI-driven documentation repair with structured research workflow, t
6
6
  compatibility: Requires DocGuard CLI installed (npm i -g docguard-cli or npx docguard-cli)
7
7
  metadata:
8
8
  author: docguard
9
- version: 0.14.0
9
+ version: 0.15.1
10
10
  source: extensions/spec-kit-docguard/skills/docguard-fix
11
11
  ---
12
- <!-- docguard:version: 0.14.0 -->
12
+ <!-- docguard:version: 0.15.1 -->
13
13
 
14
14
  # DocGuard Fix Skill
15
15
 
@@ -7,10 +7,10 @@ description: Run DocGuard guard validation against Canonical-Driven Development
7
7
  compatibility: Requires DocGuard CLI installed (npm i -g docguard-cli or npx docguard-cli)
8
8
  metadata:
9
9
  author: docguard
10
- version: 0.14.0
10
+ version: 0.15.1
11
11
  source: extensions/spec-kit-docguard/skills/docguard-guard
12
12
  ---
13
- <!-- docguard:version: 0.14.0 -->
13
+ <!-- docguard:version: 0.15.1 -->
14
14
 
15
15
  # DocGuard Guard Skill
16
16
 
@@ -6,10 +6,10 @@ description: Cross-document consistency analysis and quality assessment. Perform
6
6
  compatibility: Requires DocGuard CLI installed (npm i -g docguard-cli or npx docguard-cli)
7
7
  metadata:
8
8
  author: docguard
9
- version: 0.14.0
9
+ version: 0.15.1
10
10
  source: extensions/spec-kit-docguard/skills/docguard-review
11
11
  ---
12
- <!-- docguard:version: 0.14.0 -->
12
+ <!-- docguard:version: 0.15.1 -->
13
13
 
14
14
  # DocGuard Review Skill
15
15
 
@@ -6,10 +6,10 @@ description: CDD maturity assessment with category-aware improvement roadmap. Ru
6
6
  compatibility: Requires DocGuard CLI installed (npm i -g docguard-cli or npx docguard-cli)
7
7
  metadata:
8
8
  author: docguard
9
- version: 0.14.0
9
+ version: 0.15.1
10
10
  source: extensions/spec-kit-docguard/skills/docguard-score
11
11
  ---
12
- <!-- docguard:version: 0.14.0 -->
12
+ <!-- docguard:version: 0.15.1 -->
13
13
 
14
14
  # DocGuard Score Skill
15
15
 
@@ -4,7 +4,7 @@ description: Keep canonical documentation ALWAYS UP TO DATE. Refreshes code-trut
4
4
  compatibility: Requires DocGuard CLI installed (npm i -g docguard-cli or npx docguard-cli)
5
5
  metadata:
6
6
  author: docguard
7
- version: 0.14.0
7
+ version: 0.15.1
8
8
  source: extensions/spec-kit-docguard/skills/docguard-sync
9
9
  ---
10
10
 
@@ -7,6 +7,95 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.15.1] - 2026-05-26
11
+
12
+ Feature + performance release. **497 tests** (was 492, +5). 22 validators.
13
+ Headline: full `--changed-only` set now covers **5 validators in ~100ms** on
14
+ both wu-whatsappinbox AND a synthetic 1000-file repo. New `.docguard.json`
15
+ JSON Schema for IDE autocomplete.
16
+
17
+ > **Note**: v0.15.0 was committed but never published — the CI self-guard
18
+ > failed because the new `tests/scoping-extended.test.mjs` had literal
19
+ > `// DRIFT:` strings inside JS fixture data that Drift-Comments treated as
20
+ > real drift comments. v0.15.1 includes a two-part fix: the test uses string
21
+ > concatenation so the literal marker isn't in source, AND Drift-Comments
22
+ > now skips test files by default (matching TODO-Tracking's pattern; opt in
23
+ > via `config.drift.includeTestFiles`). Everything else in this release was
24
+ > ready in v0.15.0 — see the v0.15.0-planned features below.
25
+
26
+ ### Fixed (v0.15.1 hotfix)
27
+
28
+ - **Drift-Comments false-positives from test fixtures.** Test files commonly carry literal `// DRIFT:` strings inside JS string fixtures (`'// DRIFT: example\n'`). Reading the test as source treated those as real drift comments. Drift-Comments now skips test files by default — same defensive posture TODO-Tracking adopted in v0.11.2 for the same reason. New `config.drift.includeTestFiles` opt-in for projects that genuinely use DRIFT markers in test code.
29
+
30
+ ### Added
31
+
32
+ - **P3: Drift-Comments + TODO-Tracking honor `config.changedFiles`.** Extending the v0.13 N-1 + v0.14-P2 lite-mode scoping. Now 5 of 22 validators scope to changed files in `--changed-only` mode (was 3). `CHANGED_ONLY_VALIDATORS` updated to include `drift` and `todoTracking`. **Result on wu: `--changed-only --since HEAD~3` runs 5 validators in 116ms** (was 78ms with 3 validators in v0.14 — adding two more validators cost only ~40ms because each is scoped). **Result on synthetic 1000-file repo: 91ms** (verified via new stress test).
33
+ - **P4: JSON Schema for `.docguard.json`.** New `schemas/docguard-config.schema.json` shipped in the npm package. `docguard init` now writes `$schema` reference into newly-created configs so VS Code / IntelliJ / any JSON-Schema-aware editor gets autocomplete + inline validation for every config field. Includes types, descriptions, enums (severity = high/medium/low; profile = starter/standard/enterprise; projectType = cli/library/webapp/api/unknown), and field-level help text. Zero runtime impact — DocGuard ignores the `$schema` field itself.
34
+ - **Q: Stress-test fixture.** New `tests/stress-test.test.mjs` builds a synthetic 1000-file monorepo (500 services + 500 routes + 1000 doc references) and asserts:
35
+ - `--changed-only` finishes in **< 500ms** (actual: ~91ms).
36
+ - Full guard finishes in **< 5s** (actual: ~755ms).
37
+ Opt-in via `STRESS=1` to keep `npm test` fast. Catches regressions where any scoping path accidentally devolves to a full tree walk.
38
+
39
+ ### Performance
40
+
41
+ - **P1: `buildMemoryPlan` cache.** Memoizes the memory plan per (projectDir + scanner-relevant config) within a single process. Helps cross-command flows where `guard` then `sync` would otherwise rebuild the plan twice. New `clearMemoryPlanCache()` export for tests. Single-`guard` runs see no change (only one caller per process).
42
+ - **P2: `walkDir` cache in `cli/scanners/schemas.mjs`.** `walkDir` was called 8× inside `scanSchemasDeep` for different entity types (Pydantic, Mongoose, Prisma, SQLAlchemy, Sequelize, GORM, Sqlx, Hibernate). Now caches the file list per directory; subsequent callers iterate an array instead of re-traversing. Net gain on wu's mixed Python+TS stack is modest (~3% of total validator time) but real, and helps on stacks where multiple scanners hit the same root dir.
43
+ - **Combined P1+P2+P3 result on wu**: full guard 1456ms → 1431ms (~2%). `--changed-only` covers 5/22 validators in 116ms (vs 1456ms full = **12.6× faster**).
44
+
45
+ ### Internal
46
+
47
+ - **2 new test files**: `tests/scoping-extended.test.mjs` (4 tests covering P3) and `tests/stress-test.test.mjs` (2 stress tests + 1 always-passes smoke). **Total: 492 → 497 tests (+5 — stress tests opt-in via STRESS=1).**
48
+ - New helpers: `clearMemoryPlanCache()`, `clearWalkDirCache()`, `_scanTodoFile()`.
49
+ - `schemas/docguard-config.schema.json` is the first non-code file under `schemas/` — added to `package.json#files` so it ships in the npm tarball.
50
+ - `.docguard.json` now self-documents via `$schema` reference when created by `init`.
51
+ - Dry-run on wu: **672/672 PASS in 1.43s**.
52
+ - No new NPM deps.
53
+
54
+ ### Out of scope (deferred to v0.16)
55
+
56
+ - **Deeper Generated-Staleness optimization** — still the slowest validator at 26% of guard time on wu. The cache helps cross-command flows but not single-guard runs. Next attack vector: stream `buildMemoryPlan` so it yields partial results as scanners complete, letting the validator early-exit on the first non-stale section.
57
+ - **`upgrade --apply --pr` battle-test** on a real GitHub repo. Logic shipped in v0.14; end-to-end PR creation hasn't been tested against a live remote with branch protections.
58
+ - **Cross-process memoization** — if guard / sync / fix runs in CI sequentially, they each rebuild the plan. A serialized cache under `.docguard/plan.cache.json` (keyed by a tree-state hash) would share across processes.
59
+ - **Tree-state hashing for plan cache invalidation** — currently the in-process cache assumes the tree doesn't change mid-run. A proper hash would let long-running `watch` mode keep a stable cache that only invalidates on actual file changes.
60
+
61
+ ## [0.14.1] - 2026-05-26
62
+
63
+ Patch + small feature release responding to the wu-whatsappinbox v0.12 feedback.
64
+ **492 tests** (was 481, +11). 22 validators.
65
+
66
+ ### Fixed
67
+
68
+ - **N-1: Metrics-Consistency double-counted warnings.** When a doc mentioned the stale validator/check count multiple times (e.g. once in a heading, once in a body table), the validator emitted one warning per regex match — producing "4 warnings for 2 files" on wu-whatsappinbox. Now dedupes by `(file, label, found-value)` so a single file contributes ONE warning per distinct drift value. The `replace-count` mechanical fix already uses replace-all semantics, so one fix per (file, label) is sufficient. **Reported by wu-whatsappinbox.**
69
+
70
+ ### Added
71
+
72
+ - **S-12+: High-confidence anchor matches now auto-fix via `fix --write`.** v0.13.1 added "did you mean #X?" hints when Cross-Reference flagged a broken anchor. v0.14.1 takes the next step: when the suggested anchor is **unambiguous** (edit distance ≤ 2 AND no other candidates within the same distance), the warning is tagged `[auto-fixable]` and the validator emits a `replace-anchor` mechanical fix. New `replace-anchor` applier in `cli/writers/mechanical.mjs` rewrites only the anchor inside markdown link form `](#X)`, leaves plain-text occurrences and link text alone, is idempotent. **Three of five wu broken-anchor cases in v0.12.0 were "heading renamed, link not updated" — those are now `fix --write`-resolvable.**
73
+
74
+ ### Note to wu — the "still open" suggestions are all already shipped
75
+
76
+ The S-1, S-11, S-12 items in the v0.12 feedback letter all shipped earlier. The user just needs to upgrade:
77
+
78
+ - **S-1** (`sync --since <ref>` surgical refresh) → shipped in **v0.13.0** as L-1. Run `docguard sync --write --since main` to refresh only sections touched by code in the diff.
79
+ - **S-11** (changed-file → affected-doc map) → shipped in **v0.13.1** as the `docguard impact` command. Run `docguard impact --since HEAD~1` after a commit; JSON mode for CI bots.
80
+ - **S-12** (anchor "did you mean..." hints) → shipped in **v0.13.1**. Extended in this release (v0.14.1) so high-confidence matches are auto-fixable.
81
+
82
+ Run `docguard upgrade --apply` (or `npm i -g docguard-cli@latest`) to pick all of these up.
83
+
84
+ ### Internal
85
+
86
+ - **2 new test files**: `tests/metrics-dedup.test.mjs` (4) and `tests/anchor-autofix.test.mjs` (7). **Total: 481 → 492 tests (+11).**
87
+ - **New mechanical fix type**: `replace-anchor`. The APPLIERS registry now lists 6 types.
88
+ - **New helper** in `cli/validators/cross-reference.mjs`: `isUnambiguousSuggestion()` — gates the auto-fix on edit distance ≤ 2 AND single close candidate.
89
+ - No new NPM deps.
90
+
91
+ ### Out of scope (deferred to v0.15)
92
+
93
+ Same backlog as v0.14:
94
+ - Generated-Staleness perf optimization (33% of validator time).
95
+ - Shared tree walk.
96
+ - Cross-validator `config.changedFiles` opt-in.
97
+ - `upgrade --pr` battle-test.
98
+
10
99
  ## [0.14.0] - 2026-05-26
11
100
 
12
101
  Feature release closing the v0.13 backlog (4 features) + 2 quality investments
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: docguard-cli
3
- Version: 0.14.0
3
+ Version: 0.15.1
4
4
  Summary: The enforcement tool for Canonical-Driven Development (CDD). Audit, generate, and guard your project documentation. Zero dependencies.
5
5
  Project-URL: Homepage, https://github.com/raccioly/docguard
6
6
  Project-URL: Documentation, https://github.com/raccioly/docguard#readme
@@ -198,7 +198,7 @@ export function runGuardInternal(projectDir, config) {
198
198
  * Freshness (git log), Traceability (REQ scan), Doc-Quality (prose lint) —
199
199
  * stay off for speed.
200
200
  */
201
- export const CHANGED_ONLY_VALIDATORS = ['docsSync', 'environment', 'apiSurface'];
201
+ export const CHANGED_ONLY_VALIDATORS = ['docsSync', 'environment', 'apiSurface', 'drift', 'todoTracking'];
202
202
 
203
203
  /**
204
204
  * Build a validators map that enables only the pre-commit-lite set.
@@ -167,6 +167,10 @@ export async function runInit(projectDir, config, flags) {
167
167
  const ptc = typeDefaults[detectedType] || typeDefaults.unknown;
168
168
 
169
169
  const defaultConfig = {
170
+ // v0.15-P4: $schema reference enables VS Code / IDE autocomplete +
171
+ // validation for .docguard.json fields. Picked up by any
172
+ // JSON-Schema-aware editor; ignored by DocGuard itself.
173
+ $schema: 'https://raccioly.github.io/docguard/schemas/docguard-config.schema.json',
170
174
  projectName: config.projectName,
171
175
  version: '0.5',
172
176
  profile: profileName,
@@ -29,13 +29,58 @@ const md = {
29
29
  },
30
30
  };
31
31
 
32
+ /**
33
+ * v0.15-P1: in-process cache. buildMemoryPlan is expensive (~400ms on
34
+ * wu-whatsappinbox, 33% of total guard validator time) because it triggers
35
+ * routes/schemas/screens/frontend scanners — all of which walk the source
36
+ * tree. Within a single guard run, sync, generate, and the Generated-
37
+ * Staleness validator all ask for the SAME plan; without caching they each
38
+ * re-pay the cost.
39
+ *
40
+ * Cache key: projectDir + a config fingerprint that captures the fields the
41
+ * scanners actually consume (sourceRoot, ignore, projectType). Other config
42
+ * mutations (e.g. changedFiles per-validator) don't invalidate the plan.
43
+ *
44
+ * Bypass with `_skipCache: true` in opts — used by tests and any caller that
45
+ * wants a fresh scan.
46
+ */
47
+ const _memoryPlanCache = new Map(); // key → plan
48
+
49
+ export function clearMemoryPlanCache() {
50
+ _memoryPlanCache.clear();
51
+ }
52
+
53
+ function _cacheKey(projectDir, config) {
54
+ return JSON.stringify({
55
+ dir: projectDir,
56
+ sourceRoot: config.sourceRoot,
57
+ ignore: Array.isArray(config.ignore) ? [...config.ignore].sort() : null,
58
+ projectType: config.projectType,
59
+ profile: config.profile,
60
+ });
61
+ }
62
+
32
63
  /**
33
64
  * Build the full memory plan for a project.
34
65
  * @returns {{ profile, surface, docs, agentTasks }}
35
66
  * docs[].sections[]: { id, source:'code', body } OR { id, source:'human', task, grounding }
36
67
  * agentTasks: flattened prose tasks the AI must write.
37
68
  */
38
- export function buildMemoryPlan(projectDir, config = {}) {
69
+ export function buildMemoryPlan(projectDir, config = {}, opts = {}) {
70
+ if (!opts._skipCache) {
71
+ const key = _cacheKey(projectDir, config);
72
+ const cached = _memoryPlanCache.get(key);
73
+ if (cached) return cached;
74
+ }
75
+ const result = _buildMemoryPlanUncached(projectDir, config);
76
+ if (!opts._skipCache) {
77
+ _memoryPlanCache.set(_cacheKey(projectDir, config), result);
78
+ }
79
+ return result;
80
+ }
81
+
82
+ // Original implementation, renamed so the public buildMemoryPlan can wrap it.
83
+ function _buildMemoryPlanUncached(projectDir, config = {}) {
39
84
  const profile = detectProjectProfile(projectDir, config);
40
85
  const primaryFramework = profile.primary?.framework || profile.frameworks[0] || '';
41
86
 
@@ -690,20 +690,45 @@ function readFileSafe(path) {
690
690
  try { return readFileSync(path, 'utf-8'); } catch { return null; }
691
691
  }
692
692
 
693
+ // v0.15-P2: walkDir is called 8 times across schemas.mjs (Pydantic, Mongoose,
694
+ // Prisma, SQLAlchemy, Sequelize, GORM, Sqlx, Hibernate). Each call walks the
695
+ // same tree. Cache the file list per (dir, extension-set) so subsequent
696
+ // callers iterate an array instead of re-traversing.
697
+ //
698
+ // Cache key: just the dir path. The extension filter is constant across all
699
+ // callers (the regex hard-coded below), so a single cache slot per dir works.
700
+ // Lifetime: per-process. `clearWalkDirCache()` invalidates for tests.
701
+ const _walkDirCache = new Map(); // dir → string[] of file paths
702
+
703
+ export function clearWalkDirCache() {
704
+ _walkDirCache.clear();
705
+ }
706
+
707
+ const _CODE_FILE_RE = /\.(js|mjs|cjs|ts|tsx|jsx|py|rs|go|java|kt|rb)$/;
708
+
709
+ function _collectFiles(dir, out) {
710
+ let entries;
711
+ try { entries = readdirSync(dir, { withFileTypes: true }); } catch { return; }
712
+ for (const entry of entries) {
713
+ if (IGNORE_DIRS.has(entry.name) || entry.name.startsWith('.')) continue;
714
+ const fullPath = join(dir, entry.name);
715
+ if (entry.isDirectory()) {
716
+ _collectFiles(fullPath, out);
717
+ } else if (entry.isFile() && _CODE_FILE_RE.test(entry.name)) {
718
+ out.push(fullPath);
719
+ }
720
+ }
721
+ }
722
+
693
723
  function walkDir(dir, callback) {
694
724
  if (!existsSync(dir)) return;
695
- try {
696
- const entries = readdirSync(dir, { withFileTypes: true });
697
- for (const entry of entries) {
698
- if (IGNORE_DIRS.has(entry.name) || entry.name.startsWith('.')) continue;
699
- const fullPath = join(dir, entry.name);
700
- if (entry.isDirectory()) {
701
- walkDir(fullPath, callback);
702
- } else if (entry.isFile() && /\.(js|mjs|cjs|ts|tsx|jsx|py|rs|go|java|kt|rb)$/.test(entry.name)) {
703
- callback(fullPath);
704
- }
705
- }
706
- } catch { /* skip */ }
725
+ let files = _walkDirCache.get(dir);
726
+ if (!files) {
727
+ files = [];
728
+ _collectFiles(dir, files);
729
+ _walkDirCache.set(dir, files);
730
+ }
731
+ for (const f of files) callback(f);
707
732
  }
708
733
 
709
734
  /**
@@ -27,7 +27,7 @@
27
27
  */
28
28
 
29
29
  import { existsSync, readFileSync, readdirSync, statSync } from 'node:fs';
30
- import { resolve, join, dirname, basename } from 'node:path';
30
+ import { resolve, join, dirname, basename, relative } from 'node:path';
31
31
 
32
32
  /**
33
33
  * Slugify a heading the way GitHub's markdown anchors work.
@@ -294,6 +294,7 @@ function collectCanonicalDocs(projectDir) {
294
294
  export function validateCrossReferences(projectDir, _config = {}) {
295
295
  const errors = [];
296
296
  const warnings = [];
297
+ const fixes = [];
297
298
  let passed = 0;
298
299
  let total = 0;
299
300
 
@@ -364,13 +365,27 @@ export function validateCrossReferences(projectDir, _config = {}) {
364
365
  if (!matches) {
365
366
  const where = targetPath === docPath ? 'same doc' : basename(targetPath);
366
367
  // S-12: suggest the closest matching anchor when there's a near-miss.
367
- // Three of five wu user-fixes were "heading renamed, link not updated"
368
- // — a suggested-slug hint makes those deterministic-fixable.
369
368
  const suggestion = anchors ? suggestAnchor(normalizedAnchor, anchors) : null;
370
369
  const hint = suggestion ? ` (did you mean #${suggestion}?)` : '';
370
+ // v0.14.1-S12+: when the suggestion is HIGH-CONFIDENCE — unambiguous
371
+ // and very close (edit distance <= 2) — emit a mechanical fix so
372
+ // `docguard fix --write` resolves it without AI. Other near-misses
373
+ // still get the hint but no fix (the user needs to verify intent).
374
+ const isHighConfidence = suggestion && isUnambiguousSuggestion(normalizedAnchor, suggestion, anchors);
371
375
  warnings.push(
372
- `${docName}:${ref.line} — broken anchor: "#${ref.anchor}" in ${where} doesn't match any heading${hint}`
376
+ `${docName}:${ref.line} — broken anchor: "#${ref.anchor}" in ${where} doesn't match any heading${hint}` +
377
+ (isHighConfidence ? ' [auto-fixable]' : '')
373
378
  );
379
+ if (isHighConfidence) {
380
+ fixes.push({
381
+ type: 'replace-anchor',
382
+ doc: relative(projectDir, docPath),
383
+ line: ref.line,
384
+ from: ref.anchor,
385
+ to: suggestion,
386
+ summary: `${docName}:${ref.line} #${ref.anchor} → #${suggestion}`,
387
+ });
388
+ }
374
389
  continue;
375
390
  }
376
391
  }
@@ -379,5 +394,28 @@ export function validateCrossReferences(projectDir, _config = {}) {
379
394
  }
380
395
  }
381
396
 
382
- return { errors, warnings, passed, total };
397
+ return { errors, warnings, passed, total, fixes };
398
+ }
399
+
400
+ /**
401
+ * v0.14.1-S12+ — is the suggested anchor an unambiguous, high-confidence
402
+ * match? Two criteria, both must hold:
403
+ * 1. Edit distance between the broken anchor and the suggestion is <= 2
404
+ * (catches typos and minor renames, refuses major slug rewrites).
405
+ * 2. The suggestion is the ONLY anchor that close — no other anchor
406
+ * within distance <= 2. Avoids fixing to the wrong candidate when
407
+ * multiple are similar.
408
+ */
409
+ function isUnambiguousSuggestion(broken, suggestion, anchors) {
410
+ if (!broken || !suggestion || !anchors) return false;
411
+ const sugDist = editDistance(broken, suggestion);
412
+ if (sugDist > 2) return false;
413
+ // Count other anchors that are also within the same tight budget.
414
+ let closeCandidates = 0;
415
+ for (const a of anchors) {
416
+ if (a === suggestion) continue;
417
+ if (editDistance(broken, a) <= 2) closeCandidates++;
418
+ if (closeCandidates > 0) return false; // ambiguous
419
+ }
420
+ return true;
383
421
  }
@@ -20,21 +20,27 @@ const IGNORE_DIRS = new Set([
20
20
  export function validateDrift(projectDir, config) {
21
21
  const results = { name: 'drift', errors: [], warnings: [], passed: 0, total: 0 };
22
22
 
23
- // Find all // DRIFT: comments in source code
24
- const driftComments = [];
25
- walkDir(projectDir, (filePath) => {
23
+ // v0.15-P3: when config.changedFiles is set (--changed-only mode), only
24
+ // visit the listed paths. Drift comments in unchanged files are still in
25
+ // git so they'll be caught by a full guard run; pre-commit hooks care
26
+ // about NEW drift comments in this commit.
27
+ const scanFile = (filePath) => {
26
28
  const ext = extname(filePath);
27
29
  if (!CODE_EXTENSIONS.has(ext)) return;
28
-
29
- const content = readFileSync(filePath, 'utf-8');
30
-
31
- // Fast early-return: skip expensive string split if no comment exists
30
+ // v0.15 hotfix: test files commonly contain literal `// DRIFT:` inside
31
+ // string fixtures (e.g. `'// DRIFT: a-drift\n'`). Reading the test as
32
+ // source would treat the string as a real drift comment. Skip test
33
+ // files unless the user opts in same pattern TODO-Tracking uses.
34
+ const rel = filePath.replace(projectDir + '/', '');
35
+ const includeTests = config?.drift?.includeTestFiles === true;
36
+ if (!includeTests && /(^|\/)(__tests__|tests?|spec)\/|\.(test|spec)\.[^.]+$/.test(rel)) {
37
+ return;
38
+ }
39
+ let content;
40
+ try { content = readFileSync(filePath, 'utf-8'); } catch { return; }
32
41
  if (!content.includes('DRIFT:')) return;
33
-
34
42
  const lines = content.split('\n');
35
-
36
43
  lines.forEach((line, i) => {
37
- // Match various comment styles: // DRIFT:, # DRIFT:, /* DRIFT:, -- DRIFT:
38
44
  const match = line.match(/(?:\/\/|#|\/\*|\-\-)\s*DRIFT:\s*(.+)/i);
39
45
  if (match) {
40
46
  driftComments.push({
@@ -44,7 +50,16 @@ export function validateDrift(projectDir, config) {
44
50
  });
45
51
  }
46
52
  });
47
- });
53
+ };
54
+
55
+ const driftComments = [];
56
+ if (Array.isArray(config.changedFiles) && config.changedFiles.length > 0) {
57
+ for (const rel of config.changedFiles) {
58
+ scanFile(resolve(projectDir, rel));
59
+ }
60
+ } else {
61
+ walkDir(projectDir, scanFile);
62
+ }
48
63
 
49
64
  if (driftComments.length === 0) {
50
65
  // No // DRIFT: comments to reconcile — not applicable (NOT a pass).
@@ -64,6 +64,14 @@ export function validateMetricsConsistency(projectDir, config, guardResults) {
64
64
  { key: 'validators', regex: /(?<!\d\/)\b(\d{2,})\s+validators?\b/gi, label: 'validators' },
65
65
  ];
66
66
 
67
+ // v0.14.1-N1: dedup by (file, label, found) — a file that mentions the
68
+ // stale number multiple times produces ONE warning, not one per occurrence.
69
+ // The replace-count applier already uses replace-all semantics, so a single
70
+ // fix per (file, label) is sufficient. Previously: "X.md" appearing 2× with
71
+ // the same drift would generate 2 warnings + 2 fixes (the second a no-op).
72
+ const reportedDrift = new Set(); // key: `${relPath}|${label}|${found}`
73
+ const reportedPass = new Set(); // key: `${relPath}|${label}` — only count one pass per (file, label)
74
+
67
75
  for (const mdFile of mdFiles) {
68
76
  const relPath = relative(projectDir, mdFile);
69
77
  // Skip changelog (historical numbers are fine by definition)
@@ -79,16 +87,32 @@ export function validateMetricsConsistency(projectDir, config, guardResults) {
79
87
 
80
88
  regex.lastIndex = 0;
81
89
  let match;
90
+ // Collect distinct (found-value) instances within THIS file first,
91
+ // then emit ONE warning per distinct value. A file that says "20" on
92
+ // line 5 and "20" on line 50 is the same drift; "20" on line 5 and
93
+ // "19" on line 50 are two distinct drifts.
94
+ const distinctFoundInFile = new Set();
82
95
  while ((match = regex.exec(content)) !== null) {
83
- total++;
84
- const found = parseInt(match[1], 10);
85
- if (found !== actuals[key] && found > 0) {
96
+ distinctFoundInFile.add(parseInt(match[1], 10));
97
+ }
98
+ if (distinctFoundInFile.size === 0) continue;
99
+
100
+ for (const found of distinctFoundInFile) {
101
+ if (found > 0 && found !== actuals[key]) {
102
+ const driftKey = `${relPath}|${label}|${found}`;
103
+ if (reportedDrift.has(driftKey)) continue;
104
+ reportedDrift.add(driftKey);
105
+ total++;
86
106
  warnings.push(
87
107
  `${relPath} says "${found} ${label}" but actual count is ${actuals[key]}. Fix with \`docguard fix --write\``
88
108
  );
89
- // Deterministic, surgical token replacement — safe to auto-apply.
90
109
  fixes.push({ type: 'replace-count', file: relPath, label, found, actual: actuals[key] });
91
110
  } else {
111
+ // Matches the actual count — one pass per (file, label), not per occurrence.
112
+ const passKey = `${relPath}|${label}`;
113
+ if (reportedPass.has(passKey)) continue;
114
+ reportedPass.add(passKey);
115
+ total++;
92
116
  passed++;
93
117
  }
94
118
  }
@@ -329,6 +329,20 @@ function isSelfPath(fullPath) {
329
329
  }
330
330
 
331
331
  function findTodos(rootDir, dir, todos, config) {
332
+ // v0.15-P3: when config.changedFiles is set (--changed-only mode), only
333
+ // scan those paths. New TODOs in this commit get caught; pre-existing
334
+ // TODOs in unchanged files are still tracked by full guard runs.
335
+ if (dir === rootDir && Array.isArray(config?.changedFiles) && config.changedFiles.length > 0) {
336
+ for (const rel of config.changedFiles) {
337
+ const full = resolve(rootDir, rel);
338
+ let stat;
339
+ try { stat = statSync(full); } catch { continue; }
340
+ if (!stat.isFile()) continue;
341
+ _scanTodoFile(rootDir, full, todos, config);
342
+ }
343
+ return;
344
+ }
345
+
332
346
  let entries;
333
347
  try { entries = readdirSync(dir); } catch { return; }
334
348
 
@@ -345,47 +359,44 @@ function findTodos(rootDir, dir, todos, config) {
345
359
  if (stat.isDirectory()) {
346
360
  findTodos(rootDir, full, todos, config);
347
361
  } else {
348
- const ext = extname(entry).toLowerCase();
349
- if (!SOURCE_EXTENSIONS.has(ext)) continue;
350
-
351
- const relPath = relative(rootDir, full);
352
-
353
- // Skip test files unless explicitly opted in — test fixture strings
354
- // commonly contain comment markers inside template literals that the
355
- // single-line heuristic can't distinguish from real comments.
356
- if (!includeTests && isTestFilePath(relPath)) continue;
357
-
358
- // Skip the validator's own source file — its docstring legitimately
359
- // names the annotation keywords it scans for.
360
- if (isSelfPath(full)) continue;
361
-
362
- // Apply config ignore patterns (todoIgnore + global ignore)
363
- if (config && shouldIgnore(relPath, config, 'todoIgnore')) continue;
364
-
365
- let content;
366
- try { content = readFileSync(full, 'utf-8'); } catch { continue; }
367
-
368
- // Fast early-return: skip expensive string split if no TODO patterns exist
369
- if (!TODO_PATTERN.test(content)) continue;
370
-
371
- const lines = content.split('\n');
372
-
373
- for (let i = 0; i < lines.length; i++) {
374
- // Restrict scanning to text inside a comment keeps the regex from
375
- // matching its own keyword list when DocGuard reads its own source.
376
- const commentText = commentPortion(lines[i]);
377
- if (commentText === null) continue;
378
- if (TODO_PATTERN.test(commentText)) {
379
- const match = commentText.match(TODO_EXTRACT);
380
- if (match) {
381
- todos.push({
382
- keyword: match[1].toUpperCase(),
383
- text: match[2].trim(),
384
- file: relPath,
385
- line: i + 1,
386
- });
387
- }
388
- }
362
+ _scanTodoFile(rootDir, full, todos, config);
363
+ }
364
+ }
365
+ }
366
+
367
+ /**
368
+ * v0.15-P3: per-file TODO scan extracted so both the full-tree walker and
369
+ * the --changed-only path can reuse it. Honors test-file filtering,
370
+ * self-path skip, ignore patterns, and the TODO regex.
371
+ */
372
+ function _scanTodoFile(rootDir, full, todos, config) {
373
+ const includeTests = config?.todoTracking?.includeTestFiles === true;
374
+ const ext = extname(full).toLowerCase();
375
+ if (!SOURCE_EXTENSIONS.has(ext)) return;
376
+
377
+ const relPath = relative(rootDir, full);
378
+
379
+ if (!includeTests && isTestFilePath(relPath)) return;
380
+ if (isSelfPath(full)) return;
381
+ if (config && shouldIgnore(relPath, config, 'todoIgnore')) return;
382
+
383
+ let content;
384
+ try { content = readFileSync(full, 'utf-8'); } catch { return; }
385
+ if (!TODO_PATTERN.test(content)) return;
386
+
387
+ const lines = content.split('\n');
388
+ for (let i = 0; i < lines.length; i++) {
389
+ const commentText = commentPortion(lines[i]);
390
+ if (commentText === null) continue;
391
+ if (TODO_PATTERN.test(commentText)) {
392
+ const match = commentText.match(TODO_EXTRACT);
393
+ if (match) {
394
+ todos.push({
395
+ keyword: match[1].toUpperCase(),
396
+ text: match[2].trim(),
397
+ file: relPath,
398
+ line: i + 1,
399
+ });
389
400
  }
390
401
  }
391
402
  }