feat: add versioned execution profiles
This commit is contained in:
parent
641e85f5a8
commit
1cd890d871
34 changed files with 2087 additions and 471 deletions
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")
|
||||
Loading…
Add table
Add a link
Reference in a new issue