Skip to content

feat(work-items): absorb v4 loop-prompt routing rules into triage skill (#478)#641

Merged
kyle-sexton merged 3 commits into
mainfrom
feat/478-triage-absorb-v4-rules
Jul 20, 2026
Merged

feat(work-items): absorb v4 loop-prompt routing rules into triage skill (#478)#641
kyle-sexton merged 3 commits into
mainfrom
feat/478-triage-absorb-v4-rules

Conversation

@kyle-sexton

Copy link
Copy Markdown
Contributor

Summary

Absorbs bullets 1–4 of the v4 loop-prompt routing rules into the /work-items:triage skill (plugins/work-items/skills/triage/SKILL.md), so the skill owns them instead of a session prompt — per the ratified operator decision on #478 (ACCEPTED option (a) verbatim). Bullet 5 stays deferred to #459 (pointer only); bullet 6 (wayfind:* label semantics) is cross-repo label policy noted on github-iac#176 and left untouched here.

Fix

  • Decision-defaulted ready route — "Triage states" now documents three briefed exits (delegable, decision-defaulted, human-gated). A single-fork item whose brief carries a well-grounded RECOMMENDED answer with only a maintainer-vetoable alternative routes to the autonomous-eligible role with status:ready plus a Decision defaulted: X — veto before merge comment. Step 2 carries the routing test; "Apply outcome" adds the matching row. Human-gated is narrowed to genuinely open decisions (open design space, product intent, cross-repo policy), with capability blockers (external access, manual QA) kept as a distinct non-delegability axis.
  • Cluster-aware routing — "Gather context" adds a cluster-detection cross-reference; "Apply outcome" documents the decision-carrier pattern using the native blocked-by edge and a blocked by #<carrier> decision member comment, with no per-member human-gated label. No new labels.
  • Multi-surface T1 stub — "Apply outcome" adds a lightweight briefing variant for T1 fixes spanning 3+ surfaces (one-line sites + fix pattern comment, autonomous-eligible role, symbol-level durability naming).
  • Severity sub-sort — the priority-label step records the finding's self-labeled severity when a rule sets priority: above it. No new labels.

Version bump 0.13.00.14.0 (read from live origin/main), plus a ## [0.14.0] CHANGELOG entry under plugins/work-items/.

Verification

Acceptance criteria, with the actual text added:

Three briefed exits + narrowed human-gated — "Triage states":

  • delegable — fully specified with no open decision → autonomous-eligible role (default agent-ready).
  • decision-defaulted — a single-fork item whose brief carries a well-grounded RECOMMENDED answer with only a maintainer-vetoable (reversible) alternative → autonomous-eligible role with status:ready, plus a Decision defaulted: X — veto before merge comment.
  • human-gated — reserved for a genuinely open decision (open design space, product intent, or cross-repo policy), or work that cannot be delegated for a capability reason (external access, manual QA) → human-gated role (default needs-human).

Decision-defaulted route + verbatim comment in step 2 and Apply outcome — step 2 "Recommend category + state":

apply the routing test: is the alternative reversible/maintainer-vetoable (→ decision-defaulted: autonomous-eligible role + status:ready, recorded with a Decision defaulted: X — veto before merge comment) or genuinely open …

Apply-outcome row:

| Briefed, decision-defaulted | … Apply labels + the autonomous-eligible role label (default agent-ready) + status:ready, and post a Decision defaulted: X — veto before merge comment |

The comment string's dash is a U+2014 em dash (verified e2 80 94), matching the ratified decision verbatim.

Cluster detection + decision-carrier pattern, no per-member human-gated — "Gather context":

  • Cluster detection — … Designate one representative as the decision carrier (human-gated, with the member numbers listed in its body) and link every other member to it via the native blocked-by edge with a blocked by #<carrier> decision comment …

Apply-outcome:

Decision-carrier clusters. … apply human-gated to the carrier only … Each other member instead gets a native blocked-by edge to the carrier plus a blocked by #<carrier> decision comment — never a per-member human-gated label.

T1 multi-surface stub + durability rule — Apply-outcome row:

| Briefed, T1 multi-surface stub | For a trivial (T1) fix spanning 3+ surfaces: in place of a full brief, post a one-line sites + fix pattern comment and apply the autonomous-eligible role label (default agent-ready). The brief durability rule still holds — name sites by interface / symbol / domain concept, not file paths or line numbers (recommended default: symbol-level naming) |

Severity sub-sort — priority-label step:

when a directive or category rule sets this label above the finding's self-labeled severity, record the original severity in the triage comment (e.g. priority set to pX by <rule>; reporter severity: <sev>) …

Bullet 5 pointer only — Direction gate, appended sentence, no fix text:

Formalizing this as the autonomous-mode contract — codifying that standing-lane rules constitute direction — is tracked in #459.

wayfind:* unchangedgrep wayfind over the skill returns no matches before or after this change.

Checks run locally on the changed files: markdownlint-cli2 → 0 errors; check-skill-portability.sh --paths … SKILL.md → no unexcused coupling tokens; plugin.json parses as valid JSON. The six existing triage evals assert PR-as-item, verify-before-interview, decompose exclusion, raw-marker clearing, and autonomous-lane direction — none assert human-gated-vs-defaulted routing, so these additive changes flip no existing eval.

Closes #478

Related

🤖 Generated with Claude Code

https://claude.ai/code/session_01KyLj6oaFVTE6xFuoYCC2KC

…ll (#478)

Absorb bullets 1-4 of the v4 loop-prompt routing rules into
/work-items:triage so the skill owns them instead of a session prompt:

- Decision-defaulted ready route: third briefed exit alongside delegable
  and human-gated; single-fork items with a well-grounded RECOMMENDED
  answer and a maintainer-vetoable alternative route to autonomous-eligible
  + status:ready with a "Decision defaulted: X — veto before merge" comment.
  Routing test added to step 2; human-gated narrowed to genuinely open
  decisions (or capability blockers).
- Cluster-aware routing: cluster-detection cross-reference in Gather
  context; one decision carrier (human-gated), members linked via native
  blocked-by edge + "blocked by #<carrier> decision" comment, no per-member
  human-gated label.
- Multi-surface T1 stub: one-line "sites + fix pattern" comment variant for
  T1 fixes spanning 3+ surfaces; symbol-level durability naming.
- Severity sub-sort: record self-labeled severity when a rule sets priority
  above it.

Bullet 5 (autonomous-mode contract) captured only as a pointer to #459.
Bullet 6 (wayfind:* semantics) untouched — cross-repo label policy noted on
github-iac#176.

Version bump 0.13.0 -> 0.14.0.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KyLj6oaFVTE6xFuoYCC2KC
@kyle-sexton kyle-sexton added the automated Opened by automation. label Jul 20, 2026
@claude

claude Bot commented Jul 20, 2026

Copy link
Copy Markdown

Claude finished @kyle-sexton's task in 2m 32s —— View job


PR Review — feat(work-items): absorb v4 loop-prompt routing rules into triage skill (#478)

  • Gather context and read PR diff
  • Review plugin.json version bump
  • Review CHANGELOG.md entry
  • Review SKILL.md routing rule changes
  • Verify alignment with CLAUDE.md guidelines
  • Post final review

Overall verdict: approve with minor notes. The changes are well-structured, internally consistent, and correctly implement the four stated routing rules. No blocking issues found. Notes below are observations and one potential ambiguity worth a follow-up issue.


plugin.json

plugins/work-items/.claude-plugin/plugin.json

Version bump 0.13.00.14.0 is correct for additive skill behavior. The description field still doesn't reference the new routing distinctions, but it's already long and this isn't typically where behavior details live. No issue.


CHANGELOG.md

plugins/work-items/CHANGELOG.md

Entry is well-structured, follows Keep a Changelog convention (no date for unreleased is acceptable here), and the Added/Changed split is correct — the human-gated narrowing is a changed behavior rather than a new feature, so its placement under ### Changed is right.


SKILL.md — routing rule changes

✅ Decision-defaulted route

Line 53–57, line 95, line 124

The three-exit definition (delegable / decision-defaulted / human-gated) is coherent and the routing test in step 2 (reversible/maintainer-vetoable → defaulted; genuinely open → human-gated) is crisp and implementable. The em dash in Decision defaulted: X — veto before merge is correctly U+2014 throughout.

⚠️ Note: delegable exit not labeled in the ASCII diagram

Line 59–65

raw → verified → briefed → autonomous-eligible (role label, default agent-ready)
 |        |          ├→ decision-defaulted → …
 |        |          └→ human-gated …

The diagram's straight-through line (briefed → autonomous-eligible) implicitly represents the delegable path, but it isn't labeled as such. Now that all three exits are named in the prose above, a reader scanning only the diagram won't see delegable called out. Low-friction fix: prepend ├→ delegable → on the top line as a branch alongside the other two. Fix this →

⚠️ Note: T1 stub row omits status:ready

Line 125

For a trivial (T1) fix spanning 3+ surfaces: in place of a full brief, post a one-line sites + fix pattern comment and apply the autonomous-eligible role label (default agent-ready).

The briefed state definition (state table, line 48) carries status:ready. The delegable and decision-defaulted rows both result in status:ready on the item. The T1 stub row only mentions agent-ready — no status:ready. This could leave a T1 stub item missing the label the autonomous lane typically expects to see alongside agent-ready for frontier pickup. If the omission is intentional (T1 stubs get a lighter hand-off that doesn't mark them ready), the table row should say so explicitly; if it's an oversight, status:ready should be added.

✅ Cluster detection

Line 87, line 135

The forward reference ("applied in step 5") and the step 5 paragraph correctly close the loop. The "never a per-member human-gated label" constraint is clearly stated. One observation: the carrier-selection criterion ("designate one representative") doesn't specify how to pick the carrier when multiple items qualify (e.g., oldest? highest-severity? reporter's item?). This is left to discretion, which may be intentional to keep the rule simple — but if inconsistent triage behavior surfaces in practice, an explicit tiebreaker rule would be easy to add.

✅ Severity sub-sort

Line 94

The format priority set to pX by <rule>; reporter severity: <sev> is specific and unambiguous. Trailing period is absent on this bullet (minor formatting; other step 2 bullets don't have one either, so it's consistent within the step).

✅ Bullet 5 pointer / wayfind:* untouched

Line 102

Deferred pointer is correctly appended as a non-behavioral sentence. wayfind: produces zero matches in the changed SKILL.md as verified.


CLAUDE.md alignment

  • Repo-agnostic — no hardcoded paths or repo-specific values introduced. ✅
  • Plugin-form-safe — all plugin-internal references continue to use ${CLAUDE_PLUGIN_ROOT}. ✅
  • No PII/secrets — skill definition only, no credentials or personal data. ✅
  • Configurable without editing — no new config scalars; existing userConfig keys unchanged. ✅
  • Security — this is prose instructions, not executable code. The direction gate in step 2 is preserved; cluster-detection writes (blocked-by edge) are correctly deferred to step 5 and gated behind the direction check. No regressions. ✅

Summary

Two notes worth a follow-up if not addressed before merge: (1) label the delegable branch in the ASCII diagram so all three exits are visible there, and (2) clarify whether the T1 stub outcome intentionally omits status:ready. Neither is blocking — the skill is behaviorally correct and internally consistent as written.

- Label the delegable branch in the Triage-states diagram so all three
  briefed exits (delegable, decision-defaulted, human-gated) are visible
  in the diagram, not just in prose.
- Make status:ready explicit on the T1 multi-surface stub outcome: the
  stub replaces the full brief but not the ready-to-work state, matching
  the other autonomous-eligible outcomes.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KyLj6oaFVTE6xFuoYCC2KC
@claude

claude Bot commented Jul 20, 2026

Copy link
Copy Markdown

Claude finished @kyle-sexton's task in 1m 6s —— View job


Review update — previous notes addressed

  • Gather context and identify what changed
  • Read updated SKILL.md to verify review notes were addressed
  • Verify delegable branch labeled in ASCII diagram
  • Verify T1 stub row includes status:ready
  • Post final review verdict

Commit 84e8edd addresses both notes from the prior review. Changes are targeted and correct:

delegable branch now labeled in the diagram

SKILL.md L59–65

The straight-through line has been replaced with an explicit three-branch fork:

raw → verified → briefed
 |        |          ├→ delegable → autonomous-eligible (role label, default agent-ready)
 |        |          ├→ decision-defaulted → autonomous-eligible + status:ready + "Decision defaulted: … — veto before merge"
 |        |          └→ human-gated (role label, default needs-human) — briefed for a human

All three exits are now visible in the diagram, matching the prose definition above it. ✅

✅ T1 stub row now includes status:ready

SKILL.md L125

The row now reads agent-ready + status:ready, with an explicit rationale: "the stub replaces the full brief but not the ready-to-work state, so the item is picked up like any other autonomous-eligible outcome." This aligns the T1 stub with the delegable and decision-defaulted rows. ✅


No new issues introduced. This PR is ready to merge.

@kyle-sexton

Copy link
Copy Markdown
Contributor Author

Review classification (work-2 lane, post-green pass)

# Finding Classification Disposition
1 ASCII state diagram left the delegable exit unlabeled while the other two branches now carry labels VALID (low) Fixed — all three briefed exits (delegable, decision-defaulted, human-gated) now labeled in the diagram
2 T1 multi-surface stub row didn't say whether it carries status:ready like the other two autonomous-eligible outcomes VALID (low) Resolved — added status:ready to the row. The stub replaces the full brief, not the ready-to-work state; matches bullet 3's "still autonomous-eligible" intent from the ratified decision

Both fixed and verified. 17/17 CI green including the review re-run.

@kyle-sexton
kyle-sexton marked this pull request as ready for review July 20, 2026 07:56
@claude

claude Bot commented Jul 20, 2026

Copy link
Copy Markdown

Claude finished @kyle-sexton's task in 1m 10s —— View job


PR Review — feat(work-items): absorb v4 loop-prompt routing rules into triage skill (#478)

  • Gather context and read changed files at HEAD (84e8edd)
  • Verify plugin.json version bump
  • Verify CHANGELOG.md entry
  • Verify SKILL.md routing rule changes
  • Confirm prior review notes were resolved
  • Check CLAUDE.md alignment

This is a third-pass review over the final state of the branch. The two notes from the first review were addressed in commit 84e8edd and confirmed in the second review. This pass re-reads all three changed files at HEAD to confirm the branch is clean.

plugin.json

plugins/work-items/.claude-plugin/plugin.json L4

Version 0.14.0 is present and correct. No other fields changed. ✅

CHANGELOG.md

plugins/work-items/CHANGELOG.md L6–41

## [0.14.0] entry is present, well-structured, and follows Keep a Changelog. Added/Changed split is correct — the human-gated narrowing is a behavioral change, not a new feature, so its placement under ### Changed is right. All four bullets from the PR description are represented. ✅

SKILL.md

Three briefed exitsL53–57: delegable / decision-defaulted / human-gated are defined clearly and consistently. ✅

ASCII diagramL59–66: all three exits are now explicitly labeled as branches (├→ delegable, ├→ decision-defaulted, └→ human-gated). The first review note is fully resolved. ✅

Routing testL96: reversible/maintainer-vetoable → decision-defaulted; genuinely open → human-gated. The test is crisp and implementable. ✅

T1 stub rowL126: now carries agent-ready + status:ready with explicit rationale ("the stub replaces the full brief but not the ready-to-work state"). The second review note is fully resolved. ✅

Cluster detectionL88, L136: carrier pattern closes the loop across steps 1 and 5. "Never a per-member human-gated label" is clearly stated. ✅

Severity sub-sortL95: format priority set to pX by <rule>; reporter severity: <sev> is specific and unambiguous. ✅

Bullet 5 pointerL103: deferred to #459 as a non-behavioral sentence. ✅

wayfind:* untouched: zero matches in the skill file. ✅

Em dashDecision defaulted: X — veto before merge uses U+2014 consistently across the three-exit prose, routing test, and apply-outcome table row. ✅

CLAUDE.md alignment

Rule Status
Repo-agnostic — no hardcoded paths
Plugin-form-safe — ${CLAUDE_PLUGIN_ROOT} refs preserved
Configurable without editing — no new userConfig scalars
No PII / secrets
Versioned — semver bump present
Direction gate preserved, cluster-detection mutations gated to step 5

No issues found. This PR is ready to merge.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 84e8eddafa

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread plugins/work-items/skills/triage/SKILL.md
kyle-sexton added a commit that referenced this pull request Jul 20, 2026
…) (#643)

## Summary

`/work-items:work` selection had no rule excluding an issue that already
has an open linked PR from the pickable frontier. An issue keeps
`status: ready` for its entire window with an open PR (from open through
merge/auto-close), so a picker had to manually cross-check `gh pr list`
to avoid re-picking work already in flight and starting a duplicate
branch. This ships the ratified in-repo open-linked-PR selection filter
(operator decision, 2026-07-19): an issue with an open linked PR is not
pickable.

## Fix

- **Selection-time frontier filter (`skills/work/SKILL.md`, Step 1).**
After `list-frontier` derives the frontier, tiers 2–3 candidates are
additionally filtered to drop any number that has an open PR targeting
it for closure — so an in-flight item leaves the pickable set instead of
being re-picked. The **closing-keyword linkage** is authoritative (the
same `Closes #N` / native-closing-keyword signal `pr-issue-linkage`
enforces); an intentional `Refs #N` opt-out does not exclude its issue.
The filter **fails open** when the bound provider exposes no PR host
(offline `local-markdown` is never a coordination surface and touches no
network tool).
- **New GitHub adapter mechanic
(`tools/work-item-tracker/adapters/github/README.md`, "Open linked
PRs").** The provider mechanics stay in the adapter per this repo's
seam/adapter separation — the skill core inlines no `gh`. It uses `gh pr
list --state open --search "<N> in:body"` (truncation-safe per item, no
page-size race) and a closing-keyword `jq` test with an exact-number
boundary so `#463` does not match `#4630` / `#1463`.
- **Retires the interim heuristic.** The prior "Already-in-flight
(interim, retire on `#463`)" bullet in the execute-step staleness
pre-check is removed — the frontier itself now excludes in-flight items,
which is exactly the retirement that bullet anticipated. Scope-narrowed
to the closing-keyword signal (the interim branch-pattern-only match is
dropped): a standard-flow PR always carries the gate-enforced `Closes
#N`, so keyword-matching is faithful to the ratified "references it as a
closing target" scope.
- **No seam-contract change.** `CONTRACT.md` and `list-frontier` are
untouched; the addition is a README-documented adapter mechanic, not a
new seam verb. The durable seam-level in-review state is explicitly NOT
built here (see Related).

## Verification

The adapter mechanic was exercised against live repo data (read-only).
`<N>` substituted per row:

```
issue #435 open-closing-PR: true    (open, unassigned, status: ready; open PR #638 closes it)
issue #487 open-closing-PR: true    (open, unassigned, status: ready; open PR #629 closes it)
issue #534 open-closing-PR: true    (open, unassigned, status: ready; open PR #634 closes it)
issue #463 open-closing-PR: false   (no open PR closes it → stays pickable)
issue #4630 open-closing-PR: false  (exact-number boundary: does not false-match on #463's PR)
```

Each of #435 / #487 / #534 is a genuine frontier-eligible candidate
(open, unassigned, `status: ready`) that under the old logic stayed
pickable despite an open PR already in flight; the filter returns `true`
for exactly those and excludes them, while #463 (no open closing PR)
returns `false` and remains pickable. `list-frontier` itself was not run
end-to-end here because the `work-items` plugin repo binds no tracker
(`.work-item-tracker.json` is a consuming-repo artifact) — the
per-number filter, which is the added logic, is what is demonstrated
above.

Closes #463

## Related

- #463 — this issue (open-linked-PR selection filter).
- #416 — planning routes through the tracker seam; argues the durable
in-review state belongs at the seam, not a GitHub-only label. This PR
does NOT implement that durable state.
- #498 — seam read-verb coverage; where a durable in-review /
container-scoped read would live. This PR does NOT implement that
durable state.

Note: PR #641 concurrently bumps `work-items` to `0.14.0` (minor, for
#478) and also edits `plugin.json` + `CHANGELOG.md`. This PR is a patch
bump to `0.13.1` from the current `origin/main` base (`0.13.0`) — a
different version slot, not a race — but whichever merges second will
need a mechanical rebase on those two files (the same-plugin concurrency
#464 treats as an awareness note, not a block).

🤖 Generated with a Claude Code implementation subagent (issue #463)

---------

Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
…b-v4-rules

# Conflicts:
#	plugins/work-items/.claude-plugin/plugin.json
#	plugins/work-items/CHANGELOG.md
@claude

claude Bot commented Jul 20, 2026

Copy link
Copy Markdown

Claude finished @kyle-sexton's task in 1m 50s —— View job


PR Review — feat(work-items): absorb v4 loop-prompt routing rules into triage skill (#478)

  • Gather context and read PR diff
  • Review plugin.json version bump
  • Review CHANGELOG.md entry
  • Review SKILL.md routing rule changes
  • Verify alignment with CLAUDE.md guidelines
  • Post final review

This pass covers the current HEAD (1136d09) — a merge of origin/main into the branch that resolved conflicts in plugin.json and CHANGELOG.md. The three changed files from the PR content (ab7d060 + 84e8edd) were already confirmed clean in the two prior review cycles; this pass focuses on whether the merge resolution introduced any issues.

Merge conflict resolution (1136d09)

origin/main gained a 0.13.1 fix release (be8d06e — open-linked-PR exclusion from work frontier) while this branch was in review. Two conflicts:

plugin.json — main: 0.13.1; this branch: 0.14.0. Resolution: 0.14.0. ✅ Correct. 0.14.0 is numerically and semantically above 0.13.1 (additive skill behavior warrants a minor bump).

CHANGELOG.md — main gained a ## [0.13.1] entry; this branch added ## [0.14.0]. Resolution: both entries are present in descending-version order (0.14.00.13.10.13.0). ✅ Keep-a-Changelog convention preserved.

SKILL.md — not in the conflict list; the merge touched no work-items triage files beyond plugin.json and CHANGELOG. The file at HEAD is identical to 84e8edd (the state already confirmed clean). ✅

Previously confirmed (no regressions)

Check Status
Three briefed exits (delegable / decision-defaulted / human-gated) defined and consistent
ASCII diagram labels all three exits explicitly
Routing test (reversible → defaulted; genuinely open → human-gated) in step 2
Decision defaulted: X — veto before merge em dash is U+2014 throughout
T1 stub row carries agent-ready + status:ready with rationale
Cluster detection + decision-carrier pattern; no per-member human-gated label
Severity sub-sort format priority set to pX by <rule>; reporter severity: <sev>
Bullet 5 pointer only (non-behavioral sentence, deferred to #459)
wayfind:* — zero matches in SKILL.md
Repo-agnostic, plugin-form-safe, no PII, configurable without editing

Open Codex finding (#656)

The P2 gap filed by Codex (cluster non-carrier members carry no positive status marker after raw is cleared, so the attention view's "Unlabeled" bucket re-selects them) was triaged as VALID (defer) by the author with the remedy analysis (A/B/C shapes and why A destroys the one-touch property) now living in issue #656. That classification is sound — this is a design decision about the attention-view contract, not a mechanical error in this PR's content. Not blocking.


This PR is ready to merge.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 1136d09840

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread plugins/work-items/skills/triage/SKILL.md
@kyle-sexton
kyle-sexton merged commit e881b3b into main Jul 20, 2026
17 checks passed
@kyle-sexton
kyle-sexton deleted the feat/478-triage-absorb-v4-rules branch July 20, 2026 09:15
kyle-sexton added a commit that referenced this pull request Jul 20, 2026
…sit merge tier

The triage lane records a defaulted (maintainer-vetoable) decision only as a
'Decision defaulted: X — veto before merge' issue comment, which a deterministic
merge gate cannot see (Codex P1 on #641). Add a tier criterion: the PR's linked
issue must carry no unratified decision-default marker. A marker is ratified
only by a human maintainer (authorAssociation OWNER/MEMBER) comment strictly
after it; reactions are not consulted (the reactions API carries no author
association, so a reaction cannot be attributed to a maintainer, and using the
operator's self-logins would let pipeline automation clear its own veto — the
same #450 attribution-drift hazard). Fail closed: an unratified marker, or a
linked issue whose comments cannot be fetched, holds the PR for the human
merge-ready list. Marker matching is deliberately loose (over-matching only
holds more for the human). Reuses fetch_issue_comments and the shared actor_kind
predicate; criterion codified in safety.md. Pass, fall-back, and fetch-error
fixtures added.

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

automated Opened by automation.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

work-items(triage): absorb v4 loop-prompt routing rules into the skill

1 participant