From 95a2d1a254c092532aba7baefb7e7db185e19d47 Mon Sep 17 00:00:00 2001 From: AIOSAI Date: Mon, 15 Jun 2026 19:33:07 -0700 Subject: [PATCH] fix(seedgo): skip *(disabled) files in audits like .archive/ dirs (td-103) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Disabled files (AIPass convention: rename name(disabled).py instead of delete) are intentionally-parked inert code, but seedgo audited them as live source — ai_mail's dashboard_sync(disabled).py dragged it to 99%, blocking green CI. - Add is_disabled_file() + DISABLED_FILE_MARKER to skip_dirs.py (single source of truth alongside SOURCE_SKIP_DIRS) - Apply in branch_audit, dead_code, unused_function, test_quality checkers + test_map function_scanner + checklist directory mode - New test in test_coverage_audit.py Verified: ai_mail 99->100%, seedgo self-audit 100%, 1060 seedgo tests pass, @cli/@flow unchanged at 100%. Co-Authored-By: Claude Opus 4.8 (1M context) --- .../aipass_standards/dead_code_check.py | 6 ++-- .../handlers/aipass_standards/skip_dirs.py | 8 +++++ .../aipass_standards/test_quality_check.py | 29 +++++++++++++++---- .../aipass_standards/unused_function_check.py | 6 ++-- .../apps/handlers/audit/branch_audit.py | 3 +- .../handlers/test_map/function_scanner.py | 2 ++ src/aipass/seedgo/apps/modules/checklist.py | 5 ++-- .../seedgo/tests/test_coverage_audit.py | 15 ++++++++++ 8 files changed, 60 insertions(+), 14 deletions(-) diff --git a/src/aipass/seedgo/apps/handlers/aipass_standards/dead_code_check.py b/src/aipass/seedgo/apps/handlers/aipass_standards/dead_code_check.py index f8b95016..2416e841 100644 --- a/src/aipass/seedgo/apps/handlers/aipass_standards/dead_code_check.py +++ b/src/aipass/seedgo/apps/handlers/aipass_standards/dead_code_check.py @@ -24,7 +24,7 @@ from pathlib import Path from aipass.prax import logger from aipass.seedgo.apps.handlers.json import json_handler from aipass.seedgo.apps.handlers.bypass.utils import is_bypassed -from aipass.seedgo.apps.handlers.aipass_standards.skip_dirs import SOURCE_SKIP_DIRS +from aipass.seedgo.apps.handlers.aipass_standards.skip_dirs import SOURCE_SKIP_DIRS, is_disabled_file AUDIT_SCOPE = "branch_level" @@ -43,8 +43,8 @@ _SKIP_DIRS = SOURCE_SKIP_DIRS | {"tests", "json_templates"} def _should_skip(path: Path) -> bool: - """Check whether any parent directory component is in the skip set.""" - return any(part in _SKIP_DIRS for part in path.parts) + """Check whether any parent directory component is in the skip set or file is disabled.""" + return any(part in _SKIP_DIRS for part in path.parts) or is_disabled_file(path.name) def _collect_scannable_files(apps_dir: Path) -> list[Path]: diff --git a/src/aipass/seedgo/apps/handlers/aipass_standards/skip_dirs.py b/src/aipass/seedgo/apps/handlers/aipass_standards/skip_dirs.py index 3d5b89f7..ce9b78c3 100644 --- a/src/aipass/seedgo/apps/handlers/aipass_standards/skip_dirs.py +++ b/src/aipass/seedgo/apps/handlers/aipass_standards/skip_dirs.py @@ -14,6 +14,14 @@ products, not committed source — scanning them causes local-vs-CI audit divergence (FPLAN-0261). """ +DISABLED_FILE_MARKER = "(disabled)" + + +def is_disabled_file(name: str) -> bool: + """Return True if filename contains the (disabled) convention marker.""" + return DISABLED_FILE_MARKER in name + + SOURCE_SKIP_DIRS: frozenset[str] = frozenset( { # Build / cache diff --git a/src/aipass/seedgo/apps/handlers/aipass_standards/test_quality_check.py b/src/aipass/seedgo/apps/handlers/aipass_standards/test_quality_check.py index 1c3026cc..2735b4ba 100644 --- a/src/aipass/seedgo/apps/handlers/aipass_standards/test_quality_check.py +++ b/src/aipass/seedgo/apps/handlers/aipass_standards/test_quality_check.py @@ -29,7 +29,7 @@ from pathlib import Path from aipass.prax import logger from aipass.seedgo.apps.handlers.json import json_handler from aipass.seedgo.apps.handlers.bypass.utils import is_bypassed -from aipass.seedgo.apps.handlers.aipass_standards.skip_dirs import SOURCE_SKIP_DIRS +from aipass.seedgo.apps.handlers.aipass_standards.skip_dirs import SOURCE_SKIP_DIRS, is_disabled_file AUDIT_SCOPE = "branch_level" @@ -175,6 +175,11 @@ def _should_skip_dir(name: str) -> bool: return name in SKIP_DIRS or name.startswith(".") +def _should_skip_file(name: str) -> bool: + """Check if a file should be skipped (disabled convention).""" + return is_disabled_file(name) + + def _find_test_files_broad(branch_path: Path) -> list[Path]: """Find all test files for module coverage analysis. @@ -201,7 +206,7 @@ def _find_test_files_broad(branch_path: Path) -> list[Path]: for py_file in sorted(branch_path.rglob("*.py")): if any(_should_skip_dir(part) for part in py_file.relative_to(branch_path).parts): continue - if py_file.name in ("__init__.py", "conftest.py"): + if py_file.name in ("__init__.py", "conftest.py") or _should_skip_file(py_file.name): continue if py_file.name.startswith("test_") or py_file.name.endswith("_test.py"): resolved = py_file.resolve() @@ -245,7 +250,12 @@ def _collect_testable_modules(branch_path: Path) -> set[str]: modules_dir = apps_dir / "modules" if modules_dir.is_dir(): for item in sorted(modules_dir.iterdir()): - if item.is_file() and item.suffix == ".py" and item.name != "__init__.py": + if ( + item.is_file() + and item.suffix == ".py" + and item.name != "__init__.py" + and not _should_skip_file(item.name) + ): modules.add(item.stem) handlers_dir = apps_dir / "handlers" @@ -254,10 +264,19 @@ def _collect_testable_modules(branch_path: Path) -> set[str]: if _should_skip_dir(item.name): continue if item.is_dir() and item.name != "__pycache__": - has_py = any(f.suffix == ".py" and f.name != "__init__.py" for f in item.iterdir() if f.is_file()) + has_py = any( + f.suffix == ".py" and f.name != "__init__.py" and not _should_skip_file(f.name) + for f in item.iterdir() + if f.is_file() + ) if has_py: modules.add(item.name) - elif item.is_file() and item.suffix == ".py" and item.name != "__init__.py": + elif ( + item.is_file() + and item.suffix == ".py" + and item.name != "__init__.py" + and not _should_skip_file(item.name) + ): modules.add(item.stem) return modules diff --git a/src/aipass/seedgo/apps/handlers/aipass_standards/unused_function_check.py b/src/aipass/seedgo/apps/handlers/aipass_standards/unused_function_check.py index 7752a24a..1f12df36 100644 --- a/src/aipass/seedgo/apps/handlers/aipass_standards/unused_function_check.py +++ b/src/aipass/seedgo/apps/handlers/aipass_standards/unused_function_check.py @@ -32,7 +32,7 @@ from pathlib import Path from aipass.prax import logger from aipass.seedgo.apps.handlers.json import json_handler from aipass.seedgo.apps.handlers.bypass.utils import is_bypassed -from aipass.seedgo.apps.handlers.aipass_standards.skip_dirs import SOURCE_SKIP_DIRS +from aipass.seedgo.apps.handlers.aipass_standards.skip_dirs import SOURCE_SKIP_DIRS, is_disabled_file AUDIT_SCOPE = "branch_level" @@ -61,8 +61,8 @@ _MAIN_BLOCK_RE = re.compile( def _should_skip(path: Path) -> bool: - """Return True if any path component is in the skip set.""" - return any(part in SKIP_DIRS for part in path.parts) + """Return True if any path component is in the skip set or file is disabled.""" + return any(part in SKIP_DIRS for part in path.parts) or is_disabled_file(path.name) def _collect_python_files(branch_path: Path) -> list[Path]: diff --git a/src/aipass/seedgo/apps/handlers/audit/branch_audit.py b/src/aipass/seedgo/apps/handlers/audit/branch_audit.py index 8f0850ba..2d192953 100644 --- a/src/aipass/seedgo/apps/handlers/audit/branch_audit.py +++ b/src/aipass/seedgo/apps/handlers/audit/branch_audit.py @@ -12,6 +12,7 @@ from pathlib import Path from typing import Any, Dict, List from aipass.prax import logger from aipass.seedgo.apps.handlers.bypass import ignore_handler +from aipass.seedgo.apps.handlers.aipass_standards.skip_dirs import is_disabled_file from aipass.seedgo.apps.handlers.json import json_handler from aipass.seedgo.apps.handlers.test_map.function_scanner import scan_branch @@ -50,7 +51,7 @@ def _collect_py_files(branch_path: Path) -> List[Dict[str, str]]: return [ {"file": str(f), "name": f.name} for f in apps_dir.rglob("*.py") - if f.name != "__init__.py" and not any(p in str(f).lower() for p in ign) + if f.name != "__init__.py" and not is_disabled_file(f.name) and not any(p in str(f).lower() for p in ign) ] diff --git a/src/aipass/seedgo/apps/handlers/test_map/function_scanner.py b/src/aipass/seedgo/apps/handlers/test_map/function_scanner.py index 54e1363f..e5fedc60 100644 --- a/src/aipass/seedgo/apps/handlers/test_map/function_scanner.py +++ b/src/aipass/seedgo/apps/handlers/test_map/function_scanner.py @@ -112,6 +112,8 @@ def _should_skip_file(py_file: Path) -> bool: """Check if file should be skipped based on naming/path rules.""" if py_file.name.startswith("_"): return True + if "(disabled)" in py_file.name: + return True return any(part.startswith(".") for part in py_file.parts) diff --git a/src/aipass/seedgo/apps/modules/checklist.py b/src/aipass/seedgo/apps/modules/checklist.py index 5974093a..a6639462 100644 --- a/src/aipass/seedgo/apps/modules/checklist.py +++ b/src/aipass/seedgo/apps/modules/checklist.py @@ -312,7 +312,7 @@ def handle_command(command: str, args: List[str]) -> bool: # Directory mode — run checklist on all .py files in directory if resolved.is_dir(): py_files = sorted(resolved.glob("*.py")) - py_files = [f for f in py_files if not f.name.startswith("_")] + py_files = [f for f in py_files if not f.name.startswith("_") and "(disabled)" not in f.name] if not py_files: error("No .py files found in directory", suggestion=f"Directory: {resolved}") return True @@ -390,7 +390,8 @@ def print_help() -> None: console.print("[yellow]USAGE:[/yellow]") console.print(" [green]drone @seedgo checklist [/green] [dim]# Check single file[/dim]") console.print( - " [green]drone @seedgo checklist [/green] [dim]# Check all .py files in directory[/dim]" + " [green]drone @seedgo checklist [/green]" + " [dim]# Check all .py files in directory[/dim]" ) console.print( " [green]drone @seedgo checklist --pack [/green] [dim]# Check with specific pack[/dim]" diff --git a/src/aipass/seedgo/tests/test_coverage_audit.py b/src/aipass/seedgo/tests/test_coverage_audit.py index b348ddd8..a7238c1f 100644 --- a/src/aipass/seedgo/tests/test_coverage_audit.py +++ b/src/aipass/seedgo/tests/test_coverage_audit.py @@ -1103,6 +1103,21 @@ class TestCollectPyFiles: assert "module.py" in names assert "xskip_bad.py" not in names + def test_excludes_disabled_files(self, tmp_path): + """Files with (disabled) in the name are excluded from collection.""" + from aipass.seedgo.apps.handlers.audit.branch_audit import ( + _collect_py_files, + ) + + apps_dir = tmp_path / "apps" + apps_dir.mkdir() + (apps_dir / "module.py").write_text("pass", encoding="utf-8") + (apps_dir / "dashboard_sync(disabled).py").write_text("pass", encoding="utf-8") + result = _collect_py_files(tmp_path) + names = [f["name"] for f in result] + assert "module.py" in names + assert "dashboard_sync(disabled).py" not in names + class TestExtractBranchLevelViolations: """Tests for _extract_branch_level_violations."""