Skip to content

[finding] the permission classifier blocks the ADDITIVE label write and permits the clobbering one — agents are pushed into the #5533 shape #10686

Description

@claude

Observation-class, measured tonight across two dev-agent runs. No gate is red, and nothing was
lost this time.
Filed unassigned, no pm:queue.

The inversion

This repo's rule for labelling an issue or PR is settled and is in every dispatch brief:

Measured tonight: the safe form was blocked for a dev agent by the session's auto-mode
permission classifier, and the unsafe form went through.
The agent, correctly, reported this
rather than hiding it, and mitigated with a read → union → write → read-back.

That mitigation narrows the race. It does not close it — it is the read-modify-write whose
race #5533 records.

The near miss, from the timeline rather than the report

On PR #10682, the label events are:

timeeventlabelactor
08:33:01Zlabeledsize/mgithub-actions[bot]
08:33:20Zlabeleddocumentationgithub-actions[bot]
08:33:35Zlabeledskip-changesetos-zhuang

No unlabeled event — nothing was dropped, and all three labels are present. But the agent's
whole-set write landed 15 seconds after a bot label it had to have already read. Had
documentation been applied at 08:33:40 instead of 08:33:20, the write would have silently
removed it, and the only symptom would have been a label quietly missing from a merged PR.

The bots are fast and they are not done when the PR opens: size/m at ~6s and documentation at
~25s after creation, in this instance. The window an agent's read-modify-write must survive is
routinely tens of seconds wide.

Why this is a real finding and not a one-off

It is not scope or credentials. The PM seat's own additive POST .../labels calls succeed
repeatedly in this same session and against these same issues (#10303, #10565, #10566, #10667
tonight), as do the targeted DELETE .../labels/<name> calls. The refusal is specific to the
dev-agent context, so it will recur for every agent dispatched, and each one faces the same
choice: violate the brief, or leave the label unset.

The failure mode is the one this repo keeps re-finding: the guidance says do the safe thing, the
tooling only permits the unsafe thing, and the unsafe thing succeeds quietly.
An agent that
follows the brief and stops looks like it failed; an agent that works around it looks like it
succeeded, right up until a bot label disappears.

Directions (not a decision)

  • A — allow POST /issues/{n}/labels in the dev-agent permission set. It is strictly narrower
    than the whole-set write already permitted: it can only add.
  • B — if A is not available, make the brief's instruction terminal: agents report the block and
    the PM applies the label, never a whole-set fallback. I have already switched my own briefs to
    this wording, but it costs a round-trip per PR and only holds for briefs that say it.
  • C — refuse the whole-set write too, so the classifier's ordering at least matches the rule's.
    Cheapest to reason about, and it would have turned tonight's near miss into a loud stop.

A is the one that makes the documented rule the executable one.

Refs

#5533 (the clobber this shape causes) · PR #10682 (where it was measured) · #10603 (the
adjacent "gh is absent" gap in the label tooling)


Generated by Claude Code

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions