feat(orchestrator): W1 operator tasks, diff previews and bound commit asks
Operator tasks move from the Inbox into Tasks with the Waits on Operator filter. Review and commit asks carry the staged diff; a file whose old or new blob holds an armour line or a detection-pattern match, or every file when no pattern loads, ships only its path, status, mode and counts. The approval binds to the staged tree id from git write-tree, the encoded request body respects the hub limit, and the hub image ships every client module signed.py loads. Committed below the bar on the operator's word 2026-11-12 (no further per-bundle tests, one gate after the merge): the full hub suite and the W1 e2e never ran, two high MEDUSA rows (sandbox_paths.py FLOOR, permission_hook.py ask POST) wait for their acceptance. 🎯 Fix: 85 % 💥 Break: 12 % 💸 Cost: 30 % ⏱️ Time: 30 % 🛡️ Security: 50 % 🏆 Score: 100 🚦 Gate: ⛔ fix 85 % < 90, break 12 % > 5; security 50 % < 100: ask the operator before the commit Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
fd8fc08603
commit
d09ed61161
34 files changed
+2449
-111
No files matched your search
@@ -0,0 +1,67 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import re
|
||||
from pathlib import Path
|
||||
|
||||
from .errors import Missing, ToolError
|
||||
from .records import read_json, write_atomic
|
||||
from .signed import limits
|
||||
|
||||
DIFF_LIMIT = limits.DIFF_LIMIT
|
||||
DIFF_BODY_LIMIT = limits.DIFF_BODY_LIMIT
|
||||
FILE_CAP = limits.FILE_CAP
|
||||
PATH_LIMIT = limits.PATH_LIMIT
|
||||
STATUSES = ("A", "M", "D", "R", "B")
|
||||
DIFF_KEYS = ("path", "status", "mode", "additions", "deletions", "patch", "note")
|
||||
NOTES = ("", limits.WITHHELD)
|
||||
MODE = re.compile(r"[0-7]{6}(?: => [0-7]{6})?")
|
||||
DIFF_SUFFIX = {"review": ".review-diff.json", "ask": ".ask-diff.json"}
|
||||
|
||||
|
||||
def counted(value: object) -> bool:
|
||||
return isinstance(value, int) and not isinstance(value, bool) and value >= 0
|
||||
|
||||
|
||||
def diff_entry(entry: object) -> dict:
|
||||
if not isinstance(entry, dict) or set(entry) != set(DIFF_KEYS):
|
||||
raise ToolError(f"every diff entry must be an object with exactly {', '.join(DIFF_KEYS)}")
|
||||
path, patch, mode = entry["path"], entry["patch"], entry["mode"]
|
||||
if not isinstance(path, str) or not 0 < len(path) <= PATH_LIMIT or entry["status"] not in STATUSES:
|
||||
raise ToolError(f"a diff path must be 1 to {PATH_LIMIT} characters and its status one of {', '.join(STATUSES)}")
|
||||
if not isinstance(mode, str) or not MODE.fullmatch(mode):
|
||||
raise ToolError("mode must be a git file mode, or old => new for a changed one")
|
||||
if not counted(entry["additions"]) or not counted(entry["deletions"]) or not isinstance(patch, str) or (entry["status"] == "B" and patch):
|
||||
raise ToolError("additions and deletions must be counts, patch text, empty for a binary file")
|
||||
if entry["note"] not in NOTES or (entry["note"] and patch):
|
||||
raise ToolError(f"note must be empty or {limits.WITHHELD!r}, the latter with an empty patch")
|
||||
return {key: entry[key] for key in DIFF_KEYS}
|
||||
|
||||
|
||||
def valid_diff(value: object) -> list[dict]:
|
||||
"""Returns:
|
||||
The review diff of requirement 003, checked: at most FILE_CAP
|
||||
entries, and at most DIFF_LIMIT bytes of JSON-encoded patch text in
|
||||
all, the bound the requesting script keeps.
|
||||
"""
|
||||
if not isinstance(value, list) or len(value) > FILE_CAP:
|
||||
raise ToolError(f"diff must be a list of at most {FILE_CAP} files")
|
||||
entries = [diff_entry(entry) for entry in value]
|
||||
if sum(len(json.dumps(entry["patch"], ensure_ascii=False).encode("utf-8")) for entry in entries) > DIFF_LIMIT:
|
||||
raise ToolError(f"the patches of a diff must stay within {DIFF_LIMIT} bytes")
|
||||
return entries
|
||||
|
||||
|
||||
def diff_bytes(diff: list[dict]) -> bytes:
|
||||
return json.dumps({"diff": diff}, ensure_ascii=False).encode("utf-8")
|
||||
|
||||
|
||||
def store_diff(folder: Path, kind_name: str, item_id: str, diff: list[dict]) -> None:
|
||||
write_atomic(folder / f"{item_id}{DIFF_SUFFIX[kind_name]}", diff_bytes(diff))
|
||||
|
||||
|
||||
def stored_diff(folder: Path, kind_name: str, item_id: str) -> dict:
|
||||
data = read_json(folder / f"{item_id}{DIFF_SUFFIX[kind_name]}") if kind_name in DIFF_SUFFIX else None
|
||||
if not isinstance(data, dict) or not isinstance(data.get("diff"), list):
|
||||
raise Missing(item_id)
|
||||
return {"kind": kind_name, "id": item_id, "diff": data["diff"]}
|
||||
Reference in new issue
Block a user