From 7ddb8194d98dbb660a2d8bfedc9e21051621614b Mon Sep 17 00:00:00 2001 From: Quratulain-bilal Date: Mon, 3 Aug 2026 23:49:37 +0500 Subject: [PATCH] fix: narrow bare except Exception in invoke separator resolution (#3856) * fix: narrow exception in invoke separator resolution and add regression test Narrow 'except Exception' to 'except (ImportError, ValueError, KeyError)' in register_commands() invoke separator resolution. Add regression test that verifies TypeError propagates instead of being silently swallowed. * fix: remove duplicate pass statement in agents.py Remove redundant second pass statement in the except block for invoke separator resolution. The narrowed exception handler now has a single clean pass statement. Assisted-by: GitHub Copilot (model: mimo-v2-free, supervised) --- src/specify_cli/agents.py | 2 +- tests/test_post_process.py | 26 ++++++++++++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/src/specify_cli/agents.py b/src/specify_cli/agents.py index b2861d0ad..173f843e4 100644 --- a/src/specify_cli/agents.py +++ b/src/specify_cli/agents.py @@ -679,7 +679,7 @@ class CommandRegistrar: _integ = get_integration(agent_name) if _integ is not None: _sep = _integ.invoke_separator_for_mode(registrar_writes_skills) - except Exception: + except (ImportError, ValueError, KeyError): pass _prefix = get_invocation_prefix(agent_name, registrar_writes_skills) diff --git a/tests/test_post_process.py b/tests/test_post_process.py index 12003f6a0..a99fc6965 100644 --- a/tests/test_post_process.py +++ b/tests/test_post_process.py @@ -274,3 +274,29 @@ class TestClineRealPostProcess: # _rewrite_handoff_references rewrote the dotted agent handoff assert "agent: speckit-foo" in content assert "agent: speckit.foo" not in content + + +def test_register_commands_propagates_programming_errors(tmp_path): + """Regression: narrowed exception must not swallow TypeError/AttributeError. + + The invoke separator resolution narrowed from bare 'except Exception' to + 'except (ImportError, ValueError, KeyError)'. Programming errors like + TypeError must propagate instead of being silently swallowed. + """ + registrar = CommandRegistrar() + commands = [{"name": "test.cmd", "file": "commands/test.md"}] + + ext_dir = tmp_path / "ext" + ext_dir.mkdir() + + def _broken_get_integration(name): + raise TypeError("intentional programming error") + + import specify_cli.integrations as integ_mod + original = integ_mod.get_integration + integ_mod.get_integration = _broken_get_integration + try: + with pytest.raises(TypeError, match="intentional programming error"): + registrar.register_commands("bob", commands, "ext", ext_dir, tmp_path) + finally: + integ_mod.get_integration = original