diff --git a/src/specify_cli/agents.py b/src/specify_cli/agents.py index b2861d0ad2..2cdee07e57 100644 --- a/src/specify_cli/agents.py +++ b/src/specify_cli/agents.py @@ -679,7 +679,8 @@ def register_commands( _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 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 12003f6a07..a99fc6965b 100644 --- a/tests/test_post_process.py +++ b/tests/test_post_process.py @@ -274,3 +274,29 @@ def test_cline_transforms_applied_via_registrar( # _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