# docguard
> The enforcement tool for Canonical-Driven Development (CDD). Audit, generate, and guard your project documentation.

<!-- llms-full.txt — full-content form. The link-index form is llms.txt. -->
<!-- Generated by DocGuard (docguard llms --full). Regenerate after doc changes. -->

---

## docs-canonical/ARCHITECTURE.md
> System architecture, component boundaries, and tech stack

# Architecture

<!-- docguard:version 0.6.0 -->
<!-- docguard:status active -->
<!-- docguard:last-reviewed 2026-07-03 -->

| Metadata | Value |
|----------|-------|
| **Status** | ![Status](https://img.shields.io/badge/status-active-brightgreen) |
| **Version** | `0.6.0` |
| **Last Updated** | 2026-05-31 |
| **Project Size** | ~24K lines across `cli/` |

---

## System Overview

DocGuard is a near-zero-dependency Node.js CLI tool. It carries one exact-pinned npm runtime dependency, `@babel/parser`, for AST-accurate JS/TS parsing, and uses the developer's own `python3` (no pip/npm dependency) for an AST-accurate Python tier. Both AST tiers load **optionally** with a per-file regex fallback, so the CLI stays robust when a parser is absent — they make JS/TS and Python full-support languages while every other language stays on the regex (beta) tier. It enforces **Canonical-Driven Development (CDD)** — a methodology where documentation is the source of truth. DocGuard audits, scores, and guards project documentation. It generates AI-actionable fix prompts and integrates with CI/CD pipelines.

It targets development teams and AI coding agents that need to maintain documentation quality across projects of any stack (JavaScript, Python, Java, etc.).

## Component Map

| Component | Responsibility | Location | Key Files |
|-----------|---------------|----------|-----------|
| **CLI Entry Point** | Argument parsing, config loading, command routing | `cli/` | `docguard.mjs` |
| **Commands** | User-facing commands (the Daily 5 — init/guard/diff/sync/score — plus situational tools: diagnose, fix, generate, trace, explain, verify, feedback, memory, agent, mcp, upgrade, watch, demo, and `init --with` scaffolders) | `cli/commands/` | `*.mjs` |
| **Validators** | 24 independent validation modules that check specific aspects of CDD compliance — all emitting structured findings with stable codes (the `CODES` registry in `findings.mjs`) | `cli/validators/` | `*.mjs` |
| **Scanners** | 16 project file scanners for test discovery, route detection, schema mapping, CDK/IaC, doc-tools, integrations, frontend surface, spec-kit, memory-plan, semantic claims, agent readability | `cli/scanners/` | `*.mjs` |
| **Writers** | Deterministic doc-mutation and output modules — section-addressable edits, mechanical fix registry, API-Reference writer, generate I/O + doc builders (split from generate.mjs), SARIF emitter (no LLM) | `cli/writers/` | `mechanical.mjs`, `sections.mjs`, `api-reference.mjs`, `generate-io.mjs`, `doc-generators.mjs`, `sarif.mjs` |
| **Config** | Configuration loading — defaults, `.docguard.json` merge, profile presets, project-type detection (extracted from the entry point to keep the import graph acyclic) | `cli/` | `config.mjs` |
| **Shared** | Cross-cutting utilities — ignore/glob filters, source-root resolution, git helpers, and the shared doc→code trace patterns used by both `trace` and the Traceability validator | `cli/` | `shared-ignore.mjs`, `shared-source.mjs`, `shared-git.mjs`, `shared-trace-patterns.mjs`, `shared.mjs` |
| **Templates** | Document skeletons (ARCHITECTURE, SECURITY, etc.) and slash command files for AI agents | `templates/` | `*.template`, `commands/*.md` |
| **Extension** | Spec Kit extension with 5 AI skills, 4 bash scripts, workflow hooks | `extensions/spec-kit-docguard/` | `skills/*/SKILL.md`, `scripts/bash/*.sh` |
| **Tests** | Per-validator unit tests + command-level integration tests using `node:test` | `tests/` | `*.test.mjs` |

## Tech Stack

| Category | Technology | Rationale |
|----------|-----------|-----------|
| Language | JavaScript (ES Modules) | Universal runtime, zero-friction `npx` usage |
| Runtime | Node.js ≥ 18 | Native `node:test`, `node:fs`, `node:child_process` |
| Dependencies | **One npm dep** — `@babel/parser` (exact-pinned, optional-load) | AST-accurate JS/TS parsing; minimal, vetted supply-chain surface |
| Optional external | `python3` (the developer's own) | AST-accurate Python parsing; not an npm/pip dependency, regex fallback when absent |
| Package Manager | npm | Standard for Node.js CLIs |
| Testing | `node:test` + `node:assert` | Built-in, no test framework dependency |
| Docker | `Dockerfile` (MCP server image) | Lets MCP directory inspectors (Glama et al.) boot `docguard mcp` for introspection checks; not part of the npm distribution |

### Recognized Config Files

DocGuard recognizes and validates these project config files:

| File | Purpose |
|------|---------|
| `.docguard.json` | Project-level DocGuard configuration |
| `.docguardignore` | Per-project file exclusions (like `.gitignore`) |
| `vitest.config.ts` / `jest.config.ts` | Test runner config (scanned for custom test patterns) |
| `.storybook/` | Component documentation tool (detected for docs-coverage) |
| `.jules-setup.sh` | This repo's own Google Jules environment bootstrap script (internal tooling, not shipped) |
| `.pre-commit-hooks.yaml` | This repo as a pre-commit hook source — consumers reference `repo: raccioly/docguard` to run `docguard-guard` (changed-only) per commit |
| `glama.json` | Glama MCP directory metadata — declares repo maintainers so the Glama listing can be claimed/managed |
| `server.json` | Official MCP Registry manifest (`io.github.raccioly/docguard`) — server name, npm package, stdio transport |

## Layer Boundaries

The architecture follows a strict 4-layer model where each layer can only import from the layers below it.

| Layer | Contains | Can Import From | Cannot Import From |
|-------|----------|----------------|--------------------|
| **Extension** (`extensions/spec-kit-docguard/`) | AI skills (SKILL.md), bash scripts, hooks, commands | CLI (via npx), Node.js built-ins | Isolated — spec-kit integration layer |
| **Commands** (`cli/commands/`) | User-facing command logic | Validators, Config (via `docguard.mjs` exports) | Isolated — each command is self-contained |
| **Validators** (`cli/validators/`) | Independent validation modules | Scanners, Shared utilities, Node.js built-ins | Cannot import from Commands or Writers |
| **Scanners** (`cli/scanners/`) | Project intelligence — detect routes, schemas, IaC, frontend surface | Shared utilities, Node.js built-ins | Cannot import from Validators, Commands, Writers |
| **Writers** (`cli/writers/`) | Mutate canonical docs surgically (section-addressable, no LLM) | Node.js built-ins only | Cannot import from Validators, Scanners, Commands |
| **Shared** (`cli/shared-*.mjs`) | Cross-cutting utilities: ignore/glob filters, source-root resolution, git helpers, shared trace patterns | Node.js built-ins only | Cannot import from any other layer |
| **Config** (`cli/config.mjs`) | `loadConfig` + defaults/profile merge + project-type detection | Shared utilities, Node.js built-ins | Cannot import from Commands (extracted so `demo`→`docguard` is no longer a cycle) |
| **Entry Point** (`cli/docguard.mjs`) | ANSI colors, argument parsing, command dispatch, banner/help | Commands, Config (`loadConfig`) | Calls validators only through commands |

**Key Rule**: Validators are pure functions. They receive `projectDir` and `config`, then return results. They stay isolated from commands and the CLI entry point. The Extension layer operates independently, using the CLI as an external tool.

```mermaid
graph TD
    A["CLI Entry Point<br/>docguard.mjs"] --> B["Shared Constants<br/>shared.mjs"]
    A --> C["Commands<br/>cli/commands/*.mjs"]
    C --> B
    C --> D["Validators<br/>cli/validators/*.mjs"]
    D --> E["Node.js Built-ins<br/>fs, path, child_process"]
    C --> E
    A --> F[".docguard.json<br/>Project Config"]
    D --> G["docs-canonical/<br/>Canonical Docs"]

    style A fill:#4a9eff,color:#fff
    style B fill:#6c757d,color:#fff
    style C fill:#28a745,color:#fff
    style D fill:#ffc107,color:#000
    style F fill:#17a2b8,color:#fff
    style G fill:#e83e8c,color:#fff
```

## Data Flow

### Request Lifecycle: `docguard guard`

```
User runs: npx docguard guard
     │
     ▼
docguard.mjs
  ├── parseArgs(process.argv)      → flags: { format, dir, ... }
  ├── loadConfig(projectDir)       → .docguard.json → merged with defaults
  │     ├── Reads .docguard.json
  │     ├── Reads package.json (name, type detection)
  │     └── Merges: defaults ← config ← CLI flags
  │
  ▼
guard.mjs
  ├── For each enabled validator:
  │     ├── structure.mjs    → checks docs-canonical/ exists, required files present
  │     ├── docs-sync.mjs    → checks DocGuard metadata headers
  │     ├── drift.mjs        → checks DRIFT-LOG.md for staleness
  │     ├── changelog.mjs    → checks Unreleased section, version entries
  │     ├── architecture.mjs → validates component map, layer boundaries
  │     ├── test-spec.mjs    → checks test framework, coverage docs
  │     ├── security.mjs     → checks auth, secrets documentation
  │     ├── environment.mjs  → checks setup steps, env vars documentation
  │     └── freshness.mjs    → checks git commit dates vs doc last-modified
  │
  ├── Collects: { pass: [...], warn: [...], fail: [...] }
  │
  ▼
Output (text | json)
  └── Exit code: 0 (pass) | 1 (fail) | 2 (warn)
```

### AI Fix Flow: `docguard fix --doc architecture`

```
fix.mjs
  ├── Looks up DOC_EXPECTATIONS['docs-canonical/ARCHITECTURE.md']
  ├── assessDocQuality(content, expectations)
  │     └── Checks: line count, placeholder count, content quality signals
  ├── Outputs: TASK, PURPOSE, RESEARCH STEPS, WRITE THE DOCUMENT
  │
  ▼
AI Agent (Claude Code, Cursor, Copilot, etc.)
  ├── Reads stdout (the research instructions)
  ├── Executes research: reads package.json, scans directories, maps imports
  ├── Writes docs-canonical/ARCHITECTURE.md with real content
  │
  ▼
docguard guard → validates the newly written document
```

## Key Design Decisions

| Decision | Rationale |
|----------|-----------|
| **Minimal dependencies** | One exact-pinned, vetted runtime dep (`@babel/parser`) earns its place by fixing silent regex truncation; it loads optionally so installs stay robust. Everything else is Node.js built-ins. |
| **Config-driven validation** | `.docguard.json` lets projects customize which validators run. A CLI project can skip database docs. |
| **Validators are independent** | Each validator is a self-contained module. Adding a validator keeps existing ones stable. |
| **AI as author, CLI as orchestrator** | The CLI detects problems and generates structured prompts. Documentation writing is the AI's responsibility. |
| **Exit codes for CI** | `0` (pass), `1` (fail), `2` (warn) enables `docguard ci` to gate deployments. |

---

## External Dependencies

DocGuard has **zero runtime dependencies**. All functionality uses Node.js built-in modules.

| Module | Usage |
|--------|-------|
| `node:fs` | File system operations (read docs, check existence) |
| `node:path` | Path resolution and manipulation |
| `node:child_process` | Git operations (freshness checks) |
| `node:url` | ES Module URL resolution |
| `node:readline` | Interactive prompts (init command) |
| `node:test` | Built-in test framework |
| `node:assert` | Test assertions |
| `node:os` | Temp directory for tests |

**Dev dependencies**: None. Tests use `node:test` (built-in since Node.js 18).

---

## Revision History

| Version | Date | Author | Changes |
|---------|------|--------|---------|
| 0.6.0 | 2026-05-31 | DocGuard Team | Refresh for v0.24.0: Python promoted to full support via a `python3` AST tier (`cli/scanners/py-ast.mjs`); JS/TS route extraction extended with cross-file mount-prefix resolution, object-form route declarations, and AST router-screen detection (`cli/scanners/js-ast.mjs`); removed the retired editor extension from the tech stack |
| 0.5.0 | 2026-05-29 | DocGuard Team | Refresh for v0.22–v0.23: validator + scanner set updated, new `config.mjs` (config extracted to break the demo↔docguard cycle) and `shared-trace-patterns.mjs` (shared multilingual trace patterns) |
| 0.4.0 | 2026-03-13 | DocGuard Team | Complete rewrite with real project data, AI orchestration architecture |
| 0.1.0 | 2026-03-13 | DocGuard Generate | Auto-generated skeleton |


---

## docs-canonical/CI-RECIPES.md

# CI Recipes

<!-- docguard:quality negation-load off — operational doc: "read-only, never modifies your repo", "fork PRs won't run", "don't commit X" are precise prohibitions; positive rephrasing would reduce clarity -->

<!-- docguard:section id=overview source=human -->
This document covers the GitHub Action and CI integration patterns DocGuard ships.
Each recipe is a copy-pasteable workflow you can drop into `.github/workflows/`.

DocGuard exposes itself as a composite action at `raccioly/docguard@<tag>` and
also ships starter workflow templates under
`extensions/spec-kit-docguard/templates/github-workflows/`. Pin to a specific
tag (e.g. `@v0.12.0`) in production — `@main` is fine for tracking the bleeding edge.
<!-- /docguard:section -->

## Recipe 1 — Guard (mandatory CI gate)

Runs all 27 validators. Read-only — never modifies your repo.

```yaml
name: DocGuard Guard
on:
  push: { branches: [main] }
  pull_request: { branches: [main] }
permissions:
  contents: read
jobs:
  guard:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with: { fetch-depth: 0 }   # Freshness validator needs git history
      - uses: raccioly/docguard@v0.12.0
        with:
          command: guard
          fail-on-warning: 'false' # flip to true once your repo is clean
```

Inputs that matter:
- `command: guard` (default)
- `fail-on-warning` — `false` (default) treats warnings as exit 0, `true` fails the job
- `format: json` — emits machine-readable output for downstream steps

## Recipe 2 — Auto-Fix (PR-time mechanical fixes)

Applies deterministic fixes — version bumps, count drift, removed endpoints,
changelog stubs — and commits them back to the PR branch.

```yaml
name: DocGuard Auto-Fix
on:
  pull_request:
    types: [opened, synchronize, reopened]
permissions:
  contents: write          # commit back to PR branch
  pull-requests: write     # post summary comment
jobs:
  autofix:
    runs-on: ubuntu-latest
    if: github.event.pull_request.head.repo.full_name == github.repository
    steps:
      - uses: actions/checkout@v4
        with:
          ref: ${{ github.event.pull_request.head.ref }}
          token: ${{ secrets.GITHUB_TOKEN }}
          fetch-depth: 0
      - uses: raccioly/docguard@v0.12.0
        with:
          command: fix
          auto-commit: 'true'
          comment-on-pr: 'true'
```

What gets fixed automatically (no AI involved):
- `replace-version` — bump `package.json`-derived version mentions in docs.
- `replace-count` — fix line/file/endpoint counts in canonical docs.
- `insert-changelog-unreleased` — drop an Unreleased stub when missing.
- `remove-endpoint` — strip an endpoint block from `API-REFERENCE.md` when the route was deleted from code (gated by a generated marker).

What does NOT get fixed automatically (run `/docguard.fix` from your editor):
- Entire prose rewrites — these need AI judgement.
- New endpoint documentation — needs human description of behavior.
- Schema docs for entities that don't have an obvious template.

**Fork PRs are skipped by design.** GitHub's branch protections won't let an
Action push to a fork, and the workflow refuses to try.

## Recipe 3 — Sync (memory refresh on a schedule or pre-merge)

`sync --write` regenerates code-truth doc sections marked
`<!-- docguard:section source=code -->`. Use it on a schedule for "always up
to date" guarantees, or pre-merge as a stricter version of Recipe 2.

```yaml
name: DocGuard Nightly Sync
on:
  schedule:
    - cron: '0 6 * * *'   # daily at 06:00 UTC
  workflow_dispatch: {}
permissions:
  contents: write
  pull-requests: write
jobs:
  sync:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with: { fetch-depth: 0 }
      - uses: raccioly/docguard@v0.12.0
        with:
          command: sync
          auto-commit: 'true'   # opens a commit on default branch
          commit-message: 'docs: nightly DocGuard memory sync'
```

For the PR variant (run sync against a PR rather than scheduled), use the same
config as Recipe 2 but with `command: sync` instead of `command: fix`.

## Recipe 4 — Score (track CDD maturity over time)

Posts the CDD score as a PR comment so reviewers see whether docs are getting
better or worse with each change.

```yaml
name: DocGuard Score
on:
  pull_request: { branches: [main] }
permissions:
  contents: read
  pull-requests: write
jobs:
  score:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: raccioly/docguard@v0.12.0
        with:
          command: score
          format: json
          score-threshold: '70'   # fail PRs that drop below 70/100
```

## Pre-commit hook (no GitHub Actions required)

Run guard locally before every commit so you catch drift at typing time, not
in CI. Works with [husky](https://typicode.github.io/husky/),
[lefthook](https://github.com/evilmartians/lefthook), or plain Git hooks.

```yaml
# .lefthook.yml
pre-commit:
  commands:
    docguard:
      run: npx docguard-cli guard --changed-only
      glob: '**/*.{ts,tsx,js,jsx,py,go,rs,java,kt,rb}'
```

`--changed-only` ships in v0.12 and runs only Docs-Sync, Environment, and
API-Surface against the staged files (instead of all 27 validators against
the whole repo). See Recipe 5 below.

## Recipe 5 — Pre-commit lite (changed files only)

For developers who want zero-cost feedback before push:

```bash
npx docguard-cli guard --changed-only --since HEAD~1
```

This runs a curated subset of validators (Docs-Sync, Environment, API-Surface)
against files modified since the given ref. Designed to complete in under 2
seconds on average repos. See `docs-canonical/ARCHITECTURE.md` for the
selected-validators rationale.

## Permissions cheatsheet

| Recipe | `contents` | `pull-requests` | Notes |
|--------|------------|-----------------|-------|
| Guard | `read` | none (or `write` for score comment) | Safe on fork PRs. |
| Auto-Fix | `write` | `write` | Skips fork PRs automatically. |
| Sync | `write` | `write` (PR variant only) | Schedule variant pushes to default branch. |
| Score | `read` | `write` | Always safe. |

## Action inputs reference

| Input | Default | Used by |
|-------|---------|---------|
| `command` | `guard` | all |
| `working-directory` | `.` | all |
| `node-version` | `20` | all |
| `format` | `text` | guard / score / diff |
| `fail-on-warning` | `false` | guard |
| `score-threshold` | `0` | score |
| `auto-commit` | `false` | fix / sync |
| `commit-message` | `docs: apply DocGuard mechanical fixes` | fix / sync |
| `comment-on-pr` | `false` | fix / sync (also score has its own comment) |
| `bot-name` | `docguard-bot` | fix / sync |
| `bot-email` | `docguard-bot@users.noreply.github.com` | fix / sync |

## Action outputs reference

| Output | Type | Set by |
|--------|------|--------|
| `score` | number (0-100) | command=score |
| `grade` | string (A+..F) | command=score |
| `result` | JSON | command=score, format=json |
| `fixes-applied` | number (file count) | command=fix or sync |
| `changed-files` | newline-separated paths | command=fix or sync |
| `committed` | `"true"` / `"false"` | auto-commit=true |

Wire these into downstream steps:

```yaml
- id: fix
  uses: raccioly/docguard@v0.12.0
  with: { command: fix, auto-commit: 'true' }
- if: steps.fix.outputs.fixes-applied != '0'
  run: echo "Applied ${{ steps.fix.outputs.fixes-applied }} fixes"
```


---

## docs-canonical/DATA-MODEL.md
> Database schemas, entity relationships, and data flow

# Data Model

<!-- docguard:version 0.5.0 -->
<!-- docguard:status active -->
<!-- docguard:last-reviewed 2026-07-03 -->

| Metadata | Value |
|----------|-------|
| **Status** | ![Status](https://img.shields.io/badge/status-active-brightgreen) |
| **Version** | `0.4.0` |
| **Database** | None — DocGuard is a stateless CLI tool |
| **Storage** | File-system only (reads project files, writes generated docs) |

---

## Entities

DocGuard has **no database**. It is a stateless CLI tool that reads project files and produces output. The "data model" consists of the configuration schemas, validator output formats, and document metadata structures documented below. All data is file-system based — DocGuard reads `.docguard.json`, scans the project directory, and validates canonical documents against the codebase.

## Configuration: `.docguard.json`

The primary data structure. Controls all CLI behavior.

| Field | Type | Required | Default | Description |
|-------|------|----------|---------|-------------|
| `projectName` | `string` | No | Inferred from `package.json` name or directory | Display name for reports |
| `version` | `string` | No | `"0.1"` | Config schema version |
| `projectType` | `string` | No | Auto-detected | One of: `cli`, `webapp`, `api`, `library`, `monorepo` |
| `requiredFiles.canonical` | `string[]` | No | 5 docs-canonical files | Paths to required CDD documents |
| `requiredFiles.agentFile` | `string[]` | No | `["AGENTS.md", "CLAUDE.md"]` | AI agent config file options |
| `requiredFiles.changelog` | `string` | No | `"CHANGELOG.md"` | Changelog file path |
| `requiredFiles.driftLog` | `string` | No | `"DRIFT-LOG.md"` | Drift log file path |
| `projectTypeConfig.needsEnvVars` | `boolean` | No | `true` | Whether ENVIRONMENT.md should check for env var docs |
| `projectTypeConfig.needsEnvExample` | `boolean` | No | `true` | Whether `.env.example` is expected |
| `projectTypeConfig.needsE2E` | `boolean` | No | `true` | Whether E2E test docs are expected |
| `projectTypeConfig.needsDatabase` | `boolean` | No | `true` | Whether DATA-MODEL should expect entity docs |
| `projectTypeConfig.testFramework` | `string` | No | Auto-detected | Test framework name (e.g., `"node:test"`, `"jest"`) |
| `projectTypeConfig.runCommand` | `string` | No | Auto-detected | Command to run the project |
| `validators.*` | `boolean` | No | `true` | Enable/disable individual validators |
| `collections.*` | `string` (glob) | No | — | Binds a documentation noun to a code collection: `"extractors": "src/extractors/*.py"` lets Metrics-Consistency flag a documented count that disagrees with the file count |
| `docs.dirs` | `string[]` | No | Auto-detected | EXTENDS the auto-detected documentation homes (docs/, documentation/, guides/, …) with non-standard dirs; exclude via `.docguardignore` |
| `severity.*` | `"high" \| "medium" \| "low"` | No | `"medium"` | Per-validator exit-code weight — `high` promotes warnings to blocking, `low` demotes them (display unchanged) |

### Example Configuration

```json
{
  "projectName": "docguard",
  "version": "0.3",
  "projectType": "cli",
  "requiredFiles": {
    "canonical": [
      "docs-canonical/ARCHITECTURE.md",
      "docs-canonical/DATA-MODEL.md",
      "docs-canonical/SECURITY.md",
      "docs-canonical/TEST-SPEC.md",
      "docs-canonical/ENVIRONMENT.md"
    ],
    "agentFile": ["AGENTS.md", "CLAUDE.md"],
    "changelog": "CHANGELOG.md",
    "driftLog": "DRIFT-LOG.md"
  },
  "projectTypeConfig": {
    "needsEnvVars": false,
    "needsE2E": false,
    "needsDatabase": false,
    "testFramework": "node:test"
  },
  "validators": {
    "structure": true,
    "docsSync": true,
    "drift": true,
    "changelog": true,
    "architecture": false,
    "testSpec": true,
    "security": false,
    "environment": true,
    "freshness": true
  }
}
```

## Document Metadata Headers

Every CDD document includes DocGuard metadata as HTML comments at the top:

| Header | Type | Required | Description |
|--------|------|----------|-------------|
| `docguard:version` | `string` | Yes | Semantic version of the document |
| `docguard:status` | `string` | Yes | One of: `draft`, `active`, `deprecated` |
| `docguard:last-reviewed` | `string` | Yes | ISO date (`YYYY-MM-DD`) |
| `docguard:generated` | `boolean` | No | `true` if auto-generated by DocGuard |

### Example Metadata Header

```markdown
<!-- docguard:version 0.4.0 -->
<!-- docguard:status active -->
<!-- docguard:last-reviewed 2026-03-13 -->
```

## Validator Output Format

Each validator returns a standardized result object:

| Field | Type | Description |
|-------|------|-------------|
| `name` | `string` | Validator name (e.g., `"structure"`, `"changelog"`) |
| `status` | `string` | `"pass"`, `"warn"`, or `"fail"` |
| `checks` | `object[]` | Array of individual check results |
| `checks[].label` | `string` | Human-readable check description |
| `checks[].passed` | `boolean` | Whether the check passed |
| `checks[].message` | `string` | Details about the result |

## Fix Command Issue Format

The `fix --format json` output follows this structure:

| Field | Type | Description |
|-------|------|-------------|
| `status` | `string` | `"clean"` or `"issues-found"` |
| `project` | `string` | Project name |
| `projectType` | `string` | Detected project type |
| `issueCount` | `number` | Total issues found |
| `autoFixable` | `number` | Issues fixable by `--auto` |
| `issues[].type` | `string` | `"missing-file"`, `"empty-doc"`, `"partial-doc"`, `"missing-config"` |
| `issues[].severity` | `string` | `"error"`, `"warning"`, `"info"` |
| `issues[].file` | `string` | Affected file path |
| `issues[].autoFixable` | `boolean` | Can be auto-fixed |
| `issues[].fix.action` | `string` | `"create"`, `"rewrite"`, `"improve"` |
| `issues[].fix.ai_instruction` | `string` | AI-actionable fix instruction |

## Score Output Format

The `score --format json` output:

| Field | Type | Description |
|-------|------|-------------|
| `score` | `number` | CDD maturity score (0-100) |
| `grade` | `string` | Letter grade: `A+`, `A`, `B`, `C`, `D`, `F` |
| `breakdown` | `object` | Per-category scores |
| `breakdown.structure` | `number` | Points for docs-canonical/ structure |
| `breakdown.content` | `number` | Points for document completeness |
| `breakdown.freshness` | `number` | Points for recently updated docs |

---

## Revision History

| Version | Date | Author | Changes |
|---------|------|--------|---------|
| 0.4.0 | 2026-03-13 | DocGuard Team | Complete rewrite — documented all config formats, output schemas, metadata headers |
| 0.1.0 | 2026-03-13 | DocGuard Generate | Auto-generated skeleton |


---

## docs-canonical/ENVIRONMENT.md
> Setup instructions, environment variables, and prerequisites

# Environment

<!-- docguard:quality negation-load off — an environment doc precisely describes the ABSENCE of requirements (no env vars, no install step, no API keys, no database); the prohibitive phrasing is accurate and intentional, not sloppy writing -->

<!-- docguard:version 0.6.0 -->
<!-- docguard:status active -->
<!-- docguard:last-reviewed 2026-07-03 -->

> DocGuard needs no environment variables. It has a single optional-load npm dependency (`@babel/parser`) and optionally uses the developer's own `python3`; everything else is Node.js built-ins.

| Metadata | Value |
|----------|-------|
| **Status** | ![Status](https://img.shields.io/badge/status-active-brightgreen) |
| **Version** | `0.6.0` |

---

## Prerequisites

| Tool | Version | Installation |
|------|---------|-------------|
| Node.js | ≥18.0.0 | [nodejs.org](https://nodejs.org) |
| npm | ≥8 | Included with Node.js |
| Git | Any | [git-scm.com](https://git-scm.com) |
| Python 3 | **Optional** — ≥3.8, enables the AST-accurate Python scanning tier; the scanners use regex otherwise | [python.org](https://python.org) |

## Environment Variables

> **None required.** DocGuard reads project files directly. No `.env` file,
> no API keys, no database connections. (Its one npm dependency, `@babel/parser`,
> needs no configuration.)

## Setup Steps

1. Clone the repository: `git clone https://github.com/raccioly/docguard.git`
2. No install needed — uses only Node.js built-in modules
3. Run directly: `node cli/docguard.mjs --help`
4. Or use via npx: `npx docguard --help`

## Development

```bash
# Run CLI locally
node cli/docguard.mjs audit

# Run the full test suite (node:test)
npm test

# Test a command on a target project
node cli/docguard.mjs diagnose --dir /path/to/project

# Quick health check
node cli/docguard.mjs guard --format json
```

## CI/CD

```bash
# GitHub Actions — use the shipped template
cp templates/ci/github-actions.yml .github/workflows/docguard.yml

# Or run CI command directly
node cli/docguard.mjs ci --threshold 70 --format json
```

---

## Revision History

| Version | Date | Author | Changes |
|---------|------|--------|---------|
| 0.6.0 | 2026-05-31 | DocGuard Team | v0.24.0: documented Python 3 as an optional prerequisite (enables the AST Python tier; regex fallback when absent); de-bristled the test-count example |
| 0.5.0 | 2026-03-13 | @raccioly | Added diagnose, CI template, development examples |
| 0.3.0 | 2026-03-12 | @raccioly | Proper CLI environment docs, no env vars |
| 0.1.0 | 2026-03-12 | DocGuard Generate | Auto-generated (corrected) |


---

## docs-canonical/REQUIREMENTS.md

# Requirements

<!-- docguard:version 0.1.0 -->
<!-- docguard:status draft -->
<!-- docguard:last-reviewed 2026-07-03 -->

> Tracks functional requirements, non-functional requirements, and success criteria.
> Use requirement IDs (FR-001, NFR-001, SC-001) for traceability back to code and tests.

![CDD Canonical](https://img.shields.io/badge/CDD-Canonical-blue)

## Functional Requirements

<!-- List functional requirements with FR-NNN IDs -->

| ID | Priority | Requirement | Status | Test Coverage |
|----|----------|-------------|--------|---------------|
| FR-001 | P1 | System MUST [capability] | 🔴 Draft | ❌ |
| FR-002 | P1 | System MUST [capability] | 🔴 Draft | ❌ |
| FR-003 | P2 | Users MUST be able to [interaction] | 🔴 Draft | ❌ |

## Non-Functional Requirements

<!-- Quality attributes: performance, security, reliability -->

| ID | Category | Requirement | Verified by |
|----|----------|-------------|-------------|
| NFR-001 | Security | CLI subprocess invocations are injection-safe — agent/config-derived values are allowlist-validated and passed via `execFileSync` (no shell interpolation of untrusted input) | `tests/security-init-injection.test.mjs` |
| NFR-002 | Portability | The published package runs with **zero runtime dependencies** on Node.js ≥18 — the packaged tarball executes standalone | `tests/npm-pack-smoke.test.mjs` |
| NFR-003 | Performance | Repeat `guard` runs reuse a cross-process plan cache that is invalidated on any working-tree change | `tests/plan-disk-cache.test.mjs` |

## Success Criteria

<!-- Measurable outcomes — aligned with spec-kit SC-NNN format -->

| ID | Criteria | Measurement | Target |
|----|----------|-------------|--------|
| SC-001 | [Measurable user outcome] | [How measured] | [Target value] |
| SC-002 | [Performance metric] | [How measured] | [Target value] |

## User Scenarios

<!-- Spec-kit aligned: Given/When/Then acceptance scenarios -->

### User Story 1 - [Title] (Priority: P1)

[Description of user journey]

**Acceptance Scenarios**:
1. **Given** [initial state], **When** [action], **Then** [expected outcome]
2. **Given** [initial state], **When** [action], **Then** [expected outcome]

## Traceability Matrix

<!-- Maps requirements → code → tests -->

| Requirement | Source File | Test File | Status |
|-------------|------------|-----------|--------|
| FR-001 | `src/[file]` | `tests/[file]` | ❌ |

## Revision History

| Version | Date | Author | Changes |
|---------|------|--------|---------|
| 0.1.0 | 2026-05-26 | DocGuard Init | Initial template |

---

*Generated by [DocGuard](https://github.com/raccioly/docguard) — aligned with [Spec Kit](https://github.com/github/spec-kit) standards.*


---

## docs-canonical/SECURITY.md
> Authentication, authorization, secrets management, and security policies

# Security

<!-- docguard:quality negation-load off — security doc: prohibitive phrasing ("never a shell string", "can't inject", "no dependencies") is precise and intentional, not sloppy writing -->

<!-- docguard:version 0.6.0 -->
<!-- docguard:status active -->
<!-- docguard:last-reviewed 2026-07-03 -->

| Metadata | Value |
|----------|-------|
| **Status** | ![Status](https://img.shields.io/badge/status-active-brightgreen) |
| **Version** | `0.6.0` |

---

## Overview

DocGuard is a **local CLI tool** that runs entirely on the user's machine. It reads project files from the filesystem and produces terminal output. It operates **fully offline**, requires **zero authentication**, and is **credential-free**.

## Authentication

| Method | Provider | Scope |
|--------|---------|-------|
| **None required** | N/A | DocGuard is a local-only CLI tool. Runs without auth. |

DocGuard operates purely on the local filesystem. All processing stays on-machine — fully isolated from servers, APIs, and cloud services.

## Authorization

| Role | Permissions | Notes |
|------|-----------|-------|
| **User** (local machine) | Full access — read/write project files | DocGuard runs with the permissions of the user invoking it |
| **CI Pipeline** | Read-only (guard, score, ci commands) | CI typically only runs validation, not init/generate |
| **AI Agent** | Depends on AI agent permissions | AI agents run DocGuard via terminal — they inherit the user's or CI's permissions |

DocGuard uses a simple permission model: it inherits filesystem permissions from the calling process.

## Secrets Management

| Secret | Storage | Used By | Notes |
|--------|---------|---------|-------|
| **None** | N/A | N/A | DocGuard requires no API keys, tokens, or credentials |

### DocGuard Security Posture

- Treats `.env` files as **project artifacts only** (checks their existence for your project, never reads values)
- Operates **100% offline** — zero HTTP requests to any API
- Writes **only within the project directory** — all output stays local
- Runs with **standard user permissions** — elevated access is unnecessary

## Security Boundaries

| Boundary | Trusted | Untrusted |
|----------|---------|-----------|
| **File reads** | Project files within `projectDir` | DocGuard only reads files within the project directory and its own templates |
| **File writes** | `docguard init`, `docguard generate`, `docguard hooks` | Only writes to `docs-canonical/`, root docs, `.docguard.json`, `.git/hooks/` |
| **Child processes** | `git log`/`git diff` (freshness), `specify init` (Spec Kit scaffolding), `python3` (Python AST parsing) | All spawned via `execFileSync`/`spawnSync` with an argv array — never a shell string. The binary is `argv[0]` (a literal filename) and each arg a literal token; the `python3` extractor script is a constant passed via `-c` and the file paths it parses arrive on stdin, never spliced into argv — so workspace paths and config values can't inject commands |
| **User input** | CLI arguments parsed by the entry point | Agent/path inputs that reach a subprocess are allowlist-validated (`/^[a-zA-Z0-9_-]{1,32}$/`) before use |

## Command Safety Levels

| Command | Reads Files | Writes Files | Runs Git | Risk |
|---------|------------|-------------|----------|------|
| `audit` | ✅ | ❌ | ❌ | None |
| `guard` | ✅ | ❌ | ✅ (read-only) | None |
| `score` | ✅ | ❌ | ❌ | None |
| `diff` | ✅ | ❌ | ✅ (read-only) | None |
| `fix` | ✅ | ❌ | ❌ | None |
| `ci` | ✅ | ❌ | ✅ (read-only) | None |
| `badge` | ✅ | ❌ | ❌ | None |
| `init` | ✅ | ✅ Creates docs | ❌ | Low — creates new files only, never overwrites |
| `generate` | ✅ | ✅ Creates docs | ❌ | Low — creates new files only, never overwrites |
| `hooks` | ✅ | ✅ Writes `.git/hooks/` | ❌ | Low — writes executable git hooks |

## Supply Chain

| Category | Status |
|----------|--------|
| **npm dependencies** | **One** — `@babel/parser` (exact-pinned), for AST-accurate JS/TS parsing |
| **Runtime dependencies** | Node.js ≥ 18, `git` (optional, for freshness checks), `python3` (optional, for Python AST parsing) |
| **Transitive dependencies** | `@babel/types` + 2 small `@babel/helper-*` packages — all first-party Babel |
| **Known vulnerabilities** | None known — `npm audit` is clean; the `@babel/*` tree is the only audit surface |

The dependency surface is deliberately minimal: a single exact-pinned, heavily-vetted parser (172M downloads/week, multi-maintainer) that loads **optionally** — if it's absent the CLI falls back to the regex tier rather than failing. New dependencies are governed by the constitution's exact-pin + supply-chain-vetting rule.

## .gitignore Audit

DocGuard's own `.gitignore` excludes:

| Pattern | Purpose |
|---------|---------|
| `node_modules/` | npm packages — the single runtime dep (`@babel/parser`); installed by npm, never committed |
| `.env` | Environment files (not used, but excluded as best practice) |

## Security Rules Checklist

- [x] Code is credential-free
- [x] `.env` files are excluded from version control
- [x] All secrets are environment-variable-based
- [x] CLI operates 100% offline
- [x] Subprocesses use `execFileSync` (argv arrays, no shell); injection-prone inputs are allowlist-validated (closed #190 in CLI init); the GitHub Action passes all inputs via `env:` rather than splicing them into shell
- [x] File writes are opt-in only (init, generate, hooks commands)
- [x] Git commands are read-only (`git log`, `git diff`)
- [x] Single exact-pinned, vetted dependency (`@babel/parser`) keeps supply-chain surface minimal; loads optionally with regex fallback

---

## Revision History

| Version | Date | Author | Changes |
|---------|------|--------|---------|
| 0.4.0 | 2026-03-13 | DocGuard Team | Complete rewrite — documented zero-auth model, command safety levels, supply chain posture |
| 0.1.0 | 2026-03-13 | DocGuard Generate | Auto-generated skeleton |


---

## docs-canonical/SURFACE-AUDIT.md

# DocGuard Surface Audit

<!-- docguard:quality negation-load off — analytical audit doc: findings are inherently stated as "guard cannot catch X", "names don't telegraph Y"; these negations are the substance, not sloppy phrasing -->

> ⚠️ **HISTORICAL SNAPSHOT — findings resolved.** This audit describes **v0.18.1
> (2026-05-26)** and its counts are NOT current. Its recommendations shipped:
> the `canonical-sync` validator landed in v0.19.0 (command/validator counts are
> now machine-governed — `guard` fails when they drift), and the surface
> consolidation landed in v0.20.0 (21 → 13 commands + deprecation aliases; see
> MIGRATION-v0.20.md). Kept as the worked example of the audit → fix loop.
> **Do not cite counts from this document** — the governed truth lives in
> README.md and is validated on every `guard` run.

> **Status:** Survey only — recommendations, no code changes.
> **Owner:** Ricardo Accioly · **Date:** 2026-05-26 · **DocGuard:** v0.18.1 (v0.19.0 staged but unpushed)
> **Scope:** Every command, every validator, every doc claim about either. The question: did 15 releases of additive work leave us with too many similar verbs for users to learn, and where is the doc-vs-code drift that `guard` can't see today?

---

## 1. Executive Summary

**TL;DR for the busy reader:**

1. **The README counts are wrong in three different ways.** Filesystem says 21 command files; `--help` shows 16 publicly; the README claims "ships 19 commands." `guard` runs 22 validators (note: this audit was conducted before v0.19's canonical-sync validator was added — the post-v0.19 count is 23); only 20 files exist (2 are inlined). Three of those claims I changed in the just-rolled-back v0.19.0 commit were *also* wrong because I trusted the previous README instead of counting.
2. **6 commands exist but `--help` doesn't list them:** `audit` (alias of `guard`), `explain`, `impact`, `llms`, `memory`, `upgrade`. Plus 11 alias variants (`gen`, `repair`, `dx`, `pipeline`, `badges`, etc.) — none documented. Users discover these from release notes if they read them.
3. **The surface is meaningfully wider than the value justifies.** 21 user-facing commands. Three of them (`init`, `setup`, `generate`) all "initialize." Three more (`diff`, `sync`, `impact`) all "show what changed." Four (`agents`, `badge`, `ci`, `hooks`) are one-shot scaffolders that could be sub-modes of `init`. That's ~10 verbs that probably should be ~4.
4. **`guard` cannot catch the README drift today.** `metrics-consistency` only cross-checks doc-to-doc numbers. The truth lives in code (file count, what `--help` enumerates, what `guard` actually runs). We need one new validator — **canonical-sync** — that asserts those code-truth counts match what the docs claim. About 200 lines, fully mechanical.
5. **Recommended path for v0.19.0:** Don't expand the surface further. Ship the **smoke gate + e2e fix + correct counts + canonical-sync validator + surface the 6 ghost commands in `--help`** as v0.19.0. Defer the actual *consolidation* (renames, aliases, deprecations) to v0.20.0 where it's the headline change with a migration guide.

The rest of this doc is the evidence.

---

## 2. Hard Data — What's Actually in the Codebase

### 2.1 Commands

**Filesystem (`cli/commands/*.mjs`): 21 files**

| File | Routes to | In `--help`? | Aliases in router |
|------|-----------|--------------|-------------------|
| `agents.mjs` | `agents` | ✅ Utilities | — |
| `badge.mjs` | `badge` | ✅ Utilities | `badges` |
| `ci.mjs` | `ci` | ✅ CI/CD | `pipeline` |
| `diagnose.mjs` | `diagnose` | ✅ Enforcement | `dx` |
| `diff.mjs` | `diff` | ✅ Analysis | — |
| `explain.mjs` | `explain` | ❌ **ghost** | `help-warning` |
| `fix.mjs` | `fix` | ✅ Utilities | `repair` |
| `generate.mjs` | `generate` | ✅ Getting Started + Memory | `gen` |
| `guard.mjs` | `guard` (also handles `audit` alias) | ✅ Enforcement | `audit` |
| `hooks.mjs` | `hooks` | ✅ CI/CD | — |
| `impact.mjs` | `impact` | ❌ **ghost** | — |
| `init.mjs` | `init` | ✅ Getting Started | — |
| `llms.mjs` | `llms` | ❌ **ghost** | — |
| `memory.mjs` | `memory` | ❌ **ghost** | — |
| `publish.mjs` | `publish` | ⚠️ Experimental | `pub` |
| `score.mjs` | `score` | ✅ Analysis | — |
| `setup.mjs` | `setup` | ✅ Getting Started | `onboard` |
| `sync.mjs` | `sync` | ✅ Memory | — |
| `trace.mjs` | `trace` | ✅ Analysis | `traceability` |
| `upgrade.mjs` | `upgrade` | ❌ **ghost** | `update` |
| `watch.mjs` | `watch` | ✅ CI/CD | — |

**Aggregate: 21 commands · 16 surfaced in `--help` · 5 fully hidden ghosts · 1 experimental · 11 alias variants none of which are documented anywhere.**

The `audit` case still exists in the router (line 526) purely as an alias to `guard`. It's not in `--help`. So technically there are 22 routable command words, but `audit` is just historic compatibility.

### 2.2 Validators

**Filesystem (`cli/validators/*.mjs`): 20 files. `guard` actually runs 22.**

The 2 extras:
- **"Doc Sections"** — exported as `validateDocSections` from `structure.mjs` (same file as Structure validator). Two validators, one file. Defensible — they share a lot of code — but the file name doesn't telegraph it.
- **"Spec-Kit"** — exported as `validateSpecKitIntegration` from `cli/scanners/speckit.mjs`. A "validator" that lives in `scanners/`. **This is architecturally wrong** — scanners are supposed to be passive code-readers; validators are the things that have severity/pass/fail semantics. Moving this to `cli/validators/spec-kit.mjs` is a trivial cleanup.

Full guard-reported list (canonical names):

```
Structure · Doc Sections · Docs-Sync · Drift-Comments · Changelog · Test-Spec ·
Environment · Security · Architecture · Freshness · Traceability · Docs-Diff ·
API-Surface · Metadata-Sync · Docs-Coverage · Doc-Quality · TODO-Tracking ·
Schema-Sync · Spec-Kit · Cross-Reference · Generated-Staleness · Metrics-Consistency
```

22 — matches the README claim on lines 90 and 411. Only the architecture diagram (which I tried to "fix" from `(19)` to `(22)` in the rolled-back commit) was actually right with `(22)`. The `(19)` it started at was the stale one.

### 2.3 Where the truth lives

| Truth | Where to read it |
|------|------------------|
| Real command count | `ls cli/commands/*.mjs \| wc -l` (21) |
| User-facing command count | Count items in the `--help` Getting-Started/Enforcement/Memory/Analysis/CI-CD/Utilities/Experimental sections of `printHelp()` in `cli/docguard.mjs` |
| Real validator count | `runGuardInternal(...).validators.length` (22) — NOT `ls cli/validators/*.mjs \| wc -l` (which is 20) |
| Real validator name list | `runGuardInternal(...).validators.map(v => v.name)` |

This is what the new **canonical-sync** validator should read from, not the filesystem count.

---

## 3. Doc Drift — Every Count Claim, Marked

Run on v0.18.1 / current repo state:

| File:Line | Claim | Reality | Verdict |
|-----------|-------|---------|---------|
| `README.md:90` | "any of the 22 validators" | guard runs 22 ✓ | ✅ Correct (newly added in rolled-back commit) |
| `README.md:238` | "DocGuard ships **19 commands**" | 21 files, 16 in `--help` | ❌ Wrong both ways |
| `README.md:411` | "/docguard.guard … all 22 validators" | 22 ✓ | ✅ Correct |
| `README.md` architecture diagram `Commands (19)` | (in current HEAD it says "Commands (15)") | 21 files / 16 user-facing | ❌ Wrong both versions |
| `README.md` architecture diagram `Validators (22)` | (current HEAD says "Validators (19)") | 22 ✓ | ❌ Current HEAD wrong; rolled-back fix was right |
| `ROADMAP.md:50` | "the zero-dependency CLI tool with **9 validators** and 8 core templates" | Was true for v0.7-ish | ⚠️ Stale (intentional — phase log) |
| `ROADMAP.md:55` | "9 validators: structure, doc-sections, docs-sync, drift, changelog, test-spec, environment, security, architecture" | Was true for v0.7-ish | ⚠️ Stale (intentional — phase log) |
| `ROADMAP.md:102` | "VS Code extension … 6 commands" | Out of scope — VS Code ext is its own repo | n/a |
| `STANDARD.md` | (no count claims found) | n/a | ✅ |
| `PHILOSOPHY.md` | (no count claims found) | n/a | ✅ |
| `COMPARISONS.md` | (no count claims found) | n/a | ✅ |

**Insight:** ROADMAP entries are intentional historical phase logs and should stay. README is the live surface and should match code-truth. STANDARD/PHILOSOPHY/COMPARISONS already abstract over counts — good pattern, no regression risk there.

**The one validator we need (canonical-sync) catches lines 238 and the architecture diagram. That's the entire blast radius for v0.19.0.**

---

## 4. Overlap Matrix — Where the Surface Sprawled

Annotated by intent, not file structure. The right framing: "if I were a new user, would I know which one to reach for?"

### 4.1 Initialization cluster — three commands to start a project

| Command | What it does | Who reaches for it |
|---------|--------------|--------------------|
| `init` | Creates `docs-canonical/` skeleton, `.docguard.json`, optional spec-kit handoff | First-time setup of a *new* project |
| `setup` | Interactive 7-step wizard: project detection → docs → skills → slash commands → agent configs → integrations → hooks | Same first-time setup but with more hand-holding |
| `generate` | Reverse-engineers docs from existing code (the "killer feature") | First-time setup of a *project that already exists* |

**Honest overlap:** `init` is the bare-bones path, `setup` is the wizard, `generate` is the AI-fill-it-in path. Three valid mental models but the names don't telegraph that. A new user reading `--help` sees three "Getting Started" items and has to guess.

**Recommended renaming (v0.20):**
- `init` → unchanged (bare skeleton, the "I know what I want" path)
- `setup` → fold into `init --wizard` (interactive flag, not a separate verb)
- `generate` → `init --from-code` (or keep `generate` as a top-level since the AI integration is the marquee story, but make `init --from-code` an alias so users have a discoverable path)

### 4.2 "What changed" cluster — three commands answer one question

| Command | What it tells you | Granularity |
|---------|-------------------|-------------|
| `diff` | Current snapshot: gaps between docs and code right now | Whole project |
| `sync` | Same data, but *applies* the mechanical fix (`--write`) | Whole project |
| `impact` | "Files changed since `--since`; which doc sections reference any of them?" | Per-changed-file → affected docs |

Defensible separation if you squint: `diff` reports, `sync` writes, `impact` filters by recency. But the names don't telegraph that.

**Recommended renaming (v0.20):**
- Keep `diff` (read-only inspection — clear verb)
- Keep `sync` (write/apply — clear verb)
- Rename `impact` → `diff --since <ref>` (it's a filtered diff, not a different operation). Keep `impact` as a deprecation alias for one release.

### 4.3 Scaffolders cluster — four one-shot writers

| Command | Writes | Re-runs needed? |
|---------|--------|-----------------|
| `agents` | `.cursor/rules/`, `.clinerules`, `.github/copilot-instructions.md`, etc. | Rarely |
| `badge` | Shields.io URL or markdown | Rarely |
| `ci` | GitHub Actions / pipeline YAML | Rarely |
| `hooks` | `.husky/` git hooks | Rarely |

All four are "scaffold this thing once" commands. None of them have ongoing semantics. They're conceptually closer to `init --with=X` than to top-level verbs.

**Recommended renaming (v0.20):**
- Add `init --with agents,hooks,ci,badge[,llms,publish]` as the canonical entry point
- Keep the four top-level commands as deprecation aliases for one release with a `(now: \`init --with agents\`)` hint in their help text

### 4.4 Introspection cluster — five ways to ask "what's the state"

| Command | What you ask | What you get |
|---------|--------------|--------------|
| `score` | "How good are my docs (0-100)?" | Weighted category breakdown |
| `score --diff` | "What changed in the score between commits?" | Per-category delta |
| `memory` | "What does DocGuard remember about my code?" | Memory accuracy headline (same number `score` shows) |
| `memory --diff` | "Which doc claims don't match code right now?" | Per-domain drill-down |
| `trace` | "Map docs ↔ code ↔ tests" | Requirements traceability matrix |
| `trace --reverse` | "Which doc sections reference this code file?" | Reverse map |
| `explain` | "What is this validator/warning?" | Static help text |
| `diff` | "What's drifted right now?" | Current state snapshot |

**Defensible.** These genuinely answer different questions. The risk isn't overlap, it's discoverability — `memory` and `explain` are ghost commands in `--help` today.

**Recommended fix (v0.19):** Surface all of them in `--help`. Don't rename.

### 4.5 Action cluster — three ways to fix something

| Command | What it does | Manual / Automated |
|---------|--------------|--------------------|
| `fix` | Per-doc AI fix prompt generator (`--doc <name> --format prompt`) | Manual (AI writes) |
| `diagnose` | Run `guard` + emit AI fix prompts for everything in one shot | Manual (AI writes) |
| `sync --write` | Mechanical fix for source=code sections (no AI needed) | Automated |
| `fix --write` | Same `sync --write` data plus mechanical changelog/metrics/metadata patches | Automated |
| `upgrade --apply` | Migrate `.docguard.json` schema (and optionally CLI version) | Automated |

**Honest overlap:** `fix --write` and `sync --write` do the same mechanical fixes for the section-marker case. `fix` ≈ "AI fix for this one thing"; `diagnose` ≈ "AI fix for everything"; `sync --write` ≈ "no AI, just refresh"; `upgrade` ≈ "migrate config schema."

**Recommended (v0.20):** Document the mental model explicitly in `--help`:
- `fix` — manual, AI-assisted, one-doc-at-a-time
- `diagnose` — manual, AI-assisted, whole-project
- `sync` — automated, mechanical, idempotent

No renames. Just better grouping in `--help`.

---

## 5. Proposed Target Surface (v0.20+)

After consolidation, the verbs a new user has to learn:

### Tier 1 — "the daily five" (always in `--help` Quick Reference)

| Verb | Purpose | Replaces |
|------|---------|----------|
| `init` | Bootstrap (skeleton, wizard, or from-code via flags) | `init`, `setup`/`onboard`, parts of `generate` |
| `guard` | Validate | `guard`, `audit` |
| `diff` | Inspect drift (current + `--since <ref>` for impact) | `diff`, `impact` |
| `sync` | Apply mechanical fixes | `sync` (unchanged) |
| `score` | CDD maturity score (with `--diff` for delta) | `score` (unchanged) |

### Tier 2 — "the situational verbs" (in `--help` Tools section)

| Verb | Purpose |
|------|---------|
| `fix` | Generate per-doc AI fix prompt |
| `diagnose` | Whole-project AI fix orchestrator |
| `generate` | Reverse-engineer from existing code (keep as a top-level — marquee feature) |
| `explain` | Static help for a validator or warning |
| `memory` | Show what DocGuard remembers + `--diff` |
| `trace` | Traceability matrix + `--reverse` |
| `upgrade` | Migrate config / CLI |
| `watch` | Live re-validation |

### Tier 3 — folded into `init --with`

`agents`, `badge`, `ci`, `hooks`, `llms`, `publish` — all become `init --with <name>` with deprecation aliases for one release.

**Net surface for users:** 5 daily verbs + 8 situational verbs = **13 commands** instead of 21. Plus `--help` groups them by use-case, not by alphabet.

### What this audit explicitly does NOT recommend

- **No mass renames.** The names that already work (`guard`, `fix`, `diff`, `score`, `sync`) stay. Renaming a working verb is a tax users pay for cleanup-theater. The win is *removing* and *folding*, not *renaming*.
- **No breaking changes in v0.19.** Every existing command word keeps working through v0.20 with an alias.
- **No new aliases beyond what's needed for backwards-compat.** `gen`, `repair`, `dx`, `pipeline`, `badges`, `audit`, `update`, `onboard`, `help-warning`, `traceability`, `pub` — these 11 cute aliases are currently undocumented anywhere. v0.20 should pick one shape: either *document all of them* (don't) or *quietly drop them, keeping only `audit→guard` for backwards-compat* (do this).

---

## 6. Migration Plan (v0.19.0 → v0.20.0)

### v0.19.0 — "make `guard` self-aware"

Goal: ship the smoke gate + e2e fix from the rolled-back commit, plus the *minimum* surface fix that proves `guard` can police its own claims.

1. **Add `canonical-sync` validator** (see §7). Catches `cli/commands/*.mjs` count drift vs README claim, and `runGuardInternal().validators.length` drift vs README claim. ~200 lines + tests.
2. **Surface the 6 ghost commands in `--help`** — `explain`, `impact`, `llms`, `memory`, `upgrade`, plus a Utilities note for `audit` (alias).
3. **Correct README to real counts.** `21 commands (16 user-facing)` and `23 validators`. Architecture diagram numbers match.
4. **Pin alias usage in `--help`.** Each command's section shows the canonical name only; aliases are not documented (we'll deprecate them in v0.20).
5. **Move `validateSpecKitIntegration` from `cli/scanners/speckit.mjs` to `cli/validators/spec-kit.mjs`.** Architectural cleanup; file count then matches validator count (21 → 22).

After v0.19.0, `node cli/docguard.mjs guard` will fail loudly if anyone changes a command file count without updating the README — exactly the missing check that let v0.13's stale "Commands (15)" survive five releases.

### v0.20.0 — "the consolidation release"

Goal: reduce the user-facing verbs from 21 to 13. Every existing command keeps working through this release; deprecation warnings flag the new shape.

1. **Deprecate `setup`/`onboard` → `init --wizard`.** Print the warning, keep working.
2. **Deprecate `impact` → `diff --since <ref>`.** Print the warning, keep working.
3. **Deprecate `agents`/`badge`/`ci`/`hooks`/`llms`/`publish` → `init --with <name>`.** Print warning, keep working.
4. **Drop the cute aliases** (`gen`, `repair`, `dx`, `pipeline`, `badges`, `update`, `pub`, `help-warning`, `traceability`). Keep only `audit → guard` (backward compat with historical CI scripts).
5. **Reorganize `--help` into the Tier-1 / Tier-2 / Tier-3 structure from §5.**
6. **Migration guide:** `docs-implementation/MIGRATION-v0.20.md` with a per-command before/after table.

### v1.0.0 — "remove the deprecation aliases"

After v0.20 has been out for ~2–3 months. Just delete the alias cases from the router. Print a clear error suggesting the v0.20 replacement.

---

## 7. New Validator Spec: `canonical-sync`

The check that would have prevented this entire audit being necessary.

**File:** `cli/validators/canonical-sync.mjs`
**Severity:** `high` (a doc lying about the tool's basic surface is a credibility-killer)
**Cost:** Cheap. Runs `runGuardInternal`-style validator-list query (already in memory) + reads `cli/commands/` directory + greps a handful of README patterns.

### Rules

For each of these claims in README, STANDARD, PHILOSOPHY, COMPARISONS, ROADMAP:

| Pattern | Code-truth source | Fail mode |
|---------|-------------------|-----------|
| `(\d+)\s+commands?` (in a sentence about DocGuard's surface, not a phase log) | Count of `cli/commands/*.mjs` files | Mismatch → WARN with the right number |
| `(\d+)\s+validators?` | `runGuardInternal(...).validators.length` | Mismatch → WARN |
| `(\d+)\s+checks?` | `runGuardInternal(...).validators.reduce((n,v)=>n+v.total,0)` (where `total` is the per-validator check count) | Mismatch → WARN |
| Validator names listed inline (e.g. "Structure, Doc Sections, Docs-Sync, ...") | `runGuardInternal(...).validators.map(v => v.name)` | Missing or extra name → WARN with diff |
| Command names listed in tables | Files in `cli/commands/*.mjs` | Missing or extra → WARN |

### Opt-out & scope

- Skips files in `docs-implementation/` and `ROADMAP.md` (phase logs are legitimately historical)
- Skips `<!-- docguard:section source=human -->` blocks (prose, not surface inventory)
- Honors `config.canonicalSyncIgnore` for project-specific opt-out

### Test cases (drives implementation)

1. README claims "21 commands", filesystem has 21 → pass.
2. README claims "19 commands", filesystem has 21 → warn with "expected 21".
3. README lists 22 validator names matching `guard` output → pass.
4. README lists 21 validator names + 1 wrong name → warn with diff.
5. ROADMAP.md says "9 validators" in a phase log → pass (file is excluded).
6. `docs-implementation/CURRENT-STATE.md` says "5 commands" → pass (file is excluded).

### Why not `--write` for this validator

Tempting, but no. The count-mismatch fix is often *not* "edit the number" — it's "go look at what changed in `--help` and reorganize the table around it." A mechanical patch that just bumps `19 → 21` would mask the real action item (which 5 commands are new and where do they belong in the doc's flow). WARN-only is the right shape.

---

## 8. Open Questions for the Owner

1. **`audit` alias:** keep forever or drop in v1.0? It's been in the router since v0.5-ish and may be in someone's CI script. Cost to keep: 2 router lines. **Recommend: keep.**
2. **`generate` vs `init --from-code`:** keep both? `generate` is the marquee story but `init --from-code` is more discoverable. **Recommend: keep `generate` as top-level; add `init --from-code` as an alias that prints "running `docguard generate`…" and dispatches.**
3. **`publish` (Mintlify scaffolder):** it's marked Experimental and is the only Tier-3 candidate that *isn't* purely additive (it talks to an external platform). Fold into `init --with publish` like the others, or pull it out to its own plugin? **Recommend: fold for v0.20 since it's still experimental.**
4. **Validator name consistency:** "Drift-Comments" in guard output but `drift.mjs` filename — same for "TODO-Tracking" / `todo-tracking.mjs`, etc. Mostly fine but worth one consistency pass in v0.20.
5. **`canonical-sync` validator's own credibility:** should the validator validate its own claim? (i.e. README says "23 validators including canonical-sync" — does `canonical-sync` count itself?). **Recommend: yes, count itself. The whole point is the count being self-policed.**

---

## 9. What Lives Where (for future-Ricardo)

For anyone reading this six months from now:

- **Hard count truth:** `cli/commands/*.mjs` (filesystem) + `cli/docguard.mjs` printHelp (user-facing) + `cli/commands/guard.mjs` validator registration array (validators)
- **Doc claims:** README.md (Usage, architecture diagram, validators section) + STANDARD.md (no counts, intentional) + PHILOSOPHY.md (no counts, intentional)
- **Phase logs (excluded from canonical-sync):** ROADMAP.md, CHANGELOG.md, docs-implementation/CURRENT-STATE.md
- **This audit:** `docs-canonical/SURFACE-AUDIT.md` — refresh quarterly or whenever surface changes more than ±3 commands

---

*End of audit. No code touched. Awaiting owner decision on v0.19.0 scope (§6.1) and v0.20.0 consolidation (§6.2).*


---

## docs-canonical/TEST-SPEC.md
> Test coverage requirements, testing strategy, and quality rules

# Test Specification

<!-- docguard:version 0.8.0 -->
<!-- docguard:status active -->
<!-- docguard:last-reviewed 2026-07-03 -->

> DocGuard has a single optional-load npm dependency (`@babel/parser`) and an optional `python3` AST tier. CLI integration tests cover the full stack with `node:test` (zero dev dependencies) and exercise both AST extractors (`js-ast`, `py-ast`) plus their regex fallbacks. The Python AST tests skip themselves automatically on a machine that lacks `python3`.

| Metadata | Value |
|----------|-------|
| **Status** | ![Status](https://img.shields.io/badge/status-active-brightgreen) |
| **Project Type** | CLI |
| **Test Framework** | `node:test` (built-in) |
| **Test Files** | `tests/` |

---

DocGuard's tests verify command behavior through subprocess execution. Each test runs the full CLI binary via execSync, capturing stdout and checking output patterns. This approach tests the complete stack in a single pass: argument parsing, config loading, validator execution, and output formatting.

Tests are designed to be config-aware. They verify that project-type settings like needsEnvExample and testFramework correctly influence scoring and validation behavior. Regression guards pin specific bug fixes with dedicated assertions, ensuring fixed issues cannot recur.

All tests use the built-in node:test framework with zero test dependencies. The test suite runs in under 10 seconds and is executed automatically by CI on every push.

Test names follow the pattern: "verb + expected behavior" (e.g., "runs and shows a score", "respects projectTypeConfig"). Each test is self-contained with no shared mutable state between tests.

## Test Categories

| Category | Framework | Location | Run Command |
|----------|-----------|----------|-------------|
| Unit | node:test | tests/ | `npm test` |
| CLI Integration | node:test | tests/ | `npm test` |

> **CLI integration tests cover the full stack** — this is a CLI tool with zero UI surface.
> Commands are validated end-to-end via Node.js subprocess execution, making separate E2E tests redundant.

All test files live in `tests/` and match the glob `tests/*.test.mjs` — individual files are not enumerated here (the suite grows every release); see the Source-to-Test Map below for the source→test traceability that matters.

## Coverage Rules

| Metric | Target | Current |
|--------|:------:|:-------:|
| Command Coverage | 100% | 100% (all commands) |
| Validator Coverage | 80% | 100% (all validators) |
| Flag Coverage | 80% | 100% |
| Test Count | — | 600+ tests (`npm test`) |

## Source-to-Test Map

| Source File | Test File | Status |
|------------|-----------|:------:|
| `cli/docguard.mjs` | `tests/commands.test.mjs` | ✅ |
| `cli/shared.mjs` | `tests/commands.test.mjs` | ✅ |
| `cli/commands/init.mjs` | `tests/commands.test.mjs` | ✅ |
| `cli/commands/guard.mjs` | `tests/commands.test.mjs` | ✅ |
| `cli/commands/score.mjs` | `tests/commands.test.mjs` | ✅ |
| `cli/commands/diff.mjs` | `tests/commands.test.mjs` | ✅ |
| `cli/commands/generate.mjs` | `tests/commands.test.mjs` | ✅ |
| `cli/commands/agents.mjs` | `tests/commands.test.mjs` | ✅ |
| `cli/commands/hooks.mjs` | `tests/commands.test.mjs` | ✅ |
| `cli/commands/diagnose.mjs` | `tests/commands.test.mjs` | ✅ |
| `cli/commands/badge.mjs` | `tests/commands.test.mjs` | ✅ |
| `cli/commands/ci.mjs` | `tests/commands.test.mjs` | ✅ |
| `cli/commands/fix.mjs` | `tests/commands.test.mjs` | ✅ |
| `cli/commands/watch.mjs` | `tests/commands.test.mjs` | ✅ pass |
| `cli/commands/publish.mjs` | `tests/commands.test.mjs` | ✅ |
| `cli/commands/trace.mjs` | `tests/commands.test.mjs` | ✅ |
| `cli/validators/structure.mjs` | `tests/commands.test.mjs` | ✅ |
| `cli/validators/docs-diff.mjs` | `tests/commands.test.mjs` | ✅ |

> **Note**: `watch.mjs` is an interactive file-watcher (uses `fs.watch` + process signals). It is
> verified via manual execution rather than automated tests, which is appropriate for
> interactive/daemon-style commands per ISO/IEC/IEEE 29119-3 §7.2 (manual test procedures).

## Critical CLI Flows

| # | Flow | Test File | Status |
|---|------|-----------|:------:|
| 1 | `docguard audit` | `tests/commands.test.mjs` | ✅ |
| 2 | `docguard init` | `tests/commands.test.mjs` | ✅ |
| 3 | `docguard guard` | `tests/commands.test.mjs` | ✅ |
| 4 | `docguard guard --format json` | `tests/commands.test.mjs` | ✅ |
| 5 | `docguard score` | `tests/commands.test.mjs` | ✅ |
| 6 | `docguard score --format json` | `tests/commands.test.mjs` | ✅ |
| 7 | `docguard score --tax` | `tests/commands.test.mjs` | ✅ |
| 8 | `docguard diagnose` | `tests/commands.test.mjs` | ✅ |
| 9 | `docguard diagnose --format json` | `tests/commands.test.mjs` | ✅ |
| 10 | `docguard generate` | `tests/commands.test.mjs` | ✅ |
| 11 | `docguard init --profile starter` | `tests/commands.test.mjs` | ✅ |

---

## Revision History

| Version | Date | Author | Changes |
|---------|------|--------|---------|
| 0.7.0 | 2026-03-13 | @raccioly | Added trace, publish; watch.mjs coverage justified (ISO 29119); 15 commands |
| 0.5.0 | 2026-03-13 | @raccioly | Added diagnose, guard JSON, profile, tax tests (24→30) |
| 0.3.0 | 2026-03-12 | @raccioly | Real tests, project-type-aware spec |
| 0.1.0 | 2026-03-12 | DocGuard Generate | Auto-generated (corrected) |
| `cli/scanners/schemas.mjs` | `tests/schemas.test.mjs` | ✅ |


---

## DRIFT-LOG.md
> Known deviations from canonical documentation

# Drift Log

> Documents conscious deviations from canonical specifications.
> Every `// DRIFT: reason` in code must have a corresponding entry here.

| Date | File | Canonical Doc | Drift Description | Severity | Resolution |
|------|------|---------------|-------------------|----------|------------|
| 2026-03-13 | `cli/commands/generate.mjs` | ARCHITECTURE.md | AGENTS.md template includes `// DRIFT: reason` as an instruction pattern for end users. These are template strings, not actual code deviations. | Info | By design — template content |
| 2026-03-13 | `cli/commands/generate.mjs` | ARCHITECTURE.md | DRIFT-LOG.md template includes `// DRIFT: reason` as placeholder text. | Info | By design — template content |
| 2026-03-13 | `cli/commands/agents.mjs` | ARCHITECTURE.md | Agent config generators include `// DRIFT: reason` as instruction text for AI agents. 3 occurrences across Windsurf, Cursor, and generic agent configs. | Info | By design — instruction content |
| 2026-03-13 | `cli/validators/drift.mjs` | ARCHITECTURE.md | Drift validator references `// DRIFT:` pattern in JSDoc and regex. | Info | By design — validator implementation |
| 2026-05-12 | `tests/drift.test.mjs` | ARCHITECTURE.md | Drift validator tests use `// DRIFT:` comments to simulate project files having drift comments. | Info | By design — test implementation |
| 2026-05-26 | `tests/scoping-extended.test.mjs` | ARCHITECTURE.md | v0.15 P3 test fixture builds `// D' + 'RIFT:` strings via concat to test changed-files scoping without false-positiving the outer scan. | Info | By design — test implementation; mitigated by v0.15.1 hotfix that skips test files by default in Drift-Comments |
| 2026-05-26 | `cli/validators/drift.mjs` | ARCHITECTURE.md | Drift-Comments validator v0.15.1+ skips test files by default (matches TODO-Tracking's pattern). Opt in via `config.drift.includeTestFiles` if your project genuinely uses DRIFT markers in test code. | Info | By design — defensive default to prevent fixture false-positives |
| 2026-05-26 | `CHANGELOG.md` / `extensions/spec-kit-docguard/skills/*` | None | v0.12-v0.15 changelogs and release notes reference `// DRIFT:` in feature descriptions (e.g. K-3 .docguardignore, v0.13 sync, v0.14 P3 scoping). Documentation prose only, not actionable drift. | Info | By design — release notes |
| 2026-07-03 | `templates/commands/*`, `CHANGELOG.md`, `docs/ai-integration.md` | None | v0.29 batch audit: the DRIFT mentions in recently-committed files are the known by-design classes above (template instruction text, validator docstrings, changelog prose, and the new AI-integration guide's workflow step 6 teaching the drift protocol). No new code deviations from canonical docs were introduced by the findings migration, generate split, or integration-surface work. | Info | Audited — no actionable drift |
| 2026-07-03 | post-v0.29 batch (`cli/scanners/speckit.mjs`, `tests/speckit-phantom.test.mjs`, `packaging/*`) | None | Post-release batch audit (phantom detection, instruction audit, trace --features, distribution files): DRIFT mentions are validator/test/doc prose of the by-design classes above. No new code deviations. | Info | Audited — no actionable drift |


---

## CHANGELOG.md
> Version history and release notes

# Changelog

All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]

## [0.31.0] - 2026-07-07

Accuracy release — six research-backed detectors that make drift detection
change-aware and language-agnostic, built on one shared diff foundation. Every
new check was empirically tuned read-only against six real production repos
(TypeScript + Python) before shipping; all are deterministic (no LLM at
validation time) and soft (`confidence: low`, never break CI). Validator count
24 → 27.

### Added
- **`docguard impact` — doc→doc blast radius + agent-instruction files** (feat 1).
  Agent-instruction files (AGENTS.md/CLAUDE.md/GEMINI.md) are now indexed, so a
  changed code file they reference is surfaced. New: when a canonical/agent doc
  changes, the docs that reference it — including agent-instruction files — are
  flagged as a "blast radius" (`{ changedDocs, blastRadius }` in JSON). No
  verified competitor propagates doc staleness across the doc graph. Proven on a
  real repo: an ARCHITECTURE.md change flags the AGENTS.md/CLAUDE.md that cite it.
- **Diff-Suspicion validator (DSP001)** (feat 3) — change-driven. A doc that BOTH
  references a code file changed since the ref AND shares domain tokens removed
  in that diff is flagged for review. Deterministic diff-overlap rule
  (arXiv 2010.01625, F1 74.7); path/module refs + domain-token filtering +
  per-doc cap keep it quiet at PR granularity.
- **Reference-Existence validator (REF001)** (feat 2) — two-revision check. A
  compound code identifier backticked in a doc that existed when the doc was last
  updated but has ZERO matches at HEAD is flagged as outdated (arXiv 2212.01479).
  In-memory HEAD identifier set + authoritative git-grep confirmation; zero false
  positives across the corpus.
- **API-Doc-Smells validator (APS001 Bloated / APS002 Lazy)** (feat 4) —
  deterministic length signals on signature-headed doc units (F1 0.90 / 0.95).
- **IR-based traceability soft-matching** (feat 5) — `cli/shared-ir.mjs`
  (zero-dep TF-IDF + cosine). An untraced requirement now surfaces the
  TF-IDF-closest test file ("X may already cover it — add @req there"),
  reducing false "no coverage" for tests that lack the annotation.
- **`docguard verify --since <ref>` — change-aware staging** (feat 6). Attaches
  an activity-labeled (ordered replace/delete/add) structured diff to the staged
  agent-judgment tasks and flags which claims are about just-changed code —
  CARL-CCI showed the structured-diff representation drives judgment accuracy
  (arXiv 2512.19883).
- **`cli/shared-diff.mjs`** — zero-dependency unified-diff parser + identifier-
  aware tokenizer + activity-labeled diff, the shared foundation for feats 1/2/3/6.

### Fixed
- `hooks` crash from a `core.hooksPath` edge and other pre-ship bugs caught by
  dogfooding DocGuard on itself (a `walkFiles`-vs-`git grep` dot-directory
  asymmetry that fabricated reference-existence false positives; a `.map(basename)`
  index-as-suffix crash in verify).
- **Self-counting consistency** — `canonical-sync` and `metrics-consistency` now
  agree on the validator count (both 27); a default-off validator previously made
  them disagree.

### Changed
- New validators default ON except where noted; all are soft warnings.
- README, ARCHITECTURE.md, quickstart, CI-RECIPES, AGENTS.md updated to 27
  validators (historical version-log counts preserved).

## [0.30.1] - 2026-07-06

Patch release: a hooks crash fix that unblocks sandboxed CI/agent environments,
plus two portability/robustness hardenings.

### Fixed
- **`hooks` and `init --with hooks` crashed under `core.hooksPath=/dev/null`**
  (bug-200). `getHooksDir` resolved the literal `/dev/null` that
  `git rev-parse --git-path hooks` returns when hooks are disabled that way, so
  callers wrote `/dev/null/pre-commit` → `ENOTDIR: not a directory`. It now
  guards the pseudo-path and falls back to `.git/hooks`. This unblocks the
  Google Jules sandbox VM (which sets that config) and anyone who disables hooks
  via `core.hooksPath=/dev/null`. Regression test added.

### Changed
- **`score`: dropped the shell `| wc -l` pipe** in the commit-churn estimate
  (`estimateDocTax`) in favor of `execFileSync` + counting in JS — no shell,
  portable to Windows (no `wc`), matching the pattern `freshness.mjs` already
  uses.
- **`.jules-setup.sh` hardened** so Google Jules stops aborting with "Working
  tree is dirty" after setup: `npm install` → `npm ci` (never rewrites
  `package-lock.json`), and `git clean -fd` → `git reset --hard HEAD &&
  git clean -fd` (discards the tracked `.agent/skills` regeneration that
  `--version` triggers; `-fd` respects `.gitignore`, so `node_modules` survives).

## [0.30.0] - 2026-07-04

Competitive-adoption batch (from the spec-kit catalog scan — the best ideas of
45 doc/validation extensions, rebuilt on DocGuard's deterministic engine) plus
the distribution-channel expansion.

### Added
- **Spec-Kit: phantom-completion detection (SPK008/SPK009)** — tasks marked
  `[x]` in `tasks.md` whose named deliverables don't exist and carry no
  implementation evidence (repo file names, code symbols, plan/spec artifacts,
  task-ID annotations, git log) are flagged, capped at 10 per run with an
  elision note. A checked task with no artifact is memory corruption for
  agents. Precision-first: calibrated against this repo's own 57 checked tasks
  (0 false positives) — prose-only and ID-only tasks are never accused. Opt
  out via `specKit.phantomCheck: false`.
- **`verify --instructions` — agent-instruction drift audit** (MemoryLint-
  inspired). Extracts imperative rules from AGENTS.md/CLAUDE.md, flags exact
  duplicates, never-vs-always contradiction pairs, stale file pointers, and
  unknown `docguard` command references deterministically, then stages
  topically-clustered rule pairs (cross-file prioritized, capped 40) as agent
  judgment tasks — the same extraction/judgment split as `verify --semantic`.
  Mirrors generated by `agents --sync` are skipped. Dogfooded: found a real
  stale pointer in DocGuard's own AGENTS.md on first run (fixed).
- **`trace --features` — per-feature spec-adherence report** (retrospective-
  inspired). Every spec-kit feature scored individually: requirement-ID test
  coverage (40%), task completion (25%), checked-task file evidence (20%),
  artifact completeness (15%) — graded A–F, worst-first, one fix hint each;
  unmeasurable signals are neutral (weights renormalize), never punitive.
  `--format json` for CI.
- **Distribution channels** — `.pre-commit-hooks.yaml` (validated with the
  official pre-commit validator; changed-only guard per commit + full guard
  for pre-push), official MCP Registry manifest (`server.json`, 2025-12-11
  schema, ajv-validated; `mcpName` ownership proof added to package.json),
  Smithery config, GitLab CI/CD Catalog component
  (`templates/ci/gitlab-component.yml`, SARIF artifact), Homebrew formula with
  the real npm-tarball sha256 (`packaging/homebrew/`), and a full submission
  playbook (`packaging/submissions.md`). awesome-mcp-servers listing PR
  submitted upstream.

### Changed
- The spec-kit catalog submission description (next release's prefill) now
  leads with the differentiators: MCP server, SARIF output, deterministic
  zero-LLM core, 24 validators with stable finding codes.
- README: `verify --instructions` / `trace --features` / integrate-via
  pre-commit/MCP/GitLab/Homebrew rows; the long-shipped Mermaid ER-diagram
  generation is finally documented.

## [0.29.0] - 2026-07-03

Closes both gaps from LLM field report #6 (a downstream adopter reported guard
**A+ / "Accurate: 100%" while a watched doc stated a wrong count** — the one
false-negative a documentation-integrity tool must not have). Diagnosis held up:
the literal cause was a domain noun missing from a hardcoded vocabulary, and an
ALCOA pillar named "Accurate" that was computed from structure/markers, not facts.
The fix is precision-first (the tool's existing philosophy), not the report's
recall-maximizing "validate every claim in every doc" — which prior field reports
already showed floods false positives.

### Added — AI integration surface
The detection core is the moat; this batch makes the output consumable by
everything that isn't a human reading a terminal (the gap vs. Swimm/Mintlify/
Context7 identified in the platform review).

- **`docguard mcp` — Model Context Protocol server** over stdio (JSON-RPC 2.0,
  zero dependencies, `node:readline`). Five tools: `docguard_guard`,
  `docguard_score`, `docguard_explain`, `docguard_verify_claims`,
  `docguard_diagnose` — DocGuard's read-only core as native agent tools for
  Claude, Cursor, and any MCP client (`claude mcp add docguard -- npx
  docguard-cli mcp`). Config loads per call; a malformed `.docguard.json`
  becomes an `isError` tool result instead of killing the session (loadConfig's
  process.exit is defused by pre-parsing); stdout is the pure transport
  (registered in both the headless gate and READ_ONLY_COMMANDS, so no banner
  and no scaffolding side effects).
- **Action: inline PR annotations + sticky doc-impact comment** — `guard` runs
  now annotate each finding on the PR diff (`annotations` input, default on,
  capped at 50) and maintain a single sticky PR comment (`pr-comment`, default
  on) with the guard verdict, top findings, and the canonical docs impacted by
  the PR's changed files (`diff --since origin/<base>`). Purely additive steps
  gated on `always()` (feedback must appear exactly when guard fails); degrade
  gracefully on fork tokens, shallow clones, and missing permissions; existing
  outputs and exit codes untouched.
- **SARIF 2.1.0 output** — `docguard guard --format sarif` maps the structured
  findings 1:1 onto SARIF (codes → rules with title/help from the registry,
  locations → physicalLocation/region, low-confidence → property bags,
  validator crashes → synthesized `DOCGUARD-<KEY>` results, exit codes
  unchanged). Drops straight into GitHub Code Scanning and enterprise SARIF
  dashboards. `sarif` joins `json` in the machine-format gate, so stdout is the
  pure artifact — no banner.
- **`docguard llms --full`** — generates `llms-full.txt` (the Mintlify-style
  full-content companion to the `llms.txt` index): every canonical + optional
  doc inlined under one fetch, per-doc 400-line cap with truncation notes.
- **`docguard memory --pack`** — writes `.docguard/context-pack.md`, a compact
  (<200 lines) code-truth-stamped session-start context for AI agents: guard
  status, scanner-derived surface counts (modules/endpoints/entities/env
  vars/tests), canonical-doc index with last-reviewed dates, the Rules/Workflow
  sections of AGENTS.md verbatim, and known-drift summary. Everything derived
  from scanners — regenerable, hallucination-free.
- **`docguard agents --sync` / `--check`** — AGENTS.md becomes the CANONICAL
  source for the whole agent-file family (CLAUDE.md, GEMINI settings,
  `.github/copilot-instructions.md`, `.cursor/rules/`, `.clinerules`,
  `.windsurfrules`). Generated variants carry a source-hash marker; `--sync`
  regenerates marked/missing variants (never touches unmarked hand-written
  files without `--force`); `--check` is the CI gate (exit 2 on stale). Kills
  the hand-duplicated-agent-file drift class entirely.
- **Agent Readability score axis** — `docguard score` now measures how well AI
  consumers can read the repo (display-only, like ALCOA+ — the gating grade is
  untouched): agent entry file presence, entry-file token budget, section
  addressability (quotable-alone + unique headings), structured-content
  density, machine-marker presence, llms.txt, and entry-file link integrity.
  Deterministic, zero-LLM. Dogfooded: found real defects in DocGuard's own
  docs (duplicate headings, an unmarked doc) on first run.

### Added
- **Auto-detected documentation homes** — clearly-named doc folders (`docs/`,
  `doc/`, `documentation/`, `guides/`, `guide/`, `handbook/`, `manual/`, `wiki/`,
  plus `docs-canonical/`, `docs-implementation/`, `extensions/`, and Docusaurus
  `website/docs/`) are now claim-scanned and counted as "tracked" **without being
  enrolled** in `requiredFiles.canonical`. A folder literally named `documentation/`
  is unambiguously a doc home DocGuard governs; this stays distinct from the
  arbitrary-subdir walk the wu-whatsappinbox scoping fix removed (a number buried
  in `security/wolf-archive/` is still never scanned). `config.docs.dirs` EXTENDS
  the set with non-standard homes (it never replaces auto-detection); use
  `.docguardignore` to exclude a conventional dir. The doc-home set is now a single
  source of truth (`resolveDocDirs`) shared by the claim scanner and the coverage
  map, so "tracked" provably means "actually scanned." New optional `docs.dirs` key
  in the schema.
- **Project collections** — `config.collections` maps a documentation noun (e.g.
  `extractors`) to a glob whose matching-file count is the source of truth.
  Metrics-Consistency now flags a documented count that disagrees ("16 extractors"
  in prose vs 19 files on disk) **deterministically, in `guard`, with no LLM** —
  catching the exact class that bit the adopter. A declared collection is the
  opt-in binding, so it does not need the `docguard`-on-the-line subject bind the
  built-in checks/validators counts use; reserved nouns (checks/validators/tests)
  keep their built-in meaning; an unresolved glob (0 matches) is skipped, never
  asserting a false "0". Complements `surfaceSync` (WHICH members drift) with a
  count check (HOW MANY). New optional key in `docguard-config.schema.json`.
- **Coverage line in `guard`** — every run now reports how many Markdown files are
  canonical / tracked / ignored / outside any tier, turning silent non-coverage
  (the "I forgot to enroll this doc" trap) into a visible count. Calm by default:
  the count shows every run; the file list is one `--verbose` away (loud-by-default
  would just train users to ignore it). Also exposed on the `guard --format json`
  contract as `coverage`.
- **Unverified-claims notice in `guard`** — the deterministic semantic-claim
  extractor (previously only reachable via `verify --semantic`) now runs in `guard`
  and reports how many documented counts/limits/enums remain unverified against
  code, so a green run states plainly that structure is sound, *not* that the
  numbers still match. Exposed as `semanticClaims` on the JSON contract.

### Changed
- **ALCOA+ "Accurate" no longer overclaims.** It gains a third, honest state —
  `unverified` (cyan 🔍) — shown when structure passes but documented factual
  claims haven't been checked against code. Previously it read ✅ "100%" purely
  from drift markers + prose quality, which is how an adopter saw "Accurate: 100%"
  over a doc that stated the wrong number. `unverified` counts as not-met for the
  ALCOA compliance percentage (so it stops overclaiming) but renders neutrally, not
  as a failure. **Display-only: the gating CDD maturity grade (`score` / `ci`
  threshold) is unchanged.**
- Extended the semantic claim-extractor vocabulary with the common
  pluggable-architecture nouns (`extractors`, `plugins`, `detectors`, `scanners`,
  `commands`, `rules`, `hooks`, `handlers`, `agents`, `skills`, …). The missing
  `extractors` was the literal root cause of the field report.

### Internal hardening (project-review batch)
- **ONE walker, ONE anchored glob compiler.** Sixteen private recursive
  directory walkers (13 validators + guard coverage + diff + generate) and three
  divergent glob→regex implementations are consolidated into
  `shared-ignore.mjs`: `walkFiles(dir, cb, {ignoreDirs, keepDot, onError})` and
  `compileGlob()` (superset: `**/`, `**`, `*`, `?`, `{a,b}`). Per-validator
  IGNORE_DIRS sets stay local **by design** — they carry intentional variance
  (drift excludes `cli/` because DocGuard's own regexes contain `DRIFT:`;
  docs-sync excludes `__tests__`), and the load-bearing dot-entry exceptions are
  preserved via `keepDot` (security must scan `.env`; traceability keeps
  `.env*`, `.gitignore`, `.github/`). The ignore-side `globToRegex` keeps its
  documented unanchored semantics — different contract, own bug history.
- **Partial-walk counts are now fail-safe.** `countGlobFiles` returns −1 when
  the walk was incomplete (permission-denied subtree), so a collection count
  can never silently under-count and "correct" a right doc number to a wrong
  one. Callers treat ≤0 as "don't assert".
- **Findings migration COMPLETE — all 24 validators.** Every validator now
  emits structured findings with stable, `explain`-able, inline-suppressible
  codes; the legacy hand-built errors/warnings strings are gone from the
  validator layer (`resultFromFindings` derives them from the same array, so
  messages are byte-identical and counts/exit codes are unchanged). The CODES
  registry grew from 8 (SEC only) to **91** across 21 prefixes: STR, CHG, MET,
  FRS (freshness, via a new guard adapter — its array contract is preserved),
  ENV, TSP, DRF, DSY, DDF, DCV, MDS, TRC, TDO, SCH, ARC, CSY, SPK (implemented
  in scanners/speckit.mjs behind the validator shim), XRF, GST, SSY, plus full
  first-time migrations of API (api-surface) and DQ (doc-quality), which turned
  out to be fully legacy rather than partial. `confidence: 'low'` is set only
  where the pre-existing message already hedged (TSP003, API003, API004's
  code-scan variant). Guard's rich rendering (`[CODE]` tags, `→ suggestion`
  lines, low-confidence markers, `docguard feedback` reporting) now covers the
  entire validator surface.
- **Docs truth pass**: SURFACE-AUDIT.md gets a "historical snapshot — findings
  resolved" banner (its v0.18.1 counts were being read as current); STANDARD.md
  §8 no longer embeds a validator table (it had drifted 16 validators behind —
  points at the machine-governed README list instead); README leads with a
  compact "Why DocGuard?" and moves "What's New" below CI/CD; ROADMAP Phase 4.5
  updated through v0.28; CONTRIBUTING gains the **surface rule** (a new
  user-facing command must retire one or justify growth) and the **findings
  rule** (new validators must emit findings); pyproject.toml no longer claims
  "zero dependencies" (now: "no Python dependencies, requires Node 18+").
- **Hygiene**: removed tracked scratch files (`test-draft.js`,
  `test-metrics.js`, `pr_description.md`) and a dead `IGNORE_DIRS` set in
  freshness.mjs.
- **`generate.mjs` split (1530 → 559 lines).** The generate command now has
  three coherent modules: `cli/writers/generate-io.mjs` (backup/safe-write/
  doc-registration/citation helpers, 142 lines) and
  `cli/writers/doc-generators.mjs` (the 7 document builders, 853 lines), with
  command flow + stack detection + project scanning staying in
  `cli/commands/generate.mjs`. Pure code motion — bodies byte-identical,
  verified by the full suite plus `generate`/`generate --plan` smoke runs.
- **CI flake fix (watch spawn tests).** The two `docguard watch` tests polled
  with a fixed 2-second cap — a hair-trigger race against CLI startup that
  intermittently failed on slow runners and passed on re-run. Replaced with a
  15-second `waitFor` deadline; assertions unchanged (a genuinely broken watch
  still fails, just not a slow-booting one).

### Remediation policy (suggest vs. auto-update)
DocGuard detects **divergence**, not which side is right — a doc claim that no
longer matches code can mean the doc is stale OR the code regressed and the doc is
the correct intent (the CDD premise: canonical docs are the spec). So:
- **Auto-fix only the provably-mechanical class** — a number bound to a code
  collection (`collections`), where the true value is known and the code is
  definitionally the source. These emit a `fix` object applied **only** via an
  explicit `docguard fix --write`, with `actualSource` provenance, fail-closed,
  and reversible via git. **Never silent.**
- **Everything semantic/prose is SUGGEST-only** — surfaced as a finding (and via
  `verify --semantic` for agent judgment), never auto-rewritten. DocGuard's
  deterministic core can't author correct prose and must not assume code is always
  the source of truth. Enrichment/rewriting is an agent task the human approves —
  not a validator silently editing docs.

## [0.28.0] - 2026-06-22

Closes the detection-gap items deferred from LLM field report #3 — the checks
regex/AST couldn't make before — plus a latent CI-correctness bug surfaced by
dogfooding.

### Added
- **`docguard verify --semantic`** (field report #5) — extracts the semantic
  claims in the canonical docs (documented numbers, limits, and enums: retention
  days, rate limits, GSI/role counts, status enums) as a structured verification
  task list with each claim's doc:line, section, and nearest cited code path. The
  highest-value bug class (a doc value drifted from code) and the one regex/AST
  can't judge — so DocGuard does the deterministic discovery and the agent does
  the comparison (the `docguard agent` division of labour). Precision-first:
  numbers count only with a recognized unit, enums only as 2+ UPPER_SNAKE values
  in a status/state context; version strings, dates, and code-fenced numbers are
  ignored.
- **`docguard sync --tests`** (field report #10) — reconciles the hand-maintained
  TEST-SPEC Source-to-Test Map from disk: drops ghost-source rows (source file
  deleted), appends newly-covered co-located source↔test pairs, and reports ghost
  test references for the human (never auto-edits a curated status/notes cell).
  Preview by default; `--write` applies.

### Fixed
- **Dynamic `import()` no longer counted as an import cycle** (field report #2) —
  the Architecture validator excludes runtime `await import()` edges from cycle
  detection (a dynamic import is the canonical way to BREAK a load-time cycle).
  Static `import`/`require` edges still count, and dynamic edges still count for
  layer-boundary checks.
- **API-Surface diffs the OpenAPI spec against the registered routes** (field
  report #4) — when a spec is the authoritative surface, the API-REFERENCE doc
  reconciles against the spec, so a spec that declares a phantom endpoint (no
  Express/Fastify route registers it) passed clean. It's now flagged. Conservative:
  only runs when code routes are actually scannable.
- **Freshness markers stamped on `init`** (field report #11) — the SECURITY,
  ENVIRONMENT, TEST-SPEC, and REQUIREMENTS templates gained the standard
  `docguard:last-reviewed` header, and `init` stamps every canonical doc with a
  today-dated marker (belt-and-suspenders for future templates). Freshness is now
  marker-based and consistent from day one — and satisfiable in a pre-commit
  review loop. `explain freshness` now documents the marker > git-mtime precedence.
- **`guard --format json` no longer truncates large reports** — replaced
  `console.log(...) + process.exit()` with `process.exitCode` + a drained write.
  A JSON payload over ~8 KB written to a pipe flushes asynchronously, so the
  immediate `process.exit()` cut it off mid-string — a CI consumer parsing stdout
  got "Unterminated string in JSON" on exactly the big reports that matter.
  (Surfaced by dogfooding this release.)

### Notes
- Tests 813 → 825 (new `tests/field-report-3-deferred.test.mjs`, each fix with a
  non-vacuous control). All field-report-3 items are now addressed.

## [0.27.0] - 2026-06-19

Acting on a third end-to-end LLM field report (a coding agent ran DocGuard on a
Vite+Vitest WhatsApp-inbox repo). The headline is architectural: DocGuard is a
tool *for LLMs*, so every run should end with a suggested next action and every
finding it surfaces should be addressable, suppressible, and — when uncertain —
reportable. This release introduces structured **findings** (stable codes +
confidence + a built-in suggestion), wires them through `guard`/`explain`, adds a
local-first **feedback** loop, and fixes the group-A false positives the report
flagged.

### Added
- **Structured findings with stable codes** (`cli/findings.mjs`) — a validator
  can now emit `Finding[]` (code like `SEC001`, `high`/`low` confidence, and a
  machine-readable `suggestion`) via `resultFromFindings(...)`. Fully
  backward-compatible: the legacy `{errors,warnings,passed,total}` shape is
  derived from the same array, so non-migrated validators are unchanged. Security
  is the first fully-migrated validator.
- **Every guard run ends with a suggested next step** — issues render with an
  inline `→ suggestion` (fix command or suppression pragma); a clean run points
  at the next workflow step. `guard --format json` now carries a stable
  `findings` / `reportable` / `nextStep` contract for agents in hooks/CI.
- **`docguard feedback`** — collects the low-confidence findings of a guard run
  (likely false positives, and anything DocGuard flagged uncertainly), writes a
  full local record under `.docguard/feedback/`, and prints a **1-click,
  prefilled, redacted, length-capped** GitHub issue URL (zero typing; no source
  code or secret values; capped well under GitHub's ~8 KB URL limit — the failure

<!-- truncated: 1891 more lines — read CHANGELOG.md directly -->

---

## ROADMAP.md
> Planned features and development roadmap

# DocGuard Roadmap

<!-- docguard:version 0.6.0 -->
<!-- docguard:status living -->
<!-- docguard:last-reviewed 2026-07-02 -->
<!-- docguard:owner @raccioly -->

> The planned evolution of DocGuard and Canonical-Driven Development (CDD).

| Metadata | Value |
|----------|-------|
| **Status** | ![Status](https://img.shields.io/badge/status-active-brightgreen) |
| **Version** | `0.6.0` |
| **Last Updated** | 2026-07-02 |
| **Owner** | [@raccioly](https://github.com/raccioly) |

---

## Vision

Make **Canonical-Driven Development** the industry standard for AI-age software projects — where documentation drives development and machines enforce compliance.

---

## Current Phase

| Phase | Name | Status | Timeline |
|:-----:|------|:------:|----------|
| 0 | Research & Standard | ✅ Complete | Mar 2026 |
| 1 | Core CLI | ✅ Complete | Mar 2026 |
| 2 | Polish & Adoption | ✅ Complete | Mar 2026 |
| 3 | AI Generate Mode | ✅ Complete | Mar 2026 |
| 4 | Integrations | ✅ Complete | Mar 2026 |
| 4.5 | Continuous Hardening | 🔄 Ongoing | Mar 2026 – present |
| 5 | Dashboard (SaaS) | 💭 Future | Q4 2026 |

### Phase 4.5: Continuous Hardening (v0.11 → v0.28, ongoing) 🔄

Sustained, feedback-driven maturation since the March milestones. The cadence is
deliberately field-report-driven (real adopter reports → class-level fixes);
the counterweight is that each accumulated batch must also land internal
hardening (consolidation, findings migration), not just surface fixes — see
CHANGELOG `[Unreleased]` for the batch in progress:

- **v0.28.0 — field report #3 detection gaps + a CI-correctness fix.** Closed the five deferred items: `verify --semantic` (extract documented numbers/limits/enums for an agent to check against code — the semantic-drift class), `sync --tests` (reconcile the TEST-SPEC source→test map from disk), dynamic `import()` no longer counted as a cycle edge, API-Surface diffs the OpenAPI spec against registered routes (phantom-endpoint detection), and freshness markers stamped on `init`. Also fixed a latent bug where `guard --format json` truncated >8 KB reports piped in CI (process.exit before stdout drained). Tests 813 → 825.
- **v0.27.0 — LLM field report #3: findings + the feedback loop.** Reframed DocGuard around its real audience — LLMs. Introduced structured **findings** (stable codes like `SEC001`, confidence, and a built-in `→ suggestion`), so every guard run ends with a suggested next action and `--format json` carries a stable `findings`/`reportable`/`nextStep` contract. Added inline secret suppression (`// docguard:ignore SEC001`), `explain <CODE>`, a read-only skills nudge, and a local-first **`docguard feedback`** command (1-click, prefilled, redacted, length-capped issue URL — no auto-filing, no leaked secrets). Fixed the group-A false positives: prose values mis-flagged as passwords (now low-confidence), Vitest-in-`vite.config`/`scripts.test` detection, `docs-canonical/ROADMAP.md` TODO tracking, runner/CI env vars, and passive-voice override parity. Tests 794 → 813.
- **v0.26.0 — LLM field report #2: trust + agent-mode.** Fixed the general *class* behind 7 issues a coding agent hit end-to-end (the v0.25.0 fixes were real but narrow; two tests even codified the bugs): read-only commands now never mutate the tree, surface detection excludes test fixtures by default (the first-run fix), Metrics-Consistency is subject-bound + fail-closed (no more data-corrupting auto-fix), project name comes from the manifest, `generate` respects the active profile, freshness states both remedies, and env detection counts reads not mentions. Added pre-filled code-truth (ARCHITECTURE Component Map + a TEST-SPEC inventory) and a first-class **`docguard agent`** task-graph command (ordered, pre-filled, per-task verify) that collapses ~10 agent round-trips into one. Tests 765 → 794.
- **v0.25.0 — field-report fixes + CLI/library ergonomics.** Closed a silent `.docguardignore` failure (trailing-slash `dir/` patterns matched nothing across every scanner/validator), a `generate --write` ENOENT crash, a dead `init --fix` flag, and `generate --plan` write side-effects. Added a `pinned` section marker (hand-maintained code sections survive staleness + `sync`), per-command `--help`, kind-gated low-confidence surface flagging for scanner/tool projects, and `cli`/`library` doc profiles. Tests 749 → 765.
- **v0.24.0 — real parsers, full-support languages.** Relaxed the zero-dependency rule for one exact-pinned npm dep (`@babel/parser`) plus an optional `python3` AST tier, both with regex fallback. Closed false-green paths (silent brace-truncation in JS/TS schemas; undercounted Python models), added Express cross-file mount-prefix resolution, Fastify object-form routes, and a hardened `requiredFiles` migration. Field-tested read-only against real Next.js/Express/Python/AppSync projects.
- **Validators grew 9 → 24** — added Canonical-Sync, Surface-Sync, Metrics-Consistency, Doc-Quality, Traceability, Cross-Reference, Generated-Staleness, and more.
- **Language-aware** test/trace discovery (Python, Go, Rust, Java/Kotlin, Ruby, PHP) shared between `docguard trace` and the guard-time Traceability validator.
- **Per-doc/per-rule overrides** — `docguard:section … n/a`, `docguard:quality negation-load off`, `docguard:spec-type bugfix` — so the validators fit real projects instead of forcing ceremony.
- **Security** — closed a command-injection vector in CLI `init` (#190); subprocesses now use `execFileSync` + allowlist validation, and the GitHub Action passes all inputs via the environment rather than splicing them into shell.
- **Distribution** — npm + PyPI + GitHub Action + Spec Kit community-catalog auto-sync.

---

## Phase 0: Research & Standard ✅

Defined the CDD methodology and created the DocGuard specification.

- [x] Landscape analysis (Spec Kit, AGENTS.md, Kiro, Cursor)
- [x] CDD philosophy and three pillars
- [x] Full standard specification (STANDARD.md)
- [x] Agent compatibility research (10+ AI coding agents)
- [x] Competitive comparisons with honest limitations

## Phase 1: Core CLI ✅

Built the zero-dependency CLI tool with 9 validators and 8 core templates.

- [x] `docguard audit` — scan project, report documentation status
- [x] `docguard init` — create CDD docs from professional templates
- [x] `docguard guard` — validate project against canonical docs
- [x] 9 validators: structure, doc-sections, docs-sync, drift, changelog, test-spec, environment, security, architecture
- [x] 8 core templates with versioning headers, badges, and revision history
- [x] Stack-specific configs (Next.js, Fastify, Python, generic)
- [x] GitHub CI workflow (Node 18/20/22)
- [x] MIT license, CONTRIBUTING.md, issue templates

## Phase 2: Polish & Adoption ✅

Expanded the CLI with scoring, diffing, and agent integration.

- [x] `docguard score` — CDD maturity score (0-100) with weighted categories and bar charts
- [x] `docguard diff` — canonical docs ↔ implementation comparison
- [x] `docguard agents` — auto-generate configs for 6 AI agents (Cursor, Copilot, Cline, Windsurf, Claude, Gemini)
- [x] `--format json` output for CI integration
- [x] `--fix` flag for auto-creating missing files
- [x] `--force` flag for overwriting existing files
- [x] `--agent <name>` flag for targeting specific agents
- [x] 8 additional templates: KNOWN-GOTCHAS, TROUBLESHOOTING, RUNBOOKS, VENDOR-BUGS, CURRENT-STATE, ADR, DEPLOYMENT, ROADMAP
- [x] npm publish (`npx docguard-cli` works globally; PyPI wrapper too)

## Phase 3: AI Generate Mode ✅

The killer feature — reverse-engineer documentation from existing codebases.

- [x] `docguard generate` command
- [x] Framework auto-detection (15+ frameworks: Next.js, React, Vue, Angular, Fastify, Express, Django, etc.)
- [x] Database detection (8+: PostgreSQL, MySQL, MongoDB, DynamoDB, SQLite, etc.)
- [x] ORM detection (Drizzle, Prisma, TypeORM, Sequelize, Knex)
- [x] Route scanning → ARCHITECTURE.md route listing
- [x] Schema/model scanning → DATA-MODEL.md entity extraction
- [x] Test file analysis → TEST-SPEC.md service-to-test mapping
- [x] Env var scanning → ENVIRONMENT.md with categorized variables
- [x] Auth detection → SECURITY.md pre-fill
- [x] Hosting detection (Amplify, Vercel, Docker, Fly.io, Railway, Render)
- [x] Import analysis → Circular dependency detection + layer boundary validation from ARCHITECTURE.md

## Phase 4: Integrations ✅

Deep integration with development tools and platforms.

- [x] GitHub Action (reusable action.yml with PR score comments, thresholds)
- [x] Pre-commit hook generator (guard validation)
- [x] Pre-push hook generator (minimum score enforcement)
- [x] Commit-msg hook (conventional commits validation)
- [x] Badge service (shields.io CDD score, type, guarded-by badges)
- [x] CI command (guard + score pipeline, JSON output, thresholds)
- [x] npm publish preparation (.npmignore, prepublishOnly, CI dry-run)
- [x] ~~VS Code extension (status bar score, inline diagnostics, 6 commands)~~ — **removed in v0.24.0** (was unmaintained and broken; the CLI + CI gate are the supported surface)

## Phase 5: Dashboard 💭

Web-based CDD governance for teams and organizations.

- [ ] Web dashboard showing CDD scores across repos
- [ ] Historical trend graphs
- [ ] Team leaderboards
- [ ] Drift alerts (Slack/email)
- [ ] Compliance reports (PDF export)

---

## Contributing

We welcome contributions at any phase! See [CONTRIBUTING.md](CONTRIBUTING.md) to get started.

Priority areas for contributions:
- **Templates** — Add stack-specific templates (Django, Spring Boot, Go)
- **Validators** — Write new validation rules
- **Testing** — Run DocGuard against your projects and report issues
- **Documentation** — Improve the standard and guides


---

## AGENTS.md
> AI agent behavior rules and workflow instructions

# AI Agent Instructions — DocGuard

<!-- docguard:last-reviewed 2026-07-03 -->

> This project follows **Canonical-Driven Development (CDD)**.
> Documentation is the source of truth. Read before coding.
> DocGuard is an official [GitHub Spec Kit](https://github.com/github/spec-kit) community extension.

## Workflow

1. **Read** `docs-canonical/` before suggesting changes
2. **Check** existing patterns in the codebase
3. **Run** `docguard diagnose` to see what needs fixing
4. **Confirm** your approach before writing code
5. **Implement** matching existing code style
6. **Log** any deviations in `DRIFT-LOG.md` with `// DRIFT: reason`
7. **Verify** with `docguard guard` — all checks must pass

## Project Stack

- **Language**: JavaScript (ES modules)
- **Runtime**: Node.js 18+
- **Dependencies**: One — `@babel/parser` (exact-pinned, optional-load); Node.js built-ins otherwise
- **Testing**: `node:test` (built-in)
- **Distribution**: npm + PyPI
- **Version**: see `package.json` (single source of truth — do not hardcode here)

## Key Files

| File | Purpose |
|------|---------|
| `docs-canonical/ARCHITECTURE.md` | System design |
| `docs-canonical/DATA-MODEL.md` | Database schemas |
| `docs-canonical/SECURITY.md` | Auth & secrets |
| `docs-canonical/TEST-SPEC.md` | Test requirements |
| `docs-canonical/ENVIRONMENT.md` | Environment setup |
| `docs-canonical/REQUIREMENTS.md` | Spec-kit aligned requirements |
| `CHANGELOG.md` | Change tracking |
| `DRIFT-LOG.md` | Documented deviations |

## Commands

`docguard --help` is the authoritative list (counts intentionally not hardcoded
here — they drift). The surface, grouped as `--help` shows it:

**The Daily 5** — `init` (bootstrap + scan), `guard` (CI gate, all validators),
`diff` (doc↔code gaps; `--since <ref>` for changed-file impact), `sync` (refresh
code-truth sections), `score` (CDD maturity 0-100).

**Tools** — `demo` (zero-install tour), `diagnose` (guard → AI fix prompts),
`fix` (AI fix instructions; `--doc <name>`), `generate` (reverse-engineer docs;
`--plan`), `explain` (explain a validator/warning), `memory` (what DocGuard
remembers), `trace` (requirements traceability; `--reverse`), `upgrade` (migrate
config/CLI), `watch` (live re-guard).

**`init --with <name>`** scaffolders — `agents`, `hooks`, `ci`, `badge`, `llms`,
`publish` (also reachable as standalone deprecation aliases).

**Deprecation aliases** — `setup` → `init --wizard`; `audit` → `guard`
(permanent); `impact` → `diff --since`.

## Consuming Guard Output (agents)

Prefer the machine contract over parsing prose: `docguard guard --format json`
returns `status` (PASS/WARN/FAIL, matches exit code 0/2/1), `findings[]`
(`{code, severity, confidence, message, location, suggestion}`), `nextStep`,
`reportable[]` (low-confidence findings — verify before acting), `coverage`
(Markdown tier map incl. `unclassified[]`), and `semanticClaims.count`
(documented numbers not yet verified against code).

- Every finding has a stable code (`STR001`, `ENV003`, `XRF002`, …) — all 27
  validators emit them. `docguard explain <CODE>` gives the contract and fix.
- Mechanical fixes go through `docguard fix --write` (provenance-checked,
  fail-closed) — never hand-apply what the tool fixes deterministically.
- Genuine false positives: suppress at the site with `// docguard:ignore <CODE>`
  (reason required) or `<!-- docguard:validator <key> n/a — reason -->`, and
  report them via `docguard feedback`.
- Doc≠code does not mean the doc is wrong — canonical docs are the spec. If the
  code regressed from a documented decision, fix the code or log a
  `// DRIFT: reason` + DRIFT-LOG.md entry instead of rewriting the doc.

## AI Skills

DocGuard provides enterprise-grade AI behavior protocols via the Spec Kit extension:

| Skill | Purpose |
|-------|---------|
| `docguard-guard` | 6-step quality gate with severity triage and structured reporting |
| `docguard-fix` | 7-step research workflow with validation loops (max 3 iterations) |
| `docguard-review` | Read-only semantic cross-document consistency analysis |
| `docguard-score` | CDD maturity assessment with ROI-based improvement roadmap |

Skills are located at `extensions/spec-kit-docguard/skills/*/SKILL.md`. They tell agents **how to think**, not just what to run.

## Spec Kit Hooks

DocGuard integrates into the spec-kit workflow:

| Hook | When | Required? |
|------|------|-----------|
| `after_implement` | After `/speckit.implement` | Mandatory |
| `before_tasks` | Before `/speckit.tasks` | Optional |
| `after_tasks` | After `/speckit.tasks` | Optional |

## Extension Structure

```
extensions/spec-kit-docguard/
├── skills/                    # AI behavior protocols
│   ├── docguard-guard/SKILL.md
│   ├── docguard-fix/SKILL.md
│   ├── docguard-review/SKILL.md
│   └── docguard-score/SKILL.md
├── scripts/bash/              # Orchestration scripts (--json output)
├── commands/                  # Spec Kit slash commands
├── templates/                 # Hook registration templates
└── extension.yml              # Skills, scripts, hooks declaration
```

## Rules

- **PR-first workflow — no direct-to-main commits.** Create a branch (`git checkout -b <type>/<slug>`), push, `gh pr create`, let CI run, self-review, squash-merge. Tag releases only after merge on `main`. The only acceptable direct-to-main: typo fixes in comments or README badge URLs.
- Never commit without updating CHANGELOG.md
- If code deviates from docs, add `// DRIFT: reason`
- Security rules in SECURITY.md are mandatory
- Test requirements in TEST-SPEC.md must be met
- Run `docguard guard` before pushing — all checks must pass
- All file writes use `safeWrite()` — backups before overwrite


## Agent Rules

### Automated agents / bots (Jules "Sentinel", "Bolt", "Palette", and any auto-PR agent)
- **Never open a duplicate PR.** Before opening ANY PR, search existing **open
  AND closed** PRs and issues for the same topic/title. If it exists, STOP — do
  not open another. (Dozens of duplicate command-injection and diff-optimization
  PRs were closed as noise.)
- **Do not re-open resolved work.** See `.jules/sentinel.md` (execSync/command
  injection — RESOLVED in v0.21.1 + #296) and `.jules/bolt.md` (diff/scan
  micro-optimizations — already applied; code refactored since). These are
  historical learnings, **not** standing mandates to re-scan every run.
- **Bar for a new PR:** a genuinely new, unaddressed finding, with evidence — a
  concrete exploit path / failing test (security) or a benchmark showing >20%
  real-workload improvement (performance). A Big-O note alone is insufficient.
- This repo has **no web UI and no VS Code extension** — skip all UX tasks.

### Dependencies
- Never add a package without first verifying it exists on the official registry (npm/PyPI).
- Always pin to exact versions in `package.json` and `requirements.txt`. No ^, ~, or >= ranges.
- Prefer packages with >10k weekly downloads and >1 maintainer.
- If you suggest a package, confirm its first-publish date is older than 30 days.
- Never modify .npmrc, pnpm-workspace.yaml, or dependabot.yml without explicit user confirmation.

### CI/CD
- Never write a workflow using `pull_request_target` with checkout of PR-controlled refs.
- Always pin third-party GitHub Actions to commit SHA, not @v1 or @main.


---
Generated by DocGuard | [docguard-cli](https://www.npmjs.com/package/docguard-cli)
