Skip to content

Commit 3c26611

Browse files
sriumcpclaude
andauthored
fix(cli): give honest error for path-shaped status targets (AI-native-Systems-Research#182)
Before: `nous status /abs/path/.nous/missing-run` from any cwd printed "Could not find .nous/ directory in any parent" — misleading because the user gave a fully-qualified path. resolve_work_dir() silently re-interpreted the unresolved path as a bare run-id and walked up from cwd looking for .nous/, conflating three distinct failure modes under one error. Now: a target containing a path separator or absolute path that doesn't resolve to a valid work-dir produces "Work directory not found: <p>", naming the actual path. Bare run-id resolution (the existing ergonomic of `nous status my-campaign` from inside a repo) is preserved. Closes AI-native-Systems-Research#181 Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 6d4345e commit 3c26611

2 files changed

Lines changed: 45 additions & 0 deletions

File tree

orchestrator/cli.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,10 @@ def resolve_work_dir(target):
4545
if p.is_dir() and (p / "state.json").exists():
4646
return p
4747

48+
if p.is_absolute() or "/" in target:
49+
print(f"Work directory not found: {p}", file=sys.stderr)
50+
sys.exit(1)
51+
4852
run_id = target
4953
root = _find_repo_root()
5054
work_dir = root / ".nous" / run_id

tests/test_cli.py

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,47 @@ def test_campaign_yaml_not_found_raises(self):
4646
with pytest.raises(SystemExit):
4747
resolve_work_dir("/no/such/campaign.yaml")
4848

49+
def test_absolute_path_to_nonexistent_dir_reports_missing_workdir(
50+
self, tmp_path, capsys
51+
):
52+
"""An absolute path that doesn't exist must not be silently
53+
reinterpreted as a bare run-id — the user clearly intended a path,
54+
so the error should name that path, not 'no .nous/ in any parent'.
55+
Regression for #181."""
56+
missing = tmp_path / "inference-sim" / ".nous" / "paper-burst"
57+
with pytest.raises(SystemExit):
58+
resolve_work_dir(str(missing))
59+
err = capsys.readouterr().err
60+
assert "Work directory not found" in err
61+
assert str(missing) in err
62+
assert ".nous/ directory in any parent" not in err
63+
64+
def test_absolute_path_to_dir_without_state_json_reports_missing_workdir(
65+
self, tmp_path, capsys
66+
):
67+
"""A directory that exists but lacks state.json (e.g. mid-bootstrap
68+
or wrong path) must produce the same path-shaped error, not the
69+
run-id walk-up error. Regression for #181."""
70+
half = tmp_path / ".nous" / "half-bootstrapped"
71+
half.mkdir(parents=True)
72+
with pytest.raises(SystemExit):
73+
resolve_work_dir(str(half))
74+
err = capsys.readouterr().err
75+
assert "Work directory not found" in err
76+
assert ".nous/ directory in any parent" not in err
77+
78+
def test_relative_path_with_separator_treated_as_path(
79+
self, tmp_path, monkeypatch, capsys
80+
):
81+
"""A relative target containing a path separator is path-shaped —
82+
don't fall through to run-id resolution."""
83+
monkeypatch.chdir(tmp_path)
84+
with pytest.raises(SystemExit):
85+
resolve_work_dir("subdir/missing-run")
86+
err = capsys.readouterr().err
87+
assert "Work directory not found" in err
88+
assert ".nous/ directory in any parent" not in err
89+
4990

5091
class TestCmdRun:
5192
def test_run_errors_if_state_beyond_init(self, tmp_path):

0 commit comments

Comments
 (0)