Skip to content

feat: add generic refine agent#86

Open
ascerra wants to merge 3 commits into
mainfrom
feat/add-refine-agent
Open

feat: add generic refine agent#86
ascerra wants to merge 3 commits into
mainfrom
feat/add-refine-agent

Conversation

@ascerra

@ascerra ascerra commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Adds a platform-agnostic refinement agent that decomposes work items into implementable children with acceptance criteria
  • Includes harness config, sandbox policy (read-only GitHub API), pre/post scripts, result schema, platform context docs (Jira/GitHub/GitLab), and test suite (29 tests passing)
  • Depends on shared scripts from feat: add generic explore agent #11 (explore agent) — comment-helpers.sh, pre-explore.sh, and markdown-to-adf.py

Related Issue

Continuation of agent migration from konflux-ci/refinement to generic agents repo.

Changes

File Description
agents/refine.md Generic refine agent prompt (no Konflux-specific references)
harness/refine.yaml Harness config with env.runner/env.sandbox format, human-directive mount
policies/refine.yaml Sandbox policy with read-only GitHub API access
schemas/refine-result.schema.json Output validation schema
scripts/pre-refine.sh Context preparation (issue, exploration, platform, routing)
scripts/post-refine.sh Result processing, comment posting, label management
scripts/post-refine-test.sh 29-test suite covering reply targeting, plan summary, labels, JSON extraction
scripts/platform-{jira,github,gitlab}.md Platform-specific hierarchy and format context
env/refine.env Sandbox environment variables
docs/refine.md User-facing documentation
config.yaml Registers harness/refine.yaml
README.md Lists refine agent in agent table

Testing

  • bash scripts/post-refine-test.sh — 29/29 tests passing
  • Integration test with live issue (post-merge)

Checklist

  • No Konflux-specific references in agent code
  • Sandbox policy enforces read-only GitHub API access
  • PUT verb blocked in disallowedTools
  • Human directive file mounted into sandbox
  • Forge block uses env.runner/env.sandbox format
  • Pipeline labels parameterized via environment variables

Made with Cursor

Add a platform-agnostic refinement agent that decomposes work items into
implementable children with acceptance criteria. Includes harness config,
sandbox policy (read-only GitHub API), pre/post scripts, result schema,
platform context docs (Jira/GitHub/GitLab), and test suite (29 tests).

Depends on shared scripts from PR #11 (explore agent) — comment-helpers.sh,
pre-explore.sh, and markdown-to-adf.py.

Signed-off-by: Adam Scerra <ascerra@redhat.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
@ascerra ascerra requested a review from a team as a code owner July 9, 2026 17:45
@fullsend-ai-review

fullsend-ai-review Bot commented Jul 9, 2026

Copy link
Copy Markdown

🤖 Finished Review · ✅ Success · Started 5:46 PM UTC · Completed 5:57 PM UTC
Commit: 8e5887d · View workflow run →

@qodo-code-review

Copy link
Copy Markdown

PR Summary by Qodo

Add platform-agnostic refine agent with harness, policy, schema, and scripts

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

Grey Divider

AI Description

• Add a generic refine agent that always decomposes work into implementable child items.
• Wire a full refine harness (pre/post scripts, schema validation loop) with read-only sandbox
 policy.
• Document platform-specific hierarchy/format rules and add a shell test suite for post-processing.
Diagram

graph TD
  A(("Trigger /fs-refine")) --> B["harness/refine.yaml"] --> C["scripts/pre-refine.sh"] --> D["agents/refine.md"] --> E["schemas/refine-result.schema.json"] --> F["scripts/post-refine.sh"] --> G{{"Issue platform\n(GitHub/Jira)"}}
  F --> H[("Run artifact\nrefine-result.json")]

  subgraph Legend
    direction LR
    _start(("Trigger")) ~~~ _cfg["Config/Harness"] ~~~ _dec{{"Decision/Target"}} ~~~ _art[("Artifact")]
  end
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Adopt a shared cross-agent result schema
  • ➕ Reduces schema proliferation and makes downstream tooling consistent across explore/refine/critique
  • ➕ Enables reusable validation/post-processing utilities
  • ➖ Requires broader refactor and coordination across other agent PRs
  • ➖ May slow delivery of the refine agent rollout
2. Do not auto-update issue descriptions; comment-only output
  • ➕ Avoids additional write paths/permissions and reduces risk of accidental overwrites
  • ➕ Keeps refine as a purely additive workflow step
  • ➖ Lowers usability (refined description is harder to find/consume)
  • ➖ May create noisy, fragmented specs across many comments
3. Move post-processing logic into a small typed tool (Python)
  • ➕ More maintainable parsing/templating than large bash + jq pipelines
  • ➕ Easier unit testing and future extensions (multi-platform handling)
  • ➖ Adds runtime dependency/packaging decisions
  • ➖ Higher initial implementation cost than shell scripts

Recommendation: The PR’s approach (separate refine harness with read-only sandbox + runner-side post-script) is appropriate for least-privilege and keeps the agent prompt platform-agnostic via injected platform context. Consider converging on a shared result schema across agents later, but it’s reasonable to ship refine with its own schema now. If write-risk becomes a concern, the first simplification would be making proposed_description comment-only rather than patching the issue body/description.

Files changed (14) +1925 / -0

Enhancement (1) +576 / -0
refine.mdIntroduce generic refine agent prompt and output contract +576/-0

Introduce generic refine agent prompt and output contract

• Adds a platform-agnostic refinement agent prompt that always decomposes a work item into implementable children with acceptance criteria, dependencies, confidence scoring, open questions, and a proposed description. Enforces read-only behavior via disallowed tool patterns and mandates JSON-only output.

agents/refine.md

Tests (1) +286 / -0
post-refine-test.shAdd unit-style shell tests for post-refine summary/label logic +286/-0

Add unit-style shell tests for post-refine summary/label logic

• Adds a 29-test bash suite that verifies reply-target selection, plan summary formatting, revision detection, label payload generation, iteration output discovery, and jq extraction behavior. Enables validating core post-refine logic without live APIs.

scripts/post-refine-test.sh

Documentation (5) +226 / -0
README.mdAdd Refine agent to the agent catalog table +1/-0

Add Refine agent to the agent catalog table

• Documents the new Refine agent entry, including trigger label and command. Helps users discover the new pipeline stage.

README.md

refine.mdAdd user-facing Refine agent documentation +79/-0

Add user-facing Refine agent documentation

• Documents refine behavior, pipeline position (Explore → Refine → Critique), revision rounds, control labels, and platform support. Includes guidance for human directives, routing skills, and platform context injection.

docs/refine.md

platform-github.mdAdd GitHub platform context for hierarchy and description rules +47/-0

