feat: add versioned execution profiles
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 1s

This commit is contained in:
tegwick 2026-08-21 00:21:53 +02:00
parent 641e85f5a8
commit 1cd890d871
34 changed files with 2087 additions and 471 deletions

21
tests/test_cli.py Normal file
View file

@ -0,0 +1,21 @@
import json
from pathlib import Path
from glas_harness.cli import main
from glas_harness.contract import ExecutionRequest
def test_profiles_command_lists_committed_constellations(capsys) -> None:
assert main(["profiles", "--json"]) == 0
rows = json.loads(capsys.readouterr().out)
assert {row["rein_id"] for row in rows} == {"rein-aharness", "rein-openweights"}
def test_execution_request_example_matches_contract() -> None:
fixture = Path(__file__).resolve().parents[1] / "examples" / "execution-request.json"
request = ExecutionRequest.model_validate_json(fixture.read_text())
assert request.harness_profile_ref == "harness.agent-dev-local@1.0.0"
assert request.assignment_ref == "role-assignment:agent-7:42"

View file

@ -11,7 +11,7 @@ def test_cli_channel_is_a_channel() -> None:
def _args(**overrides) -> argparse.Namespace:
defaults = dict(
sandbox_profile="profile.bwrap-local",
harness_profile="harness.agent-dev-local@1.0.0",
repo="/tmp/repo",
title="t",
description="d",
@ -28,7 +28,7 @@ def test_parse_invocation_maps_all_fields() -> None:
invocation = channel.parse_invocation(_args())
assert invocation == GatewayInvocation(
sandbox_profile="profile.bwrap-local",
harness_profile="harness.agent-dev-local@1.0.0",
repo="/tmp/repo",
title="t",
description="d",

View file

@ -3,8 +3,18 @@ from unittest.mock import MagicMock, patch
from sandboxer.models import Reachability, SandboxState, SandboxStatus
from glas_harness.contract import Rein, SandboxHandle, ToolCall, ToolResult
from glas_harness.gateway import run_task_through_rein
from glas_harness.contract import (
ExecutionRequest,
ExecutionSummary,
Rein,
SandboxHandle,
ToolCall,
ToolResult,
)
from glas_harness.gateway import run_execution, run_task_through_rein
PROFILE = "harness.agent-dev-local@1.0.0"
class _FakeRein(Rein):
@ -13,6 +23,7 @@ class _FakeRein(Rein):
def start_session(self, profile, inputs, sandbox: SandboxHandle):
self.calls.append("start_session")
assert str(profile.ref) == PROFILE
assert sandbox.sandbox_id == "sbx1"
assert sandbox.reachability.get("workspace_dir") == "/tmp/ws"
return {"session": "s1"}
@ -20,11 +31,24 @@ class _FakeRein(Rein):
def dispatch_tool(self, session, tool_call: ToolCall) -> ToolResult:
self.calls.append("dispatch_tool")
assert tool_call.name == "run_task"
return ToolResult(ok=True, output="done")
return ToolResult(
ok=True,
output="sensitive direct output",
events=[{"type": "tool_use"}],
events_completeness="complete",
tokens_spent=123,
resolved_model="claude-sonnet-4-6",
)
def end_session(self, session):
self.calls.append("end_session")
return {"commit_sha": "deadbeef", "committed": "True"}
return ExecutionSummary(
committed=True,
commit_sha="deadbeef",
outcome="succeeded",
tokens_spent=123,
resolved_model="claude-sonnet-4-6",
)
def _fake_status(sandbox_id: str = "sbx1") -> SandboxStatus:
@ -42,29 +66,39 @@ def _fake_status(sandbox_id: str = "sbx1") -> SandboxStatus:
)
def test_run_task_through_rein_creates_and_destroys_sandbox() -> None:
def _request(*, profile: str = PROFILE, report_to_hub: bool = False) -> ExecutionRequest:
return ExecutionRequest(
harness_profile_ref=profile,
repo="/tmp/repo",
title="t",
description="d",
request_id="req-1",
correlation_id="corr-1",
assignment_ref="assignment:42",
report_to_hub=report_to_hub,
)
def test_run_execution_creates_and_destroys_sandbox() -> None:
manager = MagicMock()
manager.create.return_value = _fake_status()
rein = _FakeRein()
result = run_task_through_rein(
sandbox_profile="profile.bwrap-local",
repo="/tmp/repo",
title="t",
description="d",
rein=rein,
manager=manager,
report_to_hub=False,
)
result = run_execution(_request(), rein=rein, manager=manager)
assert rein.calls == ["start_session", "dispatch_tool", "end_session"]
manager.create.assert_called_once()
manager.destroy.assert_called_once_with("sbx1")
assert result["tool_ok"] is True
assert result["summary"]["committed"] == "True"
assert result.ok is True
assert result.evidence.profile_ref == PROFILE
assert result.evidence.rein_id == "rein-aharness"
assert result.evidence.commit_sha == "deadbeef"
assert result.evidence.tokens_spent == 123
assert result.evidence.refs["assignment_ref"] == "assignment:42"
assert result.tool_output == "sensitive direct output"
def test_run_task_through_rein_destroys_sandbox_even_on_failure() -> None:
def test_run_execution_normalizes_execution_failure_and_tears_down() -> None:
manager = MagicMock()
manager.create.return_value = _fake_status()
@ -72,94 +106,89 @@ def test_run_task_through_rein_destroys_sandbox_even_on_failure() -> None:
def dispatch_tool(self, session, tool_call):
raise RuntimeError("boom")
rein = _FailingRein()
try:
run_task_through_rein(
sandbox_profile="profile.bwrap-local",
repo="/tmp/repo",
title="t",
description="d",
rein=rein,
manager=manager,
report_to_hub=False,
)
except RuntimeError:
pass
result = run_execution(_request(), rein=_FailingRein(), manager=manager)
assert result.ok is False
assert result.evidence.outcome == "failed"
assert result.evidence.failure_stage == "execution"
assert result.evidence.error == "execution failed; inspect direct caller error"
assert result.tool_error == "boom"
manager.destroy.assert_called_once_with("sbx1")
def test_run_task_through_rein_reports_success_event() -> None:
def test_run_execution_refuses_unknown_profile_before_sandbox() -> None:
manager = MagicMock()
result = run_execution(_request(profile="harness.unknown@1.0.0"), manager=manager)
assert result.ok is False
assert result.evidence.outcome == "refused"
assert result.evidence.failure_stage == "resolution"
assert "unknown harness profile" in (result.evidence.error or "")
manager.create.assert_not_called()
def test_hub_receives_normalized_evidence_without_raw_output() -> None:
manager = MagicMock()
manager.create.return_value = _fake_status()
rein = _FakeRein()
with patch("glas_harness.gateway.hub.post_progress_event", return_value=True) as post:
run_task_through_rein(
sandbox_profile="profile.bwrap-local",
repo="/tmp/repo",
title="t",
description="d",
rein=rein,
manager=manager,
)
result = run_execution(_request(report_to_hub=True), rein=_FakeRein(), manager=manager)
post.assert_called_once()
kwargs = post.call_args.kwargs
assert kwargs["event_type"] == "gateway_run"
assert "ok)" in kwargs["summary"]
assert kwargs["detail"]["ok"] is True
assert kwargs["detail"]["sandbox_id"] == "sbx1"
assert kwargs["detail"]["rein"] == "_FakeRein"
detail = post.call_args.kwargs["detail"]
assert detail["outcome"] == "succeeded"
assert detail["profile_ref"] == PROFILE
assert "tool_output" not in detail
assert "sensitive direct output" not in str(detail)
assert result.tool_output == "sensitive direct output"
def test_run_task_through_rein_reports_failure_event_and_still_raises() -> None:
def test_hub_failure_detail_excludes_raw_provider_error() -> None:
manager = MagicMock()
manager.create.return_value = _fake_status()
class _FailingRein(_FakeRein):
def dispatch_tool(self, session, tool_call):
raise RuntimeError("boom")
rein = _FailingRein()
raise RuntimeError("provider body containing sensitive material")
with patch("glas_harness.gateway.hub.post_progress_event", return_value=True) as post:
try:
run_task_through_rein(
sandbox_profile="profile.bwrap-local",
repo="/tmp/repo",
title="t",
description="d",
rein=rein,
manager=manager,
)
assert False, "expected RuntimeError to propagate"
except RuntimeError:
pass
post.assert_called_once()
kwargs = post.call_args.kwargs
assert "failed)" in kwargs["summary"]
assert kwargs["detail"]["ok"] is False
assert kwargs["detail"]["error"] == "boom"
assert kwargs["detail"]["result"] is None
def test_run_task_through_rein_skips_hub_when_disabled() -> None:
manager = MagicMock()
manager.create.return_value = _fake_status()
rein = _FakeRein()
with patch("glas_harness.gateway.hub.post_progress_event") as post:
run_task_through_rein(
sandbox_profile="profile.bwrap-local",
repo="/tmp/repo",
title="t",
description="d",
rein=rein,
manager=manager,
report_to_hub=False,
result = run_execution(
_request(report_to_hub=True), rein=_FailingRein(), manager=manager
)
post.assert_not_called()
detail = post.call_args.kwargs["detail"]
assert detail["error"] == "execution failed; inspect direct caller error"
assert "sensitive material" not in str(detail)
assert "sensitive material" in (result.tool_error or "")
def test_wrapper_requires_and_reports_harness_profile() -> None:
manager = MagicMock()
manager.create.return_value = _fake_status()
result = run_task_through_rein(
harness_profile=PROFILE,
repo="/tmp/repo",
title="t",
description="d",
rein=_FakeRein(),
manager=manager,
report_to_hub=False,
)
assert result["ok"] is True
assert result["evidence"]["profile_ref"] == PROFILE
def test_teardown_failure_is_visible_in_evidence() -> None:
manager = MagicMock()
manager.create.return_value = _fake_status()
manager.destroy.side_effect = RuntimeError("cannot teardown")
result = run_execution(_request(), rein=_FakeRein(), manager=manager)
assert result.ok is False
assert result.evidence.failure_stage == "teardown"
assert result.evidence.error == "teardown failed; inspect direct caller error"
assert result.tool_error == "cannot teardown"

164
tests/test_profiles.py Normal file
View file

@ -0,0 +1,164 @@
from pathlib import Path
import pytest
from glas_harness.profiles import (
AmbiguousProfileError,
IncompatibleProfileError,
ProfileCatalog,
ProfileError,
UnknownProfileError,
)
from glas_harness.reins.rein_aharness import ReinAharness
from glas_harness.reins.rein_openweights import ReinOpenWeights
def _write(path: Path, name: str, text: str) -> None:
(path / name).write_text(text)
def _profile(
*,
profile_id: str = "harness.test",
version: str = "1.0.0",
contract: str = "1.0",
rein: str = "rein-test",
required: str = "session_style: unattended",
extra: str = "",
) -> str:
return f"""\
id: {profile_id}
version: \"{version}\"
contract_version: \"{contract}\"
status: enabled
rein:
id: {rein}
required_capabilities:
{required}
sandbox_profile: profile.test
tool_profile: green-commit-only
model:
provider: test
model: model-1
model_class: other
route: test-route
limits:
budget_tokens: 100
{extra}
"""
def _rein(*, rein_id: str = "rein-test", capability: str = "unattended") -> str:
return f"""\
id: {rein_id}
version: \"1.0.0\"
title: Test rein
handler: glas_harness.reins.rein_aharness:ReinAharness
contract_versions: [\"1.0\"]
capabilities:
session_style: {capability}
status: implemented
"""
def test_committed_catalog_resolves_both_constellations() -> None:
catalog = ProfileCatalog()
contexts = catalog.validate_all()
assert len(contexts) == 3
assert {context.rein_id for context in contexts} == {
"rein-aharness",
"rein-openweights",
}
profile, descriptor = catalog.resolve(
"harness.agent-dev-openweights-local@1.0.0"
)
rein = catalog.build_rein(profile, descriptor)
assert isinstance(rein, ReinOpenWeights)
assert rein.model == "qwen/qwen-2.5-72b-instruct"
assert rein.tool_profile == "green-commit-only"
assert rein.max_turns == 20
assert rein.budget_tokens == 60000
profile, descriptor = catalog.resolve("harness.agent-dev-local@1.0.0")
rein = catalog.build_rein(profile, descriptor)
assert isinstance(rein, ReinAharness)
assert rein.model == "claude-sonnet-4-6"
assert rein.tool_profile == "green-commit-only"
assert rein.budget_tokens == 60000
def test_unknown_profile_fails_closed() -> None:
with pytest.raises(UnknownProfileError, match="unknown harness profile"):
ProfileCatalog().resolve("harness.missing@1.0.0")
def test_unpinned_multi_version_profile_is_ambiguous(tmp_path) -> None:
profiles = tmp_path / "profiles"
reins = tmp_path / "reins"
profiles.mkdir()
reins.mkdir()
_write(profiles, "one.yaml", _profile(version="1.0.0"))
_write(profiles, "two.yaml", _profile(version="2.0.0"))
_write(reins, "rein.yaml", _rein())
with pytest.raises(AmbiguousProfileError, match="pin one of"):
ProfileCatalog(profiles, reins).resolve("harness.test")
@pytest.mark.parametrize(
("profile_text", "match"),
[
(_profile(version="not-semver"), "semantic versioning"),
(_profile(extra="unexpected: true"), "extra_forbidden"),
(_profile(extra="api_key: sk-this-is-inline-and-forbidden"), "inline secret"),
],
)
def test_malformed_or_sensitive_profiles_are_rejected(
tmp_path, profile_text: str, match: str
) -> None:
profiles = tmp_path / "profiles"
reins = tmp_path / "reins"
profiles.mkdir()
reins.mkdir()
_write(profiles, "profile.yaml", profile_text)
_write(reins, "rein.yaml", _rein())
with pytest.raises(ProfileError, match=match):
ProfileCatalog(profiles, reins).profiles()
def test_duplicate_profile_revision_is_rejected(tmp_path) -> None:
profiles = tmp_path / "profiles"
reins = tmp_path / "reins"
profiles.mkdir()
reins.mkdir()
_write(profiles, "one.yaml", _profile())
_write(profiles, "two.yaml", _profile())
_write(reins, "rein.yaml", _rein())
with pytest.raises(ProfileError, match="duplicate harness profile"):
ProfileCatalog(profiles, reins).profiles()
@pytest.mark.parametrize(
("profile_text", "rein_text", "match"),
[
(_profile(contract="2.0"), _rein(), "requires contract 2.0"),
(_profile(rein="rein-missing"), _rein(), "unknown rein"),
(_profile(required="session_style: interactive"), _rein(), "capability"),
],
)
def test_incompatible_profile_or_rein_is_rejected(
tmp_path, profile_text: str, rein_text: str, match: str
) -> None:
profiles = tmp_path / "profiles"
reins = tmp_path / "reins"
profiles.mkdir()
reins.mkdir()
_write(profiles, "profile.yaml", profile_text)
_write(reins, "rein.yaml", rein_text)
with pytest.raises(IncompatibleProfileError, match=match):
ProfileCatalog(profiles, reins).resolve("harness.test@1.0.0")

View file

@ -5,6 +5,7 @@ from unittest.mock import MagicMock, patch
import pytest
from glas_harness.contract import Rein, SandboxHandle, ToolCall
from glas_harness.profiles import ProfileCatalog
from glas_harness.reins.rein_aharness import ReinAharness, ReinAharnessNotInstalled
@ -27,7 +28,7 @@ def test_start_session_writes_task_file_and_captures_head(tmp_path) -> None:
rein = ReinAharness()
sandbox = SandboxHandle(sandbox_id="abc", host="localhost", reachability={"workspace_dir": str(repo)})
session = rein.start_session(
profile={"id": "harness.agent-dev-local"},
profile=ProfileCatalog().resolve("harness.agent-dev-local@1.0.0")[0],
inputs={"title": "t", "description": "d"},
sandbox=sandbox,
)
@ -47,7 +48,11 @@ def test_start_session_requires_resolvable_target_repo() -> None:
def test_dispatch_tool_invokes_agent_harness_cli() -> None:
rein = ReinAharness()
rein = ReinAharness(
model="claude-sonnet-4-6",
tool_profile="green-commit-only",
budget_tokens=1234,
)
session = {"task_file": "/tmp/task.json"}
fake_result = MagicMock(returncode=0, stdout="ok", stderr="")
@ -57,6 +62,9 @@ def test_dispatch_tool_invokes_agent_harness_cli() -> None:
argv = run.call_args.args[0]
assert argv[:3] == ["/usr/bin/agent-harness", "run", "--task-file"]
assert argv[argv.index("--model") + 1] == "claude-sonnet-4-6"
assert argv[argv.index("--tool-profile") + 1] == "green-commit-only"
assert argv[argv.index("--budget-tokens") + 1] == "1234"
assert result.ok is True
assert result.output == "ok"
@ -88,8 +96,9 @@ def test_end_session_detects_new_commit(tmp_path) -> None:
subprocess.run(["git", "commit", "-q", "--allow-empty", "-m", "task"], cwd=repo, check=True)
summary = rein.end_session({"target_repo": str(repo), "head_before": head_before})
assert summary["committed"] == "True"
assert summary["commit_sha"] != head_before
assert summary.committed is True
assert summary.outcome == "succeeded"
assert summary.commit_sha != head_before
def test_end_session_no_new_commit(tmp_path) -> None:
@ -104,7 +113,8 @@ def test_end_session_no_new_commit(tmp_path) -> None:
head = git_head(str(repo))
summary = rein.end_session({"target_repo": str(repo), "head_before": head})
assert summary["committed"] == "False"
assert summary.committed is False
assert summary.outcome == "failed"
def test_dispatch_tool_streams_events_when_enabled() -> None:

View file

@ -5,6 +5,7 @@ from unittest.mock import MagicMock, patch
import pytest
from glas_harness.contract import Rein, SandboxHandle, ToolCall
from glas_harness.profiles import ProfileCatalog
from glas_harness.reins.rein_openweights import ReinOpenWeights, ReinOpenWeightsNotInstalled
@ -27,7 +28,7 @@ def test_start_session_writes_task_file_and_captures_head(tmp_path) -> None:
rein = ReinOpenWeights()
sandbox = SandboxHandle(sandbox_id="abc", host="localhost", reachability={"workspace_dir": str(repo)})
session = rein.start_session(
profile={"id": "harness.agent-dev-local"},
profile=ProfileCatalog().resolve("harness.agent-dev-openweights-local@1.0.0")[0],
inputs={"title": "t", "description": "d"},
sandbox=sandbox,
)
@ -63,7 +64,12 @@ def test_dispatch_tool_invokes_rein_openweights_cli() -> None:
def test_dispatch_tool_passes_model_when_set() -> None:
rein = ReinOpenWeights(model="meta-llama/llama-3.1-70b-instruct")
rein = ReinOpenWeights(
model="meta-llama/llama-3.1-70b-instruct",
max_turns=8,
budget_tokens=1234,
tool_profile="green-commit-only",
)
session = {"task_file": "/tmp/task.json"}
fake_result = MagicMock(returncode=0, stdout="ok", stderr="")
@ -74,6 +80,9 @@ def test_dispatch_tool_passes_model_when_set() -> None:
argv = run.call_args.args[0]
assert "--model" in argv
assert "meta-llama/llama-3.1-70b-instruct" in argv
assert argv[argv.index("--max-turns") + 1] == "8"
assert argv[argv.index("--budget-tokens") + 1] == "1234"
assert argv[argv.index("--tool-profile") + 1] == "green-commit-only"
def test_dispatch_tool_reports_failure() -> None:
@ -102,5 +111,6 @@ def test_end_session_detects_new_commit(tmp_path) -> None:
subprocess.run(["git", "commit", "-q", "--allow-empty", "-m", "task"], cwd=repo, check=True)
summary = rein.end_session({"target_repo": str(repo), "head_before": head_before})
assert summary["committed"] == "True"
assert summary["commit_sha"] != head_before
assert summary.committed is True
assert summary.outcome == "succeeded"
assert summary.commit_sha != head_before