[{"data":1,"prerenderedAt":75},["Reactive",2],{"blog-post-markdown-document-versioning-change-tracking-complete-guide":3},{"slug":4,"title":5,"description":6,"excerpt":7,"date":8,"category":9,"author":10,"keywords":11,"readingMinutes":12,"html":13,"headings":14,"tools":49,"related":50},"markdown-document-versioning-change-tracking-complete-guide","Markdown Document Versioning and Change Tracking: Complete Guide for Professional Documentation Management","Master document versioning and change tracking in Markdown for professional documentation workflows. Learn version control integration, automated change detection, collaborative editing, and revision management for comprehensive documentation maintenance.","Markdown document versioning and change tracking enables professional documentation management through systematic revision control, collaborative editing workflows, and automated change detection…","2025-09-13","Tutorial","Matthew Rathbone","markdown versioning, document change tracking, markdown revision control, git documentation workflow, collaborative markdown editing, document history tracking, markdown diff tools, version control markdown",30,"\u003Cp>Markdown document versioning and change tracking enables professional documentation management through systematic revision control, collaborative editing workflows, and automated change detection that transforms simple text files into enterprise-grade documentation systems. While Markdown&#39;s plain text format naturally supports version control, advanced techniques provide sophisticated tracking, review processes, and historical analysis capabilities that meet the demands of complex documentation projects.\u003C/p>\n\u003Ch2 id=\"why-implement-document-versioning-for-markdown\">Why Implement Document Versioning for Markdown?\u003C/h2>\n\u003Cp>Document versioning provides essential benefits for professional documentation workflows:\u003C/p>\n\u003Cul>\n\u003Cli>\u003Cstrong>Change Attribution\u003C/strong>: Track exactly who made what changes and when for accountability and collaboration\u003C/li>\n\u003Cli>\u003Cstrong>Historical Analysis\u003C/strong>: Understand document evolution patterns and identify key revision points\u003C/li>\n\u003Cli>\u003Cstrong>Rollback Capabilities\u003C/strong>: Safely revert changes when errors are introduced or requirements change\u003C/li>\n\u003Cli>\u003Cstrong>Collaborative Workflows\u003C/strong>: Enable multiple contributors to work simultaneously without conflicts\u003C/li>\n\u003Cli>\u003Cstrong>Compliance Requirements\u003C/strong>: Meet audit and regulatory demands for change documentation and approval processes\u003C/li>\n\u003C/ul>\n\u003Ch2 id=\"git-based-versioning-fundamentals\">Git-Based Versioning Fundamentals\u003C/h2>\n\u003Ch3 id=\"repository-structure-for-documentation-projects\">Repository Structure for Documentation Projects\u003C/h3>\n\u003Cp>Organize Markdown documentation with version control best practices:\u003C/p>\n\u003Cpre>\u003Ccode class=\"hljs language-bash\">\u003Cspan class=\"hljs-comment\"># Documentation repository structure\u003C/span>\ndocs-project/\n├── .git/                          \u003Cspan class=\"hljs-comment\"># Git version control data\u003C/span>\n├── .gitignore                     \u003Cspan class=\"hljs-comment\"># Ignore patterns for documentation builds\u003C/span>\n├── README.md                      \u003Cspan class=\"hljs-comment\"># Project overview and contribution guide\u003C/span>\n├── CHANGELOG.md                   \u003Cspan class=\"hljs-comment\"># High-level change history\u003C/span>\n├── .github/                       \u003Cspan class=\"hljs-comment\"># GitHub-specific workflows and templates\u003C/span>\n│   ├── workflows/\n│   │   ├── documentation.yml      \u003Cspan class=\"hljs-comment\"># CI/CD for docs building and validation\u003C/span>\n│   │   └── link-check.yml         \u003Cspan class=\"hljs-comment\"># Automated link validation\u003C/span>\n│   ├── ISSUE_TEMPLATE/\n│   │   ├── documentation-bug.md   \u003Cspan class=\"hljs-comment\"># Bug report template\u003C/span>\n│   │   └── content-request.md     \u003Cspan class=\"hljs-comment\"># Content addition requests\u003C/span>\n│   └── pull_request_template.md   \u003Cspan class=\"hljs-comment\"># PR template with review checklist\u003C/span>\n├── docs/                          \u003Cspan class=\"hljs-comment\"># Main documentation content\u003C/span>\n│   ├── api/                       \u003Cspan class=\"hljs-comment\"># API documentation\u003C/span>\n│   ├── guides/                    \u003Cspan class=\"hljs-comment\"># User guides and tutorials\u003C/span>\n│   ├── reference/                 \u003Cspan class=\"hljs-comment\"># Reference documentation\u003C/span>\n│   └── internal/                  \u003Cspan class=\"hljs-comment\"># Internal documentation (access-controlled)\u003C/span>\n├── assets/                        \u003Cspan class=\"hljs-comment\"># Images, diagrams, and media files\u003C/span>\n├── templates/                     \u003Cspan class=\"hljs-comment\"># Document templates for consistency\u003C/span>\n├── tools/                         \u003Cspan class=\"hljs-comment\"># Custom scripts for document processing\u003C/span>\n│   ├── generate-toc.py           \u003Cspan class=\"hljs-comment\"># Table of contents generator\u003C/span>\n│   ├── link-validator.sh         \u003Cspan class=\"hljs-comment\"># Link validation script\u003C/span>\n│   └── changelog-generator.py    \u003Cspan class=\"hljs-comment\"># Automated changelog generation\u003C/span>\n└── config/                        \u003Cspan class=\"hljs-comment\"># Configuration files\u003C/span>\n    ├── markdownlint.yml          \u003Cspan class=\"hljs-comment\"># Markdown linting rules\u003C/span>\n    └── spelling-wordlist.txt     \u003Cspan class=\"hljs-comment\"># Custom spelling dictionary\u003C/span>\n\n\u003Cspan class=\"hljs-comment\"># Git configuration for documentation projects\u003C/span>\ngit config --\u003Cspan class=\"hljs-built_in\">local\u003C/span> core.autocrlf input          \u003Cspan class=\"hljs-comment\"># Consistent line endings\u003C/span>\ngit config --\u003Cspan class=\"hljs-built_in\">local\u003C/span> core.filemode \u003Cspan class=\"hljs-literal\">false\u003C/span>          \u003Cspan class=\"hljs-comment\"># Ignore file permission changes\u003C/span>\ngit config --\u003Cspan class=\"hljs-built_in\">local\u003C/span> merge.ours.driver \u003Cspan class=\"hljs-literal\">true\u003C/span>       \u003Cspan class=\"hljs-comment\"># Custom merge strategies\u003C/span>\ngit config --\u003Cspan class=\"hljs-built_in\">local\u003C/span> diff.md.textconv \u003Cspan class=\"hljs-string\">&quot;pandoc --to=plain&quot;\u003C/span> \u003Cspan class=\"hljs-comment\"># Better diff display\u003C/span>\n\u003C/code>\u003C/pre>\u003Ch3 id=\"advanced-git-configuration-for-markdown\">Advanced Git Configuration for Markdown\u003C/h3>\n\u003Cp>Optimize Git behavior for documentation workflows:\u003C/p>\n\u003Cpre>\u003Ccode class=\"hljs language-bash\">\u003Cspan class=\"hljs-comment\"># .gitattributes - Configure file handling behavior\u003C/span>\n*.md text eol=lf diff=md            \u003Cspan class=\"hljs-comment\"># Markdown files with custom diff\u003C/span>\n*.mdx text eol=lf diff=md           \u003Cspan class=\"hljs-comment\"># MDX files (React + Markdown)\u003C/span>\n*.yaml text eol=lf                  \u003Cspan class=\"hljs-comment\"># YAML configuration files\u003C/span>\n*.yml text eol=lf                   \u003Cspan class=\"hljs-comment\"># YAML configuration files\u003C/span>\n*.json text eol=lf                  \u003Cspan class=\"hljs-comment\"># JSON configuration files\u003C/span>\n\n\u003Cspan class=\"hljs-comment\"># Binary files\u003C/span>\n*.png binary                        \u003Cspan class=\"hljs-comment\"># Images are binary\u003C/span>\n*.jpg binary                        \u003Cspan class=\"hljs-comment\"># Images are binary\u003C/span>\n*.pdf binary                        \u003Cspan class=\"hljs-comment\"># PDFs are binary\u003C/span>\n*.drawio binary                     \u003Cspan class=\"hljs-comment\"># Diagrams are binary\u003C/span>\n\n\u003Cspan class=\"hljs-comment\"># Generated files (exclude from version control)\u003C/span>\n_site/ export-ignore               \u003Cspan class=\"hljs-comment\"># Jekyll build output\u003C/span>\npublic/ export-ignore              \u003Cspan class=\"hljs-comment\"># Static site output\u003C/span>\nnode_modules/ export-ignore        \u003Cspan class=\"hljs-comment\"># Node.js dependencies\u003C/span>\n.DS_Store export-ignore            \u003Cspan class=\"hljs-comment\"># macOS system files\u003C/span>\n\n\u003Cspan class=\"hljs-comment\"># Custom merge strategies for specific files\u003C/span>\nCHANGELOG.md merge=union           \u003Cspan class=\"hljs-comment\"># Union merge for changelog files\u003C/span>\npackage-lock.json merge=ours       \u003Cspan class=\"hljs-comment\"># Keep our version of lock files\u003C/span>\n\u003C/code>\u003C/pre>\u003Cpre>\u003Ccode class=\"hljs language-bash\">\u003Cspan class=\"hljs-comment\"># .gitignore - Documentation-specific ignore patterns\u003C/span>\n\u003Cspan class=\"hljs-comment\"># Build outputs\u003C/span>\n_site/\npublic/\ndist/\n.cache/\n\n\u003Cspan class=\"hljs-comment\"># Dependency directories\u003C/span>\nnode_modules/\nvendor/bundle/\n\n\u003Cspan class=\"hljs-comment\"># Environment and configuration\u003C/span>\n.\u003Cspan class=\"hljs-built_in\">env\u003C/span>\n.env.local\n.vscode/\n.idea/\n\n\u003Cspan class=\"hljs-comment\"># Operating system files\u003C/span>\n.DS_Store\nThumbs.db\n\n\u003Cspan class=\"hljs-comment\"># Temporary files\u003C/span>\n*.tmp\n*.swp\n*.swo\n*~\n\n\u003Cspan class=\"hljs-comment\"># Generated documentation files\u003C/span>\napi-docs-generated/\ncoverage-reports/\ntest-results/\n\n\u003Cspan class=\"hljs-comment\"># Local development files\u003C/span>\n.jekyll-metadata\n.bundle/\n.sass-cache/\n\u003C/code>\u003C/pre>\u003Ch3 id=\"commit-message-standards-for-documentation\">Commit Message Standards for Documentation\u003C/h3>\n\u003Cp>Implement structured commit messaging for documentation changes:\u003C/p>\n\u003Cpre>\u003Ccode class=\"hljs language-bash\">\u003Cspan class=\"hljs-comment\"># Conventional commit format for documentation\u003C/span>\ngit commit -m \u003Cspan class=\"hljs-string\">&quot;docs: add API authentication examples\n\n- Include OAuth2 flow diagrams\n- Add code samples for Python, JavaScript, and curl\n- Update error handling documentation\n- Link to security best practices guide\n\nAddresses #456\nCo-authored-by: security-team@company.com&quot;\u003C/span>\n\n\u003Cspan class=\"hljs-comment\"># Commit type prefixes for documentation\u003C/span>\ndocs:     \u003Cspan class=\"hljs-comment\"># Documentation changes\u003C/span>\nfix:      \u003Cspan class=\"hljs-comment\"># Bug fixes in documentation\u003C/span>\nfeat:     \u003Cspan class=\"hljs-comment\"># New documentation features\u003C/span>\nstyle:    \u003Cspan class=\"hljs-comment\"># Formatting changes (no content change)\u003C/span>\nrefactor: \u003Cspan class=\"hljs-comment\"># Restructuring documentation\u003C/span>\n\u003Cspan class=\"hljs-built_in\">test\u003C/span>:     \u003Cspan class=\"hljs-comment\"># Adding tests for documentation builds\u003C/span>\nchore:    \u003Cspan class=\"hljs-comment\"># Maintenance tasks (updating dependencies, etc.)\u003C/span>\n\n\u003Cspan class=\"hljs-comment\"># Examples of well-structured documentation commits\u003C/span>\ngit commit -m \u003Cspan class=\"hljs-string\">&quot;docs: update API rate limiting guide\n\n- Add Token Bucket algorithm implementation\n- Include Redis-based distributed rate limiting\n- Add monitoring and alerting examples\n- Update error response format documentation\n\nBreaking change: Rate limit headers now use RFC format\nCloses #789&quot;\u003C/span>\n\ngit commit -m \u003Cspan class=\"hljs-string\">&quot;fix: correct code example in authentication guide\n\nThe JWT verification example had incorrect signature validation.\nUpdated to use proper HMAC-SHA256 verification process.\n\nFixes #234&quot;\u003C/span>\n\ngit commit -m \u003Cspan class=\"hljs-string\">&quot;feat: add interactive code examples to API docs\n\n- Implement runnable code samples with syntax highlighting\n- Add copy-to-clipboard functionality\n- Include environment variable templating\n- Support multiple programming languages\n\nEnhancement for issue #567&quot;\u003C/span>\n\u003C/code>\u003C/pre>\u003Ch2 id=\"advanced-change-tracking-techniques\">Advanced Change Tracking Techniques\u003C/h2>\n\u003Ch3 id=\"diff-visualization-and-analysis\">Diff Visualization and Analysis\u003C/h3>\n\u003Cp>Create sophisticated diff analysis for Markdown changes:\u003C/p>\n\u003Cpre>\u003Ccode class=\"hljs language-python\">\u003Cspan class=\"hljs-comment\">#!/usr/bin/env python3\u003C/span>\n\u003Cspan class=\"hljs-string\">&quot;&quot;&quot;\nAdvanced Markdown diff analyzer with semantic change detection.\nIdentifies content changes, structural modifications, and formatting updates.\n&quot;&quot;&quot;\u003C/span>\n\n\u003Cspan class=\"hljs-keyword\">import\u003C/span> re\n\u003Cspan class=\"hljs-keyword\">import\u003C/span> difflib\n\u003Cspan class=\"hljs-keyword\">import\u003C/span> argparse\n\u003Cspan class=\"hljs-keyword\">import\u003C/span> json\n\u003Cspan class=\"hljs-keyword\">from\u003C/span> pathlib \u003Cspan class=\"hljs-keyword\">import\u003C/span> Path\n\u003Cspan class=\"hljs-keyword\">from\u003C/span> typing \u003Cspan class=\"hljs-keyword\">import\u003C/span> \u003Cspan class=\"hljs-type\">Dict\u003C/span>, \u003Cspan class=\"hljs-type\">List\u003C/span>, \u003Cspan class=\"hljs-type\">Tuple\u003C/span>, \u003Cspan class=\"hljs-type\">Any\u003C/span>\n\u003Cspan class=\"hljs-keyword\">from\u003C/span> datetime \u003Cspan class=\"hljs-keyword\">import\u003C/span> datetime\n\u003Cspan class=\"hljs-keyword\">import\u003C/span> hashlib\n\n\u003Cspan class=\"hljs-keyword\">class\u003C/span> \u003Cspan class=\"hljs-title class_\">MarkdownDiffAnalyzer\u003C/span>:\n    \u003Cspan class=\"hljs-string\">&quot;&quot;&quot;\n    Analyzes changes between Markdown document versions with semantic understanding.\n    &quot;&quot;&quot;\u003C/span>\n    \n    \u003Cspan class=\"hljs-keyword\">def\u003C/span> \u003Cspan class=\"hljs-title function_\">__init__\u003C/span>(\u003Cspan class=\"hljs-params\">self\u003C/span>):\n        self.heading_pattern = re.\u003Cspan class=\"hljs-built_in\">compile\u003C/span>(\u003Cspan class=\"hljs-string\">r&#x27;^#+\\s+(.+)$&#x27;\u003C/span>, re.MULTILINE)\n        self.link_pattern = re.\u003Cspan class=\"hljs-built_in\">compile\u003C/span>(\u003Cspan class=\"hljs-string\">r&#x27;\\[([^\\]]+)\\]\\(([^)]+)\\)&#x27;\u003C/span>)\n        self.code_block_pattern = re.\u003Cspan class=\"hljs-built_in\">compile\u003C/span>(\u003Cspan class=\"hljs-string\">r&#x27;```[\\s\\S]*?```&#x27;\u003C/span>)\n        self.image_pattern = re.\u003Cspan class=\"hljs-built_in\">compile\u003C/span>(\u003Cspan class=\"hljs-string\">r&#x27;!\\[([^\\]]*)\\]\\(([^)]+)\\)&#x27;\u003C/span>)\n        \n    \u003Cspan class=\"hljs-keyword\">def\u003C/span> \u003Cspan class=\"hljs-title function_\">extract_structure\u003C/span>(\u003Cspan class=\"hljs-params\">self, content: \u003Cspan class=\"hljs-built_in\">str\u003C/span>\u003C/span>) -&gt; \u003Cspan class=\"hljs-type\">Dict\u003C/span>[\u003Cspan class=\"hljs-built_in\">str\u003C/span>, \u003Cspan class=\"hljs-type\">Any\u003C/span>]:\n        \u003Cspan class=\"hljs-string\">&quot;&quot;&quot;Extract document structure for semantic comparison.&quot;&quot;&quot;\u003C/span>\n        lines = content.split(\u003Cspan class=\"hljs-string\">&#x27;\\n&#x27;\u003C/span>)\n        \n        structure = {\n            \u003Cspan class=\"hljs-string\">&#x27;headings&#x27;\u003C/span>: [],\n            \u003Cspan class=\"hljs-string\">&#x27;links&#x27;\u003C/span>: [],\n            \u003Cspan class=\"hljs-string\">&#x27;images&#x27;\u003C/span>: [],\n            \u003Cspan class=\"hljs-string\">&#x27;code_blocks&#x27;\u003C/span>: [],\n            \u003Cspan class=\"hljs-string\">&#x27;line_count&#x27;\u003C/span>: \u003Cspan class=\"hljs-built_in\">len\u003C/span>(lines),\n            \u003Cspan class=\"hljs-string\">&#x27;word_count&#x27;\u003C/span>: \u003Cspan class=\"hljs-built_in\">len\u003C/span>(content.split()),\n            \u003Cspan class=\"hljs-string\">&#x27;character_count&#x27;\u003C/span>: \u003Cspan class=\"hljs-built_in\">len\u003C/span>(content)\n        }\n        \n        \u003Cspan class=\"hljs-comment\"># Extract headings with hierarchy\u003C/span>\n        \u003Cspan class=\"hljs-keyword\">for\u003C/span> \u003Cspan class=\"hljs-keyword\">match\u003C/span> \u003Cspan class=\"hljs-keyword\">in\u003C/span> self.heading_pattern.finditer(content):\n            level = \u003Cspan class=\"hljs-built_in\">len\u003C/span>(\u003Cspan class=\"hljs-keyword\">match\u003C/span>.group(\u003Cspan class=\"hljs-number\">0\u003C/span>).split()[\u003Cspan class=\"hljs-number\">0\u003C/span>])  \u003Cspan class=\"hljs-comment\"># Count # characters\u003C/span>\n            text = \u003Cspan class=\"hljs-keyword\">match\u003C/span>.group(\u003Cspan class=\"hljs-number\">1\u003C/span>).strip()\n            structure[\u003Cspan class=\"hljs-string\">&#x27;headings&#x27;\u003C/span>].append({\n                \u003Cspan class=\"hljs-string\">&#x27;level&#x27;\u003C/span>: level,\n                \u003Cspan class=\"hljs-string\">&#x27;text&#x27;\u003C/span>: text,\n                \u003Cspan class=\"hljs-string\">&#x27;line&#x27;\u003C/span>: content[:\u003Cspan class=\"hljs-keyword\">match\u003C/span>.start()].count(\u003Cspan class=\"hljs-string\">&#x27;\\n&#x27;\u003C/span>) + \u003Cspan class=\"hljs-number\">1\u003C/span>\n            })\n        \n        \u003Cspan class=\"hljs-comment\"># Extract links\u003C/span>\n        \u003Cspan class=\"hljs-keyword\">for\u003C/span> \u003Cspan class=\"hljs-keyword\">match\u003C/span> \u003Cspan class=\"hljs-keyword\">in\u003C/span> self.link_pattern.finditer(content):\n            structure[\u003Cspan class=\"hljs-string\">&#x27;links&#x27;\u003C/span>].append({\n                \u003Cspan class=\"hljs-string\">&#x27;text&#x27;\u003C/span>: \u003Cspan class=\"hljs-keyword\">match\u003C/span>.group(\u003Cspan class=\"hljs-number\">1\u003C/span>),\n                \u003Cspan class=\"hljs-string\">&#x27;url&#x27;\u003C/span>: \u003Cspan class=\"hljs-keyword\">match\u003C/span>.group(\u003Cspan class=\"hljs-number\">2\u003C/span>),\n                \u003Cspan class=\"hljs-string\">&#x27;line&#x27;\u003C/span>: content[:\u003Cspan class=\"hljs-keyword\">match\u003C/span>.start()].count(\u003Cspan class=\"hljs-string\">&#x27;\\n&#x27;\u003C/span>) + \u003Cspan class=\"hljs-number\">1\u003C/span>\n            })\n        \n        \u003Cspan class=\"hljs-comment\"># Extract images\u003C/span>\n        \u003Cspan class=\"hljs-keyword\">for\u003C/span> \u003Cspan class=\"hljs-keyword\">match\u003C/span> \u003Cspan class=\"hljs-keyword\">in\u003C/span> self.image_pattern.finditer(content):\n            structure[\u003Cspan class=\"hljs-string\">&#x27;images&#x27;\u003C/span>].append({\n                \u003Cspan class=\"hljs-string\">&#x27;alt_text&#x27;\u003C/span>: \u003Cspan class=\"hljs-keyword\">match\u003C/span>.group(\u003Cspan class=\"hljs-number\">1\u003C/span>),\n                \u003Cspan class=\"hljs-string\">&#x27;src&#x27;\u003C/span>: \u003Cspan class=\"hljs-keyword\">match\u003C/span>.group(\u003Cspan class=\"hljs-number\">2\u003C/span>),\n                \u003Cspan class=\"hljs-string\">&#x27;line&#x27;\u003C/span>: content[:\u003Cspan class=\"hljs-keyword\">match\u003C/span>.start()].count(\u003Cspan class=\"hljs-string\">&#x27;\\n&#x27;\u003C/span>) + \u003Cspan class=\"hljs-number\">1\u003C/span>\n            })\n        \n        \u003Cspan class=\"hljs-comment\"># Extract code blocks\u003C/span>\n        \u003Cspan class=\"hljs-keyword\">for\u003C/span> \u003Cspan class=\"hljs-keyword\">match\u003C/span> \u003Cspan class=\"hljs-keyword\">in\u003C/span> self.code_block_pattern.finditer(content):\n            code_content = \u003Cspan class=\"hljs-keyword\">match\u003C/span>.group(\u003Cspan class=\"hljs-number\">0\u003C/span>)\n            language = \u003Cspan class=\"hljs-string\">&#x27;&#x27;\u003C/span>\n            \u003Cspan class=\"hljs-keyword\">if\u003C/span> code_content.startswith(\u003Cspan class=\"hljs-string\">&#x27;```&#x27;\u003C/span>) \u003Cspan class=\"hljs-keyword\">and\u003C/span> \u003Cspan class=\"hljs-built_in\">len\u003C/span>(code_content) &gt; \u003Cspan class=\"hljs-number\">3\u003C/span>:\n                first_line = code_content.split(\u003Cspan class=\"hljs-string\">&#x27;\\n&#x27;\u003C/span>)[\u003Cspan class=\"hljs-number\">0\u003C/span>]\n                language = first_line[\u003Cspan class=\"hljs-number\">3\u003C/span>:].strip()\n            \n            structure[\u003Cspan class=\"hljs-string\">&#x27;code_blocks&#x27;\u003C/span>].append({\n                \u003Cspan class=\"hljs-string\">&#x27;language&#x27;\u003C/span>: language,\n                \u003Cspan class=\"hljs-string\">&#x27;content&#x27;\u003C/span>: code_content,\n                \u003Cspan class=\"hljs-string\">&#x27;line&#x27;\u003C/span>: content[:\u003Cspan class=\"hljs-keyword\">match\u003C/span>.start()].count(\u003Cspan class=\"hljs-string\">&#x27;\\n&#x27;\u003C/span>) + \u003Cspan class=\"hljs-number\">1\u003C/span>,\n                \u003Cspan class=\"hljs-string\">&#x27;size&#x27;\u003C/span>: \u003Cspan class=\"hljs-built_in\">len\u003C/span>(code_content)\n            })\n        \n        \u003Cspan class=\"hljs-keyword\">return\u003C/span> structure\n    \n    \u003Cspan class=\"hljs-keyword\">def\u003C/span> \u003Cspan class=\"hljs-title function_\">compare_structures\u003C/span>(\u003Cspan class=\"hljs-params\">self, old_structure: \u003Cspan class=\"hljs-type\">Dict\u003C/span>, new_structure: \u003Cspan class=\"hljs-type\">Dict\u003C/span>\u003C/span>) -&gt; \u003Cspan class=\"hljs-type\">Dict\u003C/span>[\u003Cspan class=\"hljs-built_in\">str\u003C/span>, \u003Cspan class=\"hljs-type\">Any\u003C/span>]:\n        \u003Cspan class=\"hljs-string\">&quot;&quot;&quot;Compare document structures to identify semantic changes.&quot;&quot;&quot;\u003C/span>\n        changes = {\n            \u003Cspan class=\"hljs-string\">&#x27;headings&#x27;\u003C/span>: {\u003Cspan class=\"hljs-string\">&#x27;added&#x27;\u003C/span>: [], \u003Cspan class=\"hljs-string\">&#x27;removed&#x27;\u003C/span>: [], \u003Cspan class=\"hljs-string\">&#x27;modified&#x27;\u003C/span>: []},\n            \u003Cspan class=\"hljs-string\">&#x27;links&#x27;\u003C/span>: {\u003Cspan class=\"hljs-string\">&#x27;added&#x27;\u003C/span>: [], \u003Cspan class=\"hljs-string\">&#x27;removed&#x27;\u003C/span>: []},\n            \u003Cspan class=\"hljs-string\">&#x27;images&#x27;\u003C/span>: {\u003Cspan class=\"hljs-string\">&#x27;added&#x27;\u003C/span>: [], \u003Cspan class=\"hljs-string\">&#x27;removed&#x27;\u003C/span>: []},\n            \u003Cspan class=\"hljs-string\">&#x27;code_blocks&#x27;\u003C/span>: {\u003Cspan class=\"hljs-string\">&#x27;added&#x27;\u003C/span>: [], \u003Cspan class=\"hljs-string\">&#x27;removed&#x27;\u003C/span>: [], \u003Cspan class=\"hljs-string\">&#x27;modified&#x27;\u003C/span>: []},\n            \u003Cspan class=\"hljs-string\">&#x27;metrics&#x27;\u003C/span>: {\n                \u003Cspan class=\"hljs-string\">&#x27;line_count_change&#x27;\u003C/span>: new_structure[\u003Cspan class=\"hljs-string\">&#x27;line_count&#x27;\u003C/span>] - old_structure[\u003Cspan class=\"hljs-string\">&#x27;line_count&#x27;\u003C/span>],\n                \u003Cspan class=\"hljs-string\">&#x27;word_count_change&#x27;\u003C/span>: new_structure[\u003Cspan class=\"hljs-string\">&#x27;word_count&#x27;\u003C/span>] - old_structure[\u003Cspan class=\"hljs-string\">&#x27;word_count&#x27;\u003C/span>],\n                \u003Cspan class=\"hljs-string\">&#x27;character_count_change&#x27;\u003C/span>: new_structure[\u003Cspan class=\"hljs-string\">&#x27;character_count&#x27;\u003C/span>] - old_structure[\u003Cspan class=\"hljs-string\">&#x27;character_count&#x27;\u003C/span>]\n            }\n        }\n        \n        \u003Cspan class=\"hljs-comment\"># Compare headings\u003C/span>\n        old_headings = {h[\u003Cspan class=\"hljs-string\">&#x27;text&#x27;\u003C/span>]: h \u003Cspan class=\"hljs-keyword\">for\u003C/span> h \u003Cspan class=\"hljs-keyword\">in\u003C/span> old_structure[\u003Cspan class=\"hljs-string\">&#x27;headings&#x27;\u003C/span>]}\n        new_headings = {h[\u003Cspan class=\"hljs-string\">&#x27;text&#x27;\u003C/span>]: h \u003Cspan class=\"hljs-keyword\">for\u003C/span> h \u003Cspan class=\"hljs-keyword\">in\u003C/span> new_structure[\u003Cspan class=\"hljs-string\">&#x27;headings&#x27;\u003C/span>]}\n        \n        \u003Cspan class=\"hljs-keyword\">for\u003C/span> heading_text \u003Cspan class=\"hljs-keyword\">in\u003C/span> old_headings:\n            \u003Cspan class=\"hljs-keyword\">if\u003C/span> heading_text \u003Cspan class=\"hljs-keyword\">not\u003C/span> \u003Cspan class=\"hljs-keyword\">in\u003C/span> new_headings:\n                changes[\u003Cspan class=\"hljs-string\">&#x27;headings&#x27;\u003C/span>][\u003Cspan class=\"hljs-string\">&#x27;removed&#x27;\u003C/span>].append(old_headings[heading_text])\n            \u003Cspan class=\"hljs-keyword\">elif\u003C/span> old_headings[heading_text][\u003Cspan class=\"hljs-string\">&#x27;level&#x27;\u003C/span>] != new_headings[heading_text][\u003Cspan class=\"hljs-string\">&#x27;level&#x27;\u003C/span>]:\n                changes[\u003Cspan class=\"hljs-string\">&#x27;headings&#x27;\u003C/span>][\u003Cspan class=\"hljs-string\">&#x27;modified&#x27;\u003C/span>].append({\n                    \u003Cspan class=\"hljs-string\">&#x27;text&#x27;\u003C/span>: heading_text,\n                    \u003Cspan class=\"hljs-string\">&#x27;old_level&#x27;\u003C/span>: old_headings[heading_text][\u003Cspan class=\"hljs-string\">&#x27;level&#x27;\u003C/span>],\n                    \u003Cspan class=\"hljs-string\">&#x27;new_level&#x27;\u003C/span>: new_headings[heading_text][\u003Cspan class=\"hljs-string\">&#x27;level&#x27;\u003C/span>]\n                })\n        \n        \u003Cspan class=\"hljs-keyword\">for\u003C/span> heading_text \u003Cspan class=\"hljs-keyword\">in\u003C/span> new_headings:\n            \u003Cspan class=\"hljs-keyword\">if\u003C/span> heading_text \u003Cspan class=\"hljs-keyword\">not\u003C/span> \u003Cspan class=\"hljs-keyword\">in\u003C/span> old_headings:\n                changes[\u003Cspan class=\"hljs-string\">&#x27;headings&#x27;\u003C/span>][\u003Cspan class=\"hljs-string\">&#x27;added&#x27;\u003C/span>].append(new_headings[heading_text])\n        \n        \u003Cspan class=\"hljs-comment\"># Compare links\u003C/span>\n        old_links = {(l[\u003Cspan class=\"hljs-string\">&#x27;text&#x27;\u003C/span>], l[\u003Cspan class=\"hljs-string\">&#x27;url&#x27;\u003C/span>]) \u003Cspan class=\"hljs-keyword\">for\u003C/span> l \u003Cspan class=\"hljs-keyword\">in\u003C/span> old_structure[\u003Cspan class=\"hljs-string\">&#x27;links&#x27;\u003C/span>]}\n        new_links = {(l[\u003Cspan class=\"hljs-string\">&#x27;text&#x27;\u003C/span>], l[\u003Cspan class=\"hljs-string\">&#x27;url&#x27;\u003C/span>]) \u003Cspan class=\"hljs-keyword\">for\u003C/span> l \u003Cspan class=\"hljs-keyword\">in\u003C/span> new_structure[\u003Cspan class=\"hljs-string\">&#x27;links&#x27;\u003C/span>]}\n        \n        \u003Cspan class=\"hljs-keyword\">for\u003C/span> link \u003Cspan class=\"hljs-keyword\">in\u003C/span> old_links - new_links:\n            changes[\u003Cspan class=\"hljs-string\">&#x27;links&#x27;\u003C/span>][\u003Cspan class=\"hljs-string\">&#x27;removed&#x27;\u003C/span>].append({\u003Cspan class=\"hljs-string\">&#x27;text&#x27;\u003C/span>: link[\u003Cspan class=\"hljs-number\">0\u003C/span>], \u003Cspan class=\"hljs-string\">&#x27;url&#x27;\u003C/span>: link[\u003Cspan class=\"hljs-number\">1\u003C/span>]})\n        \n        \u003Cspan class=\"hljs-keyword\">for\u003C/span> link \u003Cspan class=\"hljs-keyword\">in\u003C/span> new_links - old_links:\n            changes[\u003Cspan class=\"hljs-string\">&#x27;links&#x27;\u003C/span>][\u003Cspan class=\"hljs-string\">&#x27;added&#x27;\u003C/span>].append({\u003Cspan class=\"hljs-string\">&#x27;text&#x27;\u003C/span>: link[\u003Cspan class=\"hljs-number\">0\u003C/span>], \u003Cspan class=\"hljs-string\">&#x27;url&#x27;\u003C/span>: link[\u003Cspan class=\"hljs-number\">1\u003C/span>]})\n        \n        \u003Cspan class=\"hljs-comment\"># Compare images\u003C/span>\n        old_images = {(i[\u003Cspan class=\"hljs-string\">&#x27;alt_text&#x27;\u003C/span>], i[\u003Cspan class=\"hljs-string\">&#x27;src&#x27;\u003C/span>]) \u003Cspan class=\"hljs-keyword\">for\u003C/span> i \u003Cspan class=\"hljs-keyword\">in\u003C/span> old_structure[\u003Cspan class=\"hljs-string\">&#x27;images&#x27;\u003C/span>]}\n        new_images = {(i[\u003Cspan class=\"hljs-string\">&#x27;alt_text&#x27;\u003C/span>], i[\u003Cspan class=\"hljs-string\">&#x27;src&#x27;\u003C/span>]) \u003Cspan class=\"hljs-keyword\">for\u003C/span> i \u003Cspan class=\"hljs-keyword\">in\u003C/span> new_structure[\u003Cspan class=\"hljs-string\">&#x27;images&#x27;\u003C/span>]}\n        \n        \u003Cspan class=\"hljs-keyword\">for\u003C/span> image \u003Cspan class=\"hljs-keyword\">in\u003C/span> old_images - new_images:\n            changes[\u003Cspan class=\"hljs-string\">&#x27;images&#x27;\u003C/span>][\u003Cspan class=\"hljs-string\">&#x27;removed&#x27;\u003C/span>].append({\u003Cspan class=\"hljs-string\">&#x27;alt_text&#x27;\u003C/span>: image[\u003Cspan class=\"hljs-number\">0\u003C/span>], \u003Cspan class=\"hljs-string\">&#x27;src&#x27;\u003C/span>: image[\u003Cspan class=\"hljs-number\">1\u003C/span>]})\n        \n        \u003Cspan class=\"hljs-keyword\">for\u003C/span> image \u003Cspan class=\"hljs-keyword\">in\u003C/span> new_images - old_images:\n            changes[\u003Cspan class=\"hljs-string\">&#x27;images&#x27;\u003C/span>][\u003Cspan class=\"hljs-string\">&#x27;added&#x27;\u003C/span>].append({\u003Cspan class=\"hljs-string\">&#x27;alt_text&#x27;\u003C/span>: image[\u003Cspan class=\"hljs-number\">0\u003C/span>], \u003Cspan class=\"hljs-string\">&#x27;src&#x27;\u003C/span>: image[\u003Cspan class=\"hljs-number\">1\u003C/span>]})\n        \n        \u003Cspan class=\"hljs-comment\"># Compare code blocks (by content hash)\u003C/span>\n        old_code_hashes = {hashlib.md5(cb[\u003Cspan class=\"hljs-string\">&#x27;content&#x27;\u003C/span>].encode()).hexdigest(): cb \u003Cspan class=\"hljs-keyword\">for\u003C/span> cb \u003Cspan class=\"hljs-keyword\">in\u003C/span> old_structure[\u003Cspan class=\"hljs-string\">&#x27;code_blocks&#x27;\u003C/span>]}\n        new_code_hashes = {hashlib.md5(cb[\u003Cspan class=\"hljs-string\">&#x27;content&#x27;\u003C/span>].encode()).hexdigest(): cb \u003Cspan class=\"hljs-keyword\">for\u003C/span> cb \u003Cspan class=\"hljs-keyword\">in\u003C/span> new_structure[\u003Cspan class=\"hljs-string\">&#x27;code_blocks&#x27;\u003C/span>]}\n        \n        \u003Cspan class=\"hljs-keyword\">for\u003C/span> hash_val \u003Cspan class=\"hljs-keyword\">in\u003C/span> old_code_hashes:\n            \u003Cspan class=\"hljs-keyword\">if\u003C/span> hash_val \u003Cspan class=\"hljs-keyword\">not\u003C/span> \u003Cspan class=\"hljs-keyword\">in\u003C/span> new_code_hashes:\n                changes[\u003Cspan class=\"hljs-string\">&#x27;code_blocks&#x27;\u003C/span>][\u003Cspan class=\"hljs-string\">&#x27;removed&#x27;\u003C/span>].append(old_code_hashes[hash_val])\n        \n        \u003Cspan class=\"hljs-keyword\">for\u003C/span> hash_val \u003Cspan class=\"hljs-keyword\">in\u003C/span> new_code_hashes:\n            \u003Cspan class=\"hljs-keyword\">if\u003C/span> hash_val \u003Cspan class=\"hljs-keyword\">not\u003C/span> \u003Cspan class=\"hljs-keyword\">in\u003C/span> old_code_hashes:\n                changes[\u003Cspan class=\"hljs-string\">&#x27;code_blocks&#x27;\u003C/span>][\u003Cspan class=\"hljs-string\">&#x27;added&#x27;\u003C/span>].append(new_code_hashes[hash_val])\n        \n        \u003Cspan class=\"hljs-keyword\">return\u003C/span> changes\n    \n    \u003Cspan class=\"hljs-keyword\">def\u003C/span> \u003Cspan class=\"hljs-title function_\">generate_change_summary\u003C/span>(\u003Cspan class=\"hljs-params\">self, old_content: \u003Cspan class=\"hljs-built_in\">str\u003C/span>, new_content: \u003Cspan class=\"hljs-built_in\">str\u003C/span>\u003C/span>) -&gt; \u003Cspan class=\"hljs-type\">Dict\u003C/span>[\u003Cspan class=\"hljs-built_in\">str\u003C/span>, \u003Cspan class=\"hljs-type\">Any\u003C/span>]:\n        \u003Cspan class=\"hljs-string\">&quot;&quot;&quot;Generate comprehensive change summary with semantic analysis.&quot;&quot;&quot;\u003C/span>\n        old_structure = self.extract_structure(old_content)\n        new_structure = self.extract_structure(new_content)\n        \n        \u003Cspan class=\"hljs-comment\"># Get line-by-line diff\u003C/span>\n        old_lines = old_content.split(\u003Cspan class=\"hljs-string\">&#x27;\\n&#x27;\u003C/span>)\n        new_lines = new_content.split(\u003Cspan class=\"hljs-string\">&#x27;\\n&#x27;\u003C/span>)\n        \n        diff = \u003Cspan class=\"hljs-built_in\">list\u003C/span>(difflib.unified_diff(\n            old_lines, \n            new_lines, \n            fromfile=\u003Cspan class=\"hljs-string\">&#x27;old_version&#x27;\u003C/span>,\n            tofile=\u003Cspan class=\"hljs-string\">&#x27;new_version&#x27;\u003C/span>,\n            lineterm=\u003Cspan class=\"hljs-string\">&#x27;&#x27;\u003C/span>\n        ))\n        \n        \u003Cspan class=\"hljs-comment\"># Analyze diff for change types\u003C/span>\n        additions = \u003Cspan class=\"hljs-built_in\">sum\u003C/span>(\u003Cspan class=\"hljs-number\">1\u003C/span> \u003Cspan class=\"hljs-keyword\">for\u003C/span> line \u003Cspan class=\"hljs-keyword\">in\u003C/span> diff \u003Cspan class=\"hljs-keyword\">if\u003C/span> line.startswith(\u003Cspan class=\"hljs-string\">&#x27;+&#x27;\u003C/span>) \u003Cspan class=\"hljs-keyword\">and\u003C/span> \u003Cspan class=\"hljs-keyword\">not\u003C/span> line.startswith(\u003Cspan class=\"hljs-string\">&#x27;+++&#x27;\u003C/span>))\n        deletions = \u003Cspan class=\"hljs-built_in\">sum\u003C/span>(\u003Cspan class=\"hljs-number\">1\u003C/span> \u003Cspan class=\"hljs-keyword\">for\u003C/span> line \u003Cspan class=\"hljs-keyword\">in\u003C/span> diff \u003Cspan class=\"hljs-keyword\">if\u003C/span> line.startswith(\u003Cspan class=\"hljs-string\">&#x27;-&#x27;\u003C/span>) \u003Cspan class=\"hljs-keyword\">and\u003C/span> \u003Cspan class=\"hljs-keyword\">not\u003C/span> line.startswith(\u003Cspan class=\"hljs-string\">&#x27;---&#x27;\u003C/span>))\n        \n        \u003Cspan class=\"hljs-comment\"># Compare structures\u003C/span>\n        structural_changes = self.compare_structures(old_structure, new_structure)\n        \n        \u003Cspan class=\"hljs-keyword\">return\u003C/span> {\n            \u003Cspan class=\"hljs-string\">&#x27;timestamp&#x27;\u003C/span>: datetime.now().isoformat(),\n            \u003Cspan class=\"hljs-string\">&#x27;line_diff&#x27;\u003C/span>: {\n                \u003Cspan class=\"hljs-string\">&#x27;additions&#x27;\u003C/span>: additions,\n                \u003Cspan class=\"hljs-string\">&#x27;deletions&#x27;\u003C/span>: deletions,\n                \u003Cspan class=\"hljs-string\">&#x27;changes&#x27;\u003C/span>: additions + deletions\n            },\n            \u003Cspan class=\"hljs-string\">&#x27;structural_changes&#x27;\u003C/span>: structural_changes,\n            \u003Cspan class=\"hljs-string\">&#x27;diff_output&#x27;\u003C/span>: \u003Cspan class=\"hljs-string\">&#x27;\\n&#x27;\u003C/span>.join(diff),\n            \u003Cspan class=\"hljs-string\">&#x27;change_classification&#x27;\u003C/span>: self._classify_changes(structural_changes)\n        }\n    \n    \u003Cspan class=\"hljs-keyword\">def\u003C/span> \u003Cspan class=\"hljs-title function_\">_classify_changes\u003C/span>(\u003Cspan class=\"hljs-params\">self, structural_changes: \u003Cspan class=\"hljs-type\">Dict\u003C/span>\u003C/span>) -&gt; \u003Cspan class=\"hljs-type\">Dict\u003C/span>[\u003Cspan class=\"hljs-built_in\">str\u003C/span>, \u003Cspan class=\"hljs-built_in\">str\u003C/span>]:\n        \u003Cspan class=\"hljs-string\">&quot;&quot;&quot;Classify the type and significance of changes.&quot;&quot;&quot;\u003C/span>\n        classification = {\n            \u003Cspan class=\"hljs-string\">&#x27;significance&#x27;\u003C/span>: \u003Cspan class=\"hljs-string\">&#x27;minor&#x27;\u003C/span>,  \u003Cspan class=\"hljs-comment\"># minor, major, breaking\u003C/span>\n            \u003Cspan class=\"hljs-string\">&#x27;type&#x27;\u003C/span>: \u003Cspan class=\"hljs-string\">&#x27;content&#x27;\u003C/span>,       \u003Cspan class=\"hljs-comment\"># content, structure, formatting\u003C/span>\n            \u003Cspan class=\"hljs-string\">&#x27;impact&#x27;\u003C/span>: \u003Cspan class=\"hljs-string\">&#x27;low&#x27;\u003C/span>          \u003Cspan class=\"hljs-comment\"># low, medium, high\u003C/span>\n        }\n        \n        \u003Cspan class=\"hljs-comment\"># Determine significance\u003C/span>\n        \u003Cspan class=\"hljs-keyword\">if\u003C/span> structural_changes[\u003Cspan class=\"hljs-string\">&#x27;headings&#x27;\u003C/span>][\u003Cspan class=\"hljs-string\">&#x27;removed&#x27;\u003C/span>] \u003Cspan class=\"hljs-keyword\">or\u003C/span> structural_changes[\u003Cspan class=\"hljs-string\">&#x27;headings&#x27;\u003C/span>][\u003Cspan class=\"hljs-string\">&#x27;added&#x27;\u003C/span>]:\n            \u003Cspan class=\"hljs-keyword\">if\u003C/span> \u003Cspan class=\"hljs-built_in\">len\u003C/span>(structural_changes[\u003Cspan class=\"hljs-string\">&#x27;headings&#x27;\u003C/span>][\u003Cspan class=\"hljs-string\">&#x27;removed&#x27;\u003C/span>]) &gt; \u003Cspan class=\"hljs-number\">2\u003C/span> \u003Cspan class=\"hljs-keyword\">or\u003C/span> \u003Cspan class=\"hljs-built_in\">len\u003C/span>(structural_changes[\u003Cspan class=\"hljs-string\">&#x27;headings&#x27;\u003C/span>][\u003Cspan class=\"hljs-string\">&#x27;added&#x27;\u003C/span>]) &gt; \u003Cspan class=\"hljs-number\">2\u003C/span>:\n                classification[\u003Cspan class=\"hljs-string\">&#x27;significance&#x27;\u003C/span>] = \u003Cspan class=\"hljs-string\">&#x27;major&#x27;\u003C/span>\n            \u003Cspan class=\"hljs-keyword\">else\u003C/span>:\n                classification[\u003Cspan class=\"hljs-string\">&#x27;significance&#x27;\u003C/span>] = \u003Cspan class=\"hljs-string\">&#x27;minor&#x27;\u003C/span>\n        \n        \u003Cspan class=\"hljs-keyword\">if\u003C/span> structural_changes[\u003Cspan class=\"hljs-string\">&#x27;links&#x27;\u003C/span>][\u003Cspan class=\"hljs-string\">&#x27;removed&#x27;\u003C/span>] \u003Cspan class=\"hljs-keyword\">or\u003C/span> structural_changes[\u003Cspan class=\"hljs-string\">&#x27;code_blocks&#x27;\u003C/span>][\u003Cspan class=\"hljs-string\">&#x27;removed&#x27;\u003C/span>]:\n            classification[\u003Cspan class=\"hljs-string\">&#x27;significance&#x27;\u003C/span>] = \u003Cspan class=\"hljs-string\">&#x27;breaking&#x27;\u003C/span>\n        \n        \u003Cspan class=\"hljs-comment\"># Determine type\u003C/span>\n        \u003Cspan class=\"hljs-keyword\">if\u003C/span> (structural_changes[\u003Cspan class=\"hljs-string\">&#x27;headings&#x27;\u003C/span>][\u003Cspan class=\"hljs-string\">&#x27;added&#x27;\u003C/span>] \u003Cspan class=\"hljs-keyword\">or\u003C/span> \n            structural_changes[\u003Cspan class=\"hljs-string\">&#x27;headings&#x27;\u003C/span>][\u003Cspan class=\"hljs-string\">&#x27;removed&#x27;\u003C/span>] \u003Cspan class=\"hljs-keyword\">or\u003C/span> \n            structural_changes[\u003Cspan class=\"hljs-string\">&#x27;headings&#x27;\u003C/span>][\u003Cspan class=\"hljs-string\">&#x27;modified&#x27;\u003C/span>]):\n            classification[\u003Cspan class=\"hljs-string\">&#x27;type&#x27;\u003C/span>] = \u003Cspan class=\"hljs-string\">&#x27;structure&#x27;\u003C/span>\n        \u003Cspan class=\"hljs-keyword\">elif\u003C/span> structural_changes[\u003Cspan class=\"hljs-string\">&#x27;links&#x27;\u003C/span>][\u003Cspan class=\"hljs-string\">&#x27;added&#x27;\u003C/span>] \u003Cspan class=\"hljs-keyword\">or\u003C/span> structural_changes[\u003Cspan class=\"hljs-string\">&#x27;links&#x27;\u003C/span>][\u003Cspan class=\"hljs-string\">&#x27;removed&#x27;\u003C/span>]:\n            classification[\u003Cspan class=\"hljs-string\">&#x27;type&#x27;\u003C/span>] = \u003Cspan class=\"hljs-string\">&#x27;content&#x27;\u003C/span>\n        \n        \u003Cspan class=\"hljs-comment\"># Determine impact\u003C/span>\n        total_changes = (\n            \u003Cspan class=\"hljs-built_in\">len\u003C/span>(structural_changes[\u003Cspan class=\"hljs-string\">&#x27;headings&#x27;\u003C/span>][\u003Cspan class=\"hljs-string\">&#x27;added&#x27;\u003C/span>]) +\n            \u003Cspan class=\"hljs-built_in\">len\u003C/span>(structural_changes[\u003Cspan class=\"hljs-string\">&#x27;headings&#x27;\u003C/span>][\u003Cspan class=\"hljs-string\">&#x27;removed&#x27;\u003C/span>]) +\n            \u003Cspan class=\"hljs-built_in\">len\u003C/span>(structural_changes[\u003Cspan class=\"hljs-string\">&#x27;links&#x27;\u003C/span>][\u003Cspan class=\"hljs-string\">&#x27;added&#x27;\u003C/span>]) +\n            \u003Cspan class=\"hljs-built_in\">len\u003C/span>(structural_changes[\u003Cspan class=\"hljs-string\">&#x27;links&#x27;\u003C/span>][\u003Cspan class=\"hljs-string\">&#x27;removed&#x27;\u003C/span>]) +\n            \u003Cspan class=\"hljs-built_in\">len\u003C/span>(structural_changes[\u003Cspan class=\"hljs-string\">&#x27;code_blocks&#x27;\u003C/span>][\u003Cspan class=\"hljs-string\">&#x27;added&#x27;\u003C/span>]) +\n            \u003Cspan class=\"hljs-built_in\">len\u003C/span>(structural_changes[\u003Cspan class=\"hljs-string\">&#x27;code_blocks&#x27;\u003C/span>][\u003Cspan class=\"hljs-string\">&#x27;removed&#x27;\u003C/span>])\n        )\n        \n        \u003Cspan class=\"hljs-keyword\">if\u003C/span> total_changes &gt; \u003Cspan class=\"hljs-number\">10\u003C/span>:\n            classification[\u003Cspan class=\"hljs-string\">&#x27;impact&#x27;\u003C/span>] = \u003Cspan class=\"hljs-string\">&#x27;high&#x27;\u003C/span>\n        \u003Cspan class=\"hljs-keyword\">elif\u003C/span> total_changes &gt; \u003Cspan class=\"hljs-number\">3\u003C/span>:\n            classification[\u003Cspan class=\"hljs-string\">&#x27;impact&#x27;\u003C/span>] = \u003Cspan class=\"hljs-string\">&#x27;medium&#x27;\u003C/span>\n        \u003Cspan class=\"hljs-keyword\">else\u003C/span>:\n            classification[\u003Cspan class=\"hljs-string\">&#x27;impact&#x27;\u003C/span>] = \u003Cspan class=\"hljs-string\">&#x27;low&#x27;\u003C/span>\n        \n        \u003Cspan class=\"hljs-keyword\">return\u003C/span> classification\n\n\u003Cspan class=\"hljs-keyword\">def\u003C/span> \u003Cspan class=\"hljs-title function_\">main\u003C/span>():\n    parser = argparse.ArgumentParser(description=\u003Cspan class=\"hljs-string\">&#x27;Analyze changes between Markdown document versions&#x27;\u003C/span>)\n    parser.add_argument(\u003Cspan class=\"hljs-string\">&#x27;old_file&#x27;\u003C/span>, \u003Cspan class=\"hljs-built_in\">help\u003C/span>=\u003Cspan class=\"hljs-string\">&#x27;Path to old version of the document&#x27;\u003C/span>)\n    parser.add_argument(\u003Cspan class=\"hljs-string\">&#x27;new_file&#x27;\u003C/span>, \u003Cspan class=\"hljs-built_in\">help\u003C/span>=\u003Cspan class=\"hljs-string\">&#x27;Path to new version of the document&#x27;\u003C/span>)\n    parser.add_argument(\u003Cspan class=\"hljs-string\">&#x27;--output&#x27;\u003C/span>, \u003Cspan class=\"hljs-string\">&#x27;-o&#x27;\u003C/span>, \u003Cspan class=\"hljs-built_in\">help\u003C/span>=\u003Cspan class=\"hljs-string\">&#x27;Output file for analysis results (JSON format)&#x27;\u003C/span>)\n    parser.add_argument(\u003Cspan class=\"hljs-string\">&#x27;--format&#x27;\u003C/span>, choices=[\u003Cspan class=\"hljs-string\">&#x27;json&#x27;\u003C/span>, \u003Cspan class=\"hljs-string\">&#x27;text&#x27;\u003C/span>], default=\u003Cspan class=\"hljs-string\">&#x27;text&#x27;\u003C/span>, \u003Cspan class=\"hljs-built_in\">help\u003C/span>=\u003Cspan class=\"hljs-string\">&#x27;Output format&#x27;\u003C/span>)\n    \n    args = parser.parse_args()\n    \n    \u003Cspan class=\"hljs-comment\"># Read files\u003C/span>\n    old_content = Path(args.old_file).read_text(encoding=\u003Cspan class=\"hljs-string\">&#x27;utf-8&#x27;\u003C/span>)\n    new_content = Path(args.new_file).read_text(encoding=\u003Cspan class=\"hljs-string\">&#x27;utf-8&#x27;\u003C/span>)\n    \n    \u003Cspan class=\"hljs-comment\"># Analyze changes\u003C/span>\n    analyzer = MarkdownDiffAnalyzer()\n    analysis = analyzer.generate_change_summary(old_content, new_content)\n    \n    \u003Cspan class=\"hljs-keyword\">if\u003C/span> args.\u003Cspan class=\"hljs-built_in\">format\u003C/span> == \u003Cspan class=\"hljs-string\">&#x27;json&#x27;\u003C/span>:\n        output = json.dumps(analysis, indent=\u003Cspan class=\"hljs-number\">2\u003C/span>)\n    \u003Cspan class=\"hljs-keyword\">else\u003C/span>:\n        \u003Cspan class=\"hljs-comment\"># Format as human-readable text\u003C/span>\n        classification = analysis[\u003Cspan class=\"hljs-string\">&#x27;change_classification&#x27;\u003C/span>]\n        changes = analysis[\u003Cspan class=\"hljs-string\">&#x27;structural_changes&#x27;\u003C/span>]\n        \n        output = \u003Cspan class=\"hljs-string\">f&quot;&quot;&quot;\nMarkdown Document Change Analysis\n================================\n\nChange Classification:\n- Significance: \u003Cspan class=\"hljs-subst\">{classification[\u003Cspan class=\"hljs-string\">&#x27;significance&#x27;\u003C/span>]}\u003C/span>\n- Type: \u003Cspan class=\"hljs-subst\">{classification[\u003Cspan class=\"hljs-string\">&#x27;type&#x27;\u003C/span>]}\u003C/span>\n- Impact: \u003Cspan class=\"hljs-subst\">{classification[\u003Cspan class=\"hljs-string\">&#x27;impact&#x27;\u003C/span>]}\u003C/span>\n\nLine Changes:\n- Additions: \u003Cspan class=\"hljs-subst\">{analysis[\u003Cspan class=\"hljs-string\">&#x27;line_diff&#x27;\u003C/span>][\u003Cspan class=\"hljs-string\">&#x27;additions&#x27;\u003C/span>]}\u003C/span> lines\n- Deletions: \u003Cspan class=\"hljs-subst\">{analysis[\u003Cspan class=\"hljs-string\">&#x27;line_diff&#x27;\u003C/span>][\u003Cspan class=\"hljs-string\">&#x27;deletions&#x27;\u003C/span>]}\u003C/span> lines\n- Total changes: \u003Cspan class=\"hljs-subst\">{analysis[\u003Cspan class=\"hljs-string\">&#x27;line_diff&#x27;\u003C/span>][\u003Cspan class=\"hljs-string\">&#x27;changes&#x27;\u003C/span>]}\u003C/span> lines\n\nStructural Changes:\n- Headings added: \u003Cspan class=\"hljs-subst\">{\u003Cspan class=\"hljs-built_in\">len\u003C/span>(changes[\u003Cspan class=\"hljs-string\">&#x27;headings&#x27;\u003C/span>][\u003Cspan class=\"hljs-string\">&#x27;added&#x27;\u003C/span>])}\u003C/span>\n- Headings removed: \u003Cspan class=\"hljs-subst\">{\u003Cspan class=\"hljs-built_in\">len\u003C/span>(changes[\u003Cspan class=\"hljs-string\">&#x27;headings&#x27;\u003C/span>][\u003Cspan class=\"hljs-string\">&#x27;removed&#x27;\u003C/span>])}\u003C/span>\n- Headings modified: \u003Cspan class=\"hljs-subst\">{\u003Cspan class=\"hljs-built_in\">len\u003C/span>(changes[\u003Cspan class=\"hljs-string\">&#x27;headings&#x27;\u003C/span>][\u003Cspan class=\"hljs-string\">&#x27;modified&#x27;\u003C/span>])}\u003C/span>\n- Links added: \u003Cspan class=\"hljs-subst\">{\u003Cspan class=\"hljs-built_in\">len\u003C/span>(changes[\u003Cspan class=\"hljs-string\">&#x27;links&#x27;\u003C/span>][\u003Cspan class=\"hljs-string\">&#x27;added&#x27;\u003C/span>])}\u003C/span>\n- Links removed: \u003Cspan class=\"hljs-subst\">{\u003Cspan class=\"hljs-built_in\">len\u003C/span>(changes[\u003Cspan class=\"hljs-string\">&#x27;links&#x27;\u003C/span>][\u003Cspan class=\"hljs-string\">&#x27;removed&#x27;\u003C/span>])}\u003C/span>\n- Code blocks added: \u003Cspan class=\"hljs-subst\">{\u003Cspan class=\"hljs-built_in\">len\u003C/span>(changes[\u003Cspan class=\"hljs-string\">&#x27;code_blocks&#x27;\u003C/span>][\u003Cspan class=\"hljs-string\">&#x27;added&#x27;\u003C/span>])}\u003C/span>\n- Code blocks removed: \u003Cspan class=\"hljs-subst\">{\u003Cspan class=\"hljs-built_in\">len\u003C/span>(changes[\u003Cspan class=\"hljs-string\">&#x27;code_blocks&#x27;\u003C/span>][\u003Cspan class=\"hljs-string\">&#x27;removed&#x27;\u003C/span>])}\u003C/span>\n\nContent Metrics:\n- Line count change: \u003Cspan class=\"hljs-subst\">{changes[\u003Cspan class=\"hljs-string\">&#x27;metrics&#x27;\u003C/span>][\u003Cspan class=\"hljs-string\">&#x27;line_count_change&#x27;\u003C/span>]}\u003C/span>\n- Word count change: \u003Cspan class=\"hljs-subst\">{changes[\u003Cspan class=\"hljs-string\">&#x27;metrics&#x27;\u003C/span>][\u003Cspan class=\"hljs-string\">&#x27;word_count_change&#x27;\u003C/span>]}\u003C/span>\n- Character count change: \u003Cspan class=\"hljs-subst\">{changes[\u003Cspan class=\"hljs-string\">&#x27;metrics&#x27;\u003C/span>][\u003Cspan class=\"hljs-string\">&#x27;character_count_change&#x27;\u003C/span>]}\u003C/span>\n\nAnalysis completed at: \u003Cspan class=\"hljs-subst\">{analysis[\u003Cspan class=\"hljs-string\">&#x27;timestamp&#x27;\u003C/span>]}\u003C/span>\n&quot;&quot;&quot;\u003C/span>\n    \n    \u003Cspan class=\"hljs-keyword\">if\u003C/span> args.output:\n        Path(args.output).write_text(output, encoding=\u003Cspan class=\"hljs-string\">&#x27;utf-8&#x27;\u003C/span>)\n        \u003Cspan class=\"hljs-built_in\">print\u003C/span>(\u003Cspan class=\"hljs-string\">f&quot;Analysis saved to \u003Cspan class=\"hljs-subst\">{args.output}\u003C/span>&quot;\u003C/span>)\n    \u003Cspan class=\"hljs-keyword\">else\u003C/span>:\n        \u003Cspan class=\"hljs-built_in\">print\u003C/span>(output)\n\n\u003Cspan class=\"hljs-keyword\">if\u003C/span> __name__ == \u003Cspan class=\"hljs-string\">&#x27;__main__&#x27;\u003C/span>:\n    main()\n\u003C/code>\u003C/pre>\u003Ch3 id=\"automated-change-detection-and-notifications\">Automated Change Detection and Notifications\u003C/h3>\n\u003Cp>Implement automated systems for monitoring documentation changes:\u003C/p>\n\u003Cpre>\u003Ccode class=\"hljs language-yaml\">\u003Cspan class=\"hljs-comment\"># .github/workflows/documentation-changes.yml\u003C/span>\n\u003Cspan class=\"hljs-comment\"># GitHub Actions workflow for automated change detection and notification\u003C/span>\n\n\u003Cspan class=\"hljs-attr\">name:\u003C/span> \u003Cspan class=\"hljs-string\">Documentation\u003C/span> \u003Cspan class=\"hljs-string\">Change\u003C/span> \u003Cspan class=\"hljs-string\">Analysis\u003C/span>\n\n\u003Cspan class=\"hljs-attr\">on:\u003C/span>\n  \u003Cspan class=\"hljs-attr\">push:\u003C/span>\n    \u003Cspan class=\"hljs-attr\">branches:\u003C/span> [\u003Cspan class=\"hljs-string\">main\u003C/span>, \u003Cspan class=\"hljs-string\">develop\u003C/span>]\n    \u003Cspan class=\"hljs-attr\">paths:\u003C/span> [\u003Cspan class=\"hljs-string\">&#x27;docs/**/*.md&#x27;\u003C/span>, \u003Cspan class=\"hljs-string\">&#x27;*.md&#x27;\u003C/span>]\n  \u003Cspan class=\"hljs-attr\">pull_request:\u003C/span>\n    \u003Cspan class=\"hljs-attr\">branches:\u003C/span> [\u003Cspan class=\"hljs-string\">main\u003C/span>]\n    \u003Cspan class=\"hljs-attr\">paths:\u003C/span> [\u003Cspan class=\"hljs-string\">&#x27;docs/**/*.md&#x27;\u003C/span>, \u003Cspan class=\"hljs-string\">&#x27;*.md&#x27;\u003C/span>]\n\n\u003Cspan class=\"hljs-attr\">jobs:\u003C/span>\n  \u003Cspan class=\"hljs-attr\">analyze-changes:\u003C/span>\n    \u003Cspan class=\"hljs-attr\">runs-on:\u003C/span> \u003Cspan class=\"hljs-string\">ubuntu-latest\u003C/span>\n    \n    \u003Cspan class=\"hljs-attr\">steps:\u003C/span>\n    \u003Cspan class=\"hljs-bullet\">-\u003C/span> \u003Cspan class=\"hljs-attr\">name:\u003C/span> \u003Cspan class=\"hljs-string\">Checkout\u003C/span> \u003Cspan class=\"hljs-string\">current\u003C/span> \u003Cspan class=\"hljs-string\">branch\u003C/span>\n      \u003Cspan class=\"hljs-attr\">uses:\u003C/span> \u003Cspan class=\"hljs-string\">actions/checkout@v3\u003C/span>\n      \u003Cspan class=\"hljs-attr\">with:\u003C/span>\n        \u003Cspan class=\"hljs-attr\">fetch-depth:\u003C/span> \u003Cspan class=\"hljs-number\">0\u003C/span>  \u003Cspan class=\"hljs-comment\"># Full history for comparison\u003C/span>\n    \n    \u003Cspan class=\"hljs-bullet\">-\u003C/span> \u003Cspan class=\"hljs-attr\">name:\u003C/span> \u003Cspan class=\"hljs-string\">Setup\u003C/span> \u003Cspan class=\"hljs-string\">Python\u003C/span>\n      \u003Cspan class=\"hljs-attr\">uses:\u003C/span> \u003Cspan class=\"hljs-string\">actions/setup-python@v4\u003C/span>\n      \u003Cspan class=\"hljs-attr\">with:\u003C/span>\n        \u003Cspan class=\"hljs-attr\">python-version:\u003C/span> \u003Cspan class=\"hljs-string\">&#x27;3.9&#x27;\u003C/span>\n    \n    \u003Cspan class=\"hljs-bullet\">-\u003C/span> \u003Cspan class=\"hljs-attr\">name:\u003C/span> \u003Cspan class=\"hljs-string\">Install\u003C/span> \u003Cspan class=\"hljs-string\">analysis\u003C/span> \u003Cspan class=\"hljs-string\">dependencies\u003C/span>\n      \u003Cspan class=\"hljs-attr\">run:\u003C/span> \u003Cspan class=\"hljs-string\">|\n        pip install difflib pathlib argparse\n        chmod +x ./tools/markdown-diff-analyzer.py\n\u003C/span>    \n    \u003Cspan class=\"hljs-bullet\">-\u003C/span> \u003Cspan class=\"hljs-attr\">name:\u003C/span> \u003Cspan class=\"hljs-string\">Identify\u003C/span> \u003Cspan class=\"hljs-string\">changed\u003C/span> \u003Cspan class=\"hljs-string\">files\u003C/span>\n      \u003Cspan class=\"hljs-attr\">id:\u003C/span> \u003Cspan class=\"hljs-string\">changed-files\u003C/span>\n      \u003Cspan class=\"hljs-attr\">uses:\u003C/span> \u003Cspan class=\"hljs-string\">tj-actions/changed-files@v35\u003C/span>\n      \u003Cspan class=\"hljs-attr\">with:\u003C/span>\n        \u003Cspan class=\"hljs-attr\">files:\u003C/span> \u003Cspan class=\"hljs-string\">|\n          docs/**/*.md\n          *.md\n\u003C/span>    \n    \u003Cspan class=\"hljs-bullet\">-\u003C/span> \u003Cspan class=\"hljs-attr\">name:\u003C/span> \u003Cspan class=\"hljs-string\">Analyze\u003C/span> \u003Cspan class=\"hljs-string\">document\u003C/span> \u003Cspan class=\"hljs-string\">changes\u003C/span>\n      \u003Cspan class=\"hljs-attr\">if:\u003C/span> \u003Cspan class=\"hljs-string\">steps.changed-files.outputs.any_changed\u003C/span> \u003Cspan class=\"hljs-string\">==\u003C/span> \u003Cspan class=\"hljs-string\">&#x27;true&#x27;\u003C/span>\n      \u003Cspan class=\"hljs-attr\">run:\u003C/span> \u003Cspan class=\"hljs-string\">|\n        echo &quot;Changed files: ${{ steps.changed-files.outputs.all_changed_files }}&quot;\n\u003C/span>        \n        \u003Cspan class=\"hljs-comment\"># Create analysis results directory\u003C/span>\n        \u003Cspan class=\"hljs-string\">mkdir\u003C/span> \u003Cspan class=\"hljs-string\">-p\u003C/span> \u003Cspan class=\"hljs-string\">analysis-results\u003C/span>\n        \n        \u003Cspan class=\"hljs-comment\"># Analyze each changed file\u003C/span>\n        \u003Cspan class=\"hljs-string\">for\u003C/span> \u003Cspan class=\"hljs-string\">file\u003C/span> \u003Cspan class=\"hljs-string\">in\u003C/span> \u003Cspan class=\"hljs-string\">${{\u003C/span> \u003Cspan class=\"hljs-string\">steps.changed-files.outputs.all_changed_files\u003C/span> \u003Cspan class=\"hljs-string\">}};\u003C/span> \u003Cspan class=\"hljs-string\">do\u003C/span>\n          \u003Cspan class=\"hljs-string\">echo\u003C/span> \u003Cspan class=\"hljs-string\">&quot;Analyzing changes in $file&quot;\u003C/span>\n          \n          \u003Cspan class=\"hljs-comment\"># Get the previous version of the file\u003C/span>\n          \u003Cspan class=\"hljs-string\">git\u003C/span> \u003Cspan class=\"hljs-string\">show\u003C/span> \u003Cspan class=\"hljs-string\">HEAD~1:$file\u003C/span> \u003Cspan class=\"hljs-string\">&gt;\u003C/span> \u003Cspan class=\"hljs-string\">previous_version.md\u003C/span> \u003Cspan class=\"hljs-number\">2\u003C/span>\u003Cspan class=\"hljs-string\">&gt;/dev/null\u003C/span> \u003Cspan class=\"hljs-string\">||\u003C/span> \u003Cspan class=\"hljs-string\">echo\u003C/span> \u003Cspan class=\"hljs-string\">&quot;# New file&quot;\u003C/span> \u003Cspan class=\"hljs-string\">&gt;\u003C/span> \u003Cspan class=\"hljs-string\">previous_version.md\u003C/span>\n          \n          \u003Cspan class=\"hljs-comment\"># Run analysis\u003C/span>\n          \u003Cspan class=\"hljs-string\">python\u003C/span> \u003Cspan class=\"hljs-string\">./tools/markdown-diff-analyzer.py\u003C/span> \u003Cspan class=\"hljs-string\">\\\u003C/span>\n            \u003Cspan class=\"hljs-string\">previous_version.md\u003C/span> \u003Cspan class=\"hljs-string\">\\\u003C/span>\n            \u003Cspan class=\"hljs-string\">&quot;$file&quot;\u003C/span> \u003Cspan class=\"hljs-string\">\\\u003C/span>\n            \u003Cspan class=\"hljs-string\">--format\u003C/span> \u003Cspan class=\"hljs-string\">json\u003C/span> \u003Cspan class=\"hljs-string\">\\\u003C/span>\n            \u003Cspan class=\"hljs-string\">--output\u003C/span> \u003Cspan class=\"hljs-string\">&quot;analysis-results/$(basename $file .md)-analysis.json&quot;\u003C/span>\n        \u003Cspan class=\"hljs-string\">done\u003C/span>\n    \n    \u003Cspan class=\"hljs-bullet\">-\u003C/span> \u003Cspan class=\"hljs-attr\">name:\u003C/span> \u003Cspan class=\"hljs-string\">Generate\u003C/span> \u003Cspan class=\"hljs-string\">change\u003C/span> \u003Cspan class=\"hljs-string\">summary\u003C/span>\n      \u003Cspan class=\"hljs-attr\">if:\u003C/span> \u003Cspan class=\"hljs-string\">steps.changed-files.outputs.any_changed\u003C/span> \u003Cspan class=\"hljs-string\">==\u003C/span> \u003Cspan class=\"hljs-string\">&#x27;true&#x27;\u003C/span>\n      \u003Cspan class=\"hljs-attr\">run:\u003C/span> \u003Cspan class=\"hljs-string\">|\n        cat &gt; change-summary.md &lt;&lt; &#x27;EOF&#x27;\n        # Documentation Change Summary\n\u003C/span>        \n        \u003Cspan class=\"hljs-comment\">## Files Modified\u003C/span>\n        \u003Cspan class=\"hljs-string\">${{\u003C/span> \u003Cspan class=\"hljs-string\">steps.changed-files.outputs.all_changed_files\u003C/span> \u003Cspan class=\"hljs-string\">}}\u003C/span>\n        \n        \u003Cspan class=\"hljs-comment\">## Analysis Results\u003C/span>\n        \u003Cspan class=\"hljs-string\">EOF\u003C/span>\n        \n        \u003Cspan class=\"hljs-comment\"># Append analysis results\u003C/span>\n        \u003Cspan class=\"hljs-string\">for\u003C/span> \u003Cspan class=\"hljs-string\">analysis_file\u003C/span> \u003Cspan class=\"hljs-string\">in\u003C/span> \u003Cspan class=\"hljs-string\">analysis-results/*.json;\u003C/span> \u003Cspan class=\"hljs-string\">do\u003C/span>\n          \u003Cspan class=\"hljs-string\">if\u003C/span> [ \u003Cspan class=\"hljs-string\">-f\u003C/span> \u003Cspan class=\"hljs-string\">&quot;$analysis_file&quot;\u003C/span> ]\u003Cspan class=\"hljs-string\">;\u003C/span> \u003Cspan class=\"hljs-string\">then\u003C/span>\n            \u003Cspan class=\"hljs-string\">echo\u003C/span> \u003Cspan class=\"hljs-string\">&quot;Processing $analysis_file&quot;\u003C/span>\n            \u003Cspan class=\"hljs-string\">python\u003C/span> \u003Cspan class=\"hljs-string\">&lt;&lt;\u003C/span> \u003Cspan class=\"hljs-string\">PYTHON\u003C/span>\n\u003Cspan class=\"hljs-string\">import\u003C/span> \u003Cspan class=\"hljs-string\">json\u003C/span>\n\u003Cspan class=\"hljs-string\">import\u003C/span> \u003Cspan class=\"hljs-string\">os\u003C/span>\n\n\u003Cspan class=\"hljs-string\">analysis_file\u003C/span> \u003Cspan class=\"hljs-string\">=\u003C/span> \u003Cspan class=\"hljs-string\">&quot;$analysis_file&quot;\u003C/span>\n\u003Cspan class=\"hljs-string\">if\u003C/span> \u003Cspan class=\"hljs-string\">os.path.exists(analysis_file):\u003C/span>\n    \u003Cspan class=\"hljs-string\">with\u003C/span> \u003Cspan class=\"hljs-string\">open(analysis_file,\u003C/span> \u003Cspan class=\"hljs-string\">&#x27;r&#x27;\u003C/span>\u003Cspan class=\"hljs-string\">)\u003C/span> \u003Cspan class=\"hljs-attr\">as f:\u003C/span>\n        \u003Cspan class=\"hljs-string\">data\u003C/span> \u003Cspan class=\"hljs-string\">=\u003C/span> \u003Cspan class=\"hljs-string\">json.load(f)\u003C/span>\n    \n    \u003Cspan class=\"hljs-string\">filename\u003C/span> \u003Cspan class=\"hljs-string\">=\u003C/span> \u003Cspan class=\"hljs-string\">os.path.basename(analysis_file).replace(&#x27;-analysis.json&#x27;,\u003C/span> \u003Cspan class=\"hljs-string\">&#x27;.md&#x27;\u003C/span>\u003Cspan class=\"hljs-string\">)\u003C/span>\n    \u003Cspan class=\"hljs-string\">classification\u003C/span> \u003Cspan class=\"hljs-string\">=\u003C/span> \u003Cspan class=\"hljs-string\">data[&#x27;change_classification&#x27;]\u003C/span>\n    \u003Cspan class=\"hljs-string\">changes\u003C/span> \u003Cspan class=\"hljs-string\">=\u003C/span> \u003Cspan class=\"hljs-string\">data[&#x27;structural_changes&#x27;]\u003C/span>\n    \n    \u003Cspan class=\"hljs-string\">print(f&quot;&quot;&quot;\u003C/span>\n\u003Cspan class=\"hljs-comment\">### {filename}\u003C/span>\n\n\u003Cspan class=\"hljs-string\">**Classification:**\u003C/span> {\u003Cspan class=\"hljs-string\">classification\u003C/span>[\u003Cspan class=\"hljs-string\">&#x27;significance&#x27;\u003C/span>]} {\u003Cspan class=\"hljs-string\">classification\u003C/span>[\u003Cspan class=\"hljs-string\">&#x27;type&#x27;\u003C/span>]} \u003Cspan class=\"hljs-string\">changes\u003C/span> \u003Cspan class=\"hljs-string\">with\u003C/span> {\u003Cspan class=\"hljs-string\">classification\u003C/span>[\u003Cspan class=\"hljs-string\">&#x27;impact&#x27;\u003C/span>]} \u003Cspan class=\"hljs-string\">impact\u003C/span>\n\n\u003Cspan class=\"hljs-string\">**Changes:**\u003C/span>\n\u003Cspan class=\"hljs-bullet\">-\u003C/span> \u003Cspan class=\"hljs-attr\">Lines added:\u003C/span> {\u003Cspan class=\"hljs-string\">data\u003C/span>[\u003Cspan class=\"hljs-string\">&#x27;line_diff&#x27;\u003C/span>][\u003Cspan class=\"hljs-string\">&#x27;additions&#x27;\u003C/span>]}\n\u003Cspan class=\"hljs-bullet\">-\u003C/span> \u003Cspan class=\"hljs-attr\">Lines deleted:\u003C/span> {\u003Cspan class=\"hljs-string\">data\u003C/span>[\u003Cspan class=\"hljs-string\">&#x27;line_diff&#x27;\u003C/span>][\u003Cspan class=\"hljs-string\">&#x27;deletions&#x27;\u003C/span>]}\n\u003Cspan class=\"hljs-bullet\">-\u003C/span> \u003Cspan class=\"hljs-attr\">Headings added:\u003C/span> {\u003Cspan class=\"hljs-string\">len(changes\u003C/span>[\u003Cspan class=\"hljs-string\">&#x27;headings&#x27;\u003C/span>][\u003Cspan class=\"hljs-string\">&#x27;added&#x27;\u003C/span>]\u003Cspan class=\"hljs-string\">)\u003C/span>}\n\u003Cspan class=\"hljs-bullet\">-\u003C/span> \u003Cspan class=\"hljs-attr\">Headings removed:\u003C/span> {\u003Cspan class=\"hljs-string\">len(changes\u003C/span>[\u003Cspan class=\"hljs-string\">&#x27;headings&#x27;\u003C/span>][\u003Cspan class=\"hljs-string\">&#x27;removed&#x27;\u003C/span>]\u003Cspan class=\"hljs-string\">)\u003C/span>}\n\u003Cspan class=\"hljs-bullet\">-\u003C/span> \u003Cspan class=\"hljs-attr\">Links added:\u003C/span> {\u003Cspan class=\"hljs-string\">len(changes\u003C/span>[\u003Cspan class=\"hljs-string\">&#x27;links&#x27;\u003C/span>][\u003Cspan class=\"hljs-string\">&#x27;added&#x27;\u003C/span>]\u003Cspan class=\"hljs-string\">)\u003C/span>}\n\u003Cspan class=\"hljs-bullet\">-\u003C/span> \u003Cspan class=\"hljs-attr\">Links removed:\u003C/span> {\u003Cspan class=\"hljs-string\">len(changes\u003C/span>[\u003Cspan class=\"hljs-string\">&#x27;links&#x27;\u003C/span>][\u003Cspan class=\"hljs-string\">&#x27;removed&#x27;\u003C/span>]\u003Cspan class=\"hljs-string\">)\u003C/span>}\n\n\u003Cspan class=\"hljs-string\">&quot;&quot;\u003C/span>\u003Cspan class=\"hljs-string\">&quot;)\nPYTHON\n          fi\n        done &gt;&gt; change-summary.md\n    \n    - name: Comment on Pull Request\n      if: github.event_name == &#x27;pull_request&#x27;\n      uses: actions/github-script@v6\n      with:\n        script: |\n          const fs = require(&#x27;fs&#x27;);\n          \n          if (fs.existsSync(&#x27;change-summary.md&#x27;)) {\n            const changeSummary = fs.readFileSync(&#x27;change-summary.md&#x27;, &#x27;utf8&#x27;);\n            \n            github.rest.issues.createComment({\n              issue_number: context.issue.number,\n              owner: context.repo.owner,\n              repo: context.repo.repo,\n              body: changeSummary\n            });\n          }\n    \n    - name: Send Slack notification for significant changes\n      if: steps.changed-files.outputs.any_changed == &#x27;true&#x27;\n      run: |\n        # Check if any changes are classified as &#x27;major&#x27; or &#x27;breaking&#x27;\n        significant_changes=false\n        \n        for analysis_file in analysis-results/*.json; do\n          if [ -f &quot;\u003C/span>\u003Cspan class=\"hljs-string\">$analysis_file&quot;\u003C/span> \u003Cspan class=\"hljs-string\">];\u003C/span> \u003Cspan class=\"hljs-string\">then\u003C/span>\n            \u003Cspan class=\"hljs-string\">significance=$(python\u003C/span> \u003Cspan class=\"hljs-string\">-c\u003C/span> \u003Cspan class=\"hljs-string\">&quot;\nimport json\nwith open(&#x27;$analysis_file&#x27;, &#x27;r&#x27;) as f:\n    data = json.load(f)\nprint(data[&#x27;change_classification&#x27;][&#x27;significance&#x27;])\n&quot;\u003C/span>\u003Cspan class=\"hljs-string\">)\u003C/span>\n            \n            \u003Cspan class=\"hljs-string\">if\u003C/span> [ \u003Cspan class=\"hljs-string\">&quot;$significance&quot;\u003C/span> \u003Cspan class=\"hljs-string\">=\u003C/span> \u003Cspan class=\"hljs-string\">&quot;major&quot;\u003C/span> ] \u003Cspan class=\"hljs-string\">||\u003C/span> [ \u003Cspan class=\"hljs-string\">&quot;$significance&quot;\u003C/span> \u003Cspan class=\"hljs-string\">=\u003C/span> \u003Cspan class=\"hljs-string\">&quot;breaking&quot;\u003C/span> ]\u003Cspan class=\"hljs-string\">;\u003C/span> \u003Cspan class=\"hljs-string\">then\u003C/span>\n              \u003Cspan class=\"hljs-string\">significant_changes=true\u003C/span>\n              \u003Cspan class=\"hljs-string\">break\u003C/span>\n            \u003Cspan class=\"hljs-string\">fi\u003C/span>\n          \u003Cspan class=\"hljs-string\">fi\u003C/span>\n        \u003Cspan class=\"hljs-string\">done\u003C/span>\n        \n        \u003Cspan class=\"hljs-string\">if\u003C/span> [ \u003Cspan class=\"hljs-string\">&quot;$significant_changes&quot;\u003C/span> \u003Cspan class=\"hljs-string\">=\u003C/span> \u003Cspan class=\"hljs-literal\">true\u003C/span> ]\u003Cspan class=\"hljs-string\">;\u003C/span> \u003Cspan class=\"hljs-string\">then\u003C/span>\n          \u003Cspan class=\"hljs-string\">curl\u003C/span> \u003Cspan class=\"hljs-string\">-X\u003C/span> \u003Cspan class=\"hljs-string\">POST\u003C/span> \u003Cspan class=\"hljs-string\">-H\u003C/span> \u003Cspan class=\"hljs-string\">&#x27;Content-type: application/json&#x27;\u003C/span> \u003Cspan class=\"hljs-string\">\\\u003C/span>\n            \u003Cspan class=\"hljs-string\">--data\u003C/span> \u003Cspan class=\"hljs-string\">&#x27;{\n              &quot;text&quot;: &quot;🚨 Significant documentation changes detected in repository $\u003Cspan class=\"hljs-template-variable\">{{ github.repository }}\u003C/span>&quot;,\n              &quot;blocks&quot;: [\n                {\n                  &quot;type&quot;: &quot;section&quot;,\n                  &quot;text&quot;: {\n                    &quot;type&quot;: &quot;mrkdwn&quot;,\n                    &quot;text&quot;: &quot;*Documentation Change Alert*\\n\\nSignificant changes detected in the documentation. Review required.&quot;\n                  }\n                },\n                {\n                  &quot;type&quot;: &quot;section&quot;,\n                  &quot;fields&quot;: [\n                    {\n                      &quot;type&quot;: &quot;mrkdwn&quot;,\n                      &quot;text&quot;: &quot;*Repository:*\\n$\u003Cspan class=\"hljs-template-variable\">{{ github.repository }}\u003C/span>&quot;\n                    },\n                    {\n                      &quot;type&quot;: &quot;mrkdwn&quot;, \n                      &quot;text&quot;: &quot;*Branch:*\\n$\u003Cspan class=\"hljs-template-variable\">{{ github.ref_name }}\u003C/span>&quot;\n                    },\n                    {\n                      &quot;type&quot;: &quot;mrkdwn&quot;,\n                      &quot;text&quot;: &quot;*Commit:*\\n$\u003Cspan class=\"hljs-template-variable\">{{ github.sha }}\u003C/span>&quot;\n                    },\n                    {\n                      &quot;type&quot;: &quot;mrkdwn&quot;,\n                      &quot;text&quot;: &quot;*Author:*\\n$\u003Cspan class=\"hljs-template-variable\">{{ github.actor }}\u003C/span>&quot;\n                    }\n                  ]\n                }\n              ]\n            }&#x27;\u003C/span> \u003Cspan class=\"hljs-string\">\\\u003C/span>\n            \u003Cspan class=\"hljs-string\">${{\u003C/span> \u003Cspan class=\"hljs-string\">secrets.SLACK_WEBHOOK_URL\u003C/span> \u003Cspan class=\"hljs-string\">}}\u003C/span>\n        \u003Cspan class=\"hljs-string\">fi\u003C/span>\n    \n    \u003Cspan class=\"hljs-bullet\">-\u003C/span> \u003Cspan class=\"hljs-attr\">name:\u003C/span> \u003Cspan class=\"hljs-string\">Archive\u003C/span> \u003Cspan class=\"hljs-string\">analysis\u003C/span> \u003Cspan class=\"hljs-string\">results\u003C/span>\n      \u003Cspan class=\"hljs-attr\">if:\u003C/span> \u003Cspan class=\"hljs-string\">steps.changed-files.outputs.any_changed\u003C/span> \u003Cspan class=\"hljs-string\">==\u003C/span> \u003Cspan class=\"hljs-string\">&#x27;true&#x27;\u003C/span>\n      \u003Cspan class=\"hljs-attr\">uses:\u003C/span> \u003Cspan class=\"hljs-string\">actions/upload-artifact@v3\u003C/span>\n      \u003Cspan class=\"hljs-attr\">with:\u003C/span>\n        \u003Cspan class=\"hljs-attr\">name:\u003C/span> \u003Cspan class=\"hljs-string\">change-analysis-results\u003C/span>\n        \u003Cspan class=\"hljs-attr\">path:\u003C/span> \u003Cspan class=\"hljs-string\">|\n          analysis-results/\n          change-summary.md\n\u003C/span>        \u003Cspan class=\"hljs-attr\">retention-days:\u003C/span> \u003Cspan class=\"hljs-number\">30\u003C/span>\n\u003C/code>\u003C/pre>\u003Ch2 id=\"collaborative-editing-workflows\">Collaborative Editing Workflows\u003C/h2>\n\u003Ch3 id=\"branch-based-documentation-development\">Branch-Based Documentation Development\u003C/h3>\n\u003Cp>Implement structured branching strategies for documentation:\u003C/p>\n\u003Cpre>\u003Ccode class=\"hljs language-bash\">\u003Cspan class=\"hljs-comment\"># Documentation branching strategy\u003C/span>\n\u003Cspan class=\"hljs-comment\"># Based on GitFlow with documentation-specific adaptations\u003C/span>\n\n\u003Cspan class=\"hljs-comment\"># Main branches\u003C/span>\nmain           \u003Cspan class=\"hljs-comment\"># Production-ready documentation\u003C/span>\ndevelop        \u003Cspan class=\"hljs-comment\"># Integration branch for new features\u003C/span>\nhotfix/*       \u003Cspan class=\"hljs-comment\"># Emergency fixes for production docs\u003C/span>\nrelease/*      \u003Cspan class=\"hljs-comment\"># Preparation branches for documentation releases\u003C/span>\n\n\u003Cspan class=\"hljs-comment\"># Feature branches for documentation work\u003C/span>\nfeature/api-v2-docs                    \u003Cspan class=\"hljs-comment\"># Major API documentation updates\u003C/span>\nfeature/user-guide-restructure         \u003Cspan class=\"hljs-comment\"># Structural changes to user guides\u003C/span>\nfeature/tutorial-series-authentication \u003Cspan class=\"hljs-comment\"># New tutorial content\u003C/span>\ndocs/fix-broken-links                  \u003Cspan class=\"hljs-comment\"># Documentation maintenance\u003C/span>\ncontent/mobile-sdk-examples            \u003Cspan class=\"hljs-comment\"># Content additions\u003C/span>\n\n\u003Cspan class=\"hljs-comment\"># Branch naming conventions for documentation\u003C/span>\ndocs/&lt;\u003Cspan class=\"hljs-built_in\">type\u003C/span>&gt;/&lt;description&gt;              \u003Cspan class=\"hljs-comment\"># General documentation work\u003C/span>\ncontent/&lt;area&gt;/&lt;feature&gt;               \u003Cspan class=\"hljs-comment\"># Content creation and updates\u003C/span>\nfix/&lt;issue-number&gt;-&lt;description&gt;       \u003Cspan class=\"hljs-comment\"># Bug fixes in documentation\u003C/span>\nupdate/&lt;component&gt;-&lt;version&gt;           \u003Cspan class=\"hljs-comment\"># Version-specific updates\u003C/span>\nreview/&lt;reviewer&gt;-&lt;document&gt;           \u003Cspan class=\"hljs-comment\"># Review-specific branches\u003C/span>\n\n\u003Cspan class=\"hljs-comment\"># Example workflow for adding new documentation\u003C/span>\ngit checkout develop\ngit pull origin develop\ngit checkout -b feature/webhook-integration-guide\n\n\u003Cspan class=\"hljs-comment\"># Work on documentation\u003C/span>\n\u003Cspan class=\"hljs-comment\"># ... edit files ...\u003C/span>\n\n\u003Cspan class=\"hljs-comment\"># Commit changes with descriptive messages\u003C/span>\ngit add docs/webhooks/\ngit commit -m \u003Cspan class=\"hljs-string\">&quot;docs: add comprehensive webhook integration guide\n\n- Include setup instructions for different platforms\n- Add code examples for Python, Node.js, and PHP\n- Document security best practices\n- Include troubleshooting section with common issues\n\nAddresses #789&quot;\u003C/span>\n\n\u003Cspan class=\"hljs-comment\"># Push feature branch\u003C/span>\ngit push origin feature/webhook-integration-guide\n\n\u003Cspan class=\"hljs-comment\"># Create pull request for review\u003C/span>\ngh \u003Cspan class=\"hljs-built_in\">pr\u003C/span> create --title \u003Cspan class=\"hljs-string\">&quot;Add webhook integration guide&quot;\u003C/span> \\\n             --body \u003Cspan class=\"hljs-string\">&quot;Comprehensive guide for webhook integration covering setup, security, and troubleshooting.&quot;\u003C/span> \\\n             --reviewer docs-team,api-team \\\n             --label documentation,review-needed\n\n\u003Cspan class=\"hljs-comment\"># After review and approval, merge to develop\u003C/span>\ngh \u003Cspan class=\"hljs-built_in\">pr\u003C/span> merge --squash --delete-branch\n\u003C/code>\u003C/pre>\u003Ch3 id=\"review-and-approval-workflows\">Review and Approval Workflows\u003C/h3>\n\u003Cp>Establish comprehensive review processes for documentation changes:\u003C/p>\n\u003Cpre>\u003Ccode class=\"hljs language-markdown\">&lt;!-- .github/pull\u003Cspan class=\"hljs-emphasis\">_request_\u003C/span>template.md --&gt;\n&lt;!-- Documentation Pull Request Template --&gt;\n\n\u003Cspan class=\"hljs-section\">## Documentation Change Summary\u003C/span>\n\n\u003Cspan class=\"hljs-section\">### Type of Change\u003C/span>\n\u003Cspan class=\"hljs-bullet\">-\u003C/span> [ ] New documentation\n\u003Cspan class=\"hljs-bullet\">-\u003C/span> [ ] Content update/revision\n\u003Cspan class=\"hljs-bullet\">-\u003C/span> [ ] Structural reorganization\n\u003Cspan class=\"hljs-bullet\">-\u003C/span> [ ] Bug fix (broken links, typos, incorrect information)\n\u003Cspan class=\"hljs-bullet\">-\u003C/span> [ ] Style/formatting improvements\n\n\u003Cspan class=\"hljs-section\">### Scope of Changes\u003C/span>\n\u003Cspan class=\"hljs-bullet\">-\u003C/span> [ ] API documentation\n\u003Cspan class=\"hljs-bullet\">-\u003C/span> [ ] User guides/tutorials\n\u003Cspan class=\"hljs-bullet\">-\u003C/span> [ ] Developer documentation\n\u003Cspan class=\"hljs-bullet\">-\u003C/span> [ ] Internal documentation\n\u003Cspan class=\"hljs-bullet\">-\u003C/span> [ ] Configuration/setup guides\n\n\u003Cspan class=\"hljs-section\">### Description\u003C/span>\n&lt;!-- Provide a clear description of the changes made --&gt;\n\n\u003Cspan class=\"hljs-section\">### Files Changed\u003C/span>\n&lt;!-- List the main files that were added, modified, or deleted --&gt;\n\n\u003Cspan class=\"hljs-section\">### Review Checklist\u003C/span>\n\n\u003Cspan class=\"hljs-section\">#### Content Review\u003C/span>\n\u003Cspan class=\"hljs-bullet\">-\u003C/span> [ ] Information is accurate and up-to-date\n\u003Cspan class=\"hljs-bullet\">-\u003C/span> [ ] Examples and code samples work correctly\n\u003Cspan class=\"hljs-bullet\">-\u003C/span> [ ] Links are functional and point to correct destinations\n\u003Cspan class=\"hljs-bullet\">-\u003C/span> [ ] Images and diagrams are clear and relevant\n\u003Cspan class=\"hljs-bullet\">-\u003C/span> [ ] Content follows the style guide\n\u003Cspan class=\"hljs-bullet\">-\u003C/span> [ ] Terminology is consistent throughout\n\n\u003Cspan class=\"hljs-section\">#### Technical Review\u003C/span>\n\u003Cspan class=\"hljs-bullet\">-\u003C/span> [ ] Code examples follow best practices\n\u003Cspan class=\"hljs-bullet\">-\u003C/span> [ ] API examples use current version syntax\n\u003Cspan class=\"hljs-bullet\">-\u003C/span> [ ] Configuration examples are valid\n\u003Cspan class=\"hljs-bullet\">-\u003C/span> [ ] Security considerations are addressed\n\u003Cspan class=\"hljs-bullet\">-\u003C/span> [ ] Performance implications are documented\n\n\u003Cspan class=\"hljs-section\">#### Editorial Review\u003C/span>\n\u003Cspan class=\"hljs-bullet\">-\u003C/span> [ ] Grammar and spelling are correct\n\u003Cspan class=\"hljs-bullet\">-\u003C/span> [ ] Writing is clear and concise\n\u003Cspan class=\"hljs-bullet\">-\u003C/span> [ ] Document structure is logical\n\u003Cspan class=\"hljs-bullet\">-\u003C/span> [ ] Headings and subheadings are descriptive\n\u003Cspan class=\"hljs-bullet\">-\u003C/span> [ ] Cross-references are appropriate\n\n\u003Cspan class=\"hljs-section\">#### Accessibility Review\u003C/span>\n\u003Cspan class=\"hljs-bullet\">-\u003C/span> [ ] Alt text provided for images\n\u003Cspan class=\"hljs-bullet\">-\u003C/span> [ ] Headings follow hierarchical structure (h1, h2, h3...)\n\u003Cspan class=\"hljs-bullet\">-\u003C/span> [ ] Links have descriptive text\n\u003Cspan class=\"hljs-bullet\">-\u003C/span> [ ] Tables have proper headers\n\u003Cspan class=\"hljs-bullet\">-\u003C/span> [ ] Color is not the only way to convey information\n\n\u003Cspan class=\"hljs-section\">### Testing Checklist\u003C/span>\n\u003Cspan class=\"hljs-bullet\">-\u003C/span> [ ] Documentation builds successfully\n\u003Cspan class=\"hljs-bullet\">-\u003C/span> [ ] All links have been validated\n\u003Cspan class=\"hljs-bullet\">-\u003C/span> [ ] Code examples have been tested\n\u003Cspan class=\"hljs-bullet\">-\u003C/span> [ ] Screenshots are current and accurate\n\u003Cspan class=\"hljs-bullet\">-\u003C/span> [ ] Search functionality works with new content\n\n\u003Cspan class=\"hljs-section\">### Impact Assessment\u003C/span>\n\u003Cspan class=\"hljs-bullet\">-\u003C/span> [ ] Changes are backward compatible\n\u003Cspan class=\"hljs-bullet\">-\u003C/span> [ ] No breaking changes to existing workflows\n\u003Cspan class=\"hljs-bullet\">-\u003C/span> [ ] Translation requirements identified (if applicable)\n\u003Cspan class=\"hljs-bullet\">-\u003C/span> [ ] SEO impact considered\n\u003Cspan class=\"hljs-bullet\">-\u003C/span> [ ] User impact is minimal/positive\n\n\u003Cspan class=\"hljs-section\">### Reviewer Instructions\u003C/span>\n&lt;!-- Specific areas where you want focused review --&gt;\n\n\u003Cspan class=\"hljs-section\">### Related Issues\u003C/span>\n&lt;!-- Link any related issues or feature requests --&gt;\nCloses #\nAddresses #\nRelated to #\n\n\u003Cspan class=\"hljs-section\">### Deployment Notes\u003C/span>\n&lt;!-- Any special considerations for deploying these changes --&gt;\n\n---\n\n\u003Cspan class=\"hljs-section\">### Reviewer Sign-off\u003C/span>\n\n\u003Cspan class=\"hljs-section\">#### Technical Review\u003C/span>\n\u003Cspan class=\"hljs-bullet\">-\u003C/span> [ ] Reviewed by: @reviewer-username\n\u003Cspan class=\"hljs-bullet\">-\u003C/span> [ ] Date: YYYY-MM-DD\n\u003Cspan class=\"hljs-bullet\">-\u003C/span> [ ] Comments addressed: [ ] Yes [ ] No [ ] N/A\n\n\u003Cspan class=\"hljs-section\">#### Editorial Review  \u003C/span>\n\u003Cspan class=\"hljs-bullet\">-\u003C/span> [ ] Reviewed by: @editor-username\n\u003Cspan class=\"hljs-bullet\">-\u003C/span> [ ] Date: YYYY-MM-DD\n\u003Cspan class=\"hljs-bullet\">-\u003C/span> [ ] Comments addressed: [ ] Yes [ ] No [ ] N/A\n\n\u003Cspan class=\"hljs-section\">#### Final Approval\u003C/span>\n\u003Cspan class=\"hljs-bullet\">-\u003C/span> [ ] Approved by: @approver-username\n\u003Cspan class=\"hljs-bullet\">-\u003C/span> [ ] Date: YYYY-MM-DD\n\u003Cspan class=\"hljs-bullet\">-\u003C/span> [ ] Ready for merge: [ ] Yes [ ] No\n\n\u003Cspan class=\"hljs-section\">### Post-Merge Tasks\u003C/span>\n\u003Cspan class=\"hljs-bullet\">-\u003C/span> [ ] Update related documentation\n\u003Cspan class=\"hljs-bullet\">-\u003C/span> [ ] Notify stakeholders of changes\n\u003Cspan class=\"hljs-bullet\">-\u003C/span> [ ] Update changelog\n\u003Cspan class=\"hljs-bullet\">-\u003C/span> [ ] Monitor for user feedback\n\u003C/code>\u003C/pre>\u003Ch2 id=\"document-history-and-analytics\">Document History and Analytics\u003C/h2>\n\u003Ch3 id=\"change-tracking-dashboards\">Change Tracking Dashboards\u003C/h3>\n\u003Cp>Create comprehensive tracking and reporting systems:\u003C/p>\n\u003Cpre>\u003Ccode class=\"hljs language-python\">\u003Cspan class=\"hljs-comment\">#!/usr/bin/env python3\u003C/span>\n\u003Cspan class=\"hljs-string\">&quot;&quot;&quot;\nDocumentation analytics and change tracking dashboard generator.\nAnalyzes Git history to create insights about documentation evolution.\n&quot;&quot;&quot;\u003C/span>\n\n\u003Cspan class=\"hljs-keyword\">import\u003C/span> git\n\u003Cspan class=\"hljs-keyword\">import\u003C/span> json\n\u003Cspan class=\"hljs-keyword\">import\u003C/span> pandas \u003Cspan class=\"hljs-keyword\">as\u003C/span> pd\n\u003Cspan class=\"hljs-keyword\">import\u003C/span> matplotlib.pyplot \u003Cspan class=\"hljs-keyword\">as\u003C/span> plt\n\u003Cspan class=\"hljs-keyword\">import\u003C/span> seaborn \u003Cspan class=\"hljs-keyword\">as\u003C/span> sns\n\u003Cspan class=\"hljs-keyword\">from\u003C/span> datetime \u003Cspan class=\"hljs-keyword\">import\u003C/span> datetime, timedelta\n\u003Cspan class=\"hljs-keyword\">from\u003C/span> pathlib \u003Cspan class=\"hljs-keyword\">import\u003C/span> Path\n\u003Cspan class=\"hljs-keyword\">from\u003C/span> collections \u003Cspan class=\"hljs-keyword\">import\u003C/span> defaultdict, Counter\n\u003Cspan class=\"hljs-keyword\">import\u003C/span> argparse\n\n\u003Cspan class=\"hljs-keyword\">class\u003C/span> \u003Cspan class=\"hljs-title class_\">DocumentationAnalytics\u003C/span>:\n    \u003Cspan class=\"hljs-string\">&quot;&quot;&quot;\n    Generates analytics and insights from documentation Git history.\n    &quot;&quot;&quot;\u003C/span>\n    \n    \u003Cspan class=\"hljs-keyword\">def\u003C/span> \u003Cspan class=\"hljs-title function_\">__init__\u003C/span>(\u003Cspan class=\"hljs-params\">self, repo_path: \u003Cspan class=\"hljs-built_in\">str\u003C/span>\u003C/span>):\n        self.repo = git.Repo(repo_path)\n        self.commits = \u003Cspan class=\"hljs-built_in\">list\u003C/span>(self.repo.iter_commits())\n        \n    \u003Cspan class=\"hljs-keyword\">def\u003C/span> \u003Cspan class=\"hljs-title function_\">analyze_activity_patterns\u003C/span>(\u003Cspan class=\"hljs-params\">self\u003C/span>) -&gt; \u003Cspan class=\"hljs-built_in\">dict\u003C/span>:\n        \u003Cspan class=\"hljs-string\">&quot;&quot;&quot;Analyze documentation activity patterns over time.&quot;&quot;&quot;\u003C/span>\n        activity_data = {\n            \u003Cspan class=\"hljs-string\">&#x27;commits_by_date&#x27;\u003C/span>: defaultdict(\u003Cspan class=\"hljs-built_in\">int\u003C/span>),\n            \u003Cspan class=\"hljs-string\">&#x27;commits_by_author&#x27;\u003C/span>: defaultdict(\u003Cspan class=\"hljs-built_in\">int\u003C/span>),\n            \u003Cspan class=\"hljs-string\">&#x27;commits_by_hour&#x27;\u003C/span>: defaultdict(\u003Cspan class=\"hljs-built_in\">int\u003C/span>),\n            \u003Cspan class=\"hljs-string\">&#x27;commits_by_day_of_week&#x27;\u003C/span>: defaultdict(\u003Cspan class=\"hljs-built_in\">int\u003C/span>),\n            \u003Cspan class=\"hljs-string\">&#x27;files_by_extension&#x27;\u003C/span>: defaultdict(\u003Cspan class=\"hljs-built_in\">int\u003C/span>)\n        }\n        \n        \u003Cspan class=\"hljs-keyword\">for\u003C/span> commit \u003Cspan class=\"hljs-keyword\">in\u003C/span> self.commits:\n            commit_date = datetime.fromtimestamp(commit.committed_date)\n            date_str = commit_date.strftime(\u003Cspan class=\"hljs-string\">&#x27;%Y-%m-%d&#x27;\u003C/span>)\n            \n            activity_data[\u003Cspan class=\"hljs-string\">&#x27;commits_by_date&#x27;\u003C/span>][date_str] += \u003Cspan class=\"hljs-number\">1\u003C/span>\n            activity_data[\u003Cspan class=\"hljs-string\">&#x27;commits_by_author&#x27;\u003C/span>][commit.author.name] += \u003Cspan class=\"hljs-number\">1\u003C/span>\n            activity_data[\u003Cspan class=\"hljs-string\">&#x27;commits_by_hour&#x27;\u003C/span>][commit_date.hour] += \u003Cspan class=\"hljs-number\">1\u003C/span>\n            activity_data[\u003Cspan class=\"hljs-string\">&#x27;commits_by_day_of_week&#x27;\u003C/span>][commit_date.strftime(\u003Cspan class=\"hljs-string\">&#x27;%A&#x27;\u003C/span>)] += \u003Cspan class=\"hljs-number\">1\u003C/span>\n            \n            \u003Cspan class=\"hljs-comment\"># Analyze file types in commit\u003C/span>\n            \u003Cspan class=\"hljs-keyword\">try\u003C/span>:\n                \u003Cspan class=\"hljs-keyword\">for\u003C/span> file_path \u003Cspan class=\"hljs-keyword\">in\u003C/span> commit.stats.files:\n                    \u003Cspan class=\"hljs-keyword\">if\u003C/span> file_path.endswith(\u003Cspan class=\"hljs-string\">&#x27;.md&#x27;\u003C/span>) \u003Cspan class=\"hljs-keyword\">or\u003C/span> file_path.endswith(\u003Cspan class=\"hljs-string\">&#x27;.mdx&#x27;\u003C/span>):\n                        activity_data[\u003Cspan class=\"hljs-string\">&#x27;files_by_extension&#x27;\u003C/span>][\u003Cspan class=\"hljs-string\">&#x27;.md&#x27;\u003C/span>] += \u003Cspan class=\"hljs-number\">1\u003C/span>\n                    \u003Cspan class=\"hljs-keyword\">elif\u003C/span> file_path.endswith(\u003Cspan class=\"hljs-string\">&#x27;.yml&#x27;\u003C/span>) \u003Cspan class=\"hljs-keyword\">or\u003C/span> file_path.endswith(\u003Cspan class=\"hljs-string\">&#x27;.yaml&#x27;\u003C/span>):\n                        activity_data[\u003Cspan class=\"hljs-string\">&#x27;files_by_extension&#x27;\u003C/span>][\u003Cspan class=\"hljs-string\">&#x27;.yaml&#x27;\u003C/span>] += \u003Cspan class=\"hljs-number\">1\u003C/span>\n                    \u003Cspan class=\"hljs-keyword\">elif\u003C/span> file_path.endswith(\u003Cspan class=\"hljs-string\">&#x27;.json&#x27;\u003C/span>):\n                        activity_data[\u003Cspan class=\"hljs-string\">&#x27;files_by_extension&#x27;\u003C/span>][\u003Cspan class=\"hljs-string\">&#x27;.json&#x27;\u003C/span>] += \u003Cspan class=\"hljs-number\">1\u003C/span>\n            \u003Cspan class=\"hljs-keyword\">except\u003C/span>:\n                \u003Cspan class=\"hljs-keyword\">continue\u003C/span>  \u003Cspan class=\"hljs-comment\"># Skip commits with issues accessing file stats\u003C/span>\n        \n        \u003Cspan class=\"hljs-keyword\">return\u003C/span> activity_data\n    \n    \u003Cspan class=\"hljs-keyword\">def\u003C/span> \u003Cspan class=\"hljs-title function_\">analyze_content_evolution\u003C/span>(\u003Cspan class=\"hljs-params\">self\u003C/span>) -&gt; \u003Cspan class=\"hljs-built_in\">dict\u003C/span>:\n        \u003Cspan class=\"hljs-string\">&quot;&quot;&quot;Analyze how documentation content has evolved over time.&quot;&quot;&quot;\u003C/span>\n        evolution_data = {\n            \u003Cspan class=\"hljs-string\">&#x27;document_growth&#x27;\u003C/span>: [],\n            \u003Cspan class=\"hljs-string\">&#x27;major_changes&#x27;\u003C/span>: [],\n            \u003Cspan class=\"hljs-string\">&#x27;contributor_patterns&#x27;\u003C/span>: defaultdict(\u003Cspan class=\"hljs-built_in\">list\u003C/span>)\n        }\n        \n        \u003Cspan class=\"hljs-comment\"># Track document size over time\u003C/span>\n        current_date = datetime.now()\n        \u003Cspan class=\"hljs-keyword\">for\u003C/span> days_back \u003Cspan class=\"hljs-keyword\">in\u003C/span> \u003Cspan class=\"hljs-built_in\">range\u003C/span>(\u003Cspan class=\"hljs-number\">0\u003C/span>, \u003Cspan class=\"hljs-number\">365\u003C/span>, \u003Cspan class=\"hljs-number\">7\u003C/span>):  \u003Cspan class=\"hljs-comment\"># Weekly samples for past year\u003C/span>\n            target_date = current_date - timedelta(days=days_back)\n            \n            \u003Cspan class=\"hljs-keyword\">try\u003C/span>:\n                \u003Cspan class=\"hljs-comment\"># Get commit closest to target date\u003C/span>\n                commits_before_date = [\n                    c \u003Cspan class=\"hljs-keyword\">for\u003C/span> c \u003Cspan class=\"hljs-keyword\">in\u003C/span> self.commits \n                    \u003Cspan class=\"hljs-keyword\">if\u003C/span> datetime.fromtimestamp(c.committed_date) &lt;= target_date\n                ]\n                \n                \u003Cspan class=\"hljs-keyword\">if\u003C/span> commits_before_date:\n                    closest_commit = commits_before_date[\u003Cspan class=\"hljs-number\">0\u003C/span>]\n                    \n                    \u003Cspan class=\"hljs-comment\"># Count markdown files at this point in history\u003C/span>\n                    md_files = \u003Cspan class=\"hljs-number\">0\u003C/span>\n                    total_size = \u003Cspan class=\"hljs-number\">0\u003C/span>\n                    \n                    \u003Cspan class=\"hljs-keyword\">for\u003C/span> item \u003Cspan class=\"hljs-keyword\">in\u003C/span> closest_commit.tree.traverse():\n                        \u003Cspan class=\"hljs-keyword\">if\u003C/span> item.path.endswith(\u003Cspan class=\"hljs-string\">&#x27;.md&#x27;\u003C/span>) \u003Cspan class=\"hljs-keyword\">and\u003C/span> item.\u003Cspan class=\"hljs-built_in\">type\u003C/span> == \u003Cspan class=\"hljs-string\">&#x27;blob&#x27;\u003C/span>:\n                            md_files += \u003Cspan class=\"hljs-number\">1\u003C/span>\n                            \u003Cspan class=\"hljs-keyword\">try\u003C/span>:\n                                total_size += item.data_stream.read().__len__()\n                            \u003Cspan class=\"hljs-keyword\">except\u003C/span>:\n                                \u003Cspan class=\"hljs-keyword\">pass\u003C/span>\n                    \n                    evolution_data[\u003Cspan class=\"hljs-string\">&#x27;document_growth&#x27;\u003C/span>].append({\n                        \u003Cspan class=\"hljs-string\">&#x27;date&#x27;\u003C/span>: target_date.strftime(\u003Cspan class=\"hljs-string\">&#x27;%Y-%m-%d&#x27;\u003C/span>),\n                        \u003Cspan class=\"hljs-string\">&#x27;file_count&#x27;\u003C/span>: md_files,\n                        \u003Cspan class=\"hljs-string\">&#x27;total_size&#x27;\u003C/span>: total_size\n                    })\n            \u003Cspan class=\"hljs-keyword\">except\u003C/span>:\n                \u003Cspan class=\"hljs-keyword\">continue\u003C/span>\n        \n        \u003Cspan class=\"hljs-comment\"># Identify major changes (commits with &gt;10 files changed or &gt;1000 lines)\u003C/span>\n        \u003Cspan class=\"hljs-keyword\">for\u003C/span> commit \u003Cspan class=\"hljs-keyword\">in\u003C/span> self.commits[:\u003Cspan class=\"hljs-number\">100\u003C/span>]:  \u003Cspan class=\"hljs-comment\"># Last 100 commits\u003C/span>\n            \u003Cspan class=\"hljs-keyword\">try\u003C/span>:\n                total_changes = \u003Cspan class=\"hljs-built_in\">sum\u003C/span>(commit.stats.files.values())\n                \u003Cspan class=\"hljs-keyword\">if\u003C/span> (\u003Cspan class=\"hljs-built_in\">len\u003C/span>(commit.stats.files) &gt; \u003Cspan class=\"hljs-number\">10\u003C/span> \u003Cspan class=\"hljs-keyword\">or\u003C/span> \n                    total_changes &gt; \u003Cspan class=\"hljs-number\">1000\u003C/span> \u003Cspan class=\"hljs-keyword\">or\u003C/span> \n                    \u003Cspan class=\"hljs-string\">&#x27;breaking&#x27;\u003C/span> \u003Cspan class=\"hljs-keyword\">in\u003C/span> commit.message.lower() \u003Cspan class=\"hljs-keyword\">or\u003C/span>\n                    \u003Cspan class=\"hljs-string\">&#x27;major&#x27;\u003C/span> \u003Cspan class=\"hljs-keyword\">in\u003C/span> commit.message.lower()):\n                    \n                    evolution_data[\u003Cspan class=\"hljs-string\">&#x27;major_changes&#x27;\u003C/span>].append({\n                        \u003Cspan class=\"hljs-string\">&#x27;commit&#x27;\u003C/span>: commit.hexsha[:\u003Cspan class=\"hljs-number\">8\u003C/span>],\n                        \u003Cspan class=\"hljs-string\">&#x27;date&#x27;\u003C/span>: datetime.fromtimestamp(commit.committed_date).strftime(\u003Cspan class=\"hljs-string\">&#x27;%Y-%m-%d&#x27;\u003C/span>),\n                        \u003Cspan class=\"hljs-string\">&#x27;author&#x27;\u003C/span>: commit.author.name,\n                        \u003Cspan class=\"hljs-string\">&#x27;message&#x27;\u003C/span>: commit.message.strip().split(\u003Cspan class=\"hljs-string\">&#x27;\\n&#x27;\u003C/span>)[\u003Cspan class=\"hljs-number\">0\u003C/span>][:\u003Cspan class=\"hljs-number\">100\u003C/span>],\n                        \u003Cspan class=\"hljs-string\">&#x27;files_changed&#x27;\u003C/span>: \u003Cspan class=\"hljs-built_in\">len\u003C/span>(commit.stats.files),\n                        \u003Cspan class=\"hljs-string\">&#x27;lines_changed&#x27;\u003C/span>: total_changes\n                    })\n            \u003Cspan class=\"hljs-keyword\">except\u003C/span>:\n                \u003Cspan class=\"hljs-keyword\">continue\u003C/span>\n        \n        \u003Cspan class=\"hljs-keyword\">return\u003C/span> evolution_data\n    \n    \u003Cspan class=\"hljs-keyword\">def\u003C/span> \u003Cspan class=\"hljs-title function_\">generate_contributor_insights\u003C/span>(\u003Cspan class=\"hljs-params\">self\u003C/span>) -&gt; \u003Cspan class=\"hljs-built_in\">dict\u003C/span>:\n        \u003Cspan class=\"hljs-string\">&quot;&quot;&quot;Generate insights about documentation contributors.&quot;&quot;&quot;\u003C/span>\n        contributors = defaultdict(\u003Cspan class=\"hljs-keyword\">lambda\u003C/span>: {\n            \u003Cspan class=\"hljs-string\">&#x27;commits&#x27;\u003C/span>: \u003Cspan class=\"hljs-number\">0\u003C/span>,\n            \u003Cspan class=\"hljs-string\">&#x27;files_modified&#x27;\u003C/span>: \u003Cspan class=\"hljs-built_in\">set\u003C/span>(),\n            \u003Cspan class=\"hljs-string\">&#x27;first_commit&#x27;\u003C/span>: \u003Cspan class=\"hljs-literal\">None\u003C/span>,\n            \u003Cspan class=\"hljs-string\">&#x27;last_commit&#x27;\u003C/span>: \u003Cspan class=\"hljs-literal\">None\u003C/span>,\n            \u003Cspan class=\"hljs-string\">&#x27;commit_messages&#x27;\u003C/span>: []\n        })\n        \n        \u003Cspan class=\"hljs-keyword\">for\u003C/span> commit \u003Cspan class=\"hljs-keyword\">in\u003C/span> self.commits:\n            author = commit.author.name\n            commit_date = datetime.fromtimestamp(commit.committed_date)\n            \n            contributors[author][\u003Cspan class=\"hljs-string\">&#x27;commits&#x27;\u003C/span>] += \u003Cspan class=\"hljs-number\">1\u003C/span>\n            contributors[author][\u003Cspan class=\"hljs-string\">&#x27;commit_messages&#x27;\u003C/span>].append(commit.message.strip())\n            \n            \u003Cspan class=\"hljs-keyword\">if\u003C/span> \u003Cspan class=\"hljs-keyword\">not\u003C/span> contributors[author][\u003Cspan class=\"hljs-string\">&#x27;first_commit&#x27;\u003C/span>]:\n                contributors[author][\u003Cspan class=\"hljs-string\">&#x27;first_commit&#x27;\u003C/span>] = commit_date\n            \u003Cspan class=\"hljs-keyword\">if\u003C/span> \u003Cspan class=\"hljs-keyword\">not\u003C/span> contributors[author][\u003Cspan class=\"hljs-string\">&#x27;last_commit&#x27;\u003C/span>] \u003Cspan class=\"hljs-keyword\">or\u003C/span> commit_date &gt; contributors[author][\u003Cspan class=\"hljs-string\">&#x27;last_commit&#x27;\u003C/span>]:\n                contributors[author][\u003Cspan class=\"hljs-string\">&#x27;last_commit&#x27;\u003C/span>] = commit_date\n            \n            \u003Cspan class=\"hljs-keyword\">try\u003C/span>:\n                \u003Cspan class=\"hljs-keyword\">for\u003C/span> file_path \u003Cspan class=\"hljs-keyword\">in\u003C/span> commit.stats.files:\n                    \u003Cspan class=\"hljs-keyword\">if\u003C/span> file_path.endswith(\u003Cspan class=\"hljs-string\">&#x27;.md&#x27;\u003C/span>):\n                        contributors[author][\u003Cspan class=\"hljs-string\">&#x27;files_modified&#x27;\u003C/span>].add(file_path)\n            \u003Cspan class=\"hljs-keyword\">except\u003C/span>:\n                \u003Cspan class=\"hljs-keyword\">continue\u003C/span>\n        \n        \u003Cspan class=\"hljs-comment\"># Convert to serializable format\u003C/span>\n        contributor_data = {}\n        \u003Cspan class=\"hljs-keyword\">for\u003C/span> author, data \u003Cspan class=\"hljs-keyword\">in\u003C/span> contributors.items():\n            contributor_data[author] = {\n                \u003Cspan class=\"hljs-string\">&#x27;commits&#x27;\u003C/span>: data[\u003Cspan class=\"hljs-string\">&#x27;commits&#x27;\u003C/span>],\n                \u003Cspan class=\"hljs-string\">&#x27;files_modified&#x27;\u003C/span>: \u003Cspan class=\"hljs-built_in\">len\u003C/span>(data[\u003Cspan class=\"hljs-string\">&#x27;files_modified&#x27;\u003C/span>]),\n                \u003Cspan class=\"hljs-string\">&#x27;files_list&#x27;\u003C/span>: \u003Cspan class=\"hljs-built_in\">list\u003C/span>(data[\u003Cspan class=\"hljs-string\">&#x27;files_modified&#x27;\u003C/span>])[:\u003Cspan class=\"hljs-number\">10\u003C/span>],  \u003Cspan class=\"hljs-comment\"># Top 10 files\u003C/span>\n                \u003Cspan class=\"hljs-string\">&#x27;first_commit&#x27;\u003C/span>: data[\u003Cspan class=\"hljs-string\">&#x27;first_commit&#x27;\u003C/span>].strftime(\u003Cspan class=\"hljs-string\">&#x27;%Y-%m-%d&#x27;\u003C/span>) \u003Cspan class=\"hljs-keyword\">if\u003C/span> data[\u003Cspan class=\"hljs-string\">&#x27;first_commit&#x27;\u003C/span>] \u003Cspan class=\"hljs-keyword\">else\u003C/span> \u003Cspan class=\"hljs-literal\">None\u003C/span>,\n                \u003Cspan class=\"hljs-string\">&#x27;last_commit&#x27;\u003C/span>: data[\u003Cspan class=\"hljs-string\">&#x27;last_commit&#x27;\u003C/span>].strftime(\u003Cspan class=\"hljs-string\">&#x27;%Y-%m-%d&#x27;\u003C/span>) \u003Cspan class=\"hljs-keyword\">if\u003C/span> data[\u003Cspan class=\"hljs-string\">&#x27;last_commit&#x27;\u003C/span>] \u003Cspan class=\"hljs-keyword\">else\u003C/span> \u003Cspan class=\"hljs-literal\">None\u003C/span>,\n                \u003Cspan class=\"hljs-string\">&#x27;activity_span_days&#x27;\u003C/span>: (data[\u003Cspan class=\"hljs-string\">&#x27;last_commit&#x27;\u003C/span>] - data[\u003Cspan class=\"hljs-string\">&#x27;first_commit&#x27;\u003C/span>]).days \u003Cspan class=\"hljs-keyword\">if\u003C/span> data[\u003Cspan class=\"hljs-string\">&#x27;first_commit&#x27;\u003C/span>] \u003Cspan class=\"hljs-keyword\">and\u003C/span> data[\u003Cspan class=\"hljs-string\">&#x27;last_commit&#x27;\u003C/span>] \u003Cspan class=\"hljs-keyword\">else\u003C/span> \u003Cspan class=\"hljs-number\">0\u003C/span>\n            }\n        \n        \u003Cspan class=\"hljs-keyword\">return\u003C/span> contributor_data\n    \n    \u003Cspan class=\"hljs-keyword\">def\u003C/span> \u003Cspan class=\"hljs-title function_\">generate_report\u003C/span>(\u003Cspan class=\"hljs-params\">self, output_path: \u003Cspan class=\"hljs-built_in\">str\u003C/span>\u003C/span>):\n        \u003Cspan class=\"hljs-string\">&quot;&quot;&quot;Generate comprehensive analytics report.&quot;&quot;&quot;\u003C/span>\n        \u003Cspan class=\"hljs-built_in\">print\u003C/span>(\u003Cspan class=\"hljs-string\">&quot;Analyzing documentation repository...&quot;\u003C/span>)\n        \n        activity_data = self.analyze_activity_patterns()\n        evolution_data = self.analyze_content_evolution()\n        contributor_data = self.generate_contributor_insights()\n        \n        report = {\n            \u003Cspan class=\"hljs-string\">&#x27;generated_at&#x27;\u003C/span>: datetime.now().isoformat(),\n            \u003Cspan class=\"hljs-string\">&#x27;repository_path&#x27;\u003C/span>: \u003Cspan class=\"hljs-built_in\">str\u003C/span>(self.repo.working_dir),\n            \u003Cspan class=\"hljs-string\">&#x27;total_commits&#x27;\u003C/span>: \u003Cspan class=\"hljs-built_in\">len\u003C/span>(self.commits),\n            \u003Cspan class=\"hljs-string\">&#x27;analysis_period&#x27;\u003C/span>: {\n                \u003Cspan class=\"hljs-string\">&#x27;first_commit&#x27;\u003C/span>: datetime.fromtimestamp(self.commits[-\u003Cspan class=\"hljs-number\">1\u003C/span>].committed_date).strftime(\u003Cspan class=\"hljs-string\">&#x27;%Y-%m-%d&#x27;\u003C/span>) \u003Cspan class=\"hljs-keyword\">if\u003C/span> self.commits \u003Cspan class=\"hljs-keyword\">else\u003C/span> \u003Cspan class=\"hljs-literal\">None\u003C/span>,\n                \u003Cspan class=\"hljs-string\">&#x27;last_commit&#x27;\u003C/span>: datetime.fromtimestamp(self.commits[\u003Cspan class=\"hljs-number\">0\u003C/span>].committed_date).strftime(\u003Cspan class=\"hljs-string\">&#x27;%Y-%m-%d&#x27;\u003C/span>) \u003Cspan class=\"hljs-keyword\">if\u003C/span> self.commits \u003Cspan class=\"hljs-keyword\">else\u003C/span> \u003Cspan class=\"hljs-literal\">None\u003C/span>\n            },\n            \u003Cspan class=\"hljs-string\">&#x27;activity_patterns&#x27;\u003C/span>: {\n                \u003Cspan class=\"hljs-string\">&#x27;most_active_authors&#x27;\u003C/span>: \u003Cspan class=\"hljs-built_in\">dict\u003C/span>(Counter(activity_data[\u003Cspan class=\"hljs-string\">&#x27;commits_by_author&#x27;\u003C/span>]).most_common(\u003Cspan class=\"hljs-number\">10\u003C/span>)),\n                \u003Cspan class=\"hljs-string\">&#x27;busiest_days&#x27;\u003C/span>: \u003Cspan class=\"hljs-built_in\">dict\u003C/span>(Counter(activity_data[\u003Cspan class=\"hljs-string\">&#x27;commits_by_day_of_week&#x27;\u003C/span>]).most_common()),\n                \u003Cspan class=\"hljs-string\">&#x27;peak_hours&#x27;\u003C/span>: \u003Cspan class=\"hljs-built_in\">dict\u003C/span>(Counter(activity_data[\u003Cspan class=\"hljs-string\">&#x27;commits_by_hour&#x27;\u003C/span>]).most_common(\u003Cspan class=\"hljs-number\">5\u003C/span>)),\n                \u003Cspan class=\"hljs-string\">&#x27;file_types&#x27;\u003C/span>: \u003Cspan class=\"hljs-built_in\">dict\u003C/span>(activity_data[\u003Cspan class=\"hljs-string\">&#x27;files_by_extension&#x27;\u003C/span>])\n            },\n            \u003Cspan class=\"hljs-string\">&#x27;content_evolution&#x27;\u003C/span>: evolution_data,\n            \u003Cspan class=\"hljs-string\">&#x27;contributors&#x27;\u003C/span>: contributor_data,\n            \u003Cspan class=\"hljs-string\">&#x27;insights&#x27;\u003C/span>: self._generate_insights(activity_data, evolution_data, contributor_data)\n        }\n        \n        \u003Cspan class=\"hljs-comment\"># Save report\u003C/span>\n        \u003Cspan class=\"hljs-keyword\">with\u003C/span> \u003Cspan class=\"hljs-built_in\">open\u003C/span>(output_path, \u003Cspan class=\"hljs-string\">&#x27;w&#x27;\u003C/span>) \u003Cspan class=\"hljs-keyword\">as\u003C/span> f:\n            json.dump(report, f, indent=\u003Cspan class=\"hljs-number\">2\u003C/span>)\n        \n        \u003Cspan class=\"hljs-built_in\">print\u003C/span>(\u003Cspan class=\"hljs-string\">f&quot;Analytics report saved to \u003Cspan class=\"hljs-subst\">{output_path}\u003C/span>&quot;\u003C/span>)\n        \n        \u003Cspan class=\"hljs-comment\"># Generate visualizations\u003C/span>\n        self._create_visualizations(report, output_path)\n    \n    \u003Cspan class=\"hljs-keyword\">def\u003C/span> \u003Cspan class=\"hljs-title function_\">_generate_insights\u003C/span>(\u003Cspan class=\"hljs-params\">self, activity_data, evolution_data, contributor_data\u003C/span>) -&gt; \u003Cspan class=\"hljs-built_in\">list\u003C/span>:\n        \u003Cspan class=\"hljs-string\">&quot;&quot;&quot;Generate actionable insights from the data.&quot;&quot;&quot;\u003C/span>\n        insights = []\n        \n        \u003Cspan class=\"hljs-comment\"># Contributor insights\u003C/span>\n        total_contributors = \u003Cspan class=\"hljs-built_in\">len\u003C/span>(contributor_data)\n        \u003Cspan class=\"hljs-keyword\">if\u003C/span> total_contributors &gt; \u003Cspan class=\"hljs-number\">1\u003C/span>:\n            insights.append(\u003Cspan class=\"hljs-string\">f&quot;Documentation is actively maintained by \u003Cspan class=\"hljs-subst\">{total_contributors}\u003C/span> contributors&quot;\u003C/span>)\n            \n            \u003Cspan class=\"hljs-comment\"># Find most active contributor\u003C/span>\n            most_active = \u003Cspan class=\"hljs-built_in\">max\u003C/span>(contributor_data.items(), key=\u003Cspan class=\"hljs-keyword\">lambda\u003C/span> x: x[\u003Cspan class=\"hljs-number\">1\u003C/span>][\u003Cspan class=\"hljs-string\">&#x27;commits&#x27;\u003C/span>])\n            insights.append(\u003Cspan class=\"hljs-string\">f&quot;Most active contributor: \u003Cspan class=\"hljs-subst\">{most_active[\u003Cspan class=\"hljs-number\">0\u003C/span>]}\u003C/span> with \u003Cspan class=\"hljs-subst\">{most_active[\u003Cspan class=\"hljs-number\">1\u003C/span>][\u003Cspan class=\"hljs-string\">&#x27;commits&#x27;\u003C/span>]}\u003C/span> commits&quot;\u003C/span>)\n        \n        \u003Cspan class=\"hljs-comment\"># Activity pattern insights\u003C/span>\n        \u003Cspan class=\"hljs-keyword\">if\u003C/span> activity_data[\u003Cspan class=\"hljs-string\">&#x27;commits_by_day_of_week&#x27;\u003C/span>]:\n            busiest_day = \u003Cspan class=\"hljs-built_in\">max\u003C/span>(activity_data[\u003Cspan class=\"hljs-string\">&#x27;commits_by_day_of_week&#x27;\u003C/span>].items(), key=\u003Cspan class=\"hljs-keyword\">lambda\u003C/span> x: x[\u003Cspan class=\"hljs-number\">1\u003C/span>])\n            insights.append(\u003Cspan class=\"hljs-string\">f&quot;Most documentation work happens on \u003Cspan class=\"hljs-subst\">{busiest_day[\u003Cspan class=\"hljs-number\">0\u003C/span>]}\u003C/span>&quot;\u003C/span>)\n        \n        \u003Cspan class=\"hljs-comment\"># Growth insights\u003C/span>\n        \u003Cspan class=\"hljs-keyword\">if\u003C/span> \u003Cspan class=\"hljs-built_in\">len\u003C/span>(evolution_data[\u003Cspan class=\"hljs-string\">&#x27;document_growth&#x27;\u003C/span>]) &gt;= \u003Cspan class=\"hljs-number\">2\u003C/span>:\n            recent_count = evolution_data[\u003Cspan class=\"hljs-string\">&#x27;document_growth&#x27;\u003C/span>][\u003Cspan class=\"hljs-number\">0\u003C/span>][\u003Cspan class=\"hljs-string\">&#x27;file_count&#x27;\u003C/span>]\n            older_count = evolution_data[\u003Cspan class=\"hljs-string\">&#x27;document_growth&#x27;\u003C/span>][-\u003Cspan class=\"hljs-number\">1\u003C/span>][\u003Cspan class=\"hljs-string\">&#x27;file_count&#x27;\u003C/span>]\n            \u003Cspan class=\"hljs-keyword\">if\u003C/span> recent_count &gt; older_count:\n                growth_rate = ((recent_count - older_count) / older_count) * \u003Cspan class=\"hljs-number\">100\u003C/span>\n                insights.append(\u003Cspan class=\"hljs-string\">f&quot;Documentation has grown by \u003Cspan class=\"hljs-subst\">{growth_rate:\u003Cspan class=\"hljs-number\">.1\u003C/span>f}\u003C/span>% in file count over the analysis period&quot;\u003C/span>)\n        \n        \u003Cspan class=\"hljs-comment\"># Major changes insight\u003C/span>\n        \u003Cspan class=\"hljs-keyword\">if\u003C/span> evolution_data[\u003Cspan class=\"hljs-string\">&#x27;major_changes&#x27;\u003C/span>]:\n            insights.append(\u003Cspan class=\"hljs-string\">f&quot;Identified \u003Cspan class=\"hljs-subst\">{\u003Cspan class=\"hljs-built_in\">len\u003C/span>(evolution_data[\u003Cspan class=\"hljs-string\">&#x27;major_changes&#x27;\u003C/span>])}\u003C/span> major documentation changes requiring special attention&quot;\u003C/span>)\n        \n        \u003Cspan class=\"hljs-keyword\">return\u003C/span> insights\n    \n    \u003Cspan class=\"hljs-keyword\">def\u003C/span> \u003Cspan class=\"hljs-title function_\">_create_visualizations\u003C/span>(\u003Cspan class=\"hljs-params\">self, report_data, output_path\u003C/span>):\n        \u003Cspan class=\"hljs-string\">&quot;&quot;&quot;Create visualization charts for the analytics report.&quot;&quot;&quot;\u003C/span>\n        \u003Cspan class=\"hljs-keyword\">try\u003C/span>:\n            \u003Cspan class=\"hljs-keyword\">import\u003C/span> matplotlib.pyplot \u003Cspan class=\"hljs-keyword\">as\u003C/span> plt\n            \u003Cspan class=\"hljs-keyword\">import\u003C/span> seaborn \u003Cspan class=\"hljs-keyword\">as\u003C/span> sns\n            \n            plt.style.use(\u003Cspan class=\"hljs-string\">&#x27;default&#x27;\u003C/span>)\n            fig, axes = plt.subplots(\u003Cspan class=\"hljs-number\">2\u003C/span>, \u003Cspan class=\"hljs-number\">2\u003C/span>, figsize=(\u003Cspan class=\"hljs-number\">15\u003C/span>, \u003Cspan class=\"hljs-number\">10\u003C/span>))\n            \n            \u003Cspan class=\"hljs-comment\"># Chart 1: Commits by author\u003C/span>\n            authors = \u003Cspan class=\"hljs-built_in\">list\u003C/span>(report_data[\u003Cspan class=\"hljs-string\">&#x27;activity_patterns&#x27;\u003C/span>][\u003Cspan class=\"hljs-string\">&#x27;most_active_authors&#x27;\u003C/span>].keys())[:\u003Cspan class=\"hljs-number\">10\u003C/span>]\n            commits = \u003Cspan class=\"hljs-built_in\">list\u003C/span>(report_data[\u003Cspan class=\"hljs-string\">&#x27;activity_patterns&#x27;\u003C/span>][\u003Cspan class=\"hljs-string\">&#x27;most_active_authors&#x27;\u003C/span>].values())[:\u003Cspan class=\"hljs-number\">10\u003C/span>]\n            \n            axes[\u003Cspan class=\"hljs-number\">0\u003C/span>, \u003Cspan class=\"hljs-number\">0\u003C/span>].bar(authors, commits)\n            axes[\u003Cspan class=\"hljs-number\">0\u003C/span>, \u003Cspan class=\"hljs-number\">0\u003C/span>].set_title(\u003Cspan class=\"hljs-string\">&#x27;Top Contributors by Commits&#x27;\u003C/span>)\n            axes[\u003Cspan class=\"hljs-number\">0\u003C/span>, \u003Cspan class=\"hljs-number\">0\u003C/span>].set_xlabel(\u003Cspan class=\"hljs-string\">&#x27;Author&#x27;\u003C/span>)\n            axes[\u003Cspan class=\"hljs-number\">0\u003C/span>, \u003Cspan class=\"hljs-number\">0\u003C/span>].set_ylabel(\u003Cspan class=\"hljs-string\">&#x27;Number of Commits&#x27;\u003C/span>)\n            axes[\u003Cspan class=\"hljs-number\">0\u003C/span>, \u003Cspan class=\"hljs-number\">0\u003C/span>].tick_params(axis=\u003Cspan class=\"hljs-string\">&#x27;x&#x27;\u003C/span>, rotation=\u003Cspan class=\"hljs-number\">45\u003C/span>)\n            \n            \u003Cspan class=\"hljs-comment\"># Chart 2: Activity by day of week\u003C/span>\n            days = \u003Cspan class=\"hljs-built_in\">list\u003C/span>(report_data[\u003Cspan class=\"hljs-string\">&#x27;activity_patterns&#x27;\u003C/span>][\u003Cspan class=\"hljs-string\">&#x27;busiest_days&#x27;\u003C/span>].keys())\n            day_commits = \u003Cspan class=\"hljs-built_in\">list\u003C/span>(report_data[\u003Cspan class=\"hljs-string\">&#x27;activity_patterns&#x27;\u003C/span>][\u003Cspan class=\"hljs-string\">&#x27;busiest_days&#x27;\u003C/span>].values())\n            \n            axes[\u003Cspan class=\"hljs-number\">0\u003C/span>, \u003Cspan class=\"hljs-number\">1\u003C/span>].bar(days, day_commits)\n            axes[\u003Cspan class=\"hljs-number\">0\u003C/span>, \u003Cspan class=\"hljs-number\">1\u003C/span>].set_title(\u003Cspan class=\"hljs-string\">&#x27;Documentation Activity by Day of Week&#x27;\u003C/span>)\n            axes[\u003Cspan class=\"hljs-number\">0\u003C/span>, \u003Cspan class=\"hljs-number\">1\u003C/span>].set_xlabel(\u003Cspan class=\"hljs-string\">&#x27;Day&#x27;\u003C/span>)\n            axes[\u003Cspan class=\"hljs-number\">0\u003C/span>, \u003Cspan class=\"hljs-number\">1\u003C/span>].set_ylabel(\u003Cspan class=\"hljs-string\">&#x27;Number of Commits&#x27;\u003C/span>)\n            axes[\u003Cspan class=\"hljs-number\">0\u003C/span>, \u003Cspan class=\"hljs-number\">1\u003C/span>].tick_params(axis=\u003Cspan class=\"hljs-string\">&#x27;x&#x27;\u003C/span>, rotation=\u003Cspan class=\"hljs-number\">45\u003C/span>)\n            \n            \u003Cspan class=\"hljs-comment\"># Chart 3: Document growth over time\u003C/span>\n            growth_data = report_data[\u003Cspan class=\"hljs-string\">&#x27;content_evolution&#x27;\u003C/span>][\u003Cspan class=\"hljs-string\">&#x27;document_growth&#x27;\u003C/span>]\n            \u003Cspan class=\"hljs-keyword\">if\u003C/span> growth_data:\n                dates = [item[\u003Cspan class=\"hljs-string\">&#x27;date&#x27;\u003C/span>] \u003Cspan class=\"hljs-keyword\">for\u003C/span> item \u003Cspan class=\"hljs-keyword\">in\u003C/span> growth_data]\n                file_counts = [item[\u003Cspan class=\"hljs-string\">&#x27;file_count&#x27;\u003C/span>] \u003Cspan class=\"hljs-keyword\">for\u003C/span> item \u003Cspan class=\"hljs-keyword\">in\u003C/span> growth_data]\n                \n                axes[\u003Cspan class=\"hljs-number\">1\u003C/span>, \u003Cspan class=\"hljs-number\">0\u003C/span>].plot(dates[-\u003Cspan class=\"hljs-number\">30\u003C/span>:], file_counts[-\u003Cspan class=\"hljs-number\">30\u003C/span>:], marker=\u003Cspan class=\"hljs-string\">&#x27;o&#x27;\u003C/span>)  \u003Cspan class=\"hljs-comment\"># Last 30 data points\u003C/span>\n                axes[\u003Cspan class=\"hljs-number\">1\u003C/span>, \u003Cspan class=\"hljs-number\">0\u003C/span>].set_title(\u003Cspan class=\"hljs-string\">&#x27;Documentation Growth Over Time&#x27;\u003C/span>)\n                axes[\u003Cspan class=\"hljs-number\">1\u003C/span>, \u003Cspan class=\"hljs-number\">0\u003C/span>].set_xlabel(\u003Cspan class=\"hljs-string\">&#x27;Date&#x27;\u003C/span>)\n                axes[\u003Cspan class=\"hljs-number\">1\u003C/span>, \u003Cspan class=\"hljs-number\">0\u003C/span>].set_ylabel(\u003Cspan class=\"hljs-string\">&#x27;Number of Files&#x27;\u003C/span>)\n                axes[\u003Cspan class=\"hljs-number\">1\u003C/span>, \u003Cspan class=\"hljs-number\">0\u003C/span>].tick_params(axis=\u003Cspan class=\"hljs-string\">&#x27;x&#x27;\u003C/span>, rotation=\u003Cspan class=\"hljs-number\">45\u003C/span>)\n            \n            \u003Cspan class=\"hljs-comment\"># Chart 4: File type distribution\u003C/span>\n            file_types = report_data[\u003Cspan class=\"hljs-string\">&#x27;activity_patterns&#x27;\u003C/span>][\u003Cspan class=\"hljs-string\">&#x27;file_types&#x27;\u003C/span>]\n            \u003Cspan class=\"hljs-keyword\">if\u003C/span> file_types:\n                types = \u003Cspan class=\"hljs-built_in\">list\u003C/span>(file_types.keys())\n                counts = \u003Cspan class=\"hljs-built_in\">list\u003C/span>(file_types.values())\n                \n                axes[\u003Cspan class=\"hljs-number\">1\u003C/span>, \u003Cspan class=\"hljs-number\">1\u003C/span>].pie(counts, labels=types, autopct=\u003Cspan class=\"hljs-string\">&#x27;%1.1f%%&#x27;\u003C/span>)\n                axes[\u003Cspan class=\"hljs-number\">1\u003C/span>, \u003Cspan class=\"hljs-number\">1\u003C/span>].set_title(\u003Cspan class=\"hljs-string\">&#x27;File Type Distribution&#x27;\u003C/span>)\n            \n            plt.tight_layout()\n            \n            \u003Cspan class=\"hljs-comment\"># Save visualization\u003C/span>\n            chart_path = output_path.replace(\u003Cspan class=\"hljs-string\">&#x27;.json&#x27;\u003C/span>, \u003Cspan class=\"hljs-string\">&#x27;_charts.png&#x27;\u003C/span>)\n            plt.savefig(chart_path, dpi=\u003Cspan class=\"hljs-number\">300\u003C/span>, bbox_inches=\u003Cspan class=\"hljs-string\">&#x27;tight&#x27;\u003C/span>)\n            \u003Cspan class=\"hljs-built_in\">print\u003C/span>(\u003Cspan class=\"hljs-string\">f&quot;Charts saved to \u003Cspan class=\"hljs-subst\">{chart_path}\u003C/span>&quot;\u003C/span>)\n            \n        \u003Cspan class=\"hljs-keyword\">except\u003C/span> ImportError:\n            \u003Cspan class=\"hljs-built_in\">print\u003C/span>(\u003Cspan class=\"hljs-string\">&quot;Matplotlib/seaborn not available, skipping visualizations&quot;\u003C/span>)\n        \u003Cspan class=\"hljs-keyword\">except\u003C/span> Exception \u003Cspan class=\"hljs-keyword\">as\u003C/span> e:\n            \u003Cspan class=\"hljs-built_in\">print\u003C/span>(\u003Cspan class=\"hljs-string\">f&quot;Error creating visualizations: \u003Cspan class=\"hljs-subst\">{e}\u003C/span>&quot;\u003C/span>)\n\n\u003Cspan class=\"hljs-keyword\">def\u003C/span> \u003Cspan class=\"hljs-title function_\">main\u003C/span>():\n    parser = argparse.ArgumentParser(description=\u003Cspan class=\"hljs-string\">&#x27;Generate documentation analytics report&#x27;\u003C/span>)\n    parser.add_argument(\u003Cspan class=\"hljs-string\">&#x27;repo_path&#x27;\u003C/span>, \u003Cspan class=\"hljs-built_in\">help\u003C/span>=\u003Cspan class=\"hljs-string\">&#x27;Path to the Git repository&#x27;\u003C/span>)\n    parser.add_argument(\u003Cspan class=\"hljs-string\">&#x27;--output&#x27;\u003C/span>, \u003Cspan class=\"hljs-string\">&#x27;-o&#x27;\u003C/span>, default=\u003Cspan class=\"hljs-string\">&#x27;documentation_analytics.json&#x27;\u003C/span>, \u003Cspan class=\"hljs-built_in\">help\u003C/span>=\u003Cspan class=\"hljs-string\">&#x27;Output file path&#x27;\u003C/span>)\n    \n    args = parser.parse_args()\n    \n    \u003Cspan class=\"hljs-keyword\">try\u003C/span>:\n        analyzer = DocumentationAnalytics(args.repo_path)\n        analyzer.generate_report(args.output)\n        \u003Cspan class=\"hljs-built_in\">print\u003C/span>(\u003Cspan class=\"hljs-string\">&quot;Documentation analytics completed successfully!&quot;\u003C/span>)\n        \n    \u003Cspan class=\"hljs-keyword\">except\u003C/span> Exception \u003Cspan class=\"hljs-keyword\">as\u003C/span> e:\n        \u003Cspan class=\"hljs-built_in\">print\u003C/span>(\u003Cspan class=\"hljs-string\">f&quot;Error generating analytics: \u003Cspan class=\"hljs-subst\">{e}\u003C/span>&quot;\u003C/span>)\n        \u003Cspan class=\"hljs-keyword\">return\u003C/span> \u003Cspan class=\"hljs-number\">1\u003C/span>\n    \n    \u003Cspan class=\"hljs-keyword\">return\u003C/span> \u003Cspan class=\"hljs-number\">0\u003C/span>\n\n\u003Cspan class=\"hljs-keyword\">if\u003C/span> __name__ == \u003Cspan class=\"hljs-string\">&#x27;__main__&#x27;\u003C/span>:\n    exit(main())\n\u003C/code>\u003C/pre>\u003Ch2 id=\"integration-with-documentation-workflows\">Integration with Documentation Workflows\u003C/h2>\n\u003Cp>Markdown document versioning integrates seamlessly with modern documentation practices. When combined with \u003Ca href=\"/blog/markdown-syntax-highlighting-complete-guide\">syntax highlighting capabilities\u003C/a>, versioning enables tracking of code example changes and ensures consistency across documentation updates while maintaining visual appeal.\u003C/p>\n\u003Cp>For comprehensive documentation management, versioning works effectively with \u003Ca href=\"/blog/markdown-metadata-yaml-frontmatter-complete-guide\">metadata and frontmatter\u003C/a> to create document lifecycle tracking systems that maintain version history alongside structured document properties and automated processing workflows.\u003C/p>\n\u003Cp>When managing complex documentation projects requiring both change tracking and collaborative features, versioning complements \u003Ca href=\"/blog/markdown-annotations-comments-complete-guide\">annotations and comments\u003C/a> by preserving editorial discussion history and decision-making context throughout the document evolution process.\u003C/p>\n\u003Ch2 id=\"advanced-version-control-strategies\">Advanced Version Control Strategies\u003C/h2>\n\u003Ch3 id=\"semantic-versioning-for-documentation\">Semantic Versioning for Documentation\u003C/h3>\n\u003Cp>Implement semantic versioning principles for documentation releases:\u003C/p>\n\u003Cpre>\u003Ccode class=\"hljs language-yaml\">\u003Cspan class=\"hljs-comment\"># Documentation version configuration\u003C/span>\n\u003Cspan class=\"hljs-comment\"># .doc-version.yml\u003C/span>\n\n\u003Cspan class=\"hljs-comment\"># Semantic versioning for documentation\u003C/span>\n\u003Cspan class=\"hljs-attr\">version:\u003C/span>\n  \u003Cspan class=\"hljs-attr\">major:\u003C/span> \u003Cspan class=\"hljs-number\">2\u003C/span>        \u003Cspan class=\"hljs-comment\"># Breaking changes, major restructuring\u003C/span>\n  \u003Cspan class=\"hljs-attr\">minor:\u003C/span> \u003Cspan class=\"hljs-number\">1\u003C/span>        \u003Cspan class=\"hljs-comment\"># New content, significant additions\u003C/span>\n  \u003Cspan class=\"hljs-attr\">patch:\u003C/span> \u003Cspan class=\"hljs-number\">3\u003C/span>        \u003Cspan class=\"hljs-comment\"># Bug fixes, minor corrections, typos\u003C/span>\n  \n\u003Cspan class=\"hljs-comment\"># Version metadata\u003C/span>\n\u003Cspan class=\"hljs-attr\">metadata:\u003C/span>\n  \u003Cspan class=\"hljs-attr\">release_name:\u003C/span> \u003Cspan class=\"hljs-string\">&quot;API v2.1 Documentation Update&quot;\u003C/span>\n  \u003Cspan class=\"hljs-attr\">release_date:\u003C/span> \u003Cspan class=\"hljs-string\">&quot;2025-09-13&quot;\u003C/span>\n  \u003Cspan class=\"hljs-attr\">changelog_path:\u003C/span> \u003Cspan class=\"hljs-string\">&quot;CHANGELOG.md&quot;\u003C/span>\n  \n\u003Cspan class=\"hljs-comment\"># Versioning rules\u003C/span>\n\u003Cspan class=\"hljs-attr\">versioning_rules:\u003C/span>\n  \u003Cspan class=\"hljs-attr\">major_triggers:\u003C/span>\n    \u003Cspan class=\"hljs-bullet\">-\u003C/span> \u003Cspan class=\"hljs-string\">api_breaking_changes\u003C/span>\n    \u003Cspan class=\"hljs-bullet\">-\u003C/span> \u003Cspan class=\"hljs-string\">documentation_restructure\u003C/span>\n    \u003Cspan class=\"hljs-bullet\">-\u003C/span> \u003Cspan class=\"hljs-string\">removal_of_content\u003C/span>\n    \u003Cspan class=\"hljs-bullet\">-\u003C/span> \u003Cspan class=\"hljs-string\">workflow_changes\u003C/span>\n  \n  \u003Cspan class=\"hljs-attr\">minor_triggers:\u003C/span>\n    \u003Cspan class=\"hljs-bullet\">-\u003C/span> \u003Cspan class=\"hljs-string\">new_features_documented\u003C/span>\n    \u003Cspan class=\"hljs-bullet\">-\u003C/span> \u003Cspan class=\"hljs-string\">new_tutorials_added\u003C/span>\n    \u003Cspan class=\"hljs-bullet\">-\u003C/span> \u003Cspan class=\"hljs-string\">expanded_examples\u003C/span>\n    \u003Cspan class=\"hljs-bullet\">-\u003C/span> \u003Cspan class=\"hljs-string\">additional_languages\u003C/span>\n  \n  \u003Cspan class=\"hljs-attr\">patch_triggers:\u003C/span>\n    \u003Cspan class=\"hljs-bullet\">-\u003C/span> \u003Cspan class=\"hljs-string\">typo_corrections\u003C/span>\n    \u003Cspan class=\"hljs-bullet\">-\u003C/span> \u003Cspan class=\"hljs-string\">link_fixes\u003C/span>\n    \u003Cspan class=\"hljs-bullet\">-\u003C/span> \u003Cspan class=\"hljs-string\">formatting_improvements\u003C/span>\n    \u003Cspan class=\"hljs-bullet\">-\u003C/span> \u003Cspan class=\"hljs-string\">clarifications\u003C/span>\n\n\u003Cspan class=\"hljs-comment\"># Automated version bumping rules\u003C/span>\n\u003Cspan class=\"hljs-attr\">automation:\u003C/span>\n  \u003Cspan class=\"hljs-attr\">auto_patch:\u003C/span> \u003Cspan class=\"hljs-literal\">true\u003C/span>              \u003Cspan class=\"hljs-comment\"># Automatically bump patch for minor fixes\u003C/span>\n  \u003Cspan class=\"hljs-attr\">require_approval_major:\u003C/span> \u003Cspan class=\"hljs-literal\">true\u003C/span>  \u003Cspan class=\"hljs-comment\"># Require manual approval for major versions\u003C/span>\n  \u003Cspan class=\"hljs-attr\">require_approval_minor:\u003C/span> \u003Cspan class=\"hljs-literal\">false\u003C/span> \u003Cspan class=\"hljs-comment\"># Allow automatic minor version bumps\u003C/span>\n  \n  \u003Cspan class=\"hljs-attr\">triggers:\u003C/span>\n    \u003Cspan class=\"hljs-attr\">patch:\u003C/span>\n      \u003Cspan class=\"hljs-bullet\">-\u003C/span> \u003Cspan class=\"hljs-string\">&quot;fix: &quot;\u003C/span>\n      \u003Cspan class=\"hljs-bullet\">-\u003C/span> \u003Cspan class=\"hljs-string\">&quot;docs: fix&quot;\u003C/span>\n      \u003Cspan class=\"hljs-bullet\">-\u003C/span> \u003Cspan class=\"hljs-string\">&quot;style: &quot;\u003C/span>\n    \u003Cspan class=\"hljs-attr\">minor:\u003C/span>\n      \u003Cspan class=\"hljs-bullet\">-\u003C/span> \u003Cspan class=\"hljs-string\">&quot;feat: &quot;\u003C/span>\n      \u003Cspan class=\"hljs-bullet\">-\u003C/span> \u003Cspan class=\"hljs-string\">&quot;docs: add&quot;\u003C/span>\n      \u003Cspan class=\"hljs-bullet\">-\u003C/span> \u003Cspan class=\"hljs-string\">&quot;docs: new&quot;\u003C/span>\n    \u003Cspan class=\"hljs-attr\">major:\u003C/span>\n      \u003Cspan class=\"hljs-bullet\">-\u003C/span> \u003Cspan class=\"hljs-string\">&quot;BREAKING CHANGE&quot;\u003C/span>\n      \u003Cspan class=\"hljs-bullet\">-\u003C/span> \u003Cspan class=\"hljs-string\">&quot;docs: restructure&quot;\u003C/span>\n\n\u003Cspan class=\"hljs-comment\"># Release artifacts\u003C/span>\n\u003Cspan class=\"hljs-attr\">artifacts:\u003C/span>\n  \u003Cspan class=\"hljs-attr\">generate_pdf:\u003C/span> \u003Cspan class=\"hljs-literal\">true\u003C/span>\n  \u003Cspan class=\"hljs-attr\">generate_epub:\u003C/span> \u003Cspan class=\"hljs-literal\">false\u003C/span>\n  \u003Cspan class=\"hljs-attr\">generate_zip:\u003C/span> \u003Cspan class=\"hljs-literal\">true\u003C/span>\n  \u003Cspan class=\"hljs-attr\">include_assets:\u003C/span> \u003Cspan class=\"hljs-literal\">true\u003C/span>\n\u003C/code>\u003C/pre>\u003Ch3 id=\"change-log-automation\">Change Log Automation\u003C/h3>\n\u003Cp>Create automated changelog generation from commit history:\u003C/p>\n\u003Cpre>\u003Ccode class=\"hljs language-python\">\u003Cspan class=\"hljs-comment\">#!/usr/bin/env python3\u003C/span>\n\u003Cspan class=\"hljs-string\">&quot;&quot;&quot;\nAutomated changelog generator for documentation projects.\nParses Git commit history to generate structured changelog files.\n&quot;&quot;&quot;\u003C/span>\n\n\u003Cspan class=\"hljs-keyword\">import\u003C/span> re\n\u003Cspan class=\"hljs-keyword\">import\u003C/span> git\n\u003Cspan class=\"hljs-keyword\">from\u003C/span> datetime \u003Cspan class=\"hljs-keyword\">import\u003C/span> datetime\n\u003Cspan class=\"hljs-keyword\">from\u003C/span> pathlib \u003Cspan class=\"hljs-keyword\">import\u003C/span> Path\n\u003Cspan class=\"hljs-keyword\">from\u003C/span> typing \u003Cspan class=\"hljs-keyword\">import\u003C/span> \u003Cspan class=\"hljs-type\">Dict\u003C/span>, \u003Cspan class=\"hljs-type\">List\u003C/span>, \u003Cspan class=\"hljs-type\">Tuple\u003C/span>\n\u003Cspan class=\"hljs-keyword\">import\u003C/span> argparse\n\n\u003Cspan class=\"hljs-keyword\">class\u003C/span> \u003Cspan class=\"hljs-title class_\">ChangelogGenerator\u003C/span>:\n    \u003Cspan class=\"hljs-string\">&quot;&quot;&quot;\n    Generates changelog from Git commit history with semantic understanding.\n    &quot;&quot;&quot;\u003C/span>\n    \n    \u003Cspan class=\"hljs-keyword\">def\u003C/span> \u003Cspan class=\"hljs-title function_\">__init__\u003C/span>(\u003Cspan class=\"hljs-params\">self, repo_path: \u003Cspan class=\"hljs-built_in\">str\u003C/span>\u003C/span>):\n        self.repo = git.Repo(repo_path)\n        \n        \u003Cspan class=\"hljs-comment\"># Commit message patterns\u003C/span>\n        self.patterns = {\n            \u003Cspan class=\"hljs-string\">&#x27;feat&#x27;\u003C/span>: \u003Cspan class=\"hljs-string\">r&#x27;^feat(?:\\([^)]+\\))?: (.+)&#x27;\u003C/span>,\n            \u003Cspan class=\"hljs-string\">&#x27;fix&#x27;\u003C/span>: \u003Cspan class=\"hljs-string\">r&#x27;^fix(?:\\([^)]+\\))?: (.+)&#x27;\u003C/span>,\n            \u003Cspan class=\"hljs-string\">&#x27;docs&#x27;\u003C/span>: \u003Cspan class=\"hljs-string\">r&#x27;^docs(?:\\([^)]+\\))?: (.+)&#x27;\u003C/span>,\n            \u003Cspan class=\"hljs-string\">&#x27;style&#x27;\u003C/span>: \u003Cspan class=\"hljs-string\">r&#x27;^style(?:\\([^)]+\\))?: (.+)&#x27;\u003C/span>,\n            \u003Cspan class=\"hljs-string\">&#x27;refactor&#x27;\u003C/span>: \u003Cspan class=\"hljs-string\">r&#x27;^refactor(?:\\([^)]+\\))?: (.+)&#x27;\u003C/span>,\n            \u003Cspan class=\"hljs-string\">&#x27;test&#x27;\u003C/span>: \u003Cspan class=\"hljs-string\">r&#x27;^test(?:\\([^)]+\\))?: (.+)&#x27;\u003C/span>,\n            \u003Cspan class=\"hljs-string\">&#x27;chore&#x27;\u003C/span>: \u003Cspan class=\"hljs-string\">r&#x27;^chore(?:\\([^)]+\\))?: (.+)&#x27;\u003C/span>,\n            \u003Cspan class=\"hljs-string\">&#x27;breaking&#x27;\u003C/span>: \u003Cspan class=\"hljs-string\">r&#x27;BREAKING CHANGE:?\\s*(.+)&#x27;\u003C/span>\n        }\n    \n    \u003Cspan class=\"hljs-keyword\">def\u003C/span> \u003Cspan class=\"hljs-title function_\">parse_commits_since_tag\u003C/span>(\u003Cspan class=\"hljs-params\">self, since_tag: \u003Cspan class=\"hljs-built_in\">str\u003C/span> = \u003Cspan class=\"hljs-literal\">None\u003C/span>\u003C/span>) -&gt; \u003Cspan class=\"hljs-type\">Dict\u003C/span>[\u003Cspan class=\"hljs-built_in\">str\u003C/span>, \u003Cspan class=\"hljs-type\">List\u003C/span>[\u003Cspan class=\"hljs-type\">Dict\u003C/span>]]:\n        \u003Cspan class=\"hljs-string\">&quot;&quot;&quot;Parse commits since the last tag or specified tag.&quot;&quot;&quot;\u003C/span>\n        commits_by_type = {\n            \u003Cspan class=\"hljs-string\">&#x27;breaking&#x27;\u003C/span>: [],\n            \u003Cspan class=\"hljs-string\">&#x27;features&#x27;\u003C/span>: [],\n            \u003Cspan class=\"hljs-string\">&#x27;fixes&#x27;\u003C/span>: [],\n            \u003Cspan class=\"hljs-string\">&#x27;docs&#x27;\u003C/span>: [],\n            \u003Cspan class=\"hljs-string\">&#x27;other&#x27;\u003C/span>: []\n        }\n        \n        \u003Cspan class=\"hljs-comment\"># Get commits since tag\u003C/span>\n        \u003Cspan class=\"hljs-keyword\">if\u003C/span> since_tag:\n            \u003Cspan class=\"hljs-keyword\">try\u003C/span>:\n                tag_commit = self.repo.commit(since_tag)\n                commits = \u003Cspan class=\"hljs-built_in\">list\u003C/span>(self.repo.iter_commits(\u003Cspan class=\"hljs-string\">f&#x27;\u003Cspan class=\"hljs-subst\">{since_tag}\u003C/span>..HEAD&#x27;\u003C/span>))\n            \u003Cspan class=\"hljs-keyword\">except\u003C/span>:\n                \u003Cspan class=\"hljs-built_in\">print\u003C/span>(\u003Cspan class=\"hljs-string\">f&quot;Warning: Tag \u003Cspan class=\"hljs-subst\">{since_tag}\u003C/span> not found, using all commits&quot;\u003C/span>)\n                commits = \u003Cspan class=\"hljs-built_in\">list\u003C/span>(self.repo.iter_commits())\n        \u003Cspan class=\"hljs-keyword\">else\u003C/span>:\n            \u003Cspan class=\"hljs-comment\"># Get commits since last tag\u003C/span>\n            \u003Cspan class=\"hljs-keyword\">try\u003C/span>:\n                tags = \u003Cspan class=\"hljs-built_in\">sorted\u003C/span>(self.repo.tags, key=\u003Cspan class=\"hljs-keyword\">lambda\u003C/span> t: t.commit.committed_date, reverse=\u003Cspan class=\"hljs-literal\">True\u003C/span>)\n                \u003Cspan class=\"hljs-keyword\">if\u003C/span> tags:\n                    last_tag = tags[\u003Cspan class=\"hljs-number\">0\u003C/span>]\n                    commits = \u003Cspan class=\"hljs-built_in\">list\u003C/span>(self.repo.iter_commits(\u003Cspan class=\"hljs-string\">f&#x27;\u003Cspan class=\"hljs-subst\">{last_tag}\u003C/span>..HEAD&#x27;\u003C/span>))\n                \u003Cspan class=\"hljs-keyword\">else\u003C/span>:\n                    commits = \u003Cspan class=\"hljs-built_in\">list\u003C/span>(self.repo.iter_commits())\n            \u003Cspan class=\"hljs-keyword\">except\u003C/span>:\n                commits = \u003Cspan class=\"hljs-built_in\">list\u003C/span>(self.repo.iter_commits())\n        \n        \u003Cspan class=\"hljs-comment\"># Parse each commit\u003C/span>\n        \u003Cspan class=\"hljs-keyword\">for\u003C/span> commit \u003Cspan class=\"hljs-keyword\">in\u003C/span> commits:\n            message = commit.message.strip()\n            commit_data = {\n                \u003Cspan class=\"hljs-string\">&#x27;hash&#x27;\u003C/span>: commit.hexsha[:\u003Cspan class=\"hljs-number\">8\u003C/span>],\n                \u003Cspan class=\"hljs-string\">&#x27;author&#x27;\u003C/span>: commit.author.name,\n                \u003Cspan class=\"hljs-string\">&#x27;date&#x27;\u003C/span>: datetime.fromtimestamp(commit.committed_date).strftime(\u003Cspan class=\"hljs-string\">&#x27;%Y-%m-%d&#x27;\u003C/span>),\n                \u003Cspan class=\"hljs-string\">&#x27;message&#x27;\u003C/span>: message,\n                \u003Cspan class=\"hljs-string\">&#x27;parsed_message&#x27;\u003C/span>: \u003Cspan class=\"hljs-literal\">None\u003C/span>\n            }\n            \n            \u003Cspan class=\"hljs-comment\"># Check for breaking changes first\u003C/span>\n            \u003Cspan class=\"hljs-keyword\">if\u003C/span> \u003Cspan class=\"hljs-string\">&#x27;BREAKING CHANGE&#x27;\u003C/span> \u003Cspan class=\"hljs-keyword\">in\u003C/span> message:\n                breaking_match = re.search(self.patterns[\u003Cspan class=\"hljs-string\">&#x27;breaking&#x27;\u003C/span>], message, re.MULTILINE)\n                \u003Cspan class=\"hljs-keyword\">if\u003C/span> breaking_match:\n                    commit_data[\u003Cspan class=\"hljs-string\">&#x27;parsed_message&#x27;\u003C/span>] = breaking_match.group(\u003Cspan class=\"hljs-number\">1\u003C/span>).strip()\n                \u003Cspan class=\"hljs-keyword\">else\u003C/span>:\n                    commit_data[\u003Cspan class=\"hljs-string\">&#x27;parsed_message&#x27;\u003C/span>] = message.split(\u003Cspan class=\"hljs-string\">&#x27;BREAKING CHANGE&#x27;\u003C/span>)[\u003Cspan class=\"hljs-number\">1\u003C/span>].strip()\n                commits_by_type[\u003Cspan class=\"hljs-string\">&#x27;breaking&#x27;\u003C/span>].append(commit_data)\n                \u003Cspan class=\"hljs-keyword\">continue\u003C/span>\n            \n            \u003Cspan class=\"hljs-comment\"># Check other patterns\u003C/span>\n            categorized = \u003Cspan class=\"hljs-literal\">False\u003C/span>\n            \u003Cspan class=\"hljs-keyword\">for\u003C/span> commit_type, pattern \u003Cspan class=\"hljs-keyword\">in\u003C/span> self.patterns.items():\n                \u003Cspan class=\"hljs-keyword\">if\u003C/span> commit_type == \u003Cspan class=\"hljs-string\">&#x27;breaking&#x27;\u003C/span>:\n                    \u003Cspan class=\"hljs-keyword\">continue\u003C/span>\n                    \n                \u003Cspan class=\"hljs-keyword\">match\u003C/span> = re.\u003Cspan class=\"hljs-keyword\">match\u003C/span>(pattern, message)\n                \u003Cspan class=\"hljs-keyword\">if\u003C/span> \u003Cspan class=\"hljs-keyword\">match\u003C/span>:\n                    commit_data[\u003Cspan class=\"hljs-string\">&#x27;parsed_message&#x27;\u003C/span>] = \u003Cspan class=\"hljs-keyword\">match\u003C/span>.group(\u003Cspan class=\"hljs-number\">1\u003C/span>).strip()\n                    \n                    \u003Cspan class=\"hljs-keyword\">if\u003C/span> commit_type \u003Cspan class=\"hljs-keyword\">in\u003C/span> [\u003Cspan class=\"hljs-string\">&#x27;feat&#x27;\u003C/span>]:\n                        commits_by_type[\u003Cspan class=\"hljs-string\">&#x27;features&#x27;\u003C/span>].append(commit_data)\n                    \u003Cspan class=\"hljs-keyword\">elif\u003C/span> commit_type \u003Cspan class=\"hljs-keyword\">in\u003C/span> [\u003Cspan class=\"hljs-string\">&#x27;fix&#x27;\u003C/span>]:\n                        commits_by_type[\u003Cspan class=\"hljs-string\">&#x27;fixes&#x27;\u003C/span>].append(commit_data)\n                    \u003Cspan class=\"hljs-keyword\">elif\u003C/span> commit_type \u003Cspan class=\"hljs-keyword\">in\u003C/span> [\u003Cspan class=\"hljs-string\">&#x27;docs&#x27;\u003C/span>]:\n                        commits_by_type[\u003Cspan class=\"hljs-string\">&#x27;docs&#x27;\u003C/span>].append(commit_data)\n                    \u003Cspan class=\"hljs-keyword\">else\u003C/span>:\n                        commits_by_type[\u003Cspan class=\"hljs-string\">&#x27;other&#x27;\u003C/span>].append(commit_data)\n                    \n                    categorized = \u003Cspan class=\"hljs-literal\">True\u003C/span>\n                    \u003Cspan class=\"hljs-keyword\">break\u003C/span>\n            \n            \u003Cspan class=\"hljs-comment\"># If no pattern matched, add to other\u003C/span>\n            \u003Cspan class=\"hljs-keyword\">if\u003C/span> \u003Cspan class=\"hljs-keyword\">not\u003C/span> categorized:\n                commit_data[\u003Cspan class=\"hljs-string\">&#x27;parsed_message&#x27;\u003C/span>] = message.split(\u003Cspan class=\"hljs-string\">&#x27;\\n&#x27;\u003C/span>)[\u003Cspan class=\"hljs-number\">0\u003C/span>]  \u003Cspan class=\"hljs-comment\"># First line only\u003C/span>\n                commits_by_type[\u003Cspan class=\"hljs-string\">&#x27;other&#x27;\u003C/span>].append(commit_data)\n        \n        \u003Cspan class=\"hljs-keyword\">return\u003C/span> commits_by_type\n    \n    \u003Cspan class=\"hljs-keyword\">def\u003C/span> \u003Cspan class=\"hljs-title function_\">get_version_info\u003C/span>(\u003Cspan class=\"hljs-params\">self\u003C/span>) -&gt; \u003Cspan class=\"hljs-type\">Dict\u003C/span>:\n        \u003Cspan class=\"hljs-string\">&quot;&quot;&quot;Extract version information from repository.&quot;&quot;&quot;\u003C/span>\n        version_info = {\n            \u003Cspan class=\"hljs-string\">&#x27;current_version&#x27;\u003C/span>: \u003Cspan class=\"hljs-string\">&#x27;Unreleased&#x27;\u003C/span>,\n            \u003Cspan class=\"hljs-string\">&#x27;previous_version&#x27;\u003C/span>: \u003Cspan class=\"hljs-literal\">None\u003C/span>,\n            \u003Cspan class=\"hljs-string\">&#x27;release_date&#x27;\u003C/span>: datetime.now().strftime(\u003Cspan class=\"hljs-string\">&#x27;%Y-%m-%d&#x27;\u003C/span>)\n        }\n        \n        \u003Cspan class=\"hljs-comment\"># Try to get version from tags\u003C/span>\n        \u003Cspan class=\"hljs-keyword\">try\u003C/span>:\n            tags = \u003Cspan class=\"hljs-built_in\">sorted\u003C/span>(self.repo.tags, key=\u003Cspan class=\"hljs-keyword\">lambda\u003C/span> t: t.commit.committed_date, reverse=\u003Cspan class=\"hljs-literal\">True\u003C/span>)\n            \u003Cspan class=\"hljs-keyword\">if\u003C/span> tags:\n                version_info[\u003Cspan class=\"hljs-string\">&#x27;previous_version&#x27;\u003C/span>] = \u003Cspan class=\"hljs-built_in\">str\u003C/span>(tags[\u003Cspan class=\"hljs-number\">0\u003C/span>])\n                \u003Cspan class=\"hljs-comment\"># Check if there&#x27;s a version file\u003C/span>\n                \u003Cspan class=\"hljs-keyword\">if\u003C/span> \u003Cspan class=\"hljs-built_in\">len\u003C/span>(tags) &gt; \u003Cspan class=\"hljs-number\">1\u003C/span>:\n                    version_info[\u003Cspan class=\"hljs-string\">&#x27;current_version&#x27;\u003C/span>] = \u003Cspan class=\"hljs-built_in\">str\u003C/span>(tags[\u003Cspan class=\"hljs-number\">0\u003C/span>])\n        \u003Cspan class=\"hljs-keyword\">except\u003C/span>:\n            \u003Cspan class=\"hljs-keyword\">pass\u003C/span>\n        \n        \u003Cspan class=\"hljs-comment\"># Try to read from version file\u003C/span>\n        version_files = [\u003Cspan class=\"hljs-string\">&#x27;.doc-version.yml&#x27;\u003C/span>, \u003Cspan class=\"hljs-string\">&#x27;VERSION&#x27;\u003C/span>, \u003Cspan class=\"hljs-string\">&#x27;version.txt&#x27;\u003C/span>]\n        \u003Cspan class=\"hljs-keyword\">for\u003C/span> version_file \u003Cspan class=\"hljs-keyword\">in\u003C/span> version_files:\n            version_path = Path(self.repo.working_dir) / version_file\n            \u003Cspan class=\"hljs-keyword\">if\u003C/span> version_path.exists():\n                \u003Cspan class=\"hljs-keyword\">try\u003C/span>:\n                    \u003Cspan class=\"hljs-keyword\">if\u003C/span> version_file.endswith(\u003Cspan class=\"hljs-string\">&#x27;.yml&#x27;\u003C/span>):\n                        \u003Cspan class=\"hljs-keyword\">import\u003C/span> yaml\n                        \u003Cspan class=\"hljs-keyword\">with\u003C/span> \u003Cspan class=\"hljs-built_in\">open\u003C/span>(version_path) \u003Cspan class=\"hljs-keyword\">as\u003C/span> f:\n                            version_data = yaml.safe_load(f)\n                        \u003Cspan class=\"hljs-keyword\">if\u003C/span> \u003Cspan class=\"hljs-string\">&#x27;version&#x27;\u003C/span> \u003Cspan class=\"hljs-keyword\">in\u003C/span> version_data:\n                            v = version_data[\u003Cspan class=\"hljs-string\">&#x27;version&#x27;\u003C/span>]\n                            version_info[\u003Cspan class=\"hljs-string\">&#x27;current_version&#x27;\u003C/span>] = \u003Cspan class=\"hljs-string\">f&quot;v\u003Cspan class=\"hljs-subst\">{v[\u003Cspan class=\"hljs-string\">&#x27;major&#x27;\u003C/span>]}\u003C/span>.\u003Cspan class=\"hljs-subst\">{v[\u003Cspan class=\"hljs-string\">&#x27;minor&#x27;\u003C/span>]}\u003C/span>.\u003Cspan class=\"hljs-subst\">{v[\u003Cspan class=\"hljs-string\">&#x27;patch&#x27;\u003C/span>]}\u003C/span>&quot;\u003C/span>\n                    \u003Cspan class=\"hljs-keyword\">else\u003C/span>:\n                        version_info[\u003Cspan class=\"hljs-string\">&#x27;current_version&#x27;\u003C/span>] = version_path.read_text().strip()\n                    \u003Cspan class=\"hljs-keyword\">break\u003C/span>\n                \u003Cspan class=\"hljs-keyword\">except\u003C/span>:\n                    \u003Cspan class=\"hljs-keyword\">continue\u003C/span>\n        \n        \u003Cspan class=\"hljs-keyword\">return\u003C/span> version_info\n    \n    \u003Cspan class=\"hljs-keyword\">def\u003C/span> \u003Cspan class=\"hljs-title function_\">generate_changelog_section\u003C/span>(\u003Cspan class=\"hljs-params\">self, commits_by_type: \u003Cspan class=\"hljs-type\">Dict\u003C/span>, version_info: \u003Cspan class=\"hljs-type\">Dict\u003C/span>\u003C/span>) -&gt; \u003Cspan class=\"hljs-built_in\">str\u003C/span>:\n        \u003Cspan class=\"hljs-string\">&quot;&quot;&quot;Generate a changelog section for the current version.&quot;&quot;&quot;\u003C/span>\n        changelog = []\n        \n        \u003Cspan class=\"hljs-comment\"># Header\u003C/span>\n        version = version_info[\u003Cspan class=\"hljs-string\">&#x27;current_version&#x27;\u003C/span>]\n        date = version_info[\u003Cspan class=\"hljs-string\">&#x27;release_date&#x27;\u003C/span>]\n        changelog.append(\u003Cspan class=\"hljs-string\">f&quot;## [\u003Cspan class=\"hljs-subst\">{version}\u003C/span>] - \u003Cspan class=\"hljs-subst\">{date}\u003C/span>&quot;\u003C/span>)\n        changelog.append(\u003Cspan class=\"hljs-string\">&quot;&quot;\u003C/span>)\n        \n        \u003Cspan class=\"hljs-comment\"># Breaking changes (most important)\u003C/span>\n        \u003Cspan class=\"hljs-keyword\">if\u003C/span> commits_by_type[\u003Cspan class=\"hljs-string\">&#x27;breaking&#x27;\u003C/span>]:\n            changelog.append(\u003Cspan class=\"hljs-string\">&quot;### ⚠️ BREAKING CHANGES&quot;\u003C/span>)\n            changelog.append(\u003Cspan class=\"hljs-string\">&quot;&quot;\u003C/span>)\n            \u003Cspan class=\"hljs-keyword\">for\u003C/span> commit \u003Cspan class=\"hljs-keyword\">in\u003C/span> commits_by_type[\u003Cspan class=\"hljs-string\">&#x27;breaking&#x27;\u003C/span>]:\n                changelog.append(\u003Cspan class=\"hljs-string\">f&quot;- **\u003Cspan class=\"hljs-subst\">{commit[\u003Cspan class=\"hljs-string\">&#x27;parsed_message&#x27;\u003C/span>]}\u003C/span>** (\u003Cspan class=\"hljs-subst\">{commit[\u003Cspan class=\"hljs-string\">&#x27;hash&#x27;\u003C/span>]}\u003C/span>)&quot;\u003C/span>)\n            changelog.append(\u003Cspan class=\"hljs-string\">&quot;&quot;\u003C/span>)\n        \n        \u003Cspan class=\"hljs-comment\"># New features\u003C/span>\n        \u003Cspan class=\"hljs-keyword\">if\u003C/span> commits_by_type[\u003Cspan class=\"hljs-string\">&#x27;features&#x27;\u003C/span>]:\n            changelog.append(\u003Cspan class=\"hljs-string\">&quot;### ✨ New Features&quot;\u003C/span>)\n            changelog.append(\u003Cspan class=\"hljs-string\">&quot;&quot;\u003C/span>)\n            \u003Cspan class=\"hljs-keyword\">for\u003C/span> commit \u003Cspan class=\"hljs-keyword\">in\u003C/span> commits_by_type[\u003Cspan class=\"hljs-string\">&#x27;features&#x27;\u003C/span>]:\n                changelog.append(\u003Cspan class=\"hljs-string\">f&quot;- \u003Cspan class=\"hljs-subst\">{commit[\u003Cspan class=\"hljs-string\">&#x27;parsed_message&#x27;\u003C/span>]}\u003C/span> (\u003Cspan class=\"hljs-subst\">{commit[\u003Cspan class=\"hljs-string\">&#x27;hash&#x27;\u003C/span>]}\u003C/span>)&quot;\u003C/span>)\n            changelog.append(\u003Cspan class=\"hljs-string\">&quot;&quot;\u003C/span>)\n        \n        \u003Cspan class=\"hljs-comment\"># Bug fixes\u003C/span>\n        \u003Cspan class=\"hljs-keyword\">if\u003C/span> commits_by_type[\u003Cspan class=\"hljs-string\">&#x27;fixes&#x27;\u003C/span>]:\n            changelog.append(\u003Cspan class=\"hljs-string\">&quot;### 🐛 Bug Fixes&quot;\u003C/span>)\n            changelog.append(\u003Cspan class=\"hljs-string\">&quot;&quot;\u003C/span>)\n            \u003Cspan class=\"hljs-keyword\">for\u003C/span> commit \u003Cspan class=\"hljs-keyword\">in\u003C/span> commits_by_type[\u003Cspan class=\"hljs-string\">&#x27;fixes&#x27;\u003C/span>]:\n                changelog.append(\u003Cspan class=\"hljs-string\">f&quot;- \u003Cspan class=\"hljs-subst\">{commit[\u003Cspan class=\"hljs-string\">&#x27;parsed_message&#x27;\u003C/span>]}\u003C/span> (\u003Cspan class=\"hljs-subst\">{commit[\u003Cspan class=\"hljs-string\">&#x27;hash&#x27;\u003C/span>]}\u003C/span>)&quot;\u003C/span>)\n            changelog.append(\u003Cspan class=\"hljs-string\">&quot;&quot;\u003C/span>)\n        \n        \u003Cspan class=\"hljs-comment\"># Documentation changes\u003C/span>\n        \u003Cspan class=\"hljs-keyword\">if\u003C/span> commits_by_type[\u003Cspan class=\"hljs-string\">&#x27;docs&#x27;\u003C/span>]:\n            changelog.append(\u003Cspan class=\"hljs-string\">&quot;### 📚 Documentation&quot;\u003C/span>)\n            changelog.append(\u003Cspan class=\"hljs-string\">&quot;&quot;\u003C/span>)\n            \u003Cspan class=\"hljs-keyword\">for\u003C/span> commit \u003Cspan class=\"hljs-keyword\">in\u003C/span> commits_by_type[\u003Cspan class=\"hljs-string\">&#x27;docs&#x27;\u003C/span>]:\n                changelog.append(\u003Cspan class=\"hljs-string\">f&quot;- \u003Cspan class=\"hljs-subst\">{commit[\u003Cspan class=\"hljs-string\">&#x27;parsed_message&#x27;\u003C/span>]}\u003C/span> (\u003Cspan class=\"hljs-subst\">{commit[\u003Cspan class=\"hljs-string\">&#x27;hash&#x27;\u003C/span>]}\u003C/span>)&quot;\u003C/span>)\n            changelog.append(\u003Cspan class=\"hljs-string\">&quot;&quot;\u003C/span>)\n        \n        \u003Cspan class=\"hljs-comment\"># Other changes\u003C/span>\n        \u003Cspan class=\"hljs-keyword\">if\u003C/span> commits_by_type[\u003Cspan class=\"hljs-string\">&#x27;other&#x27;\u003C/span>]:\n            changelog.append(\u003Cspan class=\"hljs-string\">&quot;### 🔧 Other Changes&quot;\u003C/span>)\n            changelog.append(\u003Cspan class=\"hljs-string\">&quot;&quot;\u003C/span>)\n            \u003Cspan class=\"hljs-keyword\">for\u003C/span> commit \u003Cspan class=\"hljs-keyword\">in\u003C/span> commits_by_type[\u003Cspan class=\"hljs-string\">&#x27;other&#x27;\u003C/span>]:\n                changelog.append(\u003Cspan class=\"hljs-string\">f&quot;- \u003Cspan class=\"hljs-subst\">{commit[\u003Cspan class=\"hljs-string\">&#x27;parsed_message&#x27;\u003C/span>]}\u003C/span> (\u003Cspan class=\"hljs-subst\">{commit[\u003Cspan class=\"hljs-string\">&#x27;hash&#x27;\u003C/span>]}\u003C/span>)&quot;\u003C/span>)\n            changelog.append(\u003Cspan class=\"hljs-string\">&quot;&quot;\u003C/span>)\n        \n        \u003Cspan class=\"hljs-keyword\">return\u003C/span> \u003Cspan class=\"hljs-string\">&#x27;\\n&#x27;\u003C/span>.join(changelog)\n    \n    \u003Cspan class=\"hljs-keyword\">def\u003C/span> \u003Cspan class=\"hljs-title function_\">update_changelog_file\u003C/span>(\u003Cspan class=\"hljs-params\">self, new_section: \u003Cspan class=\"hljs-built_in\">str\u003C/span>, changelog_path: \u003Cspan class=\"hljs-built_in\">str\u003C/span> = \u003Cspan class=\"hljs-string\">&#x27;CHANGELOG.md&#x27;\u003C/span>\u003C/span>):\n        \u003Cspan class=\"hljs-string\">&quot;&quot;&quot;Update the changelog file with new section.&quot;&quot;&quot;\u003C/span>\n        changelog_file = Path(self.repo.working_dir) / changelog_path\n        \n        \u003Cspan class=\"hljs-keyword\">if\u003C/span> changelog_file.exists():\n            existing_content = changelog_file.read_text()\n            \n            \u003Cspan class=\"hljs-comment\"># Find insertion point (after the first header)\u003C/span>\n            lines = existing_content.split(\u003Cspan class=\"hljs-string\">&#x27;\\n&#x27;\u003C/span>)\n            insert_index = \u003Cspan class=\"hljs-number\">0\u003C/span>\n            \n            \u003Cspan class=\"hljs-comment\"># Skip the main header and any initial content\u003C/span>\n            \u003Cspan class=\"hljs-keyword\">for\u003C/span> i, line \u003Cspan class=\"hljs-keyword\">in\u003C/span> \u003Cspan class=\"hljs-built_in\">enumerate\u003C/span>(lines):\n                \u003Cspan class=\"hljs-keyword\">if\u003C/span> line.startswith(\u003Cspan class=\"hljs-string\">&#x27;## [&#x27;\u003C/span>) \u003Cspan class=\"hljs-keyword\">and\u003C/span> \u003Cspan class=\"hljs-string\">&#x27;Unreleased&#x27;\u003C/span> \u003Cspan class=\"hljs-keyword\">not\u003C/span> \u003Cspan class=\"hljs-keyword\">in\u003C/span> line:\n                    insert_index = i\n                    \u003Cspan class=\"hljs-keyword\">break\u003C/span>\n                \u003Cspan class=\"hljs-keyword\">elif\u003C/span> line.strip() == \u003Cspan class=\"hljs-string\">&#x27;&#x27;\u003C/span> \u003Cspan class=\"hljs-keyword\">and\u003C/span> i &gt; \u003Cspan class=\"hljs-number\">0\u003C/span>:\n                    insert_index = i + \u003Cspan class=\"hljs-number\">1\u003C/span>\n            \n            \u003Cspan class=\"hljs-comment\"># Insert new section\u003C/span>\n            lines.insert(insert_index, new_section)\n            updated_content = \u003Cspan class=\"hljs-string\">&#x27;\\n&#x27;\u003C/span>.join(lines)\n        \u003Cspan class=\"hljs-keyword\">else\u003C/span>:\n            \u003Cspan class=\"hljs-comment\"># Create new changelog\u003C/span>\n            header = \u003Cspan class=\"hljs-string\">&quot;&quot;&quot;# Changelog\n\nAll notable changes to this documentation will be documented in this file.\n\nThe format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),\nand this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).\n\n&quot;&quot;&quot;\u003C/span>\n            updated_content = header + new_section\n        \n        changelog_file.write_text(updated_content)\n        \u003Cspan class=\"hljs-keyword\">return\u003C/span> changelog_file\n\n\u003Cspan class=\"hljs-keyword\">def\u003C/span> \u003Cspan class=\"hljs-title function_\">main\u003C/span>():\n    parser = argparse.ArgumentParser(description=\u003Cspan class=\"hljs-string\">&#x27;Generate changelog from Git commits&#x27;\u003C/span>)\n    parser.add_argument(\u003Cspan class=\"hljs-string\">&#x27;repo_path&#x27;\u003C/span>, nargs=\u003Cspan class=\"hljs-string\">&#x27;?&#x27;\u003C/span>, default=\u003Cspan class=\"hljs-string\">&#x27;.&#x27;\u003C/span>, \u003Cspan class=\"hljs-built_in\">help\u003C/span>=\u003Cspan class=\"hljs-string\">&#x27;Path to Git repository&#x27;\u003C/span>)\n    parser.add_argument(\u003Cspan class=\"hljs-string\">&#x27;--since-tag&#x27;\u003C/span>, \u003Cspan class=\"hljs-built_in\">help\u003C/span>=\u003Cspan class=\"hljs-string\">&#x27;Generate changelog since specific tag&#x27;\u003C/span>)\n    parser.add_argument(\u003Cspan class=\"hljs-string\">&#x27;--output&#x27;\u003C/span>, \u003Cspan class=\"hljs-string\">&#x27;-o&#x27;\u003C/span>, default=\u003Cspan class=\"hljs-string\">&#x27;CHANGELOG.md&#x27;\u003C/span>, \u003Cspan class=\"hljs-built_in\">help\u003C/span>=\u003Cspan class=\"hljs-string\">&#x27;Changelog file path&#x27;\u003C/span>)\n    parser.add_argument(\u003Cspan class=\"hljs-string\">&#x27;--dry-run&#x27;\u003C/span>, action=\u003Cspan class=\"hljs-string\">&#x27;store_true&#x27;\u003C/span>, \u003Cspan class=\"hljs-built_in\">help\u003C/span>=\u003Cspan class=\"hljs-string\">&#x27;Print changelog without writing file&#x27;\u003C/span>)\n    \n    args = parser.parse_args()\n    \n    \u003Cspan class=\"hljs-keyword\">try\u003C/span>:\n        generator = ChangelogGenerator(args.repo_path)\n        \n        \u003Cspan class=\"hljs-built_in\">print\u003C/span>(\u003Cspan class=\"hljs-string\">&quot;Analyzing commit history...&quot;\u003C/span>)\n        commits_by_type = generator.parse_commits_since_tag(args.since_tag)\n        \n        \u003Cspan class=\"hljs-comment\"># Check if there are any commits to process\u003C/span>\n        total_commits = \u003Cspan class=\"hljs-built_in\">sum\u003C/span>(\u003Cspan class=\"hljs-built_in\">len\u003C/span>(commits) \u003Cspan class=\"hljs-keyword\">for\u003C/span> commits \u003Cspan class=\"hljs-keyword\">in\u003C/span> commits_by_type.values())\n        \u003Cspan class=\"hljs-keyword\">if\u003C/span> total_commits == \u003Cspan class=\"hljs-number\">0\u003C/span>:\n            \u003Cspan class=\"hljs-built_in\">print\u003C/span>(\u003Cspan class=\"hljs-string\">&quot;No new commits found since last release.&quot;\u003C/span>)\n            \u003Cspan class=\"hljs-keyword\">return\u003C/span> \u003Cspan class=\"hljs-number\">0\u003C/span>\n        \n        \u003Cspan class=\"hljs-built_in\">print\u003C/span>(\u003Cspan class=\"hljs-string\">f&quot;Found \u003Cspan class=\"hljs-subst\">{total_commits}\u003C/span> commits to include in changelog:&quot;\u003C/span>)\n        \u003Cspan class=\"hljs-keyword\">for\u003C/span> category, commits \u003Cspan class=\"hljs-keyword\">in\u003C/span> commits_by_type.items():\n            \u003Cspan class=\"hljs-keyword\">if\u003C/span> commits:\n                \u003Cspan class=\"hljs-built_in\">print\u003C/span>(\u003Cspan class=\"hljs-string\">f&quot;  \u003Cspan class=\"hljs-subst\">{category}\u003C/span>: \u003Cspan class=\"hljs-subst\">{\u003Cspan class=\"hljs-built_in\">len\u003C/span>(commits)}\u003C/span> commits&quot;\u003C/span>)\n        \n        version_info = generator.get_version_info()\n        new_section = generator.generate_changelog_section(commits_by_type, version_info)\n        \n        \u003Cspan class=\"hljs-keyword\">if\u003C/span> args.dry_run:\n            \u003Cspan class=\"hljs-built_in\">print\u003C/span>(\u003Cspan class=\"hljs-string\">&quot;\\n--- Generated Changelog Section ---&quot;\u003C/span>)\n            \u003Cspan class=\"hljs-built_in\">print\u003C/span>(new_section)\n        \u003Cspan class=\"hljs-keyword\">else\u003C/span>:\n            changelog_file = generator.update_changelog_file(new_section, args.output)\n            \u003Cspan class=\"hljs-built_in\">print\u003C/span>(\u003Cspan class=\"hljs-string\">f&quot;Changelog updated: \u003Cspan class=\"hljs-subst\">{changelog_file}\u003C/span>&quot;\u003C/span>)\n        \n    \u003Cspan class=\"hljs-keyword\">except\u003C/span> Exception \u003Cspan class=\"hljs-keyword\">as\u003C/span> e:\n        \u003Cspan class=\"hljs-built_in\">print\u003C/span>(\u003Cspan class=\"hljs-string\">f&quot;Error generating changelog: \u003Cspan class=\"hljs-subst\">{e}\u003C/span>&quot;\u003C/span>)\n        \u003Cspan class=\"hljs-keyword\">return\u003C/span> \u003Cspan class=\"hljs-number\">1\u003C/span>\n    \n    \u003Cspan class=\"hljs-keyword\">return\u003C/span> \u003Cspan class=\"hljs-number\">0\u003C/span>\n\n\u003Cspan class=\"hljs-keyword\">if\u003C/span> __name__ == \u003Cspan class=\"hljs-string\">&#x27;__main__&#x27;\u003C/span>:\n    exit(main())\n\u003C/code>\u003C/pre>\u003Ch2 id=\"compliance-and-audit-requirements\">Compliance and Audit Requirements\u003C/h2>\n\u003Ch3 id=\"audit-trail-documentation\">Audit Trail Documentation\u003C/h3>\n\u003Cp>Implement comprehensive audit trails for regulated environments:\u003C/p>\n\u003Cpre>\u003Ccode class=\"hljs language-markdown\">\u003Cspan class=\"hljs-section\"># Documentation Audit Trail Specification\u003C/span>\n\n\u003Cspan class=\"hljs-section\">## Overview\u003C/span>\nThis specification defines the audit trail requirements for documentation changes \nin compliance with regulatory standards (SOX, GDPR, HIPAA, etc.).\n\n\u003Cspan class=\"hljs-section\">## Audit Trail Components\u003C/span>\n\n\u003Cspan class=\"hljs-section\">### 1. Change Tracking Matrix\u003C/span>\n\n| Element | Requirement | Implementation |\n|---------|-------------|----------------|\n| \u003Cspan class=\"hljs-strong\">**Who**\u003C/span> | User identity and role | Git commit author + code review approver |\n| \u003Cspan class=\"hljs-strong\">**What**\u003C/span> | Specific changes made | Git diff + semantic analysis |\n| \u003Cspan class=\"hljs-strong\">**When**\u003C/span> | Timestamp with timezone | Git commit timestamp (UTC) |\n| \u003Cspan class=\"hljs-strong\">**Where**\u003C/span> | Document/section affected | File paths + line numbers |\n| \u003Cspan class=\"hljs-strong\">**Why**\u003C/span> | Business justification | Commit message + linked issues |\n| \u003Cspan class=\"hljs-strong\">**How**\u003C/span> | Change approval process | PR review workflow + sign-off |\n\n\u003Cspan class=\"hljs-section\">### 2. Digital Signatures and Verification\u003C/span>\n\n\u003Cspan class=\"hljs-code\">```bash\n# GPG signing for audit compliance\ngit config --global user.signingkey [GPG_KEY_ID]\ngit config --global commit.gpgsign true\n\n# Signed commit example\ngit commit -S -m &quot;docs: update privacy policy compliance section\n\nUpdated data retention policies to align with GDPR Article 17\nrequirements for data subject deletion requests.\n\nRegulatory impact: HIGH\nLegal review: COMPLETED\nApproval: @legal-team, @compliance-officer\n\nSigned-off-by: Documentation Team &lt;docs@company.com&gt;\nReviewed-by: Legal Team &lt;legal@company.com&gt;&quot;\n\n# Verify signatures\ngit log --show-signature\ngit verify-commit HEAD\u003C/span>\n\u003C/code>\u003C/pre>\u003Ch3 id=\"3-change-approval-documentation\">3. Change Approval Documentation\u003C/h3>\n\u003Cpre>\u003Ccode class=\"hljs language-yaml\">\u003Cspan class=\"hljs-comment\"># .github/workflows/compliance-audit.yml\u003C/span>\n\u003Cspan class=\"hljs-comment\"># Automated compliance checking and audit trail generation\u003C/span>\n\n\u003Cspan class=\"hljs-attr\">name:\u003C/span> \u003Cspan class=\"hljs-string\">Documentation\u003C/span> \u003Cspan class=\"hljs-string\">Compliance\u003C/span> \u003Cspan class=\"hljs-string\">Audit\u003C/span>\n\n\u003Cspan class=\"hljs-attr\">on:\u003C/span>\n  \u003Cspan class=\"hljs-attr\">push:\u003C/span>\n    \u003Cspan class=\"hljs-attr\">branches:\u003C/span> [\u003Cspan class=\"hljs-string\">main\u003C/span>]\n    \u003Cspan class=\"hljs-attr\">paths:\u003C/span> [\u003Cspan class=\"hljs-string\">&#x27;docs/**/*.md&#x27;\u003C/span>, \u003Cspan class=\"hljs-string\">&#x27;policies/**/*.md&#x27;\u003C/span>]\n\n\u003Cspan class=\"hljs-attr\">jobs:\u003C/span>\n  \u003Cspan class=\"hljs-attr\">audit-trail:\u003C/span>\n    \u003Cspan class=\"hljs-attr\">runs-on:\u003C/span> \u003Cspan class=\"hljs-string\">ubuntu-latest\u003C/span>\n    \n    \u003Cspan class=\"hljs-attr\">steps:\u003C/span>\n    \u003Cspan class=\"hljs-bullet\">-\u003C/span> \u003Cspan class=\"hljs-attr\">name:\u003C/span> \u003Cspan class=\"hljs-string\">Checkout\u003C/span> \u003Cspan class=\"hljs-string\">with\u003C/span> \u003Cspan class=\"hljs-string\">full\u003C/span> \u003Cspan class=\"hljs-string\">history\u003C/span>\n      \u003Cspan class=\"hljs-attr\">uses:\u003C/span> \u003Cspan class=\"hljs-string\">actions/checkout@v3\u003C/span>\n      \u003Cspan class=\"hljs-attr\">with:\u003C/span>\n        \u003Cspan class=\"hljs-attr\">fetch-depth:\u003C/span> \u003Cspan class=\"hljs-number\">0\u003C/span>\n    \n    \u003Cspan class=\"hljs-bullet\">-\u003C/span> \u003Cspan class=\"hljs-attr\">name:\u003C/span> \u003Cspan class=\"hljs-string\">Verify\u003C/span> \u003Cspan class=\"hljs-string\">GPG\u003C/span> \u003Cspan class=\"hljs-string\">signatures\u003C/span>\n      \u003Cspan class=\"hljs-attr\">run:\u003C/span> \u003Cspan class=\"hljs-string\">|\n        # Verify last commit is signed\n        if ! git verify-commit HEAD; then\n          echo &quot;ERROR: Unsigned commit detected&quot;\n          exit 1\n        fi\n\u003C/span>        \n        \u003Cspan class=\"hljs-string\">echo\u003C/span> \u003Cspan class=\"hljs-string\">&quot;✓ Commit signature verified&quot;\u003C/span>\n    \n    \u003Cspan class=\"hljs-bullet\">-\u003C/span> \u003Cspan class=\"hljs-attr\">name:\u003C/span> \u003Cspan class=\"hljs-string\">Generate\u003C/span> \u003Cspan class=\"hljs-string\">audit\u003C/span> \u003Cspan class=\"hljs-string\">entry\u003C/span>\n      \u003Cspan class=\"hljs-attr\">run:\u003C/span> \u003Cspan class=\"hljs-string\">|\n        # Extract commit information\n        COMMIT_HASH=$(git rev-parse HEAD)\n        COMMIT_AUTHOR=$(git log -1 --format=&#x27;%aN &lt;%aE&gt;&#x27;)\n        COMMIT_DATE=$(git log -1 --format=&#x27;%aI&#x27;)\n        COMMIT_MESSAGE=$(git log -1 --format=&#x27;%B&#x27;)\n        FILES_CHANGED=$(git diff-tree --no-commit-id --name-only -r HEAD)\n\u003C/span>        \n        \u003Cspan class=\"hljs-comment\"># Generate audit entry\u003C/span>\n        \u003Cspan class=\"hljs-string\">cat\u003C/span> \u003Cspan class=\"hljs-string\">&gt;\u003C/span> \u003Cspan class=\"hljs-string\">audit-entry.json\u003C/span> \u003Cspan class=\"hljs-string\">&lt;&lt;\u003C/span> \u003Cspan class=\"hljs-string\">EOF\u003C/span>\n        {\n          \u003Cspan class=\"hljs-attr\">&quot;audit_id&quot;:\u003C/span> \u003Cspan class=\"hljs-string\">&quot;$(uuidgen)&quot;\u003C/span>,\n          \u003Cspan class=\"hljs-attr\">&quot;timestamp&quot;:\u003C/span> \u003Cspan class=\"hljs-string\">&quot;${COMMIT_DATE}&quot;\u003C/span>,\n          \u003Cspan class=\"hljs-attr\">&quot;commit_hash&quot;:\u003C/span> \u003Cspan class=\"hljs-string\">&quot;${COMMIT_HASH}&quot;\u003C/span>,\n          \u003Cspan class=\"hljs-attr\">&quot;author&quot;:\u003C/span> \u003Cspan class=\"hljs-string\">&quot;${COMMIT_AUTHOR}&quot;\u003C/span>,\n          \u003Cspan class=\"hljs-attr\">&quot;message&quot;:\u003C/span> \u003Cspan class=\"hljs-string\">&quot;${COMMIT_MESSAGE}&quot;\u003C/span>,\n          \u003Cspan class=\"hljs-attr\">&quot;files_affected&quot;:\u003C/span> [\u003Cspan class=\"hljs-string\">$(echo\u003C/span> \u003Cspan class=\"hljs-string\">&quot;$FILES_CHANGED&quot;\u003C/span> \u003Cspan class=\"hljs-string\">|\u003C/span> \u003Cspan class=\"hljs-string\">sed\u003C/span> \u003Cspan class=\"hljs-string\">&#x27;s/.*/&quot;&amp;&quot;/&#x27;\u003C/span> \u003Cspan class=\"hljs-string\">|\u003C/span> \u003Cspan class=\"hljs-string\">tr\u003C/span> \u003Cspan class=\"hljs-string\">&#x27;\\n&#x27;\u003C/span> \u003Cspan class=\"hljs-string\">&#x27;,&#x27;\u003C/span> \u003Cspan class=\"hljs-string\">|\u003C/span> \u003Cspan class=\"hljs-string\">sed\u003C/span> \u003Cspan class=\"hljs-string\">&#x27;s/,$//&#x27;\u003C/span>\u003Cspan class=\"hljs-string\">)\u003C/span>],\n          \u003Cspan class=\"hljs-attr\">&quot;verification&quot;:\u003C/span> {\n            \u003Cspan class=\"hljs-attr\">&quot;signature_valid&quot;:\u003C/span> \u003Cspan class=\"hljs-literal\">true\u003C/span>,\n            \u003Cspan class=\"hljs-attr\">&quot;approval_workflow&quot;:\u003C/span> \u003Cspan class=\"hljs-string\">&quot;github_pr_review&quot;\u003C/span>,\n            \u003Cspan class=\"hljs-attr\">&quot;reviewers&quot;:\u003C/span> []\n          },\n          \u003Cspan class=\"hljs-attr\">&quot;compliance_flags&quot;:\u003C/span> {\n            \u003Cspan class=\"hljs-attr\">&quot;requires_legal_review&quot;:\u003C/span> \u003Cspan class=\"hljs-literal\">false\u003C/span>,\n            \u003Cspan class=\"hljs-attr\">&quot;contains_sensitive_data&quot;:\u003C/span> \u003Cspan class=\"hljs-literal\">false\u003C/span>,\n            \u003Cspan class=\"hljs-attr\">&quot;regulatory_impact&quot;:\u003C/span> \u003Cspan class=\"hljs-string\">&quot;low&quot;\u003C/span>\n          }\n        }\n        \u003Cspan class=\"hljs-string\">EOF\u003C/span>\n    \n    \u003Cspan class=\"hljs-bullet\">-\u003C/span> \u003Cspan class=\"hljs-attr\">name:\u003C/span> \u003Cspan class=\"hljs-string\">Store\u003C/span> \u003Cspan class=\"hljs-string\">audit\u003C/span> \u003Cspan class=\"hljs-string\">trail\u003C/span>\n      \u003Cspan class=\"hljs-attr\">run:\u003C/span> \u003Cspan class=\"hljs-string\">|\n        # Add to audit log\n        mkdir -p audit-trail/$(date +%Y/%m)\n        mv audit-entry.json &quot;audit-trail/$(date +%Y/%m)/$(git rev-parse --short HEAD)-audit.json&quot;\n\u003C/span>        \n        \u003Cspan class=\"hljs-comment\"># Commit audit entry\u003C/span>\n        \u003Cspan class=\"hljs-string\">git\u003C/span> \u003Cspan class=\"hljs-string\">config\u003C/span> \u003Cspan class=\"hljs-string\">user.name\u003C/span> \u003Cspan class=\"hljs-string\">&quot;Audit Bot&quot;\u003C/span>\n        \u003Cspan class=\"hljs-string\">git\u003C/span> \u003Cspan class=\"hljs-string\">config\u003C/span> \u003Cspan class=\"hljs-string\">user.email\u003C/span> \u003Cspan class=\"hljs-string\">&quot;audit@company.com&quot;\u003C/span>\n        \u003Cspan class=\"hljs-string\">git\u003C/span> \u003Cspan class=\"hljs-string\">add\u003C/span> \u003Cspan class=\"hljs-string\">audit-trail/\u003C/span>\n        \u003Cspan class=\"hljs-string\">git\u003C/span> \u003Cspan class=\"hljs-string\">commit\u003C/span> \u003Cspan class=\"hljs-string\">-m\u003C/span> \u003Cspan class=\"hljs-string\">&quot;audit: add compliance trail for $(git rev-parse --short HEAD)&quot;\u003C/span>\n\u003C/code>\u003C/pre>\u003Ch2 id=\"performance-optimization-for-large-documentation-sets\">Performance Optimization for Large Documentation Sets\u003C/h2>\n\u003Ch3 id=\"efficient-repository-management\">Efficient Repository Management\u003C/h3>\n\u003Cp>Optimize Git repositories for large documentation projects:\u003C/p>\n\u003Cpre>\u003Ccode class=\"hljs language-bash\">\u003Cspan class=\"hljs-comment\"># Git optimization for large documentation repositories\u003C/span>\n\n\u003Cspan class=\"hljs-comment\"># Use Git LFS for large files\u003C/span>\n\u003Cspan class=\"hljs-built_in\">echo\u003C/span> \u003Cspan class=\"hljs-string\">&quot;*.pdf filter=lfs diff=lfs merge=lfs -text&quot;\u003C/span> &gt;&gt; .gitattributes\n\u003Cspan class=\"hljs-built_in\">echo\u003C/span> \u003Cspan class=\"hljs-string\">&quot;*.png filter=lfs diff=lfs merge=lfs -text&quot;\u003C/span> &gt;&gt; .gitattributes\n\u003Cspan class=\"hljs-built_in\">echo\u003C/span> \u003Cspan class=\"hljs-string\">&quot;*.jpg filter=lfs diff=lfs merge=lfs -text&quot;\u003C/span> &gt;&gt; .gitattributes\n\u003Cspan class=\"hljs-built_in\">echo\u003C/span> \u003Cspan class=\"hljs-string\">&quot;*.gif filter=lfs diff=lfs merge=lfs -text&quot;\u003C/span> &gt;&gt; .gitattributes\n\u003Cspan class=\"hljs-built_in\">echo\u003C/span> \u003Cspan class=\"hljs-string\">&quot;*.mp4 filter=lfs diff=lfs merge=lfs -text&quot;\u003C/span> &gt;&gt; .gitattributes\n\n\u003Cspan class=\"hljs-comment\"># Initialize Git LFS\u003C/span>\ngit lfs install\ngit lfs track \u003Cspan class=\"hljs-string\">&quot;*.pdf&quot;\u003C/span> \u003Cspan class=\"hljs-string\">&quot;*.png&quot;\u003C/span> \u003Cspan class=\"hljs-string\">&quot;*.jpg&quot;\u003C/span> \u003Cspan class=\"hljs-string\">&quot;*.gif&quot;\u003C/span> \u003Cspan class=\"hljs-string\">&quot;*.mp4&quot;\u003C/span>\n\n\u003Cspan class=\"hljs-comment\"># Optimize repository settings\u003C/span>\ngit config core.preloadindex \u003Cspan class=\"hljs-literal\">true\u003C/span>\ngit config core.fscache \u003Cspan class=\"hljs-literal\">true\u003C/span>\ngit config gc.auto 256\ngit config pack.threads 0  \u003Cspan class=\"hljs-comment\"># Use all available cores\u003C/span>\n\n\u003Cspan class=\"hljs-comment\"># Shallow clones for CI/CD\u003C/span>\n\u003Cspan class=\"hljs-comment\"># In CI environments, use shallow clones to reduce checkout time\u003C/span>\ngit \u003Cspan class=\"hljs-built_in\">clone\u003C/span> --depth 1 --single-branch --branch main https://github.com/company/docs.git\n\n\u003Cspan class=\"hljs-comment\"># Maintenance commands for large repositories\u003C/span>\n\u003Cspan class=\"hljs-comment\"># Run periodically to maintain performance\u003C/span>\ngit gc --aggressive --prune=now\ngit repack -a -d -f --depth=250 --window=250\n\n\u003Cspan class=\"hljs-comment\"># Split large repositories using Git subtree\u003C/span>\n\u003Cspan class=\"hljs-comment\"># For very large documentation sets, consider splitting by product/service\u003C/span>\ngit subtree \u003Cspan class=\"hljs-built_in\">split\u003C/span> --prefix=docs/api-v1 -b api-v1-docs\ngit subtree \u003Cspan class=\"hljs-built_in\">split\u003C/span> --prefix=docs/user-guides -b user-guide-docs\n\n\u003Cspan class=\"hljs-comment\"># Partial clone support (Git 2.19+)\u003C/span>\n\u003Cspan class=\"hljs-comment\"># Clone only needed files\u003C/span>\ngit \u003Cspan class=\"hljs-built_in\">clone\u003C/span> --filter=blob:none https://github.com/company/docs.git\ngit \u003Cspan class=\"hljs-built_in\">clone\u003C/span> --filter=tree:0 https://github.com/company/docs.git  \u003Cspan class=\"hljs-comment\"># Even more aggressive\u003C/span>\n\u003C/code>\u003C/pre>\u003Ch3 id=\"incremental-processing-strategies\">Incremental Processing Strategies\u003C/h3>\n\u003Cp>Implement efficient processing for large documentation changes:\u003C/p>\n\u003Cpre>\u003Ccode class=\"hljs language-python\">\u003Cspan class=\"hljs-comment\">#!/usr/bin/env python3\u003C/span>\n\u003Cspan class=\"hljs-string\">&quot;&quot;&quot;\nIncremental documentation processing for large repositories.\nOnly processes files that have changed since last run.\n&quot;&quot;&quot;\u003C/span>\n\n\u003Cspan class=\"hljs-keyword\">import\u003C/span> os\n\u003Cspan class=\"hljs-keyword\">import\u003C/span> json\n\u003Cspan class=\"hljs-keyword\">import\u003C/span> hashlib\n\u003Cspan class=\"hljs-keyword\">from\u003C/span> pathlib \u003Cspan class=\"hljs-keyword\">import\u003C/span> Path\n\u003Cspan class=\"hljs-keyword\">from\u003C/span> typing \u003Cspan class=\"hljs-keyword\">import\u003C/span> \u003Cspan class=\"hljs-type\">Dict\u003C/span>, \u003Cspan class=\"hljs-type\">List\u003C/span>, \u003Cspan class=\"hljs-type\">Set\u003C/span>\n\u003Cspan class=\"hljs-keyword\">from\u003C/span> datetime \u003Cspan class=\"hljs-keyword\">import\u003C/span> datetime\n\n\u003Cspan class=\"hljs-keyword\">class\u003C/span> \u003Cspan class=\"hljs-title class_\">IncrementalDocProcessor\u003C/span>:\n    \u003Cspan class=\"hljs-string\">&quot;&quot;&quot;\n    Processes only changed documentation files for efficient builds.\n    &quot;&quot;&quot;\u003C/span>\n    \n    \u003Cspan class=\"hljs-keyword\">def\u003C/span> \u003Cspan class=\"hljs-title function_\">__init__\u003C/span>(\u003Cspan class=\"hljs-params\">self, repo_path: \u003Cspan class=\"hljs-built_in\">str\u003C/span>, cache_file: \u003Cspan class=\"hljs-built_in\">str\u003C/span> = \u003Cspan class=\"hljs-string\">&#x27;.doc-cache.json&#x27;\u003C/span>\u003C/span>):\n        self.repo_path = Path(repo_path)\n        self.cache_file = self.repo_path / cache_file\n        self.file_cache = self._load_cache()\n        \n    \u003Cspan class=\"hljs-keyword\">def\u003C/span> \u003Cspan class=\"hljs-title function_\">_load_cache\u003C/span>(\u003Cspan class=\"hljs-params\">self\u003C/span>) -&gt; \u003Cspan class=\"hljs-type\">Dict\u003C/span>:\n        \u003Cspan class=\"hljs-string\">&quot;&quot;&quot;Load file hash cache from previous run.&quot;&quot;&quot;\u003C/span>\n        \u003Cspan class=\"hljs-keyword\">if\u003C/span> self.cache_file.exists():\n            \u003Cspan class=\"hljs-keyword\">try\u003C/span>:\n                \u003Cspan class=\"hljs-keyword\">with\u003C/span> \u003Cspan class=\"hljs-built_in\">open\u003C/span>(self.cache_file, \u003Cspan class=\"hljs-string\">&#x27;r&#x27;\u003C/span>) \u003Cspan class=\"hljs-keyword\">as\u003C/span> f:\n                    \u003Cspan class=\"hljs-keyword\">return\u003C/span> json.load(f)\n            \u003Cspan class=\"hljs-keyword\">except\u003C/span>:\n                \u003Cspan class=\"hljs-keyword\">pass\u003C/span>\n        \n        \u003Cspan class=\"hljs-keyword\">return\u003C/span> {\n            \u003Cspan class=\"hljs-string\">&#x27;files&#x27;\u003C/span>: {},\n            \u003Cspan class=\"hljs-string\">&#x27;last_run&#x27;\u003C/span>: \u003Cspan class=\"hljs-literal\">None\u003C/span>,\n            \u003Cspan class=\"hljs-string\">&#x27;stats&#x27;\u003C/span>: {\u003Cspan class=\"hljs-string\">&#x27;total_files&#x27;\u003C/span>: \u003Cspan class=\"hljs-number\">0\u003C/span>, \u003Cspan class=\"hljs-string\">&#x27;processed_files&#x27;\u003C/span>: \u003Cspan class=\"hljs-number\">0\u003C/span>}\n        }\n    \n    \u003Cspan class=\"hljs-keyword\">def\u003C/span> \u003Cspan class=\"hljs-title function_\">_save_cache\u003C/span>(\u003Cspan class=\"hljs-params\">self\u003C/span>):\n        \u003Cspan class=\"hljs-string\">&quot;&quot;&quot;Save current file state to cache.&quot;&quot;&quot;\u003C/span>\n        \u003Cspan class=\"hljs-keyword\">with\u003C/span> \u003Cspan class=\"hljs-built_in\">open\u003C/span>(self.cache_file, \u003Cspan class=\"hljs-string\">&#x27;w&#x27;\u003C/span>) \u003Cspan class=\"hljs-keyword\">as\u003C/span> f:\n            json.dump(self.file_cache, f, indent=\u003Cspan class=\"hljs-number\">2\u003C/span>)\n    \n    \u003Cspan class=\"hljs-keyword\">def\u003C/span> \u003Cspan class=\"hljs-title function_\">_calculate_file_hash\u003C/span>(\u003Cspan class=\"hljs-params\">self, file_path: Path\u003C/span>) -&gt; \u003Cspan class=\"hljs-built_in\">str\u003C/span>:\n        \u003Cspan class=\"hljs-string\">&quot;&quot;&quot;Calculate hash of file content and metadata.&quot;&quot;&quot;\u003C/span>\n        content_hash = hashlib.md5()\n        \n        \u003Cspan class=\"hljs-comment\"># Include file content\u003C/span>\n        \u003Cspan class=\"hljs-keyword\">with\u003C/span> \u003Cspan class=\"hljs-built_in\">open\u003C/span>(file_path, \u003Cspan class=\"hljs-string\">&#x27;rb&#x27;\u003C/span>) \u003Cspan class=\"hljs-keyword\">as\u003C/span> f:\n            content_hash.update(f.read())\n        \n        \u003Cspan class=\"hljs-comment\"># Include modification time\u003C/span>\n        mtime = \u003Cspan class=\"hljs-built_in\">str\u003C/span>(file_path.stat().st_mtime)\n        content_hash.update(mtime.encode())\n        \n        \u003Cspan class=\"hljs-keyword\">return\u003C/span> content_hash.hexdigest()\n    \n    \u003Cspan class=\"hljs-keyword\">def\u003C/span> \u003Cspan class=\"hljs-title function_\">detect_changed_files\u003C/span>(\u003Cspan class=\"hljs-params\">self, file_patterns: \u003Cspan class=\"hljs-type\">List\u003C/span>[\u003Cspan class=\"hljs-built_in\">str\u003C/span>] = \u003Cspan class=\"hljs-literal\">None\u003C/span>\u003C/span>) -&gt; \u003Cspan class=\"hljs-type\">Set\u003C/span>[Path]:\n        \u003Cspan class=\"hljs-string\">&quot;&quot;&quot;Detect files that have changed since last processing.&quot;&quot;&quot;\u003C/span>\n        \u003Cspan class=\"hljs-keyword\">if\u003C/span> file_patterns \u003Cspan class=\"hljs-keyword\">is\u003C/span> \u003Cspan class=\"hljs-literal\">None\u003C/span>:\n            file_patterns = [\u003Cspan class=\"hljs-string\">&#x27;**/*.md&#x27;\u003C/span>, \u003Cspan class=\"hljs-string\">&#x27;**/*.mdx&#x27;\u003C/span>]\n        \n        changed_files = \u003Cspan class=\"hljs-built_in\">set\u003C/span>()\n        current_files = \u003Cspan class=\"hljs-built_in\">set\u003C/span>()\n        \n        \u003Cspan class=\"hljs-comment\"># Find all matching files\u003C/span>\n        \u003Cspan class=\"hljs-keyword\">for\u003C/span> pattern \u003Cspan class=\"hljs-keyword\">in\u003C/span> file_patterns:\n            current_files.update(self.repo_path.glob(pattern))\n        \n        \u003Cspan class=\"hljs-comment\"># Check each file for changes\u003C/span>\n        \u003Cspan class=\"hljs-keyword\">for\u003C/span> file_path \u003Cspan class=\"hljs-keyword\">in\u003C/span> current_files:\n            rel_path = \u003Cspan class=\"hljs-built_in\">str\u003C/span>(file_path.relative_to(self.repo_path))\n            current_hash = self._calculate_file_hash(file_path)\n            \n            \u003Cspan class=\"hljs-comment\"># Compare with cached hash\u003C/span>\n            cached_hash = self.file_cache[\u003Cspan class=\"hljs-string\">&#x27;files&#x27;\u003C/span>].get(rel_path, {}).get(\u003Cspan class=\"hljs-string\">&#x27;hash&#x27;\u003C/span>)\n            \n            \u003Cspan class=\"hljs-keyword\">if\u003C/span> cached_hash != current_hash:\n                changed_files.add(file_path)\n                \n                \u003Cspan class=\"hljs-comment\"># Update cache\u003C/span>\n                self.file_cache[\u003Cspan class=\"hljs-string\">&#x27;files&#x27;\u003C/span>][rel_path] = {\n                    \u003Cspan class=\"hljs-string\">&#x27;hash&#x27;\u003C/span>: current_hash,\n                    \u003Cspan class=\"hljs-string\">&#x27;last_modified&#x27;\u003C/span>: datetime.now().isoformat(),\n                    \u003Cspan class=\"hljs-string\">&#x27;size&#x27;\u003C/span>: file_path.stat().st_size\n                }\n        \n        \u003Cspan class=\"hljs-comment\"># Detect deleted files\u003C/span>\n        cached_files = \u003Cspan class=\"hljs-built_in\">set\u003C/span>(self.file_cache[\u003Cspan class=\"hljs-string\">&#x27;files&#x27;\u003C/span>].keys())\n        current_rel_paths = {\u003Cspan class=\"hljs-built_in\">str\u003C/span>(f.relative_to(self.repo_path)) \u003Cspan class=\"hljs-keyword\">for\u003C/span> f \u003Cspan class=\"hljs-keyword\">in\u003C/span> current_files}\n        \n        \u003Cspan class=\"hljs-keyword\">for\u003C/span> deleted_file \u003Cspan class=\"hljs-keyword\">in\u003C/span> cached_files - current_rel_paths:\n            \u003Cspan class=\"hljs-built_in\">print\u003C/span>(\u003Cspan class=\"hljs-string\">f&quot;Detected deleted file: \u003Cspan class=\"hljs-subst\">{deleted_file}\u003C/span>&quot;\u003C/span>)\n            \u003Cspan class=\"hljs-keyword\">del\u003C/span> self.file_cache[\u003Cspan class=\"hljs-string\">&#x27;files&#x27;\u003C/span>][deleted_file]\n        \n        \u003Cspan class=\"hljs-keyword\">return\u003C/span> changed_files\n    \n    \u003Cspan class=\"hljs-keyword\">def\u003C/span> \u003Cspan class=\"hljs-title function_\">process_changes\u003C/span>(\u003Cspan class=\"hljs-params\">self, processors: \u003Cspan class=\"hljs-type\">Dict\u003C/span>[\u003Cspan class=\"hljs-built_in\">str\u003C/span>, \u003Cspan class=\"hljs-built_in\">callable\u003C/span>] = \u003Cspan class=\"hljs-literal\">None\u003C/span>\u003C/span>) -&gt; \u003Cspan class=\"hljs-type\">Dict\u003C/span>:\n        \u003Cspan class=\"hljs-string\">&quot;&quot;&quot;Process changed files with specified processors.&quot;&quot;&quot;\u003C/span>\n        \u003Cspan class=\"hljs-keyword\">if\u003C/span> processors \u003Cspan class=\"hljs-keyword\">is\u003C/span> \u003Cspan class=\"hljs-literal\">None\u003C/span>:\n            processors = {\n                \u003Cspan class=\"hljs-string\">&#x27;lint&#x27;\u003C/span>: self._default_lint_processor,\n                \u003Cspan class=\"hljs-string\">&#x27;build&#x27;\u003C/span>: self._default_build_processor\n            }\n        \n        changed_files = self.detect_changed_files()\n        \n        results = {\n            \u003Cspan class=\"hljs-string\">&#x27;total_files&#x27;\u003C/span>: \u003Cspan class=\"hljs-built_in\">len\u003C/span>(changed_files),\n            \u003Cspan class=\"hljs-string\">&#x27;processed&#x27;\u003C/span>: \u003Cspan class=\"hljs-number\">0\u003C/span>,\n            \u003Cspan class=\"hljs-string\">&#x27;errors&#x27;\u003C/span>: [],\n            \u003Cspan class=\"hljs-string\">&#x27;warnings&#x27;\u003C/span>: [],\n            \u003Cspan class=\"hljs-string\">&#x27;processing_time&#x27;\u003C/span>: datetime.now().isoformat()\n        }\n        \n        \u003Cspan class=\"hljs-keyword\">if\u003C/span> \u003Cspan class=\"hljs-keyword\">not\u003C/span> changed_files:\n            \u003Cspan class=\"hljs-built_in\">print\u003C/span>(\u003Cspan class=\"hljs-string\">&quot;No changed files detected. Skipping processing.&quot;\u003C/span>)\n            \u003Cspan class=\"hljs-keyword\">return\u003C/span> results\n        \n        \u003Cspan class=\"hljs-built_in\">print\u003C/span>(\u003Cspan class=\"hljs-string\">f&quot;Processing \u003Cspan class=\"hljs-subst\">{\u003Cspan class=\"hljs-built_in\">len\u003C/span>(changed_files)}\u003C/span> changed files...&quot;\u003C/span>)\n        \n        \u003Cspan class=\"hljs-keyword\">for\u003C/span> file_path \u003Cspan class=\"hljs-keyword\">in\u003C/span> changed_files:\n            \u003Cspan class=\"hljs-keyword\">try\u003C/span>:\n                \u003Cspan class=\"hljs-built_in\">print\u003C/span>(\u003Cspan class=\"hljs-string\">f&quot;Processing: \u003Cspan class=\"hljs-subst\">{file_path.relative_to(self.repo_path)}\u003C/span>&quot;\u003C/span>)\n                \n                \u003Cspan class=\"hljs-comment\"># Run each processor\u003C/span>\n                \u003Cspan class=\"hljs-keyword\">for\u003C/span> processor_name, processor_func \u003Cspan class=\"hljs-keyword\">in\u003C/span> processors.items():\n                    \u003Cspan class=\"hljs-keyword\">try\u003C/span>:\n                        processor_result = processor_func(file_path)\n                        \u003Cspan class=\"hljs-keyword\">if\u003C/span> processor_result.get(\u003Cspan class=\"hljs-string\">&#x27;errors&#x27;\u003C/span>):\n                            results[\u003Cspan class=\"hljs-string\">&#x27;errors&#x27;\u003C/span>].extend(processor_result[\u003Cspan class=\"hljs-string\">&#x27;errors&#x27;\u003C/span>])\n                        \u003Cspan class=\"hljs-keyword\">if\u003C/span> processor_result.get(\u003Cspan class=\"hljs-string\">&#x27;warnings&#x27;\u003C/span>):\n                            results[\u003Cspan class=\"hljs-string\">&#x27;warnings&#x27;\u003C/span>].extend(processor_result[\u003Cspan class=\"hljs-string\">&#x27;warnings&#x27;\u003C/span>])\n                    \u003Cspan class=\"hljs-keyword\">except\u003C/span> Exception \u003Cspan class=\"hljs-keyword\">as\u003C/span> e:\n                        error_msg = \u003Cspan class=\"hljs-string\">f&quot;Error in \u003Cspan class=\"hljs-subst\">{processor_name}\u003C/span> for \u003Cspan class=\"hljs-subst\">{file_path}\u003C/span>: \u003Cspan class=\"hljs-subst\">{e}\u003C/span>&quot;\u003C/span>\n                        results[\u003Cspan class=\"hljs-string\">&#x27;errors&#x27;\u003C/span>].append(error_msg)\n                        \u003Cspan class=\"hljs-built_in\">print\u003C/span>(\u003Cspan class=\"hljs-string\">f&quot;ERROR: \u003Cspan class=\"hljs-subst\">{error_msg}\u003C/span>&quot;\u003C/span>)\n                \n                results[\u003Cspan class=\"hljs-string\">&#x27;processed&#x27;\u003C/span>] += \u003Cspan class=\"hljs-number\">1\u003C/span>\n                \n            \u003Cspan class=\"hljs-keyword\">except\u003C/span> Exception \u003Cspan class=\"hljs-keyword\">as\u003C/span> e:\n                error_msg = \u003Cspan class=\"hljs-string\">f&quot;Failed to process \u003Cspan class=\"hljs-subst\">{file_path}\u003C/span>: \u003Cspan class=\"hljs-subst\">{e}\u003C/span>&quot;\u003C/span>\n                results[\u003Cspan class=\"hljs-string\">&#x27;errors&#x27;\u003C/span>].append(error_msg)\n                \u003Cspan class=\"hljs-built_in\">print\u003C/span>(\u003Cspan class=\"hljs-string\">f&quot;ERROR: \u003Cspan class=\"hljs-subst\">{error_msg}\u003C/span>&quot;\u003C/span>)\n        \n        \u003Cspan class=\"hljs-comment\"># Update cache and stats\u003C/span>\n        self.file_cache[\u003Cspan class=\"hljs-string\">&#x27;last_run&#x27;\u003C/span>] = datetime.now().isoformat()\n        self.file_cache[\u003Cspan class=\"hljs-string\">&#x27;stats&#x27;\u003C/span>][\u003Cspan class=\"hljs-string\">&#x27;total_files&#x27;\u003C/span>] = \u003Cspan class=\"hljs-built_in\">len\u003C/span>(self.file_cache[\u003Cspan class=\"hljs-string\">&#x27;files&#x27;\u003C/span>])\n        self.file_cache[\u003Cspan class=\"hljs-string\">&#x27;stats&#x27;\u003C/span>][\u003Cspan class=\"hljs-string\">&#x27;processed_files&#x27;\u003C/span>] = results[\u003Cspan class=\"hljs-string\">&#x27;processed&#x27;\u003C/span>]\n        \n        self._save_cache()\n        \n        \u003Cspan class=\"hljs-keyword\">return\u003C/span> results\n    \n    \u003Cspan class=\"hljs-keyword\">def\u003C/span> \u003Cspan class=\"hljs-title function_\">_default_lint_processor\u003C/span>(\u003Cspan class=\"hljs-params\">self, file_path: Path\u003C/span>) -&gt; \u003Cspan class=\"hljs-type\">Dict\u003C/span>:\n        \u003Cspan class=\"hljs-string\">&quot;&quot;&quot;Default linting processor for Markdown files.&quot;&quot;&quot;\u003C/span>\n        \u003Cspan class=\"hljs-keyword\">import\u003C/span> subprocess\n        \n        result = {\u003Cspan class=\"hljs-string\">&#x27;errors&#x27;\u003C/span>: [], \u003Cspan class=\"hljs-string\">&#x27;warnings&#x27;\u003C/span>: []}\n        \n        \u003Cspan class=\"hljs-keyword\">try\u003C/span>:\n            \u003Cspan class=\"hljs-comment\"># Run markdownlint if available\u003C/span>\n            cmd_result = subprocess.run(\n                [\u003Cspan class=\"hljs-string\">&#x27;markdownlint&#x27;\u003C/span>, \u003Cspan class=\"hljs-built_in\">str\u003C/span>(file_path)],\n                capture_output=\u003Cspan class=\"hljs-literal\">True\u003C/span>,\n                text=\u003Cspan class=\"hljs-literal\">True\u003C/span>,\n                timeout=\u003Cspan class=\"hljs-number\">30\u003C/span>\n            )\n            \n            \u003Cspan class=\"hljs-keyword\">if\u003C/span> cmd_result.returncode != \u003Cspan class=\"hljs-number\">0\u003C/span>:\n                result[\u003Cspan class=\"hljs-string\">&#x27;warnings&#x27;\u003C/span>].append(\u003Cspan class=\"hljs-string\">f&quot;Linting issues in \u003Cspan class=\"hljs-subst\">{file_path}\u003C/span>: \u003Cspan class=\"hljs-subst\">{cmd_result.stdout}\u003C/span>&quot;\u003C/span>)\n                \n        \u003Cspan class=\"hljs-keyword\">except\u003C/span> FileNotFoundError:\n            \u003Cspan class=\"hljs-comment\"># markdownlint not installed, skip\u003C/span>\n            \u003Cspan class=\"hljs-keyword\">pass\u003C/span>\n        \u003Cspan class=\"hljs-keyword\">except\u003C/span> subprocess.TimeoutExpired:\n            result[\u003Cspan class=\"hljs-string\">&#x27;errors&#x27;\u003C/span>].append(\u003Cspan class=\"hljs-string\">f&quot;Linting timeout for \u003Cspan class=\"hljs-subst\">{file_path}\u003C/span>&quot;\u003C/span>)\n        \u003Cspan class=\"hljs-keyword\">except\u003C/span> Exception \u003Cspan class=\"hljs-keyword\">as\u003C/span> e:\n            result[\u003Cspan class=\"hljs-string\">&#x27;errors&#x27;\u003C/span>].append(\u003Cspan class=\"hljs-string\">f&quot;Linting error for \u003Cspan class=\"hljs-subst\">{file_path}\u003C/span>: \u003Cspan class=\"hljs-subst\">{e}\u003C/span>&quot;\u003C/span>)\n        \n        \u003Cspan class=\"hljs-keyword\">return\u003C/span> result\n    \n    \u003Cspan class=\"hljs-keyword\">def\u003C/span> \u003Cspan class=\"hljs-title function_\">_default_build_processor\u003C/span>(\u003Cspan class=\"hljs-params\">self, file_path: Path\u003C/span>) -&gt; \u003Cspan class=\"hljs-type\">Dict\u003C/span>:\n        \u003Cspan class=\"hljs-string\">&quot;&quot;&quot;Default build processor for documentation files.&quot;&quot;&quot;\u003C/span>\n        result = {\u003Cspan class=\"hljs-string\">&#x27;errors&#x27;\u003C/span>: [], \u003Cspan class=\"hljs-string\">&#x27;warnings&#x27;\u003C/span>: []}\n        \n        \u003Cspan class=\"hljs-keyword\">try\u003C/span>:\n            \u003Cspan class=\"hljs-comment\"># Basic validation - check for common issues\u003C/span>\n            content = file_path.read_text(encoding=\u003Cspan class=\"hljs-string\">&#x27;utf-8&#x27;\u003C/span>)\n            \n            \u003Cspan class=\"hljs-comment\"># Check for broken internal links\u003C/span>\n            \u003Cspan class=\"hljs-keyword\">import\u003C/span> re\n            internal_link_pattern = \u003Cspan class=\"hljs-string\">r&#x27;\\[([^\\]]+)\\]\\(([^)]+\\.md[^)]*)\\)&#x27;\u003C/span>\n            \n            \u003Cspan class=\"hljs-keyword\">for\u003C/span> \u003Cspan class=\"hljs-keyword\">match\u003C/span> \u003Cspan class=\"hljs-keyword\">in\u003C/span> re.finditer(internal_link_pattern, content):\n                link_text = \u003Cspan class=\"hljs-keyword\">match\u003C/span>.group(\u003Cspan class=\"hljs-number\">1\u003C/span>)\n                link_path = \u003Cspan class=\"hljs-keyword\">match\u003C/span>.group(\u003Cspan class=\"hljs-number\">2\u003C/span>)\n                \n                \u003Cspan class=\"hljs-comment\"># Resolve relative path\u003C/span>\n                \u003Cspan class=\"hljs-keyword\">if\u003C/span> \u003Cspan class=\"hljs-keyword\">not\u003C/span> link_path.startswith(\u003Cspan class=\"hljs-string\">&#x27;http&#x27;\u003C/span>):\n                    target_path = (file_path.parent / link_path).resolve()\n                    \u003Cspan class=\"hljs-keyword\">if\u003C/span> \u003Cspan class=\"hljs-keyword\">not\u003C/span> target_path.exists():\n                        result[\u003Cspan class=\"hljs-string\">&#x27;warnings&#x27;\u003C/span>].append(\n                            \u003Cspan class=\"hljs-string\">f&quot;Broken internal link in \u003Cspan class=\"hljs-subst\">{file_path}\u003C/span>: [\u003Cspan class=\"hljs-subst\">{link_text}\u003C/span>](\u003Cspan class=\"hljs-subst\">{link_path}\u003C/span>)&quot;\u003C/span>\n                        )\n            \n        \u003Cspan class=\"hljs-keyword\">except\u003C/span> Exception \u003Cspan class=\"hljs-keyword\">as\u003C/span> e:\n            result[\u003Cspan class=\"hljs-string\">&#x27;errors&#x27;\u003C/span>].append(\u003Cspan class=\"hljs-string\">f&quot;Build processing error for \u003Cspan class=\"hljs-subst\">{file_path}\u003C/span>: \u003Cspan class=\"hljs-subst\">{e}\u003C/span>&quot;\u003C/span>)\n        \n        \u003Cspan class=\"hljs-keyword\">return\u003C/span> result\n    \n    \u003Cspan class=\"hljs-keyword\">def\u003C/span> \u003Cspan class=\"hljs-title function_\">get_cache_stats\u003C/span>(\u003Cspan class=\"hljs-params\">self\u003C/span>) -&gt; \u003Cspan class=\"hljs-type\">Dict\u003C/span>:\n        \u003Cspan class=\"hljs-string\">&quot;&quot;&quot;Get statistics about the current cache state.&quot;&quot;&quot;\u003C/span>\n        \u003Cspan class=\"hljs-keyword\">return\u003C/span> {\n            \u003Cspan class=\"hljs-string\">&#x27;cached_files&#x27;\u003C/span>: \u003Cspan class=\"hljs-built_in\">len\u003C/span>(self.file_cache[\u003Cspan class=\"hljs-string\">&#x27;files&#x27;\u003C/span>]),\n            \u003Cspan class=\"hljs-string\">&#x27;last_run&#x27;\u003C/span>: self.file_cache.get(\u003Cspan class=\"hljs-string\">&#x27;last_run&#x27;\u003C/span>),\n            \u003Cspan class=\"hljs-string\">&#x27;cache_file_size&#x27;\u003C/span>: self.cache_file.stat().st_size \u003Cspan class=\"hljs-keyword\">if\u003C/span> self.cache_file.exists() \u003Cspan class=\"hljs-keyword\">else\u003C/span> \u003Cspan class=\"hljs-number\">0\u003C/span>,\n            \u003Cspan class=\"hljs-string\">&#x27;stats&#x27;\u003C/span>: self.file_cache.get(\u003Cspan class=\"hljs-string\">&#x27;stats&#x27;\u003C/span>, {})\n        }\n\n\u003Cspan class=\"hljs-keyword\">def\u003C/span> \u003Cspan class=\"hljs-title function_\">main\u003C/span>():\n    \u003Cspan class=\"hljs-keyword\">import\u003C/span> argparse\n    \n    parser = argparse.ArgumentParser(description=\u003Cspan class=\"hljs-string\">&#x27;Incremental documentation processor&#x27;\u003C/span>)\n    parser.add_argument(\u003Cspan class=\"hljs-string\">&#x27;repo_path&#x27;\u003C/span>, nargs=\u003Cspan class=\"hljs-string\">&#x27;?&#x27;\u003C/span>, default=\u003Cspan class=\"hljs-string\">&#x27;.&#x27;\u003C/span>, \u003Cspan class=\"hljs-built_in\">help\u003C/span>=\u003Cspan class=\"hljs-string\">&#x27;Repository path&#x27;\u003C/span>)\n    parser.add_argument(\u003Cspan class=\"hljs-string\">&#x27;--force&#x27;\u003C/span>, action=\u003Cspan class=\"hljs-string\">&#x27;store_true&#x27;\u003C/span>, \u003Cspan class=\"hljs-built_in\">help\u003C/span>=\u003Cspan class=\"hljs-string\">&#x27;Force processing all files&#x27;\u003C/span>)\n    parser.add_argument(\u003Cspan class=\"hljs-string\">&#x27;--stats&#x27;\u003C/span>, action=\u003Cspan class=\"hljs-string\">&#x27;store_true&#x27;\u003C/span>, \u003Cspan class=\"hljs-built_in\">help\u003C/span>=\u003Cspan class=\"hljs-string\">&#x27;Show cache statistics&#x27;\u003C/span>)\n    \n    args = parser.parse_args()\n    \n    processor = IncrementalDocProcessor(args.repo_path)\n    \n    \u003Cspan class=\"hljs-keyword\">if\u003C/span> args.stats:\n        stats = processor.get_cache_stats()\n        \u003Cspan class=\"hljs-built_in\">print\u003C/span>(json.dumps(stats, indent=\u003Cspan class=\"hljs-number\">2\u003C/span>))\n        \u003Cspan class=\"hljs-keyword\">return\u003C/span>\n    \n    \u003Cspan class=\"hljs-keyword\">if\u003C/span> args.force:\n        \u003Cspan class=\"hljs-comment\"># Clear cache to force full processing\u003C/span>\n        processor.file_cache = {\u003Cspan class=\"hljs-string\">&#x27;files&#x27;\u003C/span>: {}, \u003Cspan class=\"hljs-string\">&#x27;last_run&#x27;\u003C/span>: \u003Cspan class=\"hljs-literal\">None\u003C/span>, \u003Cspan class=\"hljs-string\">&#x27;stats&#x27;\u003C/span>: {}}\n    \n    results = processor.process_changes()\n    \n    \u003Cspan class=\"hljs-built_in\">print\u003C/span>(\u003Cspan class=\"hljs-string\">f&quot;\\nProcessing completed:&quot;\u003C/span>)\n    \u003Cspan class=\"hljs-built_in\">print\u003C/span>(\u003Cspan class=\"hljs-string\">f&quot;  Files processed: \u003Cspan class=\"hljs-subst\">{results[\u003Cspan class=\"hljs-string\">&#x27;processed&#x27;\u003C/span>]}\u003C/span>/\u003Cspan class=\"hljs-subst\">{results[\u003Cspan class=\"hljs-string\">&#x27;total_files&#x27;\u003C/span>]}\u003C/span>&quot;\u003C/span>)\n    \u003Cspan class=\"hljs-built_in\">print\u003C/span>(\u003Cspan class=\"hljs-string\">f&quot;  Errors: \u003Cspan class=\"hljs-subst\">{\u003Cspan class=\"hljs-built_in\">len\u003C/span>(results[\u003Cspan class=\"hljs-string\">&#x27;errors&#x27;\u003C/span>])}\u003C/span>&quot;\u003C/span>)\n    \u003Cspan class=\"hljs-built_in\">print\u003C/span>(\u003Cspan class=\"hljs-string\">f&quot;  Warnings: \u003Cspan class=\"hljs-subst\">{\u003Cspan class=\"hljs-built_in\">len\u003C/span>(results[\u003Cspan class=\"hljs-string\">&#x27;warnings&#x27;\u003C/span>])}\u003C/span>&quot;\u003C/span>)\n    \n    \u003Cspan class=\"hljs-keyword\">if\u003C/span> results[\u003Cspan class=\"hljs-string\">&#x27;errors&#x27;\u003C/span>]:\n        \u003Cspan class=\"hljs-built_in\">print\u003C/span>(\u003Cspan class=\"hljs-string\">&quot;\\nErrors:&quot;\u003C/span>)\n        \u003Cspan class=\"hljs-keyword\">for\u003C/span> error \u003Cspan class=\"hljs-keyword\">in\u003C/span> results[\u003Cspan class=\"hljs-string\">&#x27;errors&#x27;\u003C/span>]:\n            \u003Cspan class=\"hljs-built_in\">print\u003C/span>(\u003Cspan class=\"hljs-string\">f&quot;  - \u003Cspan class=\"hljs-subst\">{error}\u003C/span>&quot;\u003C/span>)\n    \n    \u003Cspan class=\"hljs-keyword\">if\u003C/span> results[\u003Cspan class=\"hljs-string\">&#x27;warnings&#x27;\u003C/span>]:\n        \u003Cspan class=\"hljs-built_in\">print\u003C/span>(\u003Cspan class=\"hljs-string\">&quot;\\nWarnings:&quot;\u003C/span>)\n        \u003Cspan class=\"hljs-keyword\">for\u003C/span> warning \u003Cspan class=\"hljs-keyword\">in\u003C/span> results[\u003Cspan class=\"hljs-string\">&#x27;warnings&#x27;\u003C/span>]:\n            \u003Cspan class=\"hljs-built_in\">print\u003C/span>(\u003Cspan class=\"hljs-string\">f&quot;  - \u003Cspan class=\"hljs-subst\">{warning}\u003C/span>&quot;\u003C/span>)\n\n\u003Cspan class=\"hljs-keyword\">if\u003C/span> __name__ == \u003Cspan class=\"hljs-string\">&#x27;__main__&#x27;\u003C/span>:\n    main()\n\u003C/code>\u003C/pre>\u003Ch2 id=\"troubleshooting-common-versioning-issues\">Troubleshooting Common Versioning Issues\u003C/h2>\n\u003Ch3 id=\"merge-conflict-resolution\">Merge Conflict Resolution\u003C/h3>\n\u003Cp>\u003Cstrong>Problem\u003C/strong>: Complex merge conflicts in documentation files\u003C/p>\n\u003Cp>\u003Cstrong>Solutions\u003C/strong>:\u003C/p>\n\u003Cpre>\u003Ccode class=\"hljs language-bash\">\u003Cspan class=\"hljs-comment\"># Configure better merge tools for Markdown\u003C/span>\ngit config merge.tool vimdiff\ngit config mergetool.vimdiff.cmd \u003Cspan class=\"hljs-string\">&#x27;vim -d &quot;$LOCAL&quot; &quot;$REMOTE&quot; &quot;$MERGED&quot;&#x27;\u003C/span>\n\n\u003Cspan class=\"hljs-comment\"># Use semantic merge strategies\u003C/span>\ngit config merge.ours.driver \u003Cspan class=\"hljs-literal\">true\u003C/span>\ngit config merge.union.driver \u003Cspan class=\"hljs-literal\">true\u003C/span>\n\n\u003Cspan class=\"hljs-comment\"># For documentation-specific merge conflicts\u003C/span>\n\u003Cspan class=\"hljs-built_in\">echo\u003C/span> \u003Cspan class=\"hljs-string\">&quot;*.md merge=union&quot;\u003C/span> &gt;&gt; .gitattributes  \u003Cspan class=\"hljs-comment\"># Union merge for less conflicts\u003C/span>\n\u003Cspan class=\"hljs-built_in\">echo\u003C/span> \u003Cspan class=\"hljs-string\">&quot;CHANGELOG.md merge=union&quot;\u003C/span> &gt;&gt; .gitattributes  \u003Cspan class=\"hljs-comment\"># Changelog files\u003C/span>\n\n\u003Cspan class=\"hljs-comment\"># Resolve conflicts with context\u003C/span>\ngit mergetool --tool=vimdiff\n\n\u003Cspan class=\"hljs-comment\"># Alternative: Use automatic conflict resolution for documentation\u003C/span>\ngit config merge.conflictstyle diff3  \u003Cspan class=\"hljs-comment\"># Show more context in conflicts\u003C/span>\n\u003C/code>\u003C/pre>\u003Ch3 id=\"large-file-history-management\">Large File History Management\u003C/h3>\n\u003Cp>\u003Cstrong>Problem\u003C/strong>: Repository size grows too large with document history\u003C/p>\n\u003Cp>\u003Cstrong>Solutions\u003C/strong>:\u003C/p>\n\u003Cpre>\u003Ccode class=\"hljs language-bash\">\u003Cspan class=\"hljs-comment\"># Use git filter-branch to remove large files from history\u003C/span>\ngit filter-branch --force --index-filter \\\n  \u003Cspan class=\"hljs-string\">&#x27;git rm --cached --ignore-unmatch path/to/large/file.pdf&#x27;\u003C/span> \\\n  --prune-empty --tag-name-filter \u003Cspan class=\"hljs-built_in\">cat\u003C/span> -- --all\n\n\u003Cspan class=\"hljs-comment\"># Use BFG Repo-Cleaner (faster alternative)\u003C/span>\njava -jar bfg.jar --delete-files \u003Cspan class=\"hljs-string\">&quot;*.{pdf,zip,tar.gz}&quot;\u003C/span> my-repo.git\ngit reflog expire --expire=now --all &amp;&amp; git gc --prune=now --aggressive\n\n\u003Cspan class=\"hljs-comment\"># Separate binary assets into Git LFS\u003C/span>\ngit lfs migrate import --include=\u003Cspan class=\"hljs-string\">&quot;*.pdf,*.png,*.jpg&quot;\u003C/span>\n\n\u003Cspan class=\"hljs-comment\"># Archive old history\u003C/span>\ngit tag archive/old-history HEAD  \u003Cspan class=\"hljs-comment\"># Mark point for archival\u003C/span>\n\u003Cspan class=\"hljs-comment\"># Create new orphan branch for fresh start if needed\u003C/span>\ngit checkout --orphan fresh-start\n\u003C/code>\u003C/pre>\u003Ch3 id=\"cross-platform-compatibility-issues\">Cross-Platform Compatibility Issues\u003C/h3>\n\u003Cp>\u003Cstrong>Problem\u003C/strong>: Line ending and encoding issues across different operating systems\u003C/p>\n\u003Cp>\u003Cstrong>Solutions\u003C/strong>:\u003C/p>\n\u003Cpre>\u003Ccode class=\"hljs language-bash\">\u003Cspan class=\"hljs-comment\"># Configure consistent line endings\u003C/span>\ngit config --global core.autocrlf input   \u003Cspan class=\"hljs-comment\"># Linux/Mac\u003C/span>\ngit config --global core.autocrlf \u003Cspan class=\"hljs-literal\">true\u003C/span>    \u003Cspan class=\"hljs-comment\"># Windows\u003C/span>\n\n\u003Cspan class=\"hljs-comment\"># Set up .gitattributes for consistent handling\u003C/span>\n\u003Cspan class=\"hljs-built_in\">echo\u003C/span> \u003Cspan class=\"hljs-string\">&quot;* text=auto&quot;\u003C/span> &gt; .gitattributes\n\u003Cspan class=\"hljs-built_in\">echo\u003C/span> \u003Cspan class=\"hljs-string\">&quot;*.md text eol=lf&quot;\u003C/span> &gt;&gt; .gitattributes\n\u003Cspan class=\"hljs-built_in\">echo\u003C/span> \u003Cspan class=\"hljs-string\">&quot;*.yml text eol=lf&quot;\u003C/span> &gt;&gt; .gitattributes\n\u003Cspan class=\"hljs-built_in\">echo\u003C/span> \u003Cspan class=\"hljs-string\">&quot;*.sh text eol=lf&quot;\u003C/span> &gt;&gt; .gitattributes\n\n\u003Cspan class=\"hljs-comment\"># Fix existing line ending issues\u003C/span>\ngit add --renormalize .\ngit commit -m \u003Cspan class=\"hljs-string\">&quot;fix: normalize line endings&quot;\u003C/span>\n\n\u003Cspan class=\"hljs-comment\"># Handle encoding issues\u003C/span>\nfile -bi *.md  \u003Cspan class=\"hljs-comment\"># Check file encoding\u003C/span>\niconv -f iso-8859-1 -t utf-8 file.md &gt; file_utf8.md  \u003Cspan class=\"hljs-comment\"># Convert encoding\u003C/span>\n\u003C/code>\u003C/pre>\u003Ch2 id=\"conclusion\">Conclusion\u003C/h2>\n\u003Cp>Markdown document versioning and change tracking transforms simple text documentation into enterprise-grade information management systems that provide comprehensive audit trails, collaborative workflows, and systematic revision control. By mastering Git integration, automated analysis tools, and advanced tracking techniques, you can create documentation processes that meet both technical requirements and regulatory compliance standards.\u003C/p>\n\u003Cp>The key to successful versioning implementation lies in choosing appropriate tools for your scale and requirements, establishing clear workflows for collaboration, and implementing automated systems that reduce manual overhead while maintaining thorough change documentation. Whether you&#39;re managing small project documentation or enterprise-wide documentation systems, the techniques covered in this guide provide the foundation for professional version control that enhances both content quality and team productivity.\u003C/p>\n\u003Cp>Remember to balance comprehensive tracking with system performance, implement appropriate security measures for sensitive documentation, and regularly review and optimize your versioning workflows as your documentation needs evolve. With proper implementation, versioning becomes an invisible but powerful foundation that supports confident documentation management and continuous improvement processes.\u003C/p>\n",[15,19,22,25,28,31,34,37,40,43,46],{"id":16,"text":17,"level":18},"why-implement-document-versioning-for-markdown","Why Implement Document Versioning for Markdown?",2,{"id":20,"text":21,"level":18},"git-based-versioning-fundamentals","Git-Based Versioning Fundamentals",{"id":23,"text":24,"level":18},"advanced-change-tracking-techniques","Advanced Change Tracking Techniques",{"id":26,"text":27,"level":18},"collaborative-editing-workflows","Collaborative Editing Workflows",{"id":29,"text":30,"level":18},"document-history-and-analytics","Document History and Analytics",{"id":32,"text":33,"level":18},"integration-with-documentation-workflows","Integration with Documentation Workflows",{"id":35,"text":36,"level":18},"advanced-version-control-strategies","Advanced Version Control Strategies",{"id":38,"text":39,"level":18},"compliance-and-audit-requirements","Compliance and Audit Requirements",{"id":41,"text":42,"level":18},"performance-optimization-for-large-documentation-sets","Performance Optimization for Large Documentation Sets",{"id":44,"text":45,"level":18},"troubleshooting-common-versioning-issues","Troubleshooting Common Versioning Issues",{"id":47,"text":48,"level":18},"conclusion","Conclusion",[],[51,59,67],{"slug":52,"title":53,"description":54,"excerpt":55,"date":56,"category":9,"author":10,"keywords":57,"readingMinutes":58},"markdown-diff-and-patch-documentation-version-control-guide","Markdown Diff and Patch Documentation: Complete Guide for Version Control Integration and Change Tracking","Master Markdown diff tools, patch documentation, and version control integration for collaborative technical writing. Learn diff strategies, change tracking workflows, and automated documentation updates with Git integration.","Advanced Markdown diff and patch documentation techniques enable sophisticated version control workflows that track content changes, facilitate collaborative writing, and maintain comprehensive…","2025-12-07","markdown diff, markdown patch, version control markdown, git markdown diff, markdown change tracking, collaborative writing, technical documentation diff, markdown git workflow",16,{"slug":60,"title":61,"description":62,"excerpt":63,"date":64,"category":9,"author":10,"keywords":65,"readingMinutes":66},"markdown-badges-shields-complete-guide","Markdown Badges and Shields: Complete Guide for Professional Documentation","Master badges and shields in Markdown for GitHub, GitLab, and documentation platforms. Learn to create custom status badges, build badges, test coverage shields, and dynamic informational elements.","Badges and shields are essential visual elements in modern technical documentation that communicate project status, build health, test coverage, and other key metrics at a glance. These compact,…","2025-08-28","markdown badges, markdown shields, github badges, build status badges, test coverage badges, shields.io badges, readme badges, documentation badges",7,{"slug":68,"title":69,"description":70,"excerpt":71,"date":72,"category":9,"author":10,"keywords":73,"readingMinutes":74},"markdown-text-wrapping-line-length-management-complete-guide","Markdown Text Wrapping and Line Length Management: Complete Guide for Professional Documentation and Cross-Platform Compatibility","Master Markdown text wrapping, line length control, and formatting strategies for professional documentation. Learn automatic wrapping, manual breaks, editor configuration, and cross-platform compatibility techniques.","Markdown text wrapping and line length management are crucial for creating readable, maintainable documentation that renders consistently across different platforms, editors, and display…","2025-11-05","markdown text wrapping, line length markdown, markdown line breaks, text formatting, markdown editors, documentation standards, text width control, markdown best practices",20,1792184941732]