docguard-cli 0.9.6__tar.gz → 0.9.7__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 (168) hide show
  1. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/.docguard.json +2 -1
  2. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/.github/workflows/spec-kit-extension.yml +1 -1
  3. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/PKG-INFO +1 -1
  4. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/cli/commands/diff.mjs +16 -3
  5. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/cli/commands/init.mjs +4 -0
  6. docguard_cli-0.9.7/cli/commands/setup.mjs +455 -0
  7. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/cli/docguard.mjs +12 -0
  8. docguard_cli-0.9.7/cli/ensure-skills.mjs +96 -0
  9. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/cli/validators/doc-quality.mjs +2 -2
  10. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/cli/validators/docs-sync.mjs +41 -6
  11. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/cli/validators/todo-tracking.mjs +11 -6
  12. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/extensions/spec-kit-docguard/README.md +13 -15
  13. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/extensions/spec-kit-docguard/extension.yml +23 -40
  14. docguard_cli-0.9.7/extensions/spec-kit-docguard/skills/docguard-fix/SKILL.md +218 -0
  15. docguard_cli-0.9.7/extensions/spec-kit-docguard/skills/docguard-guard/SKILL.md +167 -0
  16. docguard_cli-0.9.7/extensions/spec-kit-docguard/skills/docguard-review/SKILL.md +182 -0
  17. docguard_cli-0.9.7/extensions/spec-kit-docguard/skills/docguard-score/SKILL.md +178 -0
  18. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/extensions/spec-kit-docguard/templates/extensions.yml +5 -5
  19. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/package.json +1 -1
  20. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/pyproject.toml +1 -1
  21. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/.agent/commands/speckit.analyze.md +0 -0
  22. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/.agent/commands/speckit.checklist.md +0 -0
  23. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/.agent/commands/speckit.clarify.md +0 -0
  24. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/.agent/commands/speckit.constitution.md +0 -0
  25. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/.agent/commands/speckit.implement.md +0 -0
  26. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/.agent/commands/speckit.plan.md +0 -0
  27. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/.agent/commands/speckit.specify.md +0 -0
  28. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/.agent/commands/speckit.tasks.md +0 -0
  29. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/.agent/commands/speckit.taskstoissues.md +0 -0
  30. {docguard_cli-0.9.6/extensions/spec-kit-docguard → docguard_cli-0.9.7/.agent}/skills/docguard-fix/SKILL.md +0 -0
  31. {docguard_cli-0.9.6/extensions/spec-kit-docguard → docguard_cli-0.9.7/.agent}/skills/docguard-guard/SKILL.md +0 -0
  32. {docguard_cli-0.9.6/extensions/spec-kit-docguard → docguard_cli-0.9.7/.agent}/skills/docguard-review/SKILL.md +0 -0
  33. {docguard_cli-0.9.6/extensions/spec-kit-docguard → docguard_cli-0.9.7/.agent}/skills/docguard-score/SKILL.md +0 -0
  34. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/.agent/skills/speckit-analyze/SKILL.md +0 -0
  35. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/.agent/skills/speckit-checklist/SKILL.md +0 -0
  36. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/.agent/skills/speckit-clarify/SKILL.md +0 -0
  37. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/.agent/skills/speckit-constitution/SKILL.md +0 -0
  38. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/.agent/skills/speckit-implement/SKILL.md +0 -0
  39. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/.agent/skills/speckit-plan/SKILL.md +0 -0
  40. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/.agent/skills/speckit-specify/SKILL.md +0 -0
  41. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/.agent/skills/speckit-tasks/SKILL.md +0 -0
  42. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/.agent/skills/speckit-taskstoissues/SKILL.md +0 -0
  43. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/.docguardignore +0 -0
  44. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
  45. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
  46. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/.github/workflows/ci.yml +0 -0
  47. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/.gitignore +0 -0
  48. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/.npmignore +0 -0
  49. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/.specify/init-options.json +0 -0
  50. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/.specify/memory/constitution.md +0 -0
  51. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/.specify/scripts/bash/check-prerequisites.sh +0 -0
  52. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/.specify/scripts/bash/common.sh +0 -0
  53. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/.specify/scripts/bash/create-new-feature.sh +0 -0
  54. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/.specify/scripts/bash/setup-plan.sh +0 -0
  55. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/.specify/scripts/bash/update-agent-context.sh +0 -0
  56. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/.specify/templates/agent-file-template.md +0 -0
  57. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/.specify/templates/checklist-template.md +0 -0
  58. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/.specify/templates/constitution-template.md +0 -0
  59. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/.specify/templates/plan-template.md +0 -0
  60. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/.specify/templates/spec-template.md +0 -0
  61. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/.specify/templates/tasks-template.md +0 -0
  62. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/AGENTS.md +0 -0
  63. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/CHANGELOG.md +0 -0
  64. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/CODE_OF_CONDUCT.md +0 -0
  65. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/COMPARISONS.md +0 -0
  66. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/CONTRIBUTING.md +0 -0
  67. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/DRIFT-LOG.md +0 -0
  68. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/LICENSE +0 -0
  69. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/PHILOSOPHY.md +0 -0
  70. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/README.md +0 -0
  71. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/ROADMAP.md +0 -0
  72. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/SECURITY.md +0 -0
  73. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/STANDARD.md +0 -0
  74. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/SUPPORT.md +0 -0
  75. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/action.yml +0 -0
  76. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/cli/commands/agents.mjs +0 -0
  77. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/cli/commands/badge.mjs +0 -0
  78. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/cli/commands/ci.mjs +0 -0
  79. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/cli/commands/diagnose.mjs +0 -0
  80. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/cli/commands/fix.mjs +0 -0
  81. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/cli/commands/generate.mjs +0 -0
  82. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/cli/commands/guard.mjs +0 -0
  83. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/cli/commands/hooks.mjs +0 -0
  84. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/cli/commands/llms.mjs +0 -0
  85. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/cli/commands/publish.mjs +0 -0
  86. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/cli/commands/score.mjs +0 -0
  87. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/cli/commands/trace.mjs +0 -0
  88. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/cli/commands/watch.mjs +0 -0
  89. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/cli/scanners/doc-tools.mjs +0 -0
  90. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/cli/scanners/routes.mjs +0 -0
  91. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/cli/scanners/schemas.mjs +0 -0
  92. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/cli/scanners/speckit.mjs +0 -0
  93. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/cli/shared.mjs +0 -0
  94. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/cli/validators/architecture.mjs +0 -0
  95. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/cli/validators/changelog.mjs +0 -0
  96. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/cli/validators/docs-coverage.mjs +0 -0
  97. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/cli/validators/docs-diff.mjs +0 -0
  98. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/cli/validators/drift.mjs +0 -0
  99. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/cli/validators/environment.mjs +0 -0
  100. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/cli/validators/freshness.mjs +0 -0
  101. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/cli/validators/metadata-sync.mjs +0 -0
  102. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/cli/validators/metrics-consistency.mjs +0 -0
  103. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/cli/validators/schema-sync.mjs +0 -0
  104. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/cli/validators/security.mjs +0 -0
  105. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/cli/validators/structure.mjs +0 -0
  106. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/cli/validators/test-spec.mjs +0 -0
  107. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/cli/validators/traceability.mjs +0 -0
  108. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/commands/docguard.fix.md +0 -0
  109. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/commands/docguard.guard.md +0 -0
  110. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/commands/docguard.review.md +0 -0
  111. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/commands/docguard.score.md +0 -0
  112. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/configs/fastify.json +0 -0
  113. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/configs/generic.json +0 -0
  114. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/configs/nextjs.json +0 -0
  115. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/configs/python.json +0 -0
  116. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/docguard_cli/__init__.py +0 -0
  117. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/docguard_cli/wrapper.py +0 -0
  118. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/docs/ai-integration.md +0 -0
  119. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/docs/commands.md +0 -0
  120. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/docs/configuration.md +0 -0
  121. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/docs/faq.md +0 -0
  122. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/docs/installation.md +0 -0
  123. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/docs/profiles.md +0 -0
  124. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/docs/quickstart.md +0 -0
  125. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/docs-canonical/ARCHITECTURE.md +0 -0
  126. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/docs-canonical/DATA-MODEL.md +0 -0
  127. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/docs-canonical/ENVIRONMENT.md +0 -0
  128. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/docs-canonical/SECURITY.md +0 -0
  129. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/docs-canonical/TEST-SPEC.md +0 -0
  130. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/extensions/spec-kit-docguard/LICENSE +0 -0
  131. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/extensions/spec-kit-docguard/commands/diagnose.md +0 -0
  132. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/extensions/spec-kit-docguard/commands/generate.md +0 -0
  133. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/extensions/spec-kit-docguard/commands/guard.md +0 -0
  134. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/extensions/spec-kit-docguard/commands/init.md +0 -0
  135. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/extensions/spec-kit-docguard/commands/score.md +0 -0
  136. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/extensions/spec-kit-docguard/commands/trace.md +0 -0
  137. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/extensions/spec-kit-docguard/scripts/bash/common.sh +0 -0
  138. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/extensions/spec-kit-docguard/scripts/bash/docguard-check-docs.sh +0 -0
  139. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/extensions/spec-kit-docguard/scripts/bash/docguard-init-doc.sh +0 -0
  140. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/extensions/spec-kit-docguard/scripts/bash/docguard-suggest-fix.sh +0 -0
  141. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/templates/ADR.md.template +0 -0
  142. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/templates/AGENTS.md.template +0 -0
  143. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/templates/ARCHITECTURE.md.template +0 -0
  144. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/templates/CHANGELOG.md.template +0 -0
  145. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/templates/CURRENT-STATE.md.template +0 -0
  146. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/templates/DATA-MODEL.md.template +0 -0
  147. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/templates/DEPLOYMENT.md.template +0 -0
  148. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/templates/DRIFT-LOG.md.template +0 -0
  149. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/templates/ENVIRONMENT.md.template +0 -0
  150. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/templates/KNOWN-GOTCHAS.md.template +0 -0
  151. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/templates/REQUIREMENTS.md.template +0 -0
  152. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/templates/ROADMAP.md.template +0 -0
  153. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/templates/RUNBOOKS.md.template +0 -0
  154. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/templates/SECURITY.md.template +0 -0
  155. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/templates/TEST-SPEC.md.template +0 -0
  156. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/templates/TROUBLESHOOTING.md.template +0 -0
  157. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/templates/VENDOR-BUGS.md.template +0 -0
  158. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/templates/ci/github-actions.yml +0 -0
  159. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/templates/commands/docguard.fix.md +0 -0
  160. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/templates/commands/docguard.guard.md +0 -0
  161. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/templates/commands/docguard.init.md +0 -0
  162. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/templates/commands/docguard.review.md +0 -0
  163. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/templates/commands/docguard.update.md +0 -0
  164. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/tests/commands.test.mjs +0 -0
  165. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/vscode-extension/.vscodeignore +0 -0
  166. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/vscode-extension/README.md +0 -0
  167. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/vscode-extension/extension.js +0 -0
  168. {docguard_cli-0.9.6 → docguard_cli-0.9.7}/vscode-extension/package.json +0 -0
@@ -1,6 +1,7 @@
1
1
  {
2
2
  "projectName": "docguard",
3
- "version": "0.3",
3
+ "version": "0.4",
4
+ "profile": "enterprise",
4
5
 
5
6
  "projectType": "cli",
6
7
 
@@ -19,7 +19,7 @@ jobs:
19
19
 
20
20
  - name: Sync version in extension.yml
21
21
  run: |
22
- sed -i "s/version: \".*\"/version: \"${GITHUB_REF_NAME#v}\"/" extensions/spec-kit-docguard/extension.yml
22
+ sed -i 's/^ version: ".*"/ version: "'"${GITHUB_REF_NAME#v}"'"/' extensions/spec-kit-docguard/extension.yml
23
23
  echo "Updated extension.yml to version ${GITHUB_REF_NAME#v}"
24
24
  grep 'version:' extensions/spec-kit-docguard/extension.yml
25
25
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: docguard-cli
3
- Version: 0.9.6
3
+ Version: 0.9.7
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
@@ -157,7 +157,12 @@ function diffEntities(dir) {
157
157
  'EntityName', 'Entity', 'metadata', 'tbd', 'cascade', 'fields',
158
158
  'purpose', 'version', 'author', 'example', 'TODO', 'Overview',
159
159
  'Revision', 'History', 'Entities', 'Relationships', 'Indexes',
160
- 'Migration', 'Strategy',
160
+ 'Migration', 'Strategy', 'Trade-offs', 'Tradeoffs', 'Notes',
161
+ 'Summary', 'Details', 'Configuration', 'Setup', 'Reference',
162
+ 'Appendix', 'Glossary', 'FAQ', 'Introduction', 'Background',
163
+ 'Prerequisites', 'Requirements', 'Assumptions', 'Constraints',
164
+ 'Dependencies', 'Architecture', 'Design', 'Implementation',
165
+ 'Testing', 'Deployment', 'Monitoring', 'Operations', 'Security',
161
166
  ]);
162
167
 
163
168
  const headerRegex = /^### (\S+)/gm;
@@ -165,9 +170,11 @@ function diffEntities(dir) {
165
170
  while ((match = headerRegex.exec(content)) !== null) {
166
171
  const name = match[1].replace(/[`*]/g, '');
167
172
  // Skip template placeholders (<!-- ... -->) and noise words
168
- if (name.startsWith('<!--') || name.length <= 1 || HEADER_NOISE.has(name) || HEADER_NOISE.has(name.toLowerCase())) {
173
+ if (name.startsWith('<!--') || name.length <= 2 || HEADER_NOISE.has(name) || HEADER_NOISE.has(name.toLowerCase())) {
169
174
  continue;
170
175
  }
176
+ // Skip hyphenated words (e.g., 'Trade-offs', 'Set-up') — these are section titles, not entities
177
+ if (name.includes('-')) continue;
171
178
  docEntities.add(name.toLowerCase());
172
179
  }
173
180
 
@@ -194,10 +201,16 @@ function diffEntities(dir) {
194
201
  // Common table headers and template words
195
202
  'true', 'false', 'header', 'checks', 'project', 'count', 'grade',
196
203
  'breakdown', 'issuecount', 'autofixable', 'projectname', 'projecttype',
204
+ // Common doc section words (not entity names)
205
+ 'trade', 'offs', 'tradeoffs', 'setup', 'overview', 'summary',
206
+ 'details', 'configuration', 'reference', 'pattern', 'patterns',
207
+ 'strategy', 'approach', 'impact', 'benefit', 'risk', 'concern',
208
+ 'action', 'result', 'outcome', 'inverted', 'composite', 'secondary',
197
209
  ]);
198
210
  while ((match = tableRegex.exec(content)) !== null) {
199
211
  const name = match[1];
200
- if (name.length > 2 && !TABLE_NOISE.has(name.toLowerCase())) {
212
+ // Skip short names (<=3 chars) and noise words
213
+ if (name.length > 3 && !TABLE_NOISE.has(name.toLowerCase())) {
201
214
  docEntities.add(name.toLowerCase());
202
215
  }
203
216
  }
@@ -8,6 +8,7 @@ import { resolve, dirname } from 'node:path';
8
8
  import { fileURLToPath } from 'node:url';
9
9
  import { createInterface } from 'node:readline';
10
10
  import { c, PROFILES } from '../shared.mjs';
11
+ import { ensureSkills } from '../ensure-skills.mjs';
11
12
 
12
13
  function detectProjectType(dir) {
13
14
  const pkgPath = resolve(dir, 'package.json');
@@ -285,4 +286,7 @@ export async function runInit(projectDir, config, flags) {
285
286
  } else {
286
287
  console.log(`\n ${c.dim}Run${c.reset} ${c.cyan}docguard diagnose${c.reset} ${c.dim}to check for issues.${c.reset}\n`);
287
288
  }
289
+
290
+ // Auto-install skills and commands
291
+ ensureSkills(projectDir, flags);
288
292
  }
@@ -0,0 +1,455 @@
1
+ /**
2
+ * Setup Command — Interactive onboarding wizard for DocGuard
3
+ *
4
+ * Walks through 7 steps to ensure DocGuard is fully configured:
5
+ * 1. Project detection & config
6
+ * 2. Canonical docs
7
+ * 3. AI skills
8
+ * 4. Slash commands
9
+ * 5. Agent configs
10
+ * 6. External integrations (spec-kit, understanding)
11
+ * 7. Git hooks
12
+ *
13
+ * Each step shows current status (✅/⚠️) and offers to fix what's missing.
14
+ * Supports --skip-prompts for non-interactive CI mode.
15
+ *
16
+ * Zero dependencies — pure Node.js built-ins only.
17
+ */
18
+
19
+ import { existsSync, mkdirSync, readFileSync, writeFileSync, readdirSync } from 'node:fs';
20
+ import { resolve, dirname, basename } from 'node:path';
21
+ import { fileURLToPath } from 'node:url';
22
+ import { createInterface } from 'node:readline';
23
+ import { execSync } from 'node:child_process';
24
+ import { c } from '../shared.mjs';
25
+ import { ensureSkills } from '../ensure-skills.mjs';
26
+
27
+ const __filename = fileURLToPath(import.meta.url);
28
+ const __dirname = dirname(__filename);
29
+ const TEMPLATES_DIR = resolve(__dirname, '../../templates');
30
+ const SKILLS_SOURCE = resolve(__dirname, '../../extensions/spec-kit-docguard/skills');
31
+ const COMMANDS_SOURCE = resolve(__dirname, '../../commands');
32
+
33
+ // ── Readline Helper ─────────────────────────────────────────────────────
34
+
35
+ function askQuestion(prompt) {
36
+ const rl = createInterface({ input: process.stdin, output: process.stdout });
37
+ return new Promise(res => {
38
+ rl.question(prompt, answer => {
39
+ rl.close();
40
+ res(answer.trim().toLowerCase());
41
+ });
42
+ });
43
+ }
44
+
45
+ async function askYesNo(prompt, defaultYes = true) {
46
+ const label = defaultYes ? 'Y/n' : 'y/N';
47
+ const answer = await askQuestion(`${prompt} [${label}]: `);
48
+ if (answer === '') return defaultYes;
49
+ return answer === 'y' || answer === 'yes';
50
+ }
51
+
52
+ // ── Project Type Detection ──────────────────────────────────────────────
53
+
54
+ function detectProjectType(dir) {
55
+ const pkgPath = resolve(dir, 'package.json');
56
+ if (existsSync(pkgPath)) {
57
+ try {
58
+ const pkg = JSON.parse(readFileSync(pkgPath, 'utf-8'));
59
+ const allDeps = { ...(pkg.dependencies || {}), ...(pkg.devDependencies || {}) };
60
+ if (pkg.bin) return 'cli';
61
+ if (allDeps.next || allDeps.react || allDeps.vue || allDeps['@angular/core'] ||
62
+ allDeps.svelte || allDeps.nuxt) return 'webapp';
63
+ if (allDeps.express || allDeps.fastify || allDeps.hono || allDeps.koa) return 'api';
64
+ if (pkg.main || pkg.exports || pkg.module) return 'library';
65
+ } catch { /* fall through */ }
66
+ }
67
+ if (existsSync(resolve(dir, 'manage.py'))) return 'webapp';
68
+ if (existsSync(resolve(dir, 'setup.py')) || existsSync(resolve(dir, 'pyproject.toml'))) return 'library';
69
+ return 'unknown';
70
+ }
71
+
72
+ // ── CLI Detection ───────────────────────────────────────────────────────
73
+
74
+ function isCliAvailable(name) {
75
+ try {
76
+ const cmd = process.platform === 'win32' ? `where ${name}` : `which ${name}`;
77
+ execSync(`${cmd} 2>/dev/null`, { encoding: 'utf-8', timeout: 3000 });
78
+ return true;
79
+ } catch {
80
+ return false;
81
+ }
82
+ }
83
+
84
+ function detectAgentDirs(projectDir) {
85
+ const agentDirs = [
86
+ { name: 'GitHub Copilot', dir: '.github', commandsPath: '.github/commands' },
87
+ { name: 'Cursor', dir: '.cursor', commandsPath: '.cursor/rules' },
88
+ { name: 'Google Gemini', dir: '.gemini', commandsPath: '.gemini/commands' },
89
+ { name: 'Claude Code', dir: '.claude', commandsPath: '.claude/commands' },
90
+ { name: 'Antigravity', dir: '.agents', commandsPath: '.agents/workflows' },
91
+ ];
92
+
93
+ return agentDirs.filter(a => existsSync(resolve(projectDir, a.dir)));
94
+ }
95
+
96
+ // ── Main Setup Wizard ───────────────────────────────────────────────────
97
+
98
+ export async function runSetup(projectDir, config, flags) {
99
+ console.log(`${c.bold}🧙 DocGuard Setup Wizard${c.reset}`);
100
+ console.log(`${c.dim} Directory: ${projectDir}${c.reset}\n`);
101
+
102
+ const interactive = !flags.skipPrompts;
103
+ let configured = 0;
104
+ let alreadyGood = 0;
105
+
106
+ // ── Step 1: Project Detection & Config ──────────────────────────────
107
+
108
+ console.log(` ${c.bold}Step 1/7: Project Detection${c.reset}`);
109
+
110
+ const detectedType = detectProjectType(projectDir);
111
+ console.log(` ${c.green}✅${c.reset} Project type: ${c.cyan}${detectedType}${c.reset}`);
112
+
113
+ const configPath = resolve(projectDir, '.docguard.json');
114
+ if (existsSync(configPath)) {
115
+ const cfg = JSON.parse(readFileSync(configPath, 'utf-8'));
116
+ console.log(` ${c.green}✅${c.reset} .docguard.json exists (profile: ${c.cyan}${cfg.profile || 'standard'}${c.reset})`);
117
+ alreadyGood++;
118
+ } else {
119
+ console.log(` ${c.yellow}⚠️${c.reset} .docguard.json missing`);
120
+ const create = interactive
121
+ ? await askYesNo(` → Create config file?`)
122
+ : true;
123
+
124
+ if (create) {
125
+ const typeDefaults = {
126
+ cli: { needsEnvVars: false, needsEnvExample: false, needsE2E: false, needsDatabase: false },
127
+ library: { needsEnvVars: false, needsEnvExample: false, needsE2E: false, needsDatabase: false },
128
+ webapp: { needsEnvVars: true, needsEnvExample: true, needsE2E: true, needsDatabase: true },
129
+ api: { needsEnvVars: true, needsEnvExample: true, needsE2E: false, needsDatabase: true },
130
+ unknown: { needsEnvVars: true, needsEnvExample: true, needsE2E: false, needsDatabase: true },
131
+ };
132
+
133
+ const defaultConfig = {
134
+ projectName: config.projectName,
135
+ version: '0.4',
136
+ profile: 'standard',
137
+ projectType: detectedType,
138
+ projectTypeConfig: typeDefaults[detectedType] || typeDefaults.unknown,
139
+ };
140
+
141
+ writeFileSync(configPath, JSON.stringify(defaultConfig, null, 2) + '\n', 'utf-8');
142
+ console.log(` ${c.green}✅ Created .docguard.json${c.reset}`);
143
+ configured++;
144
+ }
145
+ }
146
+
147
+ console.log('');
148
+
149
+ // ── Step 2: Canonical Docs ──────────────────────────────────────────
150
+
151
+ console.log(` ${c.bold}Step 2/7: Canonical Docs${c.reset}`);
152
+
153
+ const canonicalDocs = [
154
+ { file: 'docs-canonical/ARCHITECTURE.md', template: 'ARCHITECTURE.md.template', label: 'Architecture', defaultYes: true },
155
+ { file: 'docs-canonical/DATA-MODEL.md', template: 'DATA-MODEL.md.template', label: 'Data Model', defaultYes: ['webapp', 'api'].includes(detectedType) },
156
+ { file: 'docs-canonical/SECURITY.md', template: 'SECURITY.md.template', label: 'Security', defaultYes: ['webapp', 'api'].includes(detectedType) },
157
+ { file: 'docs-canonical/TEST-SPEC.md', template: 'TEST-SPEC.md.template', label: 'Test Spec', defaultYes: true },
158
+ { file: 'docs-canonical/ENVIRONMENT.md', template: 'ENVIRONMENT.md.template', label: 'Environment', defaultYes: ['webapp', 'api'].includes(detectedType) },
159
+ { file: 'docs-canonical/REQUIREMENTS.md', template: 'REQUIREMENTS.md.template', label: 'Requirements', defaultYes: true },
160
+ ];
161
+
162
+ const trackingFiles = [
163
+ { file: 'AGENTS.md', template: 'AGENTS.md.template', label: 'Agent Instructions' },
164
+ { file: 'CHANGELOG.md', template: 'CHANGELOG.md.template', label: 'Changelog' },
165
+ { file: 'DRIFT-LOG.md', template: 'DRIFT-LOG.md.template', label: 'Drift Log' },
166
+ ];
167
+
168
+ let missingDocs = [];
169
+
170
+ // Check canonical docs
171
+ for (const doc of [...canonicalDocs, ...trackingFiles]) {
172
+ const fullPath = resolve(projectDir, doc.file);
173
+ if (existsSync(fullPath)) {
174
+ console.log(` ${c.green}✅${c.reset} ${doc.file}`);
175
+ alreadyGood++;
176
+ } else {
177
+ console.log(` ${c.yellow}⚠️${c.reset} ${doc.file} ${c.dim}(missing)${c.reset}`);
178
+ missingDocs.push(doc);
179
+ }
180
+ }
181
+
182
+ if (missingDocs.length > 0) {
183
+ const create = interactive
184
+ ? await askYesNo(` → Create ${missingDocs.length} missing doc(s) from templates?`)
185
+ : true;
186
+
187
+ if (create) {
188
+ const today = new Date().toISOString().split('T')[0];
189
+ for (const doc of missingDocs) {
190
+ const destPath = resolve(projectDir, doc.file);
191
+ const templatePath = resolve(TEMPLATES_DIR, doc.template);
192
+
193
+ const destDir = dirname(destPath);
194
+ if (!existsSync(destDir)) {
195
+ mkdirSync(destDir, { recursive: true });
196
+ }
197
+
198
+ if (existsSync(templatePath)) {
199
+ const content = readFileSync(templatePath, 'utf-8').replace(/YYYY-MM-DD/g, today);
200
+ writeFileSync(destPath, content, 'utf-8');
201
+ console.log(` ${c.green}✅ Created ${doc.file}${c.reset}`);
202
+ configured++;
203
+ }
204
+ }
205
+ }
206
+ }
207
+
208
+ console.log('');
209
+
210
+ // ── Step 3: AI Skills ──────────────────────────────────────────────
211
+
212
+ console.log(` ${c.bold}Step 3/7: AI Skills${c.reset}`);
213
+
214
+ const skillNames = ['docguard-guard', 'docguard-fix', 'docguard-review', 'docguard-score'];
215
+ const skillsDest = resolve(projectDir, '.agent/skills');
216
+ let missingSkills = [];
217
+
218
+ for (const skill of skillNames) {
219
+ const skillPath = resolve(skillsDest, skill, 'SKILL.md');
220
+ if (existsSync(skillPath)) {
221
+ console.log(` ${c.green}✅${c.reset} ${skill}`);
222
+ alreadyGood++;
223
+ } else {
224
+ console.log(` ${c.yellow}⚠️${c.reset} ${skill} ${c.dim}(not installed)${c.reset}`);
225
+ missingSkills.push(skill);
226
+ }
227
+ }
228
+
229
+ if (missingSkills.length > 0) {
230
+ const install = interactive
231
+ ? await askYesNo(` → Install ${missingSkills.length} AI skill(s) to .agent/skills/?`)
232
+ : true;
233
+
234
+ if (install) {
235
+ for (const skill of missingSkills) {
236
+ const srcSkill = resolve(SKILLS_SOURCE, skill, 'SKILL.md');
237
+ const destDir = resolve(skillsDest, skill);
238
+ if (existsSync(srcSkill)) {
239
+ if (!existsSync(destDir)) mkdirSync(destDir, { recursive: true });
240
+ writeFileSync(resolve(destDir, 'SKILL.md'), readFileSync(srcSkill, 'utf-8'), 'utf-8');
241
+ console.log(` ${c.green}✅ Installed ${skill}${c.reset}`);
242
+ configured++;
243
+ }
244
+ }
245
+ }
246
+ }
247
+
248
+ console.log('');
249
+
250
+ // ── Step 4: Slash Commands ─────────────────────────────────────────
251
+
252
+ console.log(` ${c.bold}Step 4/7: Slash Commands${c.reset}`);
253
+
254
+ // Check root commands/ dir
255
+ const rootCommandsDir = resolve(projectDir, 'commands');
256
+ const rootCommandsExist = existsSync(resolve(rootCommandsDir, 'docguard.guard.md'));
257
+
258
+ if (rootCommandsExist) {
259
+ console.log(` ${c.green}✅${c.reset} commands/ ${c.dim}(root)${c.reset}`);
260
+ alreadyGood++;
261
+ } else {
262
+ console.log(` ${c.yellow}⚠️${c.reset} commands/ ${c.dim}(not installed)${c.reset}`);
263
+ }
264
+
265
+ // Detect agent directories and sync commands
266
+ const detectedAgents = detectAgentDirs(projectDir);
267
+ let unsyncedAgents = [];
268
+
269
+ for (const agent of detectedAgents) {
270
+ const agentCommandCheck = resolve(projectDir, agent.commandsPath, 'docguard.guard.md');
271
+ if (existsSync(agentCommandCheck)) {
272
+ console.log(` ${c.green}✅${c.reset} ${agent.commandsPath}/ ${c.dim}(${agent.name})${c.reset}`);
273
+ alreadyGood++;
274
+ } else {
275
+ console.log(` ${c.yellow}⚠️${c.reset} ${agent.commandsPath}/ ${c.dim}(${agent.name} — not synced)${c.reset}`);
276
+ unsyncedAgents.push(agent);
277
+ }
278
+ }
279
+
280
+ const needsCommands = !rootCommandsExist || unsyncedAgents.length > 0;
281
+
282
+ if (needsCommands && existsSync(COMMANDS_SOURCE)) {
283
+ const install = interactive
284
+ ? await askYesNo(` → Install/sync slash commands?`)
285
+ : true;
286
+
287
+ if (install) {
288
+ const commandFiles = readdirSync(COMMANDS_SOURCE).filter(f => f.endsWith('.md'));
289
+
290
+ // Install to root commands/
291
+ if (!rootCommandsExist) {
292
+ if (!existsSync(rootCommandsDir)) mkdirSync(rootCommandsDir, { recursive: true });
293
+ for (const file of commandFiles) {
294
+ const destPath = resolve(rootCommandsDir, file);
295
+ if (!existsSync(destPath)) {
296
+ writeFileSync(destPath, readFileSync(resolve(COMMANDS_SOURCE, file), 'utf-8'), 'utf-8');
297
+ }
298
+ }
299
+ console.log(` ${c.green}✅ Installed to commands/${c.reset}`);
300
+ configured++;
301
+ }
302
+
303
+ // Sync to agent-specific dirs
304
+ for (const agent of unsyncedAgents) {
305
+ const destDir = resolve(projectDir, agent.commandsPath);
306
+ if (!existsSync(destDir)) mkdirSync(destDir, { recursive: true });
307
+ for (const file of commandFiles) {
308
+ const destPath = resolve(destDir, file);
309
+ if (!existsSync(destPath)) {
310
+ writeFileSync(destPath, readFileSync(resolve(COMMANDS_SOURCE, file), 'utf-8'), 'utf-8');
311
+ }
312
+ }
313
+ console.log(` ${c.green}✅ Synced to ${agent.commandsPath}/ (${agent.name})${c.reset}`);
314
+ configured++;
315
+ }
316
+ }
317
+ }
318
+
319
+ console.log('');
320
+
321
+ // ── Step 5: Agent Configs ──────────────────────────────────────────
322
+
323
+ console.log(` ${c.bold}Step 5/7: Agent Configs${c.reset}`);
324
+
325
+ const agentConfigs = [
326
+ { file: 'AGENTS.md', label: 'Agent Instructions' },
327
+ { file: 'CLAUDE.md', label: 'Claude Code' },
328
+ { file: '.cursor/rules/cdd.mdc', label: 'Cursor' },
329
+ { file: '.github/copilot-instructions.md', label: 'GitHub Copilot' },
330
+ ];
331
+
332
+ let missingConfigs = [];
333
+ for (const cfg of agentConfigs) {
334
+ const fullPath = resolve(projectDir, cfg.file);
335
+ if (existsSync(fullPath)) {
336
+ console.log(` ${c.green}✅${c.reset} ${cfg.file} ${c.dim}(${cfg.label})${c.reset}`);
337
+ alreadyGood++;
338
+ } else {
339
+ // AGENTS.md is handled in step 2, skip it here
340
+ if (cfg.file !== 'AGENTS.md') {
341
+ console.log(` ${c.dim}──${c.reset} ${cfg.file} ${c.dim}(${cfg.label} — not generated)${c.reset}`);
342
+ missingConfigs.push(cfg);
343
+ }
344
+ }
345
+ }
346
+
347
+ if (missingConfigs.length > 0) {
348
+ console.log(` ${c.dim} Run ${c.cyan}docguard agents${c.dim} to generate agent-specific configs${c.reset}`);
349
+ }
350
+
351
+ console.log('');
352
+
353
+ // ── Step 6: Integrations ───────────────────────────────────────────
354
+
355
+ console.log(` ${c.bold}Step 6/7: Integrations${c.reset}`);
356
+
357
+ // Check spec-kit framework
358
+ const speckitDir = resolve(projectDir, '.speckit');
359
+ const hasSpeckit = existsSync(speckitDir) || existsSync(resolve(projectDir, 'spec.md'));
360
+ if (hasSpeckit) {
361
+ console.log(` ${c.green}✅${c.reset} spec-kit ${c.dim}(spec-driven development configured)${c.reset}`);
362
+ alreadyGood++;
363
+ } else {
364
+ console.log(` ${c.dim}──${c.reset} spec-kit ${c.dim}(not configured — optional)${c.reset}`);
365
+ console.log(` ${c.dim} Spec Kit enables spec-driven development with AI agents${c.reset}`);
366
+ console.log(` ${c.dim} See: ${c.cyan}https://github.com/github/spec-kit${c.reset}`);
367
+ }
368
+
369
+ // Check for spec-kit extensions
370
+ const extensionsDir = resolve(projectDir, 'extensions');
371
+
372
+ // DocGuard extension (this project IS DocGuard, so check if extension is bundled)
373
+ const docguardExt = resolve(extensionsDir, 'spec-kit-docguard', 'extension.yml');
374
+ if (existsSync(docguardExt)) {
375
+ console.log(` ${c.green}✅${c.reset} docguard extension ${c.dim}(spec-kit CDD enforcement)${c.reset}`);
376
+ alreadyGood++;
377
+ } else {
378
+ // DocGuard is installed as a CLI, not necessarily as a spec-kit extension
379
+ console.log(` ${c.green}✅${c.reset} docguard CLI ${c.dim}(standalone — 19 validators + 31 quality metrics)${c.reset}`);
380
+ alreadyGood++;
381
+ }
382
+
383
+ // Understanding extension (spec-kit community extension)
384
+ const understandingExt = resolve(extensionsDir, 'spec-kit-understanding', 'extension.yml');
385
+ if (existsSync(understandingExt)) {
386
+ console.log(` ${c.green}✅${c.reset} understanding ${c.dim}(spec-kit deep doc analysis)${c.reset}`);
387
+ alreadyGood++;
388
+ } else {
389
+ console.log(` ${c.dim}──${c.reset} understanding ${c.dim}(spec-kit extension — optional)${c.reset}`);
390
+ console.log(` ${c.dim} Install via spec-kit: ${c.cyan}https://github.com/github/spec-kit/tree/main/extensions${c.reset}`);
391
+ }
392
+
393
+ console.log('');
394
+
395
+ // ── Step 7: Git Hooks ──────────────────────────────────────────────
396
+
397
+ console.log(` ${c.bold}Step 7/7: Git Hooks${c.reset}`);
398
+
399
+ const gitDir = resolve(projectDir, '.git');
400
+ if (!existsSync(gitDir)) {
401
+ console.log(` ${c.dim}──${c.reset} No .git directory ${c.dim}(not a git repo)${c.reset}`);
402
+ } else {
403
+ const preCommitHook = resolve(gitDir, 'hooks', 'pre-commit');
404
+ let hasDocguardHook = false;
405
+
406
+ if (existsSync(preCommitHook)) {
407
+ const content = readFileSync(preCommitHook, 'utf-8');
408
+ hasDocguardHook = content.includes('docguard');
409
+ }
410
+
411
+ if (hasDocguardHook) {
412
+ console.log(` ${c.green}✅${c.reset} pre-commit hook ${c.dim}(docguard guard)${c.reset}`);
413
+ alreadyGood++;
414
+ } else {
415
+ console.log(` ${c.dim}──${c.reset} pre-commit hook ${c.dim}(not installed)${c.reset}`);
416
+ if (interactive) {
417
+ const install = await askYesNo(` → Install docguard guard as pre-commit hook?`, false);
418
+ if (install) {
419
+ try {
420
+ const hooksDir = resolve(gitDir, 'hooks');
421
+ if (!existsSync(hooksDir)) mkdirSync(hooksDir, { recursive: true });
422
+
423
+ const hookContent = existsSync(preCommitHook)
424
+ ? readFileSync(preCommitHook, 'utf-8') + '\n\n# DocGuard CDD validation\nnpx docguard guard --fail-on-warning\n'
425
+ : '#!/bin/sh\n\n# DocGuard CDD validation\nnpx docguard guard --fail-on-warning\n';
426
+
427
+ writeFileSync(preCommitHook, hookContent, { mode: 0o755 });
428
+ console.log(` ${c.green}✅ Pre-commit hook installed${c.reset}`);
429
+ configured++;
430
+ } catch (e) {
431
+ console.log(` ${c.yellow}⚠️ Failed to install hook: ${e.message}${c.reset}`);
432
+ }
433
+ }
434
+ }
435
+ }
436
+ }
437
+
438
+ // ── Summary ────────────────────────────────────────────────────────
439
+
440
+ console.log(`\n ${c.bold}─────────────────────────────────────${c.reset}`);
441
+
442
+ if (configured > 0) {
443
+ console.log(` ${c.green}✅ Setup complete!${c.reset} ${configured} item(s) configured, ${alreadyGood} already good.`);
444
+ } else if (alreadyGood > 0) {
445
+ console.log(` ${c.green}✅ Everything is set up!${c.reset} ${alreadyGood} item(s) verified.`);
446
+ } else {
447
+ console.log(` ${c.dim}No changes made.${c.reset}`);
448
+ }
449
+
450
+ console.log(`\n ${c.bold}Next steps:${c.reset}`);
451
+ console.log(` ${c.dim}Fill docs:${c.reset} ${c.cyan}docguard diagnose${c.reset}`);
452
+ console.log(` ${c.dim}Validate:${c.reset} ${c.cyan}docguard guard${c.reset}`);
453
+ console.log(` ${c.dim}Check score:${c.reset} ${c.cyan}docguard score${c.reset}`);
454
+ console.log('');
455
+ }
@@ -38,6 +38,8 @@ import { runDiagnose } from './commands/diagnose.mjs';
38
38
  import { runPublish } from './commands/publish.mjs';
39
39
  import { runTrace } from './commands/trace.mjs';
40
40
  import { runLlms } from './commands/llms.mjs';
41
+ import { runSetup } from './commands/setup.mjs';
42
+ import { ensureSkills } from './ensure-skills.mjs';
41
43
 
42
44
  // ── Shared constants (imported to break circular dependencies) ──────────
43
45
  import { c, PROFILES } from './shared.mjs';
@@ -218,6 +220,7 @@ function printHelp() {
218
220
 
219
221
  ${c.bold}Getting Started:${c.reset}
220
222
  ${c.green}init${c.reset} Initialize CDD docs (interactive setup)
223
+ ${c.green}setup${c.reset} Full onboarding wizard (skills, integrations, hooks)
221
224
  ${c.green}generate${c.reset} Reverse-engineer canonical docs from existing code
222
225
 
223
226
  ${c.bold}Enforcement:${c.reset}
@@ -376,6 +379,11 @@ async function main() {
376
379
 
377
380
  const config = loadConfig(projectDir);
378
381
 
382
+ // Silent auto-check: install skills/commands if missing
383
+ if (command !== 'setup' && command !== 'init') {
384
+ ensureSkills(projectDir, flags);
385
+ }
386
+
379
387
  switch (command) {
380
388
  case 'audit':
381
389
  // audit is an alias for guard — guard does everything the old audit did + 50 more checks
@@ -384,6 +392,10 @@ async function main() {
384
392
  case 'init':
385
393
  await runInit(projectDir, config, flags);
386
394
  break;
395
+ case 'setup':
396
+ case 'onboard':
397
+ await runSetup(projectDir, config, flags);
398
+ break;
387
399
  case 'guard':
388
400
  runGuard(projectDir, config, flags);
389
401
  break;
@@ -0,0 +1,96 @@
1
+ /**
2
+ * Ensure Skills — Silent auto-check for DocGuard AI skills and commands
3
+ *
4
+ * Called before every command execution. If skills or commands are missing,
5
+ * copies them from the package's bundled assets into the project directory.
6
+ *
7
+ * Zero dependencies — pure Node.js built-ins only.
8
+ */
9
+
10
+ import { existsSync, mkdirSync, readFileSync, writeFileSync, readdirSync, cpSync } from 'node:fs';
11
+ import { resolve, dirname, join } from 'node:path';
12
+ import { fileURLToPath } from 'node:url';
13
+ import { c } from './shared.mjs';
14
+
15
+ const __filename = fileURLToPath(import.meta.url);
16
+ const __dirname = dirname(__filename);
17
+
18
+ // Source locations in the npm package
19
+ const SKILLS_SOURCE = resolve(__dirname, '..', 'extensions', 'spec-kit-docguard', 'skills');
20
+ const COMMANDS_SOURCE = resolve(__dirname, '..', 'commands');
21
+
22
+ // Destination in the user's project
23
+ const SKILLS_DEST = '.agent/skills';
24
+ const COMMANDS_DEST = 'commands';
25
+
26
+ /**
27
+ * Silently ensure skills and commands are installed in the project.
28
+ *
29
+ * @param {string} projectDir - The project root directory
30
+ * @param {object} flags - CLI flags (format, etc.)
31
+ * @returns {{ skillsInstalled: boolean, commandsInstalled: boolean }}
32
+ */
33
+ export function ensureSkills(projectDir, flags = {}) {
34
+ const result = { skillsInstalled: false, commandsInstalled: false };
35
+ const silent = flags.format === 'json';
36
+
37
+ // ── Skills ────────────────────────────────────────────────────────────
38
+ const skillsCheck = resolve(projectDir, SKILLS_DEST, 'docguard-guard', 'SKILL.md');
39
+ if (!existsSync(skillsCheck) && existsSync(SKILLS_SOURCE)) {
40
+ try {
41
+ const skillDirs = readdirSync(SKILLS_SOURCE).filter(d =>
42
+ existsSync(resolve(SKILLS_SOURCE, d, 'SKILL.md'))
43
+ );
44
+
45
+ for (const skillDir of skillDirs) {
46
+ const destDir = resolve(projectDir, SKILLS_DEST, skillDir);
47
+ if (!existsSync(destDir)) {
48
+ mkdirSync(destDir, { recursive: true });
49
+ }
50
+ const srcSkill = resolve(SKILLS_SOURCE, skillDir, 'SKILL.md');
51
+ const destSkill = resolve(destDir, 'SKILL.md');
52
+ if (!existsSync(destSkill)) {
53
+ writeFileSync(destSkill, readFileSync(srcSkill, 'utf-8'), 'utf-8');
54
+ }
55
+ }
56
+
57
+ result.skillsInstalled = true;
58
+ if (!silent) {
59
+ console.log(` ${c.cyan}✨ DocGuard AI skills installed → ${SKILLS_DEST}/${c.reset}`);
60
+ }
61
+ } catch {
62
+ // Silent failure — skills are optional enhancement
63
+ }
64
+ }
65
+
66
+ // ── Slash Commands ────────────────────────────────────────────────────
67
+ const commandsCheck = resolve(projectDir, COMMANDS_DEST, 'docguard.guard.md');
68
+ if (!existsSync(commandsCheck) && existsSync(COMMANDS_SOURCE)) {
69
+ try {
70
+ const commandFiles = readdirSync(COMMANDS_SOURCE).filter(f => f.endsWith('.md'));
71
+
72
+ if (commandFiles.length > 0) {
73
+ const destDir = resolve(projectDir, COMMANDS_DEST);
74
+ if (!existsSync(destDir)) {
75
+ mkdirSync(destDir, { recursive: true });
76
+ }
77
+
78
+ for (const file of commandFiles) {
79
+ const destPath = resolve(destDir, file);
80
+ if (!existsSync(destPath)) {
81
+ writeFileSync(destPath, readFileSync(resolve(COMMANDS_SOURCE, file), 'utf-8'), 'utf-8');
82
+ }
83
+ }
84
+
85
+ result.commandsInstalled = true;
86
+ if (!silent) {
87
+ console.log(` ${c.cyan}✨ DocGuard slash commands installed → ${COMMANDS_DEST}/${c.reset}`);
88
+ }
89
+ }
90
+ } catch {
91
+ // Silent failure — commands are optional enhancement
92
+ }
93
+ }
94
+
95
+ return result;
96
+ }