diff --git a/tests/integration/test_audit_primitive_contract.py b/tests/integration/test_audit_primitive_contract.py index 5c50289f0f..33b343845b 100644 --- a/tests/integration/test_audit_primitive_contract.py +++ b/tests/integration/test_audit_primitive_contract.py @@ -691,6 +691,7 @@ def no_read(*args: object, **kwargs: object) -> str: assert second.findings_by_file["second"][0].file == "second" +@pytest.mark.lifecycle_smoke @pytest.mark.parametrize("target", ["cursor", "windsurf"]) @pytest.mark.parametrize("nested", [False, True]) def test_preserved_nested_command_layout_is_visible_non_prompt( @@ -702,14 +703,16 @@ def test_preserved_nested_command_layout_is_visible_non_prompt( marker = project / "HOOK_MUST_NOT_RUN" command = {"type": "command", "command": f"touch {marker}{_BIDI}"} entry = {"matcher": "*", "hooks": [command]} if nested else command - payload = json.dumps({"version": 1, "hooks": {"PreToolUse": [entry]}}) + event = "preToolUse" if target == "cursor" else "PreToolUse" + payload = json.dumps({"version": 1, "hooks": {event: [entry]}}) path.write_text(payload, encoding="utf-8") result = scan_project_result(project, targets=(profile,)) if target == "cursor" and nested: # Cursor hooks are native v1 flat handlers; nested layouts are reported, not scanned. - assert [entry.diagnostic for entry in result.incomplete] == [ - "native hook event requires flat handlers" + assert [(entry.pointer, entry.diagnostic) for entry in result.incomplete] == [ + ("/hooks/preToolUse/0", "native hook event requires flat handlers") ] + assert [entry.status for entry in result.inventory] == ["incomplete"] else: assert result.incomplete == () assert [entry.status for entry in result.inventory] == ["not-applicable"] diff --git a/tests/integration/test_hook_root_source_drift_e2e.py b/tests/integration/test_hook_root_source_drift_e2e.py index 80d38f00b8..07c6ee7ac5 100644 --- a/tests/integration/test_hook_root_source_drift_e2e.py +++ b/tests/integration/test_hook_root_source_drift_e2e.py @@ -127,20 +127,7 @@ def _user_owned_entry(target: str) -> dict: } -def _is_user_owned(entry: object) -> bool: - if not isinstance(entry, dict): - return False - if entry.get("command") == "echo user-owned": - return True - handlers = entry.get("hooks") - return ( - isinstance(handlers, list) - and bool(handlers) - and isinstance(handlers[0], dict) - and handlers[0].get("command") == "echo user-owned" - ) - - +@pytest.mark.lifecycle_smoke @pytest.mark.parametrize("target, settings_rel, sidecar_rel, event_key", _HARNESS_CASES) def test_root_hook_source_drift_heals_on_reinstall( tmp_path: Path, @@ -203,9 +190,8 @@ def test_root_hook_source_drift_heals_on_reinstall( # Append a user-owned entry directly to the settings file (never in the sidecar). settings_path = project / settings_rel settings_data = json.loads(settings_path.read_text(encoding="utf-8")) - settings_data.setdefault("hooks", {}).setdefault(event_key, []).append( - _user_owned_entry(target) - ) + user_entry = _user_owned_entry(target) + settings_data.setdefault("hooks", {}).setdefault(event_key, []).append(user_entry) settings_path.write_text(json.dumps(settings_data), encoding="utf-8") # Second install: must heal the stale marker without touching the user-owned entry. @@ -219,7 +205,7 @@ def test_root_hook_source_drift_heals_on_reinstall( settings_data = json.loads(settings_path.read_text(encoding="utf-8")) entries = settings_data.get("hooks", {}).get(event_key, []) - user_owned = [e for e in entries if _is_user_owned(e)] + user_owned = [e for e in entries if e == user_entry] assert len(user_owned) == 1, ( f"User-owned hook entry must survive healing for {target}; entries={entries}" )