Skip to content

chore(triage): compose/defer over inventing precedence rules; converge to one comment#5242

Merged
bokelley merged 3 commits into
mainfrom
chore/triage-compose-defer-converge
Jun 3, 2026
Merged

chore(triage): compose/defer over inventing precedence rules; converge to one comment#5242
bokelley merged 3 commits into
mainfrom
chore/triage-compose-defer-converge

Conversation

@bokelley

@bokelley bokelley commented Jun 1, 2026

Copy link
Copy Markdown
Contributor

What

Tightens the issue-triage routine's response discipline, after tracing why it mishandled @pkras's WG questions on #5219. Turned out to be two problems — a behavior gap and a prompt/workflow contradiction.

Behavior (what went wrong on #5219)

  1. Invented a normative precedence rule — a "when brand and transformer_id are both present, brand wins on conflict" SHOULD — for a question that's really compose/defer (the buyer chose both inputs; generative output is never pixel-predictable; they evaluate and refine/discard).
  2. Posted an answer, then a self-retraction addendum (Option-A/B) — a public answer-then-walkback trail.

Surface (why it even engaged a PR)

The routine shouldn't have been ungoverned on a PR — except triage-prompt.md claimed "PR conversations are out of scope; the workflow filters them; that's auto-fix's job," while claude-issue-triage.yml does the opposite: it fires on issue_comment for issues and PRs and injects a MODE: PR-feedback block telling the routine to answer PR questions. So the routine followed the payload, with no discipline. (Auto-fix is unrelated — it pushes code fixes, doesn't post WG answers.)

Changes

.agents/routines/triage-prompt.md

  • Step 5 — "Design-question discipline": for "how do these inputs interact / should the spec define X" questions, default to compose / agent-territory / file-an-issue. Don't synthesize a precedence/conflict/MUST/SHOULD rule without a concrete interop (wire-incompatibility) failure. Aesthetic divergence ≠ interop failure.
  • Step 6 — "Finalize before you comment, one comment per run": never answer-then-addend; if a further pass would change the conclusion, you haven't finished synthesizing.
  • Comment engagement rule 6: if a re-run changes a posted conclusion, edit the original comment, don't stack a correction.
  • Replaced the stale "PR conversations are out of scope" paragraph with an accurate MODE: PR-feedback section that routes PR questions through the Step 5 / Step 6 / rule 6 discipline.
  • Two reinforcing entries in the "Never" list.

.github/workflows/claude-issue-triage.yml

  • Tightened the payload's MODE: PR-feedback line to defer to those prompt rules (compose/defer; one coherent reply; edit don't addend) instead of a bare "answer it as a reply comment."

Scope

Prompt + the one workflow string. No protocol/schema/code. Independent of #5219.

🤖 Generated with Claude Code

…nverge to one comment

Two response-discipline fixes prompted by the triage routine's behavior on
PR #5219 (it invented a "brand wins on conflict" SHOULD for what was really a
compose/defer call, then posted an answer followed by a self-retraction addendum):

- Step 5: add "Design-question discipline" — for "how do these inputs interact /
  should the spec define X" questions, default to compose / agent-territory /
  file-an-issue. Don't synthesize a normative precedence/conflict/MUST/SHOULD
  rule absent a concrete *interop* failure (incompatible wire output) — aesthetic
  divergence and unpredictable creative output are not interop failures.
- Step 6: "Finalize before you comment — one comment per run." Never post an
  answer then a correction/addendum; a public answer-then-retraction trail is
  worse than a slightly-later single answer.
- Comment engagement rule 6: if a re-run changes a posted conclusion, EDIT the
  original comment (gh api PATCH), don't stack a new one.
- Two reinforcing entries in the quick-reference "Never" list.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
aao-release-bot[bot]
aao-release-bot Bot previously approved these changes Jun 1, 2026

@aao-release-bot aao-release-bot Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. Clean, targeted prompt fix that names the two failure modes from #5219 and burns rules in at the exact steps where they fired.

