Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/copilot_usage/docs/architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ Monorepo containing Python CLI utilities that share tooling, CI, and common depe
| `report.py` | Rich-formatted terminal output — summary tables (with Model Calls and User Msgs columns), live view, premium request breakdown. Shows raw counts and `~`-prefixed premium cost estimates for live/active sessions; historical post-shutdown views display exact API-provided numbers. |
| `render_detail.py` | Session detail rendering — extracted from report.py. Displays event timeline, per-event metadata, and session-level aggregates. |
| `_formatting.py` | Shared formatting utilities — `format_duration()` and `format_tokens()` with doctest-verified examples. Used by report.py and render_detail.py. |
| `_fs_utils.py` | Shared filesystem/caching utilities — `lru_insert` (LRU eviction for module-level `OrderedDict` caches) and `safe_file_identity` (returns `(mtime_ns, size)` for robust cache-invalidation; returns `None` on any `OSError`). Used by `parser.py` and `vscode_parser.py`. |
| `pricing.py` | Model pricing registry — multiplier lookup, tier categorization. Multipliers are used for `~`-prefixed cost estimates in live/active views (`render_live_sessions`, `render_cost_view`); historical post-shutdown views use exact API-provided numbers exclusively. |
| `logging_config.py` | Loguru setup — stderr warnings only, no file output. Uses a `_PatcherRecord` TypedDict to type-check the emoji-injection patcher without importing the unresolvable `loguru.Record` type at runtime. Called once from CLI entry point. |
| `vscode_parser.py` | VS Code Copilot Chat log parser — discovers log files per platform (macOS/Windows/Linux), parses `ccreq:` lines with regex, aggregates into `VSCodeLogSummary`. |
Expand Down
26 changes: 26 additions & 0 deletions tests/test_docs.py
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,32 @@ def test_since_last_shutdown_documents_premium_cost_estimate() -> None:
)


def test_components_table_lists_all_modules() -> None:
"""Every .py module in src/copilot_usage/ (excluding __init__.py and the
docs/ subdirectory) must appear in the ### Components table in
architecture.md."""
pkg_dir = Path(__file__).parents[1] / "src" / "copilot_usage"
on_disk = {p.name for p in pkg_dir.glob("*.py") if p.name != "__init__.py"}
components_section_match = re.search(
r"^###\s+Components\b.*?(?=^#{1,6}\s+|\Z)",
_ARCH_MD,
re.MULTILINE | re.DOTALL,
)
assert components_section_match, (
"Could not find the '### Components' section in architecture.md"
)
components_section = components_section_match.group(0)
# Extract backtick-quoted module names from rows in the Components table only.
in_table = set(
re.findall(r"^\|\s*`([^`]+\.py)`\s*\|", components_section, re.MULTILINE)
)
missing = on_disk - in_table
assert not missing, (
f"Modules missing from the ### Components table in "
f"architecture.md: {sorted(missing)}"
)


def test_architecture_detect_resume_lists_all_indicators() -> None:
"""The _detect_resume() description in architecture.md must mention the
three true resume indicators and the separately-tracked turn_start event."""
Expand Down
Loading