glas-harness/tests/test_profiles.py
tegwick 695438019c
Some checks failed
ci / validate (push) Has been cancelled
Harden SSH and profile resolution boundaries
Assistant: codex
Assistant-Model: gpt-5.6-sol
Assistant-Session: 01a0233b-178d-7162-b92f-31a31ea8ca9b
2026-08-23 12:53:05 +02:00

228 lines
6.7 KiB
Python

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",
status: str = "enabled",
rein: str = "rein-test",
required: str = "session_style: unattended",
extra: str = "",
) -> str:
return f"""\
id: {profile_id}
version: \"{version}\"
contract_version: \"{contract}\"
status: {status}
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",
}
assert {
(context.profile.id, context.operational_readiness.status)
for context in contexts
} == {
("harness.agent-dev-local", "blocked"),
("harness.agent-dev-openweights-local", "blocked"),
("harness.agent-dev", "unverified"),
}
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_ready_profile_requires_an_evidence_reference(tmp_path) -> None:
profiles = tmp_path / "profiles"
reins = tmp_path / "reins"
profiles.mkdir()
reins.mkdir()
_write(
profiles,
"profile.yaml",
_profile(
extra="""operational_readiness:
status: ready
reason: proof completed
owner: tests
"""
),
)
_write(reins, "rein.yaml", _rein())
with pytest.raises(ProfileError, match="ready operational status requires evidence_ref"):
ProfileCatalog(profiles, reins).profiles()
def test_undeclared_readiness_defaults_to_unverified(tmp_path) -> None:
profiles = tmp_path / "profiles"
reins = tmp_path / "reins"
profiles.mkdir()
reins.mkdir()
_write(profiles, "profile.yaml", _profile())
_write(reins, "rein.yaml", _rein())
context = ProfileCatalog(profiles, reins).resolve_context("harness.test@1.0.0")
assert context.operational_readiness.status == "unverified"
assert context.operational_readiness.reason == "no operational proof declared"
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")
def test_disabled_revision_still_requires_pinned_selection(tmp_path) -> None:
profiles = tmp_path / "profiles"
reins = tmp_path / "reins"
profiles.mkdir()
reins.mkdir()
_write(profiles, "enabled.yaml", _profile(version="1.0.0"))
_write(
profiles,
"disabled.yaml",
_profile(version="2.0.0", status="disabled"),
)
_write(reins, "rein.yaml", _rein())
catalog = ProfileCatalog(profiles, reins)
with pytest.raises(AmbiguousProfileError, match="pin one of"):
catalog.resolve("harness.test")
with pytest.raises(IncompatibleProfileError, match="profile disabled"):
catalog.resolve("harness.test@2.0.0")
@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")