From 05714d295cb0ae03c58b039215874f5adf617b56 Mon Sep 17 00:00:00 2001 From: Renn F Date: Fri, 19 Jun 2026 20:43:56 +0200 Subject: [PATCH] fix(retention): match the encoded workspaces root at a path boundary is_agent_owned_dir used a bare startswith on the encoded workspaces root, so a sibling root that shares the prefix (e.g. -data-workspaces2 vs -data-workspaces) was misclassified as agent-owned and its operator transcripts pruned. Require an exact match or a '-' path-boundary prefix. Supersedes #221 (the same fix from antfleet-ops, who flagged the over-match); re-done here as our own change so it can land without the contributor CLA. --- roboco/runtime/transcript_retention.py | 8 +++++++- tests/unit/runtime/test_transcript_retention.py | 10 ++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/roboco/runtime/transcript_retention.py b/roboco/runtime/transcript_retention.py index 90a0ba2e..979ceaf7 100644 --- a/roboco/runtime/transcript_retention.py +++ b/roboco/runtime/transcript_retention.py @@ -34,7 +34,13 @@ def is_agent_owned_dir(dir_name: str, workspaces_root: str) -> bool: if dir_name == "-app": return True encoded_root = workspaces_root.rstrip("/").replace("/", "-") - return bool(encoded_root) and dir_name.startswith(encoded_root) + if not encoded_root: + return False + # Match the encoded root exactly or at a path boundary (next component + # separated by "-"), so a sibling root like "-data-workspaces2" is NOT + # mistaken for a descendant of "-data-workspaces" and its operator-owned + # transcripts pruned. + return dir_name == encoded_root or dir_name.startswith(encoded_root + "-") def _is_old_transcript(path: Path, cutoff_epoch: float) -> bool: diff --git a/tests/unit/runtime/test_transcript_retention.py b/tests/unit/runtime/test_transcript_retention.py index 6e728ac6..186e5dee 100644 --- a/tests/unit/runtime/test_transcript_retention.py +++ b/tests/unit/runtime/test_transcript_retention.py @@ -38,6 +38,16 @@ def test_is_agent_owned_dir_matches_app_and_workspaces() -> None: assert is_agent_owned_dir("-home-renzof-code", WORKSPACES) is False +def test_is_agent_owned_dir_rejects_sibling_root_prefixes() -> None: + # A sibling workspace root that merely shares the encoded prefix without a + # "-" boundary must NOT be treated as agent-owned, else operator transcripts + # under it get pruned. Encoded root here is "-data-workspaces". + assert is_agent_owned_dir("-data-workspaces", WORKSPACES) is True # exact + assert is_agent_owned_dir("-data-workspaces2", WORKSPACES) is False + assert is_agent_owned_dir("-data-workspaces2-project", WORKSPACES) is False + assert is_agent_owned_dir("-data-workspacesBackup-x", WORKSPACES) is False + + def test_is_agent_owned_dir_handles_root_slash_safely() -> None: # A pathological "/" workspaces root must not make every dir agent-owned. assert is_agent_owned_dir("-Users-renzof-secret", "/") is False