diff --git a/src/plyngent/tools/workspace.py b/src/plyngent/tools/workspace.py index 30a8a51..9e4164c 100644 --- a/src/plyngent/tools/workspace.py +++ b/src/plyngent/tools/workspace.py @@ -217,10 +217,21 @@ def remove_workspace_allowlist(root: Path | str) -> None: _state.allowlist.remove(path) -def _under_any_root(resolved: Path) -> bool: +def _primary_roots() -> list[Path]: + """Primary workspace roots: bound instance (if any) then process global.""" roots: list[Path] = [] - if _state.root is not None: + from plyngent.tools.context import get_instance + + instance = get_instance() + if instance is not None and instance.workspace_root is not None: + roots.append(instance.workspace_root) + if _state.root is not None and _state.root not in roots: roots.append(_state.root) + return roots + + +def _under_any_root(resolved: Path) -> bool: + roots = _primary_roots() roots.extend(_state.allowlist) for root in roots: try: diff --git a/tests/test_tools/test_workspace_instance.py b/tests/test_tools/test_workspace_instance.py index fd7602a..cbbab39 100644 --- a/tests/test_tools/test_workspace_instance.py +++ b/tests/test_tools/test_workspace_instance.py @@ -11,6 +11,7 @@ from plyngent.tools.workspace import ( WorkspaceError, clear_workspace_root, get_workspace_root, + resolve_path, set_workspace_root, ) @@ -45,3 +46,15 @@ def test_clear_clears_bound_instance(tmp_path: Path) -> None: assert instance.workspace_root is None with pytest.raises(WorkspaceError): _ = get_workspace_root() + + +def test_resolve_path_accepts_instance_root_without_process_global(tmp_path: Path) -> None: + """Instance-only workspace must be a valid resolve root (not only process global).""" + clear_workspace_root() + target = tmp_path / "note.txt" + _ = target.write_text("hi", encoding="utf-8") + instance = InstanceState(workspace_root=tmp_path.resolve()) + with bind_instance(instance): + resolved = resolve_path("note.txt") + assert resolved == target.resolve() + clear_workspace_root()