Skip to content

fix(work-items): triage outcomes must clear the raw-intake marker - #527

Merged
kyle-sexton merged 2 commits into
mainfrom
fix/488-triage-clear-raw-marker
Jul 19, 2026
Merged

fix(work-items): triage outcomes must clear the raw-intake marker#527
kyle-sexton merged 2 commits into
mainfrom
fix/488-triage-clear-raw-marker

Conversation

@kyle-sexton

Copy link
Copy Markdown
Contributor

Summary

The work-items:triage skill's "Apply outcome" step (step 5) listed the labels each terminal outcome adds but never said to remove the raw-intake marker (status:needs-triage). Applying an outcome therefore stacked status:ready + the role label on top of needs-triage. The attention view lists open items and re-selects anything still carrying the raw marker, so every triaged item re-entered triage forever — the silent-loop-kill class (#480).

Fix

Two edits to plugins/work-items/skills/triage/SKILL.md, plus an eval and the version/CHANGELOG bump. Marker clearing is stated once as a normalization principle covering all rows (rather than repeated per row).

Step 5 lead-in (new — before the outcome table):

Every outcome is a transition off raw, not a layer on top of it. Applying an outcome clears the raw-intake marker: remove status:needs-triage (and the item leaves the unlabeled raw state) in the same edit that applies the labels below. The label sets in the table are the item's resulting state, not deltas stacked over status:needs-triage — normalization replaces the raw marker, it never adds to it.

Closing invariant (new — end of step 5):

Closing invariant — no outcome leaves a re-selectable raw item. The attention view lists open items and re-selects anything still carrying the raw marker, so every outcome must leave the item unre-selectable:

  • Outcomes that keep the item open (briefed/ready, a role label, or status:needs-info) clear status:needs-triage. A raw marker alongside status:ready, the autonomous-eligible role label, or the human-gated role label is a contradiction — the attention view reads it as still-raw and re-triages it every cycle. If an item shows both, the briefed state is the truth; clear the stale raw marker.
  • Close (already implemented / wontfix / duplicate) drops the item from the open-only attention frontier, so the raw marker is moot — a closed item never re-triages.

The close/open split is deliberate: an absolute "no outcome leaves a raw marker" is false for closes (closing does not strip labels), so the invariant names the mechanism that actually kills the loop for each branch.

The marker is unambiguously status:needs-triage (Status axis — label-taxonomy.md line 20; Triage states table line 46). The issue's "priority: needs-triage" is a misstatement (the priority: axis encodes p0–p3 urgency), so no new label was invented and the existing state-machine vocabulary is used throughout.

Also added eval #4 (triage-outcome-clears-the-raw-intake-marker) asserting the marker is cleared in the same edit as the outcome labels. Patch bump 0.12.10.12.2 (docs/behavior fix) + ### Fixed CHANGELOG entry.

Verification

Repo-pinned gates on the changed files, all green:

  • markdownlint-cli2 (.markdownlint-cli2.jsonc) on SKILL.md + CHANGELOG.mdSummary: 0 error(s)
  • typos (_typos.toml) on all changed files — exit 0
  • editorconfig-checker (.editorconfig-checker.json) on all 4 changed files — 0 errors
  • scripts/validate-plugins.shAll plugin manifests and the catalog validated
  • scripts/validate-plugin-contracts.mjs33 setup skills and 1586 plugin files checked
  • evals.json + plugin.json parse as valid JSON

Related

Closes #488

🤖 Generated with Claude Code

Step 5 "Apply outcome" listed the labels each outcome adds but never said
to remove status:needs-triage, so applying an outcome stacked status:ready
and the role label on top of the raw marker. The open-only attention view
re-selects any item still carrying the marker, re-triaging the same items
forever (silent-loop-kill class).

Step 5 now frames every outcome as a transition off raw that replaces the
marker, and a closing invariant forbids a raw marker alongside a
briefed/ready or role label on an open item. Adds an eval asserting the
marker-clearing behavior. Patch bump 0.12.1 -> 0.12.2.

Closes #488

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011V31qpAHP3jfs76B9d5Rfo
@claude

claude Bot commented Jul 19, 2026

Copy link
Copy Markdown

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


PR Review

  • Gather context and understand the request
  • Read changed files (SKILL.md, evals.json, plugin.json, CHANGELOG.md)
  • Verify the fix logic and invariant language
  • Check eval correctness and coverage
  • Verify version bump and CHANGELOG format
  • Post review findings

Summary: The fix is correct and well-scoped. The silent-loop bug is real — the outcome table was adding labels without clearing the raw marker, and the attention view's open-item + raw-marker query would re-select the item on every triage cycle. No blocking issues; one important observation about coverage and a couple of nits.


Findings

🟡 Nit — Eval covers briefed-delegable only; needs-info clearing the marker has no dedicated test

The closing invariant explicitly names status:needs-info as an open outcome that must clear status:needs-triage, but eval #4's prompt only exercises the briefed-for-autonomous path. The needs-info case has its own subtlety (the item returns to the attention view via bucket 3 on reporter reply rather than bucket 2, which is the desired behavior), and it's the only open outcome the eval doesn't prove an agent handles correctly.

evals/evals.json — eval #4 expectations

A fifth eval with #XX currently tagged status:needs-triage; mark it needs-info would close the gap. Not blocking for this PR given the invariant is stated clearly in SKILL.md, but worth a follow-up.


🟡 Nit — Lead-in paragraph position leaves a reading-order ambiguity for needs-info

The lead-in (line 106) says "every outcome clears status:needs-triage". The outcome table row for Needs more info says "status:needs-info + needs-info template comment" with no explicit remove instruction in the Action column. A reader scanning only the table rows could conclude that removing the marker applies only to the briefed/role-label cases unless they also read the closing invariant naming needs-info explicitly. The fix is functionally complete as-is; the observation is only that the table row could add "and clear status:needs-triage" for scanability.

SKILL.mdNeeds more info row, line 112


✅ Fix logic — correct

The "same edit" requirement in the lead-in paragraph handles atomicity correctly: if the remove and add were separate calls there would be a race window. Naming the simultaneous mutation collapses that window.

The close branch being called out separately (raw marker becomes moot, item falls off the open-only frontier) is the right call — an absolute "no outcome ever leaves a raw marker" would be technically false for closes (closing doesn't strip labels), and the current invariant language is precise about why the close branch is safe.

✅ Triage state round-trip for needs-info — correct

Clearing status:needs-triage when applying needs-info does not orphan the item. The attention view bucket 3 (status:needs-info with reporter activity) picks it back up on re-engagement, which is exactly the right re-entry point.

✅ Version bump — correctly scoped

0.12.1 → 0.12.2 is the right level for a docs/behavior fix that adds no new API surface. CHANGELOG format matches existing conventions in this file (no date on version header, consistent with all prior entries).

✅ No security or blocking issues

This is a documentation-only change to a Markdown skill file. None of the REVIEW.md blocking criteria (authorization checks, tenant scoping, secrets, injection, audit logging, atomicity across multiple state writes) apply here.


Verdict: Approve with the eval gap noted as a follow-up suggestion. The fix is correct, the invariant language is precise, and the versioning is right.

Eval #4 exercised only the briefed-delegable open outcome. The closing
invariant names status:needs-info as the other open outcome that must
clear status:needs-triage, and its re-entry path differs (attention-view
needs-info bucket on reporter reply, not the raw-marker bucket). Add
eval #5 to prove an agent clears the raw marker on the needs-info
outcome without orphaning the item.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@claude

claude Bot commented Jul 19, 2026

Copy link
Copy Markdown

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


PR Review

  • Gather context and understand the request
  • Read changed files and new commit
  • Verify the new eval addresses previous feedback
  • Post updated review findings

What changed since the last review

The latest commit (201bee2) adds eval #5triage-needs-info-outcome-clears-the-raw-intake-marker — directly addressing the previous review's nit about missing needs-info coverage.


Findings

✅ Previous nit resolved — needs-info eval is now present and well-scoped

The new eval covers all four distinct aspects of the needs-info clearing path:

  1. Atomicity — marker cleared in the same edit as status:needs-info
  2. Resulting state — open item carries status:needs-info alone, not stacked on status:needs-triage
  3. Non-orphaning — item re-enters the attention view via the needs-info-with-reporter-activity bucket on reporter reply
  4. Loop distinction — distinguishes the desired (bucket 3) re-entry from the silent-loop re-selection a leftover raw marker would cause

The expected_output prose captures all of these, and the four expectations are distinct and non-redundant. This is correct.

evals.json eval #5, lines 59–69


🟡 Remaining nit — table-row scanability (still open, still non-blocking)

The previous review noted that the Needs more info row in the outcome table (line 112) doesn't list an explicit remove step alongside the add. This was not addressed in this PR — which is a valid choice. The lead-in paragraph (line 106) and the closing invariant (lines 122–125) both cover it clearly. The only downside is that a reader scanning only the table row won't see the instruction inline. Logged for awareness; not a merge blocker.


✅ Overall

Both commits are correct. The fix is sound, the eval set now covers all open-outcome paths (briefed-delegable + needs-info), and no new issues were introduced. The second prior nit is the only open item and it is non-blocking.

Verdict: ready to merge.

@kyle-sexton

Copy link
Copy Markdown
Contributor Author

Thanks for the review. Both items are non-blocking nits; classification below.

# Finding Classification Evidence Reacted
1 Eval covers briefed-delegable only; needs-info clearing the marker has no dedicated test VALID — fixed On-thesis coverage gap: needs-info is the other open outcome the closing invariant (SKILL.md L124) names, and its re-entry differs (attention-view needs-info bucket on reporter reply, not the raw-marker bucket). Added eval #5 triage-needs-info-outcome-clears-the-raw-intake-marker proving the marker is cleared without orphaning the item. Commit 201bee2. 👍
2 Needs more info table row could restate "and clear status:needs-triage" for scanability VALID observation — declining the edit The observation (only the closing invariant names needs-info) is accurate, but the lead-in at SKILL.md L106 governs every row uniformly ("remove status:needs-triage … in the same edit that applies the labels below"), and the sibling open-outcome rows (Briefed delegable / needs-human, L110-111) likewise do not restate the clear in their Action column. Singling out the needs-info row would break that uniform pattern and duplicate the lead-in — a DRY/consistency regression per this repo's no-duplication rule. Kept the row consistent with its siblings. 👍

Verdict acknowledged as Approve. No blocking findings.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant