e2680802 - Gate github-assignment dispatch behind optional policy.json - #50
e2680802 - Gate github-assignment dispatch behind optional policy.json#50Danswar wants to merge 21 commits into
Conversation
…g; surface denials from agent watch assigned.
…xed behavior, document the watch-assigned denial print.
…tring reference, and isolate 4 more deny-tests from the private-repo fallback.
…the README at the policy.json gate.
… requirements to when a policy is actually active.
…mlink policy.json case.
…dom activity uuid.
…wo more bool-vs-int guards.
…s-omitted, and load_policy's docstring.
…lowing them. pathlib's is_file/exists/is_symlink catch any OSError internally, not just FileNotFoundError, so a permission or filesystem error on policy.json read as "no policy" and silently fail-opened the dispatch gate. Use os.lstat/ os.stat directly, which raise, and add a print-denied regression test for watch assigned that was missing test coverage. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015feCXyaLpnyhxuygxAPU2h
|
Ready for review. Four lane verdicts, all
CI (pytest): green at this head. No open review threads or comments. EN: See PR description for scope. Capability only — the admission gate is wired in and tested, but no persona's DE: Siehe PR-Beschreibung für den Umfang. Nur die Fähigkeit — das Admission-Gate ist verdrahtet und getestet, aber noch kein |
|
EN: One behavior needs an explicit product decision before approval: a denied assignment remains at the queue head, so later assignments can be blocked behind it. Confirm that this is the intended operator workflow, or provide an explicit way to skip/quarantine a denied item. The earlier ready comment describes a clean merge state; GitHub now reports conflicts, so that part is stale. |
EN:
dispatch_assignedcurrently starts a coding session for any GitHub issue assignment matched bywatch.json's repo allow-list, with no actor check and no kill switch.jobs.pyalready has a tested, fail-closed admission function (admits()) built for exactly this shape of check, but nothing called it. This adds an optionalpolicy.json(loaded fromAGENT_HOME) consulted via the existingadmits()before a session starts; when the file is absent, behavior is unchanged, so no currently-running persona is affected.jobs.pyis untouched.DE:
dispatch_assignedstartet aktuell für jede GitHub-Issue-Zuweisung, die vonwatch.jsons Repo-Allowlist erfasst wird, eine Coding-Session — ohne Actor-Prüfung und ohne Kill-Switch.jobs.pyhat bereits eine getestete, fail-closed Admission-Funktion (admits()) genau für diese Art Prüfung, die aber bisher nirgends aufgerufen wird. Dieser PR fügt ein optionalespolicy.json(ausAGENT_HOME) hinzu, das vor dem Sessionstart über das bestehendeadmits()geprüft wird; fehlt die Datei, bleibt das Verhalten unverändert — keine aktuell laufende Persona ist betroffen.jobs.pybleibt unangetastet.Details
load_policy(home)— parsesAGENT_HOME/policy.jsonif present,Noneif absent, raises on invalid JSON.scan_assignednow captures the assigning GitHub user's login (payload["assigned_by"]) from theassignedevent'sactor.login, sinceadmits()needs anactor.dispatch_assignedevaluatesadmits(policy, actor=assigned_by, repo=repo, job_type="implement", private=...)before any side effect (workspace files,start,knock,unclaim_wake) and returns"denied"with zero state mutation on refusal, so the same queue head re-evaluates cleanly on the next poll.privateis derived from a newrepos_privatepolicy list (no live GitHub visibility lookup added).policy.jsonis added or turned on in this PR.