Problem
babysit_resolve_thread.py's bulk resolve path (--resolve with no --thread-id) does not
require the per-thread TOCTOU pins that the single-thread path does, so an unattended
worker (--autonomous) can resolve review threads it never vetted.
The pin guard (--expected-comment-count + --expected-last-updated) only fires when
--thread-id is supplied (babysit_resolve_thread.py:319). The documented worker/autopilot flow
resolves in bulk — source-control-babysit-resolve-thread owner/repo#N --allowed-owners <watched-owners> --resolve --include-human (SKILL.md §Autopilot step 2), no --thread-id. In
autonomous mode the tool resolves every isOutdated bot thread; because a worker's own push is
what marks a thread isOutdated, a finding can flip to outdated between the vet snapshot and the
resolve, and the bulk call clears it with no proof it was addressed.
The address-then-resolve discipline is enforced by prose ("address the finding first, then
resolve"), not by the tool: the bulk path trusts the orchestrator instead of pinning each thread.
Reported by Codex on #322 (P2, inline on babysit_resolve_thread.py).
The decision to make
Two shapes, both defensible — needs a call:
- Reject bulk autonomous resolves: in
--autonomous mode, require a pinned --thread-id per
thread (with --expected-comment-count + --expected-last-updated), forcing the orchestrator
to resolve one vetted thread at a time. Safest; changes the worker flow from one bulk call to a
per-thread loop.
- Pin the bulk set: allow bulk autonomous resolve but require a snapshot pin (e.g. the head
SHA the vet was taken against) so a thread that changed since the vet is skipped, not cleared.
Acceptance
- Autonomous bulk resolve can no longer clear a thread that changed since it was vetted.
- The worker/autopilot flow in
SKILL.md and reference/* is updated to the chosen shape.
- Regression test in
test_guards.py (autonomous bulk resolve without pins is refused / skips
changed threads).
Related
Problem
babysit_resolve_thread.py's bulk resolve path (--resolvewith no--thread-id) does notrequire the per-thread TOCTOU pins that the single-thread path does, so an unattended
worker (
--autonomous) can resolve review threads it never vetted.The pin guard (
--expected-comment-count+--expected-last-updated) only fires when--thread-idis supplied (babysit_resolve_thread.py:319). The documented worker/autopilot flowresolves in bulk —
source-control-babysit-resolve-thread owner/repo#N --allowed-owners <watched-owners> --resolve --include-human(SKILL.md §Autopilot step 2), no--thread-id. Inautonomous mode the tool resolves every
isOutdatedbot thread; because a worker's own push iswhat marks a thread
isOutdated, a finding can flip to outdated between the vet snapshot and theresolve, and the bulk call clears it with no proof it was addressed.
The address-then-resolve discipline is enforced by prose ("address the finding first, then
resolve"), not by the tool: the bulk path trusts the orchestrator instead of pinning each thread.
Reported by Codex on #322 (P2, inline on
babysit_resolve_thread.py).The decision to make
Two shapes, both defensible — needs a call:
--autonomousmode, require a pinned--thread-idperthread (with
--expected-comment-count+--expected-last-updated), forcing the orchestratorto resolve one vetted thread at a time. Safest; changes the worker flow from one bulk call to a
per-thread loop.
SHA the vet was taken against) so a thread that changed since the vet is skipped, not cleared.
Acceptance
SKILL.mdandreference/*is updated to the chosen shape.test_guards.py(autonomous bulk resolve without pins is refused / skipschanged threads).
Related