revert(ack): restore three-role collaboration scope
This reverts commit a0f1c15b85.
This commit is contained in:
@@ -23,22 +23,13 @@ RECEIPT_VERSION = 1
|
||||
LAUNCH_PROTOCOL_VERSION = 1
|
||||
MAX_ROUNDS = 3
|
||||
|
||||
ROLES = frozenset({"developer", "test", "operator"})
|
||||
REQUIRED_DEFAULT_ROLES = frozenset({"developer", "test"})
|
||||
STANDARD_ONLY_ROLES = frozenset({"test", "operator"})
|
||||
ROLES = frozenset({"developer", "test"})
|
||||
CLIS = frozenset({"codex", "cursor-agent"})
|
||||
TIERS = frozenset({"standard", "strong"})
|
||||
REASONING_EFFORTS = frozenset({"low", "medium", "high", "xhigh"})
|
||||
PERMISSION_MODES = frozenset({"read-only", "workspace-write"})
|
||||
ORCHESTRATION_MODES = frozenset({"orca", "manual"})
|
||||
BASE_ENVIRONMENT_POLICY = "per-cli-allowlist-v1"
|
||||
OPERATOR_ENVIRONMENT_POLICY = "per-cli-plus-operator-publish-v1"
|
||||
ENVIRONMENT_POLICIES = frozenset(
|
||||
{BASE_ENVIRONMENT_POLICY, OPERATOR_ENVIRONMENT_POLICY}
|
||||
)
|
||||
DEFAULT_KEYS = frozenset(
|
||||
{"developer", "test", "operator", "developerUpgraded"}
|
||||
)
|
||||
DEFAULT_KEYS = frozenset({"developer", "test", "developerUpgraded"})
|
||||
|
||||
ORCHESTRATION_FIELDS = frozenset(
|
||||
{
|
||||
@@ -193,16 +184,6 @@ def _is_positive_int(value: Any) -> bool:
|
||||
return isinstance(value, int) and not isinstance(value, bool) and value > 0
|
||||
|
||||
|
||||
def environment_policy_for_role(role: Any) -> str:
|
||||
"""Return the fixed credential policy for a validated worker role."""
|
||||
|
||||
if role == "operator":
|
||||
return OPERATOR_ENVIRONMENT_POLICY
|
||||
if role in {"developer", "test"}:
|
||||
return BASE_ENVIRONMENT_POLICY
|
||||
raise ValueError("role must be developer/test/operator")
|
||||
|
||||
|
||||
def _is_timestamp(value: Any) -> bool:
|
||||
if not isinstance(value, str):
|
||||
return False
|
||||
@@ -230,7 +211,7 @@ def validate_profile(profile: Any, *, where: str = "profile") -> list[str]:
|
||||
permission = profile.get("permissionMode")
|
||||
|
||||
if not isinstance(role, str) or role not in ROLES:
|
||||
errors.append(f"{where}.role: must be developer/test/operator")
|
||||
errors.append(f"{where}.role: must be developer/test")
|
||||
if not isinstance(cli, str) or cli not in CLIS:
|
||||
errors.append(f"{where}.cli: must be codex/cursor-agent")
|
||||
if not isinstance(tier, str) or tier not in TIERS:
|
||||
@@ -250,13 +231,8 @@ def validate_profile(profile: Any, *, where: str = "profile") -> list[str]:
|
||||
elif cli == "cursor-agent" and effort is not None:
|
||||
errors.append(f"{where}.reasoningEffort: Cursor requires null")
|
||||
|
||||
if (
|
||||
isinstance(role, str)
|
||||
and role in STANDARD_ONLY_ROLES
|
||||
and tier != "standard"
|
||||
):
|
||||
label = "Test" if role == "test" else "Operator"
|
||||
errors.append(f"{where}.tier: {label} may only use standard")
|
||||
if role == "test" and tier != "standard":
|
||||
errors.append(f"{where}.tier: Test may only use standard")
|
||||
if tier == "strong" and role != "developer":
|
||||
errors.append(f"{where}.tier: strong may only be used by Developer")
|
||||
|
||||
@@ -292,11 +268,8 @@ def _validate_model_allowlist(value: Any, where: str) -> list[str]:
|
||||
errors.append(f"{role_where}: must not be empty")
|
||||
for tier in sorted(set(tiers) - TIERS, key=repr):
|
||||
errors.append(f"{role_where}: unknown tier {tier!r}")
|
||||
if role in STANDARD_ONLY_ROLES and "strong" in tiers:
|
||||
label = "Test" if role == "test" else "Operator"
|
||||
errors.append(
|
||||
f"{role_where}: {label} cannot define a strong allowlist"
|
||||
)
|
||||
if role == "test" and "strong" in tiers:
|
||||
errors.append(f"{role_where}: Test cannot define a strong allowlist")
|
||||
for tier, models in tiers.items():
|
||||
tier_where = f"{role_where}.{tier}"
|
||||
if tier not in TIERS:
|
||||
@@ -410,7 +383,7 @@ def validate_orchestration(
|
||||
for default_key in sorted(set(defaults) - DEFAULT_KEYS, key=repr):
|
||||
errors.append(f"{where}.defaults: unknown key {default_key!r}")
|
||||
if mode == "orca":
|
||||
for role in sorted(REQUIRED_DEFAULT_ROLES - set(defaults)):
|
||||
for role in sorted(ROLES - set(defaults)):
|
||||
errors.append(f"{where}.defaults: missing role {role!r}")
|
||||
for default_key, profile_id in defaults.items():
|
||||
default_where = f"{where}.defaults.{default_key}"
|
||||
@@ -434,22 +407,6 @@ def validate_orchestration(
|
||||
if profile.get("permissionMode") not in PERMISSION_MODES:
|
||||
errors.append(f"{default_where}: default profile has unsafe permissions")
|
||||
|
||||
operator_profile_id = defaults.get("operator")
|
||||
test_profile_id = defaults.get("test")
|
||||
operator_profile = valid_profiles.get(operator_profile_id)
|
||||
test_profile = valid_profiles.get(test_profile_id)
|
||||
if operator_profile_id is not None and test_profile is None:
|
||||
errors.append(
|
||||
f"{where}.defaults.operator: requires a valid Test default profile"
|
||||
)
|
||||
elif operator_profile is not None and test_profile is not None:
|
||||
for field in ("cli", "tier", "model", "reasoningEffort"):
|
||||
if operator_profile.get(field) != test_profile.get(field):
|
||||
errors.append(
|
||||
f"{where}.defaults.operator: operator default must use "
|
||||
f"the Test default {field}"
|
||||
)
|
||||
|
||||
return errors
|
||||
|
||||
|
||||
@@ -545,7 +502,7 @@ def _validate_created_for(value: Any, where: str) -> list[str]:
|
||||
errors.append(f"{where}.attemptId: must belong to taskId")
|
||||
role = value.get("role")
|
||||
if not isinstance(role, str) or role not in ROLES:
|
||||
errors.append(f"{where}.role: must be developer/test/operator")
|
||||
errors.append(f"{where}.role: must be developer/test")
|
||||
return errors
|
||||
|
||||
|
||||
@@ -614,10 +571,9 @@ def _validate_requested(value: Any, where: str) -> list[str]:
|
||||
elif isinstance(argv, list) and all(isinstance(arg, str) for arg in argv):
|
||||
if argv_hash != canonical_sha256(argv):
|
||||
errors.append(f"{where}.argvHash: does not match argv")
|
||||
if value.get("environmentPolicy") not in ENVIRONMENT_POLICIES:
|
||||
if value.get("environmentPolicy") != "per-cli-allowlist-v1":
|
||||
errors.append(
|
||||
f"{where}.environmentPolicy: must be 'per-cli-allowlist-v1' or "
|
||||
"'per-cli-plus-operator-publish-v1'"
|
||||
f"{where}.environmentPolicy: must be 'per-cli-allowlist-v1'"
|
||||
)
|
||||
return errors
|
||||
|
||||
@@ -766,19 +722,6 @@ def validate_worker_receipt(
|
||||
if binding.get("observedWorktreePath") != worktree.get("path"):
|
||||
errors.append(f"{where}.binding.observedWorktreePath: does not match worktree.path")
|
||||
|
||||
if isinstance(created_for, dict) and isinstance(requested, dict):
|
||||
try:
|
||||
expected_environment_policy = environment_policy_for_role(
|
||||
created_for.get("role")
|
||||
)
|
||||
except ValueError:
|
||||
pass
|
||||
else:
|
||||
if requested.get("environmentPolicy") != expected_environment_policy:
|
||||
errors.append(
|
||||
f"{where}.requested.environmentPolicy: does not match role"
|
||||
)
|
||||
|
||||
if (
|
||||
isinstance(created_for, dict)
|
||||
and isinstance(worktree, dict)
|
||||
@@ -1034,10 +977,7 @@ __all__ = [
|
||||
"RECEIPT_VERSION",
|
||||
"LAUNCH_PROTOCOL_VERSION",
|
||||
"MAX_ROUNDS",
|
||||
"BASE_ENVIRONMENT_POLICY",
|
||||
"OPERATOR_ENVIRONMENT_POLICY",
|
||||
"canonical_sha256",
|
||||
"environment_policy_for_role",
|
||||
"profile_hash",
|
||||
"receipt_hash",
|
||||
"render_worker_argv",
|
||||
|
||||
Reference in New Issue
Block a user