From 820d33ba1ebeb6497bb813ffca961b2a9d17bfdf Mon Sep 17 00:00:00 2001 From: tegwick Date: Tue, 13 Oct 2026 21:18:06 +0200 Subject: [PATCH] Add green-research-commit tool profile (GLAS-WP-0016-T03) Green commit tools plus WebFetch through the sandbox proxy, for the FI research brief Glas profile. No push, no arbitrary shell, no credentials; granted paths stay enforced by the repository grant acceptance policy. Co-Authored-By: Claude Opus 5.5 Assistant: claude-code Assistant-Model: opus Assistant-Process: 269692@bnt-lap001 Assistant-Session: 8077e68a-0985-4b41-898c-2dc602b0d6be --- rein_aharness/profiles.py | 15 +++++++++++++++ tests/test_manifest.py | 13 ++++++++++++- 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/rein_aharness/profiles.py b/rein_aharness/profiles.py index 3b5c646..3fdfdcd 100644 --- a/rein_aharness/profiles.py +++ b/rein_aharness/profiles.py @@ -28,6 +28,11 @@ _GREEN_COMMIT_TOOLS = ( # (see mailscan.py); the session only reads reports and updates queues. _BLUE_MAIL_TRIAGE_TOOLS = _GREEN_COMMIT_TOOLS +# Green-lane research brief: local commit tools plus HTTPS fetch. Egress is +# the sandbox proxy's; granted paths are enforced by the run's repository +# grant acceptance policy. Publication is a separate deterministic publisher. +_GREEN_RESEARCH_COMMIT_TOOLS = _GREEN_COMMIT_TOOLS + ",WebFetch" + @dataclass(frozen=True) class ToolProfile: @@ -61,6 +66,16 @@ PROFILES: dict[str, ToolProfile] = { allowed_tools=_GREEN_COMMIT_TOOLS, lane="green", ), + "green-research-commit": ToolProfile( + name="green-research-commit", + description=( + "Green-lane research commit: green-commit-only tools plus HTTPS " + "fetch through the sandbox proxy. Commits limited to the run's " + "granted paths. No push, no arbitrary shell, no credentials." + ), + allowed_tools=_GREEN_RESEARCH_COMMIT_TOOLS, + lane="green", + ), "blue-mail-triage": ToolProfile( name="blue-mail-triage", description=( diff --git a/tests/test_manifest.py b/tests/test_manifest.py index 4b78c68..ca76b31 100644 --- a/tests/test_manifest.py +++ b/tests/test_manifest.py @@ -184,12 +184,23 @@ def test_load_manifest_missing(tmp_path: Path) -> None: def test_profiles_registry() -> None: names = {p.name for p in list_profiles()} - assert names == {"green-commit-only", "blue-mail-triage"} + assert names == {"green-commit-only", "green-research-commit", "blue-mail-triage"} green = get_profile("green-commit-only") assert "git commit" in green.allowed_tools assert "git push" not in green.allowed_tools +def test_green_research_commit_profile() -> None: + research = get_profile("green-research-commit") + green = get_profile("green-commit-only") + rules = research.allowed_tools.split(",") + assert set(rules) == set(green.allowed_tools.split(",")) | {"WebFetch"} + assert "git push" not in research.allowed_tools + assert not any(rule in {"Bash", "Bash(*)"} for rule in rules) + assert research.available_tools.split(",")[-1] == "WebFetch" + assert research.lane == "green" + + def test_cli_validate_ok(tmp_path: Path) -> None: _write_manifest( tmp_path,