Skip to content

feat(triage): add effort-based gating before auto-promoting to coder#36

Open
rh-hemartin wants to merge 2 commits into
mainfrom
feat/triage-effort-analysis
Open

feat(triage): add effort-based gating before auto-promoting to coder#36
rh-hemartin wants to merge 2 commits into
mainfrom
feat/triage-effort-analysis

Conversation

@rh-hemartin

Copy link
Copy Markdown
Member

Summary

  • Add effort estimation (0.25–3 scale) to triage agent, matching the RICE effort dimension used by the prioritize agent
  • Bug/docs/performance issues with effort >= 2.0 get triaged instead of ready-to-code, routing high-complexity work through human review before dispatch
  • Update schema, post-triage script, and tests to support the new effort field

Migrated from fullsend-ai/fullsend feat/triage-effort-analysis.

Test plan

  • Run bash scripts/post-triage-test.sh — all cases pass including new effort-gating scenarios
  • Verify triage agent prompt includes effort estimation guidance and scoring table
  • Verify schema accepts effort field with correct bounds

🤖 Generated with Claude Code

Add effort estimation to triage agent (0.25-3 scale matching RICE).
Bug/docs/performance issues with effort >= 2.0 get triaged instead of
ready-to-code, routing high-complexity work through human review before
dispatch.

Migrated from fullsend-ai/fullsend feat/triage-effort-analysis.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Hector Martinez <hemartin@redhat.com>
@rh-hemartin rh-hemartin self-assigned this Jul 7, 2026
@fullsend-ai-review

fullsend-ai-review Bot commented Jul 7, 2026

Copy link
Copy Markdown

🤖 Review · ⚠️ Cancelled · Started 6:31 AM UTC · Ended 6:34 AM UTC
Commit: e8381e3 · View workflow run →

@qodo-code-review

Copy link
Copy Markdown

PR Summary by Qodo

Add effort scoring and auto-promotion gating to triage pipeline

✨ Enhancement 🧪 Tests 📝 Documentation ⚙️ Configuration changes 🕐 20-40 Minutes

Grey Divider

AI Description

• Add effort estimation (0.25–3) to triage outputs and schema validation.
• Gate bug/docs/performance auto-promotion when effort >= 2.0 for human review.
• Extend post-triage tests to cover low/high effort routing and logging.
Diagram

graph TD
  A["agents/triage.md"] --> B["Triage result JSON (effort)"] --> C["scripts/post-triage.sh"] --> D{{"GitHub Issues labels"}}
  S["triage-result.schema.json"] --> B
  T["scripts/post-triage-test.sh"] --> C
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Gate by severity/impact instead of effort
  • ➕ Avoids relying on an LLM-estimated numeric field
  • ➕ Uses signals already required in triage output (severity/impact)
  • ➖ Severity is not strongly correlated with implementation complexity
  • ➖ May still auto-promote complex refactors that are high effort but not 'high severity'
2. Introduce a separate `needs-human-review` label
  • ➕ Keeps triaged semantics stable while adding a clear review queue
  • ➕ Allows tooling to distinguish 'unprioritized' vs 'blocked by complexity'
  • ➖ Adds label taxonomy and automation complexity
  • ➖ Requires downstream workflow updates and maintainer alignment
3. Treat missing effort as low effort (auto-promote)
  • ➕ Maintains current throughput even if agent forgets effort
  • ➕ Reduces risk of over-triaging due to format drift
  • ➖ Increases risk of dispatching high-complexity work without review
  • ➖ Makes the gating easy to bypass accidentally

Recommendation: The PR’s approach (explicit effort scoring + threshold gating for bug/docs/perf) is a good fit for preventing costly auto-dispatch while keeping low-effort fixes flowing. The only decision worth re-checking is the handling of missing effort: defaulting to triaged is safer, but it also makes prompt/schema drift more disruptive—consider adding monitoring/alerts or a test that fails if effort is absent in real runs.

