factory: buzz agent PRs say 'Part of', not 'Closes' — merges never close the ticket and reviews silently drop the Spec axis - #191
Merged
Conversation
added 4 commits
August 13, 2026 11:30
Extracts the "Closes #n / Fixes #n / Resolves #n" regex into a small pure module with unit tests, so review-verdict.ts's issue resolver and the implement runner's new fail-loud PR-body guard share one definition of what counts as a closing keyword instead of drifting independently. Task: #170. Signed-off-by: sandcastle-agent <sandcastle-agent@users.noreply.github.com>
buzz was the sole fleet repo instructing its agent PR-open step to write "Part of #N" and explicitly forbidding "Closes #N" — correct when a human merged and closed by hand, but block#285 made the merge itself the reviewed/gated event, so the ticket now never auto-closes and the unblock dispatcher never fires. Also fixes review-verdict.ts's resolveIssueFromPrBody, which resolves the Spec-axis target issue from that same keyword: buzz PRs always returned null, silently degrading every review to Standards-only. resolveIssueFromPrBody now delegates to the shared matchClosingKeywordIssueNumber (previous commit) instead of duplicating the regex inline. Task: #170 AC1, AC2, AC3. Signed-off-by: sandcastle-agent <sandcastle-agent@users.noreply.github.com>
The open-pr phase is an agent step (open-pr-prompt.md), not deterministic host code, so its "COMPLETE" cannot be trusted any more than the existing push/PR-exists checks it sits next to. After confirming the PR is open, the runner now fetches its body from the host and asserts it contains a same-repo `Closes #<issue>` (or Fixes/Resolves) via the shared matchClosingKeywordIssueNumber. A mismatch or missing keyword fails the job with the same loud, non-zero-exit path as a missing PR, instead of silently submitting a verdict for a PR that will never close its ticket. Verified via a temp-env smoke import (module loads and reaches its first real env check cleanly) and the pinned @biomejs/biome (no new findings on the touched lines; two flagged lines are pre-existing and untouched by this diff). No TypeScript project covers .sandcastle/, so also spot-checked with `tsc --strict --module nodenext` against a synthesized @types/node — same residual .mjs-import warning the pre-existing needs-human-evaluator.mjs import already has, nothing new. Task: #170 AC4. Signed-off-by: sandcastle-agent <sandcastle-agent@users.noreply.github.com>
Review refinements, no behaviour change: - drop the redundant String() around issueNumber (already a string, as every other use in this file assumes) and name the matched value closesIssueNumber. - document why the failure path deliberately skips submitFactoryOpsVerdict: approving a PR that will not close its ticket would let the auto-merge shim re-create the very dead-end the guard prevents. - cover the same-repo-only rule with a cross-repo test case. Signed-off-by: sandcastle-agent <sandcastle-agent@users.noreply.github.com>
ALLiDoizCode
approved these changes
Aug 13, 2026
ALLiDoizCode
left a comment
There was a problem hiding this comment.
Reviewer verdict: CLEAN — approved by factory-ops
This approval is a machine verdict: it attests that the gate passed and the sandcastle reviewer found nothing blocking (reviewed against issue #170, "factory: buzz agent PRs say Part of, not Closes — merges never close the ticket and reviews silently drop the Spec axis", and its acceptance criteria). It is not human judgement. See FACTORY.md, "What a factory-ops approval attests" (toon-protocol/toon-meta#282).
This was referenced Aug 13, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes the factory's open-PR prompt so agent-opened PRs use a
Closes #Nclosing keyword instead ofPart of #N, and adds a guard that fails loudly if an opened PR lacks a closing keyword.Previously, PRs opened by the buzz agent referenced their issue with
Part of #N, which does not trigger GitHub's auto-close on merge — issues stayed open after merge, and review tooling that keys off closing keywords silently dropped the Spec axis. This PR:open-pr-prompt.mdto requireCloses #N, notPart of #NPart of #170
This PR was produced by the sandcastle
agent:implementrunner and is awaiting human review.🤖 Generated with Claude Code