Skip to content

feat(#433): add in-progress action for triage agent - #434

Merged
waynesun09 merged 6 commits into
mainfrom
agent/433-in-progress-action
Jul 24, 2026
Merged

feat(#433): add in-progress action for triage agent#434
waynesun09 merged 6 commits into
mainfrom
agent/433-in-progress-action

Conversation

@fullsend-ai-coder

@fullsend-ai-coder fullsend-ai-coder Bot commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Add in-progress triage action to distinguish PRs that fix an issue from true prerequisite PRs. Previously, the "Existing PR gate" forced all addressing PRs into action: "prerequisites" (blocked framing), even when the PR directly resolves the reported problem.
  • The new action clears blocked/ready-to-code/needs-info/pr-open labels as appropriate, applies a pr-open label, and appends an "Addressed by:" section with PR links to the comment.
  • Updated across all four files specified in the issue: agent prompt, JSON schema, post-script handler, and test suite — plus scripts/pre-triage.sh and docs/triage.md to keep pr-open's lifecycle and documentation consistent with the rest of the control-label set.

Changes

  • agents/triage.md — Updated the "Existing PR gate" hard constraint to route fixing PRs to in-progress and true prerequisites to prerequisites; added in-progress action documentation, an Anti-premature-in-progress hard constraint with explicit precedence over Anti-premature-resolution, an isDraft field on the PR search query, and checkable guidance for partial-fix/draft-PR classification.
  • schemas/triage-result.schema.json — Added in-progress to the action enum; added pull_requests array property (required when action is in-progress) with URL pattern validation for /pull/ URLs.
  • scripts/post-triage.sh — Added the in-progress case handler; added pr-open to the control labels array and to the remove_label calls in the other six action handlers so it clears when an issue leaves the in-progress state; creates the pr-open label with its intended description/color before use, matching pre-code.sh's existing convention.
  • scripts/pre-triage.sh — Added pr-open to the label reset list and verification query.
  • scripts/post-triage-test.sh / scripts/validate-output-schema-test.sh — Test cases for the new action, its conditional schema rule, multi-PR handling, and pr-open removal across all six other action handlers.
  • docs/triage.md — Documented the pr-open control label, including that it's also applied independently by the code agent's pre-check.

Test plan

  • All new in-progress test cases pass (comment posting, label mutations, PR link appending, missing comment validation, control label refusal, multi-PR)
  • All pre-existing tests pass (1 pre-existing failure in post-retro-test.sh's proposal tests observed locally, environment-specific — not present in this PR's CI runs and unrelated to this change)
  • Schema validates as correct JSON, including new pull_requests conditional rule, empty-array, and malformed-URL cases
  • Secret scan passes
  • pr-open label is created with its intended description/color (gh label create --force) before being applied, matching pre-code.sh's existing convention

Closes #433

Post-script verification

  • Branch is not main/master (agent/433-in-progress-action)
  • Secret scan passed (gitleaks — e3293716ee87a1b1a6d07a403ccdeba4d724c9b9..HEAD)
  • PR body secret scan passed (gitleaks — no-git)
  • Pre-commit hooks passed (authoritative run on runner)
  • Tests ran inside sandbox

Follow-up commits (post-handoff)

The initial commit reused the same fix that was previously attempted against the wrong repo (fullsend-ai/fullsend#5414, closed). Two follow-up commits close the gaps found there and in a fresh 3-agent review of this PR:

  1. Fixed the deterministic CI failure in additional-properties-lists-known-keys (new pull_requests property wasn't in the expected sorted list), closed the pr-open label-lifecycle gap (never cleared when an issue leaves in-progress) and its missing gh label create fallback, and ported the remaining review feedback from #5414 that applies to this repo's current (more evolved) triage pipeline.
  2. Addressed findings from an independent review (Claude, Grok): moved draft-PR notes from reasoning (never read by post-triage.sh) to comment; added explicit precedence between the two Anti-premature-* hard constraints that could otherwise both apply; rewrote the partial-fix/draft-PR guidance to stop contradicting the prerequisites action's own definition; added regression tests for pr-open removal across all six handlers and schema coverage for empty/malformed pull_requests. One reported finding (a seq-based null-entry bug) was investigated and confirmed to be a false positive specific to BSD/macOS seq — verified against GNU coreutils 9.4 in an ubuntu-24.04 container matching the actual CI runner.

The triage agent's "Existing PR gate" forced every open PR
that addresses an issue into the prerequisites action, which
applies the blocked label. When a PR directly fixes an issue,
that framing is incorrect — the issue is being resolved, not
blocked.

Add a new in-progress action that distinguishes fixing PRs
from true prerequisite PRs:

- agents/triage.md: update the Existing PR gate to route
  fixing PRs to in-progress and true prerequisites to
  prerequisites; add in-progress action documentation
- schemas/triage-result.schema.json: add in-progress to the
  action enum; add pull_requests array property required
  when action is in-progress
- scripts/post-triage.sh: add in-progress handler that
  clears blocked/ready-to-code/needs-info, applies pr-open
  label, and appends Addressed by section with PR links;
  add pr-open to control labels
- scripts/post-triage-test.sh: add test cases covering
  comment posting, label mutations, PR link appending,
  missing comment validation, and control label refusal;
  update mock to capture stdin for plain comments

Closes #433
@fullsend-ai-coder
fullsend-ai-coder Bot requested a review from a team as a code owner July 24, 2026 13:56
The re-ported fix for #433 (agents/triage.md, the triage-result
schema, post-triage.sh, and their tests) carried over the same gaps
that were flagged during review of the original attempt at this fix,
fullsend-ai/fullsend#5414, which targeted a
deprecated scaffold copy and was closed in favor of this PR.

- Fix additional-properties-lists-known-keys: the expected sorted
  property list didn't include the new pull_requests field, so this
  test failed deterministically in CI.
- Add valid-in-progress / in-progress-missing-pull-requests schema
  validation coverage for the in-progress conditional rule.
- Clear pr-open in every handler that already clears blocked
  (insufficient, duplicate, prerequisites, sufficient, question,
  not-planned), and add pr-open to pre-triage.sh's label reset list
  and verification query. Without this, pr-open stuck permanently
  once an issue left the in-progress state, and label_actions
  couldn't remove it either since it's a control label.
- Create the pr-open label with its intended description/color
  before applying it, matching the convention pre-code.sh already
  uses for the same label.
- Document pr-open in the triage agent's control-label reference
  (the table and the issue-labels skill example).
- Add isDraft to the PR search query and give the agent guidance on
  classifying partial fixes and draft PRs, plus a matching
  Anti-premature-in-progress hard constraint alongside the other
  action's constraints.
- Add a multi-PR test case for the in-progress action.

Assisted-by: Claude
Signed-off-by: Wayne Sun <gsun@redhat.com>
…y review

Independent 3-agent review (Claude, Grok) of the previous commit surfaced
several real gaps, each verified against the actual code and CI runtime
before fixing:

- agents/triage.md's new "note the draft status in `reasoning`" guidance
  pointed at a field post-triage.sh never reads (only `.action` and
  `.comment` reach GitHub) -- moved to `comment`.
- The Anti-premature-in-progress and Anti-premature-resolution hard
  constraints could both apply with no stated precedence when a fixing
  PR is open but the issue still has user-facing gaps -- in-progress now
  explicitly takes priority, with remaining gaps surfaced via `comment`.
- The partial-fix/draft-PR guidance contradicted the `prerequisites`
  action's own "does not itself fix the issue" definition and gave no
  checkable criteria for "trivial" vs "substantial" -- rewritten around
  Fixes/Closes references, with an explicit fallback and a precedence
  rule for the fixing-PR-plus-separate-blocker case.
- pr-open's removal on the six actions that leave the in-progress state
  (insufficient, duplicate, prerequisites, sufficient, question,
  not-planned) had no regression coverage -- added one test per handler.
- Added schema coverage for `pull_requests: []` and a malformed PR URL,
  mirroring the existing `prerequisites` fixture coverage.
- docs/triage.md's pr-open row only credited the `in-progress` action;
  pre-code.sh also applies pr-open independently -- documented both
  sources and pr-open's staleness if the linked PR is abandoned.
- Corrected the CONTROL_LABELS comment in post-triage.sh, which was
  already inaccurate before this PR.

One reviewer-reported finding was investigated and found to be a false
positive: a claimed `seq 0 $((PR_COUNT - 1))` null-entry bug when
PR_COUNT is 0. Verified against GNU coreutils 9.4 in an ubuntu-24.04
container (matching the CI runner) that `seq 0 -1` produces zero
iterations there, not two -- the behavior only reproduces on BSD/macOS
`seq`. The path is additionally unreachable in production since the
schema requires `pull_requests` to be non-empty whenever action is
"in-progress".

Assisted-by: Claude (fix, review), Grok (review)
Signed-off-by: Wayne Sun <gsun@redhat.com>
Two independent re-review passes (Claude x2) found that the previous
commit added explicit precedence for Anti-premature-in-progress over
Anti-premature-resolution, but left an analogous, unaddressed conflict
with the untouched Anti-premature-prerequisites rule: a fixing PR plus
a separate genuine blocker (PR or issue) could be read as requiring
both `in-progress` and `prerequisites` with no stated tie-break.

- Extended the Existing PR gate's fixing-PR-plus-separate-blocker
  sentence to also cover a separate blocking *issue*, not just a PR.
- Added a reciprocal exception to Anti-premature-prerequisites and an
  explicit precedence clause to Anti-premature-in-progress, so the
  tie-break is stated from both rules regardless of which one an
  agent (or future editor) reads first.

Both re-review passes also independently re-verified the `seq`
false-positive conclusion from the prior commit against a real
ubuntu-24.04/GNU-coreutils-9.4 container (one of them starting from a
stale memory of its own that wrongly generalized BSD/macOS `seq`
behavior to GNU, and self-correcting after re-testing) -- no code
change needed there, already covered by the previous commit's message.

Assisted-by: Claude
Signed-off-by: Wayne Sun <gsun@redhat.com>
@waynesun09

Copy link
Copy Markdown
Member

/review
/fs-review

@qodo-code-review

Copy link
Copy Markdown

PR Reviewer Guide 🔍

Warning

/review is deprecated. Use /agentic_review instead (removal date not yet scheduled).

Here are some key observations to aid the review process:

⏱️ Estimated effort to review: 3 🔵🔵🔵⚪⚪
🧪 PR contains tests
🔒 No security concerns identified
⚡ No major issues detected

@waynesun09

Copy link
Copy Markdown
Member

/fs-review

@fullsend-ai-review

fullsend-ai-review Bot commented Jul 24, 2026

Copy link
Copy Markdown

🤖 Finished Review · ✅ Success · Started 3:54 PM UTC · Completed 4:13 PM UTC
Commit: 856e095 · View workflow run →

@fullsend-ai-review

Copy link
Copy Markdown

Review

Findings

Medium

  • [protected-path] agents/triage.md, scripts/post-triage.sh, scripts/post-triage-test.sh, scripts/pre-triage.sh, scripts/validate-output-schema-test.sh — PR modifies files under protected paths (agents/, scripts/). The linked issue (Triage agent incorrectly marks issue as blocked #433) explicitly authorizes changes to agents/triage.md, schemas/triage-result.schema.json, scripts/post-triage.sh, and scripts/post-triage-test.sh. The additional protected files (scripts/pre-triage.sh, scripts/validate-output-schema-test.sh) are justified for label lifecycle consistency and test coverage. Human approval is always required for protected-path changes, regardless of context.

Low

  • [gh-label-create-inconsistency] scripts/post-triage.sh — The in-progress handler uses gh label create --force for the pr-open label. This follows scripts/pre-code.sh's existing convention for creating the same label but is new to post-triage.sh. Non-actionable — the pattern is consistent with the existing pr-open label lifecycle.

  • [commit-type-mismatch] — PR title uses feat(#433) but issue Triage agent incorrectly marks issue as blocked #433 is labeled bug. The feat type is defensible: while the issue describes incorrect behavior, the solution introduces a new in-progress action type — a new agent behavior per COMMITS.md's definition of feat. Non-actionable.

@fullsend-ai-review fullsend-ai-review Bot added the requires-manual-review Review requires human judgment label Jul 24, 2026
A multi-agent review of this branch surfaced one high and five medium
findings against the new in-progress action. Address them:

- The Existing PR gate told the agent to prefer `prerequisites` when it
  could not tell a fixing PR from a true prerequisite. That contradicted
  the Anti-premature-in-progress hard constraint, which only exempts PRs
  positively determined to be prerequisites, and routed every ambiguous
  PR back to the `blocked` framing this issue was filed to stop. Flip the
  tiebreak to `in-progress` and reword the constraint to match.

- The handler applied `pr-open` and posted "an open PR addresses this
  issue" without checking that any PR URL was actually present, so an
  empty `pull_requests` produced a claim with nothing to link. The schema
  requires the field, but the agent is instructed to emit its best JSON
  after three failed validation attempts, so re-check it here. Replace
  the seq/xargs URL loop with a read over `jq -r`, which renders a
  byte-identical comment and drops the platform-dependent seq bounds.

- in-progress is a durable status but posted a fresh comment on every
  run, and triage re-runs on every issue edit. Route it through the
  sticky comment path under its own marker so re-runs update in place.

- Triage discovered PRs with an unfiltered listing capped at 50 while the
  code agent's pre-check uses a targeted search, so the gate could
  silently miss a PR and fall through to `sufficient`. Add the targeted
  search and state that coder-bot PRs count for the gate.

- A result carrying both `prerequisites` and `pull_requests` had the
  former dropped with no trace. Warn instead, matching how the script
  already reports refused control labels.

- The `pr-open` docs implied recovery was automatic. State plainly that
  nothing clears the label when the linked PR closes unmerged, and define
  in-progress against prerequisites while there.

Also fix two wording defects in the same regions: the comment template
asked the agent to link PRs the post-script appends anyway, and the
"an open PR already addresses this issue" bullet sat under blocking
relationships, priming the agent on `blocked` before it reached the gate.

Assisted-by: Claude (fix, review), Grok (review)
Signed-off-by: Wayne Sun <gsun@redhat.com>
Follow-up review of the previous commit found the jq call that collects
PR URLs had moved into a process substitution, where its exit status is
invisible to set -e. A pull_requests that clears the count check but is
not an array of objects — a bare string, a number, an array of strings —
then rendered an empty "Addressed by:" list and continued, applying
pr-open and posting the linkless comment the count guard exists to
prevent. The previous code aborted before any label mutation. Capture
with command substitution again, and use jq -e so a null url fails too.

Also:

- Warn about dropped prerequisites only when there is something to drop;
  an empty existing/create pair is schema-valid and was tripping a
  spurious warning in the run log.
- Request url in the targeted PR search. The agent has to emit a full
  pull_requests[].url, so omitting it forced the URL to be rebuilt by
  hand; the code agent's equivalent search already asks for it.
- List the new in-progress marker in the prior-triage detection step,
  which is the one place that enumerates markers.
- Correct the pr-open doc line, which said the issue is not re-evaluated
  until someone runs /fs-triage manually and so contradicted the trigger
  list above it — an issue edit re-runs triage too. Note that the
  in-progress comment is likewise not retracted.
- Assert the marker in the sufficient sticky-comment test, so swapping
  the two markers cannot pass unnoticed in either direction.

Assisted-by: Claude (fix, review), Grok (review)
Signed-off-by: Wayne Sun <gsun@redhat.com>

@waynesun09 waynesun09 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Approving after a multi-agent review and fix cycle on this branch.

Review found 1 high and 5 medium findings against the new in-progress action; all are addressed in 428a846 and 27f95f0:

  • The Existing PR gate's "when unsure, prefer prerequisites" tiebreak contradicted the Anti-premature-in-progress hard constraint and routed ambiguous PRs back to blocked framing — the exact behavior #433 was filed about. Tiebreak flipped to in-progress; the constraint now permits prerequisites only when positively determined.
  • The handler applied pr-open and claimed a PR addressed the issue without verifying any PR URL was present. Added a count guard, plus a follow-up fix restoring set -e propagation on the jq call so a malformed pull_requests aborts instead of rendering an empty "Addressed by:" list.
  • in-progress re-posted a fresh comment on every triage run; it is a durable status and triage re-runs on every issue edit. Now routed through the sticky comment path under its own marker.
  • Triage's PR discovery (unfiltered listing capped at 50) was not equivalent to the code agent's pre-check (targeted search); the gate could silently miss a PR and fall through to sufficient. Added the targeted search.
  • A result carrying both prerequisites and pull_requests had the former dropped silently; now warns, gated on there actually being something to drop.
  • The pr-open docs implied automatic recovery. Corrected to state that nothing clears the label when the linked PR closes unmerged.

Verification: 80 assertions pass in scripts/post-triage-test.sh (up from 56, including guard-branch regression tests that fail against the pre-fix script), schema tests pass, shellcheck clean, and all required CI checks are green. Verified from a clean checkout of the head ref.

@waynesun09
waynesun09 added this pull request to the merge queue Jul 24, 2026
Merged via the queue into main with commit 78540ca Jul 24, 2026
12 checks passed
@waynesun09
waynesun09 deleted the agent/433-in-progress-action branch July 24, 2026 20:33
@fullsend-ai-retro

fullsend-ai-retro Bot commented Jul 24, 2026

Copy link
Copy Markdown

🤖 Finished Retro · ✅ Success · Started 8:36 PM UTC · Completed 8:51 PM UTC
Commit: 27f95f0 · View workflow run →

@fullsend-ai-retro

Copy link
Copy Markdown

Retro: PR #434 — Add in-progress action for triage agent

Timeline

  1. Issue Triage agent incorrectly marks issue as blocked #433 filed 2026-07-14 by deboer-tim: Triage agent incorrectly routes fixing PRs to prerequisites (blocked framing) instead of recognizing them as addressing the issue.
  2. Triage + code cycle (2026-07-21): Triage run 29833027365 succeeded; code run 29833476130 succeeded.
  3. Re-triage + code (2026-07-24 13:41–13:47 UTC): Human waynesun09 triggered /fs-triage. Triage run 30097893841 and code run 30098255815 both succeeded.
  4. PR feat(#433): add in-progress action for triage agent #434 created (13:56 UTC): Initial commit e2a9232. Code agent iterated through 3 more fix commits (1837718, 8271039, 856e095) before review, reaching 56 test assertions.
  5. Review agent (run 30107212738, 15:54–16:13 UTC): Dispatched 5 sub-agents (correctness, style-conventions, intent-coherence, docs-currency, cross-repo-contracts). Found 1 medium (protected-path, procedural) and 2 low (non-actionable) findings. Zero correctness bugs detected. Outcome: comment action — no fix agent dispatched.
  6. Human review (16:13–20:26 UTC): waynesun09 conducted independent multi-agent review, identified 6 correctness bugs (1 high, 5 medium). All addressed in two fix commits (428a846, 27f95f0), bringing test assertions from 56 to 80.
  7. PR merged 2026-07-24 at 20:33 UTC after human approval.

Key findings

Review quality gap — correctness sub-agent missed all 6 bugs. The correctness sub-agent (Opus) analyzed handler logic, schema correctness, label lifecycle, and test coverage but reported zero findings. The most critical miss was a logical contradiction: the Existing PR gate's "when unsure, prefer prerequisites" tiebreak directly undermined the new Anti-premature-in-progress hard constraint — ambiguous cases would still route to blocked framing, re-introducing the exact bug #433 was filed about. The human also found: missing PR URL count guard, missing set -e propagation on a jq call, duplicate comment posting on every triage re-run, PR discovery method mismatch (unfiltered listing vs. targeted search), and silent data loss when both prerequisites and pull_requests were present.

Cross-repo-contracts sub-agent false positives: This sub-agent (Sonnet) produced 5 findings including a CRITICAL false positive ("missing handler for in-progress") because it read from disk (base branch) instead of using the API-fetched PR head content provided in its prompt. The orchestrator correctly filtered 4 of 5 as false positives, but the token cost was wasted and the orchestrator's challenger pass had to reason through each one.

Fix agent not involved: The review agent's comment action did not trigger a fix dispatch. All post-review fixes were produced through the human's independent review cycle, not through the automated fix pipeline.

Evidence for existing issues

  • fullsend#4305 (Review agent approved with zero findings despite multiple correctness bugs): This retro adds another instance — the correctness sub-agent ran a thorough-sounding analysis across multiple checklists but found nothing despite 6 real bugs.
  • fullsend#1375 (Improve review agent coverage of shell script correctness bugs): 5 of the 6 missed bugs were in post-triage.sh — missing guards, error propagation gaps, idempotency failures, and silent data drops are all shell script correctness patterns.
  • fullsend#2747 (Review agent includes base-branch changes producing false positives): The cross-repo-contracts sub-agent reading from disk at the base branch is a related manifestation, though the mechanism differs (sub-agent disk access vs. diff computation).
  • fullsend#2599 (Per-PR review budget cap): ~15 triage runs and ~20 review runs (6 cancelled, 14 succeeded) during this PR's 6.5-hour lifecycle. Most cancellations were expected (superseded by new pushes), but the volume is notable.

Proposals filed

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

Labels

requires-manual-review Review requires human judgment Review effort 3/5

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Triage agent incorrectly marks issue as blocked

1 participant