Land HARNESS-WP-0001 T01/T02/T04/T05: extend ADR-005 schedule.yml with harness fields, named tool-profile registry, ADR-004 metrics writes, and BudgetTracker wiring. CLI gains validate/profiles; task-file path kept.
78 lines
2.4 KiB
Python
78 lines
2.4 KiB
Python
"""Named tool-profile registry.
|
|
|
|
Instances declare a profile by name in the instance manifest; the harness
|
|
resolves and enforces the allow-list. Instances never enumerate tools.
|
|
Unknown profile names refuse to run.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from dataclasses import dataclass
|
|
|
|
|
|
class UnknownToolProfileError(ValueError):
|
|
"""Raised when a manifest references a profile that is not registered."""
|
|
|
|
|
|
# Claude Code --allowedTools strings. No push, no network, no arbitrary shell.
|
|
_GREEN_COMMIT_TOOLS = (
|
|
"Read,Write,Edit,Glob,Grep,"
|
|
"Bash(git add:*),Bash(git commit:*),Bash(git status),"
|
|
"Bash(git log:*),Bash(git diff:*),Bash(date:*),Bash(ls:*)"
|
|
)
|
|
|
|
# Blue-lane mail triage session: same session tools as green-commit-only.
|
|
# Credentialed IMAP scan is a deterministic pre-step outside the session
|
|
# (see mailscan.py); the session only reads reports and updates queues.
|
|
_BLUE_MAIL_TRIAGE_TOOLS = _GREEN_COMMIT_TOOLS
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class ToolProfile:
|
|
"""A named hard allow-list for agentic sessions."""
|
|
|
|
name: str
|
|
description: str
|
|
allowed_tools: str
|
|
lane: str # green | blue — advisory; enforcement is the allow-list
|
|
|
|
|
|
PROFILES: dict[str, ToolProfile] = {
|
|
"green-commit-only": ToolProfile(
|
|
name="green-commit-only",
|
|
description=(
|
|
"Green-lane local commit: read/edit tools plus git add/commit/"
|
|
"status/log/diff. No push, no network, no arbitrary shell."
|
|
),
|
|
allowed_tools=_GREEN_COMMIT_TOOLS,
|
|
lane="green",
|
|
),
|
|
"blue-mail-triage": ToolProfile(
|
|
name="blue-mail-triage",
|
|
description=(
|
|
"Blue-lane mail triage session after a credentialed deterministic "
|
|
"scan: same local commit tools as green-commit-only. Credentials "
|
|
"and network stay outside the agentic session."
|
|
),
|
|
allowed_tools=_BLUE_MAIL_TRIAGE_TOOLS,
|
|
lane="blue",
|
|
),
|
|
}
|
|
|
|
|
|
def get_profile(name: str) -> ToolProfile:
|
|
"""Resolve a profile by name. Raises UnknownToolProfileError if missing."""
|
|
key = (name or "").strip()
|
|
if not key:
|
|
raise UnknownToolProfileError("tool_profile name is empty")
|
|
profile = PROFILES.get(key)
|
|
if profile is None:
|
|
known = ", ".join(sorted(PROFILES))
|
|
raise UnknownToolProfileError(
|
|
f"unknown tool_profile '{key}' (known: {known})"
|
|
)
|
|
return profile
|
|
|
|
|
|
def list_profiles() -> list[ToolProfile]:
|
|
return [PROFILES[k] for k in sorted(PROFILES)]
|