sumd 0.3.5__tar.gz → 0.3.7__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.
- {sumd-0.3.5 → sumd-0.3.7}/CHANGELOG.md +13 -0
- {sumd-0.3.5 → sumd-0.3.7}/PKG-INFO +6 -6
- {sumd-0.3.5 → sumd-0.3.7}/README.md +5 -5
- {sumd-0.3.5 → sumd-0.3.7}/pyproject.toml +1 -1
- {sumd-0.3.5 → sumd-0.3.7}/sumd/__init__.py +1 -1
- {sumd-0.3.5 → sumd-0.3.7}/sumd/cli.py +32 -24
- {sumd-0.3.5 → sumd-0.3.7}/.gitignore +0 -0
- {sumd-0.3.5 → sumd-0.3.7}/LICENSE +0 -0
- {sumd-0.3.5 → sumd-0.3.7}/sumd/extractor.py +0 -0
- {sumd-0.3.5 → sumd-0.3.7}/sumd/generator.py +0 -0
- {sumd-0.3.5 → sumd-0.3.7}/sumd/mcp_server.py +0 -0
- {sumd-0.3.5 → sumd-0.3.7}/sumd/parser.py +0 -0
- {sumd-0.3.5 → sumd-0.3.7}/sumd/pipeline.py +0 -0
- {sumd-0.3.5 → sumd-0.3.7}/sumd/renderer.py +0 -0
- {sumd-0.3.5 → sumd-0.3.7}/sumd/sections/__init__.py +0 -0
- {sumd-0.3.5 → sumd-0.3.7}/sumd/sections/api_stubs.py +0 -0
- {sumd-0.3.5 → sumd-0.3.7}/sumd/sections/architecture.py +0 -0
- {sumd-0.3.5 → sumd-0.3.7}/sumd/sections/base.py +0 -0
- {sumd-0.3.5 → sumd-0.3.7}/sumd/sections/call_graph.py +0 -0
- {sumd-0.3.5 → sumd-0.3.7}/sumd/sections/code_analysis.py +0 -0
- {sumd-0.3.5 → sumd-0.3.7}/sumd/sections/configuration.py +0 -0
- {sumd-0.3.5 → sumd-0.3.7}/sumd/sections/dependencies.py +0 -0
- {sumd-0.3.5 → sumd-0.3.7}/sumd/sections/deployment.py +0 -0
- {sumd-0.3.5 → sumd-0.3.7}/sumd/sections/environment.py +0 -0
- {sumd-0.3.5 → sumd-0.3.7}/sumd/sections/extras.py +0 -0
- {sumd-0.3.5 → sumd-0.3.7}/sumd/sections/interfaces.py +0 -0
- {sumd-0.3.5 → sumd-0.3.7}/sumd/sections/metadata.py +0 -0
- {sumd-0.3.5 → sumd-0.3.7}/sumd/sections/quality.py +0 -0
- {sumd-0.3.5 → sumd-0.3.7}/sumd/sections/refactor_analysis.py +0 -0
- {sumd-0.3.5 → sumd-0.3.7}/sumd/sections/source_snippets.py +0 -0
- {sumd-0.3.5 → sumd-0.3.7}/sumd/sections/test_contracts.py +0 -0
- {sumd-0.3.5 → sumd-0.3.7}/sumd/sections/workflows.py +0 -0
- {sumd-0.3.5 → sumd-0.3.7}/sumd/toon_parser.py +0 -0
|
@@ -7,6 +7,19 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.3.7] - 2026-04-19
|
|
11
|
+
|
|
12
|
+
### Docs
|
|
13
|
+
- Update README.md
|
|
14
|
+
|
|
15
|
+
## [0.3.6] - 2026-04-19
|
|
16
|
+
|
|
17
|
+
### Docs
|
|
18
|
+
- Update README.md
|
|
19
|
+
|
|
20
|
+
### Other
|
|
21
|
+
- Update sumd/cli.py
|
|
22
|
+
|
|
10
23
|
## [0.3.5] - 2026-04-19
|
|
11
24
|
|
|
12
25
|
### Docs
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: sumd
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.7
|
|
4
4
|
Summary: SUMD - Structured Unified Markdown Descriptor for AI-aware project documentation
|
|
5
5
|
Project-URL: Homepage, https://github.com/tom/statement
|
|
6
6
|
Project-URL: Repository, https://github.com/tom/statement
|
|
@@ -41,17 +41,17 @@ Description-Content-Type: text/markdown
|
|
|
41
41
|
|
|
42
42
|
## AI Cost Tracking
|
|
43
43
|
|
|
44
|
-
    
