CI and Automation Guide for docmgr

Integrate docmgr validation into CI/CD pipelines with GitHub Actions, GitLab CI, pre-commit hooks, and automation patterns.

Packages

Sections

Agent documentation | LLMs.txt | Sitemap

| \\\n xargs -I FILE docmgr doc relate --ticket FEAT-042 \\\n --file-note \"FILE:Auto-related from git diff\"\n\n# With git commit messages as notes\nfor file in $(git diff main --name-only); do\n NOTE=$(git log -1 --pretty=%B \"$file\" | head -1)\n docmgr doc relate --ticket FEAT-042 --file-note \"$file:$NOTE\"\ndone\n```\n\n### Find Impacted Docs Before Refactoring\n\n```bash\n# Before renaming/moving files, find docs that reference them\ndocmgr doc search --file pkg/auth/service.go --with-glaze-output --output json | \\\n jq -r '.[] | .path'\n\n# Or search by directory\ndocmgr doc search --dir pkg/auth/ --with-glaze-output --output json | \\\n jq -r '.[] | \"\\(.ticket): \\(.title)\"' | sort -u\n```\n\n### Generate Ticket-to-Code Map\n\n```bash\n#!/bin/bash\n# Export all ticket → code relationships\n\necho \"# Ticket to Code Map\"\necho \"\"\n\nfor ticket in $(docmgr ticket list --with-glaze-output --select ticket); do\n echo \"## $ticket\"\n docmgr doc search --ticket \"$ticket\" --with-glaze-output --output json | \\\n jq -r '.[0].related_files[]? | \"- \\(.path) — \\(.note)\"' 2\u003e/dev/null\n echo \"\"\ndone\n```\n\n---\n\n## 7. CI Strictness Strategies\n\n### Strategy 1: Gradual Enforcement\n\n```bash\n# Week 1-2: Validate on warning (soft)\ndocmgr doctor --all --fail-on none # Just print warnings\n\n# Week 3-4: Block on errors only\ndocmgr doctor --all --fail-on error\n\n# Week 5+: Block on errors and warnings\ndocmgr doctor --all --fail-on warning\n```\n\n### Strategy 2: Per-Branch Rules\n\n```yaml\n# Strict on main/production\non:\n push:\n branches: [main]\n# run: docmgr doctor --all --fail-on warning\n\n# Lenient on feature branches\non:\n pull_request:\n# run: docmgr doctor --all --fail-on error\n```\n\n### Strategy 3: Focus on Changed Files\n\n```bash\n#!/bin/bash\n# Only validate tickets with changes\n\nCHANGED_TICKETS=$(git diff origin/main --name-only | \\\n grep \"^ttmp/\" | cut -d/ -f2 | sort -u)\n\nfor ticket in $CHANGED_TICKETS; do\n docmgr doctor --ticket \"$ticket\" --fail-on error\ndone\n```\n\n---\n\n## 8. Monitoring and Alerts\n\n### Slack Integration\n\n```bash\n#!/bin/bash\n# scripts/docs-health-slack.sh\n\nSTALE_COUNT=$(docmgr status --stale-after 30 --with-glaze-output --output json | \\\n jq '.docs | map(select(.stale)) | length')\n\nif [ \"$STALE_COUNT\" -gt 5 ]; then\n curl -X POST \"$SLACK_WEBHOOK_URL\" \\\n -H 'Content-Type: application/json' \\\n -d \"{\n \\\"text\\\": \\\"⚠️ Documentation Health Alert\\\",\n \\\"blocks\\\": [{\n \\\"type\\\": \\\"section\\\",\n \\\"text\\\": {\n \\\"type\\\": \\\"mrkdwn\\\",\n \\\"text\\\": \\\"*$STALE_COUNT docs* are stale (\u003e30 days). Review needed!\\\"\n }\n }]\n }\"\nfi\n```\n\n### Dashboard Metrics\n\n```bash\n#!/bin/bash\n# Export metrics for dashboard\n\ndocmgr status --with-glaze-output --output json | \\\n jq '{\n total_tickets: .tickets,\n total_docs: .docs,\n stale_docs: (.docs | map(select(.stale)) | length),\n by_type: (.docs | group_by(.doc_type) | map({type: .[0].doc_type, count: length}))\n }'\n```\n\nSend to monitoring system (Prometheus, Datadog, etc.).\n\n---\n\n## 9. Common Automation Patterns\n\nBulk operations and automation patterns transform docmgr from a documentation tool into a programmable documentation system. These patterns leverage structured output (`--with-glaze-output`) and command composability to automate tedious tasks like syncing metadata from external systems, bulk-updating stale docs, and generating documentation indexes. The key insight is using `docmgr doc search` to find target docs, then piping paths to `docmgr meta update` or `docmgr doc relate` for batch modifications.\n\n### Pattern 1: Sync Metadata from External System\n\n```bash\n#!/bin/bash\n# Sync owners from Jira\n\nfor ticket in $(docmgr list tickets --with-glaze-output --select ticket); do\n OWNERS=$(curl -s \"jira.com/api/ticket/$ticket\" | jq -r '.assignees | join(\",\")')\n if [ -n \"$OWNERS\" ]; then\n docmgr meta update --ticket \"$ticket\" --field Owners --value \"$OWNERS\"\n fi\ndone\n```\n\n### Pattern 2: Auto-Update Stale Doc Status\n\n```bash\n#!/bin/bash\n# Mark stale docs for review\n\ndocmgr doc search --updated-since \"60 days ago\" --with-glaze-output --output json | \\\n jq -r '.[] | .path' | \\\n while read doc; do\n docmgr meta update --doc \"$doc\" --field Status --value \"needs-review\"\n done\n```\n\n### Pattern 3: Generate Documentation Index\n\n```bash\n#!/bin/bash\n# Create DOCS.md with all tickets\n\necho \"# Documentation Index\" \u003e DOCS.md\necho \"\" \u003e\u003e DOCS.md\necho \"Auto-generated: $(date)\" \u003e\u003e DOCS.md\necho \"\" \u003e\u003e DOCS.md\n\ndocmgr ticket list --with-glaze-output --output json | \\\n jq -r '.[] | \"## [\\(.ticket)] \\(.title)\\n\\n**Topics:** \\(.topics)\\n**Status:** \\(.status)\\n\\n\"' \\\n \u003e\u003e DOCS.md\n```\n\nRun in CI, commit back to repo.\n\n---\n\n## 10. Troubleshooting CI Issues\n\n### Issue: Doctor Fails in CI But Passes Locally\n\n**Possible causes:**\n- Different working directory\n- Missing `.docmgrignore`\n- Different `--stale-after` threshold\n\n**Debug:**\n```bash\n# In CI, print what it sees\n- name: Debug\n run: |\n pwd\n ls -la ttmp/\n docmgr status --summary-only\n docmgr doctor --all --fail-on none # See all warnings\n```\n\n---\n\n### Issue: False Positives from Archived Docs\n\n**Solution:** Use `.docmgrignore`\n\n```\n# In ttmp/.docmgrignore\narchive/\n2023-*/\n2024-*/\nLEGACY-*/\n```\n\n---\n\n### Issue: CI Takes Too Long\n\n**Solutions:**\n\n1. **Only validate changed tickets:**\n```bash\nCHANGED=$(git diff origin/main --name-only | grep \"^ttmp/\" | cut -d/ -f2 | sort -u)\nfor t in $CHANGED; do docmgr doctor --ticket \"$t\"; done\n```\n\n2. **Cache docmgr installation:**\n```yaml\n- name: Cache Go modules\n uses: actions/cache@v3\n with:\n path: ~/go/bin/docmgr\n key: ${{ runner.os }}-docmgr-${{ hashFiles('go.sum') }}\n```\n\n3. **Skip on draft PRs:**\n```yaml\nif: github.event.pull_request.draft == false\n```\n\n---\n\n## 11. Advanced: Custom Validation Scripts\n\n### Enforce Ticket Naming Convention\n\n```bash\n#!/bin/bash\n# Validate ticket IDs match pattern\n\ndocmgr list tickets --with-glaze-output --output json | \\\n jq -r '.[] | .ticket' | \\\n while read ticket; do\n if ! [[ \"$ticket\" =~ ^[A-Z]+-[0-9]+$ ]]; then\n echo \"❌ Invalid ticket ID: $ticket (expected: PROJ-123)\"\n exit 1\n fi\n done\n```\n\n### Enforce Required RelatedFiles\n\n```bash\n#!/bin/bash\n# Ensure design docs have related files\n\ndocmgr list docs --doc-type design-doc --with-glaze-output --output json | \\\n jq -r '.[] | select(.related_files == null or (.related_files | length) == 0) | .path' | \\\n while read doc; do\n echo \"⚠️ Design doc missing RelatedFiles: $doc\"\n done\n```\n\n### Enforce Summary Field\n\n```bash\n#!/bin/bash\n# Check all docs have non-empty summaries\n\ndocmgr list docs --with-glaze-output --output json | \\\n jq -r '.[] | select(.summary == \"\" or .summary == null) | \"\\(.ticket)/\\(.path)\"' | \\\n while read doc; do\n echo \"❌ Missing Summary: $doc\"\n EXIT_CODE=1\n done\n\nexit ${EXIT_CODE:-0}\n```\n\n---\n\n## 12. Performance Optimization\n\n### Caching Strategies\n\n**Cache docmgr binary:**\n```yaml\n- name: Cache docmgr\n uses: actions/cache@v3\n with:\n path: ~/go/bin/docmgr\n key: docmgr-${{ hashFiles('**/go.sum') }}\n \n- name: Install docmgr\n run: |\n if [ ! -f ~/go/bin/docmgr ]; then\n go install -tags sqlite_fts5 github.com/go-go-golems/docmgr@latest\n fi\n```\n\n**Parallel validation:**\n```bash\n# Validate tickets in parallel\ndocmgr ticket list --with-glaze-output --select ticket | \\\n xargs -P 4 -I {} docmgr doctor --ticket {} --fail-on error\n```\n\n---\n\n## Quick Reference\n\n### CI Validation Commands\n\n```bash\n# Basic validation\ndocmgr doctor --all --fail-on error\n\n# With staleness\ndocmgr doctor --all --stale-after 30 --fail-on error\n\n# Specific ticket\ndocmgr doctor --ticket MEN-4242 --fail-on error\n\n# JSON output for reporting\ndocmgr doctor --all --with-glaze-output --output json\n```\n\n### Common Make Targets\n\n```bash\nmake docs-validate # Run validation\nmake docs-status # Check health\nmake docs-report # Generate report\nmake ci # Full CI including docs\n```\n\n### Pre-commit Hook Location\n\n```bash\n.git/hooks/pre-commit\nchmod +x .git/hooks/pre-commit\n```\n\n---\n\n## Related Documentation\n\n- **Repository setup:** `docmgr help how-to-setup` — Initialize workspace\n- **Daily usage:** `docmgr help how-to-use` — Creating and managing docs\n- **Templates:** `docmgr help templates-and-guidelines` — Customization\n\n---\n\n## Examples from Real Projects\n\n### Strict Validation (High Standards)\n\n```yaml\n# Requires: no errors, no warnings, no stale docs \u003e14 days\nvalidate-docs:\n script:\n - docmgr doctor --all --stale-after 14 --fail-on warning\n```\n\n### Lenient Validation (Growing Project)\n\n```yaml\n# Only blocks on broken links, allows stale docs\nvalidate-docs:\n script:\n - docmgr doctor --all --fail-on error\n - docmgr status # Print warnings but don't fail\n```\n\n### Balanced Validation (Most Teams)\n\n```yaml\n# Blocks on errors, warns on staleness\nvalidate-docs:\n script:\n - docmgr doctor --all --stale-after 30 --fail-on error\n - |\n STALE=$(docmgr status --stale-after 30 --with-glaze-output --output json | \\\n jq '.docs | map(select(.stale)) | length')\n if [ \"$STALE\" -gt 10 ]; then\n echo \"⚠️ Warning: $STALE stale docs\"\n fi\n```\n\n---\n\n**This guide covers CI integration, automation, reporting, and monitoring for docmgr.**\n"},"fulfilledTimeStamp":1782955585801}},"mutations":{},"provided":{"tags":{"Section":{"advanced-workflows":["listSections({\"packageName\":\"docmgr\",\"version\":\"v0.0.19\"})"],"ci-and-automation":["listSections({\"packageName\":\"docmgr\",\"version\":\"v0.0.19\"})"],"cli-guide":["listSections({\"packageName\":\"docmgr\",\"version\":\"v0.0.19\"})"],"codebase-architecture":["listSections({\"packageName\":\"docmgr\",\"version\":\"v0.0.19\"})"],"diagnostics-taxonomy-and-rules":["listSections({\"packageName\":\"docmgr\",\"version\":\"v0.0.19\"})"],"doctor-validation-workflow":["listSections({\"packageName\":\"docmgr\",\"version\":\"v0.0.19\"})"],"how-to-add-cli-verbs":["listSections({\"packageName\":\"docmgr\",\"version\":\"v0.0.19\"})"],"how-to-setup":["listSections({\"packageName\":\"docmgr\",\"version\":\"v0.0.19\"})"],"how-to-use":["listSections({\"packageName\":\"docmgr\",\"version\":\"v0.0.19\"})"],"http-api":["listSections({\"packageName\":\"docmgr\",\"version\":\"v0.0.19\"})"],"web-ui":["listSections({\"packageName\":\"docmgr\",\"version\":\"v0.0.19\"})"],"yaml-frontmatter-validation-reference":["listSections({\"packageName\":\"docmgr\",\"version\":\"v0.0.19\"})"],"yaml-frontmatter-validation":["listSections({\"packageName\":\"docmgr\",\"version\":\"v0.0.19\"})"],"how-to-write-skills":["listSections({\"packageName\":\"docmgr\",\"version\":\"v0.0.19\"})"],"templates-and-guidelines":["listSections({\"packageName\":\"docmgr\",\"version\":\"v0.0.19\"})"],"using-skills":["listSections({\"packageName\":\"docmgr\",\"version\":\"v0.0.19\"})"],"verb-templates-and-schema":["listSections({\"packageName\":\"docmgr\",\"version\":\"v0.0.19\"})"],"LIST":["listSections({\"packageName\":\"docmgr\",\"version\":\"v0.0.19\"})"],"docmgr:v0.0.19:ci-and-automation":["getSection({\"packageName\":\"docmgr\",\"slug\":\"ci-and-automation\",\"version\":\"v0.0.19\"})"]}},"keys":{"listPackages(undefined)":[],"listSections({\"packageName\":\"docmgr\",\"version\":\"v0.0.19\"})":[{"type":"Section","id":"advanced-workflows"},{"type":"Section","id":"ci-and-automation"},{"type":"Section","id":"cli-guide"},{"type":"Section","id":"codebase-architecture"},{"type":"Section","id":"diagnostics-taxonomy-and-rules"},{"type":"Section","id":"doctor-validation-workflow"},{"type":"Section","id":"how-to-add-cli-verbs"},{"type":"Section","id":"how-to-setup"},{"type":"Section","id":"how-to-use"},{"type":"Section","id":"http-api"},{"type":"Section","id":"web-ui"},{"type":"Section","id":"yaml-frontmatter-validation-reference"},{"type":"Section","id":"yaml-frontmatter-validation"},{"type":"Section","id":"how-to-write-skills"},{"type":"Section","id":"templates-and-guidelines"},{"type":"Section","id":"using-skills"},{"type":"Section","id":"verb-templates-and-schema"},{"type":"Section","id":"LIST"}],"getSection({\"packageName\":\"docmgr\",\"slug\":\"ci-and-automation\",\"version\":\"v0.0.19\"})":[{"type":"Section","id":"docmgr:v0.0.19:ci-and-automation"}]}},"subscriptions":{},"config":{"online":true,"focused":true,"middlewareRegistered":true,"refetchOnFocus":false,"refetchOnReconnect":false,"refetchOnMountOrArgChange":false,"keepUnusedDataFor":60,"reducerPath":"helpApi","invalidationBehavior":"delayed"}}};

CI and Automation Guide for docmgr

Integrate docmgr validation into CI/CD pipelines with GitHub Actions, GitLab CI, pre-commit hooks, and automation patterns.

Sections

Terminology & Glossary
📖 Documentation
Navigation
17 sectionsv0.1
📄 CI and Automation Guide for docmgr — glaze help ci-and-automation
ci-and-automation

CI and Automation Guide for docmgr

Integrate docmgr validation into CI/CD pipelines with GitHub Actions, GitLab CI, pre-commit hooks, and automation patterns.

Tutorialdocmgrci-cdautomationvalidation

CI and Automation Guide for docmgr

Overview

Automated validation prevents documentation drift by catching issues—broken links, missing files, unknown topics, stale docs—before they reach production. docmgr's doctor command is designed for CI/CD integration with proper exit codes, structured output for reporting, and configurable strictness levels. This guide shows how to integrate docmgr into various CI systems (GitHub Actions, GitLab CI, pre-commit hooks) and provides patterns for bulk operations, monitoring, and automated reporting.

This guide covers: CI validation, pre-commit hooks, Makefile integration, automated reporting, bulk operation patterns, and monitoring strategies.

Prerequisites:

  • docmgr initialized in your repository (see docmgr help how-to-setup)
  • CI/CD system available (GitHub Actions, GitLab CI, or equivalent)
  • Basic understanding of shell scripting for automation patterns

