feat: add versioned execution profiles
This commit is contained in:
parent
641e85f5a8
commit
1cd890d871
34 changed files with 2087 additions and 471 deletions
21
tests/test_cli.py
Normal file
21
tests/test_cli.py
Normal 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"
|
||||
|
|
@ -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",
|
||||
|
|
|
|||
|
|
@ -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
164
tests/test_profiles.py
Normal 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")
|
||||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue