#1674

fix(interface): keep derived target names usable and unique

Openlxcxjxhxwants to merge intofrom

Fixes #1673

Four ways a target or the workspace mount could be given a directory that belongs to something else. All come from names derived from the user's target string, so they are one PR.

A name made only of dots

sanitize_name("..") returned "..", and derive_repo_base_name returns it for a target whose last segment is ... That value becomes workspace_subdir, and clone_repository turns it into <tmp>/strix_repos/<run_name>/.. - the shared parent - which it rmtrees before the clone that would fail, so one bad target removes every other run's clone. A dot-only name is a directory, not a name, so sanitize_name now maps it to target, the fallback it already used for empty input. Names that merely contain dots (a..b) are untouched.

Two targets, one directory

assign_workspace_subdirs counted per base name, so repo, repo, repo-2 gave the second and the third the same repo-2: one target would mount, and clone into, the other's directory. Names are now counted until unused, so those three become repo, repo-2, repo-2-2; repeated names without such a clash keep the plain counter (app, app-2).

A repository named api-specs

stage_api_specs() mounts specs at api-specs in the workspace, and a repository of that name took the same subdir. The reserved name is seeded into the used set, and such a repository becomes api-specs-2.

--workspace-mount named like a target

attach_workspace_mount named the mount from its directory on its own, so --workspace-mount ./app next to a repository called app produced two sources with workspace_subdir = "app" - two things mounted at one path. Both places now share unique_workspace_subdir(), and the mount becomes app-2.

Validation

pytest tests/test_target_names.py tests/test_api_spec_targets.py tests/test_go_tui_runtime.py -q -> 66 passed.

inputbeforeafter
. / .. / ...the same stringtarget
git@host:.. (derived base)..target
repo, repo, repo-2 (subdirs)repo, repo-2, repo-2repo, repo-2, repo-2-2
a repository named api-specsapi-specsapi-specs-2
mount ./app + repository appapp, appapp, app-2
app, app (subdirs)app, app-2app, app-2

ruff check + format clean. Found by reading the name-deriving functions together; the input is the user's own target, not provider traffic.

Activity

7
greptile-apps[bot]1d ago

Confidence Score: 5/5

[Medium impact] This PR appears safe to merge.

Summary

sanitize_name now returns target for dot-only names, preventing derived repository names from pointing at the current or parent directory.

  • Dot-only names now use target as their workspace folder.

Reviews (2) · Last reviewed commit: "fix(interface): never derive a directory..." · Reviewed by Greptile

lxcxjxhx1d ago

Added an end-to-end assertion next to the unit ones, because a unique name only matters if the task the agent reads carries it: three targets (repo, repo, repo-2) now go through assign_workspace_subdirs into build_root_task, and the test requires the rendered text to name all three paths (/workspace/repo, /workspace/repo-2, /workspace/repo-2-2) and build_scan_targets to return exactly those. Before this branch the third target read /workspace/repo-2 in both places, so the assertion fails on main.

pytest tests/test_target_names.py -q -> 20 passed; ruff clean.