diff --git a/CHANGELOG.md b/CHANGELOG.md index 0785b006..e0391dd9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,12 @@ breaking changes may land in a minor release. ## [Unreleased] +### Fixed + +- Explain that unpinned result-artifact scans search only the configured artifact + directories themselves, so a nested story spec no longer produces an opaque + `no-artifact` breadcrumb (#780). + ## [0.12.0] — 2026-09-20 ### Added diff --git a/src/bmad_loop/adapters/generic.py b/src/bmad_loop/adapters/generic.py index 0f7fcb5e..0a8f7c33 100644 --- a/src/bmad_loop/adapters/generic.py +++ b/src/bmad_loop/adapters/generic.py @@ -1850,7 +1850,13 @@ def _frontmatter_fallback( self._note_resultless_stop( task_id, "no-artifact", - "no result artifact newer than session launch under: " + where, + ( + f"no result artifact newer than session launch at: {where}" + if only is not None + else "no result artifact newer than session launch directly under: " + + where + + " (subdirectories are not searched)" + ), ) return None if len(candidates) > 1: diff --git a/tests/test_generic_tmux.py b/tests/test_generic_tmux.py index 5f62ab5a..5a31f671 100644 --- a/tests/test_generic_tmux.py +++ b/tests/test_generic_tmux.py @@ -1047,6 +1047,25 @@ def test_resultless_stop_breadcrumb_scan_no_artifact(tmp_path, monkeypatch): assert str(impl) in crumb["detail"] # names the searched dirs +def test_resultless_stop_breadcrumb_explains_non_recursive_artifact_scan(tmp_path, monkeypatch): + """A nested result is outside the legacy scan, so the breadcrumb must say so.""" + adapter, impl = make_dev_adapter(tmp_path) + monkeypatch.setattr(generic, "RESULT_GRACE_S", 0.0) + nested = impl / "stories" + nested.mkdir() + (nested / "spec-3-1-foo.md").write_text( + "---\nstatus: done\n---\n\n## Auto Run Result\n\nStatus: done\n", + encoding="utf-8", + ) + + assert adapter._result_json(_dev_handle(), _dev_spec(tmp_path), wait=True) is None + + (crumb,) = _breadcrumbs(adapter) + assert crumb["verdict"] == "no-artifact" + assert str(impl) in crumb["detail"] + assert "subdirectories are not searched" in crumb["detail"] + + def test_resultless_stop_breadcrumb_stories_pending(tmp_path, monkeypatch): adapter, _ = make_dev_adapter(tmp_path) monkeypatch.setattr(generic, "RESULT_GRACE_S", 0.0) @@ -5885,6 +5904,9 @@ def test_expected_spec_breadcrumb_names_the_pinned_path(tmp_path, monkeypatch): (crumb,) = _breadcrumbs(adapter) assert crumb["verdict"] == "no-artifact" assert str(ours) in crumb["detail"] + assert "at:" in crumb["detail"] + assert "directly under" not in crumb["detail"] + assert "subdirectories are not searched" not in crumb["detail"] assert "someone-elses" not in crumb["detail"]