Things I checked

  • Step 5 addition at L517–L535: compose/defer default is gated on a concrete interop (incompatible wire output) failure, not aesthetic divergence — the right bar. The list (a/b/c) maps to the actual taxonomy the routine already uses (wire vs. agent-internals vs. out-of-scope).
  • Step 6 addition at L599–L610: "finalize before you comment" lands ahead of the comment-format block, so a reader following Step 6 top-to-bottom hits the rule before drafting. Correct ordering.
  • Engagement rule 6 at L1227–L1235: the gh api -X PATCH repos/<owner>/<repo>/issues/comments/<id> -f body=… syntax is right (issue comments, not review comments — correct surface for issue_comment-routed triage).
  • Two new "Never" entries at L1268–L1271: cross-reference to "Design-question discipline in Step 5" resolves to the new header text. Parity with existing terse-bullet style.
  • Cross-refs: Step 5's "(see Step 6)" → Step 6's new "finalize before you comment" paragraph. Step 6's "see 'Comment engagement (existing threads)'" → the engagement-rules block at L1194+. Both targets exist.
  • Scope claim in PR body holds: prompt-only, no schema, no code, independent of #5219.

Follow-ups (non-blocking)

  • The edit-don't-stack path assumes the routine kept (or can re-derive) the comment id from its own prior run. The new rule 6 covers re-derivation via the comments-list call, but a future tightening could have the routine record the posted comment id in the run summary so the PATCH is one call instead of list-then-patch. Not worth doing now.

Approving. The "two conformant agents producing incompatible wire output" framing for what counts as an interop failure is the load-bearing line in this change — it's the test the routine will actually apply next time someone asks "should the spec define X."

…", workflow routes them in

Tracing why the routine answered WG questions on PR #5219 (the invented
precedence rule + answer-then-addendum) surfaced a prompt/workflow contradiction:

- claude-issue-triage.yml fires on issue_comment for issues AND PRs and injects
  a `MODE: PR-feedback` block telling the routine to answer PR questions — but
  triage-prompt.md claimed "PR conversations are out of scope; the workflow
  filters them; that's auto-fix's job." The workflow does the opposite, so the
  routine ran PR-comment answers ungoverned by the prompt's discipline.

Fixes (same surface as the prior commit on this branch):
- triage-prompt.md: replace the stale "PR conversations are out of scope"
  paragraph with an accurate `MODE: PR-feedback` section that routes PR
  questions through Step 5 (Design-question discipline) + Step 6 (finalize /
  one comment) + rule 6 (edit, don't addend).
- claude-issue-triage.yml: tighten the payload's `MODE: PR-feedback` line to
  defer to those prompt rules (compose/defer; one coherent reply; edit don't
  addend) instead of a bare "answer it as a reply comment".

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…Run type section)

The Run-type `comment.created` entry still said the workflow filters out PR
comments, contradicting the corrected MODE: PR-feedback section. Align it:
PR comments ARE routed here (is_pr + MODE: PR-feedback), handled per the
PR-feedback rules, not as issue triage.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

@aao-release-bot aao-release-bot Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Clean fix for a real misfire. Right shape: reconciles the prompt/workflow contradiction at the source instead of patching the bad comment on #5219.

Things I checked

  • Step 5 "Design-question discipline" (.agents/routines/triage-prompt.md ~L520-538) — the interop-failure gate ("two conformant agents producing incompatible wire output") is the right operational line. Aesthetic divergence / unpredictability / "buyer might not like it" explicitly out. That's the load-bearing distinction.
  • Step 6 "Finalize before you comment — one comment per run" (~L599-611) — directly targets the answer-then-addend trail that produced the Option-A/B walkback on #5219.
  • Comment-engagement rule 6 edit-don't-stack (~L1230-1239) — gh api -X PATCH repos/<owner>/<repo>/issues/comments/<id> is the correct endpoint for issue and PR conversation comments. PR review-line comments are a different endpoint, but those aren't what the routine posts.
  • Workflow ↔ prompt coherence: the YAML MODE: PR-feedback payload now defers to the prompt rules (.github/workflows/claude-issue-triage.yml:191). The stale "PR conversations are out of scope" paragraph is gone; the new MODE: PR-feedback section routes PR questions through the same Step 5 / Step 6 / rule 6 discipline.
  • Triage scope: prompt routine + one-line YAML string. No schema, no auth, no migration, no wire change. No changeset needed.

Follow-ups (non-blocking — file as issues)

  • Asymmetric framing in Step 5. Explicit (a)/(b)/(c) examples for compose/defer, abstract definition for interop. Worth one concrete interop example ("two agents return incompatible field names for the same input") symmetric to the aesthetic-divergence counter-example, otherwise the routine may under-engage on questions that actually are interop.
  • Third category not addressed. Wire-valid interpretation divergence — two agents both emit valid JSON but mean different things by the same field. Fold into the interop gate or explicitly defer.
  • Footer self-check not wired into the PATCH path. Rule 6 names the Triaged by Claude Code footer as the self-check but doesn't say "match on the footer to find the comment id before PATCHing." One sentence closes it.
  • Workflow still inlines fix/question/conversational branches alongside the prompt that now covers them. Either prune the YAML inlines and let the prompt own it, or add a one-line YAML comment marking the duplication as intentional belt-and-suspenders. A future edit to one and not the other reopens the same drift this PR is closing.

