fix(seedgo): name-scope unused_function bypasses (kill silent line-drift)

unused_function bypasses matched by file+line; the line was the function's
def line, so any code shift above it staled the bypass and silently re-flagged
the exempted function, dropping the branch below 100% (S216/S217).

Mechanism: is_bypassed() gains a 'functions' field + name param; name-scoped
match takes precedence, 'lines' kept for back-compat (no other standard
changes). unused_function_check passes the function name. +7 tests (1093),
seedgo self-audit 100%, bypass schema documented.

Migration: converted 10 line-scoped entries to functions: across
drone/memory/skills; removed 3 dead memory/vector_search entries already
pointing past EOF (file is 152 lines). drone/memory/skills re-audit:
Unused_Function 100% (names verified live). Closes td-009.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QEQZXCtgnF3NQtcttTErpq
This commit is contained in:
AIOSAI
2026-06-24 05:51:54 -07:00
co-authored by Claude Opus 4.8
parent 03c95e6881
commit feecd263eb
9 changed files with 260 additions and 33 deletions
+6
View File
@@ -18,6 +18,12 @@ PyPI version — not the changelog header.
central audit collector. An in-place disabled module no longer trips a false
"missing module" violation; disabled test files no longer inflate README test
counts (td-103).
- **seedgo `unused_function` bypasses are now name-scoped** — bypasses match by
function name (`functions: [...]`) instead of line number (`lines: [...]`),
which drifted silently when code shifted and re-flagged exempted functions
(bit us S216/S217). `lines` stays supported for other standards. Migrated the
10 existing line-scoped entries across drone/memory/skills and dropped 3 dead
entries already pointing past EOF (td-009).
## [2026-06-23]
+4 -4
View File
@@ -252,25 +252,25 @@
{
"file": "apps/handlers/command_registry/ops.py",
"standard": "unused_function",
"lines": [232, 263],
"functions": ["update_command", "command_exists"],
"reason": "Public CRUD API surface (update_command, command_exists) — tested, available for programmatic use. No CLI subcommand wired yet."
},
{
"file": "apps/handlers/git/pr_handler.py",
"standard": "unused_function",
"lines": [108],
"functions": ["create_pr"],
"reason": "create_pr() is deprecated per FPLAN-0210 — pr command blocked at auth tier. Handler kept for backwards compatibility; still tested in test_git_module.py."
},
{
"file": "apps/modules/git_module.py",
"standard": "unused_function",
"lines": [665],
"functions": ["get_introspective"],
"reason": "get_introspective() called dynamically via getattr() by module_registry_handler.py:219 for internal module introspection. Also tested in test_git_module, test_system_pr, test_devpulse_plugins, test_git_access."
},
{
"file": "apps/handlers/broker/daemon.py",
"standard": "unused_function",
"lines": [422],
"functions": ["start_background"],
"reason": "Threaded broker entrypoint, exercised by tests/test_broker.py; production uses blocking start(); intentionally not called in shipped non-test code."
}
],
+2 -20
View File
@@ -559,31 +559,13 @@
{
"file": "apps/handlers/learnings/manager.py",
"standard": "unused_function",
"lines": [759],
"functions": ["update_status_counts"],
"reason": "Public API for learning extraction pipeline — called dynamically by symbolic extraction."
},
{
"file": "apps/handlers/search/vector_search.py",
"standard": "unused_function",
"lines": [247],
"reason": "Public API surface for vector search — legacy handler retained for direct-import consumers."
},
{
"file": "apps/handlers/search/vector_search.py",
"standard": "unused_function",
"lines": [316],
"reason": "Public API surface for vector search — legacy handler retained for direct-import consumers."
},
{
"file": "apps/handlers/search/vector_search.py",
"standard": "unused_function",
"lines": [380],
"reason": "Public API surface for vector search — legacy handler retained for direct-import consumers."
},
{
"file": "apps/handlers/symbolic/extractor.py",
"standard": "unused_function",
"lines": [455],
"functions": ["analyze_conversation_llm"],
"reason": "LLM-based extraction function — called conditionally when API key is available."
},
{
+23
View File
@@ -3,3 +3,26 @@
Seedgo audit bypass config for `SEEDGO`.
When an audit flags a false positive that doesn't apply to your architecture, add a bypass entry in `bypass.json` with a reason explaining why it's justified.
## Fields
| Field | Required | Description |
|-------|----------|-------------|
| `file` | yes | Relative path from branch root |
| `standard` | yes | Standard name (cli, imports, naming, etc.) |
| `lines` | no | Specific line numbers to bypass |
| `functions` | no | Function names for name-scoped bypass (required for `unused_function`) |
| `reason` | yes | Why this bypass exists |
## Name-scoped bypass (unused_function)
Use `functions` instead of `lines` for `unused_function` bypasses — function names are stable across edits, line numbers drift silently:
```json
{
"file": "apps/handlers/registry.py",
"standard": "unused_function",
"functions": ["get_skill", "get_skill_names"],
"reason": "Public API surface — called by external consumers"
}
```
@@ -277,8 +277,7 @@ def check_branch(branch_path: str, bypass_rules: list | None = None) -> dict:
unused_functions: list[dict] = []
for func_name, lineno, py_file in all_functions:
# Check bypass at file+line level
if is_bypassed(str(py_file), "unused_function", lineno, bypass_rules):
if is_bypassed(str(py_file), "unused_function", lineno, bypass_rules, name=func_name):
continue
total_refs = _count_references_in_corpus(func_name, corpus)
@@ -37,14 +37,13 @@ BYPASS_TEMPLATE = {
"file": "apps/modules/logger.py",
"standard": "cli",
"lines": [146, 177],
"pattern": "if __name__ == '__main__'",
"reason": "Circular dependency - logger cannot import CLI",
},
"fields": {
"file": "Relative path from branch root (required)",
"standard": "Standard name: cli, imports, naming, etc. (required)",
"lines": "Optional - specific line numbers to bypass",
"pattern": "Optional - pattern to match (e.g. 'if __name__')",
"functions": "Optional - list of function names for name-scoped bypass (required for unused_function)",
"reason": "Required - why this bypass exists",
},
},
@@ -18,6 +18,7 @@ def is_bypassed(
standard: str,
line: int | None = None,
bypass_rules: list | None = None,
name: str | None = None,
) -> bool:
"""Check if a violation should be bypassed.
@@ -26,6 +27,7 @@ def is_bypassed(
standard: Standard name (e.g., 'cli', 'imports')
line: Optional specific line number of the violation
bypass_rules: List of bypass rules from .seedgo/bypass.json
name: Optional function/symbol name for name-scoped bypasses
Returns:
True if this violation should be bypassed
@@ -40,15 +42,20 @@ def is_bypassed(
rule_file = rule.get("file", "")
if rule_file and rule_file not in file_path_posix:
continue
rule_lines = rule.get("lines", [])
if rule_lines and line is not None and line not in rule_lines:
continue
functions = rule.get("functions")
if functions and name is not None:
if name not in functions:
continue
elif rule.get("lines") and line is not None:
if line not in rule["lines"]:
continue
json_handler.log_operation(
"bypass_matched",
{
"file": file_path,
"standard": standard,
"line": line,
"name": name,
"rule_file": rule_file,
},
)
+212
View File
@@ -44,6 +44,7 @@ def _mock_infrastructure(monkeypatch):
for mod_name in [
"aipass.seedgo.apps.handlers.bypass.bypass_handler",
"aipass.seedgo.apps.handlers.bypass.ignore_handler",
"aipass.seedgo.apps.handlers.bypass.utils",
]:
monkeypatch.delitem(sys.modules, mod_name, raising=False)
@@ -210,3 +211,214 @@ def test_get_deprecated_patterns_returns_dict():
for key, value in patterns.items():
assert isinstance(key, str)
assert isinstance(value, str)
# ---------------------------------------------------------------------------
# Tests -- utils.is_bypassed name-scoped bypass
# ---------------------------------------------------------------------------
def test_utils_name_match_suppresses_regardless_of_line():
"""Name-scoped bypass matches by function name, ignoring line number."""
from aipass.seedgo.apps.handlers.bypass.utils import is_bypassed
rules = [
{
"file": "apps/ops.py",
"standard": "unused_function",
"functions": ["update_command"],
"reason": "public API",
}
]
assert (
is_bypassed(
"/branch/apps/ops.py",
"unused_function",
line=999,
bypass_rules=rules,
name="update_command",
)
is True
)
def test_utils_name_not_in_functions_list():
"""Name-scoped bypass rejects function not in the functions list."""
from aipass.seedgo.apps.handlers.bypass.utils import is_bypassed
rules = [
{
"file": "apps/ops.py",
"standard": "unused_function",
"functions": ["update_command"],
"reason": "public API",
}
]
assert (
is_bypassed(
"/branch/apps/ops.py",
"unused_function",
line=232,
bypass_rules=rules,
name="delete_command",
)
is False
)
def test_utils_line_drift_no_longer_breaks_name_scoped():
"""Line drift doesn't affect name-scoped bypass — name is stable."""
from aipass.seedgo.apps.handlers.bypass.utils import is_bypassed
rules = [
{
"file": "apps/ops.py",
"standard": "unused_function",
"functions": ["get_skill", "get_skill_names"],
"reason": "public API",
}
]
assert (
is_bypassed(
"/branch/apps/ops.py",
"unused_function",
line=52,
bypass_rules=rules,
name="get_skill",
)
is True
)
assert (
is_bypassed(
"/branch/apps/ops.py",
"unused_function",
line=9999,
bypass_rules=rules,
name="get_skill",
)
is True
)
def test_utils_functions_present_name_none_falls_back_to_lines():
"""When functions is set but name=None (other checker), fall back to line matching."""
from aipass.seedgo.apps.handlers.bypass.utils import is_bypassed
rules = [
{
"file": "apps/ops.py",
"standard": "unused_function",
"functions": ["update_command"],
"lines": [10],
"reason": "test",
}
]
assert (
is_bypassed(
"/branch/apps/ops.py",
"unused_function",
line=10,
bypass_rules=rules,
name=None,
)
is True
)
def test_utils_existing_lines_only_rules_still_work():
"""Existing line-only rules (no functions field) still match by line."""
from aipass.seedgo.apps.handlers.bypass.utils import is_bypassed
rules = [
{
"file": "apps/foo.py",
"standard": "cli",
"lines": [10, 20],
"reason": "circular",
}
]
assert (
is_bypassed(
"/branch/apps/foo.py",
"cli",
line=10,
bypass_rules=rules,
)
is True
)
assert (
is_bypassed(
"/branch/apps/foo.py",
"cli",
line=99,
bypass_rules=rules,
)
is False
)
def test_utils_file_only_bypass_still_matches():
"""File-level bypass (no lines, no functions) still works."""
from aipass.seedgo.apps.handlers.bypass.utils import is_bypassed
rules = [
{
"file": "apps/foo.py",
"standard": "unused_function",
"reason": "whole file bypassed",
}
]
assert (
is_bypassed(
"/branch/apps/foo.py",
"unused_function",
line=50,
bypass_rules=rules,
name="anything",
)
is True
)
def test_utils_multiple_functions_in_one_rule():
"""A single rule can list multiple function names."""
from aipass.seedgo.apps.handlers.bypass.utils import is_bypassed
rules = [
{
"file": "apps/registry.py",
"standard": "unused_function",
"functions": ["get_skill", "get_skill_names"],
"reason": "public API",
}
]
assert (
is_bypassed(
"/branch/apps/registry.py",
"unused_function",
line=1,
bypass_rules=rules,
name="get_skill",
)
is True
)
assert (
is_bypassed(
"/branch/apps/registry.py",
"unused_function",
line=1,
bypass_rules=rules,
name="get_skill_names",
)
is True
)
assert (
is_bypassed(
"/branch/apps/registry.py",
"unused_function",
line=1,
bypass_rules=rules,
name="other_func",
)
is False
)
+1 -2
View File
@@ -39,8 +39,7 @@
{
"file": "apps/handlers/registry.py",
"standard": "unused_function",
"lines": [52, 68],
"pattern": "def get_skill|def get_skill_names",
"functions": ["get_skill", "get_skill_names"],
"reason": "Public API functions — used by test_registry.py and available for external callers; part of the registry module's contract"
}
],