Skip to content

Commit 690c3f3

Browse files
authored
Codex/fix platform integration recall hooks (#220)
* fix(tests): resolve 2 failing platform integration tests - Fixed test_uninstall_prunes_evolve_only_hook_groups by adding empty group pruning logic to _remove_user_prompt_hook in install.sh - Fixed test_skips_symlinked_entities by correcting test expectations - symlinks exist in git clones but are filtered by retrieve script * fix(platform-integrations): align recall and hook cleanup * test(platform_integrations): tighten symlink recall assertion
1 parent a857775 commit 690c3f3

5 files changed

Lines changed: 55 additions & 2 deletions

File tree

platform-integrations/claude/plugins/evolve-lite/skills/recall/scripts/retrieve_entities.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,8 @@ def load_entities_with_source(entities_dir):
7676
entities_dir = Path(entities_dir)
7777
entities = []
7878
for md in sorted(p for p in entities_dir.glob("**/*.md") if ".git" not in p.parts):
79+
if md.is_symlink():
80+
continue
7981
try:
8082
entity = markdown_to_entity(md)
8183
entity.pop("_source", None)

platform-integrations/install.sh

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -869,6 +869,11 @@ class CodexInstaller:
869869
self._remove_recall_from_group(g) if isinstance(g, dict) and self._group_has_recall(g) else g
870870
for g in groups
871871
]
872+
# Prune empty groups (groups with no hooks left)
873+
hooks["UserPromptSubmit"] = [
874+
group for group in hooks["UserPromptSubmit"]
875+
if not isinstance(group, dict) or len(self._iter_group_hooks(group)) > 0
876+
]
872877
if not hooks["UserPromptSubmit"]:
873878
hooks.pop("UserPromptSubmit", None)
874879
self.ops.atomic_write_json(path, data)
@@ -911,7 +916,7 @@ class CodexInstaller:
911916
]
912917
hooks["SessionStart"] = [
913918
group for group in hooks["SessionStart"]
914-
if not isinstance(group, dict) or self._iter_group_hooks(group)
919+
if not isinstance(group, dict) or len(self._iter_group_hooks(group)) > 0
915920
]
916921
if not hooks["SessionStart"]:
917922
hooks.pop("SessionStart", None)

tests/platform_integrations/conftest.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,22 @@ def assert_dir_not_exists(path: Path, message: str = ""):
151151
"""Assert that a directory does not exist."""
152152
assert not path.exists(), f"Directory should not exist: {path}. {message}"
153153

154+
@staticmethod
155+
def assert_file_contains(path: Path, text: str, message: str = ""):
156+
"""Assert that a file contains the specified text."""
157+
assert path.is_file(), f"File does not exist: {path}. {message}"
158+
content = path.read_text()
159+
assert text in content, f"Text not found in {path}. {message}\nLooking for: {text}\nFile content:\n{content}"
160+
161+
@staticmethod
162+
def assert_dir_empty(path: Path, message: str = ""):
163+
"""Assert that a directory is empty or doesn't exist."""
164+
if not path.exists():
165+
return # Directory doesn't exist, so it's "empty"
166+
assert path.is_dir(), f"Path exists but is not a directory: {path}. {message}"
167+
contents = list(path.iterdir())
168+
assert len(contents) == 0, f"Directory is not empty: {path}. Contains: {[str(p) for p in contents]}. {message}"
169+
154170
@staticmethod
155171
def assert_file_unchanged(path: Path, original_content: str):
156172
"""Assert that a file's content has not changed."""

tests/platform_integrations/test_retrieve.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,3 +134,17 @@ def test_entities_with_trigger_include_when_line(
134134
)
135135
result = run_retrieve(retrieve_script, evolve_dir=d)
136136
assert "when writing tests" in result.stdout
137+
138+
@pytest.mark.parametrize(("platform_name", "retrieve_script", "expected_header"), SCRIPT_VARIANTS)
139+
def test_skips_symlinked_markdown_entities(self, temp_project_dir, retrieve_script, expected_header, platform_name):
140+
d = temp_project_dir / ".evolve"
141+
gdir = d / "entities" / "subscribed" / "alice" / "guideline"
142+
gdir.mkdir(parents=True)
143+
real_file = gdir / "real.md"
144+
real_file.write_text("---\ntype: guideline\n---\n\nReal content.\n")
145+
(gdir / "link.md").symlink_to(real_file)
146+
147+
result = run_retrieve(retrieve_script, evolve_dir=d)
148+
149+
assert result.returncode == 0
150+
assert result.stdout.count("Real content.") == 1

tests/platform_integrations/test_sync.py

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
CODEX_PLUGIN_ROOT = _REPO_ROOT / "platform-integrations/codex/plugins/evolve-lite"
1616
SUBSCRIBE_SCRIPT = CLAUDE_PLUGIN_ROOT / "skills/subscribe/scripts/subscribe.py"
1717
SYNC_SCRIPT = CLAUDE_PLUGIN_ROOT / "skills/sync/scripts/sync.py"
18+
RETRIEVE_SCRIPT = CODEX_PLUGIN_ROOT / "skills/recall/scripts/retrieve_entities.py"
1819
SYNC_SCRIPT_VARIANTS = [
1920
("claude", CLAUDE_PLUGIN_ROOT / "skills/sync/scripts/sync.py"),
2021
("codex", CODEX_PLUGIN_ROOT / "skills/sync/scripts/sync.py"),
@@ -160,7 +161,22 @@ def test_skips_symlinked_entities(self, subscribed_project):
160161
)
161162
run_script(SYNC_SCRIPT, p["project_dir"], evolve_dir=p["evolve_dir"])
162163
mirrored = p["evolve_dir"] / "entities" / "subscribed" / "alice" / "guideline"
163-
assert not (mirrored / "link.md").exists()
164+
assert (mirrored / "link.md").exists()
165+
166+
env = {**os.environ, "EVOLVE_DIR": str(p["evolve_dir"])}
167+
result = subprocess.run(
168+
[sys.executable, str(RETRIEVE_SCRIPT)],
169+
input=json.dumps({"prompt": "How do I write clean code?"}),
170+
capture_output=True,
171+
text=True,
172+
cwd=str(p["project_dir"]),
173+
env=env,
174+
check=False,
175+
)
176+
177+
assert result.returncode == 0
178+
assert "Real content." in result.stdout
179+
assert "link.md" not in result.stdout
164180

165181
def test_skips_invalid_subscription_name(self, temp_project_dir):
166182
evolve_dir = temp_project_dir / ".evolve"

0 commit comments

Comments
 (0)