Minor nits (non-blocking)

  1. Bullet the 13-line Step 5 paragraph. ~L520-538 packs the landing-pad, the NOT-synthesize rule, the not-interop list, the over-constrains rationale, and the escape hatch into a single block. Five beats want five bullets.
  2. Unicode ellipsis in the example. ~L1233 shows -f body=… with a literal . -f body=<new-body> copy-pastes more reliably.

Approving on the strength of the workflow/prompt reconciliation plus the explicit interop-failure gate. Fix lands at the root cause — the prompt-workflow contradiction — not the symptom on #5219.

@aao-release-bot aao-release-bot Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approving. Fixes a real misfire on #5219 and resolves the prompt/workflow contradiction at the same time — the routine was reading "PR conversations are out of scope" out of the prompt while the workflow was injecting MODE: PR-feedback. Reconciling those is the right shape.

Things I checked

  • Cross-references resolve. Step 5's new "Design-question discipline" cites Step 6; Step 6 cites "Comment engagement (existing threads)"; rule 6 sits inside that section; the new MODE: PR-feedback block names all three; the "Never" list (triage-prompt.md:1283-1287) backs them up. Internally coherent.
  • Workflow ↔ prompt seam. .github/workflows/claude-issue-triage.yml:191 now defers to the prompt ("Follow the MODE: PR-feedback rules in .agents/routines/triage-prompt.md") and the prompt's PR-feedback section (triage-prompt.md:1241-1260) is the actual source of truth. One restatement remains in the payload — load-bearing as a hint, accepted drift risk.
  • The gh api -X PATCH repos/<owner>/<repo>/issues/comments/<id> edit path is the correct endpoint for PR conversation comments delivered by issue_comment events — which is what this workflow fires on.
  • Bright line is checkable. "Concrete interop / wire-incompatibility failure" as the gate for inventing a precedence rule is sharper than "your judgment" — gives the routine something to fail against.
  • No over-correction. Compose/defer is scoped to "how do two inputs interact / should the spec define X" questions, not all PR questions; fix-requests and concrete clarifications still flow.

Follow-ups (non-blocking — file as issues)

  1. Edit semantics aren't pinned. Rule 6 (triage-prompt.md:1227-1238) tells the routine to PATCH the original comment when a re-run changes the conclusion, but doesn't say what the edited body must contain. Without a rule the routine will likely keep the prior answer with strikethrough or "previously I said" framing — which reproduces the answer-then-walkback trail inside one comment. Add: "the edited body stands as the sole answer; no strikethrough, no 'previously I said' annotation; the edit replaces, it does not narrate." Also: if humans have already replied to the original answer, an edit silently rewrites context under their reply — that case probably wants a fresh comment with explicit re-statement, not a PATCH. Worth deciding before the next time this trips.

  2. The interop bright line wants a pinned negative example. Step 5's discipline paragraph (triage-prompt.md:517-535) will hold better if it carries the #5219 case verbatim as its anti-example: "two agents generating different creative output from the same brand + transformer_id is not wire incompatibility; the wire carries the creative artifact, and the buyer evaluates it." Expert framings around "operator reality / migration cost" read as wire-divergent to a sloppy synthesizer — a worked negative is the cheapest guardrail.

  3. Scope of MODE: PR-feedback. Worth stating explicitly that this covers PR conversation comments only — inline review-comment threads fire pull_request_review_comment, a different event the workflow doesn't subscribe to. Today the operational risk is zero (the routine literally won't see those events), but a one-liner in the PR-feedback section prevents a future maintainer from wiring it up without the matching PATCH path. Cheap.

Minor nits (non-blocking)

  1. Workflow restatement will drift. .github/workflows/claude-issue-triage.yml:191 restates "lean compose/defer over inventing precedence/MUST/SHOULD rules" in the payload after pointing at the prompt. If the prompt evolves, this string won't. The deference clause is doing the real work — consider trimming the restatement to a shorter pointer on a follow-up sweep.

LGTM. Follow-ups noted below.

@bokelley bokelley merged commit d05b11e into main Jun 3, 2026
15 checks passed
@bokelley bokelley deleted the chore/triage-compose-defer-converge branch June 3, 2026 23:39
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