|
|
45
|
+
  
|
|
46
46
|
|
|
47
|
-
- 🤖 **LLM usage:** $5.
|
|
48
|
-
- 👤 **Human dev:** ~$
|
|
47
|
+
- 🤖 **LLM usage:** $5.5500 (37 commits)
|
|
48
|
+
- 👤 **Human dev:** ~$1306 (13.1h @ $100/h, 30min dedup)
|
|
49
49
|
|
|
50
50
|
Generated on 2026-04-19 using [openrouter/qwen/qwen3-coder-next](https://openrouter.ai/qwen/qwen3-coder-next)
|
|
51
51
|
|
|
52
52
|
---
|
|
53
53
|
|
|
54
|
-
  
|
|
55
55
|
|
|
56
56
|
**SUMD** (Structured Unified Markdown Descriptor) is a semantic project descriptor format in Markdown.
|
|
57
57
|
It defines intent, structure, execution entry points, and the mental model of a system for both humans and LLMs.
|
|
@@ -3,17 +3,17 @@
|
|
|
3
3
|
|
|
4
4
|
## AI Cost Tracking
|
|
5
5
|
|
|
6
|
-
    
|
|
7
|
+
  
|
|
8
8
|
|
|
9
|
-
- 🤖 **LLM usage:** $5.
|
|
10
|
-
- 👤 **Human dev:** ~$
|
|
9
|
+
- 🤖 **LLM usage:** $5.5500 (37 commits)
|
|
10
|
+
- 👤 **Human dev:** ~$1306 (13.1h @ $100/h, 30min dedup)
|
|
11
11
|
|
|
12
12
|
Generated on 2026-04-19 using [openrouter/qwen/qwen3-coder-next](https://openrouter.ai/qwen/qwen3-coder-next)
|
|
13
13
|
|
|
14
14
|
---
|
|
15
15
|
|
|
16
|
-
  
|
|
17
17
|
|
|
18
18
|
**SUMD** (Structured Unified Markdown Descriptor) is a semantic project descriptor format in Markdown.
|
|
19
19
|
It defines intent, structure, execution entry points, and the mental model of a system for both humans and LLMs.
|
|
@@ -4,7 +4,7 @@ SUMD is a semantic project descriptor format in Markdown that defines intent,
|
|
|
4
4
|
structure, execution entry points, and mental model of a system for both humans and LLMs.
|
|
5
5
|
"""
|
|
6
6
|
|
|
7
|
-
__version__ = "0.3.
|
|
7
|
+
__version__ = "0.3.7"
|
|
8
8
|
|
|
9
9
|
from sumd.parser import (
|
|
10
10
|
SUMDDocument,
|
|
@@ -223,29 +223,32 @@ _SKIP_DIRS = {
|
|
|
223
223
|
}
|
|
224
224
|
|
|
225
225
|
|
|
226
|
+
def _walk_projects(
|
|
227
|
+
path: Path, projects: list[Path], max_depth: int | None, depth: int
|
|
228
|
+
) -> None:
|
|
229
|
+
"""Recursively collect project directories (containing pyproject.toml)."""
|
|
230
|
+
if max_depth is not None and depth > max_depth:
|
|
231
|
+
return
|
|
232
|
+
try:
|
|
233
|
+
entries = sorted(path.iterdir(), key=lambda p: p.name)
|
|
234
|
+
except PermissionError:
|
|
235
|
+
return
|
|
236
|
+
for d in entries:
|
|
237
|
+
if not d.is_dir() or d.name.startswith(".") or d.name in _SKIP_DIRS:
|
|
238
|
+
continue
|
|
239
|
+
try:
|
|
240
|
+
if (d / "pyproject.toml").exists():
|
|
241
|
+
projects.append(d)
|
|
242
|
+
else:
|
|
243
|
+
_walk_projects(d, projects, max_depth, depth + 1)
|
|
244
|
+
except PermissionError:
|
|
245
|
+
continue
|
|
246
|
+
|
|
247
|
+
|
|
226
248
|
def _detect_projects(workspace: Path, max_depth: int | None = None) -> list[Path]:
|
|
227
249
|
"""Return sorted list of subdirectories containing pyproject.toml (recursive)."""
|
|
228
250
|
projects: list[Path] = []
|
|
229
|
-
|
|
230
|
-
def _walk(path: Path, depth: int) -> None:
|
|
231
|
-
if max_depth is not None and depth > max_depth:
|
|
232
|
-
return
|
|
233
|
-
try:
|
|
234
|
-
entries = sorted(path.iterdir(), key=lambda p: p.name)
|
|
235
|
-
except PermissionError:
|
|
236
|
-
return
|
|
237
|
-
for d in entries:
|
|
238
|
-
if not d.is_dir() or d.name.startswith(".") or d.name in _SKIP_DIRS:
|
|
239
|
-
continue
|
|
240
|
-
try:
|
|
241
|
-
if (d / "pyproject.toml").exists():
|
|
242
|
-
projects.append(d)
|
|
243
|
-
else:
|
|
244
|
-
_walk(d, depth + 1)
|
|
245
|
-
except PermissionError:
|
|
246
|
-
continue
|
|
247
|
-
|
|
248
|
-
_walk(workspace, 0)
|
|
251
|
+
_walk_projects(workspace, projects, max_depth, 0)
|
|
249
252
|
return projects
|
|
250
253
|
|
|
251
254
|
|
|
@@ -356,6 +359,14 @@ def _render_write_validate(
|
|
|
356
359
|
return doc, md_issues, cb_errors, cb_warnings, sources
|
|
357
360
|
|
|
358
361
|
|
|
362
|
+
def _echo_scan_result(proj_dir: Path, doc, sources: list, cb_warnings: list) -> None:
|
|
363
|
+
"""Print success line for a scanned project."""
|
|
364
|
+
warn_str = f" \u26a0 {len(cb_warnings)} warnings" if cb_warnings else ""
|
|
365
|
+
click.echo(
|
|
366
|
+
f" \u2705 {proj_dir.name:<18} {'ok':<10} {len(doc.sections):<10} {', '.join(sources)}{warn_str}"
|
|
367
|
+
)
|
|
368
|
+
|
|
369
|
+
|
|
359
370
|
def _scan_one_project(
|
|
360
371
|
proj_dir: Path,
|
|
361
372
|
fix: bool,
|
|
@@ -391,10 +402,7 @@ def _scan_one_project(
|
|
|
391
402
|
click.echo(f" \u2193 {e}")
|
|
392
403
|
return {"status": "INVALID", "errors": all_errors, "path": str(sumd_path)}
|
|
393
404
|
|
|
394
|
-
|
|
395
|
-
click.echo(
|
|
396
|
-
f" \u2705 {proj_dir.name:<18} {'ok':<10} {len(doc.sections):<10} {', '.join(sources)}{warn_str}"
|
|
397
|
-
)
|
|
405
|
+
_echo_scan_result(proj_dir, doc, sources, cb_warnings)
|
|
398
406
|
|
|
399
407
|
if export_json:
|
|
400
408
|
_export_sumd_json(proj_dir, doc)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|