diary-docs 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. diary_docs-0.1.0/LICENSE +21 -0
  2. diary_docs-0.1.0/PKG-INFO +228 -0
  3. diary_docs-0.1.0/README.md +199 -0
  4. diary_docs-0.1.0/diary/__init__.py +1 -0
  5. diary_docs-0.1.0/diary/__main__.py +3 -0
  6. diary_docs-0.1.0/diary/aimb/__init__.py +48 -0
  7. diary_docs-0.1.0/diary/aimb/hasher.py +157 -0
  8. diary_docs-0.1.0/diary/aimb/merge.py +252 -0
  9. diary_docs-0.1.0/diary/aimb/parser.py +202 -0
  10. diary_docs-0.1.0/diary/cli.py +999 -0
  11. diary_docs-0.1.0/diary/git_utils.py +202 -0
  12. diary_docs-0.1.0/diary/indexer/__init__.py +44 -0
  13. diary_docs-0.1.0/diary/indexer/database.py +340 -0
  14. diary_docs-0.1.0/diary/indexer/extractors.py +468 -0
  15. diary_docs-0.1.0/diary/indexer/gitignore.py +62 -0
  16. diary_docs-0.1.0/diary/indexer/indexer.py +511 -0
  17. diary_docs-0.1.0/diary/indexer/reporter.py +137 -0
  18. diary_docs-0.1.0/diary/indexer/scanner.py +65 -0
  19. diary_docs-0.1.0/diary/sync/__init__.py +33 -0
  20. diary_docs-0.1.0/diary/sync/detector.py +405 -0
  21. diary_docs-0.1.0/diary/sync/engine.py +404 -0
  22. diary_docs-0.1.0/diary/sync/protocol.py +176 -0
  23. diary_docs-0.1.0/diary/templates.py +102 -0
  24. diary_docs-0.1.0/diary_docs.egg-info/PKG-INFO +228 -0
  25. diary_docs-0.1.0/diary_docs.egg-info/SOURCES.txt +38 -0
  26. diary_docs-0.1.0/diary_docs.egg-info/dependency_links.txt +1 -0
  27. diary_docs-0.1.0/diary_docs.egg-info/entry_points.txt +2 -0
  28. diary_docs-0.1.0/diary_docs.egg-info/requires.txt +2 -0
  29. diary_docs-0.1.0/diary_docs.egg-info/top_level.txt +1 -0
  30. diary_docs-0.1.0/pyproject.toml +44 -0
  31. diary_docs-0.1.0/setup.cfg +4 -0
  32. diary_docs-0.1.0/tests/test_aimb_hasher.py +277 -0
  33. diary_docs-0.1.0/tests/test_aimb_parser.py +278 -0
  34. diary_docs-0.1.0/tests/test_cli.py +172 -0
  35. diary_docs-0.1.0/tests/test_git_utils.py +258 -0
  36. diary_docs-0.1.0/tests/test_indexer.py +215 -0
  37. diary_docs-0.1.0/tests/test_sync_detector.py +672 -0
  38. diary_docs-0.1.0/tests/test_sync_engine.py +82 -0
  39. diary_docs-0.1.0/tests/test_sync_integration.py +351 -0
  40. diary_docs-0.1.0/tests/test_sync_protocol.py +246 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 bakhija senakmoiky
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,228 @@
1
+ Metadata-Version: 2.4
2
+ Name: diary-docs
3
+ Version: 0.1.0
4
+ Summary: Scaffold DIARY documentation structure with MkDocs and Backstage support
5
+ Author-email: bakhija senakmoiky <senakmoiky@gmail.com>
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/bakhija/diary-docs
8
+ Project-URL: Repository, https://github.com/bakhija/diary-docs
9
+ Keywords: documentation,mkdocs,backstage,techdocs,scaffolder
10
+ Classifier: Development Status :: 3 - Alpha
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: License :: OSI Approved :: MIT License
13
+ Classifier: Operating System :: OS Independent
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3.8
16
+ Classifier: Programming Language :: Python :: 3.9
17
+ Classifier: Programming Language :: Python :: 3.10
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Programming Language :: Python :: 3.13
21
+ Classifier: Topic :: Documentation
22
+ Classifier: Topic :: Software Development :: Documentation
23
+ Requires-Python: >=3.8
24
+ Description-Content-Type: text/markdown
25
+ License-File: LICENSE
26
+ Requires-Dist: rich>=13.0
27
+ Requires-Dist: inquirerpy>=0.3.4
28
+ Dynamic: license-file
29
+
30
+ # diary-docs — DIARY Documentation Scaffolder
31
+
32
+ A CLI tool that scaffolds a DIARY documentation structure with MkDocs and Backstage support, indexes your codebase for knowledge retrieval, and keeps docs in sync with code changes.
33
+
34
+ ## Installation
35
+
36
+ ```bash
37
+ pip install diary-docs
38
+ ```
39
+
40
+ For development:
41
+
42
+ ```bash
43
+ pip install -e .
44
+ ```
45
+
46
+ ## Commands
47
+
48
+ ### `diary-docs init`
49
+
50
+ Initialize a new DIARY documentation project in the current directory.
51
+
52
+ ```bash
53
+ diary-docs init
54
+ ```
55
+
56
+ The tool prompts for a project name, then creates:
57
+
58
+ ```
59
+ docs/
60
+ ├── index.md
61
+ ├── objectives.md
62
+ ├── structure/
63
+ │ └── index.md
64
+ ├── techdocs/
65
+ │ ├── index.md
66
+ │ ├── architecture.md
67
+ │ ├── api-contracts.md
68
+ │ ├── deployment.md
69
+ │ ├── adr.md
70
+ │ └── development-guide.md
71
+ ├── product/
72
+ │ ├── index.md
73
+ │ ├── user-guide.md
74
+ │ └── modules.md
75
+ ├── ops-governance/
76
+ │ ├── index.md
77
+ │ ├── runbooks.md
78
+ │ └── security.md
79
+ └── knowledge-base/
80
+ ├── index.md
81
+ ├── faq.md
82
+ └── troubleshooting.md
83
+ mkdocs.yml
84
+ catalog-info.yaml
85
+ ```
86
+
87
+ It also generates an AI agent skill file for content generation.
88
+
89
+ **Options:**
90
+
91
+ | Flag | Description |
92
+ |------|-------------|
93
+ | `-f`, `--force` | Overwrite existing files |
94
+ | `--help` | Show help for this command |
95
+
96
+ If files already exist, they are skipped (unless `--force` is used).
97
+
98
+ ---
99
+
100
+ ### `diary-docs index`
101
+
102
+ Index the workspace codebase for knowledge retrieval. Extracts symbols, files, and relationships into a SQLite database.
103
+
104
+ ```bash
105
+ diary-docs index
106
+ ```
107
+
108
+ **Options:**
109
+
110
+ | Flag | Description |
111
+ |------|-------------|
112
+ | `-r`, `--report` | Generate a documentation coverage report after indexing |
113
+ | `--db-path PATH` | Custom database path (default: `docs/.index/knowledge.db`) |
114
+ | `--help` | Show help for this command |
115
+
116
+ The index powers the `diary-docs generate-content` skill, allowing AI agents to query the codebase structure without manually scanning files.
117
+
118
+ ---
119
+
120
+ ### `diary-docs sync`
121
+
122
+ Synchronize documentation with detected code changes. Compares the current workspace against git history to find outdated AIMB (AI-Managed) blocks in markdown files.
123
+
124
+ ```bash
125
+ # Preview changes without applying
126
+ diary-docs sync --dry-run
127
+
128
+ # Apply all detected changes
129
+ diary-docs sync --force
130
+ ```
131
+
132
+ **Options:**
133
+
134
+ | Flag | Description |
135
+ |------|-------------|
136
+ | `-n`, `--dry-run` | Preview changes as JSON without applying |
137
+ | `-b`, `--branch NAME` | Override branch detection |
138
+ | `-f`, `--force` | Skip conflict warnings |
139
+ | `-o`, `--output FILE` | Write JSON report to file |
140
+ | `--help` | Show help for this command |
141
+
142
+ **Dry-run output** is a JSON SyncReport showing code changes, affected docs, confidence scores, and any conflicts.
143
+
144
+ ---
145
+
146
+ ### Global Options
147
+
148
+ | Flag | Description |
149
+ |------|-------------|
150
+ | `--version` | Show version |
151
+ | `--help` | Show top-level help |
152
+
153
+ ## AI Agent Skills
154
+
155
+ `diary-docs init` generates two slash commands for AI coding agents (Claude Code, OpenCode). The skill files are placed in `.claude/commands/` or `.opencode/commands/` (you choose during init).
156
+
157
+ ### `/diary-generate-content`
158
+
159
+ Analyzes the workspace codebase via the pre-built index and generates enterprise-grade documentation content for every DIARY file.
160
+
161
+ ```bash
162
+ # In Claude Code or OpenCode:
163
+ /diary-generate-content
164
+ ```
165
+
166
+ The skill follows a multi-step workflow:
167
+ 1. Reads existing docs structure
168
+ 2. Queries the knowledge index (`docs/.index/knowledge.db`)
169
+ 3. Asks clarifying questions for missing context
170
+ 4. Generates content with Mermaid diagrams, tables, and use cases
171
+ 5. Writes all `docs/` files with AIMB (AI-Managed Block) wrappers
172
+
173
+ Output covers: architecture overview, API contracts, deployment flow, ADR log, user guide, runbooks, security compliance, FAQ, and troubleshooting.
174
+
175
+ ---
176
+
177
+ ### `/diary-sync`
178
+
179
+ Synchronizes documentation with detected code changes. Compares the current git state against history to find outdated AIMB blocks.
180
+
181
+ ```bash
182
+ # In Claude Code or OpenCode:
183
+ /diary-sync
184
+ ```
185
+
186
+ The skill follows a structured workflow:
187
+ 1. Verifies git state and runs `diary-docs sync --dry-run`
188
+ 2. Parses the SyncReport JSON for changes and conflicts
189
+ 3. Processes each high-confidence change by updating relevant AIMB blocks
190
+ 4. Flags conflicts for manual review (never auto-resolves)
191
+ 5. Finalizes with `diary-docs sync --force`
192
+ 6. Prints a summary of all processed files
193
+
194
+ **Prerequisites:** All code changes must be committed to git before running `/diary-sync`.
195
+
196
+ ---
197
+
198
+ ## What It Generates
199
+
200
+ | File/Folder | Description |
201
+ |-------------|-------------|
202
+ | `docs/` | Main documentation folder |
203
+ | `docs/index.md` | Root documentation index |
204
+ | `docs/objectives.md` | Project objectives and goals |
205
+ | `docs/structure/index.md` | Writing guidelines and conventions |
206
+ | `docs/techdocs/` | Technical documentation section |
207
+ | `docs/techdocs/architecture.md` | System architecture overview |
208
+ | `docs/techdocs/api-contracts.md` | API endpoint specifications |
209
+ | `docs/techdocs/deployment.md` | Deployment flow and environments |
210
+ | `docs/techdocs/adr.md` | Architecture Decision Records |
211
+ | `docs/techdocs/development-guide.md` | Local development setup guide |
212
+ | `docs/product/` | Product documentation section |
213
+ | `docs/product/user-guide.md` | End-user guide with use cases |
214
+ | `docs/product/modules.md` | Module/component reference |
215
+ | `docs/ops-governance/` | Operations & governance section |
216
+ | `docs/ops-governance/runbooks.md` | Operational runbooks |
217
+ | `docs/ops-governance/security.md` | Security compliance docs |
218
+ | `docs/knowledge-base/` | Knowledge base section |
219
+ | `docs/knowledge-base/faq.md` | Frequently asked questions |
220
+ | `docs/knowledge-base/troubleshooting.md` | Troubleshooting guide |
221
+ | `mkdocs.yml` | MkDocs configuration with TechDocs Core plugin |
222
+ | `catalog-info.yaml` | Backstage component registration file |
223
+
224
+ ## Development
225
+
226
+ ```bash
227
+ pytest tests/ -v
228
+ ```
@@ -0,0 +1,199 @@
1
+ # diary-docs — DIARY Documentation Scaffolder
2
+
3
+ A CLI tool that scaffolds a DIARY documentation structure with MkDocs and Backstage support, indexes your codebase for knowledge retrieval, and keeps docs in sync with code changes.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ pip install diary-docs
9
+ ```
10
+
11
+ For development:
12
+
13
+ ```bash
14
+ pip install -e .
15
+ ```
16
+
17
+ ## Commands
18
+
19
+ ### `diary-docs init`
20
+
21
+ Initialize a new DIARY documentation project in the current directory.
22
+
23
+ ```bash
24
+ diary-docs init
25
+ ```
26
+
27
+ The tool prompts for a project name, then creates:
28
+
29
+ ```
30
+ docs/
31
+ ├── index.md
32
+ ├── objectives.md
33
+ ├── structure/
34
+ │ └── index.md
35
+ ├── techdocs/
36
+ │ ├── index.md
37
+ │ ├── architecture.md
38
+ │ ├── api-contracts.md
39
+ │ ├── deployment.md
40
+ │ ├── adr.md
41
+ │ └── development-guide.md
42
+ ├── product/
43
+ │ ├── index.md
44
+ │ ├── user-guide.md
45
+ │ └── modules.md
46
+ ├── ops-governance/
47
+ │ ├── index.md
48
+ │ ├── runbooks.md
49
+ │ └── security.md
50
+ └── knowledge-base/
51
+ ├── index.md
52
+ ├── faq.md
53
+ └── troubleshooting.md
54
+ mkdocs.yml
55
+ catalog-info.yaml
56
+ ```
57
+
58
+ It also generates an AI agent skill file for content generation.
59
+
60
+ **Options:**
61
+
62
+ | Flag | Description |
63
+ |------|-------------|
64
+ | `-f`, `--force` | Overwrite existing files |
65
+ | `--help` | Show help for this command |
66
+
67
+ If files already exist, they are skipped (unless `--force` is used).
68
+
69
+ ---
70
+
71
+ ### `diary-docs index`
72
+
73
+ Index the workspace codebase for knowledge retrieval. Extracts symbols, files, and relationships into a SQLite database.
74
+
75
+ ```bash
76
+ diary-docs index
77
+ ```
78
+
79
+ **Options:**
80
+
81
+ | Flag | Description |
82
+ |------|-------------|
83
+ | `-r`, `--report` | Generate a documentation coverage report after indexing |
84
+ | `--db-path PATH` | Custom database path (default: `docs/.index/knowledge.db`) |
85
+ | `--help` | Show help for this command |
86
+
87
+ The index powers the `diary-docs generate-content` skill, allowing AI agents to query the codebase structure without manually scanning files.
88
+
89
+ ---
90
+
91
+ ### `diary-docs sync`
92
+
93
+ Synchronize documentation with detected code changes. Compares the current workspace against git history to find outdated AIMB (AI-Managed) blocks in markdown files.
94
+
95
+ ```bash
96
+ # Preview changes without applying
97
+ diary-docs sync --dry-run
98
+
99
+ # Apply all detected changes
100
+ diary-docs sync --force
101
+ ```
102
+
103
+ **Options:**
104
+
105
+ | Flag | Description |
106
+ |------|-------------|
107
+ | `-n`, `--dry-run` | Preview changes as JSON without applying |
108
+ | `-b`, `--branch NAME` | Override branch detection |
109
+ | `-f`, `--force` | Skip conflict warnings |
110
+ | `-o`, `--output FILE` | Write JSON report to file |
111
+ | `--help` | Show help for this command |
112
+
113
+ **Dry-run output** is a JSON SyncReport showing code changes, affected docs, confidence scores, and any conflicts.
114
+
115
+ ---
116
+
117
+ ### Global Options
118
+
119
+ | Flag | Description |
120
+ |------|-------------|
121
+ | `--version` | Show version |
122
+ | `--help` | Show top-level help |
123
+
124
+ ## AI Agent Skills
125
+
126
+ `diary-docs init` generates two slash commands for AI coding agents (Claude Code, OpenCode). The skill files are placed in `.claude/commands/` or `.opencode/commands/` (you choose during init).
127
+
128
+ ### `/diary-generate-content`
129
+
130
+ Analyzes the workspace codebase via the pre-built index and generates enterprise-grade documentation content for every DIARY file.
131
+
132
+ ```bash
133
+ # In Claude Code or OpenCode:
134
+ /diary-generate-content
135
+ ```
136
+
137
+ The skill follows a multi-step workflow:
138
+ 1. Reads existing docs structure
139
+ 2. Queries the knowledge index (`docs/.index/knowledge.db`)
140
+ 3. Asks clarifying questions for missing context
141
+ 4. Generates content with Mermaid diagrams, tables, and use cases
142
+ 5. Writes all `docs/` files with AIMB (AI-Managed Block) wrappers
143
+
144
+ Output covers: architecture overview, API contracts, deployment flow, ADR log, user guide, runbooks, security compliance, FAQ, and troubleshooting.
145
+
146
+ ---
147
+
148
+ ### `/diary-sync`
149
+
150
+ Synchronizes documentation with detected code changes. Compares the current git state against history to find outdated AIMB blocks.
151
+
152
+ ```bash
153
+ # In Claude Code or OpenCode:
154
+ /diary-sync
155
+ ```
156
+
157
+ The skill follows a structured workflow:
158
+ 1. Verifies git state and runs `diary-docs sync --dry-run`
159
+ 2. Parses the SyncReport JSON for changes and conflicts
160
+ 3. Processes each high-confidence change by updating relevant AIMB blocks
161
+ 4. Flags conflicts for manual review (never auto-resolves)
162
+ 5. Finalizes with `diary-docs sync --force`
163
+ 6. Prints a summary of all processed files
164
+
165
+ **Prerequisites:** All code changes must be committed to git before running `/diary-sync`.
166
+
167
+ ---
168
+
169
+ ## What It Generates
170
+
171
+ | File/Folder | Description |
172
+ |-------------|-------------|
173
+ | `docs/` | Main documentation folder |
174
+ | `docs/index.md` | Root documentation index |
175
+ | `docs/objectives.md` | Project objectives and goals |
176
+ | `docs/structure/index.md` | Writing guidelines and conventions |
177
+ | `docs/techdocs/` | Technical documentation section |
178
+ | `docs/techdocs/architecture.md` | System architecture overview |
179
+ | `docs/techdocs/api-contracts.md` | API endpoint specifications |
180
+ | `docs/techdocs/deployment.md` | Deployment flow and environments |
181
+ | `docs/techdocs/adr.md` | Architecture Decision Records |
182
+ | `docs/techdocs/development-guide.md` | Local development setup guide |
183
+ | `docs/product/` | Product documentation section |
184
+ | `docs/product/user-guide.md` | End-user guide with use cases |
185
+ | `docs/product/modules.md` | Module/component reference |
186
+ | `docs/ops-governance/` | Operations & governance section |
187
+ | `docs/ops-governance/runbooks.md` | Operational runbooks |
188
+ | `docs/ops-governance/security.md` | Security compliance docs |
189
+ | `docs/knowledge-base/` | Knowledge base section |
190
+ | `docs/knowledge-base/faq.md` | Frequently asked questions |
191
+ | `docs/knowledge-base/troubleshooting.md` | Troubleshooting guide |
192
+ | `mkdocs.yml` | MkDocs configuration with TechDocs Core plugin |
193
+ | `catalog-info.yaml` | Backstage component registration file |
194
+
195
+ ## Development
196
+
197
+ ```bash
198
+ pytest tests/ -v
199
+ ```
@@ -0,0 +1 @@
1
+ __version__ = "0.1.0"
@@ -0,0 +1,3 @@
1
+ from diary.cli import main
2
+
3
+ main()
@@ -0,0 +1,48 @@
1
+ """AIMB — AI Managed Block parser, hasher, and merge for markdown files."""
2
+
3
+ from .hasher import (
4
+ compute_block_hash,
5
+ verify_block_hash,
6
+ hash_all_blocks,
7
+ get_stored_hashes,
8
+ find_changed_blocks,
9
+ )
10
+ from .merge import (
11
+ ConflictInfo,
12
+ MergeDecision,
13
+ apply_replace,
14
+ decide_block_action,
15
+ format_conflict_report,
16
+ generate_block_diff,
17
+ )
18
+ from .parser import (
19
+ AIMBBlock,
20
+ parse_aimb_blocks,
21
+ parse_frontmatter,
22
+ extract_manual_blocks,
23
+ has_aimb_blocks,
24
+ get_block_by_id,
25
+ )
26
+
27
+ __all__ = [
28
+ # parser
29
+ "AIMBBlock",
30
+ "parse_aimb_blocks",
31
+ "parse_frontmatter",
32
+ "extract_manual_blocks",
33
+ "has_aimb_blocks",
34
+ "get_block_by_id",
35
+ # hasher
36
+ "compute_block_hash",
37
+ "verify_block_hash",
38
+ "hash_all_blocks",
39
+ "get_stored_hashes",
40
+ "find_changed_blocks",
41
+ # merge
42
+ "MergeDecision",
43
+ "ConflictInfo",
44
+ "decide_block_action",
45
+ "generate_block_diff",
46
+ "format_conflict_report",
47
+ "apply_replace",
48
+ ]
@@ -0,0 +1,157 @@
1
+ """AIMB block hasher — SHA256 computation and integrity checking.
2
+
3
+ Functions
4
+ ---------
5
+ compute_block_hash
6
+ SHA256 hex digest of block content.
7
+ verify_block_hash
8
+ Compare computed hash against an expected value.
9
+ hash_all_blocks
10
+ Compute hashes for every AIMB block in markdown content.
11
+ get_stored_hashes
12
+ Extract the hashes stored in AIMB metadata tags.
13
+ find_changed_blocks
14
+ Detect blocks whose stored hash differs from the current computed hash.
15
+ """
16
+
17
+ from __future__ import annotations
18
+
19
+ import hashlib
20
+ from typing import Any
21
+
22
+ from .parser import parse_aimb_blocks
23
+
24
+
25
+ # ── Helpers ──────────────────────────────────────────────────────────────
26
+
27
+
28
+ def _sha256(content: str) -> str:
29
+ """Return hex-encoded SHA-256 digest of *content*."""
30
+ return hashlib.sha256(content.encode("utf-8")).hexdigest()
31
+
32
+
33
+ # ── Public API ───────────────────────────────────────────────────────────
34
+
35
+
36
+ def compute_block_hash(content: str) -> str:
37
+ """Return the SHA-256 hex digest of *content*.
38
+
39
+ Parameters
40
+ ----------
41
+ content : str
42
+ The raw text content of an AIMB block (text between the opening
43
+ ``<!-- ai-managed ... -->`` and closing ``<!-- /ai-managed -->``
44
+ tags).
45
+
46
+ Returns
47
+ -------
48
+ str
49
+ 64-character hex-encoded SHA-256 digest.
50
+
51
+ Examples
52
+ --------
53
+ >>> compute_block_hash("test")
54
+ "9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08"
55
+ """
56
+ return _sha256(content)
57
+
58
+
59
+ def verify_block_hash(content: str, expected_hash: str) -> bool:
60
+ """Verify that *content* hashes to *expected_hash*.
61
+
62
+ Parameters
63
+ ----------
64
+ content : str
65
+ Raw block content to hash.
66
+ expected_hash : str
67
+ Previously recorded hash to compare against.
68
+
69
+ Returns
70
+ -------
71
+ bool
72
+ ``True`` if the computed hash matches *expected_hash*.
73
+ """
74
+ return compute_block_hash(content) == expected_hash
75
+
76
+
77
+ def hash_all_blocks(content: str) -> dict[str, str]:
78
+ """Compute the hash for every AIMB block in *content*.
79
+
80
+ Hashes only the **content** between the opening and closing tags
81
+ (not the tags themselves).
82
+
83
+ Parameters
84
+ ----------
85
+ content : str
86
+ Full markdown content with AIMB blocks.
87
+
88
+ Returns
89
+ -------
90
+ dict[str, str]
91
+ Mapping of ``{block_id: hash}`` for every AIMB block found.
92
+ Empty dict if no AIMB blocks exist.
93
+ """
94
+ blocks = parse_aimb_blocks(content)
95
+ return {block.id: compute_block_hash(block.content) for block in blocks}
96
+
97
+
98
+ def get_stored_hashes(content: str) -> dict[str, str]:
99
+ """Extract the hashes stored in AIMB block metadata tags.
100
+
101
+ These are the ``hash="..."`` values written into each
102
+ ``<!-- ai-managed ... -->`` opening tag.
103
+
104
+ Parameters
105
+ ----------
106
+ content : str
107
+ Full markdown content with AIMB blocks.
108
+
109
+ Returns
110
+ -------
111
+ dict[str, str]
112
+ Mapping of ``{block_id: stored_hash}``.
113
+ Empty dict if no AIMB blocks exist.
114
+ """
115
+ blocks = parse_aimb_blocks(content)
116
+ return {block.id: block.hash for block in blocks}
117
+
118
+
119
+ def find_changed_blocks(old_content: str, new_content: str) -> list[dict[str, Any]]:
120
+ """Find AIMB blocks whose stored hash differs from their current computed hash.
121
+
122
+ For each AIMB block:
123
+ - The **stored hash** is read from the metadata in *old_content*.
124
+ - The **computed hash** is calculated from the block content in
125
+ *new_content*.
126
+
127
+ Parameters
128
+ ----------
129
+ old_content : str
130
+ Previous version of the markdown content (source of stored hashes).
131
+ new_content : str
132
+ Current version of the markdown content (source of block content to
133
+ hash).
134
+
135
+ Returns
136
+ -------
137
+ list[dict[str, Any]]
138
+ A list of dicts, one per changed block, with keys:
139
+ ``id``, ``old_hash``, ``new_hash``. Empty list if no blocks
140
+ changed or no AIMB blocks exist.
141
+ """
142
+ stored = get_stored_hashes(old_content)
143
+ computed = hash_all_blocks(new_content)
144
+
145
+ changed: list[dict[str, Any]] = []
146
+ for block_id, old_hash in stored.items():
147
+ new_hash = computed.get(block_id)
148
+ if new_hash is not None and old_hash != new_hash:
149
+ changed.append(
150
+ {
151
+ "id": block_id,
152
+ "old_hash": old_hash,
153
+ "new_hash": new_hash,
154
+ }
155
+ )
156
+
157
+ return changed