From 0184f40a2bd480254aa442768532571039dfeb6a Mon Sep 17 00:00:00 2001 From: Tristen Pierson Date: Thu, 2 Apr 2026 15:36:06 -0400 Subject: [PATCH] fix: import sorting and formatting to pass CI lint checks Ruff check + format now run against src/ AND tests/ matching CI config. Co-Authored-By: Oz --- src/specsmith/auditor.py | 15 ++++++++------ src/specsmith/cli.py | 9 +++++---- src/specsmith/credit_analyzer.py | 6 ++---- src/specsmith/credits.py | 14 +++++++------ src/specsmith/importer.py | 30 +++++++++++++++++++++------- src/specsmith/scaffolder.py | 4 +--- src/specsmith/session.py | 3 +-- src/specsmith/updater.py | 7 +++++-- tests/sandbox/test_sandbox_import.py | 9 +++------ tests/sandbox/test_sandbox_new.py | 1 + tests/sandbox/test_sandbox_types.py | 1 + tests/test_auditor.py | 1 + tests/test_cli.py | 1 + tests/test_integrations.py | 1 + tests/test_scaffolder.py | 1 + tests/test_smoke.py | 3 +-- tests/test_vcs.py | 1 + 17 files changed, 65 insertions(+), 42 deletions(-) diff --git a/src/specsmith/auditor.py b/src/specsmith/auditor.py index 25a9339..2791356 100644 --- a/src/specsmith/auditor.py +++ b/src/specsmith/auditor.py @@ -125,10 +125,14 @@ def check_governance_files(root: Path) -> list[AuditResult]: found = path.exists() # For architecture.md, also search subdirectories (e.g. docs/architecture/*.md) if not found and "architecture" in f: - found = bool( - list((root / "docs").glob("**/architecture*")) - + list((root / "docs").glob("**/ARCHITECTURE*")) - ) if (root / "docs").is_dir() else False + found = ( + bool( + list((root / "docs").glob("**/architecture*")) + + list((root / "docs").glob("**/ARCHITECTURE*")) + ) + if (root / "docs").is_dir() + else False + ) results.append( AuditResult( name=f"recommended:{f}", @@ -580,8 +584,7 @@ def run_auto_fix(root: Path, report: AuditReport) -> list[str]: path = root / "docs" / "ARCHITECTURE.md" path.parent.mkdir(parents=True, exist_ok=True) path.write_text( - f"# Architecture — {root.name}\n\n" - "[Run `specsmith architect` to populate]\n", + f"# Architecture — {root.name}\n\n[Run `specsmith architect` to populate]\n", encoding="utf-8", ) fixed.append("Created stub docs/ARCHITECTURE.md") diff --git a/src/specsmith/cli.py b/src/specsmith/cli.py index e2af9a1..335d01e 100644 --- a/src/specsmith/cli.py +++ b/src/specsmith/cli.py @@ -703,9 +703,7 @@ def architect(project_dir: str, non_interactive: bool) -> None: f" [yellow]Note:[/yellow] Existing docs at {', '.join(existing)} " "are referenced but not merged. Review manually." ) - console.print( - " [dim]Run \"specsmith audit --project-dir .\" to verify governance health.[/dim]" - ) + console.print(' [dim]Run "specsmith audit --project-dir ." to verify governance health.[/dim]') # --------------------------------------------------------------------------- @@ -1463,7 +1461,10 @@ def credits_analyze(project_dir: str) -> None: "--watermarks", default=None, help="Comma-separated USD watermark alerts (e.g. 5,10,25,50)." ) def credits_budget( - project_dir: str, cap: float | None, alert_pct: int | None, watermarks: str | None, + project_dir: str, + cap: float | None, + alert_pct: int | None, + watermarks: str | None, ) -> None: """View or set credit budget and alert thresholds.""" from specsmith.credits import load_budget, save_budget diff --git a/src/specsmith/credit_analyzer.py b/src/specsmith/credit_analyzer.py index 4a56ff3..b8e0b70 100644 --- a/src/specsmith/credit_analyzer.py +++ b/src/specsmith/credit_analyzer.py @@ -43,8 +43,7 @@ def analyze_spend(root: Path) -> AnalysisReport: severity="info", message="No credit data yet.", recommendation=( - "Record usage with `specsmith credits record` " - "or integrate with your AI agent." + "Record usage with `specsmith credits record` or integrate with your AI agent." ), ) ) @@ -112,8 +111,7 @@ def analyze_spend(root: Path) -> AnalysisReport: category="governance", severity="info", message=( - f"Governance files total {total_gov_lines} lines " - f"across {len(gov_files)} files." + f"Governance files total {total_gov_lines} lines across {len(gov_files)} files." ), recommendation=( "Ensure agents lazy-load governance files. Only rules.md + workflow.md " diff --git a/src/specsmith/credits.py b/src/specsmith/credits.py index 08f8c75..3d07330 100644 --- a/src/specsmith/credits.py +++ b/src/specsmith/credits.py @@ -167,9 +167,9 @@ def record_usage( provider=provider, tokens_in=tokens_in, tokens_out=tokens_out, - estimated_cost_usd=cost_usd if cost_usd is not None else estimate_cost( - model, tokens_in, tokens_out - ), + estimated_cost_usd=cost_usd + if cost_usd is not None + else estimate_cost(model, tokens_in, tokens_out), task=task, duration_seconds=duration_seconds, ) @@ -180,7 +180,10 @@ def record_usage( def get_summary( - root: Path, *, since: str = "", month: str = "", + root: Path, + *, + since: str = "", + month: str = "", ) -> CreditSummary: """Get aggregate credit summary with budget alerts.""" entries = _load_entries(root) @@ -222,8 +225,7 @@ def get_summary( pct = (month_cost / budget.monthly_cap_usd) * 100 if budget.monthly_cap_usd else 0 if pct >= 100: summary.alerts.append( - f"BUDGET EXCEEDED: ${month_cost:.2f} / ${budget.monthly_cap_usd:.2f} " - f"({pct:.0f}%)" + f"BUDGET EXCEEDED: ${month_cost:.2f} / ${budget.monthly_cap_usd:.2f} ({pct:.0f}%)" ) elif pct >= budget.alert_threshold_pct: summary.alerts.append( diff --git a/src/specsmith/importer.py b/src/specsmith/importer.py index d6c4630..213d54d 100644 --- a/src/specsmith/importer.py +++ b/src/specsmith/importer.py @@ -790,15 +790,31 @@ def _extract_governance_sections(root: Path) -> dict[str, str]: # Body-level content keywords for secondary classification. # Used when heading doesn't match — scan body text for strong signals. _BODY_ARCHITECTURE_KW = [ - "register map", "address offset", "0x0", "register name", - "block diagram", "data flow", "interface spec", - "directory layout", "src/", "repository structure", - "milestone", "roadmap", "completion", "phase 2 target", + "register map", + "address offset", + "0x0", + "register name", + "block diagram", + "data flow", + "interface spec", + "directory layout", + "src/", + "repository structure", + "milestone", + "roadmap", + "completion", + "phase 2 target", ] _BODY_DRIFT_KW = [ - "subst v:", "path-length", "one-time setup", "per-machine", - "environment variable", "install once", "bootstrap", - "windows path", "ntfs", + "subst v:", + "path-length", + "one-time setup", + "per-machine", + "environment variable", + "install once", + "bootstrap", + "windows path", + "ntfs", ] for heading, body in sections.items(): diff --git a/src/specsmith/scaffolder.py b/src/specsmith/scaffolder.py index 428af3e..0afb236 100644 --- a/src/specsmith/scaffolder.py +++ b/src/specsmith/scaffolder.py @@ -406,9 +406,7 @@ def _build_community_files(config: ProjectConfig) -> list[tuple[str, str]]: files.append(("community/code_of_conduct.md.j2", "CODE_OF_CONDUCT.md")) if "pr-template" in cf and config.vcs_platform == "github": - files.append( - ("community/pull_request_template.md.j2", ".github/PULL_REQUEST_TEMPLATE.md") - ) + files.append(("community/pull_request_template.md.j2", ".github/PULL_REQUEST_TEMPLATE.md")) if "issue-templates" in cf and config.vcs_platform == "github": files.extend( diff --git a/src/specsmith/session.py b/src/specsmith/session.py index 5b72d73..ca88648 100644 --- a/src/specsmith/session.py +++ b/src/specsmith/session.py @@ -138,8 +138,7 @@ def run_session_end(root: Path) -> SessionReport: name="credits", status="ok", message=( - f"Credits: ${cs.total_cost_usd:.4f} total, " - f"{cs.session_count} session(s)" + f"Credits: ${cs.total_cost_usd:.4f} total, {cs.session_count} session(s)" ), ) ) diff --git a/src/specsmith/updater.py b/src/specsmith/updater.py index 9ca0851..48877fd 100644 --- a/src/specsmith/updater.py +++ b/src/specsmith/updater.py @@ -19,7 +19,8 @@ def get_update_channel() -> str: def check_latest_version( - *, channel: str = "", + *, + channel: str = "", ) -> tuple[str, str, str]: """Check PyPI for the latest specsmith version. @@ -60,7 +61,9 @@ def is_outdated() -> bool: def run_self_update( - *, channel: str = "", target_version: str = "", + *, + channel: str = "", + target_version: str = "", ) -> tuple[bool, str]: """Update specsmith via pip. diff --git a/tests/sandbox/test_sandbox_import.py b/tests/sandbox/test_sandbox_import.py index f55cf07..4440f6a 100644 --- a/tests/sandbox/test_sandbox_import.py +++ b/tests/sandbox/test_sandbox_import.py @@ -13,6 +13,7 @@ import yaml from click.testing import CliRunner + from specsmith.cli import main @@ -337,14 +338,10 @@ def test_import_force_overwrites_existing_docs(self, tmp_path: Path) -> None: docs = root / "docs" docs.mkdir(exist_ok=True) - (docs / "REQUIREMENTS.md").write_text( - "# Existing Requirements\n", encoding="utf-8" - ) + (docs / "REQUIREMENTS.md").write_text("# Existing Requirements\n", encoding="utf-8") runner = CliRunner() - result = runner.invoke( - main, ["import", "--project-dir", str(root), "--force"], input="y\n" - ) + result = runner.invoke(main, ["import", "--project-dir", str(root), "--force"], input="y\n") assert result.exit_code == 0 reqs = (docs / "REQUIREMENTS.md").read_text(encoding="utf-8") diff --git a/tests/sandbox/test_sandbox_new.py b/tests/sandbox/test_sandbox_new.py index fea335c..2cb9217 100644 --- a/tests/sandbox/test_sandbox_new.py +++ b/tests/sandbox/test_sandbox_new.py @@ -12,6 +12,7 @@ import yaml from click.testing import CliRunner + from specsmith.cli import main diff --git a/tests/sandbox/test_sandbox_types.py b/tests/sandbox/test_sandbox_types.py index 33bb27e..405038d 100644 --- a/tests/sandbox/test_sandbox_types.py +++ b/tests/sandbox/test_sandbox_types.py @@ -8,6 +8,7 @@ import yaml from click.testing import CliRunner + from specsmith.cli import main diff --git a/tests/test_auditor.py b/tests/test_auditor.py index 4786cd6..f19d4b5 100644 --- a/tests/test_auditor.py +++ b/tests/test_auditor.py @@ -7,6 +7,7 @@ from pathlib import Path import pytest + from specsmith.auditor import run_audit diff --git a/tests/test_cli.py b/tests/test_cli.py index 4cb9abe..f20b803 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -8,6 +8,7 @@ import yaml from click.testing import CliRunner + from specsmith.cli import main from specsmith.config import ProjectConfig, ProjectType from specsmith.scaffolder import scaffold_project diff --git a/tests/test_integrations.py b/tests/test_integrations.py index 864c34e..8acb509 100644 --- a/tests/test_integrations.py +++ b/tests/test_integrations.py @@ -7,6 +7,7 @@ from pathlib import Path import pytest + from specsmith.config import ProjectConfig, ProjectType from specsmith.integrations import get_adapter, list_adapters from specsmith.integrations.claude_code import ClaudeCodeAdapter diff --git a/tests/test_scaffolder.py b/tests/test_scaffolder.py index e7b5d8f..4096e29 100644 --- a/tests/test_scaffolder.py +++ b/tests/test_scaffolder.py @@ -7,6 +7,7 @@ from pathlib import Path import pytest + from specsmith.config import Platform, ProjectConfig, ProjectType from specsmith.scaffolder import scaffold_project diff --git a/tests/test_smoke.py b/tests/test_smoke.py index 65e1257..3c3b67c 100644 --- a/tests/test_smoke.py +++ b/tests/test_smoke.py @@ -4,9 +4,8 @@ from importlib.metadata import version as _pkg_version -from specsmith.config import Platform, ProjectConfig, ProjectType - from specsmith import __version__ +from specsmith.config import Platform, ProjectConfig, ProjectType def test_version(): diff --git a/tests/test_vcs.py b/tests/test_vcs.py index f2a94f8..99135ef 100644 --- a/tests/test_vcs.py +++ b/tests/test_vcs.py @@ -7,6 +7,7 @@ from pathlib import Path import pytest + from specsmith.config import Platform, ProjectConfig, ProjectType from specsmith.vcs import get_platform, list_platforms from specsmith.vcs.base import CommandResult