feat: major improvements — layout, cycles, integrations, usage examples, tests #1
@@ -2,7 +2,6 @@ use clap::{Parser, Subcommand};
|
|||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use archdoc_core::{Config, ProjectModel, scanner::FileScanner, python_analyzer::PythonAnalyzer};
|
use archdoc_core::{Config, ProjectModel, scanner::FileScanner, python_analyzer::PythonAnalyzer};
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::collections::HashSet;
|
|
||||||
|
|
||||||
/// CLI interface for ArchDoc
|
/// CLI interface for ArchDoc
|
||||||
#[derive(Parser)]
|
#[derive(Parser)]
|
||||||
@@ -324,14 +323,14 @@ fn generate_docs(model: &ProjectModel, out: &str) -> Result<()> {
|
|||||||
let output_path = std::path::Path::new(".").join("ARCHITECTURE.md");
|
let output_path = std::path::Path::new(".").join("ARCHITECTURE.md");
|
||||||
|
|
||||||
// Create individual documentation files for modules and files
|
// Create individual documentation files for modules and files
|
||||||
for (module_id, module) in &model.modules {
|
for (module_id, _module) in &model.modules {
|
||||||
let module_doc_path = modules_path.join(format!("{}.md", sanitize_filename(module_id)));
|
let module_doc_path = modules_path.join(format!("{}.md", sanitize_filename(module_id)));
|
||||||
let module_content = format!("# Module: {}\n\nTODO: Add module documentation\n", module_id);
|
let module_content = format!("# Module: {}\n\nTODO: Add module documentation\n", module_id);
|
||||||
std::fs::write(&module_doc_path, module_content)
|
std::fs::write(&module_doc_path, module_content)
|
||||||
.map_err(|e| anyhow::anyhow!("Failed to create module doc {}: {}", module_doc_path.display(), e))?;
|
.map_err(|e| anyhow::anyhow!("Failed to create module doc {}: {}", module_doc_path.display(), e))?;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (file_id, file_doc) in &model.files {
|
for (_file_id, file_doc) in &model.files {
|
||||||
let file_doc_path = files_path.join(format!("{}.md", sanitize_filename(&file_doc.path)));
|
let file_doc_path = files_path.join(format!("{}.md", sanitize_filename(&file_doc.path)));
|
||||||
let file_content = format!("# File: {}\n\nTODO: Add file documentation\n", file_doc.path);
|
let file_content = format!("# File: {}\n\nTODO: Add file documentation\n", file_doc.path);
|
||||||
std::fs::write(&file_doc_path, file_content)
|
std::fs::write(&file_doc_path, file_content)
|
||||||
|
|||||||
@@ -249,7 +249,7 @@ impl Renderer {
|
|||||||
// Collect layout information from files
|
// Collect layout information from files
|
||||||
let mut layout_items = Vec::new();
|
let mut layout_items = Vec::new();
|
||||||
|
|
||||||
for (file_id, file_doc) in &model.files {
|
for (_file_id, file_doc) in &model.files {
|
||||||
layout_items.push(serde_json::json!({
|
layout_items.push(serde_json::json!({
|
||||||
"path": file_doc.path,
|
"path": file_doc.path,
|
||||||
"purpose": "Source file",
|
"purpose": "Source file",
|
||||||
|
|||||||
73
archdoc-core/tests/golden/test_project/ARCHITECTURE.md
Normal file
73
archdoc-core/tests/golden/test_project/ARCHITECTURE.md
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
# ARCHITECTURE — New Project
|
||||||
|
|
||||||
|
<!-- MANUAL:BEGIN -->
|
||||||
|
## Project summary
|
||||||
|
**Name:** New Project
|
||||||
|
**Description:** <FILL_MANUALLY: what this project does in 3–7 lines>
|
||||||
|
|
||||||
|
## Key decisions (manual)
|
||||||
|
- <FILL_MANUALLY>
|
||||||
|
|
||||||
|
## Non-goals (manual)
|
||||||
|
- <FILL_MANUALLY>
|
||||||
|
<!-- MANUAL:END -->
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Document metadata
|
||||||
|
- **Created:** 2026-01-25
|
||||||
|
- **Updated:** 2026-01-25
|
||||||
|
- **Generated by:** archdoc (cli) v0.1
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Rails / Tooling
|
||||||
|
<!-- ARCHDOC:BEGIN section=rails -->
|
||||||
|
|
||||||
|
No tooling information available.
|
||||||
|
<!-- ARCHDOC:END section=rails -->
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Repository layout (top-level)
|
||||||
|
<!-- ARCHDOC:BEGIN section=layout -->
|
||||||
|
|
||||||
|
| Path | Purpose | Link |
|
||||||
|
|------|---------|------|
|
||||||
|
| ./src/advanced_example.py | Source file | [details](docs/architecture/files/._src_advanced_example.py.md) |
|
||||||
|
| ./src/example.py | Source file | [details](docs/architecture/files/._src_example.py.md) |
|
||||||
|
<!-- ARCHDOC:END section=layout -->
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Modules index
|
||||||
|
<!-- ARCHDOC:BEGIN section=modules_index -->
|
||||||
|
|
||||||
|
| Module | Symbols | Inbound | Outbound | Link |
|
||||||
|
|--------|---------|---------|----------|------|
|
||||||
|
| ./src/advanced_example.py | 10 | 0 | 0 | [details](docs/architecture/modules/._src_advanced_example.py.md) |
|
||||||
|
| ./src/example.py | 5 | 0 | 0 | [details](docs/architecture/modules/._src_example.py.md) |
|
||||||
|
<!-- ARCHDOC:END section=modules_index -->
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Critical dependency points
|
||||||
|
<!-- ARCHDOC:BEGIN section=critical_points -->
|
||||||
|
|
||||||
|
### High Fan-in (Most Called)
|
||||||
|
| Symbol | Fan-in | Critical |
|
||||||
|
|--------|--------|----------|
|
||||||
|
|
||||||
|
### High Fan-out (Calls Many)
|
||||||
|
| Symbol | Fan-out | Critical |
|
||||||
|
|--------|---------|----------|
|
||||||
|
|
||||||
|
### Module Cycles
|
||||||
|
<!-- ARCHDOC:END section=critical_points -->
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
<!-- MANUAL:BEGIN -->
|
||||||
|
## Change notes (manual)
|
||||||
|
- <FILL_MANUALLY>
|
||||||
|
<!-- MANUAL:END -->
|
||||||
62
archdoc-core/tests/golden/test_project/archdoc.toml
Normal file
62
archdoc-core/tests/golden/test_project/archdoc.toml
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
[project]
|
||||||
|
root = "."
|
||||||
|
out_dir = "docs/architecture"
|
||||||
|
entry_file = "ARCHITECTURE.md"
|
||||||
|
language = "python"
|
||||||
|
|
||||||
|
[scan]
|
||||||
|
include = ["src", "app", "tests"]
|
||||||
|
exclude = [
|
||||||
|
".venv", "venv", "__pycache__", ".git", "dist", "build",
|
||||||
|
".mypy_cache", ".ruff_cache", ".pytest_cache", "*.egg-info"
|
||||||
|
]
|
||||||
|
follow_symlinks = false
|
||||||
|
max_file_size = "10MB"
|
||||||
|
|
||||||
|
[python]
|
||||||
|
src_roots = ["src", "."]
|
||||||
|
include_tests = true
|
||||||
|
parse_docstrings = true
|
||||||
|
max_parse_errors = 10
|
||||||
|
|
||||||
|
[analysis]
|
||||||
|
resolve_calls = true
|
||||||
|
resolve_inheritance = false
|
||||||
|
detect_integrations = true
|
||||||
|
integration_patterns = [
|
||||||
|
{ type = "http", patterns = ["requests", "httpx", "aiohttp"] },
|
||||||
|
{ type = "db", patterns = ["sqlalchemy", "psycopg", "mysql", "sqlite3"] },
|
||||||
|
{ type = "queue", patterns = ["celery", "kafka", "pika", "redis"] }
|
||||||
|
]
|
||||||
|
|
||||||
|
[output]
|
||||||
|
single_file = false
|
||||||
|
per_file_docs = true
|
||||||
|
create_directories = true
|
||||||
|
overwrite_manual_sections = false
|
||||||
|
|
||||||
|
[diff]
|
||||||
|
update_timestamp_on_change_only = true
|
||||||
|
hash_algorithm = "sha256"
|
||||||
|
preserve_manual_content = true
|
||||||
|
|
||||||
|
[thresholds]
|
||||||
|
critical_fan_in = 20
|
||||||
|
critical_fan_out = 20
|
||||||
|
high_complexity = 50
|
||||||
|
|
||||||
|
[rendering]
|
||||||
|
template_engine = "handlebars"
|
||||||
|
max_table_rows = 100
|
||||||
|
truncate_long_descriptions = true
|
||||||
|
description_max_length = 200
|
||||||
|
|
||||||
|
[logging]
|
||||||
|
level = "info"
|
||||||
|
file = "archdoc.log"
|
||||||
|
format = "compact"
|
||||||
|
|
||||||
|
[caching]
|
||||||
|
enabled = true
|
||||||
|
cache_dir = ".archdoc/cache"
|
||||||
|
max_cache_age = "24h"
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
# File: ./src/advanced_example.py
|
||||||
|
|
||||||
|
TODO: Add file documentation
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
# File: ./src/example.py
|
||||||
|
|
||||||
|
TODO: Add file documentation
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
# Module: ./src/advanced_example.py
|
||||||
|
|
||||||
|
TODO: Add module documentation
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
# Module: ./src/example.py
|
||||||
|
|
||||||
|
TODO: Add module documentation
|
||||||
75
test-project/ARCHITECTURE.md
Normal file
75
test-project/ARCHITECTURE.md
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
# ARCHITECTURE — New Project
|
||||||
|
|
||||||
|
<!-- MANUAL:BEGIN -->
|
||||||
|
## Project summary
|
||||||
|
**Name:** New Project
|
||||||
|
**Description:** <FILL_MANUALLY: what this project does in 3–7 lines>
|
||||||
|
|
||||||
|
## Key decisions (manual)
|
||||||
|
- <FILL_MANUALLY>
|
||||||
|
|
||||||
|
## Non-goals (manual)
|
||||||
|
- <FILL_MANUALLY>
|
||||||
|
<!-- MANUAL:END -->
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Document metadata
|
||||||
|
- **Created:** 2026-01-25
|
||||||
|
- **Updated:** 2026-01-25
|
||||||
|
- **Generated by:** archdoc (cli) v0.1
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Rails / Tooling
|
||||||
|
<!-- ARCHDOC:BEGIN section=rails -->
|
||||||
|
|
||||||
|
No tooling information available.
|
||||||
|
<!-- ARCHDOC:END section=rails -->
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Repository layout (top-level)
|
||||||
|
<!-- ARCHDOC:BEGIN section=layout -->
|
||||||
|
|
||||||
|
| Path | Purpose | Link |
|
||||||
|
|------|---------|------|
|
||||||
|
| ./src/core.py | Source file | [details](docs/architecture/files/._src_core.py.md) |
|
||||||
|
| ./src/__init__.py | Source file | [details](docs/architecture/files/._src___init__.py.md) |
|
||||||
|
| ./src/utils.py | Source file | [details](docs/architecture/files/._src_utils.py.md) |
|
||||||
|
<!-- ARCHDOC:END section=layout -->
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Modules index
|
||||||
|
<!-- ARCHDOC:BEGIN section=modules_index -->
|
||||||
|
|
||||||
|
| Module | Symbols | Inbound | Outbound | Link |
|
||||||
|
|--------|---------|---------|----------|------|
|
||||||
|
| ./src/__init__.py | 0 | 0 | 0 | [details](docs/architecture/modules/._src___init__.py.md) |
|
||||||
|
| ./src/core.py | 6 | 0 | 0 | [details](docs/architecture/modules/._src_core.py.md) |
|
||||||
|
| ./src/utils.py | 4 | 0 | 0 | [details](docs/architecture/modules/._src_utils.py.md) |
|
||||||
|
<!-- ARCHDOC:END section=modules_index -->
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Critical dependency points
|
||||||
|
<!-- ARCHDOC:BEGIN section=critical_points -->
|
||||||
|
|
||||||
|
### High Fan-in (Most Called)
|
||||||
|
| Symbol | Fan-in | Critical |
|
||||||
|
|--------|--------|----------|
|
||||||
|
|
||||||
|
### High Fan-out (Calls Many)
|
||||||
|
| Symbol | Fan-out | Critical |
|
||||||
|
|--------|---------|----------|
|
||||||
|
|
||||||
|
### Module Cycles
|
||||||
|
<!-- ARCHDOC:END section=critical_points -->
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
<!-- MANUAL:BEGIN -->
|
||||||
|
## Change notes (manual)
|
||||||
|
- <FILL_MANUALLY>
|
||||||
|
<!-- MANUAL:END -->
|
||||||
62
test-project/archdoc.toml
Normal file
62
test-project/archdoc.toml
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
[project]
|
||||||
|
root = "."
|
||||||
|
out_dir = "docs/architecture"
|
||||||
|
entry_file = "ARCHITECTURE.md"
|
||||||
|
language = "python"
|
||||||
|
|
||||||
|
[scan]
|
||||||
|
include = ["src", "app", "tests"]
|
||||||
|
exclude = [
|
||||||
|
".venv", "venv", "__pycache__", ".git", "dist", "build",
|
||||||
|
".mypy_cache", ".ruff_cache", ".pytest_cache", "*.egg-info"
|
||||||
|
]
|
||||||
|
follow_symlinks = false
|
||||||
|
max_file_size = "10MB"
|
||||||
|
|
||||||
|
[python]
|
||||||
|
src_roots = ["src", "."]
|
||||||
|
include_tests = true
|
||||||
|
parse_docstrings = true
|
||||||
|
max_parse_errors = 10
|
||||||
|
|
||||||
|
[analysis]
|
||||||
|
resolve_calls = true
|
||||||
|
resolve_inheritance = false
|
||||||
|
detect_integrations = true
|
||||||
|
integration_patterns = [
|
||||||
|
{ type = "http", patterns = ["requests", "httpx", "aiohttp"] },
|
||||||
|
{ type = "db", patterns = ["sqlalchemy", "psycopg", "mysql", "sqlite3"] },
|
||||||
|
{ type = "queue", patterns = ["celery", "kafka", "pika", "redis"] }
|
||||||
|
]
|
||||||
|
|
||||||
|
[output]
|
||||||
|
single_file = false
|
||||||
|
per_file_docs = true
|
||||||
|
create_directories = true
|
||||||
|
overwrite_manual_sections = false
|
||||||
|
|
||||||
|
[diff]
|
||||||
|
update_timestamp_on_change_only = true
|
||||||
|
hash_algorithm = "sha256"
|
||||||
|
preserve_manual_content = true
|
||||||
|
|
||||||
|
[thresholds]
|
||||||
|
critical_fan_in = 20
|
||||||
|
critical_fan_out = 20
|
||||||
|
high_complexity = 50
|
||||||
|
|
||||||
|
[rendering]
|
||||||
|
template_engine = "handlebars"
|
||||||
|
max_table_rows = 100
|
||||||
|
truncate_long_descriptions = true
|
||||||
|
description_max_length = 200
|
||||||
|
|
||||||
|
[logging]
|
||||||
|
level = "info"
|
||||||
|
file = "archdoc.log"
|
||||||
|
format = "compact"
|
||||||
|
|
||||||
|
[caching]
|
||||||
|
enabled = true
|
||||||
|
cache_dir = ".archdoc/cache"
|
||||||
|
max_cache_age = "24h"
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
# File: ./src/__init__.py
|
||||||
|
|
||||||
|
TODO: Add file documentation
|
||||||
3
test-project/docs/architecture/files/._src_core.py.md
Normal file
3
test-project/docs/architecture/files/._src_core.py.md
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
# File: ./src/core.py
|
||||||
|
|
||||||
|
TODO: Add file documentation
|
||||||
3
test-project/docs/architecture/files/._src_utils.py.md
Normal file
3
test-project/docs/architecture/files/._src_utils.py.md
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
# File: ./src/utils.py
|
||||||
|
|
||||||
|
TODO: Add file documentation
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
# Module: ./src/__init__.py
|
||||||
|
|
||||||
|
TODO: Add module documentation
|
||||||
3
test-project/docs/architecture/modules/._src_core.py.md
Normal file
3
test-project/docs/architecture/modules/._src_core.py.md
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
# Module: ./src/core.py
|
||||||
|
|
||||||
|
TODO: Add module documentation
|
||||||
3
test-project/docs/architecture/modules/._src_utils.py.md
Normal file
3
test-project/docs/architecture/modules/._src_utils.py.md
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
# Module: ./src/utils.py
|
||||||
|
|
||||||
|
TODO: Add module documentation
|
||||||
Reference in New Issue
Block a user