Add GitHub platform context for hierarchy and description rules

• Documents how refine should model hierarchy on GitHub (labels + sub-issues) and how to format descriptions in markdown. Captures constraints and fallback behavior assumptions for child linking.

scripts/platform-github.md

platform-gitlab.mdAdd GitLab platform context template (planned support) +47/-0

Add GitLab platform context template (planned support)

• Provides a GitLab hierarchy/format guidance template for the agent, noting creation is not yet fully wired. Establishes expected epic/issue/task mapping and fallback strategies by tier.

scripts/platform-gitlab.md

platform-jira.mdAdd Jira platform context for typed hierarchy and ADF conversion +52/-0

Add Jira platform context for typed hierarchy and ADF conversion

• Defines Jira hierarchy levels and parent-child constraints, plus guidance on respecting available issue types and routing limitations across projects. Documents markdown-to-ADF conversion expectations and spike/doc task conventions.

scripts/platform-jira.md

Other (7) +837 / -0
config.yamlRegister refine harness in global agent configuration +1/-0

Register refine harness in global agent configuration

• Adds harness/refine.yaml to the configured agent sources so the new refine agent is discoverable/runnable.

config.yaml

refine.envAdd refine sandbox environment variable defaults +6/-0

Add refine sandbox environment variable defaults

• Defines default sandbox paths for issue context, exploration context, critique feedback, routing skill, and platform context used by the agent prompt/scripts.

env/refine.env

refine.yamlAdd refine harness wiring (env, mounts, schema validation loop) +78/-0

Add refine harness wiring (env, mounts, schema validation loop)

• Creates the refine harness config including host file mounts (contexts + human directive), pre/post scripts, schema validation loop, and split runner vs sandbox env configuration. Uses the standard sandbox image and attaches the refine policy.

harness/refine.yaml

refine.yamlAdd read-only sandbox policy for refine agent +71/-0

Add read-only sandbox policy for refine agent

• Defines filesystem and network restrictions for the refine sandbox, allowing read-only access to GitHub and Jira endpoints while permitting model provider access. Reinforces the model where mutations happen on the runner via post-script.

policies/refine.yaml

refine-result.schema.jsonDefine JSON schema for refine agent output +95/-0

Define JSON schema for refine agent output

• Introduces a JSON Schema requiring input metadata, complete status, confidence, target level, children array, and human-readable comment/summary. Validates optional fields like dependencies, assumptions, and proposed_description size limits.

schemas/refine-result.schema.json

post-refine.shImplement refine post-processing: publish plan, update description, label for critique +301/-0

Implement refine post-processing: publish plan, update description, label for critique

• Processes refine agent output by locating the latest iteration result, building a sticky summary comment (including open questions and assumptions), and linking to the full artifact. Optionally updates Jira/GitHub descriptions, attaches refine-result.json to Jira, and adds ready-to-critique (+ revision round) labels.

scripts/post-refine.sh

pre-refine.shImplement refine pre-processing: gather issue/explore/critique context and routing +285/-0

Implement refine pre-processing: gather issue/explore/critique context and routing

• Ensures issue-context.json exists (delegating to pre-explore.sh), locates exploration context via workspace, user ref, Jira attachment, or GHA artifact fallback, and optionally loads critique feedback for revision rounds. Injects routing skill and platform context into the workspace and exports env vars for the harness/agent.

scripts/pre-refine.sh

@qodo-code-review

qodo-code-review Bot commented Jul 9, 2026

Copy link
Copy Markdown

Code Review by Qodo

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

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

Grey Divider


Action required

1. Output filename mismatch ✓ Resolved 🐞 Bug ≡ Correctness
Description
Schema validation and post-processing are misconfigured: harness/refine.yaml sets
FULLSEND_OUTPUT_FILE=refine-result.json (so validation expects output/refine-result.json), but
agents/refine.md and scripts/post-refine.sh are hardcoded to write/read agent-result.json, which can
cause validation failure and post-refine to not find the result file.
Code

harness/refine.yaml[R52-66]

+env:
+  runner:
+    ISSUE_KEY: "${ISSUE_KEY}"
+    ISSUE_SOURCE: "${ISSUE_SOURCE}"
+    REPO_FULL_NAME: "${REPO_FULL_NAME}"
+    EXPLORE_RUN_ID: "${EXPLORE_RUN_ID}"
+    EXPLORE_CONTEXT_REF: "${EXPLORE_CONTEXT_REF}"
+    CRITIQUE_RUN_ID: "${CRITIQUE_RUN_ID}"
+    REVIEW_ROUND: "${REVIEW_ROUND}"
+    MAX_REVIEW_ROUNDS: "${MAX_REVIEW_ROUNDS}"
+    AUTO_CREATE: "${AUTO_CREATE}"
+    GITHUB_ISSUE_NUMBER: "${GITHUB_ISSUE_NUMBER}"
+    HUMAN_DIRECTIVE: "${HUMAN_DIRECTIVE}"
+    FULLSEND_OUTPUT_FILE: refine-result.json
+  sandbox:
Relevance

⭐⭐⭐ High

Team has merged output/validation contract fixes; filename mismatch likely treated as breaking
validation loop.

PR-#24
PR-#9

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The validator derives the expected output path from FULLSEND_OUTPUT_FILE; refine harness sets it to
refine-result.json, while both the agent instructions and post-script use agent-result.json,
creating an internally inconsistent contract.

harness/refine.yaml[52-66]
scripts/validate-output-schema.sh[20-40]
agents/refine.md[455-463]
scripts/post-refine.sh[41-50]

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 refine harness config expects `refine-result.json`, but the agent prompt and post-script are keyed to `agent-result.json`, and the schema validator uses `FULLSEND_OUTPUT_FILE` to select the expected output file. This inconsistency can break the validation loop and/or cause `post-refine.sh` to fail finding the result.

### Issue Context
- Validator expects `output/${FULLSEND_OUTPUT_FILE}` when set.
- Refine harness sets `FULLSEND_OUTPUT_FILE: refine-result.json`.
- Refine agent instructions and post-script both reference `agent-result.json`.

### Fix Focus Areas
- harness/refine.yaml[52-66]
- scripts/validate-output-schema.sh[20-40]
- agents/refine.md[455-463]
- scripts/post-refine.sh[41-50]
- scripts/post-refine-test.sh[168-201]

### Suggested fix (pick one consistent approach)
**Option A (match most agents):**
- Remove `FULLSEND_OUTPUT_FILE` from `harness/refine.yaml` (or set it to `agent-result.json`).
- Keep `agents/refine.md` and `post-refine.sh` using `agent-result.json`.

**Option B (custom filename like code/fix agents):**
- Update `agents/refine.md` to instruct writing `$FULLSEND_OUTPUT_DIR/refine-result.json`.
- Update `scripts/post-refine.sh` (and `scripts/post-refine-test.sh`) to search for `refine-result.json` instead of `agent-result.json`.

Either way: ensure validator, agent instruction, and post-script all agree on the same filename.

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


2. Missing shared scripts ✓ Resolved 🐞 Bug ☼ Reliability
Description
The refine pipeline will fail at runtime because post-refine.sh sources comment-helpers.sh and calls
markdown-to-adf.py, and pre-refine.sh exits if pre-explore.sh is missing; none of these files are
present in the repository snapshot, so context prep and/or post-processing will abort.
Code

scripts/post-refine.sh[R33-40]

+# NOTE: This script uses comment-helpers.sh and markdown-to-adf.py from
+# the explore agent. These must be present in the scripts/ directory.
+
+set -euo pipefail
+
+SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
+source "${SCRIPT_DIR}/comment-helpers.sh"
+
Relevance

⭐⭐⭐ High

Missing companion scripts have caused merged fixes (fallbacks/inlining) before; runtime aborts are
addressed.

PR-#41
PR-#35

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
post-refine.sh directly sources a non-existent helper script and invokes a non-existent converter
script; pre-refine.sh explicitly exits when pre-explore.sh is not found. In the current repository
snapshot, there are no matching files for these referenced paths, so the refine run will abort.

scripts/post-refine.sh[33-40]
scripts/post-refine.sh[203-214]
scripts/pre-refine.sh[37-45]

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

### Issue description
Refine’s pre/post scripts depend on `scripts/comment-helpers.sh`, `scripts/pre-explore.sh`, and `scripts/markdown-to-adf.py`, but those files are not present in this repo snapshot, causing `source`/execution failures.

### Issue Context
- `post-refine.sh` uses `source "${SCRIPT_DIR}/comment-helpers.sh"` and later runs `python3 "${SCRIPT_DIR}/markdown-to-adf.py"`.
- `pre-refine.sh` hard-fails if `pre-explore.sh` is not found when issue context is missing.

### Fix Focus Areas
- scripts/post-refine.sh[33-40]
- scripts/post-refine.sh[203-214]
- scripts/pre-refine.sh[37-45]

### Suggested fix
1. Add/commit the required shared scripts into `scripts/` (or adjust paths to where they actually live in this repo).
2. If you intentionally want a soft dependency (because another PR introduces them), then:
  - Guard `source` with an existence check and fail with a clear error that references the required PR/commit, or
  - Vendor minimal required functions directly in `post-refine.sh` / `pre-refine.sh`.
3. Ensure the harness image contains any runtime deps those scripts require.

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


3. ISSUE_KEY unsanitized in notice ✓ Resolved 📜 Skill insight ⛨ Security
Description
GitHub Actions workflow commands (::notice::, ::error::, ::warning::) are emitted with
interpolated variables that are not individually sanitized, enabling workflow-command injection via
::, encoded newlines, or control characters. This can corrupt logs and potentially alter workflow
behavior when attacker-controlled values reach these variables.
Code

scripts/pre-refine.sh[35]

+echo "::notice::Pre-refine: preparing context (source=${ISSUE_SOURCE}, key=${ISSUE_KEY})"
Relevance

⭐⭐ Medium

No historical evidence of enforcing workflow-command injection sanitization for ::notice:: variable
interpolation.

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The checklist requires sanitizing every variable interpolated into GitHub Actions workflow commands.
The added scripts emit ::notice::/::error::/::warning:: lines that interpolate variables
(e.g., ISSUE_SOURCE, ISSUE_KEY, CONTEXT_REPO, CONTEXT_PATH) with no sanitization before
printing.

scripts/pre-refine.sh[35-35]
scripts/pre-refine.sh[62-62]
Skill: pr-review
Skill: code-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
GitHub Actions workflow commands are emitted with unsanitized interpolated variables (e.g., `ISSUE_SOURCE`, `ISSUE_KEY`, `CONTEXT_REPO`, `CONTEXT_PATH`). Per compliance, every interpolated value in a workflow command must be individually sanitized (including `::`, `%`, newlines, and control chars).

## Issue Context
The scripts log using `echo "::notice::..."` / `echo "::error::..."` / `echo "::warning::..."`. These are parsed by GitHub Actions as workflow commands.

## Fix Focus Areas
- scripts/pre-refine.sh[35-35]
- scripts/pre-refine.sh[62-62]
- scripts/post-refine.sh[99-99]
- scripts/post-refine.sh[270-273]
- scripts/post-refine.sh[284-285]
- scripts/post-refine.sh[298-299]

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


View more (3)
4. Protected paths modified in PR ✗ Dismissed 📜 Skill insight § Compliance
Description
This PR modifies protected governance/infrastructure paths (agents/, harness/, policies/,
scripts/), so it must not be auto-approved and requires explicit human review. Without enforcing
this, high-impact pipeline/sandbox behavior could be changed without governance oversight.
Code

harness/refine.yaml[R1-7]

+---
+agent: agents/refine.md
+doc: docs/refine.md
+model: opus
+image: ghcr.io/fullsend-ai/fullsend-sandbox:latest
+policy: policies/refine.yaml
+
Relevance

⭐⭐ Medium

Protected-path human-review concern previously raised but left undetermined; no clear accept/reject
evidence.

PR-#59
PR-#27

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The diff adds/changes files under protected directories (agent prompt, harness config, sandbox
policy, and runner scripts). The rule requires raising a protected-path finding to ensure these
changes receive human governance review.

harness/refine.yaml[1-7]
policies/refine.yaml[1-13]
scripts/pre-refine.sh[1-36]
scripts/post-refine.sh[1-40]
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
Protected governance/infrastructure paths were modified; this PR must be gated for human review and cannot be auto-approved.

## Issue Context
The compliance rule requires a finding whenever protected paths change.

## Fix Focus Areas
- harness/refine.yaml[1-78]
- policies/refine.yaml[1-71]
- scripts/pre-refine.sh[1-285]
- scripts/post-refine.sh[1-301]
- agents/refine.md[1-576]

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


5. No linked authorizing issue ✗ Dismissed 📜 Skill insight § Compliance
Description
This is a non-trivial feature addition but the PR does not include an explicit linked issue
authorizing the work. Lack of authorization linkage increases governance and audit risk for
substantial changes.
Code

agents/refine.md[R1-16]

+---
+name: refine
+description: >-
+  Best-effort feature refinement agent. Reads a work item and exploration
+  context, assesses confidence, and ALWAYS decomposes into implementable
+  child work items. Flags uncertainties honestly but never halts — the
+  critique agent downstream decides if human input is needed.
+tools: Bash(gh,jq,python3,find,ls,cat,head,grep,wc,tree)
+model: opus
+disallowedTools: >-
+  Bash(git push *), Bash(git push),
+  Bash(gh issue create *), Bash(gh issue edit *), Bash(gh issue comment *),
+  Bash(gh pr create *), Bash(gh pr edit *), Bash(gh pr merge *),
+  Bash(gh api *POST*), Bash(gh api *DELETE*), Bash(gh api *PATCH*), Bash(gh api *PUT*)
+---
+
Relevance

⭐⭐ Medium

Only prior “link authorizing issue/justification” suggestions were undetermined; no clear
enforcement precedent.

PR-#29
PR-#25

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The checklist requires non-trivial PRs to link to an authorizing issue. This PR introduces a new
agent (new harness/policy/scripts/schema/docs), which is substantial work, but no explicit
authorizing issue link is provided in the PR metadata.

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
Non-trivial changes must be explicitly authorized via a linked issue.

## Issue Context
Add a concrete issue link (e.g., `Fixes #123` or a full URL) in the PR description so reviewers/auditors can trace authorization.

## Fix Focus Areas
- agents/refine.md[1-16]

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


6. Label update failures ignored ✓ Resolved 📜 Skill insight ☼ Reliability
Description
The script suppresses failures when adding critique-signaling labels (e.g.,
ready-to-critique/refine-revision-round-N) to GitHub and Jira, then logs success
unconditionally. This can silently break the refine→critique handoff and leave issues unlabeled or
in the wrong state while the logs claim labels were added.
Code

scripts/post-refine.sh[R276-285]

+# --- Add label to signal critique stage ---
+if [[ -n "${GITHUB_ISSUE_NUMBER:-}" && "${GITHUB_ISSUE_NUMBER}" != "N/A" ]]; then
+  LABEL_PAYLOAD='["ready-to-critique"]'
+  if [[ "$REVIEW_ROUND" -gt 1 ]]; then
+    LABEL_PAYLOAD="[\"ready-to-critique\",\"refine-revision-round-${REVIEW_ROUND}\"]"
+  fi
+  gh api "repos/${REPO_FULL_NAME}/issues/${GITHUB_ISSUE_NUMBER}/labels" \
+    --input - <<< "{\"labels\":${LABEL_PAYLOAD}}" --silent 2>/dev/null || true
+  echo "::notice::Added label 'ready-to-critique' to GitHub issue #${GITHUB_ISSUE_NUMBER}"
+fi
Relevance

⭐⭐ Medium

Reliability fixes common, but no direct precedent on masking label-add failures with “|| true” then
success notice.

PR-#41
PR-#10

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
Compliance requires explicit handling of guard/contract failure paths, and here the label-add
operation is the mechanism that signals critique readiness. In scripts/post-refine.sh, the GitHub
(gh api ... || true) and Jira (curl ... || true) label update commands are explicitly made
non-fatal via || true, but are immediately followed by unconditional success notices (e.g.,
::notice::Added label ...), which hides failures and makes the pipeline appear healthy even when
the labels were not applied.

scripts/post-refine.sh[276-285]
scripts/post-refine.sh[287-299]
scripts/post-refine.sh[276-299]
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 critique-signaling label update is a guard/contract mechanism; failures must not be silently ignored, and success notices should only be printed when the label mutation actually succeeds.

## Issue Context
`scripts/post-refine.sh` applies labels that drive the refine→critique handoff (e.g., `ready-to-critique`/`refine-revision-round-N`) to both GitHub and Jira. Those label mutation commands are currently written as non-fatal (`gh api ... || true` and `curl ... || true`), yet the script still prints success notices unconditionally, which can leave issues unlabeled while logs claim labels were added and downstream stages may never trigger.

## Fix Focus Areas
- scripts/post-refine.sh[276-285]
- scripts/post-refine.sh[287-299]

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



Remediation recommended

7. Undocumented issue body edits ✓ Resolved 🐞 Bug ⚙ Maintainability
Description
docs/refine.md describes the post-script as posting a summary comment, attaching the plan, and
adding a ready-to-critique label, but post-refine.sh also overwrites the Jira description / GitHub
issue body when proposed_description is present, which is a user-visible behavior not reflected in
the docs.
Code

scripts/post-refine.sh[R203-235]

+# Update issue description if proposed_description is present
+PROPOSED_DESC=$(jq -r '.proposed_description // ""' "${RESULT_FILE}")
+if [[ -n "$PROPOSED_DESC" && "$PROPOSED_DESC" != "null" ]]; then
+  if [[ "${ISSUE_SOURCE:-}" == "jira" && -n "${JIRA_HOST:-}" && -n "${JIRA_EMAIL:-}" && -n "${JIRA_API_TOKEN:-}" ]]; then
+    AUTH_DESC=$(printf '%s:%s' "$JIRA_EMAIL" "$JIRA_API_TOKEN" | base64 -w0)
+    ADF_FLAGS=""
+    if [[ "$JIRA_HOST" != *"atlassian.net"* ]]; then
+      ADF_FLAGS="--no-expand"
+    fi
+    DESC_ADF=$(printf '%s' "$PROPOSED_DESC" | python3 "${SCRIPT_DIR}/markdown-to-adf.py" $ADF_FLAGS | jq '.body')
+
+    DESC_HTTP=$(curl -sS -o /dev/null -w "%{http_code}" \
+      -X PUT \
+      -H "Authorization: Basic $AUTH_DESC" \
+      -H "Content-Type: application/json" \
+      -d "$(jq -nc --argjson desc "$DESC_ADF" '{fields: {description: $desc}}')" \
+      "https://${JIRA_HOST}/rest/api/3/issue/${ISSUE_KEY}")
+
+    if [[ "$DESC_HTTP" =~ ^2 ]]; then
+      echo "::notice::Updated ${ISSUE_KEY} description (previous version in History tab)"
+    else
+      echo "::warning::Failed to update ${ISSUE_KEY} description (HTTP ${DESC_HTTP}) — falling back to comment"
+      new_comment "## Proposed Feature Description
+
+${PROPOSED_DESC}"
+    fi
+
+  elif $USE_GITHUB; then
+    gh api "repos/${REPO_FULL_NAME}/issues/${GITHUB_ISSUE_NUMBER}" \
+      -X PATCH --field "body=${PROPOSED_DESC}" --silent 2>/dev/null \
+      && echo "::notice::Updated GitHub issue #${GITHUB_ISSUE_NUMBER} body" \
+      || echo "::warning::Failed to update GitHub issue body"
+  fi
Relevance

⭐⭐⭐ High

Doc/script behavior alignment changes have been accepted previously; docs accuracy is enforced.

PR-#15

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The documentation states only comment/attachment/label behavior, while the post-script contains
explicit Jira/GitHub API calls to update the description/body when proposed_description is present.

docs/refine.md[9-12]
scripts/post-refine.sh[203-235]

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 refine pipeline mutates the issue description/body when `proposed_description` is present, but user-facing docs currently state the post-script only comments, attaches the plan, and labels. This mismatch can surprise users and complicates operational expectations.

### Issue Context
- Jira: `PUT /rest/api/3/issue/${ISSUE_KEY}` updates description.
- GitHub: `PATCH repos/.../issues/...` updates issue body.

### Fix Focus Areas
- scripts/post-refine.sh[203-235]
- docs/refine.md[9-12]

### Suggested fix
Choose one:
1. **Document it clearly** in `docs/refine.md` (and any other user docs) as an explicit behavior and describe when it happens.
2. **Gate it behind an env flag** (e.g., `REFINE_UPDATE_DESCRIPTION=true`) defaulting to false, to avoid unexpected overwrites.
3. **Change behavior** to post the proposed description as a comment/attachment instead of overwriting the source-of-truth description.

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


Grey Divider

Qodo Logo

Comment thread scripts/pre-refine.sh Outdated
Comment thread scripts/post-refine.sh
Comment thread harness/refine.yaml
Comment thread agents/refine.md
Comment thread scripts/post-refine.sh
Comment thread harness/refine.yaml
Comment thread scripts/post-refine.sh
@fullsend-ai-review

fullsend-ai-review Bot commented Jul 9, 2026

Copy link
Copy Markdown

Review — Refine Agent (Re-review)

PR: #86 · Author: ascerra · Base: main · Status: open (not draft)

Changes since prior review

The fix commit (a47c0563) addressed 5 findings from the prior review:

Finding Status
Schema additionalProperties: false, $id, draft 2020-12 ✅ Fixed
fullsend-check-output call in agent prompt ✅ Fixed
ready-to-refine label removal (GitHub + Jira) ✅ Fixed
Makefile test registration ✅ Fixed
Dependencies items missing required fields ✅ Fixed

6 findings from the prior review remain unaddressed.


Findings

🟡 Medium

[secrets-handling] scripts/post-refine.shPUSH_TOKEN and Jira auth tokens not masked (persists from prior review)

PUSH_TOKEN is passed via forge.github.env.runner (harness/refine.yaml) but post-refine.sh never calls echo "::add-mask::${PUSH_TOKEN}". Every other post-script that receives PUSH_TOKEN masks it immediately (post-fix.sh:83, post-code.sh:103). Additionally, Jira basic-auth tokens are computed three separate times (AUTH_DESC, AUTH_ATTACH, AUTH_LABEL) via base64 -w0 but never masked. GHA's built-in secret masking only covers the literal secret values registered in the repository, not derived values produced by runtime computation.

Remediation: Mask at the top of the script: echo "::add-mask::${PUSH_TOKEN}". Compute Jira auth once and mask: JIRA_AUTH=$(printf '%s:%s' "$JIRA_EMAIL" "$JIRA_API_TOKEN" | base64 -w0); echo "::add-mask::${JIRA_AUTH}".


[missing-dependency] scripts/post-refine.sh, scripts/pre-refine.sh — Hard dependencies on files from PR #11 (persists, severity lowered from high to medium)

post-refine.sh sources comment-helpers.sh (line 4) and pre-refine.sh calls pre-explore.sh (line 12). Both files come from PR #11 (explore agent). The scripts have explicit existence checks with clear error messages — immediate exit with "ERROR: comment-helpers.sh not found (requires PR #11 explore agent)". The PR body documents the dependency. Lowered from prior severity of high because: (a) error handling is robust with actionable messages, (b) the dependency is explicitly documented, (c) the concern is inherently unresolvable within this PR's code — it is a merge-ordering coordination concern.

Remediation: Coordinate merge ordering so PR #11 merges first.


🔵 Low

[gha-command-injection] scripts/post-refine.sh — Inconsistent sanitize_gha application (persists from prior review)

sanitize_gha is correctly applied to GITHUB_ISSUE_NUMBER and ISSUE_KEY/REVIEW_ROUND for success-path ::notice:: commands, but the raw unsanitized values are used in ::warning:: commands on error paths (lines ~305 and ~329). While these values are not directly user-controlled in most flows, the inconsistency undermines the defense-in-depth purpose of the sanitization function.

Remediation: Compute SAFE_* variables before the if/else block so both branches use sanitized values.


[gha-command-injection] scripts/pre-refine.sh — Raw ISSUE_SOURCE in warning output (persists from prior review)

ISSUE_SOURCE is sanitized as SAFE_ISSUE_SOURCE at line 37, but the raw ISSUE_SOURCE is used in the ::warning:: output at line 282: "No platform context template found for source=${ISSUE_SOURCE}". One-character fix — safe variable is already computed and in scope.

Remediation: Use SAFE_ISSUE_SOURCE in the warning output.


[test-coverage] scripts/post-refine-test.sh — Test gaps (persists from prior review)

The 29 tests cover core decision logic well but miss: (a) GitHub fallback routing where ISSUE_SOURCE=github and GITHUB_ISSUE_NUMBER is empty, (b) proposed-description update flow, (c) Jira attachment handling, (d) data-sources footer construction.

Remediation: Add tests for the GitHub fallback routing and data-sources footer construction at minimum.


[logic-inconsistency] scripts/post-refine.sh — Inconsistent GitHub detection conditions (persists from prior review)

The script uses three different patterns to detect GitHub mode: (1) $USE_GITHUB for remove_label calls, (2) -n GITHUB_ISSUE_NUMBER && != N/A for label addition, (3) ISSUE_SOURCE == github elif for initial routing. While functionally equivalent at runtime (the elif sets GITHUB_ISSUE_NUMBER before either pattern is reached), the inconsistency is fragile.

Remediation: Use $USE_GITHUB consistently for all GitHub operations.


Notes

  • Architecture: File layout follows established agent patterns well. Image choice (fullsend-sandbox:latest) is correct for a read-only agent, matching prioritize, retro, scribe, and triage agents.
  • Schema: All additionalProperties: false and required fields are now correctly set. The $schema and $id fields match repo conventions. Minor style note: title uses "Refinement Result" vs the convention of "{Name} Agent Result" used by all other schemas.
  • Security posture: The sandbox policy correctly enforces read-only API access. The disallowedTools blocks all gh api calls (defense-in-depth alongside network policy). GH_TOKEN is properly excluded from env.sandbox.
  • Cross-repo contracts: No breaking changes — all modifications to existing files are purely additive.
  • PR title: feat: add generic refine agent uses Conventional Commits format per AGENTS.md.
Previous run

Review — Refine Agent (Re-review)

PR: #86 · Author: ascerra · Base: main · Status: open (not draft)

The fix commit (99cb712) addressed 5 findings. 7 persisted, 5 new were identified.

Severity Count Categories
High 2 schema-correctness, missing-dependency
Medium 5 missing-validation, logic-error, test-infrastructure, secrets-handling
Low 5 gha-command-injection (2), schema-correctness, test-coverage, logic-inconsistency
Initial review

Initial review found 11 findings: 2 high (schema missing additionalProperties, missing dependencies on PR #11), 6 medium (label removal, Makefile, GHA injection, secrets masking, stale icon, disallowedTools bypass), 2 low (dead code, test coverage).


Labels: PR adds a new agent with feature scope

Previous run

Review — Refine Agent (Re-review)

PR: #86 · Author: ascerra · Base: main · Status: open (not draft)

Changes since prior review

The fix commit (99cb712) addressed 4 findings from the prior review:

Finding Status
GHA command injection (HUMAN_DIRECTIVE unsanitized) ✅ Fixed — sanitize_gha added to both scripts
disallowedTools bypass (verb matching) ✅ Fixed — now blocks Bash(gh api *) entirely
Missing icon reference (docs/refine.md) ✅ Fixed — removed <img> tag
Dead code (FULLSEND_OUTPUT_FILE in harness) ✅ Fixed — removed from harness/refine.yaml
GH_TOKEN in sandbox env (security) ✅ Fixed — removed from env.sandbox

7 findings from the prior review remain unaddressed. 5 new findings were identified.


Findings

🔴 High

[schema-correctness] schemas/refine-result.schema.json — Missing additionalProperties: false and wrong schema draft (persists from prior review + new)

Two related issues: (1) The schema omits additionalProperties: false at every object level (root, input, confidence, children items, dependencies items, open_questions items). Every other schema in the repo (code-result, fix-result, triage-result, review-result, retro-result, scribe-result, prioritize-result) sets it. Without it, the validation loop silently accepts output with misspelled or extraneous fields. (2) The schema declares "$schema": "http://json-schema.org/draft-07/schema#" while all 7 other schemas use "$schema": "https://json-schema.org/draft/2020-12/schema". It also lacks the "$id" field that every other schema includes. The validation script (validate-output-schema.sh) auto-detects the draft version, meaning the refine schema would be validated with different semantics.

Remediation: Add "additionalProperties": false to every object definition. Change $schema to "https://json-schema.org/draft/2020-12/schema". Add "$id": "refine-result.schema.json".


[missing-dependency] scripts/post-refine.sh, scripts/pre-refine.sh — Hard dependencies on files from PR #11 (persists, improved)

post-refine.sh sources comment-helpers.sh (line 4) and pre-refine.sh calls pre-explore.sh (line 12). Both files come from PR #11 (explore agent). The fix commit improved this by adding explicit existence checks with clear error messages — the script now fails immediately with "ERROR: comment-helpers.sh not found (requires PR #11 explore agent)" rather than failing cryptically. However, these remain hard dependencies with no fallback: the refine agent cannot function at all if this PR merges before PR #11.

Remediation: Coordinate merge ordering so PR #11 merges first. Document the dependency in the PR description (already partially done).


🟡 Medium

[missing-validation] agents/refine.md — Agent prompt missing fullsend-check-output call (new)

Every other agent prompt in the repo (triage.md, review.md, code.md, fix.md, retro.md, prioritize.md) includes a fullsend-check-output "$FULLSEND_OUTPUT_DIR/agent-result.json" call after writing the result JSON. The refine agent's Phase 6 instructs writing to $FULLSEND_OUTPUT_DIR/agent-result.json but omits this validation step. This harness-provided binary performs inline pre-validation before the validation_loop runs.

Remediation: Add fullsend-check-output "$FULLSEND_OUTPUT_DIR/agent-result.json" after the JSON write instruction in Phase 6.


[logic-error] scripts/post-refine.shready-to-refine trigger label never removed after completion (persists from prior review)

The script removes refine-needs-input and human-refinement labels but never removes ready-to-refine. Per docs/refine.md, this is the trigger label for the refine pipeline. If it persists after completion, any label-based dispatch could re-trigger the pipeline. The Jira path also only adds ready-to-critique without removing ready-to-refine.

Remediation: Add remove_label "${REPO_FULL_NAME}" "$GITHUB_ISSUE_NUMBER" "ready-to-refine" in the GitHub path. Add {"remove":"ready-to-refine"} to the Jira label operations.


[test-infrastructure] Makefilepost-refine-test.sh not registered in test target (persists from prior review)

The script-test Makefile target lists every other agent's test script (post-triage-test.sh, post-prioritize-test.sh, post-code-test.sh, post-review-test.sh, post-fix-test.sh, post-retro-test.sh, post-scribe-test.sh, validate-output-schema-test.sh) but does not include post-refine-test.sh. The 29 tests will not run in CI.

Remediation: Add $(call run-timed,bash scripts/post-refine-test.sh) to the script-test target.


[secrets-handling] scripts/post-refine.shPUSH_TOKEN and Jira auth tokens not masked (persists from prior review)

PUSH_TOKEN is available in the runner env (harness/refine.yaml forge.github.env.runner) but post-refine.sh never calls echo "::add-mask::${PUSH_TOKEN}". Every other post-script that uses PUSH_TOKEN masks it immediately (post-fix.sh:83, post-code.sh:103). Additionally, Jira auth tokens are computed three separate times (AUTH_DESC, AUTH_ATTACH, AUTH_LABEL) via base64 -w0 but never masked.

Remediation: Mask at the top of the script: echo "::add-mask::${PUSH_TOKEN}". Compute Jira auth once and mask: JIRA_AUTH=$(printf '%s:%s' "$JIRA_EMAIL" "$JIRA_API_TOKEN" | base64 -w0); echo "::add-mask::${JIRA_AUTH}".


🔵 Low

[gha-command-injection] scripts/post-refine.sh — Inconsistent sanitize_gha application (new)

The sanitize_gha function is correctly applied to GITHUB_ISSUE_NUMBER and ISSUE_KEY/REVIEW_ROUND for success-path ::notice:: commands, but the raw unsanitized values are used in ::warning:: commands on error paths. For example, ISSUE_KEY appears unsanitized in ::warning:: on lines where Jira API calls fail, and GITHUB_ISSUE_NUMBER appears unsanitized in the label-add error path. While these values are not directly user-controlled, the inconsistency undermines the purpose of having the sanitization function.

Remediation: Sanitize ISSUE_KEY and GITHUB_ISSUE_NUMBER once at the top of the script (following pre-refine.sh's pattern with SAFE_ISSUE_SOURCE/SAFE_ISSUE_KEY) and use the safe versions everywhere.


[gha-command-injection] scripts/pre-refine.sh — Raw ISSUE_SOURCE in warning output (new)

ISSUE_SOURCE is sanitized as SAFE_ISSUE_SOURCE early in the script, but the raw ISSUE_SOURCE is still used in the ::warning:: output: "No platform context template found for source=${ISSUE_SOURCE}".

Remediation: Use SAFE_ISSUE_SOURCE in the warning output.


[schema-correctness] schemas/refine-result.schema.jsondependencies items missing required fields (new)

The children[].dependencies[] items schema defines properties type, target, and description but has no required field. The agent prompt's example shows all three fields, and the open_questions items correctly specify required: ["dimension", "question", "impact"], showing the author intended to enforce required fields.

Remediation: Add "required": ["type", "target"] to the dependencies items schema.


[test-coverage] scripts/post-refine-test.sh — Test gaps (persists from prior review)

The 29 tests cover core decision logic but miss: (a) GitHub fallback routing where ISSUE_SOURCE=github and GITHUB_ISSUE_NUMBER is empty, (b) proposed-description update flow, (c) Jira attachment handling, (d) data-sources footer construction.

Remediation: Add tests for the GitHub fallback routing and data-sources footer construction at minimum.


[logic-inconsistency] scripts/post-refine.sh — Inconsistent GitHub detection conditions (new)

The script uses three different patterns to detect GitHub mode: (1) $USE_GITHUB for remove_label calls, (2) -n GITHUB_ISSUE_NUMBER && != N/A for label addition, (3) ISSUE_SOURCE == github elif for initial routing. While the current logic produces correct results because the earlier elif assigns GITHUB_ISSUE_NUMBER="${ISSUE_KEY}", the inconsistent patterns are fragile.

Remediation: Use $USE_GITHUB consistently for all GitHub operations.


Notes

  • Architecture: File layout follows established agent patterns well.
  • Security improvements: The fix commit correctly hardened the sandbox by removing GH_TOKEN from sandbox env and blocking all gh api calls — good defense-in-depth.
  • PR title: feat: add generic refine agent uses Conventional Commits format. Scope is optional per AGENTS.md.
  • Platform context files (platform-jira.md, platform-github.md, platform-gitlab.md) in scripts/ are an architectural choice appropriate for the refine agent's multi-platform decomposition — these are context documents, not executable scripts.
  • Cross-repo contracts: No breaking changes — all modifications to existing files (README.md, config.yaml) are purely additive.
Previous run (2)

Review — Refine Agent

PR: #86 · Author: ascerra · Base: main · Status: open (not draft)

Summary

This PR adds a well-structured refine agent with comprehensive prompt design, platform-specific context docs, harness configuration, sandbox policy, output schema, pre/post scripts, and a 29-test suite. The overall architecture follows existing patterns closely. However, there are several issues that need resolution before merge.


Findings

🔴 High

[schema-correctness] schemas/refine-result.schema.json — Missing additionalProperties: false

Every other schema in this repository (code-result, fix-result, prioritize-result, retro-result, review-result, scribe-result, triage-result) sets "additionalProperties": false at the top-level object. The refine schema omits it everywhere: the root object, input, confidence, children items, dependencies items, and open_questions items. This defeats the schema's purpose as a validation gate — a result with misspelled or extraneous fields will pass validation silently.

Remediation: Add "additionalProperties": false to all object definitions in the schema, matching the convention of every other schema in the repo.


[missing-dependency] scripts/post-refine.sh — Sources comment-helpers.sh and calls markdown-to-adf.py, neither of which exist on main

Line 4 of the script sources comment-helpers.sh and calls functions from it (init_comment_helpers, sticky_comment, new_comment, remove_label). It also calls python3 markdown-to-adf.py for Jira description conversion. These files are expected from PR #11 (explore agent), which has not merged. If this PR merges first, post-refine.sh will fail immediately on every run.

Remediation: Merge PR #11 first, or coordinate atomic merge. Document the required merge order in the PR description.


[missing-dependency] scripts/pre-refine.sh — Calls pre-explore.sh which does not exist on main

Line 12 calls bash "${SCRIPT_DIR}/pre-explore.sh" to fetch issue context when issue-context.json is not pre-populated. This script also comes from PR #11.

Remediation: Same as above — coordinate merge ordering with PR #11.


🟡 Medium

[logic-error] scripts/post-refine.shready-to-refine trigger label never removed after completion

The script removes refine-needs-input and human-refinement labels but never removes ready-to-refine. Per docs/refine.md, ready-to-refine is the trigger label for this pipeline. If it persists after completion, the pipeline could re-trigger on the next issue event, creating duplicate runs. The Jira path also only adds ready-to-critique without removing ready-to-refine.

Remediation: Add remove_label "${REPO_FULL_NAME}" "$GITHUB_ISSUE_NUMBER" "ready-to-refine" in the GitHub path. Add {"remove":"ready-to-refine"} to the Jira label operations.


[test-infrastructure] Makefilepost-refine-test.sh not registered in test target

The script-test Makefile target lists every other agent's test script but does not include post-refine-test.sh. The 29 tests will not run in CI.

Remediation: Add $(call run-timed,bash scripts/post-refine-test.sh) to the script-test target.


[gha-command-injection] scripts/pre-refine.shHUMAN_DIRECTIVE interpolated unsanitized in workflow command

Line 278 emits echo "::notice::Human directive received: ${HUMAN_DIRECTIVE:0:100}...". HUMAN_DIRECTIVE is directly user-controlled (from an issue comment like /fs-refine focus on X). An attacker could craft a directive containing ::error:: or other GHA workflow command sequences to inject annotations. Other scripts in the repo (e.g., post-fix.sh) sanitize user-controlled values before interpolation into workflow commands.

Remediation: Sanitize HUMAN_DIRECTIVE before interpolation: SAFE_DIRECTIVE="${HUMAN_DIRECTIVE//::/ : }" and use the sanitized version in the ::notice:: emission.


[secrets-handling] scripts/post-refine.sh — PUSH_TOKEN and Jira auth tokens not masked

PUSH_TOKEN is passed via forge.github.env.runner but post-refine.sh never calls echo "::add-mask::${PUSH_TOKEN}". Existing scripts (post-fix.sh, post-code.sh) mask PUSH_TOKEN immediately. Additionally, Jira basic-auth tokens are computed three separate times (AUTH_DESC, AUTH_ATTACH, AUTH_LABEL) via base64 -w0 but never masked. The base64 form is a different string than the raw secret and won't be auto-masked by GHA.

Remediation: Compute tokens once at the top of the script and mask immediately: echo "::add-mask::${PUSH_TOKEN}" and JIRA_AUTH=$(printf '%s:%s' "$JIRA_EMAIL" "$JIRA_API_TOKEN" | base64 -w0); echo "::add-mask::${JIRA_AUTH}".


[docs-staleness] docs/refine.md — References non-existent icon file

Line 3 references icons/refine.png via <img src="icons/refine.png">, but docs/icons/refine.png does not exist. All other agent docs reference icons that are present in the repo (coder.png, prioritize.png, retro.png, review.png, triage.png).

Remediation: Either add docs/icons/refine.png to this PR or remove the icon reference from docs/refine.md.


[disallowedTools-bypass] agents/refine.mdgh api write operations can bypass verb matching via implicit flags

The disallowedTools blocks Bash(gh api *POST*), Bash(gh api *PATCH*), etc. by matching the literal verb string. However, gh api defaults to POST when -f or -F or --input flags are used, without the word "POST" appearing in the command. For example, gh api repos/x/issues/1 -f body=test sends a POST request without matching *POST*. This creates a bypass for the prompt-level restriction. The network policy's access: read-only on api.github.com may provide a second enforcement layer depending on how the sandbox runtime implements it.

Remediation: Consider blocking Bash(gh api *) entirely (matching the fix agent's approach, which blocks all gh api calls) since the agent's data is pre-fetched by the pre-script. Alternatively, ensure the sandbox runtime enforces HTTP method restrictions at the network policy level.


🔵 Low

[dead-code] harness/refine.yamlFULLSEND_OUTPUT_FILE: refine-result.json is unused

The env.runner block sets FULLSEND_OUTPUT_FILE: refine-result.json, but post-refine.sh hardcodes agent-result.json in its discovery loop. The agent prompt also instructs writing to $FULLSEND_OUTPUT_DIR/agent-result.json. Other agents (fix, code) use FULLSEND_OUTPUT_FILE consistently between harness and post-script.

Remediation: Either remove the FULLSEND_OUTPUT_FILE env var or update the post-script and agent prompt to use it consistently.


[test-coverage] scripts/post-refine-test.sh — Notable test gaps

The 29 tests cover core decision logic well but miss: (a) the ISSUE_SOURCE=github fallback routing where GITHUB_ISSUE_NUMBER is empty, (b) the proposed-description update flow, (c) the Jira attachment handling, (d) the data-sources footer construction. These are non-trivial code paths with branching logic.

Remediation: Add tests for the routing fallback case and the data-sources footer construction at minimum.


Notes

  • Architecture: The file layout, naming conventions, and overall structure follow established patterns well (agents/, harness/, policies/, schemas/, scripts/, env/, docs/).
  • PR title: feat: add generic refine agent correctly uses Conventional Commits format per AGENTS.md.
  • No Konflux references: Verified — the code is generic with no platform-specific references.
  • Platform context docs (platform-jira.md, platform-github.md, platform-gitlab.md) are well-structured and provide clear hierarchy guidance.
  • Agent prompt: The 576-line prompt is thorough with clear behavioral constraints, phased process, and detailed output format specification.
  • Cross-references to critique/explore agents in docs/refine.md are acceptable since the PR notes they will resolve once sibling PRs merge.

fullsend-ai-review[bot]

This comment was marked as outdated.

- Block all gh api calls in sandbox (match fix agent pattern)
- Remove FULLSEND_OUTPUT_FILE override and GH_TOKEN from sandbox
- Guard comment-helpers.sh dependency with clear PR #11 message
- Sanitize GHA workflow command output to prevent injection
- Check label mutation success before logging success notices
- Document proposed_description body updates in user docs
- Remove missing icon reference from docs

Signed-off-by: Adam Scerra <ascerra@redhat.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
@fullsend-ai-review

fullsend-ai-review Bot commented Jul 9, 2026

Copy link
Copy Markdown

🤖 Finished Review · ✅ Success · Started 6:12 PM UTC · Completed 6:23 PM UTC
Commit: 99cb712 · View workflow run →

fullsend-ai-review[bot]

This comment was marked as outdated.

- Fix SC2034/SC2129 shellcheck failures
- Upgrade schema to draft/2020-12 with additionalProperties: false
- Add fullsend-check-output after Phase 6
- Remove ready-to-refine trigger label after completion (GitHub + Jira)
- Register post-refine-test.sh in Makefile script-test target

Signed-off-by: Adam Scerra <ascerra@redhat.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
@fullsend-ai-review

fullsend-ai-review Bot commented Jul 9, 2026

Copy link
Copy Markdown

🤖 Finished Review · ✅ Success · Started 7:57 PM UTC · Completed 8:10 PM UTC
Commit: a47c056 · View workflow run →

@fullsend-ai-review fullsend-ai-review Bot dismissed stale reviews from themself July 9, 2026 20:10

Superseded by updated review

@fullsend-ai-review fullsend-ai-review Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

See the review comment for full details.

Comment thread scripts/post-refine.sh
echo "::notice::Added label 'ready-to-critique' to GitHub issue #${SAFE_GH_NUM}"
else
echo "::warning::Failed to add critique labels to GitHub issue #${GITHUB_ISSUE_NUMBER}"
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.

[low] gha-command-injection

sanitize_gha is applied on success-path ::notice:: commands but raw unsanitized GITHUB_ISSUE_NUMBER, ISSUE_KEY, and REVIEW_ROUND are used in ::warning:: commands on error paths.

Suggested fix: Compute SAFE_* variables before the if/else block so both branches use sanitized values.

Comment thread scripts/pre-refine.sh
echo "PLATFORM_CONTEXT=$WORKSPACE/platform-context.md" >> "${GITHUB_ENV:-/dev/null}"
echo "::notice::Platform context loaded: ${ISSUE_SOURCE}"
else
echo "::warning::No platform context template found for source=${ISSUE_SOURCE}"

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

[low] gha-command-injection

ISSUE_SOURCE is sanitized as SAFE_ISSUE_SOURCE at line 37 but raw ISSUE_SOURCE is used in ::warning:: output at line 282. One-character fix — safe variable is already in scope.

Suggested fix: Use SAFE_ISSUE_SOURCE in the warning output.

@fullsend-ai-review fullsend-ai-review Bot added requires-manual-review Review requires human judgment feature labels Jul 9, 2026
Comment thread env/refine.env

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.

Same deal as the other PR, move this to the harness

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

I want to move some envs to the harness file.

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

Labels

feature requires-manual-review Review requires human judgment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants