Skip to content

factory: a clean verdict clears the needs:human it applied, and only that one - #64

Merged
ALLiDoizCode merged 1 commit into
mainfrom
factory/clear-machine-applied-needs-human
Aug 12, 2026
Merged

factory: a clean verdict clears the needs:human it applied, and only that one#64
ALLiDoizCode merged 1 commit into
mainfrom
factory/clear-machine-applied-needs-human

Conversation

@ALLiDoizCode

Copy link
Copy Markdown
Contributor

Propagation of toon-meta#353 and toon-meta#354 into this repo. No behaviour of this repo's own product changes — only the two .sandcastle/ files that carry the factory fix.

The wedge

The reviewer's BLOCKING verdict applies needs:human as a side effect (toon-meta#282). Nothing ever removed it.

So a PR that went blocking → fixed → clean ended up APPROVED and still carrying the label — and auto-merge.yml refuses on exactly that label (needs-human: PR carries needs:human). Once blocked, gated forever. Structurally the same defect as the dead-agent:implement wedge: a label applied by an automated step that no automated step ever clears.

It stranded connector#923 and connector#935, both of which had to be cleared by hand. The clear could not fire there because connector still carries the old review-verdict.ts — which is the whole reason this propagation exists.

Why ownership-gated and not presence-gated

The naive fix — "a clean verdict clears the label" — trades this bug for a worse one. needs:human is a HUMAN control point (FACTORY.md), so clearing it unconditionally would let a machine overrule a person who applied it deliberately.

So the clear fires only when the most recent application of the label was by the approver identity itself. A human's label is never touched, and a human who re-applies it after a clean verdict keeps it.

That distinction needs the timeline, not the label list: the label list says only that the label is present, never who applied it. labeled/unlabeled events carry the actor and arrive oldest-first, so the last event for the label is the live state.

It fails closed everywhere — an unreadable timeline, an unknown applier, a missing approver identity or a malformed event all leave the label alone. A label that should have been cleared costs a manual edit; one cleared wrongly overrules a person.

What changed

  • .sandcastle/needs-human-evaluator.mjs — new file, the pure ownership rule, copied verbatim from toon-meta. It sits beside its only caller (that was the point of toon-meta#354): scripts/factory/ exists only in toon-meta, so the original import path resolved nowhere else and the fix was correct but unshippable.
  • .sandcastle/review-verdict.ts — the import, a clearsNeedsHuman() helper that fetches the timeline, and an else if branch on the existing if (blocking). Additive only: 75 inserted lines, nothing removed or reordered.

This repo's review-verdict.ts was byte-identical to toon-meta's pre-fix version, so the upstream patch applied cleanly and both files now match toon-meta main byte for byte.

Verification

Gate green. Import resolution confirmed with npx tsx -e "import('./.sandcastle/review-verdict.ts')"OK, which is the check that would have caught toon-meta#354's unresolvable path.

🤖 Generated with Claude Code

…that one

Propagates toon-meta#353 + toon-meta#354 into this repo.

The reviewer's BLOCKING verdict applies `needs:human` as a side effect
(toon-meta#282) and nothing ever removed it. So a PR that went blocking ->
fixed -> clean ended APPROVED *and* still carrying the label, and
auto-merge.yml refuses on exactly that label. Once blocked, gated forever.
It stranded connector#923 and connector#935, both cleared by hand.

The clear is ownership-gated, not presence-gated. `needs:human` is a HUMAN
control point (FACTORY.md), so clearing it unconditionally would let a machine
overrule a person who applied it deliberately. It fires only when the most
recent application of the label was by the approver identity itself — which
needs the TIMELINE, not the label list, because the label list says only that
the label is present, never who applied it. Fails closed everywhere.

- .sandcastle/needs-human-evaluator.mjs: new, the pure ownership rule, copied
  verbatim from toon-meta. It sits beside its only caller because
  scripts/factory/ exists only in toon-meta, so the original import path
  resolved nowhere else (toon-meta#354).
- .sandcastle/review-verdict.ts: additive only (+75 lines) — the import, the
  clearsNeedsHuman() I/O helper, and an else-if branch on the existing
  if (blocking). Nothing in this repo's copy was rewritten.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@ALLiDoizCode
ALLiDoizCode force-pushed the factory/clear-machine-applied-needs-human branch from 617f6c4 to 119dcdd Compare August 12, 2026 21:02
@ALLiDoizCode
ALLiDoizCode merged commit 023bd51 into main Aug 12, 2026
2 checks passed
@ALLiDoizCode
ALLiDoizCode deleted the factory/clear-machine-applied-needs-human branch August 12, 2026 21:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant