Summary
scripts/commands/__init__.py auto-imports every *.py file in commands/ to trigger register_command(...) side-effects. If any module fails to import (syntax error, missing dependency, circular import), the exception is caught and logged at ERROR level — but the command is silently missing from the registry. CI does not catch this because test_integration.py only asserts len(COMMAND_REGISTRY) >= 41 (see BUG-04).
Evidence
scripts/commands/__init__.py:33-38:
for fname in sorted(os.listdir(_commands_dir)):
if fname.endswith('.py') and fname != '__init__.py':
try:
importlib.import_module(f'.{fname[:-3]}', package='commands')
except Exception as e:
logging.getLogger('codelens').error(
f"Failed to import command module '{fname}': {e}"
)
No re-raise, no exit code change, no test assertion.
Impact
- Silent feature loss: A typo in
commands/new_feature.py causes the feature to disappear from codelens --help with only a log line. If logging isn't configured (default level is WARNING per utils.py:22, but ERROR > WARNING so it should show — still easy to miss in CI noise), the user sees nothing.
- CI passes anyway:
assert len(COMMAND_REGISTRY) >= 41 was set when there were 41 commands; with 60 commands now, 19 commands could fail to import before the test would notice.
- MCP server silently loses tools:
mcp_server.py derives its tool list from COMMAND_REGISTRY. A broken command module means a missing MCP tool, with no signal to the agent.
- Hard to debug: The error log goes to stderr; MCP clients only see stdout (JSON-RPC), so they have no way to know a tool is missing.
Repro
# Introduce a syntax error in a command module
echo "def broken(" > scripts/commands/_test_broken.py
python3 scripts/codelens.py --help 2>&1 | grep -i "failed to import"
# Observe: error logged to stderr, _test_broken missing from --help, exit code 0.
rm scripts/commands/_test_broken.py
Suggested fix
Two layers:
- Fail-fast in dev / CI: Add an env var
CODELENS_STRICT_COMMANDS=1 that, when set, re-raises the exception instead of logging. Set this in pytest.ini (via env=) and in .gitlab-ci.yml so CI catches import failures.
- Test coverage: Add a meta-test that asserts every
*.py file in scripts/commands/ (excluding __init__.py) successfully imports and registers a command:
# tests/test_command_registry.py
import importlib, pkgutil, commands
def test_every_command_module_registers():
cmd_dir = Path(commands.__file__).parent
for f in cmd_dir.glob("*.py"):
if f.name == "__init__.py": continue
mod = importlib.import_module(f"commands.{f.stem}")
# The module should have called register_command() at import time.
# Verify by checking COMMAND_REGISTRY contains an entry whose
# execute function lives in this module.
registered = [
name for name, info in commands.COMMAND_REGISTRY.items()
if info["execute"].__module__ == mod.__name__
]
assert registered, f"{f.name} did not register any command"
- Improve the log: Include the failed module name in a structured field that MCP clients can surface (e.g., emit a
codelens.health.commands_failed metric).
Files
scripts/commands/__init__.py (L33-38)
tests/test_command_registry.py (new)
pytest.ini (add env= if using pytest-env, or document CODELENS_STRICT_COMMANDS=1 in CI)
.gitlab-ci.yml (set CODELENS_STRICT_COMMANDS=1 on test jobs)
Summary
scripts/commands/__init__.pyauto-imports every*.pyfile incommands/to triggerregister_command(...)side-effects. If any module fails to import (syntax error, missing dependency, circular import), the exception is caught and logged at ERROR level — but the command is silently missing from the registry. CI does not catch this becausetest_integration.pyonly assertslen(COMMAND_REGISTRY) >= 41(see BUG-04).Evidence
scripts/commands/__init__.py:33-38:No re-raise, no exit code change, no test assertion.
Impact
commands/new_feature.pycauses the feature to disappear fromcodelens --helpwith only a log line. If logging isn't configured (default level is WARNING perutils.py:22, but ERROR > WARNING so it should show — still easy to miss in CI noise), the user sees nothing.assert len(COMMAND_REGISTRY) >= 41was set when there were 41 commands; with 60 commands now, 19 commands could fail to import before the test would notice.mcp_server.pyderives its tool list fromCOMMAND_REGISTRY. A broken command module means a missing MCP tool, with no signal to the agent.Repro
Suggested fix
Two layers:
CODELENS_STRICT_COMMANDS=1that, when set, re-raises the exception instead of logging. Set this inpytest.ini(viaenv=) and in.gitlab-ci.ymlso CI catches import failures.*.pyfile inscripts/commands/(excluding__init__.py) successfully imports and registers a command:codelens.health.commands_failedmetric).Files
scripts/commands/__init__.py(L33-38)tests/test_command_registry.py(new)pytest.ini(addenv=if using pytest-env, or documentCODELENS_STRICT_COMMANDS=1in CI).gitlab-ci.yml(setCODELENS_STRICT_COMMANDS=1on test jobs)