Files changed (4) +90 / -29

Enhancement (1) +20 / -3
post-triage.shGate ready-to-code labeling using 'effort' for bug/docs/performance +20/-3

Gate ready-to-code labeling using 'effort' for bug/docs/performance

• Reads 'triage_summary.effort' and updates labeling behavior: bug/documentation/performance items with effort >= 2.0 are routed to 'triaged' instead of 'ready-to-code'. Missing effort is treated conservatively by routing to human review, and logs now include category + effort for traceability.

scripts/post-triage.sh

Tests (1) +44 / -24
post-triage-test.shAdd effort-gating coverage and update fixtures to include 'effort' +44/-24

Add effort-gating coverage and update fixtures to include 'effort'

• Updates existing test payloads to include 'triage_summary.effort'. Adds new scenarios asserting that low-effort bugs get 'ready-to-code', while high-effort bug/docs/perf issues get 'triaged', including verification of the logged gating reason.

scripts/post-triage-test.sh

Documentation (1) +19 / -1
triage.mdDocument effort scoring rubric and add 'effort' to output example +19/-1

Document effort scoring rubric and add 'effort' to output example

• Adds guidance for estimating implementation effort on a 0.25–3 scale (aligned with RICE effort). Updates the triage JSON example to include an 'effort' field and explains that high-effort items should be routed for human review.

agents/triage.md

Other (1) +7 / -1
triage-result.schema.jsonExtend triage result schema to validate 'triage_summary.effort' +7/-1

Extend triage result schema to validate 'triage_summary.effort'

• Introduces a numeric 'effort' field under 'triage_summary' with bounds (min 0.25, max 3) and a descriptive hint for interpretation.

schemas/triage-result.schema.json

- Add regex guard for non-numeric effort values (fail closed to triaged)
- Add test for missing-effort and non-numeric-effort fallback paths
- Fix schema description to match triage.md effort scale labels

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Hector Martinez <hemartin@redhat.com>
@qodo-code-review

qodo-code-review Bot commented Jul 7, 2026

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (1) 📘 Rule violations (0) 📜 Skill insights (2)

Context used
✅ Compliance rules (platform): 55 rules
✅ Skills: 4 invoked
  code-review
  code-implementation
  pr-review
  docs-review

Grey Divider


Action required

1. Protected scripts/ files modified 📜 Skill insight § Compliance
Description
This PR modifies files under protected governance/infrastructure paths (e.g., scripts/ and
agents/), which require explicit human review and must not be auto-approved. Protected-path
changes increase governance and supply-chain risk if merged without manual oversight.
Code

scripts/post-triage.sh[R263-288]

    # ready-to-code, which triggers the code agent. Feature work and anything
    # else receives the triaged label and waits for human prioritization
    # (per #561, only feature issues should require human review before coding).
+    #
+    # Effort-based gating (#2207): high-effort bug/docs/performance issues
+    # (effort >= 2.0) get triaged instead of ready-to-code to route them through
+    # human review before dispatching to the code agent.
    CATEGORY=$(jq -r '.triage_summary.category // "unknown"' "${RESULT_FILE}")
-    echo "Category: ${CATEGORY}"
+    EFFORT=$(jq -r '.triage_summary.effort // "null"' "${RESULT_FILE}")
+    echo "Category: ${CATEGORY}, Effort: ${EFFORT}"
    case "${CATEGORY}" in
      bug|documentation|performance)
-        echo "Deferring ready-to-code label (${CATEGORY}) until after label_actions..."
-        DEFERRED_LABEL="ready-to-code"
+        # Effort threshold: >= 2.0 is substantial work, route to human review.
+        # Missing effort → conservatively route to human review (triaged).
+        if [[ "${EFFORT}" == "null" ]]; then
+          echo "Missing effort estimate — applying triaged label for human review..."
+          remove_label "ready-to-code"
+          add_label "triaged"
+        elif awk -v effort="${EFFORT}" 'BEGIN { exit (effort >= 2.0 ? 0 : 1) }'; then
+          echo "High effort (${EFFORT}) — applying triaged label for human review..."
+          remove_label "ready-to-code"
+          add_label "triaged"
+        else
+          echo "Low effort (${EFFORT}) — deferring ready-to-code label until after label_actions..."
+          DEFERRED_LABEL="ready-to-code"
+        fi
Evidence
The checklist flags any modifications under protected paths (including scripts/ and agents/) as
requiring a finding and human approval. The diff shows new/modified logic in
scripts/post-triage.sh and prompt/schema changes in agents/triage.md, both within the protected
path set.

scripts/post-triage.sh[262-288]
agents/triage.md[247-287]
Skill: pr-review


2. Docs contradict effort gating 📜 Skill insight ⚙ Maintainability
Description
The triage documentation still states that ready-to-code applies to bug/documentation/performance
issues as a category-level rule, but the post-triage logic now routes high-effort (and
missing-effort) items to triaged. This mismatch can mislead maintainers and auditors about when
auto-promotion to coder actually occurs.
Code

scripts/post-triage.sh[R263-288]

    # ready-to-code, which triggers the code agent. Feature work and anything
    # else receives the triaged label and waits for human prioritization
    # (per #561, only feature issues should require human review before coding).
+    #
+    # Effort-based gating (#2207): high-effort bug/docs/performance issues
+    # (effort >= 2.0) get triaged instead of ready-to-code to route them through
+    # human review before dispatching to the code agent.
    CATEGORY=$(jq -r '.triage_summary.category // "unknown"' "${RESULT_FILE}")
-    echo "Category: ${CATEGORY}"
+    EFFORT=$(jq -r '.triage_summary.effort // "null"' "${RESULT_FILE}")
+    echo "Category: ${CATEGORY}, Effort: ${EFFORT}"
    case "${CATEGORY}" in
      bug|documentation|performance)
-        echo "Deferring ready-to-code label (${CATEGORY}) until after label_actions..."
-        DEFERRED_LABEL="ready-to-code"
+        # Effort threshold: >= 2.0 is substantial work, route to human review.
+        # Missing effort → conservatively route to human review (triaged).
+        if [[ "${EFFORT}" == "null" ]]; then
+          echo "Missing effort estimate — applying triaged label for human review..."
+          remove_label "ready-to-code"
+          add_label "triaged"
+        elif awk -v effort="${EFFORT}" 'BEGIN { exit (effort >= 2.0 ? 0 : 1) }'; then
+          echo "High effort (${EFFORT}) — applying triaged label for human review..."
+          remove_label "ready-to-code"
+          add_label "triaged"
+        else
+          echo "Low effort (${EFFORT}) — deferring ready-to-code label until after label_actions..."
+          DEFERRED_LABEL="ready-to-code"
+        fi
Evidence
The updated post-triage logic explicitly routes bug/documentation/performance issues to triaged
when effort is missing or >= 2.0. However, the triage documentation still claims ready-to-code
applies to those categories as a general rule, which now contradicts runtime behavior.

scripts/post-triage.sh[262-288]
docs/triage.md[37-43]
Skill: docs-review

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`docs/triage.md` describes `ready-to-code`/`triaged` semantics that no longer match the updated post-triage behavior (effort-based gating for bug/docs/performance).

## Issue Context
The post-triage script now applies `triaged` (human review) for bug/documentation/performance items when `effort >= 2.0` or when `effort` is missing, instead of always applying `ready-to-code` for these categories.

## Fix Focus Areas
- docs/triage.md[32-44]
- scripts/post-triage.sh[262-288]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. Missing effort blocks promotion 🐞 Bug ≡ Correctness
Description
scripts/post-triage.sh routes bug/documentation/performance issues to triaged when
triage_summary.effort is missing, which can suppress auto-promotion whenever the agent omits the
field. Because effort is optional in schemas/triage-result.schema.json, these results still
validate, making this behavior easy to trigger unintentionally.
Code

scripts/post-triage.sh[R271-288]

+    EFFORT=$(jq -r '.triage_summary.effort // "null"' "${RESULT_FILE}")
+    echo "Category: ${CATEGORY}, Effort: ${EFFORT}"
    case "${CATEGORY}" in
      bug|documentation|performance)
-        echo "Deferring ready-to-code label (${CATEGORY}) until after label_actions..."
-        DEFERRED_LABEL="ready-to-code"
+        # Effort threshold: >= 2.0 is substantial work, route to human review.
+        # Missing effort → conservatively route to human review (triaged).
+        if [[ "${EFFORT}" == "null" ]]; then
+          echo "Missing effort estimate — applying triaged label for human review..."
+          remove_label "ready-to-code"
+          add_label "triaged"
+        elif awk -v effort="${EFFORT}" 'BEGIN { exit (effort >= 2.0 ? 0 : 1) }'; then
+          echo "High effort (${EFFORT}) — applying triaged label for human review..."
+          remove_label "ready-to-code"
+          add_label "triaged"
+        else
+          echo "Low effort (${EFFORT}) — deferring ready-to-code label until after label_actions..."
+          DEFERRED_LABEL="ready-to-code"
+        fi
Evidence
The post-triage script explicitly routes missing effort to triaged, while the triage prompt
instructs effort estimation with an auto-promotion bias and the schema does not require effort,
allowing omissions to pass validation and still trigger the triage fallback.

scripts/post-triage.sh[262-288]
schemas/triage-result.schema.json[121-145]
agents/triage.md[247-263]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The post-triage gating logic treats missing `triage_summary.effort` as a reason to apply the `triaged` label for bug/documentation/performance categories, but the triage result schema does not require `effort`. This means valid (schema-passing) agent outputs can unexpectedly disable auto-promotion.

## Issue Context
- Triage prompt guidance says to estimate effort for bug/docs/performance and to bias toward auto-promotion (round down), but the implementation routes *missing* effort to human review.
- The harness validates against `schemas/triage-result.schema.json` before running `post-triage.sh`, so schema constraints are the right place to prevent missing effort from reaching the gating logic (or the script should default missing effort to a low-effort value).

## Fix Focus Areas
- scripts/post-triage.sh[270-288]
- schemas/triage-result.schema.json[121-144]
- agents/triage.md[247-263]

## What to change
Choose one consistent policy and implement it end-to-end:
1) **Require effort for bug/docs/performance when action=sufficient**
  - Update `schemas/triage-result.schema.json` with an `if/then` that, when `action == "sufficient"` and `triage_summary.category` is in `{bug, documentation, performance}`, requires `triage_summary.effort`.
  - In `post-triage.sh`, replace the “missing effort => triaged” branch with a hard error (since it should be schema-impossible) or keep a defensive error in case the script is run without schema validation.

OR

2) **Default missing effort to low effort** (to preserve “bias toward auto-promotion”)
  - In `post-triage.sh`, treat missing effort as low effort (e.g., default to `1.0` and defer `ready-to-code`) and log a warning.
  - Optionally keep schema optional, but consider adding an agent-side requirement if you want stronger guarantees.

Also ensure the written guidance in `agents/triage.md` matches the chosen behavior (especially the handling of missing effort).

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Qodo Logo

Comment thread scripts/post-triage.sh
Comment on lines 263 to +288
# ready-to-code, which triggers the code agent. Feature work and anything
# else receives the triaged label and waits for human prioritization
# (per #561, only feature issues should require human review before coding).
#
# Effort-based gating (#2207): high-effort bug/docs/performance issues
# (effort >= 2.0) get triaged instead of ready-to-code to route them through
# human review before dispatching to the code agent.
CATEGORY=$(jq -r '.triage_summary.category // "unknown"' "${RESULT_FILE}")
echo "Category: ${CATEGORY}"
EFFORT=$(jq -r '.triage_summary.effort // "null"' "${RESULT_FILE}")
echo "Category: ${CATEGORY}, Effort: ${EFFORT}"
case "${CATEGORY}" in
bug|documentation|performance)
echo "Deferring ready-to-code label (${CATEGORY}) until after label_actions..."
DEFERRED_LABEL="ready-to-code"
# Effort threshold: >= 2.0 is substantial work, route to human review.
# Missing effort → conservatively route to human review (triaged).
if [[ "${EFFORT}" == "null" ]]; then
echo "Missing effort estimate — applying triaged label for human review..."
remove_label "ready-to-code"
add_label "triaged"
elif awk -v effort="${EFFORT}" 'BEGIN { exit (effort >= 2.0 ? 0 : 1) }'; then
echo "High effort (${EFFORT}) — applying triaged label for human review..."
remove_label "ready-to-code"
add_label "triaged"
else
echo "Low effort (${EFFORT}) — deferring ready-to-code label until after label_actions..."
DEFERRED_LABEL="ready-to-code"
fi

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Action required

1. Protected scripts/ files modified 📜 Skill insight § Compliance

This PR modifies files under protected governance/infrastructure paths (e.g., scripts/ and
agents/), which require explicit human review and must not be auto-approved. Protected-path
changes increase governance and supply-chain risk if merged without manual oversight.

Comment thread scripts/post-triage.sh
Comment on lines 263 to +288
# ready-to-code, which triggers the code agent. Feature work and anything
# else receives the triaged label and waits for human prioritization
# (per #561, only feature issues should require human review before coding).
#
# Effort-based gating (#2207): high-effort bug/docs/performance issues
# (effort >= 2.0) get triaged instead of ready-to-code to route them through
# human review before dispatching to the code agent.
CATEGORY=$(jq -r '.triage_summary.category // "unknown"' "${RESULT_FILE}")
echo "Category: ${CATEGORY}"
EFFORT=$(jq -r '.triage_summary.effort // "null"' "${RESULT_FILE}")
echo "Category: ${CATEGORY}, Effort: ${EFFORT}"
case "${CATEGORY}" in
bug|documentation|performance)
echo "Deferring ready-to-code label (${CATEGORY}) until after label_actions..."
DEFERRED_LABEL="ready-to-code"
# Effort threshold: >= 2.0 is substantial work, route to human review.
# Missing effort → conservatively route to human review (triaged).
if [[ "${EFFORT}" == "null" ]]; then
echo "Missing effort estimate — applying triaged label for human review..."
remove_label "ready-to-code"
add_label "triaged"
elif awk -v effort="${EFFORT}" 'BEGIN { exit (effort >= 2.0 ? 0 : 1) }'; then
echo "High effort (${EFFORT}) — applying triaged label for human review..."
remove_label "ready-to-code"
add_label "triaged"
else
echo "Low effort (${EFFORT}) — deferring ready-to-code label until after label_actions..."
DEFERRED_LABEL="ready-to-code"
fi

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Action required

2. Docs contradict effort gating 📜 Skill insight ⚙ Maintainability

The triage documentation still states that ready-to-code applies to bug/documentation/performance
issues as a category-level rule, but the post-triage logic now routes high-effort (and
missing-effort) items to triaged. This mismatch can mislead maintainers and auditors about when
auto-promotion to coder actually occurs.
Agent Prompt
## Issue description
`docs/triage.md` describes `ready-to-code`/`triaged` semantics that no longer match the updated post-triage behavior (effort-based gating for bug/docs/performance).

## Issue Context
The post-triage script now applies `triaged` (human review) for bug/documentation/performance items when `effort >= 2.0` or when `effort` is missing, instead of always applying `ready-to-code` for these categories.

## Fix Focus Areas
- docs/triage.md[32-44]
- scripts/post-triage.sh[262-288]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment thread scripts/post-triage.sh
Comment on lines +271 to +288
EFFORT=$(jq -r '.triage_summary.effort // "null"' "${RESULT_FILE}")
echo "Category: ${CATEGORY}, Effort: ${EFFORT}"
case "${CATEGORY}" in
bug|documentation|performance)
echo "Deferring ready-to-code label (${CATEGORY}) until after label_actions..."
DEFERRED_LABEL="ready-to-code"
# Effort threshold: >= 2.0 is substantial work, route to human review.
# Missing effort → conservatively route to human review (triaged).
if [[ "${EFFORT}" == "null" ]]; then
echo "Missing effort estimate — applying triaged label for human review..."
remove_label "ready-to-code"
add_label "triaged"
elif awk -v effort="${EFFORT}" 'BEGIN { exit (effort >= 2.0 ? 0 : 1) }'; then
echo "High effort (${EFFORT}) — applying triaged label for human review..."
remove_label "ready-to-code"
add_label "triaged"
else
echo "Low effort (${EFFORT}) — deferring ready-to-code label until after label_actions..."
DEFERRED_LABEL="ready-to-code"
fi

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Action required

3. Missing effort blocks promotion 🐞 Bug ≡ Correctness

scripts/post-triage.sh routes bug/documentation/performance issues to triaged when
triage_summary.effort is missing, which can suppress auto-promotion whenever the agent omits the
field. Because effort is optional in schemas/triage-result.schema.json, these results still
validate, making this behavior easy to trigger unintentionally.
Agent Prompt
## Issue description
The post-triage gating logic treats missing `triage_summary.effort` as a reason to apply the `triaged` label for bug/documentation/performance categories, but the triage result schema does not require `effort`. This means valid (schema-passing) agent outputs can unexpectedly disable auto-promotion.

## Issue Context
- Triage prompt guidance says to estimate effort for bug/docs/performance and to bias toward auto-promotion (round down), but the implementation routes *missing* effort to human review.
- The harness validates against `schemas/triage-result.schema.json` before running `post-triage.sh`, so schema constraints are the right place to prevent missing effort from reaching the gating logic (or the script should default missing effort to a low-effort value).

## Fix Focus Areas
- scripts/post-triage.sh[270-288]
- schemas/triage-result.schema.json[121-144]
- agents/triage.md[247-263]

## What to change
Choose one consistent policy and implement it end-to-end:
1) **Require effort for bug/docs/performance when action=sufficient**
   - Update `schemas/triage-result.schema.json` with an `if/then` that, when `action == "sufficient"` and `triage_summary.category` is in `{bug, documentation, performance}`, requires `triage_summary.effort`.
   - In `post-triage.sh`, replace the “missing effort => triaged” branch with a hard error (since it should be schema-impossible) or keep a defensive error in case the script is run without schema validation.

OR

2) **Default missing effort to low effort** (to preserve “bias toward auto-promotion”)
   - In `post-triage.sh`, treat missing effort as low effort (e.g., default to `1.0` and defer `ready-to-code`) and log a warning.
   - Optionally keep schema optional, but consider adding an agent-side requirement if you want stronger guarantees.

Also ensure the written guidance in `agents/triage.md` matches the chosen behavior (especially the handling of missing effort).

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

@fullsend-ai-review

fullsend-ai-review Bot commented Jul 7, 2026

Copy link
Copy Markdown

🤖 Finished Review · ✅ Success · Started 6:35 AM UTC · Completed 6:44 AM UTC
Commit: c51787d · View workflow run →

@fullsend-ai-review

Copy link
Copy Markdown

Review

Verdict: comment · 3 medium, 2 low findings

The effort-based gating logic is well-designed: the bash branching correctly handles missing, non-numeric, and numeric effort values; the schema addition is backward-compatible (optional field); and tests cover the primary scenarios including boundary cases at 2.0 and edge cases for missing/non-numeric effort. The overall approach — gating auto-promotion for high-complexity issues — fits the existing triage pipeline architecture.

Three areas worth addressing:

Findings

1. GHA workflow command injection via unsanitized EFFORT interpolation · medium · security

File: scripts/post-triage.sh

The new echo "::warning::Non-numeric effort value '${EFFORT}'" interpolates the raw EFFORT value into a GitHub Actions workflow command. On this code path, EFFORT has explicitly failed the numeric regex — meaning it may contain arbitrary characters including literal newlines (decoded by jq -r from JSON \n escapes) and :: sequences. A newline followed by ::add-mask:: or ::error:: would be processed as a separate workflow command.

The same risk applies to the earlier echo "Category: ${CATEGORY}, Effort: ${EFFORT}" line, which runs before any validation.

post-prioritize.sh (lines 59-63) demonstrates the correct pattern: strip ::, %0A/%0a, %0D/%0d before interpolating into workflow commands. The new code should follow this established sanitization pattern.

Note: This is defense-in-depth — schema validation (effort type: number) runs before the post-script, so exploitation requires schema validation bypass. The existing ::warning:: lines in post-triage.sh for label values have the same gap (pre-existing, not introduced by this PR).

Remediation: Sanitize EFFORT before all echo statements that interpolate it, following the post-prioritize.sh pattern:

safe_effort="${EFFORT//$'\n'/}"
safe_effort="${safe_effort//$'\r'/}"
safe_effort="${safe_effort//::/}"
safe_effort="${safe_effort//%0A/}"
safe_effort="${safe_effort//%0a/}"
safe_effort="${safe_effort//%0D/}"
safe_effort="${safe_effort//%0d/}"

2. Documentation now contradicts actual behavior — docs/triage.md · medium · docs-currency

File: docs/triage.md, lines 40-41

The control labels table describes routing behavior that this PR changes:

  • Line 40 (ready-to-code): says "low-risk (bug, documentation, performance)" — now incomplete; only low-effort issues in these categories auto-promote.
  • Line 41 (triaged): says "feature or other category" — now incomplete; high-effort (≥ 2.0) bug/docs/performance issues also receive triaged.

Remediation: Update the label descriptions to reflect effort gating, e.g.:

  • ready-to-code: "The issue is fully specified, low-risk (bug, documentation, performance), and estimated effort is below 2.0."
  • triaged: "The issue is fully specified but is a feature, has high estimated effort (≥ 2.0), or is in a category that requires human prioritization."

3. Documentation now contradicts actual behavior — docs/code.md · medium · docs-currency

File: docs/code.md, line 41

The ready-to-code label description says "Applied by the triage post-script for low-risk categories (bug, documentation, performance)" — this no longer captures the effort condition.

Remediation: Append "with estimated effort below 2.0" to the description.

4. Test fixtures for non-applicable categories include effort values · low · test-integrity

File: scripts/post-triage-test.sh

The sufficient-feature-gets-triaged and sufficient-other-gets-triaged test fixtures include "effort":2.0 and "effort":1.0 respectively, but triage.md instructs the agent to "only estimate effort for bug/docs/performance categories." While the effort values are harmlessly ignored by the script (the feature/other case branches don't read effort), the fixtures create an inconsistency between what the agent is told to produce and what the tests validate.

Remediation: Consider removing the effort field from feature/other test fixtures to match the agent's documented behavior, or add a comment explaining why they're included (e.g., "verifies effort is harmlessly ignored for non-applicable categories").

5. No test for effort just below threshold · low · test-adequacy

File: scripts/post-triage-test.sh

The test suite covers effort=2.0 (boundary, routes to triaged) and effort=0.25/0.5/1.0 (below threshold, routes to ready-to-code), but no test explicitly verifies effort=1.99 or 1.9 routes to ready-to-code. The gap between tested values (1.0 → 2.0) is large relative to the threshold.

Remediation: Add a test case for effort=1.5 or 1.99 to tighten boundary coverage.

@fullsend-ai-review fullsend-ai-review Bot added the requires-manual-review Review requires human judgment label Jul 7, 2026
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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant