Skip to content

feat(#1754): add TRIAGE_AUTO_CODE configuration for ready-to-code - #567

Merged
ralphbean merged 14 commits into
mainfrom
agent/1754-triage-auto-code-config
Aug 5, 2026
Merged

feat(#1754): add TRIAGE_AUTO_CODE configuration for ready-to-code#567
ralphbean merged 14 commits into
mainfrom
agent/1754-triage-auto-code-config

Conversation

@ralphbean

@ralphbean ralphbean commented Jul 30, 2026

Copy link
Copy Markdown
Member

Summary

  • Adds TRIAGE_AUTO_CODE env var to control whether triage auto-applies ready-to-code (which triggers the code agent). Three modes: on (default, preserves existing behavior), off (never auto-promote), category (auto-promote only listed categories via TRIAGE_AUTO_CODE_CATEGORIES).
  • Wires the vars into harness/triage.yaml under env.runner.
  • Documents both variables in docs/triage.md.
  • 20 new test cases covering all modes, category filtering, interaction with the workflow-change guard, and preservation of category labels.

This delivers the category-allowlist slice of fullsend-ai/fullsend#1754. Clarity-score and label-based conditional criteria are deferred to a follow-up.

Relates to fullsend-ai/fullsend#1754

Test plan

  • All 107 post-triage tests pass (make test)
  • Full suite passes (make test)
  • shellcheck clean on post-triage.sh
  • End-to-end test: ran triage with TRIAGE_AUTO_CODE=off against appdumpster/test-repo#40 (bug category) — confirmed it received bug + triaged instead of bug + ready-to-code
  • Verify docs render correctly on GitHub

🤖 Generated with Claude Code

@ralphbean
ralphbean requested a review from a team as a code owner July 30, 2026 16:10
@qodo-code-review

Copy link
Copy Markdown

PR Summary by Qodo

Add TRIAGE_AUTO_CODE to control ready-to-code auto-promotion in triage

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

Grey Divider

AI Description

• Add TRIAGE_AUTO_CODE(+categories) to gate auto-applying the ready-to-code label.
• Wire new env vars into the triage harness runner environment defaults.
• Expand post-triage tests and document new triage configuration variables.
Diagram

graph TD
  A["harness/triage.yaml"] --> B["scripts/post-triage.sh"] --> C{{"GitHub API\n(issue labels)"}}
  D["TRIAGE_AUTO_CODE* env"] --> B
  E["scripts/post-triage-test.sh"] --> B
  F["docs/triage.md"] --> D
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Strict mode validation (fail on unknown TRIAGE_AUTO_CODE)
  • ➕ Avoids silently defaulting to "on" when misconfigured
  • ➕ Makes behavior explicit in CI/harness environments
  • ➖ Can break existing setups with typos until fixed
  • ➖ Requires deciding failure semantics (hard fail vs warning + fallback)
2. Configuration file-driven policy (YAML/JSON) instead of env enums
  • ➕ Easier to evolve beyond three modes (per-repo/per-org policies, label maps)
  • ➕ More discoverable and versionable alongside other harness config
  • ➖ More moving parts than environment variables
  • ➖ Requires parsing/validation logic in shell or moving logic to another runtime

Recommendation: The env-driven enum approach is a good fit for a small policy toggle and preserves default behavior. The main improvement worth considering is adding explicit validation/logging for unrecognized TRIAGE_AUTO_CODE values (currently treated as "on"), to prevent accidental auto-promotion due to typos.

Files changed (4) +266 / -5

Enhancement (1) +38 / -4
post-triage.shGate ready-to-code auto-promotion behind TRIAGE_AUTO_CODE policy +38/-4

Gate ready-to-code auto-promotion behind TRIAGE_AUTO_CODE policy

• Adds TRIAGE_AUTO_CODE and TRIAGE_AUTO_CODE_CATEGORIES handling via an auto_code_allowed() helper. Updates the workflow-change guard and per-category labeling branches to apply triaged when auto-code is disabled, while preserving existing default behavior when enabled.

scripts/post-triage.sh

Tests (1) +222 / -0
post-triage-test.shAdd coverage for TRIAGE_AUTO_CODE modes and category filtering +222/-0

Add coverage for TRIAGE_AUTO_CODE modes and category filtering

• Introduces helper runners to execute the post-triage script with extra env vars and asserts gh label calls. Adds ~20 test cases covering default/on/off/category modes, allowlist behavior, workflow-change guard interaction, and preservation of category labels.

scripts/post-triage-test.sh

Documentation (1) +4 / -1
triage.mdDocument TRIAGE_AUTO_CODE and TRIAGE_AUTO_CODE_CATEGORIES +4/-1

Document TRIAGE_AUTO_CODE and TRIAGE_AUTO_CODE_CATEGORIES

• Replaces the previous "None" variable section with a table documenting the new auto-promotion controls, their defaults, and how the category allowlist mode works.

docs/triage.md

Other (1) +2 / -0
triage.yamlPass auto-code configuration into triage runner env +2/-0

Pass auto-code configuration into triage runner env

• Adds TRIAGE_AUTO_CODE and TRIAGE_AUTO_CODE_CATEGORIES to env.runner with default values, making the behavior configurable without editing scripts.

harness/triage.yaml

@fullsend-ai-review

fullsend-ai-review Bot commented Jul 30, 2026

Copy link
Copy Markdown

🤖 Review · ⚠️ Cancelled · Started 4:11 PM UTC · Ended 4:21 PM UTC
Commit: 647a8e8 · View workflow run →

@qodo-code-review

qodo-code-review Bot commented Jul 30, 2026

Copy link
Copy Markdown

Code Review by Qodo

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

Grey Divider


Action required

1. Protected harness/scripts changes 📜 Skill insight § Compliance
Description
This PR modifies files under protected governance/infrastructure paths (harness/ and scripts/),
which requires explicit human review and must not be auto-approved. Treat this PR as requiring
manual approval even if CI is green.
Code

harness/triage.yaml[R45-46]

+        TRIAGE_AUTO_CODE: "${TRIAGE_AUTO_CODE:-on}"
+        TRIAGE_AUTO_CODE_CATEGORIES: "${TRIAGE_AUTO_CODE_CATEGORIES:-bug,documentation,performance}"
Relevance

●●● Strong

Repo enforces protected-path findings; schema blocks auto-approve when protected paths touched (PR
#303).

PR-#303

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
Compliance requires raising a finding whenever protected governance/infrastructure paths are
modified. The diff shows changes in harness/triage.yaml and scripts/post-triage.sh, both of
which are listed protected paths.

harness/triage.yaml[41-46]
scripts/post-triage.sh[387-458]
Skill: pr-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
The PR modifies protected governance/infrastructure paths (notably `harness/` and `scripts/`). Per compliance, these changes must be explicitly flagged for human review and must not be auto-approved.

## Issue Context
Protected-path modifications are higher-risk because they can change execution/config behavior for agents and automation.

## Fix Focus Areas
- harness/triage.yaml[45-46]
- scripts/post-triage.sh[387-458]

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



Remediation recommended

2. Category mode misgates warning ✓ Resolved 🐞 Bug ≡ Correctness
Description
When TRIAGE_AUTO_CODE=category, auto_code_allowed returns success for any category present in
TRIAGE_AUTO_CODE_CATEGORIES, but only bug/documentation/performance branches ever defer
ready-to-code. If TRIAGE_AUTO_CODE_CATEGORIES includes unsupported categories (e.g. feature),
the workflow-change guard can emit a misleading “Skipping ready-to-code” warning and pre-apply
triaged even though that category will never apply ready-to-code.
Code

scripts/post-triage.sh[R405-416]

+    auto_code_allowed() {
+      case "${AUTO_CODE}" in
+        off) return 1 ;;
+        category)
+          local categories="${TRIAGE_AUTO_CODE_CATEGORIES:-bug,documentation,performance}"
+          # Check if CATEGORY appears in the comma-separated list.
+          echo ",${categories}," | grep -qF ",${CATEGORY},"
+          ;;
+        *) # "on" or unrecognized — preserve default behavior.
+          [[ "${CATEGORY}" == "bug" || "${CATEGORY}" == "documentation" || "${CATEGORY}" == "performance" ]]
+          ;;
+      esac
Relevance

●●● Strong

Same issue previously fixed/accepted: gate “Skipping ready-to-code” warning to only categories that
can get ready-to-code (PR #326).

PR-#326

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The new predicate allows any configured category to satisfy the workflow-change guard, but the
feature) branch never defers ready-to-code, so the guard’s warning can fire even when the code
would not apply ready-to-code for that category.

scripts/post-triage.sh[402-428]
scripts/post-triage.sh[430-469]
PR-#326

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

### Issue description
`auto_code_allowed()` treats any category in `TRIAGE_AUTO_CODE_CATEGORIES` as eligible during `TRIAGE_AUTO_CODE=category`, but the switch statement only ever applies/defer `ready-to-code` for `bug|documentation|performance`. This mismatch can reintroduce the “Skipping ready-to-code” warning for categories that cannot receive `ready-to-code`.

### Issue Context
- The workflow-change guard is now gated by `auto_code_allowed`, not by an explicit set of auto-promotable categories.
- The `feature)` branch always applies `feature` + `triaged` and never defers `ready-to-code`.

### Fix Focus Areas
- scripts/post-triage.sh[402-428]
- scripts/post-triage.sh[430-469]

### Suggested approach
- Define a single authoritative set of categories that can ever auto-promote (currently `bug,documentation,performance`).
- In `category` mode, compute eligibility as: `CATEGORY in supported_set` **and** `CATEGORY in TRIAGE_AUTO_CODE_CATEGORIES`.
- Optionally: if `TRIAGE_AUTO_CODE_CATEGORIES` includes unsupported categories, emit a one-time warning explaining they are ignored (prevents silent misconfiguration).

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


3. Category list whitespace breaks ✓ Resolved 🐞 Bug ☼ Reliability
Description
In TRIAGE_AUTO_CODE=category mode, TRIAGE_AUTO_CODE_CATEGORIES is matched with an exact fixed-string
,${CATEGORY}, search and whitespace is not normalized. Common comma-separated values with spaces
(e.g. bug, documentation) will fail to match and silently disable auto-promotion for those
categories.
Code

scripts/post-triage.sh[R409-412]

+          local categories="${TRIAGE_AUTO_CODE_CATEGORIES:-bug,documentation,performance}"
+          # Check if CATEGORY appears in the comma-separated list.
+          echo ",${categories}," | grep -qF ",${CATEGORY},"
+          ;;
Relevance

●● Moderate

No clear prior accepted/rejected guidance on trimming whitespace in comma-separated env var lists;
relevance unclear.

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The docs describe a comma-separated list, but the code performs an exact fixed-string membership
check that fails when list elements include spaces.

scripts/post-triage.sh[405-416]
docs/triage.md[134-139]

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

### Issue description
`TRIAGE_AUTO_CODE_CATEGORIES` is documented as a comma-separated list, but the implementation requires entries contain no surrounding whitespace. This causes configuration to silently fail (e.g. `bug, documentation` won’t match `documentation`).

### Issue Context
Current logic checks membership by string containment with comma sentinels and `grep -qF`, without trimming whitespace.

### Fix Focus Areas
- scripts/post-triage.sh[408-412]
- docs/triage.md[136-139]

### Suggested approach
- Normalize the categories string before matching, e.g. strip all ASCII whitespace: `categories=${categories//[[:space:]]/}`.
- Or parse into an array: `IFS=',' read -ra parts <<< "$categories"` and trim each part before comparing.
- Consider documenting that whitespace is allowed (after fix) or rejecting/validating with a clear error/warning if you prefer strict syntax.

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


Grey Divider

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

To customize comments, go to the Qodo configuration screen, or learn more in the docs.

Qodo Logo

Comment thread harness/triage.yaml Outdated
Comment thread scripts/post-triage.sh
Comment thread scripts/post-triage.sh Outdated
@ralphbean
ralphbean force-pushed the agent/1754-triage-auto-code-config branch from 908eaeb to 5ac6c31 Compare July 30, 2026 16:21
@fullsend-ai-review

fullsend-ai-review Bot commented Jul 30, 2026

Copy link
Copy Markdown

🤖 Finished Review · ✅ Success · Started 4:23 PM UTC · Completed 4:37 PM UTC
Commit: 5ac6c31 · View workflow run →

@fullsend-ai-review

fullsend-ai-review Bot commented Jul 30, 2026

Copy link
Copy Markdown

Review

Findings

Medium

  • [protected-path] harness/triage.yaml, scripts/post-triage.sh, scripts/post-triage-test.sh — PR modifies protected governance/infrastructure files (harness/, scripts/). The PR links to Triage agent configuration for code fullsend#1754 and explains the rationale. Human approval is always required for protected-path changes.

Low

  • [API-contract-violation] harness/triage.yaml:39 — The top-level env.runner block hardcodes TRIAGE_AUTO_CODE: "on" and TRIAGE_AUTO_CODE_CATEGORIES: "bug,documentation,performance" as literal strings. review.yaml uses the same literal-default pattern for REVIEW_FINDING_SEVERITY_THRESHOLD, so this is consistent with at least one other harness config. However, fix.yaml, code.yaml, and scribe.yaml use ${VAR} pass-through. Verify that the fullsend CLI's env.runner precedence allows external overrides to take effect when users follow the documented override instructions.

  • [edge-case] scripts/post-triage.sh:413 — In category_in_auto_code_list, the categories list is lowercased but the CATEGORY variable (from jq) is not lowercased before the case-sensitive grep -qF match. The schema enum constrains category to lowercase values, so this only matters in the validation-bypass path (after 3 failed validation attempts).

  • [behavioral-change] scripts/post-triage.sh:449 — The workflow-change warning (::warning::Triage detected workflow file changes required (#325)) is now emitted unconditionally for all categories when requires_workflow_changes=true, whereas previously it only fired for bug/documentation/performance. This is informational — it affects only CI log output, not label mutations.

Previous run

Review

Findings

Medium

  • [API-contract-violation] harness/triage.yaml:39 — The top-level env.runner block hardcodes TRIAGE_AUTO_CODE: "on" and TRIAGE_AUTO_CODE_CATEGORIES: "bug,documentation,performance" as literal strings. Every other harness config (fix.yaml, scribe.yaml) uses the ${VAR} pass-through pattern for top-level runner env vars. The forge.github.env.runner entries in the same file correctly use pass-through (${TRIAGE_AUTO_CODE}), creating an inconsistency within the file. If the fullsend CLI applies top-level env.runner with higher precedence than the external environment in non-forge mode, user overrides set via CI workflow env: blocks would not take effect.
    Remediation: Use the pass-through-with-default pattern: TRIAGE_AUTO_CODE: "${TRIAGE_AUTO_CODE:-on}" and TRIAGE_AUTO_CODE_CATEGORIES: "${TRIAGE_AUTO_CODE_CATEGORIES:-bug,documentation,performance}".

  • [documentation-correctness] docs/triage.md:138 — The TRIAGE_AUTO_CODE_CATEGORIES description says it applies "when TRIAGE_AUTO_CODE=category" but the implementation treats on and category identically — both call category_in_auto_code_list which checks TRIAGE_AUTO_CODE_CATEGORIES (on | category) category_in_auto_code_list). The on description says "auto-promote bug/documentation/performance" which is only accurate with the default categories list. A user who sets TRIAGE_AUTO_CODE=on and TRIAGE_AUTO_CODE_CATEGORIES=bug would see only bugs auto-promote, contradicting the documented semantics of on.
    Remediation: Either update the docs to state that TRIAGE_AUTO_CODE_CATEGORIES applies to both on and category modes, or change auto_code_allowed so on mode always uses the hardcoded three categories.

  • [protected-path] harness/triage.yaml, scripts/post-triage.sh, scripts/post-triage-test.sh — PR modifies protected governance/infrastructure files (harness/, scripts/). The PR links to Triage agent configuration for code fullsend#1754 and explains the rationale. Human approval is always required for protected-path changes.

Low

  • [behavioral-change] scripts/post-triage.sh — The workflow-change warning (::warning::Triage detected workflow file changes required (#325)) is now emitted unconditionally for all categories when requires_workflow_changes=true, whereas previously it only fired for bug/documentation/performance. This is informational — it affects only CI log output, not label mutations.

  • [stale-doc] docs/code.md:32 — The ready-to-code label description states that triage unconditionally applies it for bug/documentation/performance categories without mentioning configurability. The description remains accurate for the default configuration but is now incomplete.

Previous run (2)

Review

Findings

Medium

  • [API-contract-violation] harness/triage.yaml:38 — The env.runner block hardcodes TRIAGE_AUTO_CODE: "on" and TRIAGE_AUTO_CODE_CATEGORIES: "bug,documentation,performance" as literal strings. Every other harness config that passes runner env vars uses the ${VAR} expansion pattern (e.g., fix.yaml uses TARGET_BRANCH: "${TARGET_BRANCH}"). Because these are literal values rather than pass-throughs, a user who sets TRIAGE_AUTO_CODE=off in their CI workflow env: block — as docs/triage.md instructs — would have that value overridden by the harness config's hardcoded "on". The documented configuration mechanism will not function.
    Remediation: Use the pass-through-with-default pattern: TRIAGE_AUTO_CODE: "${TRIAGE_AUTO_CODE:-on}" and TRIAGE_AUTO_CODE_CATEGORIES: "${TRIAGE_AUTO_CODE_CATEGORIES:-bug,documentation,performance}".

  • [protected-path] harness/triage.yaml, scripts/post-triage.sh, scripts/post-triage-test.sh — PR modifies protected governance/infrastructure files (harness/, scripts/). The PR links to Triage agent configuration for code fullsend#1754 and explains the rationale. Human approval is always required for protected-path changes.

Low

  • [coherence-concern] scripts/post-triage.sh — The fallback-to-permissive behavior (treating unrecognized TRIAGE_AUTO_CODE values as on) means typos or configuration errors will silently enable auto-coding rather than failing closed. The *) branch emits a ::warning but then proceeds to auto-promote as if on. A fail-closed approach (treating unrecognized values as off) would be more conservative and prevent unintended agent dispatch.

  • [behavioral-change] scripts/post-triage.sh — The workflow-change warning (::warning::Triage detected workflow file changes required (#325)) is now emitted unconditionally for all categories when requires_workflow_changes=true, whereas previously it only fired for bug/documentation/performance. This is informational — it affects only CI log output, not label mutations.

  • [docs-currency] docs/code.md:32 — The ready-to-code label description states that triage unconditionally applies it for bug/documentation/performance categories without mentioning configurability. The description remains accurate for the default configuration but is now incomplete.


Next steps:

  • /fs-fix — agent addresses review findings automatically
  • /fs-fix <your instruction> — agent fixes with your specific guidance
  • Push commits directly — review re-runs automatically on push
  • /fs-fix-stop — disable automatic fix runs for this PR
Previous run (3)

Review

Findings

Medium

  • [API-contract-violation] harness/triage.yaml:38 — The env.runner block hardcodes TRIAGE_AUTO_CODE: "on" and TRIAGE_AUTO_CODE_CATEGORIES: "bug,documentation,performance" as literal strings. Every other harness config that passes runner env vars uses the ${VAR} expansion pattern (e.g., fix.yaml uses TARGET_BRANCH: "${TARGET_BRANCH}", scribe.yaml uses SCRIBE_REPO: ${SCRIBE_REPO}). Because these are literal values rather than pass-throughs, a user who sets TRIAGE_AUTO_CODE=off in their CI workflow env: block — as docs/triage.md instructs — would have that value overridden by the harness config's hardcoded "on". The documented configuration mechanism will not function.
    Remediation: Use the pass-through-with-default pattern: TRIAGE_AUTO_CODE: "${TRIAGE_AUTO_CODE:-on}" and TRIAGE_AUTO_CODE_CATEGORIES: "${TRIAGE_AUTO_CODE_CATEGORIES:-bug,documentation,performance}".

  • [protected-path] harness/triage.yaml, scripts/post-triage.sh, scripts/post-triage-test.sh — PR modifies protected governance/infrastructure files (harness/, scripts/). The PR links to Triage agent configuration for code fullsend#1754 and explains the rationale. Human approval is always required for protected-path changes.

Low

  • [coherence-concern] scripts/post-triage.sh — The fallback-to-permissive behavior (treating unrecognized TRIAGE_AUTO_CODE values as on) means typos or configuration errors will silently enable auto-coding rather than failing closed. The *) branch emits a ::warning but then proceeds to auto-promote as if on. A fail-closed approach (treating unrecognized values as off) would be more conservative and prevent unintended agent dispatch.

  • [behavioral-change] scripts/post-triage.sh — The workflow-change warning (::warning::Triage detected workflow file changes required (#325)) is now emitted unconditionally for all categories when requires_workflow_changes=true, whereas previously it only fired for bug/documentation/performance. This is informational — it affects only CI log output, not label mutations.

  • [docs-currency] docs/code.md:32 — The ready-to-code label description states that triage unconditionally applies it for bug/documentation/performance categories without mentioning configurability. The description remains accurate for the default configuration but is now incomplete.


Next steps:

  • /fs-fix — agent addresses review findings automatically
  • /fs-fix <your instruction> — agent fixes with your specific guidance
  • Push commits directly — review re-runs automatically on push
  • /fs-fix-stop — disable automatic fix runs for this PR
Previous run (4)

Review

Findings

Medium

  • [API-contract-violation] harness/triage.yaml:38 — The env.runner block hardcodes TRIAGE_AUTO_CODE: "on" and TRIAGE_AUTO_CODE_CATEGORIES: "bug,documentation,performance" as literal strings. Every other harness config that passes runner env vars uses the ${VAR} expansion pattern (e.g., fix.yaml uses TARGET_BRANCH: "${TARGET_BRANCH}", scribe.yaml uses SCRIBE_REPO: ${SCRIBE_REPO}). Because these are literal values rather than pass-throughs, a user who sets TRIAGE_AUTO_CODE=off in their CI workflow env: block — as docs/triage.md instructs — would have that value overridden by the harness config's hardcoded "on". The documented configuration mechanism will not function.
    Remediation: Use the pass-through-with-default pattern: TRIAGE_AUTO_CODE: "${TRIAGE_AUTO_CODE:-on}" and TRIAGE_AUTO_CODE_CATEGORIES: "${TRIAGE_AUTO_CODE_CATEGORIES:-bug,documentation,performance}".

  • [protected-path] harness/triage.yaml, scripts/post-triage.sh, scripts/post-triage-test.sh — PR modifies protected governance/infrastructure files (harness/, scripts/). The PR links to Triage agent configuration for code fullsend#1754 and explains the rationale. Human approval is always required for protected-path changes.

Low

  • [coherence-concern] scripts/post-triage.sh — The fallback-to-permissive behavior (treating unrecognized TRIAGE_AUTO_CODE values as on) means typos or configuration errors will silently enable auto-coding rather than failing closed. The *) branch emits a ::warning but then proceeds to auto-promote as if on. A fail-closed approach (treating unrecognized values as off) would be more conservative and prevent unintended agent dispatch.

  • [behavioral-change] scripts/post-triage.sh — The workflow-change warning (::warning::Triage detected workflow file changes required (#325)) is now emitted unconditionally for all categories when requires_workflow_changes=true, whereas previously it only fired for bug/documentation/performance. This is informational — it affects only CI log output, not label mutations.

  • [docs-currency] docs/code.md:32 — The ready-to-code label description states that triage unconditionally applies it for bug/documentation/performance categories without mentioning configurability. The description remains accurate for the default configuration but is now incomplete.


Next steps:

  • /fs-fix — agent addresses review findings automatically
  • /fs-fix <your instruction> — agent fixes with your specific guidance
  • Push commits directly — review re-runs automatically on push
  • /fs-fix-stop — disable automatic fix runs for this PR
Previous run (5)

Review

Findings

Medium

  • [API-contract-violation] harness/triage.yaml:38 — The env.runner block hardcodes TRIAGE_AUTO_CODE: "on" and TRIAGE_AUTO_CODE_CATEGORIES: "bug,documentation,performance" as literal strings. Every other harness config that passes runner env vars uses the ${VAR} expansion pattern (e.g., fix.yaml uses TARGET_BRANCH: "${TARGET_BRANCH}", scribe.yaml uses SCRIBE_REPO: ${SCRIBE_REPO}). Because these are literal values rather than pass-throughs, a user who sets TRIAGE_AUTO_CODE=off in their CI workflow env: block — as docs/triage.md instructs — would have that value overridden by the harness config's hardcoded "on". The documented override mechanism will not function.
    Remediation: Use the pass-through-with-default pattern: TRIAGE_AUTO_CODE: "${TRIAGE_AUTO_CODE:-on}" and TRIAGE_AUTO_CODE_CATEGORIES: "${TRIAGE_AUTO_CODE_CATEGORIES:-bug,documentation,performance}".

  • [protected-path] harness/triage.yaml, scripts/post-triage.sh, scripts/post-triage-test.sh — PR modifies protected governance/infrastructure files (harness/, scripts/). The PR links to Triage agent configuration for code fullsend#1754 and explains the rationale. Human approval is always required for protected-path changes.

Low

  • [coherence-concern] scripts/post-triage.sh — The fallback-to-permissive behavior (treating unrecognized TRIAGE_AUTO_CODE values as on) means typos or configuration errors will silently enable auto-coding rather than failing closed. The *) branch emits a ::warning but then proceeds to auto-promote as if on. A fail-closed approach (treating unrecognized values as off) would be more conservative and prevent unintended agent dispatch.

  • [behavioral-change] scripts/post-triage.sh — The workflow-change warning (::warning::Triage detected workflow file changes required (#325)) is now emitted unconditionally for all categories when requires_workflow_changes=true, whereas previously it only fired for bug/documentation/performance. This is informational — it affects only CI log output, not label mutations.


Next steps:

  • /fs-fix — agent addresses review findings automatically
  • /fs-fix <your instruction> — agent fixes with your specific guidance
  • Push commits directly — review re-runs automatically on push
  • /fs-fix-stop — disable automatic fix runs for this PR
Previous run (6)

Review

Findings

Medium

  • [protected-path] harness/triage.yaml, scripts/post-triage.sh, scripts/post-triage-test.sh — PR modifies protected governance/infrastructure files (harness/, scripts/). The PR links to Triage agent configuration for code fullsend#1754 and explains the rationale. Human approval is always required for protected-path changes.

Low

  • [logic-gap] scripts/post-triage.sh — The auto_code_allowed() function is only consulted for bug, documentation, and performance categories in the case statement. Other categories (feature, etc.) have hardcoded behavior that always applies triaged. Setting TRIAGE_AUTO_CODE=category with TRIAGE_AUTO_CODE_CATEGORIES=feature would have no effect. The docs/triage.md Variables table states "Any valid triage categories" for valid values, which overstates the mechanism's actual scope.

  • [behavioral-change] scripts/post-triage.sh — The workflow-change warning is now emitted unconditionally for all categories when requires_workflow_changes=true. Previously it only fired for bug/documentation/performance. The warning message text also changed. If downstream monitoring parses the specific warning string, it would break.

Previous run (7)

Review

Findings

Medium

  • [protected-path] harness/triage.yaml, scripts/post-triage.sh, scripts/post-triage-test.sh, scripts/pre-code.sh, scripts/pre-code.src.sh — PR modifies protected governance/infrastructure files (harness/, scripts/). The PR links to Triage agent configuration for code fullsend#1754 and explains the rationale. Human approval is always required for protected-path changes.

Low

  • [logic-gap] scripts/post-triage.sh — The auto_code_allowed() function is only consulted for bug, documentation, and performance categories in the case statement. Other categories (feature, etc.) have hardcoded behavior that always applies triaged. Setting TRIAGE_AUTO_CODE=category with TRIAGE_AUTO_CODE_CATEGORIES=feature would have no effect. The docs/triage.md Variables table states "Any valid triage categories" for valid values, which overstates the mechanism's actual scope.

  • [GHA workflow command injection] scripts/post-triage.shCATEGORY (from untrusted agent jq output) is interpolated into multiple echo statements without sanitizing control characters. The PR adds new echo paths that interpolate CATEGORY (e.g., "Applying triaged label (auto-code disabled for ${CATEGORY})..."). On a GHA runner, a multi-line CATEGORY could inject workflow commands. The most dangerous commands (::set-env::, ::add-path::) are disabled since Oct 2020, reducing impact. Remediation: CATEGORY="${CATEGORY//[[:cntrl:]]/}" immediately after extraction.

  • [behavioral-change] scripts/post-triage.sh — The workflow-change warning is now emitted unconditionally for all categories when requires_workflow_changes=true. Previously it only fired for bug/documentation/performance. The message is purely informational, so the broader scope is harmless.

  • [stale-doc] docs/code.md:32 — The ready-to-code label description states it is "Applied by the triage agent for low-risk categories" without noting this behavior is now configurable via TRIAGE_AUTO_CODE. The PR already updates docs/triage.md with a Variables table and cross-reference. Adding "by default" to code.md would improve clarity.

  • [missing-configuration-guidance] docs/triage.md — The Variables table documents TRIAGE_AUTO_CODE and TRIAGE_AUTO_CODE_CATEGORIES but does not explain WHERE users configure these values. The established pattern in docs/code.md includes location guidance (e.g., "Set via runner_env in harness/code.yaml").

Previous run (8)

Review

Findings

Medium

  • [protected-path] harness/triage.yaml, scripts/post-triage.sh, scripts/post-triage-test.sh, scripts/pre-code.src.sh, scripts/lib/prescript-output.lib.sh — PR modifies protected governance/infrastructure files (harness/, scripts/). The PR links to Triage agent configuration for code fullsend#1754 and explains the rationale. Human approval is always required for protected-path changes.

Low

  • [GHA workflow command injection] scripts/pre-code.src.sh:28::notice:: emits GITHUB_ISSUE_URL before the format validation check runs. The most dangerous workflow commands (::set-env::, ::add-path::) are disabled since Oct 2020, but remaining commands like ::error:: could be injected before validation exits. Move the notice to after validation or sanitize first.

  • [GHA workflow command injection] scripts/pre-code.src.sh:87COMMENT_BODY (user-authored) is echoed raw to stdout. On GHA runners, multi-line content could inject :: workflow commands. Consider logging length instead of raw content.

  • [GHA workflow command injection] scripts/pre-code.src.sh:112::notice:: interpolates FIRST_PR_NUM and FIRST_PR_AUTHOR from parsed gh output without explicit validation. Defense-in-depth validation recommended.

  • [GHA workflow command injection] scripts/post-triage.shCATEGORY from agent output (untrusted) is interpolated into stdout messages. Multi-line values from jq -r could inject workflow commands. Sanitize with CATEGORY="${CATEGORY//[[:cntrl:]]/}".

  • [scope-exceeded] scripts/pre-code.src.sh — New 203-line script implements pre-code input validation, existing human PR detection, and pre-commit tool auto-installation. These features are unrelated to the TRIAGE_AUTO_CODE configuration (issue #1754); the script references Remove redundant pre-code.sh / pre-fix.sh calls from reusable workflows fullsend#4718.

  • [scope-exceeded] scripts/lib/prescript-output.lib.sh — New 26-line library implements a pre-script output protocol (referencing Remove redundant pre-code.sh / pre-fix.sh calls from reusable workflows fullsend#4718). Infrastructure unrelated to TRIAGE_AUTO_CODE (issue #1754).

  • [scope-creep] scripts/pre-code.src.sh — The pre-code script bundles three independent concerns: input validation, existing-PR detection, and pre-commit tool auto-installation.

  • [behavioral-change] scripts/post-triage.sh — The workflow-change warning is now emitted unconditionally for all categories when requires_workflow_changes=true. Previously it only fired for bug/documentation/performance. The message is purely informational, so the broader scope is harmless.

  • [stale-doc] docs/code.md:32 — The ready-to-code label description states it is "Applied by the triage agent for low-risk categories" without noting this behavior is now configurable via TRIAGE_AUTO_CODE. Adding "by default" would improve clarity.

  • [missing-configuration-guidance] docs/triage.md — The documentation adds TRIAGE_AUTO_CODE and TRIAGE_AUTO_CODE_CATEGORIES variables but does not explain WHERE users configure these values. Adding "Set via runner env in harness/triage.yaml" would follow established patterns.

Previous run (9)

Review

Findings

Medium

  • [protected-path] harness/triage.yaml, scripts/post-triage.sh, scripts/post-triage-test.sh — PR modifies protected governance/infrastructure files (harness/, scripts/). The PR links to Triage agent configuration for code fullsend#1754 and explains the rationale. Human approval is always required for protected-path changes.

Low

  • [error-handling-gap] scripts/post-triage.sh:401 — Under set -euo pipefail, ${TRIAGE_AUTO_CODE} without a :- default will crash with "unbound variable" if the env var is not set. The harness config provides defaults, but the script is not self-defensive against alternative forges that don't inject env.runner vars. Same applies to ${TRIAGE_AUTO_CODE_CATEGORIES} on line 408. This follows the script's established pattern (other required vars like GITHUB_ISSUE_URL also use bare expansion), so the risk is consistent with existing code.

  • [behavioral-change] scripts/post-triage.sh:419 — The workflow-change warning (::warning::Triage detected workflow file changes required) is now emitted unconditionally for all categories when requires_workflow_changes=true. Previously it only fired for bug/documentation/performance. The new message text is purely informational (unlike the old "Skipping ready-to-code" which described suppression), so the broader scope is harmless.

  • [stale-doc] docs/code.md:32 — The ready-to-code label description states it is "Applied by the triage agent for low-risk categories" without noting this behavior is now configurable via TRIAGE_AUTO_CODE. The triage.md doc (changed in this PR) already includes the configurability note and links to the Variables section, providing indirect coverage. Adding "by default" would improve clarity.

  • [missing-configuration-guidance] docs/triage.md — The documentation adds TRIAGE_AUTO_CODE and TRIAGE_AUTO_CODE_CATEGORIES variables but does not explain WHERE users configure these values. The existing CODE_ALLOWED_TARGET_BRANCHES in docs/code.md includes "Set via runner_env in harness/code.yaml" guidance. Adding similar guidance (e.g., "Set via runner env in harness/triage.yaml") would follow the established pattern.

Previous run (10)

Review

Findings

Medium

  • [protected-path] harness/triage.yaml, scripts/post-triage.sh, scripts/post-triage-test.sh — PR modifies protected governance/infrastructure files (harness/, scripts/). The PR links to Triage agent configuration for code fullsend#1754 and explains the rationale. Human approval is always required for protected-path changes.

Low

  • [stale-doc] docs/code.md:32 — The ready-to-code label description states it is "Applied by the triage agent for low-risk categories" without noting this behavior is now configurable via TRIAGE_AUTO_CODE. The triage.md doc (changed in this PR) already includes the configurability note and links to the Variables section, providing indirect coverage. Adding "by default" would improve clarity.

  • [missing-configuration-guidance] docs/triage.md — The documentation adds TRIAGE_AUTO_CODE and TRIAGE_AUTO_CODE_CATEGORIES variables but does not explain WHERE users configure these values. The existing CODE_ALLOWED_TARGET_BRANCHES in docs/code.md includes "Set via runner_env in harness/code.yaml" guidance. Adding similar guidance (e.g., "Set via runner env in harness/triage.yaml") would follow the established pattern.

Previous run (11)

Review

Findings

Medium

  • [protected-path] harness/triage.yaml, scripts/post-triage.sh, scripts/post-triage-test.sh — PR modifies protected governance/infrastructure files (harness/, scripts/). The PR links to Triage agent configuration for code fullsend#1754 and explains the rationale. Human approval is always required for protected-path changes.

Low

  • [edge-case] scripts/post-triage.sh:403 — The auto_code_allowed function uses case-sensitive matching for TRIAGE_AUTO_CODE values. Setting TRIAGE_AUTO_CODE=OFF (uppercase) falls through to the * default, preserving auto-promotion instead of disabling it. The fallback to default behavior is documented and safe, but a case-insensitive match would prevent user confusion.

  • [edge-case] scripts/post-triage-test.sh:730 — The run_test_with_env helper uses unquoted ${extra_env} with word-splitting to iterate KEY=VALUE pairs. This breaks if any value contains spaces — a latent fragility in the test harness.

  • [stale-doc] docs/code.md:32 — The ready-to-code label description states it is "Applied by the triage agent for low-risk categories" without noting this behavior is now configurable. The existing link to triage.md provides indirect coverage, but adding "by default" would improve clarity.

  • [documentation-alignment] docs/triage.md — The Variables table uses 3 columns (Variable | Default | Description) while other agent docs (review.md, code.md) use 4 columns (Variable | Description | Default | Valid values). Aligning the column structure would improve consistency.

Previous run (12)

Review

Findings

Medium

  • [stale-doc] docs/code.md:32 — The ready-to-code label description states it is "Applied by the triage agent for low-risk categories (bug, documentation, performance)" without noting this behavior is now configurable via TRIAGE_AUTO_CODE. After this PR, the description is misleading for users who disable auto-promotion.
    Remediation: Update to note that auto-promotion is configurable, e.g., add "by default" or reference the triage agent's Variables section.

  • [protected-path] harness/triage.yaml, scripts/post-triage.sh, scripts/post-triage-test.sh — PR modifies protected governance/infrastructure files (harness/, scripts/). The PR links to Triage agent configuration for code fullsend#1754 and explains the rationale. Human approval is always required for protected-path changes.

Low

  • [edge-case] scripts/post-triage.sh — The auto_code_allowed function uses case-sensitive matching for TRIAGE_AUTO_CODE values. Setting TRIAGE_AUTO_CODE=OFF (uppercase) falls through to the * default, preserving auto-promotion instead of disabling it. The fallback to default behavior is documented and safe, but a case-insensitive match would prevent user confusion.

  • [edge-case] scripts/post-triage-test.sh — The run_test_with_env helper uses unquoted ${extra_env} with word-splitting to iterate KEY=VALUE pairs. This breaks if any value contains spaces — a latent fragility in the test harness.


Labels: PR modifies the triage agent post-script and harness configuration.

fullsend-ai-review[bot]

This comment was marked as outdated.

@fullsend-ai-review fullsend-ai-review Bot added requires-manual-review Review requires human judgment triage-agent labels Jul 30, 2026
@fullsend-ai-review

fullsend-ai-review Bot commented Jul 30, 2026

Copy link
Copy Markdown

🤖 Finished Review · ✅ Success · Started 4:40 PM UTC · Completed 4:57 PM UTC
Commit: 780c846 · View workflow run →

fullsend-ai-review[bot]

This comment was marked as outdated.

@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.

Additional review findings (verified against head commit 780c846, deduplicated against existing threads).

Comment thread scripts/post-triage.sh Outdated
Comment thread scripts/post-triage-test.sh Outdated
Comment thread docs/triage.md Outdated
Comment thread scripts/post-triage.sh
@fullsend-ai-review

fullsend-ai-review Bot commented Jul 30, 2026

Copy link
Copy Markdown

🤖 Finished Review · ✅ Success · Started 5:28 PM UTC · Completed 5:44 PM UTC
Commit: cdb0696 · View workflow run →

@fullsend-ai-review

fullsend-ai-review Bot commented Jul 30, 2026

Copy link
Copy Markdown

🤖 Finished Review · ✅ Success · Started 6:05 PM UTC · Completed 6:24 PM UTC
Commit: 571ec3d · View workflow run →

fullsend-ai-review[bot]

This comment was marked as outdated.

@fullsend-ai-review

fullsend-ai-review Bot commented Jul 30, 2026

Copy link
Copy Markdown

🤖 Finished Review · ✅ Success · Started 6:40 PM UTC · Completed 6:57 PM UTC
Commit: 2fa6df9 · View workflow run →

fullsend-ai-review[bot]

This comment was marked as outdated.

@fullsend-ai-review

fullsend-ai-review Bot commented Jul 30, 2026

Copy link
Copy Markdown

🤖 Review · ⚠️ Cancelled · Started 7:06 PM UTC · Ended 7:06 PM UTC
Commit: a0ab900 · View workflow run →

ralphbean and others added 6 commits July 30, 2026 15:06
Add TRIAGE_AUTO_CODE env var to control whether triage auto-applies the
ready-to-code label (which triggers the code agent). Three modes:

- on (default): auto-promote bug/documentation/performance — preserves
  existing behavior.
- off: never auto-promote; always apply triaged instead, requiring
  human review before coding starts.
- category: auto-promote only categories listed in
  TRIAGE_AUTO_CODE_CATEGORIES (comma-separated, default:
  bug,documentation,performance).

Closes fullsend-ai/fullsend#1754

Assisted-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Ralph Bean <rbean@redhat.com>
Suppress SC2163 shellcheck warning in post-triage-test.sh where
export "${kv}" is intentionally used to export KEY=VALUE pairs from
word-split strings.

Remove ${VAR:-default} syntax from harness/triage.yaml forge env vars —
the fullsend Go binary does not support shell-style defaults in YAML
env expansion. The post-triage.sh script already handles defaults
internally.

Signed-off-by: Ralph Bean <rbean@redhat.com>
Assisted-by: Claude claude-opus-4-6 <noreply@anthropic.com>
Signed-off-by: Ralph Bean <rbean@redhat.com>
Strip whitespace from the comma-separated categories string before
matching, so "bug, documentation" works the same as "bug,documentation".
Add a test case for whitespace tolerance.

Signed-off-by: Ralph Bean <rbean@redhat.com>
Assisted-by: Claude claude-opus-4-6 <noreply@anthropic.com>
Signed-off-by: Ralph Bean <rbean@redhat.com>
- Normalize TRIAGE_AUTO_CODE to lowercase for case-insensitive matching
- Emit (#325) workflow-change warning independently of auto_code_allowed
  so the operational signal is always visible when REQUIRES_WORKFLOW is true
- Fix run_test_with_env to use newline-delimited parsing so values with
  spaces (like "bug, documentation, performance") survive intact
- Switch whitespace-tolerant test to use documentation fixture to actually
  exercise multi-item category matching
- Reorder docs table to match Variable | Description | Default | Valid
  values convention from review.md and code.md

Signed-off-by: Ralph Bean <rbean@redhat.com>
Assisted-by: Claude claude-opus-4-6 <noreply@anthropic.com>
Signed-off-by: Ralph Bean <rbean@redhat.com>
The harness file is the single source of truth for env var defaults.
Move TRIAGE_AUTO_CODE and TRIAGE_AUTO_CODE_CATEGORIES from post-script
shell defaults (:-on, :-bug,...) to top-level env.runner literals in
harness/triage.yaml. End users override via base-derived harness
configs instead of workflow env vars.

This also fixes the functional test failures — fullsend validates all
forge.github.env.runner ${VAR} refs against the host environment, so
the previous approach required every caller (eval, production workflow,
end users) to have these vars pre-set even though they're optional
with defaults.

Signed-off-by: Ralph Bean <rbean@redhat.com>
Assisted-by: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Ralph Bean <rbean@redhat.com>
Add :- defaults to TRIAGE_AUTO_CODE and TRIAGE_AUTO_CODE_CATEGORIES so
the script doesn't crash under set -euo pipefail when the env vars are
unset (e.g. running outside the harness).

Signed-off-by: Ralph Bean <rbean@redhat.com>
Assisted-by: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Ralph Bean <rbean@redhat.com>
@ralphbean
ralphbean force-pushed the agent/1754-triage-auto-code-config branch from a0ab900 to 896f6d8 Compare July 30, 2026 19:06
@fullsend-ai-review

fullsend-ai-review Bot commented Jul 30, 2026

Copy link
Copy Markdown

🤖 Review · ⚠️ Cancelled · Started 7:08 PM UTC · Ended 7:20 PM UTC
Commit: 896f6d8 · View workflow run →

@fullsend-ai-review

fullsend-ai-review Bot commented Jul 30, 2026

Copy link
Copy Markdown

🤖 Finished Review · ✅ Success · Started 7:22 PM UTC · Completed 7:38 PM UTC
Commit: ec468fd · View workflow run →

@fullsend-ai-review
fullsend-ai-review Bot dismissed their stale review August 3, 2026 18:57

Superseded by updated review

fullsend-ai-review[bot]

This comment was marked as outdated.

@fullsend-ai-review fullsend-ai-review Bot added the requires-manual-review Review requires human judgment label Aug 3, 2026

@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.

Review-only sweep — 1 new finding (ADR 0080 merged since the last sweep and now requires override docs that docs/triage.md still lacks).

Comment thread docs/triage.md Outdated

@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 — no functional blockers. Outstanding item: docs/triage.md still needs the per-repo/org override instructions ADR 0080 mandates for this exact PR (merged 2026-08-03, cites this PR by name). Small, doc-only gap — trusting this gets closed before merge. Two other pre-existing MEDIUM notes (harness env-var pass-through convention, TRIAGE_AUTO_CODE_CATEGORIES doc wording) are non-blocking style/doc items.

@deboer-tim

Copy link
Copy Markdown
Collaborator

I created a very similar PR a couple weeks ago: #331. I've just closed it as a duplicate of this PR but one nit: the code agent docs (docs/code.md) include what conditions/categories the triage agent will auto-triage and this will make it incorrect. That doc should be cleaned up, preferably but removing unnecessary details of the triage agent.

However, the main reason I didn't push on my PR is that I started to get uncomfortable with having a triage-specific way to disable triggering the code agent. First, it's kind of backwards (we want coder to not trigger automatically, not triage to behave differently) and architecturally odd (triage agent shouldn't know details of code agent or care if it's human), but mostly it's because I think every agent should have an 'installed but not triggered automatically' mode. i.e. triage, review, or retro only happens when a human asks.

Some of these may be unlikely to be used (who really cares if triage adds a comment?) but I've been leaning towards a platform-level agent setting or CEL for 'only trigger on human request' being a better way to handle this. It would provide a simple, consistent way to handle this without complexity in any agent, plus optional softer onboarding for all agents.

(TRIAGE_AUTO_CODE_CATEGORIES should still be here as triage config. One could argue whether it should be the triage agent deciding when the coding agent has enough details to do well vs code agent deciding what it can fix, but I think the time/$$/simplicity means triage will always be the one to decide)

@ralphbean

Copy link
Copy Markdown
Member Author

Yeah, CEL expressions are probably the way for most of your "act on labels or only act on explicit commands" configuration. There's an epic tracking this: fullsend-ai/fullsend#2888 (per-repo harness CEL dispatch) — moving each default agent's trigger logic off the bash router and onto CEL expressions one at a time.

"category" and "on" were already 100% identical in auto_code_allowed()
after the in-script default list was dropped -- both just call
category_in_auto_code_list(). Drop the redundant enum value and update
docs/triage.md to describe the actual two-value behavior, plus add the
override-path note ADR 0080 requires for this variable.

Addresses PR review feedback.

Assisted-by: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Ralph Bean <rbean@redhat.com>
@fullsend-ai-review

fullsend-ai-review Bot commented Aug 5, 2026

Copy link
Copy Markdown

🤖 Finished Review · ✅ Success · Started 6:42 PM UTC · Completed 6:59 PM UTC
Commit: 75d64c3 · View workflow run →

@ralphbean
ralphbean added this pull request to the merge queue Aug 5, 2026
Merged via the queue into main with commit ff0e29b Aug 5, 2026
16 checks passed
@ralphbean
ralphbean deleted the agent/1754-triage-auto-code-config branch August 5, 2026 19:02
@fullsend-ai-retro

fullsend-ai-retro Bot commented Aug 5, 2026

Copy link
Copy Markdown

🤖 Finished Retro · ✅ Success · Started 7:04 PM UTC · Completed 7:14 PM UTC
Commit: 75d64c3 · View workflow run →

@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.

Review findings below (inline comments cover 3 of them; one more that doesn't anchor to a specific line is here in the summary).

[MEDIUM] PR description still advertises a third "category" mode that this PR's own final commit removed

The PR description currently reads: "Three modes: on (default, preserves existing behavior), off (never auto-promote), category (auto-promote only listed categories via TRIAGE_AUTO_CODE_CATEGORIES)." The current head commit collapsed the category enum value into on (docs/triage.md's Variables table now lists only on/off as valid values, and on's description already reads as category-gated auto-promotion). The description was never updated to match, so it now describes a design that contradicts the shipped implementation as of the commit under review. This is separate from the earlier resolved thread about the "closes #1754" auto-close scoping claim — that thread never touched this "three modes" text.

Suggestion: update the description to describe the final two-value design (on/off, with on scoped by TRIAGE_AUTO_CODE_CATEGORIES) before merge, since this text is the durable record of how #1754 was resolved.

Comment thread scripts/post-triage.sh
# the new action. Every terminal action below resets its own set of control
# labels, but "triaged" is only ever re-applied (never removed) by the
# handlers themselves, so it must be cleared up front rather than per-branch.
remove_label "triaged"

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.

[HIGH] remove_label("triaged") runs before per-action input validation, mutating GitHub state on failing runs

remove_label "triaged" (line 122) executes unconditionally immediately before case "${ACTION}" in (line 124) — i.e. before every branch's own validation, e.g. insufficient's [[ -z "${COMMENT}" ]] guard (lines 126-129), and before the final *) echo "ERROR: unknown action..."; exit 1 fallback (lines 522-524) for a malformed/unrecognized ACTION.

remove_label() issues a live gh api ... -X DELETE against the issue's labels with errors swallowed (2>/dev/null || true), so this is a real, unguarded side effect. Every other mutation in this script follows validate-then-mutate (each terminal action checks its required fields before calling add_label/remove_label). This new call breaks that invariant: a malformed agent-result.json or a not-yet-handled future ACTION value will now strip the triaged label from the live issue before the script aborts, leaving the issue with no control label and no explanatory comment despite the run being reported as failed.

This ordering concern wasn't raised in the earlier thread that introduced this single pre-dispatch call — that thread fixed a coverage gap (stale label only cleared on sufficient) but didn't flag the new validation-ordering regression.

Suggestion: move the remove_label "triaged" call inside each terminal action's block (after that action's own validation/guard, alongside its other remove_label calls), or gate it behind a check that ACTION is a known, already-validated terminal action, so no label mutation happens before a validation failure short-circuits the script.

Comment thread scripts/post-triage.sh
# the new action. Every terminal action below resets its own set of control
# labels, but "triaged" is only ever re-applied (never removed) by the
# handlers themselves, so it must be cleared up front rather than per-branch.
remove_label "triaged"

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.

[MEDIUM] Stale-"triaged"-label removal is test-covered for only 2 of 7 action branches

The case "${ACTION}" in dispatch has 7 branches (insufficient, duplicate, prerequisites, in-progress, sufficient, question, not-planned). The comment above this shared remove_label "triaged" call states it must fire for every terminal action, but scripts/post-triage-test.sh only has run_test "insufficient-clears-stale-triaged-label" and run_test "sufficient-clears-stale-triaged-label"duplicate, prerequisites, in-progress, question, and not-planned have zero regression coverage for this DELETE call.

Because the fix is currently a single shared call, the immediate risk is low, but there's no test to catch a future refactor (e.g. reintroducing per-branch logic, floated elsewhere in review as a follow-up for the auto-code triplication) from silently dropping the removal on 5 of the 7 branches.

Suggestion: add one run_test "<action>-clears-stale-triaged-label" case per remaining branch (duplicate, prerequisites, in-progress, question, not-planned), mirroring the existing insufficient/sufficient tests in scripts/post-triage-test.sh.

Comment thread docs/triage.md
| `TRIAGE_AUTO_CODE` | Controls whether triage auto-applies `ready-to-code`. `on` — auto-promote categories listed in `TRIAGE_AUTO_CODE_CATEGORIES`. `off` — never auto-promote; always apply `triaged`. | `on` | `on`, `off` |
| `TRIAGE_AUTO_CODE_CATEGORIES` | Comma-separated list of categories to auto-promote when `TRIAGE_AUTO_CODE=on`. | `bug,documentation,performance` | `bug`, `documentation`, `performance` |

To override these defaults per repo or org, create a custom harness for the

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.

[MEDIUM] New override guidance doesn't match the SHA-pinned base: pattern docs/code.md actually requires, and a bare relative path won't resolve cross-repo

This new paragraph tells operators to override the two new variables by creating .fullsend/triage.yaml with "a base: pointing at harness/triage.yaml" — a repo-relative markdown link, with no YAML example. But docs/code.md's own "How to configure" section requires base: to be a full SHA-pinned URL with an integrity hash — base: https://raw.githubusercontent.com/fullsend-ai/agents/<SHA>/harness/code.yaml#sha256=<sha256sum> — obtained via a documented curl/sha256sum recipe, not a bare relative path.

Checking fullsend's harness composition (loadBaseChain), a non-https:// base value is resolved relative to the child harness file's own directory on disk. That only works when the overriding .fullsend/triage.yaml lives in the same checkout as harness/triage.yaml (local/monorepo composition). An external org's .fullsend/triage.yaml lives in a different repository, where no harness/triage.yaml file exists, so the guidance as literally written wouldn't resolve there.

This substance hasn't been confirmed anywhere in the thread — the "Does that cover it?" question after this text was pushed has no reply yet.

Suggestion: give a concrete YAML example mirroring code.md's SHA-pinned base: URL (with the same curl/sha256sum snippet, substituted for triage.yaml), and drop or clarify the bare relative-path phrasing so it isn't read as the literal value to place in base:.

@fullsend-ai-retro

Copy link
Copy Markdown

Retro: PR #567 — TRIAGE_AUTO_CODE configuration

Timeline: PR #567, authored by ralphbean, added TRIAGE_AUTO_CODE env var controls for triage auto-promotion behavior. The PR spanned 6 days (Jul 30 – Aug 5, 2026), accumulated 15 commits, and triggered 17 review agent dispatches (13 successful, 4 cancelled) before merging. Three human reviewers (waynesun09, maruiz93, deboer-tim) provided substantive feedback that drove 9 of those 15 commits.

Key findings

Review quality gap — human reviewers significantly outperformed the review agent on this PR. The review agent's correctness sub-agent missed the PR's highest-severity bugs, all caught by human reviewer waynesun09:

  • Stale triaged label surviving re-triage (label mutual-exclusion invariant violation)
  • Bash 3.2 portability failure (${VAR,,} syntax requires bash 4+)
  • Degenerate tests passing trivially due to shell word-splitting (the test assertion was vacuous)
  • Empty-string vs unset semantic mismatch (:- vs - in parameter expansion)
  • Five independent copies of the default category list with no single source of truth

Meanwhile, the review agent spent significant token budget repeating the [API-contract-violation] finding verbatim across 6 consecutive runs after the author had already confirmed the pattern was intentional per ADR 0080.

Human reviewer maruiz93 raised architectural concerns about the config override mechanism (CI env blocks vs harness composition) that led to ADRs 0080/0081 — a class of design-level feedback outside the review agent's current capability.

Token cost — 13 full review runs on a single PR is excessive. Most runs produced near-identical findings on unchanged code. The agent does have re-review narrowing (severity anchoring, dimension skipping), but it still dispatched full review cycles on every push.

Evidence for existing open issues

  • #106 (re-raises findings after author declines scope): The [API-contract-violation] finding was repeated 6 times across successive runs after the author explicitly confirmed the literal-default pattern was intentional. This is strong evidence for Review agent re-raises pre-existing findings after author explicitly declines scope #106.
  • #131 (correctness sub-agent should include common shell script pitfall checks): The ${VAR,,} bash 4+ syntax and the :- vs - parameter expansion semantic difference are exactly the class of shell pitfalls Review correctness sub-agent should include common shell script pitfall checks #131 targets. This PR provides two concrete missed-catch examples.
  • #343 (scope re-review to finding verification): 13 full review runs were dispatched; many produced near-identical findings on unchanged code. Narrowing re-review scope to finding verification on follow-up pushes would have substantially reduced token cost.
  • #680 (suppress governance CHANGES_REQUESTED when human approvals satisfy the gate): The review agent maintained CHANGES_REQUESTED on every run due to protected-path findings, even after human reviewers had already approved.

Proposals filed

One proposal targeting the review agent's correctness sub-agent test integrity checks — a novel gap not covered by existing issues.

Proposals filed

ggallen pushed a commit that referenced this pull request Aug 19, 2026
remove_label "triaged" previously only ran on the sufficient branch,
so an issue that acquired triaged under a prior TRIAGE_AUTO_CODE=off
run kept it alongside needs-info/duplicate/blocked/question/pr-open/
not-planned on any later re-triage. Move the reset to a single point
before the action dispatch so every terminal action gets the same
cleanup.

Also add coverage for the TRIAGE_AUTO_CODE=category default-category
fallback with TRIAGE_AUTO_CODE_CATEGORIES genuinely unset — the
existing "default" test inherited the harness-level export instead of
exercising the script's own bash default.

Addresses review feedback on #567.

Assisted-by: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Ralph Bean <rbean@redhat.com>
ggallen pushed a commit that referenced this pull request Aug 19, 2026
…efault

The bug/documentation/performance allowlist was independently expressed
in three places inside post-triage.sh (the "on" branch, the "*" fallback
branch, and the "category" branch's own env-var default) plus docs/triage.md
and harness/triage.yaml. Rather than extract a shared constant, remove the
script-level default entirely: "on" and "category" now both read the list
from TRIAGE_AUTO_CODE_CATEGORIES via a single category_in_auto_code_list()
helper, with an absent/unset var treated as an empty allowlist. The
"bug,documentation,performance" default now lives only in
harness/triage.yaml (which always sets it) and docs/triage.md.

Updates test coverage accordingly: the tests that previously locked in
the script's own default now assert the var is required.

Addresses review feedback on #567.

Assisted-by: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Ralph Bean <rbean@redhat.com>
ggallen pushed a commit to ggallen/agents that referenced this pull request Aug 19, 2026
remove_label "triaged" previously only ran on the sufficient branch,
so an issue that acquired triaged under a prior TRIAGE_AUTO_CODE=off
run kept it alongside needs-info/duplicate/blocked/question/pr-open/
not-planned on any later re-triage. Move the reset to a single point
before the action dispatch so every terminal action gets the same
cleanup.

Also add coverage for the TRIAGE_AUTO_CODE=category default-category
fallback with TRIAGE_AUTO_CODE_CATEGORIES genuinely unset — the
existing "default" test inherited the harness-level export instead of
exercising the script's own bash default.

Addresses review feedback on fullsend-ai#567.

Assisted-by: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Ralph Bean <rbean@redhat.com>
ggallen pushed a commit to ggallen/agents that referenced this pull request Aug 19, 2026
…efault

The bug/documentation/performance allowlist was independently expressed
in three places inside post-triage.sh (the "on" branch, the "*" fallback
branch, and the "category" branch's own env-var default) plus docs/triage.md
and harness/triage.yaml. Rather than extract a shared constant, remove the
script-level default entirely: "on" and "category" now both read the list
from TRIAGE_AUTO_CODE_CATEGORIES via a single category_in_auto_code_list()
helper, with an absent/unset var treated as an empty allowlist. The
"bug,documentation,performance" default now lives only in
harness/triage.yaml (which always sets it) and docs/triage.md.

Updates test coverage accordingly: the tests that previously locked in
the script's own default now assert the var is required.

Addresses review feedback on fullsend-ai#567.

Assisted-by: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Ralph Bean <rbean@redhat.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants