docguard-cli 0.9.4 → 0.9.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/README.md +281 -203
  2. package/cli/commands/init.mjs +1 -0
  3. package/cli/scanners/speckit.mjs +318 -87
  4. package/cli/validators/metrics-consistency.mjs +2 -1
  5. package/cli/validators/traceability.mjs +17 -9
  6. package/commands/docguard.fix.md +65 -0
  7. package/commands/docguard.guard.md +60 -0
  8. package/commands/docguard.review.md +53 -0
  9. package/commands/docguard.score.md +61 -0
  10. package/docs/installation.md +37 -19
  11. package/docs/quickstart.md +21 -6
  12. package/extensions/spec-kit-docguard/LICENSE +21 -0
  13. package/extensions/spec-kit-docguard/README.md +105 -0
  14. package/extensions/spec-kit-docguard/commands/diagnose.md +43 -0
  15. package/extensions/spec-kit-docguard/commands/generate.md +50 -0
  16. package/extensions/spec-kit-docguard/commands/guard.md +73 -0
  17. package/extensions/spec-kit-docguard/commands/init.md +38 -0
  18. package/extensions/spec-kit-docguard/commands/score.md +53 -0
  19. package/extensions/spec-kit-docguard/commands/trace.md +56 -0
  20. package/extensions/spec-kit-docguard/extension.yml +109 -0
  21. package/extensions/spec-kit-docguard/scripts/bash/common.sh +106 -0
  22. package/extensions/spec-kit-docguard/scripts/bash/docguard-check-docs.sh +153 -0
  23. package/extensions/spec-kit-docguard/scripts/bash/docguard-init-doc.sh +153 -0
  24. package/extensions/spec-kit-docguard/scripts/bash/docguard-suggest-fix.sh +107 -0
  25. package/extensions/spec-kit-docguard/skills/docguard-fix/SKILL.md +218 -0
  26. package/extensions/spec-kit-docguard/skills/docguard-guard/SKILL.md +167 -0
  27. package/extensions/spec-kit-docguard/skills/docguard-review/SKILL.md +182 -0
  28. package/extensions/spec-kit-docguard/skills/docguard-score/SKILL.md +178 -0
  29. package/extensions/spec-kit-docguard/templates/extensions.yml +39 -0
  30. package/package.json +5 -2
  31. package/templates/REQUIREMENTS.md.template +68 -0
  32. package/templates/commands/docguard.fix.md +35 -39
  33. package/templates/commands/docguard.guard.md +26 -13
  34. package/templates/commands/docguard.init.md +35 -28
  35. package/templates/commands/docguard.review.md +33 -23
  36. package/templates/commands/docguard.update.md +15 -4
@@ -0,0 +1,53 @@
1
+ ---
2
+ description: "Calculate CDD maturity score with multi-signal quality breakdown"
3
+ handoffs:
4
+ - label: Improve Score
5
+ agent: docguard.fix
6
+ prompt: Fix highest-ROI documentation issues to improve score
7
+ - label: Deep Review
8
+ agent: docguard.review
9
+ prompt: Perform semantic analysis for accuracy verification
10
+ ---
11
+
12
+ # DocGuard Score
13
+
14
+ Calculate your project's Canonical-Driven Development maturity score (0-100) across 8 weighted categories.
15
+
16
+ ## User Input
17
+
18
+ $ARGUMENTS
19
+
20
+ ## Steps
21
+
22
+ 1. Run DocGuard score on the current project:
23
+
24
+ ```bash
25
+ npx --yes docguard-cli@latest score $ARGUMENTS
26
+ ```
27
+
28
+ 2. Review the breakdown:
29
+ - **Structure** (25%) — required files present
30
+ - **Doc Quality** (20%) — docs have required sections
31
+ - **Testing** (15%) — test spec alignment
32
+ - **Security** (10%) — no hardcoded secrets
33
+ - **Environment** (10%) — env docs configured
34
+ - **Drift** (10%) — drift tracking discipline
35
+ - **Changelog** (5%) — changelog maintenance
36
+ - **Architecture** (5%) — layer boundary compliance
37
+
38
+ 3. For per-signal quality labels, add `--signals`.
39
+
40
+ ## Grading
41
+
42
+ | Score | Grade | Status |
43
+ |-------|-------|--------|
44
+ | 90-100 | A | Strong CDD compliance |
45
+ | 75-89 | B | Good, some gaps |
46
+ | 50-74 | C | Needs work |
47
+ | < 50 | D | Significant gaps |
48
+
49
+ ## Flags
50
+
51
+ - `--signals` — Show multi-signal CJE composite breakdown with quality labels
52
+ - `--tax` — Show estimated maintenance effort
53
+ - `--format json` — Output as JSON
@@ -0,0 +1,56 @@
1
+ ---
2
+ description: "Generate requirements traceability matrix"
3
+ handoffs:
4
+ - label: Fix Coverage Gaps
5
+ agent: docguard.fix
6
+ prompt: Fix traceability gaps found in the matrix
7
+ - label: Run Guard
8
+ agent: docguard.guard
9
+ prompt: Validate traceability checks pass
10
+ ---
11
+
12
+ # DocGuard Trace
13
+
14
+ Generate a requirements traceability matrix mapping canonical docs ↔ source code ↔ tests. Config-aware — respects `.docguard.json` exclusions and detects orphaned files.
15
+
16
+ ## User Input
17
+
18
+ $ARGUMENTS
19
+
20
+ ## Steps
21
+
22
+ 1. Run DocGuard trace on the current project:
23
+
24
+ ```bash
25
+ npx --yes docguard-cli@latest trace $ARGUMENTS
26
+ ```
27
+
28
+ 2. Review the matrix. Each canonical doc gets a coverage signal:
29
+ - **TRACED** — doc + source code + tests all linked
30
+ - **PARTIAL** — doc exists, source found, no test coverage
31
+ - **UNLINKED** — doc exists but no matching source code
32
+ - **MISSING** — doc not found
33
+
34
+ 3. Orphaned files (exist but excluded from config) are flagged with cleanup instructions.
35
+
36
+ ## Standards
37
+
38
+ Maps against industry standards per document type:
39
+
40
+ | Document | Standard |
41
+ |----------|----------|
42
+ | ARCHITECTURE.md | arc42 / C4 Model |
43
+ | DATA-MODEL.md | C4 Component / ER (Chen) |
44
+ | TEST-SPEC.md | ISO/IEC/IEEE 29119-3 |
45
+ | SECURITY.md | OWASP ASVS v4.0 |
46
+ | ENVIRONMENT.md | 12-Factor App |
47
+ | API-REFERENCE.md | OpenAPI 3.1 |
48
+
49
+ ## Flags
50
+
51
+ - `--format json` — Output as JSON
52
+ - `--dir <path>` — Run on a different directory
53
+
54
+ ## Research
55
+
56
+ Inspired by ISO/IEC/IEEE 29119 traceability requirements (Lopez et al., AITPG, IEEE TSE 2026).
@@ -0,0 +1,109 @@
1
+ schema_version: "1.0"
2
+
3
+ extension:
4
+ id: "docguard"
5
+ name: "DocGuard — CDD Enforcement"
6
+ version: "0.9.6"
7
+ description: "Canonical-Driven Development enforcement with enterprise-grade AI skills. 19 automated validators, structured research workflows, quality validation loops, and spec-kit integration hooks. Zero dependencies."
8
+ author: "Ricardo Accioly"
9
+ repository: "https://github.com/raccioly/docguard"
10
+ license: "MIT"
11
+ homepage: "https://www.npmjs.com/package/docguard-cli"
12
+
13
+ requires:
14
+ speckit_version: ">=0.1.0"
15
+ tools:
16
+ - name: "node"
17
+ required: true
18
+ version: ">=18.0.0"
19
+ - name: "npx"
20
+ required: true
21
+
22
+ provides:
23
+ commands:
24
+ - name: "docguard.guard"
25
+ file: "commands/guard.md"
26
+ description: "Run 19-validator quality gate with severity triage and remediation plan"
27
+ aliases: ["speckit.docguard.guard"]
28
+
29
+ - name: "docguard.fix"
30
+ file: "commands/fix.md"
31
+ description: "AI-driven documentation repair with codebase research and validation loops"
32
+ aliases: ["speckit.docguard.fix"]
33
+
34
+ - name: "docguard.review"
35
+ file: "commands/review.md"
36
+ description: "Cross-document semantic consistency analysis (read-only)"
37
+ aliases: ["speckit.docguard.review"]
38
+
39
+ - name: "docguard.score"
40
+ file: "commands/score.md"
41
+ description: "CDD maturity score with ROI-based improvement roadmap"
42
+ aliases: ["speckit.docguard.score"]
43
+
44
+ - name: "speckit.docguard.diagnose"
45
+ file: "commands/review.md"
46
+ description: "Diagnose all issues and generate a complete AI remediation plan"
47
+
48
+ - name: "speckit.docguard.generate"
49
+ file: "commands/fix.md"
50
+ description: "Reverse-engineer canonical docs from existing codebase"
51
+
52
+ skills:
53
+ - name: "docguard-guard"
54
+ path: "skills/docguard-guard/SKILL.md"
55
+ description: "19-validator quality gate with severity triage and structured reporting"
56
+
57
+ - name: "docguard-fix"
58
+ path: "skills/docguard-fix/SKILL.md"
59
+ description: "AI-driven documentation repair with research workflow and validation loops"
60
+
61
+ - name: "docguard-review"
62
+ path: "skills/docguard-review/SKILL.md"
63
+ description: "Cross-document semantic consistency analysis with quality scoring"
64
+
65
+ - name: "docguard-score"
66
+ path: "skills/docguard-score/SKILL.md"
67
+ description: "CDD maturity assessment with ROI-based improvement roadmap"
68
+
69
+ scripts:
70
+ - name: "docguard-check-docs"
71
+ path: "scripts/bash/docguard-check-docs.sh"
72
+ description: "Discover project docs, return JSON inventory with metadata"
73
+
74
+ - name: "docguard-suggest-fix"
75
+ path: "scripts/bash/docguard-suggest-fix.sh"
76
+ description: "Run guard, parse results, output prioritized fix suggestions"
77
+
78
+ - name: "docguard-init-doc"
79
+ path: "scripts/bash/docguard-init-doc.sh"
80
+ description: "Initialize a new canonical document with metadata header"
81
+
82
+ hooks:
83
+ after_implement:
84
+ command: "docguard.guard"
85
+ optional: false
86
+ prompt: "Run DocGuard validation after implementation"
87
+ description: "Mandatory quality gate — ensures docs stay in sync with code"
88
+
89
+ before_tasks:
90
+ command: "docguard.review"
91
+ optional: true
92
+ prompt: "Review documentation consistency before generating tasks?"
93
+
94
+ after_tasks:
95
+ command: "docguard.score"
96
+ optional: true
97
+ prompt: "Show CDD maturity score after task generation?"
98
+
99
+ tags:
100
+ - "documentation"
101
+ - "validation"
102
+ - "quality"
103
+ - "cdd"
104
+ - "spec-driven"
105
+ - "traceability"
106
+ - "ai-agents"
107
+ - "enforcement"
108
+ - "spec-kit"
109
+ - "skills"
@@ -0,0 +1,106 @@
1
+ #!/usr/bin/env bash
2
+ # DocGuard — Shared utilities for bash scripts
3
+ # Used by all DocGuard orchestration scripts
4
+
5
+ set -e
6
+
7
+ # ── Project Root Detection ─────────────────────────────────────────────────
8
+
9
+ find_docguard_root() {
10
+ local dir="${1:-$(pwd)}"
11
+ while [ "$dir" != "/" ]; do
12
+ # Check for DocGuard project markers
13
+ if [ -d "$dir/docs-canonical" ] || [ -f "$dir/.docguard.json" ] || [ -f "$dir/CHANGELOG.md" ]; then
14
+ echo "$dir"
15
+ return 0
16
+ fi
17
+ dir="$(dirname "$dir")"
18
+ done
19
+ return 1
20
+ }
21
+
22
+ # ── DocGuard CLI Detection ─────────────────────────────────────────────────
23
+
24
+ find_docguard_cli() {
25
+ local root="${1:-$(pwd)}"
26
+
27
+ # Check for local dev mode first
28
+ if [ -f "$root/cli/docguard.mjs" ]; then
29
+ echo "node $root/cli/docguard.mjs"
30
+ return 0
31
+ fi
32
+
33
+ # Check for global install
34
+ if command -v docguard-cli >/dev/null 2>&1; then
35
+ echo "docguard-cli"
36
+ return 0
37
+ fi
38
+
39
+ # Fall back to npx
40
+ if command -v npx >/dev/null 2>&1; then
41
+ echo "npx docguard-cli"
42
+ return 0
43
+ fi
44
+
45
+ return 1
46
+ }
47
+
48
+ # ── JSON Escape ────────────────────────────────────────────────────────────
49
+
50
+ json_escape() {
51
+ local s="$1"
52
+ s="${s//\\/\\\\}"
53
+ s="${s//\"/\\\"}"
54
+ s="${s//$'\n'/\\n}"
55
+ s="${s//$'\t'/\\t}"
56
+ s="${s//$'\r'/\\r}"
57
+ printf '%s' "$s"
58
+ }
59
+
60
+ # ── JSON Output Helper ────────────────────────────────────────────────────
61
+
62
+ json_output() {
63
+ # Build JSON from key=value pairs
64
+ # Usage: json_output key1 "value1" key2 "value2"
65
+ local result="{"
66
+ local first=true
67
+ while [ $# -ge 2 ]; do
68
+ if [ "$first" = true ]; then
69
+ first=false
70
+ else
71
+ result="$result,"
72
+ fi
73
+ result="$result\"$1\":\"$(json_escape "$2")\""
74
+ shift 2
75
+ done
76
+ result="$result}"
77
+ echo "$result"
78
+ }
79
+
80
+ # ── Date Helpers ───────────────────────────────────────────────────────────
81
+
82
+ today_iso() {
83
+ date +%Y-%m-%d
84
+ }
85
+
86
+ # ── File Helpers ───────────────────────────────────────────────────────────
87
+
88
+ file_exists() {
89
+ [ -f "$1" ]
90
+ }
91
+
92
+ dir_exists() {
93
+ [ -d "$1" ]
94
+ }
95
+
96
+ ensure_dir() {
97
+ mkdir -p "$1"
98
+ }
99
+
100
+ # ── Metadata Helpers ──────────────────────────────────────────────────────
101
+
102
+ extract_metadata() {
103
+ local file="$1"
104
+ local key="$2"
105
+ grep "docguard:${key}" "$file" 2>/dev/null | sed "s/.*docguard:${key} //" | sed 's/ -->//' | tr -d '\r'
106
+ }
@@ -0,0 +1,153 @@
1
+ #!/usr/bin/env bash
2
+ # DocGuard — Check project documentation status
3
+ # Returns JSON with document inventory and health status
4
+ #
5
+ # Usage:
6
+ # ./docguard-check-docs.sh [--json] [--verbose]
7
+ #
8
+ # JSON output fields:
9
+ # PROJECT_ROOT — absolute path to project root
10
+ # CLI_CMD — command to run DocGuard CLI
11
+ # DOCS — array of {name, path, exists, version, status, lastReviewed}
12
+ # SCORE — CDD maturity score (if --verbose)
13
+ # GUARD_PASS — number of passing guard checks (if --verbose)
14
+ # GUARD_TOTAL — total guard checks (if --verbose)
15
+
16
+ set -e
17
+
18
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
19
+ source "$SCRIPT_DIR/common.sh"
20
+
21
+ JSON_MODE=false
22
+ VERBOSE=false
23
+
24
+ while [ $# -gt 0 ]; do
25
+ case "$1" in
26
+ --json) JSON_MODE=true ;;
27
+ --verbose) VERBOSE=true ;;
28
+ --help|-h)
29
+ echo "Usage: $0 [--json] [--verbose]"
30
+ echo ""
31
+ echo "Options:"
32
+ echo " --json Output in JSON format for AI consumption"
33
+ echo " --verbose Include score and guard results"
34
+ echo " --help Show this help message"
35
+ exit 0
36
+ ;;
37
+ *) echo "Unknown option: $1" >&2; exit 1 ;;
38
+ esac
39
+ shift
40
+ done
41
+
42
+ # Find project root
43
+ PROJECT_ROOT=$(find_docguard_root "$(pwd)") || {
44
+ echo "Error: No DocGuard project found. Run 'docguard init' first." >&2
45
+ exit 1
46
+ }
47
+
48
+ # Find CLI command
49
+ CLI_CMD=$(find_docguard_cli "$PROJECT_ROOT") || {
50
+ echo "Error: DocGuard CLI not found. Install with: npm i -g docguard-cli" >&2
51
+ exit 1
52
+ }
53
+
54
+ cd "$PROJECT_ROOT"
55
+
56
+ # Canonical documents to check
57
+ CANONICAL_DOCS=(
58
+ "docs-canonical/ARCHITECTURE.md"
59
+ "docs-canonical/DATA-MODEL.md"
60
+ "docs-canonical/SECURITY.md"
61
+ "docs-canonical/TEST-SPEC.md"
62
+ "docs-canonical/ENVIRONMENT.md"
63
+ "docs-canonical/REQUIREMENTS.md"
64
+ )
65
+
66
+ # Support documents
67
+ SUPPORT_DOCS=(
68
+ "CHANGELOG.md"
69
+ "DRIFT-LOG.md"
70
+ "AGENTS.md"
71
+ "README.md"
72
+ "ROADMAP.md"
73
+ )
74
+
75
+ if $JSON_MODE; then
76
+ # Build canonical docs JSON array
77
+ DOCS_JSON="["
78
+ first=true
79
+ for doc in "${CANONICAL_DOCS[@]}" "${SUPPORT_DOCS[@]}"; do
80
+ if [ "$first" = true ]; then first=false; else DOCS_JSON="$DOCS_JSON,"; fi
81
+
82
+ doc_name=$(basename "$doc" .md)
83
+ doc_path="$PROJECT_ROOT/$doc"
84
+ doc_exists="false"
85
+ doc_version=""
86
+ doc_status=""
87
+ doc_reviewed=""
88
+
89
+ if [ -f "$doc_path" ]; then
90
+ doc_exists="true"
91
+ doc_version=$(extract_metadata "$doc_path" "version" 2>/dev/null || echo "")
92
+ doc_status=$(extract_metadata "$doc_path" "status" 2>/dev/null || echo "")
93
+ doc_reviewed=$(extract_metadata "$doc_path" "last-reviewed" 2>/dev/null || echo "")
94
+ fi
95
+
96
+ DOCS_JSON="$DOCS_JSON{\"name\":\"$(json_escape "$doc_name")\",\"path\":\"$(json_escape "$doc")\",\"exists\":$doc_exists"
97
+ [ -n "$doc_version" ] && DOCS_JSON="$DOCS_JSON,\"version\":\"$(json_escape "$doc_version")\""
98
+ [ -n "$doc_status" ] && DOCS_JSON="$DOCS_JSON,\"status\":\"$(json_escape "$doc_status")\""
99
+ [ -n "$doc_reviewed" ] && DOCS_JSON="$DOCS_JSON,\"lastReviewed\":\"$(json_escape "$doc_reviewed")\""
100
+ DOCS_JSON="$DOCS_JSON}"
101
+ done
102
+ DOCS_JSON="$DOCS_JSON]"
103
+
104
+ # Optionally include score and guard
105
+ EXTRAS=""
106
+ if $VERBOSE; then
107
+ SCORE_OUTPUT=$(eval $CLI_CMD score --format json 2>/dev/null || echo "")
108
+ GUARD_OUTPUT=$(eval $CLI_CMD guard 2>&1 || true)
109
+
110
+ # Extract score
111
+ SCORE=$(echo "$SCORE_OUTPUT" | grep -o '"total":[0-9]*' | head -1 | sed 's/"total"://' || echo "0")
112
+
113
+ # Extract guard pass/total from output like "156/160 passed"
114
+ GUARD_PASS=$(echo "$GUARD_OUTPUT" | grep -o '[0-9]*/[0-9]* passed' | sed 's|/.*||' || echo "0")
115
+ GUARD_TOTAL=$(echo "$GUARD_OUTPUT" | grep -o '[0-9]*/[0-9]* passed' | sed 's|.*/||; s| .*||' || echo "0")
116
+
117
+ EXTRAS=",\"score\":$SCORE,\"guardPass\":$GUARD_PASS,\"guardTotal\":$GUARD_TOTAL"
118
+ fi
119
+
120
+ # Check for spec-kit
121
+ HAS_SPECKIT="false"
122
+ [ -d "$PROJECT_ROOT/.specify" ] && HAS_SPECKIT="true"
123
+
124
+ echo "{\"projectRoot\":\"$(json_escape "$PROJECT_ROOT")\",\"cliCommand\":\"$(json_escape "$CLI_CMD")\",\"hasSpecKit\":$HAS_SPECKIT,\"docs\":$DOCS_JSON$EXTRAS}"
125
+ else
126
+ echo "DocGuard Project: $PROJECT_ROOT"
127
+ echo "CLI: $CLI_CMD"
128
+ echo ""
129
+ echo "Canonical Documents:"
130
+ for doc in "${CANONICAL_DOCS[@]}"; do
131
+ if [ -f "$PROJECT_ROOT/$doc" ]; then
132
+ version=$(extract_metadata "$PROJECT_ROOT/$doc" "version" 2>/dev/null || echo "?")
133
+ reviewed=$(extract_metadata "$PROJECT_ROOT/$doc" "last-reviewed" 2>/dev/null || echo "?")
134
+ echo " ✅ $doc (v$version, reviewed: $reviewed)"
135
+ else
136
+ echo " ❌ $doc (MISSING)"
137
+ fi
138
+ done
139
+ echo ""
140
+ echo "Support Documents:"
141
+ for doc in "${SUPPORT_DOCS[@]}"; do
142
+ if [ -f "$PROJECT_ROOT/$doc" ]; then
143
+ echo " ✅ $doc"
144
+ else
145
+ echo " ❌ $doc (MISSING)"
146
+ fi
147
+ done
148
+
149
+ if $VERBOSE; then
150
+ echo ""
151
+ eval $CLI_CMD score 2>&1 || true
152
+ fi
153
+ fi
@@ -0,0 +1,153 @@
1
+ #!/usr/bin/env bash
2
+ # DocGuard — Initialize a new canonical document with metadata header
3
+ # Copies template and adds DocGuard metadata scaffolding
4
+ #
5
+ # Usage:
6
+ # ./docguard-init-doc.sh <doc-name> [--json] [--version X.X.X]
7
+ #
8
+ # Examples:
9
+ # ./docguard-init-doc.sh architecture
10
+ # ./docguard-init-doc.sh security --json --version 0.5.0
11
+ #
12
+ # JSON output fields:
13
+ # DOC_PATH — absolute path to created document
14
+ # DOC_NAME — canonical document name
15
+ # TEMPLATE — template used (if any)
16
+ # CREATED — whether file was created (true/false)
17
+
18
+ set -e
19
+
20
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
21
+ source "$SCRIPT_DIR/common.sh"
22
+
23
+ JSON_MODE=false
24
+ DOC_VERSION="0.1.0"
25
+ DOC_NAME=""
26
+
27
+ while [ $# -gt 0 ]; do
28
+ case "$1" in
29
+ --json) JSON_MODE=true ;;
30
+ --version)
31
+ shift
32
+ DOC_VERSION="${1:-0.1.0}"
33
+ ;;
34
+ --help|-h)
35
+ echo "Usage: $0 <doc-name> [--json] [--version X.X.X]"
36
+ echo ""
37
+ echo "Document names: architecture, data-model, security, test-spec, environment, requirements"
38
+ echo ""
39
+ echo "Options:"
40
+ echo " --json Output in JSON format"
41
+ echo " --version X.X.X Set initial version (default: 0.1.0)"
42
+ echo " --help Show this help"
43
+ exit 0
44
+ ;;
45
+ *)
46
+ if [ -z "$DOC_NAME" ]; then
47
+ DOC_NAME="$1"
48
+ else
49
+ echo "Error: Unexpected argument: $1" >&2
50
+ exit 1
51
+ fi
52
+ ;;
53
+ esac
54
+ shift
55
+ done
56
+
57
+ if [ -z "$DOC_NAME" ]; then
58
+ echo "Error: Document name required" >&2
59
+ echo "Usage: $0 <doc-name> [--json] [--version X.X.X]" >&2
60
+ exit 1
61
+ fi
62
+
63
+ # Normalize document name
64
+ DOC_NAME_UPPER=$(echo "$DOC_NAME" | tr '[:lower:]' '[:upper:]' | tr '-' '-')
65
+ DOC_FILE="docs-canonical/${DOC_NAME_UPPER}.md"
66
+
67
+ # Find project root
68
+ PROJECT_ROOT=$(find_docguard_root "$(pwd)") || {
69
+ echo "Error: No DocGuard project found." >&2
70
+ exit 1
71
+ }
72
+
73
+ cd "$PROJECT_ROOT"
74
+
75
+ DOC_PATH="$PROJECT_ROOT/$DOC_FILE"
76
+ CREATED=false
77
+ TEMPLATE_USED=""
78
+
79
+ # Check if file already exists
80
+ if [ -f "$DOC_PATH" ]; then
81
+ if $JSON_MODE; then
82
+ echo "{\"docPath\":\"$(json_escape "$DOC_PATH")\",\"docName\":\"$(json_escape "$DOC_NAME_UPPER")\",\"created\":false,\"reason\":\"File already exists\"}"
83
+ else
84
+ echo "⚠ $DOC_FILE already exists. Use docguard fix to update it."
85
+ fi
86
+ exit 0
87
+ fi
88
+
89
+ # Ensure docs-canonical directory exists
90
+ ensure_dir "$PROJECT_ROOT/docs-canonical"
91
+
92
+ # Check for template
93
+ TEMPLATE_DIR="$PROJECT_ROOT/templates"
94
+ TEMPLATE_FILE="$TEMPLATE_DIR/${DOC_NAME_UPPER}.md"
95
+
96
+ # Generate metadata header
97
+ TODAY=$(today_iso)
98
+ HEADER="# ${DOC_NAME_UPPER}
99
+
100
+ <!-- docguard:version ${DOC_VERSION} -->
101
+ <!-- docguard:status active -->
102
+ <!-- docguard:last-reviewed ${TODAY} -->
103
+ "
104
+
105
+ if [ -f "$TEMPLATE_FILE" ]; then
106
+ # Use template, but replace/add metadata header
107
+ cp "$TEMPLATE_FILE" "$DOC_PATH"
108
+ TEMPLATE_USED="$TEMPLATE_FILE"
109
+
110
+ # Ensure metadata header exists
111
+ if ! grep -q "docguard:version" "$DOC_PATH"; then
112
+ # Prepend metadata after first heading
113
+ tmp_file=$(mktemp)
114
+ head -1 "$DOC_PATH" > "$tmp_file"
115
+ echo "" >> "$tmp_file"
116
+ echo "<!-- docguard:version ${DOC_VERSION} -->" >> "$tmp_file"
117
+ echo "<!-- docguard:status active -->" >> "$tmp_file"
118
+ echo "<!-- docguard:last-reviewed ${TODAY} -->" >> "$tmp_file"
119
+ tail -n +2 "$DOC_PATH" >> "$tmp_file"
120
+ mv "$tmp_file" "$DOC_PATH"
121
+ fi
122
+ CREATED=true
123
+ else
124
+ # Generate from scratch with skeleton
125
+ cat > "$DOC_PATH" << EOF
126
+ ${HEADER}
127
+ <!-- ACTION REQUIRED: This is a skeleton document. Fill each section with
128
+ real project-specific content. Run 'docguard fix --doc ${DOC_NAME}' for
129
+ AI-generated guidance on what to write. -->
130
+
131
+ ## Overview
132
+
133
+ [Describe the purpose of this document and what it covers]
134
+
135
+ ## Details
136
+
137
+ [Add project-specific content here]
138
+
139
+ ## References
140
+
141
+ - [Link to related documents or resources]
142
+ EOF
143
+ CREATED=true
144
+ fi
145
+
146
+ if $JSON_MODE; then
147
+ echo "{\"docPath\":\"$(json_escape "$DOC_PATH")\",\"docName\":\"$(json_escape "$DOC_NAME_UPPER")\",\"template\":\"$(json_escape "$TEMPLATE_USED")\",\"created\":$CREATED,\"version\":\"$(json_escape "$DOC_VERSION")\"}"
148
+ else
149
+ echo "✅ Created $DOC_FILE"
150
+ [ -n "$TEMPLATE_USED" ] && echo " Template: $TEMPLATE_USED"
151
+ echo " Version: $DOC_VERSION"
152
+ echo " Next: Run 'docguard fix --doc $DOC_NAME' for content guidance"
153
+ fi