fix: scan dashboard workflows from data-home logs too

Installed dashboards could not see recordings under site-packages logs.
Include get_data_home()/logs paths and stop using PROJECT_ROOT as the
default cloud reporter workspace root after pip install.
This commit is contained in:
Ayush7614 2026-07-29 02:55:43 +05:30
parent 5140ea47a3
commit a7bfd6cc26
5 changed files with 83 additions and 10 deletions

View file

@ -20,7 +20,7 @@ from openspace.cloud.telemetry_payloads import (
build_skill_use_report_payload,
short_cloud_request_id,
)
from openspace.config.constants import PROJECT_ROOT
from openspace.config.constants import get_data_home
from openspace.skill_engine.types import ExecutionAnalysis, SkillJudgment
from openspace.utils.logging import Logger
@ -47,7 +47,12 @@ class CloudSkillQualityReporter:
self._client = client
self._mapping_store = mapping_store
self._outbox = outbox
self._workspace_root = Path(workspace_root).resolve() if workspace_root else PROJECT_ROOT
if workspace_root is not None:
self._workspace_root = Path(workspace_root).resolve()
elif Path.cwd().exists():
self._workspace_root = Path.cwd().resolve()
else:
self._workspace_root = get_data_home(create=False)
async def maybe_report_analysis(
self,

View file

@ -18,7 +18,7 @@ from openspace.cloud.telemetry_payloads import (
build_usage_report_payload,
short_cloud_request_id,
)
from openspace.config.constants import PROJECT_ROOT, get_data_home
from openspace.config.constants import get_data_home
class CloudTaskTraceReporter:
@ -39,7 +39,12 @@ class CloudTaskTraceReporter:
self._artifact_dir = Path(
artifact_dir or get_data_home(create=True) / "cloud-task-traces"
)
self._workspace_root = Path(workspace_root).resolve() if workspace_root else PROJECT_ROOT
if workspace_root is not None:
self._workspace_root = Path(workspace_root).resolve()
elif Path.cwd().exists():
self._workspace_root = Path.cwd().resolve()
else:
self._workspace_root = get_data_home(create=False)
async def maybe_report_execution(
self,

View file

@ -94,6 +94,40 @@ def get_log_dir(*, create: bool = True) -> Path:
return path
def get_workflow_roots() -> list[Path]:
"""Directories the dashboard should scan for workflow/run artifacts.
Always includes writable data-home log paths. When running from a source
checkout, also includes the historical repo-relative roots so local
development keeps finding existing recordings and benchmark runs.
"""
data_logs = get_log_dir(create=False)
roots: list[Path] = [
data_logs / "recordings",
data_logs / "trajectories",
]
if is_source_checkout():
roots.extend(
[
PROJECT_ROOT / "logs" / "recordings",
PROJECT_ROOT / "logs" / "trajectories",
PROJECT_ROOT / "benchmarks" / "gdpval" / "results",
PROJECT_ROOT / "benchmarks" / "terminal_bench" / "runs",
]
)
# Preserve order while dropping duplicates (same path via symlink/resolve).
seen: set[Path] = set()
unique: list[Path] = []
for root in roots:
key = root.resolve() if root.exists() else root
if key in seen:
continue
seen.add(key)
unique.append(root)
return unique
__all__ = [
"CONFIG_GROUNDING",
"CONFIG_SECURITY",
@ -108,4 +142,5 @@ __all__ = [
"get_default_db_path",
"get_cache_dir",
"get_log_dir",
"get_workflow_roots",
]

View file

@ -28,16 +28,13 @@ from openspace.skill_engine.evolution import (
from openspace.skill_engine.triggers import TriggerStore
from openspace.skill_engine.types import SkillRecord
from openspace.config.constants import get_workflow_roots
API_PREFIX = "/api/v1"
PACKAGE_ROOT = Path(__file__).resolve().parents[2]
FRONTEND_DIST_DIR = PROJECT_ROOT / "apps" / "dashboard" / "dist"
PACKAGED_DASHBOARD_STATIC_DIR = PACKAGE_ROOT / "packaged" / "dashboard"
WORKFLOW_ROOTS = [
PROJECT_ROOT / "logs" / "recordings",
PROJECT_ROOT / "logs" / "trajectories",
PROJECT_ROOT / "benchmarks" / "gdpval" / "results",
PROJECT_ROOT / "benchmarks" / "terminal_bench" / "runs",
]
WORKFLOW_ROOTS = get_workflow_roots()
PIPELINE_STAGES = [
{

View file

@ -122,3 +122,34 @@ def test_package_version_matches_pyproject() -> None:
match = re.search(r'^version\s*=\s*"([^"]+)"', text, re.MULTILINE)
assert match is not None
assert openspace.__version__ == match.group(1)
def test_get_workflow_roots_include_data_home_logs(
tmp_path: Path, monkeypatch
) -> None:
monkeypatch.setenv("OPENSPACE_HOME", str(tmp_path / "data"))
monkeypatch.delenv("OPENSPACE_DATA_DIR", raising=False)
monkeypatch.setattr(constants, "is_source_checkout", lambda root=None: False)
roots = constants.get_workflow_roots()
data_home = (tmp_path / "data").resolve()
assert data_home / "logs" / "recordings" in [p.resolve() for p in roots]
assert data_home / "logs" / "trajectories" in [p.resolve() for p in roots]
assert not any("benchmarks" in str(p) for p in roots)
def test_get_workflow_roots_include_repo_paths_in_checkout(
tmp_path: Path, monkeypatch
) -> None:
(tmp_path / "pyproject.toml").write_text('[project]\nname="openspace"\n', encoding="utf-8")
pkg = tmp_path / "openspace"
pkg.mkdir()
(pkg / "__init__.py").write_text("", encoding="utf-8")
monkeypatch.setenv("OPENSPACE_HOME", str(tmp_path / "data"))
monkeypatch.delenv("OPENSPACE_DATA_DIR", raising=False)
monkeypatch.setattr(constants, "PROJECT_ROOT", tmp_path)
monkeypatch.setattr(constants, "is_source_checkout", lambda root=None: True)
roots = [str(p) for p in constants.get_workflow_roots()]
assert any(str(tmp_path / "benchmarks" / "gdpval" / "results") == r for r in roots)
assert any("recordings" in r for r in roots)