1. GitHub Actions Integration

GitHub Actions integration provides automated documentation validation on every pull request, preventing broken links and stale docs from being merged. The workflow triggers only on documentation changes to save CI minutes, installs docmgr, and runs doctor with configurable strictness. This section provides complete workflow examples from basic validation to advanced reporting with structured output.

Basic Validation

Add to .github/workflows/docs-validation.yml:

name: Validate Documentation

on:
  pull_request:
    paths:
      - 'ttmp/**'
      - '.ttmp.yaml'
      - 'pkg/doc/**'

jobs:
  validate-docs:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      
      - name: Set up Go
        uses: actions/setup-go@v4
        with:
          go-version: '1.21'
      
      - name: Install docmgr
        run: go install -tags sqlite_fts5 github.com/go-go-golems/docmgr@latest
      
      - name: Validate documentation
        run: |
          docmgr doctor --all \
            --stale-after 30 \
            --fail-on error

Trigger: Only runs when docs are changed (saves CI minutes).


Validation with Reporting

name: Validate and Report Docs

on:
  pull_request:
    paths:
      - 'ttmp/**'

jobs:
  validate-docs:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      
      - name: Install docmgr
        run: go install -tags sqlite_fts5 github.com/go-go-golems/docmgr@latest
      
      - name: Validate documentation
        run: |
          docmgr doctor --all --stale-after 30 --fail-on error
      
      - name: Generate report on failure
        if: failure()
        run: |
          echo "=== Documentation Issues ==="
          docmgr doctor --all --with-glaze-output --output json | \
            jq -r '.[] | select(.issue != "none") | "[\(.ticket)] \(.path): \(.message)"'

Adjusting Strictness Over Time

Phase-based approach:

# Phase 1: Start lenient (errors only)
- name: Validate (Phase 1)
  run: docmgr doctor --all --fail-on error

# Phase 2: Add staleness (60 days)
- name: Validate (Phase 2)
  run: docmgr doctor --all --stale-after 60 --fail-on error

# Phase 3: Stricter staleness (30 days)
- name: Validate (Phase 3)
  run: docmgr doctor --all --stale-after 30 --fail-on error

# Phase 4: Warnings as errors (strict)
- name: Validate (Phase 4)
  run: docmgr doctor --all --stale-after 30 --fail-on warning

Use .docmgrignore to suppress false positives rather than lowering standards.


2. GitLab CI Integration

Add to .gitlab-ci.yml:

validate-docs:
  stage: test
  image: golang:1.21
  script:
    - go install -tags sqlite_fts5 github.com/go-go-golems/docmgr@latest
    - docmgr doctor --all --stale-after 30 --fail-on error
  only:
    changes:
      - ttmp/**
      - .ttmp.yaml
  allow_failure: false

With Reporting

validate-docs:
  stage: test
  image: golang:1.21
  script:
    - go install -tags sqlite_fts5 github.com/go-go-golems/docmgr@latest
    - docmgr doctor --all --stale-after 30 --fail-on error || EXIT_CODE=$?
    - |
      if [ $EXIT_CODE -ne 0 ]; then
        echo "=== Documentation Issues ==="
        docmgr doctor --all --with-glaze-output --output json | \
          jq -r '.[] | select(.issue != "none") | "[\(.ticket)] \(.path): \(.message)"'
        exit $EXIT_CODE
      fi

3. Pre-commit Hook

Validate docs before allowing commits.

Basic Hook

Create .git/hooks/pre-commit:

#!/bin/bash

# Validate docs before commit
if ! docmgr doctor --all --fail-on error; then
  echo "❌ Documentation validation failed"
  echo ""
  echo "Fix issues or bypass with: git commit --no-verify"
  exit 1
fi

echo "✅ Documentation validation passed"

Make it executable:

chmod +x .git/hooks/pre-commit

Hook with Focused Validation

#!/bin/bash

# Only validate tickets with changed docs
CHANGED_TICKETS=$(git diff --cached --name-only | \
  grep "^ttmp/" | \
  cut -d/ -f2 | \
  sort -u)

if [ -z "$CHANGED_TICKETS" ]; then
  echo "No doc changes, skipping validation"
  exit 0
fi

echo "Validating changed tickets: $CHANGED_TICKETS"

for ticket in $CHANGED_TICKETS; do
  if ! docmgr doctor --ticket "$ticket" --fail-on error; then
    echo "❌ Validation failed for $ticket"
    exit 1
  fi
done

echo "✅ All changed tickets validated"

Benefits: Only validates tickets you changed, faster feedback.


4. Makefile Integration

Add docmgr targets to your Makefile:

.PHONY: docs-validate docs-status docs-report docs-clean

# Validate all docs
docs-validate:
	@echo "Validating documentation..."
	@docmgr doctor --all --stale-after 30 --fail-on error

# Show status
docs-status:
	@docmgr status

# Generate report
docs-report:
	@echo "=== Documentation Summary ==="
	@docmgr status --summary-only
	@echo ""
	@echo "=== Stale Docs (>30 days) ==="
	@docmgr status --stale-after 30 --with-glaze-output --output json | \
	  jq -r '.docs[] | select(.stale) | "[\(.ticket)] \(.title) — stale \(.days_since_update) days"'
	@echo ""
	@echo "=== Recent Activity (7 days) ==="
	@docmgr doc search --updated-since "7 days ago"

# Clean up old date-based tickets
docs-clean:
	@echo "Archiving old tickets..."
	@find ttmp/202[0-3]-* -type d -maxdepth 0 -exec mv {} ttmp/archive/ \; 2>/dev/null || true

# Add to CI target
ci: test lint docs-validate

# Add to pre-commit
pre-commit: fmt lint docs-validate

Usage:

make docs-validate   # Before committing
make docs-status     # Check health
make docs-report     # Weekly review
make ci              # Full CI locally

5. Structured Output (Glaze Framework)

Every docmgr command that produces output can render it in multiple structured formats (JSON, CSV, YAML, TSV) through the Glaze framework. This design decouples the command's business logic from its output format, enabling the same command to serve both human users (with readable tables and text) and automation scripts (with parseable JSON or CSV).

Available Output Formats

  • json — Valid JSON, parseable
  • csv — Comma-separated (for spreadsheets)
  • tsv — Tab-separated
  • yaml — YAML format
  • table — ASCII table (human-readable)

Stable Field Names (API Contract)

Use these with --fields, --filter, --select:

Tickets:

  • ticket, title, status, topics, path, last_updated

Docs:

  • ticket, doc_type, title, status, topics, path, last_updated

Tasks:

  • index, checked, text, file

Vocabulary:

  • category, slug, description

Field Selection Examples

# Paths only (newline-separated)
docmgr list docs --ticket MEN-4242 --with-glaze-output --select path

# Custom columns (CSV)
docmgr list docs --with-glaze-output --output csv \
  --fields doc_type,title,path

# Templated output
docmgr list docs --ticket MEN-4242 --with-glaze-output \
  --select-template '{{.doc_type}}: {{.title}}' --select _0

The stable field contracts ensure your scripts won't break when docmgr is updated, making it safe to build CI/CD integrations, reporting dashboards, and bulk operation scripts on top of docmgr.


6. Automation Patterns

Pattern 1: Find and update stale docs

# Find docs older than 60 days, mark for review
docmgr doc search --updated-since "60 days ago" --with-glaze-output --output json | \
  jq -r '.[] | .path' | \
  while read doc; do
    docmgr meta update --doc "$doc" --field Status --value "needs-review"
  done

Pattern 2: CI validation

#!/bin/bash
# .github/workflows/validate-docs.yml

if ! docmgr doctor --all --stale-after 14 --fail-on error; then
  echo "ERROR: Documentation validation failed"
  # Get list of issues
  docmgr doctor --all --with-glaze-output --output json | \
    jq -r '.[] | select(.issue != "none") | "\(.path): \(.message)"'
  exit 1
fi

Pattern 2b: Export the workspace index as a CI artifact (debugging)

When CI fails or behaves differently than local, exporting the workspace index to SQLite can make investigation much faster: you can download the DB artifact and inspect exactly what docs/topics/related-files were indexed.

# Export index for offline inspection (artifact)
docmgr workspace export-sqlite --out diagnostics/docmgr-index.sqlite --force

# Optional: include markdown bodies for deeper debugging (larger file)
docmgr workspace export-sqlite --out diagnostics/docmgr-index-with-body.sqlite --force --include-body

The exported DB includes a README table populated from docmgr’s embedded docs (pkg/doc/*.md), so the artifact is self-describing even outside the repo.

Pattern 3: Weekly doc report

# Generate report of doc activity
docmgr status --stale-after 7 --with-glaze-output --output json | \
  jq -r '.docs[] | select(.stale) | "\(.ticket): \(.title) (stale \(.days_since_update) days)"'

Pattern 4: Bulk operations

# Create similar tickets
for i in {1..5}; do
    TICKET=PROJ-00$i
    docmgr ticket create-ticket --ticket $TICKET --title "Feature $i" --topics backend
    docmgr doc add --ticket $TICKET --doc-type design-doc --title "Design $i"
done

# Update all docs of a type
docmgr meta update --ticket MEN-4242 --doc-type design-doc \
    --field Status --value complete

7. Automated Reporting

Weekly Documentation Report

#!/bin/bash
# scripts/weekly-docs-report.sh

echo "╔════════════════════════════════════════════════════════════╗"
echo "║  Weekly Documentation Report                               ║"
echo "╚════════════════════════════════════════════════════════════╝"
echo ""

echo "📊 Overview:"
docmgr status --summary-only
echo ""

echo "⚠️  Stale Docs (>30 days):"
docmgr doc search --updated-since "30 days ago" --with-glaze-output --output json | \
  jq -r '.[] | "  • [\(.ticket)] \(.title) (updated: \(.last_updated))"'
echo ""

echo "📝 Recent Activity (last 7 days):"
docmgr doc search --updated-since "7 days ago" --with-glaze-output --output json | \
  jq -r '.[] | "  • [\(.ticket)] \(.title) — \(.doc_type)"' | head -10
echo ""

echo "🔍 Top Topics:"
docmgr doc list --with-glaze-output --output json | \
  jq -r '.[].topics' | tr ',' '\n' | sort | uniq -c | sort -rn | head -5

Run weekly in CI or via cron:

# .github/workflows/weekly-report.yml
on:
  schedule:
    - cron: '0 9 * * MON'  # Every Monday at 9am

jobs:
  report:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Install docmgr
        run: go install -tags sqlite_fts5 github.com/go-go-golems/docmgr@latest
      - name: Generate report
        run: bash scripts/weekly-docs-report.sh

Stale Doc Notifications

#!/bin/bash
# Find docs that haven't been updated in 60 days

echo "Docs requiring attention (>60 days since update):"

docmgr doc search --updated-since "60 days ago" --with-glaze-output --output json | \
  jq -r '.[] | {
    ticket: .ticket,
    title: .title,
    path: .path,
    updated: .last_updated
  } | "[\(.ticket)] \(.title)\n  Path: \(.path)\n  Last updated: \(.updated)\n"'

Send to Slack:

REPORT=$(bash scripts/stale-docs.sh)
curl -X POST "$SLACK_WEBHOOK_URL" \
  -d "{\"text\": \"$REPORT\"}"

6. Bulk Operations and Scripting

Update All Docs in Batch

# Update status on all docs for completed ticket
docmgr meta update --ticket MEN-4242 --field Status --value complete

# Update owners across entire workspace
for ticket in $(docmgr ticket list --with-glaze-output --select ticket); do
  docmgr meta update --ticket "$ticket" --field Owners --value "new,team"
done

Relate Files Automatically

# Auto-relate files from feature branch (notes required for each path)
git diff main --name-only | \
  grep -E '\.(go|ts|tsx|py)
#x27; | \ xargs -I FILE docmgr doc relate --ticket FEAT-042 \ --file-note "FILE:Auto-related from git diff" # With git commit messages as notes for file in $(git diff main --name-only); do NOTE=$(git log -1 --pretty=%B "$file" | head -1) docmgr doc relate --ticket FEAT-042 --file-note "$file:$NOTE" done

Find Impacted Docs Before Refactoring

# Before renaming/moving files, find docs that reference them
docmgr doc search --file pkg/auth/service.go --with-glaze-output --output json | \
  jq -r '.[] | .path'

# Or search by directory
docmgr doc search --dir pkg/auth/ --with-glaze-output --output json | \
  jq -r '.[] | "\(.ticket): \(.title)"' | sort -u

Generate Ticket-to-Code Map

#!/bin/bash
# Export all ticket → code relationships

echo "# Ticket to Code Map"
echo ""

for ticket in $(docmgr ticket list --with-glaze-output --select ticket); do
  echo "## $ticket"
  docmgr doc search --ticket "$ticket" --with-glaze-output --output json | \
    jq -r '.[0].related_files[]? | "- \(.path) — \(.note)"' 2>/dev/null
  echo ""
done

7. CI Strictness Strategies

Strategy 1: Gradual Enforcement

# Week 1-2: Validate on warning (soft)
docmgr doctor --all --fail-on none  # Just print warnings

# Week 3-4: Block on errors only
docmgr doctor --all --fail-on error

# Week 5+: Block on errors and warnings
docmgr doctor --all --fail-on warning

Strategy 2: Per-Branch Rules

# Strict on main/production
on:
  push:
    branches: [main]
# run: docmgr doctor --all --fail-on warning

# Lenient on feature branches
on:
  pull_request:
# run: docmgr doctor --all --fail-on error

Strategy 3: Focus on Changed Files

#!/bin/bash
# Only validate tickets with changes

CHANGED_TICKETS=$(git diff origin/main --name-only | \
  grep "^ttmp/" | cut -d/ -f2 | sort -u)

for ticket in $CHANGED_TICKETS; do
  docmgr doctor --ticket "$ticket" --fail-on error
done

8. Monitoring and Alerts

Slack Integration

#!/bin/bash
# scripts/docs-health-slack.sh

STALE_COUNT=$(docmgr status --stale-after 30 --with-glaze-output --output json | \
  jq '.docs | map(select(.stale)) | length')

if [ "$STALE_COUNT" -gt 5 ]; then
  curl -X POST "$SLACK_WEBHOOK_URL" \
    -H 'Content-Type: application/json' \
    -d "{
      \"text\": \"⚠️  Documentation Health Alert\",
      \"blocks\": [{
        \"type\": \"section\",
        \"text\": {
          \"type\": \"mrkdwn\",
          \"text\": \"*$STALE_COUNT docs* are stale (>30 days). Review needed!\"
        }
      }]
    }"
fi

Dashboard Metrics

#!/bin/bash
# Export metrics for dashboard

docmgr status --with-glaze-output --output json | \
  jq '{
    total_tickets: .tickets,
    total_docs: .docs,
    stale_docs: (.docs | map(select(.stale)) | length),
    by_type: (.docs | group_by(.doc_type) | map({type: .[0].doc_type, count: length}))
  }'

Send to monitoring system (Prometheus, Datadog, etc.).


9. Common Automation Patterns

Bulk operations and automation patterns transform docmgr from a documentation tool into a programmable documentation system. These patterns leverage structured output (--with-glaze-output) and command composability to automate tedious tasks like syncing metadata from external systems, bulk-updating stale docs, and generating documentation indexes. The key insight is using docmgr doc search to find target docs, then piping paths to docmgr meta update or docmgr doc relate for batch modifications.

Pattern 1: Sync Metadata from External System

#!/bin/bash
# Sync owners from Jira

for ticket in $(docmgr list tickets --with-glaze-output --select ticket); do
  OWNERS=$(curl -s "jira.com/api/ticket/$ticket" | jq -r '.assignees | join(",")')
  if [ -n "$OWNERS" ]; then
    docmgr meta update --ticket "$ticket" --field Owners --value "$OWNERS"
  fi
done

Pattern 2: Auto-Update Stale Doc Status

#!/bin/bash
# Mark stale docs for review

docmgr doc search --updated-since "60 days ago" --with-glaze-output --output json | \
  jq -r '.[] | .path' | \
  while read doc; do
    docmgr meta update --doc "$doc" --field Status --value "needs-review"
  done

Pattern 3: Generate Documentation Index

#!/bin/bash
# Create DOCS.md with all tickets

echo "# Documentation Index" > DOCS.md
echo "" >> DOCS.md
echo "Auto-generated: $(date)" >> DOCS.md
echo "" >> DOCS.md

docmgr ticket list --with-glaze-output --output json | \
  jq -r '.[] | "## [\(.ticket)] \(.title)\n\n**Topics:** \(.topics)\n**Status:** \(.status)\n\n"' \
  >> DOCS.md

Run in CI, commit back to repo.


10. Troubleshooting CI Issues

Issue: Doctor Fails in CI But Passes Locally

Possible causes:

  • Different working directory
  • Missing .docmgrignore
  • Different --stale-after threshold

Debug:

# In CI, print what it sees
- name: Debug
  run: |
    pwd
    ls -la ttmp/
    docmgr status --summary-only
    docmgr doctor --all --fail-on none  # See all warnings

Issue: False Positives from Archived Docs

Solution: Use .docmgrignore

# In ttmp/.docmgrignore
archive/
2023-*/
2024-*/
LEGACY-*/

Issue: CI Takes Too Long

Solutions:

  1. Only validate changed tickets:
CHANGED=$(git diff origin/main --name-only | grep "^ttmp/" | cut -d/ -f2 | sort -u)
for t in $CHANGED; do docmgr doctor --ticket "$t"; done
  1. Cache docmgr installation:
- name: Cache Go modules
  uses: actions/cache@v3
  with:
    path: ~/go/bin/docmgr
    key: ${{ runner.os }}-docmgr-${{ hashFiles('go.sum') }}
  1. Skip on draft PRs:
if: github.event.pull_request.draft == false

11. Advanced: Custom Validation Scripts

Enforce Ticket Naming Convention

#!/bin/bash
# Validate ticket IDs match pattern

docmgr list tickets --with-glaze-output --output json | \
  jq -r '.[] | .ticket' | \
  while read ticket; do
    if ! [[ "$ticket" =~ ^[A-Z]+-[0-9]+$ ]]; then
      echo "❌ Invalid ticket ID: $ticket (expected: PROJ-123)"
      exit 1
    fi
  done

Enforce Required RelatedFiles

#!/bin/bash
# Ensure design docs have related files

docmgr list docs --doc-type design-doc --with-glaze-output --output json | \
  jq -r '.[] | select(.related_files == null or (.related_files | length) == 0) | .path' | \
  while read doc; do
    echo "⚠️  Design doc missing RelatedFiles: $doc"
  done

Enforce Summary Field

#!/bin/bash
# Check all docs have non-empty summaries

docmgr list docs --with-glaze-output --output json | \
  jq -r '.[] | select(.summary == "" or .summary == null) | "\(.ticket)/\(.path)"' | \
  while read doc; do
    echo "❌ Missing Summary: $doc"
    EXIT_CODE=1
  done

exit ${EXIT_CODE:-0}

12. Performance Optimization

Caching Strategies

Cache docmgr binary:

- name: Cache docmgr
  uses: actions/cache@v3
  with:
    path: ~/go/bin/docmgr
    key: docmgr-${{ hashFiles('**/go.sum') }}
  
- name: Install docmgr
  run: |
    if [ ! -f ~/go/bin/docmgr ]; then
      go install -tags sqlite_fts5 github.com/go-go-golems/docmgr@latest
    fi

Parallel validation:

# Validate tickets in parallel
docmgr ticket list --with-glaze-output --select ticket | \
  xargs -P 4 -I {} docmgr doctor --ticket {} --fail-on error

Quick Reference

CI Validation Commands

# Basic validation
docmgr doctor --all --fail-on error

# With staleness
docmgr doctor --all --stale-after 30 --fail-on error

# Specific ticket
docmgr doctor --ticket MEN-4242 --fail-on error

# JSON output for reporting
docmgr doctor --all --with-glaze-output --output json

Common Make Targets

make docs-validate    # Run validation
make docs-status      # Check health
make docs-report      # Generate report
make ci               # Full CI including docs

Pre-commit Hook Location

.git/hooks/pre-commit
chmod +x .git/hooks/pre-commit

  • Repository setup: docmgr help how-to-setup — Initialize workspace
  • Daily usage: docmgr help how-to-use — Creating and managing docs
  • Templates: docmgr help templates-and-guidelines — Customization

Examples from Real Projects

Strict Validation (High Standards)

# Requires: no errors, no warnings, no stale docs >14 days
validate-docs:
  script:
    - docmgr doctor --all --stale-after 14 --fail-on warning

Lenient Validation (Growing Project)

# Only blocks on broken links, allows stale docs
validate-docs:
  script:
    - docmgr doctor --all --fail-on error
    - docmgr status  # Print warnings but don't fail

Balanced Validation (Most Teams)

# Blocks on errors, warns on staleness
validate-docs:
  script:
    - docmgr doctor --all --stale-after 30 --fail-on error
    - |
      STALE=$(docmgr status --stale-after 30 --with-glaze-output --output json | \
        jq '.docs | map(select(.stale)) | length')
      if [ "$STALE" -gt 10 ]; then
        echo "⚠️  Warning: $STALE stale docs"
      fi

This guide covers CI integration, automation, reporting, and monitoring for docmgr.