Skip to content

test(eval): add fix agent human /fs-fix functional eval#183

Open
ascerra wants to merge 8 commits into
eval/code-functional-testfrom
eval/fix-functional-test
Open

test(eval): add fix agent human /fs-fix functional eval#183
ascerra wants to merge 8 commits into
eval/code-functional-testfrom
eval/fix-functional-test

Conversation

@ascerra

@ascerra ascerra commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Add eval/fix/ with 001-human-fs-fix-add (existing PR + human_instruction in case input)
  • Extend shared eval scripts for fix env, real PR-head checkout, and PR head/file capture

Closes #182

Stacked on #177

Base is eval/code-functional-test (PR #177) so this PR is fix-only. After #177 merges to main, rebase this branch onto main and retarget the PR base to main.

Test plan

  • ./eval/lint-cases.sh fix
  • Functional-tests (fix) green
  • Artifact shows new_commit + expected_files pass

Functional test proof

CI run: https://github.com/fullsend-ai/agents/actions/runs/29431325042
Job: functional-tests (fix)pass

Ephemeral fixture (torn down after case)

Step Evidence
Repo halfsend/eval-001-human-fs-fix-add-eaf3b3ca
PR under fix https://github.com/halfsend/eval-001-human-fs-fix-add-eaf3b3ca/pull/1
PR head branch eval-pr-1784131907-3665
Baseline → new head c2eab6fe85c316

Judge results (summary.yaml from artifact eval-results-fix)

Judge Pass rate Rationale
new_commit 1.0 New commit on PR: c2eab6f…e85c316…
expected_files 1.0 All expected files present: ['calc.py']
forbidden_labels 1.0 No forbidden labels specified
max_turns 1.0 Turns OK: 13 ≤ 80
max_cost 1.0 Cost OK: ~$1.47 ≤ $8.00

Captured fixture state (excerpt)

{
  "fixture_type": "pull_request",
  "fixture_url": "https://github.com/halfsend/eval-001-human-fs-fix-add-eaf3b3ca/pull/1",
  "head_sha": "e85c3164bcd15b5a5d67d3553a882c37c8ea650f",
  "pre_agent_head": "c2eab6f4006228091cfe6bb4f4da3ece8c479d28",
  "head_ref": "eval-pr-1784131907-3665",
  "files": ["calc.py", "tests/test_calc.py"]
}

Note: the halfsend eval repo is deleted by teardown-fixture.sh after capture, so the PR URL above is historical proof from the artifact, not a live page.

@ascerra
ascerra requested a review from a team as a code owner July 15, 2026 15:17
@fullsend-ai-review

fullsend-ai-review Bot commented Jul 15, 2026

Copy link
Copy Markdown

🤖 Finished Review · ✅ Success · Started 3:18 PM UTC · Completed 3:30 PM UTC
Commit: ae8fbe0 · View workflow run →

@qodo-code-review

Copy link
Copy Markdown

PR Summary by Qodo

Add code/fix functional eval suites with PR-head checkout and capture

🧪 Tests ✨ Enhancement 📝 Documentation 🕐 40+ Minutes

Grey Divider

AI Description

• Add eval/fix human /fs-fix PR fixture with judges for new commit + expected files.
• Add eval/code end-to-end functional eval case and tiny-calc fixture repo.
• Extend shared runner/capture scripts to checkout PR head and record head SHA/files.
Diagram

graph TD
  A["eval/fix/eval.yaml"] --> B["setup-fixture.sh"] --> C["run-fullsend.sh"] --> D["fullsend run fix"] --> E["capture-fixture.sh"] --> F["output/fixture-state.json"] --> G["Judges: new_commit + expected_files"]
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Parameterize a single eval suite for code vs fix
  • ➕ Less duplication across eval/code and eval/fix (shared judges, shared YAML scaffolding).
  • ➕ Easier to roll out common runner/capture changes once.
  • ➖ Harder to keep agent-specific env and success criteria isolated (risk of accidental coupling).
  • ➖ Makes CI selection and triage less obvious than separate eval//eval.yaml.
2. Post an actual `/fs-fix` PR comment in the ephemeral repo
  • ➕ More realistic end-to-end coverage of comment parsing and trigger behavior.
  • ➕ Better observability for humans inspecting the ephemeral PR.
  • ➖ Adds flakiness/rate-limit surface area and increases reliance on GitHub comment APIs.
  • ➖ Design explicitly scopes v1 away from live-comment triggering; would change the test contract.
3. Use commit-list judge rather than head-sha comparison
  • ➕ More robust proof of agent activity (can assert number of new commits or author/email).
  • ➕ Can provide clearer diagnostics when pushes rewrite history.
  • ➖ Requires additional capture logic (commits list) and more complex judge logic.
  • ➖ Head-SHA delta + expected_files is a simpler, sufficient v1 structural signal.

Recommendation: Keep the current approach: separate eval/fix mirroring eval/code, with additive shared-script changes. It preserves clear CI selection boundaries, limits scope to deterministic env-driven triggers, and provides a minimal-but-strong structural success signal (new head SHA + expected changed file). Consider adding a follow-up case that posts a real /fs-fix comment once the env-driven pipeline is stable.

Files changed (15) +1268 / -16

Enhancement (2) +162 / -16
capture-fixture.shCapture PR head SHA, changed files, and baseline head for fix judges +78/-3

Capture PR head SHA, changed files, and baseline head for fix judges

• Adds a retrying 'fetch_pr_files' helper and enriches capture output for both issue and pull_request fixtures. For PR fixtures, records 'head_sha', 'head_ref', changed 'files', 'files_fetch_failed', and 'pre_agent_head' (from env or 'pre-agent-head.txt').

eval/scripts/capture-fixture.sh

run-fullsend.shRun agents on PR head and emit fix-agent human-trigger env +84/-13

Run agents on PR head and emit fix-agent human-trigger env

• Changes eval cloning to a 'GITHUB_WORKSPACE'-like layout ('target-repo/') and checks out the PR head for pull_request fixtures. Adds dotenv emission hardening (newline/shape checks), emits required code/fix harness env ('PUSH_TOKEN_SOURCE', workspace, bot email), and sets fix-only vars ('TRIGGER_SOURCE', 'HUMAN_INSTRUCTION', 'PRE_AGENT_HEAD', empty 'REVIEW_BODY_FILE').

eval/scripts/run-fullsend.sh

Tests (11) +451 / -0
annotations.yamlDefine expectations and budgets for code eval case 001 +20/-0

Define expectations and budgets for code eval case 001

• Adds 'expected_files' plus turn/cost budgets for the code-agent functional eval case. Provides narrative expectations for the end-to-end success signal (post-script PR creation).

eval/code/cases/001-fix-add/annotations.yaml

input.yamlAdd issue fixture describing calc add() bug for code eval +22/-0

Add issue fixture describing calc add() bug for code eval

• Defines an issue-based fixture used by the code agent to implement a fix. The issue text guides the agent to correct 'add()' behavior while keeping tests passing.

eval/code/cases/001-fix-add/input.yaml

repoPoint code eval case at shared tiny-calc repo fixture +1/-0

Point code eval case at shared tiny-calc repo fixture

• Adds a repo reference to '../../repos/tiny-calc' so the code eval case uses a consistent fixture repository layout.

eval/code/cases/001-fix-add/repo

eval.yamlIntroduce code agent functional eval suite and judges +172/-0

Introduce code agent functional eval suite and judges

• Adds the 'code-eval' configuration, including hooks, runner invocation, budgets, and judges like 'pr_created' and 'expected_files'. Establishes the artifact contract via 'output/fixture-state.json' and 'metrics.json'.

eval/code/eval.yaml

README.mdAdd tiny-calc README for code eval fixture repo +3/-0

Add tiny-calc README for code eval fixture repo

• Documents the minimal fixture repo used by the code-agent eval.

eval/code/repos/tiny-calc/README.md

calc.pyAdd tiny-calc buggy implementation for code eval +6/-0

Add tiny-calc buggy implementation for code eval

• Introduces a minimal 'add()' implementation containing an intentional operator bug ('a - b') for the code agent to fix.

eval/code/repos/tiny-calc/calc.py

test_calc.pyAdd tests asserting correct add() behavior for code eval +11/-0

Add tests asserting correct add() behavior for code eval

• Adds pytest tests that fail until 'add()' is fixed, providing a deterministic target for the functional eval.

eval/code/repos/tiny-calc/tests/test_calc.py

annotations.yamlDefine expectations and budgets for fix eval case 001 +15/-0

Define expectations and budgets for fix eval case 001

• Adds 'expected_files' plus turn/cost budgets for the fix-agent PR-based case. Documents the structural success criteria: push a new commit on the existing PR touching 'calc.py'.

eval/fix/cases/001-human-fs-fix-add/annotations.yaml

input.yamlAdd PR fixture with buggy calc and tests for /fs-fix case +31/-0

Add PR fixture with buggy calc and tests for /fs-fix case

• Defines a pull-request fixture where the PR branch introduces buggy 'calc.py' and tests. Provides a PR body hint that a '/fs-fix' action may be needed, while the actual trigger is via env in the runner.

eval/fix/cases/001-human-fs-fix-add/input.yaml

README.mdAdd base-branch README for fix eval fixture repo +3/-0

Add base-branch README for fix eval fixture repo

• Adds a minimal README on 'main' clarifying that product code lives only on the PR branch for this eval.

eval/fix/cases/001-human-fs-fix-add/repo/README.md

eval.yamlIntroduce fix agent functional eval suite and judges +167/-0

Introduce fix agent functional eval suite and judges

• Adds the 'fix-eval' configuration wired to the shared setup/runner/capture scripts. Implements judges 'new_commit' and 'expected_files' driven by captured PR head SHA and file list, plus budget/label checks.

eval/fix/eval.yaml

Documentation (2) +655 / -0
2026-07-15-fix-agent-functional-eval.mdAdd implementation plan for fix-agent functional eval +536/-0

Add implementation plan for fix-agent functional eval

• Introduces a step-by-step plan describing required script changes, eval config, case fixture, and validation judges. Documents constraints like human-only triggers and exact 'HUMAN_INSTRUCTION' formatting.

docs/superpowers/plans/2026-07-15-fix-agent-functional-eval.md

2026-07-15-fix-agent-functional-eval-design.mdAdd fix-agent functional eval design spec +119/-0

Add fix-agent functional eval design spec

• Defines the v1 scope for a fix-agent functional eval: human trigger via env, PR-based fixture, required env variables, and judge criteria. Explicitly documents out-of-scope items (live comments, bot triggers, full Actions dispatch).

docs/superpowers/specs/2026-07-15-fix-agent-functional-eval-design.md

@ascerra
ascerra changed the base branch from main to eval/code-functional-test July 15, 2026 15:20
@qodo-code-review

qodo-code-review Bot commented Jul 15, 2026

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (1) 📘 Rule violations (0) 📎 Requirement gaps (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. HUMAN_INSTRUCTION agent prompt strings ✓ Resolved 📜 Skill insight ⛨ Security
Description
The PR introduces explicit agent-instruction text in both documentation and runtime env emission
(HUMAN_INSTRUCTION), matching disallowed prompt/agent-instruction patterns in committed content.
This can create prompt-injection style payloads in code/config/docs and violates the repo’s “no
agent instruction patterns” compliance rule.
Code

eval/scripts/run-fullsend.sh[R122-131]

+  if [[ "$AGENT" == "fix" ]]; then
+    REVIEW_BODY_FILE="$(mktemp)"
+    : > "$REVIEW_BODY_FILE"
+    emit_env "TRIGGER_SOURCE" "eval-human"
+    emit_env "HUMAN_INSTRUCTION" "calc.py's add() returns a - b instead of a + b. Change it to return a + b so the existing tests in tests/test_calc.py pass. Do not refactor beyond that fix."
+    emit_env "FIX_ITERATION" "1"
+    emit_env "TARGET_BRANCH" "main"
+    emit_env "PRE_AGENT_HEAD" "${PRE_AGENT_HEAD}"
+    emit_env "REVIEW_BODY_FILE" "${REVIEW_BODY_FILE}"
+  fi
Relevance

⭐⭐ Medium

No prior repo evidence on banning agent-instruction strings; some compliance-hardening suggestions
were rejected elsewhere.

PR-#148

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
Compliance rule 1538322 forbids agent-instruction patterns in comments, string literals, or config
values in changed files. The PR adds explicit agent-directed instructions in docs and emits a
detailed natural-language instruction via emit_env "HUMAN_INSTRUCTION" ..., which is a prompt-like
instruction string committed into the repo and used as a runtime value.

eval/scripts/run-fullsend.sh[122-131]
docs/superpowers/plans/2026-07-15-fix-agent-functional-eval.md[3-7]
docs/superpowers/specs/2026-07-15-fix-agent-functional-eval-design.md[35-46]
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
The PR adds agent-instruction style content (including a concrete `HUMAN_INSTRUCTION` prompt string and “for agentic workers” instructions) inside committed files. This violates the compliance requirement forbidding agent-instruction patterns in comments, string literals, and config values.

## Issue Context
The functional eval may still need a human instruction at runtime, but it must be represented in a way that does not embed agent-instruction/prompt text directly in committed repo content (docs/scripts/config). Consider alternative mechanisms (e.g., referencing an external fixture artifact, generating the instruction at runtime from non-instructional structured data, or storing only a neutral bug descriptor and composing the instruction in-memory).

## Fix Focus Areas
- eval/scripts/run-fullsend.sh[122-131]
- docs/superpowers/plans/2026-07-15-fix-agent-functional-eval.md[3-7]
- docs/superpowers/specs/2026-07-15-fix-agent-functional-eval-design.md[35-46]

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



Remediation recommended

2. Workspace override hides helpers 🐞 Bug ☼ Reliability
Description
eval/scripts/run-fullsend.sh rewrites GITHUB_WORKSPACE to a temp directory for code/fix runs, but
pre/post scripts use $GITHUB_WORKSPACE/scripts and $GITHUB_WORKSPACE/.fullsend/scripts as fallback
locations for missing companion tooling. This can disable pre-commit tool auto-install and cause
post-code/post-fix to fail on repos with .pre-commit-config.yaml when those companion scripts are
only present in the original workspace.
Code

eval/scripts/run-fullsend.sh[R94-104]

+  # Code/fix harness runner_env refs — mint normally sets these; eval skips mint.
+  # Only override GITHUB_WORKSPACE for agents whose post-scripts expand
+  # REPO_DIR=${GITHUB_WORKSPACE}/target-repo (triage reads config.yaml from
+  # the real Actions workspace and must not be redirected to the temp clone).
+  case "$AGENT" in
+    code|fix)
+      emit_env "PUSH_TOKEN_SOURCE" "eval"
+      emit_env "CODE_ALLOWED_TARGET_BRANCHES" ""
+      emit_env "GITHUB_WORKSPACE" "${EVAL_GH_WORKSPACE}"
+      emit_env "GIT_BOT_EMAIL" "fullsend-eval[bot]@users.noreply.github.com"
+      ;;
Relevance

⭐⭐⭐ High

Team recently added ${GITHUB_WORKSPACE}/scripts fallback for missing companions; overriding
GITHUB_WORKSPACE risks breaking that reliability fix.

PR-#41
PR-#148

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
run-fullsend.sh explicitly overwrites GITHUB_WORKSPACE for code/fix; pre/post scripts then use that
variable to locate companion scripts under workspace-relative paths when local copies are missing,
so changing it can break the fallback and skip/disable tool installation relied on before
authoritative pre-commit runs.

eval/scripts/run-fullsend.sh[94-105]
scripts/pre-fix.sh[109-140]
scripts/pre-code.sh[129-160]
scripts/post-fix.sh[181-213]
scripts/post-code.sh[260-310]

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

### Issue description
`run-fullsend.sh` sets `GITHUB_WORKSPACE` to a temp dir (`EVAL_GH_WORKSPACE`) for `code|fix` so `REPO_DIR=${GITHUB_WORKSPACE}/target-repo` resolves, but this changes the lookup path used by pre/post scripts for companion tooling (`resolve-precommit-tools.py` / `install-precommit-tools.sh`).

### Issue Context
The repo’s pre/post scripts explicitly try `${GITHUB_WORKSPACE}/scripts` and `${GITHUB_WORKSPACE}/.fullsend/scripts` as fallbacks when those companion scripts are not present alongside the checked-in `scripts/*.sh`.

### Fix Focus Areas
- eval/scripts/run-fullsend.sh[94-105]
- scripts/pre-fix.sh[109-140]
- scripts/pre-code.sh[129-160]
- scripts/post-fix.sh[181-213]
- scripts/post-code.sh[260-310]

### Suggested changes
Implement one of:
1) **Clone into the real case workspace** (so `GITHUB_WORKSPACE` can remain the real workspace) and set `TARGET_DIR` to `${CASE_WORKSPACE}/target-repo` (or similar), avoiding the override.
2) **Set `REPO_DIR` explicitly** for code/fix runs (if fullsend’s env precedence allows it) and do not override `GITHUB_WORKSPACE`.
3) **Populate the temp workspace with required helper dirs** by copying/linking `${ORIG_GITHUB_WORKSPACE}/scripts` (or `.fullsend/scripts`) into `${EVAL_GH_WORKSPACE}` before exporting `GITHUB_WORKSPACE`.

Add a small comment explaining why the chosen approach preserves both `REPO_DIR` resolution and companion-script discovery.

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


3. PR capture lacks retries ✓ Resolved 🐞 Bug ☼ Reliability
Description
eval/scripts/capture-fixture.sh fetches PR metadata via several separate gh pr view calls (pr
fields, comments, reviews) with no retry and set -euo pipefail, so a transient GitHub API/CLI
failure can abort after_each without producing fixture-state.json. This is inconsistent with the
newly-added retry logic for fetching PR file lists and can make PR-based evals flaky.
Code

eval/scripts/capture-fixture.sh[R103-108]

    pr_json=$(gh pr view "$FIXTURE_NUMBER" --repo "$EPHEMERAL_REPO" \
-      --json state,labels,assignees,milestone,title,mergeable,reviewDecision)
+      --json state,labels,assignees,milestone,title,mergeable,reviewDecision,headRefOid,headRefName)
    comments_json=$(gh pr view "$FIXTURE_NUMBER" --repo "$EPHEMERAL_REPO" --json comments \
      | jq '[.comments[] | {author: .author.login, body: .body, created_at: .createdAt}]')
    reviews_json=$(gh pr view "$FIXTURE_NUMBER" --repo "$EPHEMERAL_REPO" --json reviews \
      | jq '[.reviews[] | {author: .author.login, state: .state, body: .body}]')
Relevance

⭐⭐⭐ High

Eval harness already added best-effort gh calls/retries to reduce flakiness; extending retries to
other gh pr view fits pattern.

PR-#31

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The script is fail-fast (set -euo pipefail), has retries only for the files sub-fetch, and still
performs multiple separate gh pr view calls without retries in the PR capture branch—any transient
failure can abort the hook.

eval/scripts/capture-fixture.sh[16-26]
eval/scripts/capture-fixture.sh[28-43]
eval/scripts/capture-fixture.sh[102-109]

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

### Issue description
`capture-fixture.sh` adds retries for `files` (via `fetch_pr_files`) but still makes multiple non-retried `gh pr view` calls for PR metadata/comments/reviews in the `pull_request)` branch. With `set -euo pipefail`, any one of these failing can terminate the hook and prevent `fixture-state.json` from being written.

### Issue Context
The functional eval judges depend on `output/fixture-state.json`; flakiness here becomes an infrastructure failure, not an agent failure.

### Fix Focus Areas
- eval/scripts/capture-fixture.sh[16-26]
- eval/scripts/capture-fixture.sh[28-43]
- eval/scripts/capture-fixture.sh[102-154]

### Suggested changes
- Add a small `retry_gh()` helper (similar to `fetch_pr_files` retry loop) and use it for:
 - the main PR metadata fetch (`pr_json=...`)
 - comments fetch
 - reviews fetch
- Optionally reduce API calls by using **one** `gh pr view` call with all needed JSON fields (`state,labels,assignees,milestone,title,mergeable,reviewDecision,headRefOid,headRefName,comments,reviews,files`) and then `jq` to shape into the desired output.
- On persistent failure, still write a valid `fixture-state.json` with explicit failure flags (e.g., `pr_fetch_failed: true`, null fields) so judges can fail with a clear message rather than the hook crashing.

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


Grey Divider

Qodo Logo

Comment thread eval/scripts/run-fullsend.sh
Comment thread eval/scripts/capture-fixture.sh Outdated
@fullsend-ai-review

fullsend-ai-review Bot commented Jul 15, 2026

Copy link
Copy Markdown

Looks good to me

Previous run

Review — approve

PR: #183test(eval): add fix agent human /fs-fix functional eval
Scope: Adds eval/fix/ functional eval for the fix agent pipeline (human /fs-fix trigger), extends shared eval scripts for fix-specific env, real PR-head checkout, and enriched fixture state capture.

Re-review delta

Prior review (at 1540d4fd) approved the PR. One rebase was performed since — all 7 PR files are byte-identical to the prior approved state. The rebase updated the base branch (eval/code-functional-test) to include PR #184 (artifact scrub) and PR #178 (API access restriction) which were merged independently. No code changes in this PR's scope.

Analysis

Correctness: No issues found. All five judges (new_commit, expected_files, forbidden_labels, max_turns, max_cost) correctly handle null/missing data with appropriate type coercions. The retry_cmd wrapper and git refs API polling in capture-fixture.sh are well-bounded (21s max polling + 9s max retry = 30s within the 60s after_each timeout). The PRE_AGENT_HEAD producer/consumer contract (env var + sidecar file fallback) is verified complete. The HUMAN_INSTRUCTION propagation chain (input.yaml → yq strenv → hook-outputs → harness → emit_env → dotenv) is sound. The fix eval's fixture-state.json structure aligns with the judge expectations.

Security: No issues found. emit_env() with name regex validation and newline/CR rejection is a security improvement over the baseline raw echo pattern. HEAD_REF regex (^[A-Za-z0-9._/-]+$) correctly excludes shell metacharacters. GH_TOKEN is handled through credential helpers (not embedded in URLs), env files are mode 0600 and cleaned up on exit, and the scrub pipeline (in the base branch) provides defense-in-depth. All fixture content is checked-in test data authored by the development team — no untrusted input surfaces.

Intent & coherence: All 7 changed files trace directly to issue #182's acceptance criteria. No scope creep detected. The eval/fix/ structure follows the established pattern from eval/triage/ and eval/review/. The stacking on PR #177 is appropriate and explicitly documented.

Style/conventions: Code follows all established conventions: #!/usr/bin/env bash, set -euo pipefail, uppercase env var names, lowercase function names, stderr error output. Agent-specific case "$AGENT" branching in the shared runner follows the pre-existing case "$FIXTURE_TYPE" pattern.

Documentation: No staleness found. The eval system has no existing documentation (pre-existing gap across all eval agents, not attributable to this PR). Internal env vars (HUMAN_INSTRUCTION, PRE_AGENT_HEAD, etc.) are correctly omitted from user-facing docs.

Positive observations

  • emit_env() with name and value validation is genuine security hardening that benefits all eval agents.
  • The graceful pr_fetch_failed fallback in capture-fixture.sh ensures judges fail with clear messages rather than hook aborts.
  • Git refs API + polling for head_sha capture is a well-designed fix for the GitHub PR API headRefOid lag race condition.
  • The HUMAN_INSTRUCTION lifecycle (input.yaml → setup-fixture → hook-outputs → env file → agent) correctly keeps test content with the test case.
  • The pre-agent-head.txt sidecar file provides defense-in-depth for PRE_AGENT_HEAD propagation across process boundaries.
Previous run (2)

Looks good to me

Previous run

Review — approve

PR: #183test(eval): add fix agent human /fs-fix functional eval
Scope: Adds eval/fix/ functional eval for the fix agent pipeline (human /fs-fix trigger), extends shared eval scripts for fix-specific env, PR-head checkout, and enriched fixture state capture. Adds scrub-eval-results.sh for comprehensive secret redaction before artifact upload.

Re-review delta

Prior review (at 0889e1d) approved the PR with all earlier findings resolved. One commit was pushed since:

Commit Description
8b088ff fix(eval): scrub ::add-mask:: tokens from functional-test artifacts

This commit replaces the inline find ... -delete in .github/workflows/functional-tests.yml with a dedicated eval/scripts/scrub-eval-results.sh script that:

  • Deletes .eval-env files (preserving prior behavior)
  • Scrubs all 6 GitHub token prefixes (ghp_, gho_, ghu_, ghs_, ghr_, github_pat_) and x-access-token: credential URLs from text files
  • Runs a fail-closed verification pass to detect surviving tokens

This is a net security improvement over the prior delete-only approach.

Analysis

Correctness: The scrub regex correctly handles all 6 GitHub token prefixes and credential URL patterns. The \S+ match for ::add-mask:: payloads is appropriate since tokens contain no whitespace. Edge cases are handled: empty directories are skipped ([[ -d "$root" ]] || continue), empty files are skipped ([[ -s "$f" ]] || return 0), and the find targets only text file extensions. The workflow change preserves the original .eval-env deletion behavior while adding the broader scrub. GHA steps are strictly sequential, so no race between scrub and upload.

Security: The script is a clear improvement. The perl scrub patterns are comprehensive for GitHub-issued tokens. The x-access-token pattern correctly handles credential URLs. The fail-closed verification pass adds defense-in-depth. One observation: the verification regex (leak_pat) covers fewer standalone patterns than the scrub regex (see finding below), but this is a defense-in-depth gap — the scrub itself is correct for all patterns.

Intent & coherence: The scrub script goes slightly beyond issue #182's explicit acceptance criteria but directly supports the eval infrastructure being added. The commit type fix(eval) correctly signals this as a bug fix (tokens leaking to artifacts). Architecturally well-placed in eval/scripts/.

Style: The script follows all established conventions: #!/usr/bin/env bash, set -euo pipefail, em-dash comment header, uppercase variable names, lowercase function names, stderr error output.

Documentation: No staleness found. The eval system has no existing documentation files that need updating.

Observations

1. Verification regex narrower than scrub regex — low

File: eval/scripts/scrub-eval-results.sh (line 50)
Category: defense-in-depth

The leak_pat verification regex has standalone \b<prefix>_[A-Za-z0-9_]{20,} patterns for ghp_, gho_, and github_pat_ only. The ghu_, ghs_, and ghr_ prefixes are only checked when preceded by ::add-mask::. Similarly, the x-access-token: pattern is not verified. The scrub regex correctly handles all patterns — this gap is only in the verification/alert layer. Practical risk is low: if a bare ghs_ token survived perl scrubbing (unlikely given the regex matches), it would not trigger the fail-closed alert, but the scrub itself would have already redacted it.

Suggested follow-up: Add \bghu_[A-Za-z0-9_]{20,}, \bghs_[A-Za-z0-9_]{20,}, and \bghr_[A-Za-z0-9_]{20,} to leak_pat for parity with the scrub regex.

Positive observations

  • The script is a significant security upgrade over the prior inline find ... -delete which only removed .eval-env files but left tokens in log/JSON output.
  • The fail-closed design (exit 1 on detected leaks) is the right pattern for secret scrubbing.
  • GHA ::add-mask:: runtime masking provides additional defense for any tokens that reach step logs.
  • The --binary-files=without-match flag and extension-based file selection prevent corruption of binary artifacts.

Labels: PR adds fix agent eval infrastructure, extends shared eval scripts, and hardens eval artifact secret scrubbing.


Protected paths detected — this PR modifies files under one or more
protected paths. The review agent cannot approve PRs that touch these paths.
A human reviewer must approve this PR.

Protected files in this PR:

  • .github/workflows/functional-tests.yml
Previous run (3)

Review — approve

PR: #183test(eval): add fix agent human /fs-fix functional eval
Scope: Adds eval/fix/ functional eval for the fix agent pipeline (human /fs-fix trigger), extends shared eval scripts (run-fullsend.sh, capture-fixture.sh, setup-fixture.sh) for fix-specific env, PR-head checkout, and enriched fixture state capture.

Re-review delta

Prior review (at ae8fbe0) raised 5 findings. Three commits were pushed to address them:

Prior finding Severity Resolution
PR-head checkout applies to all pull_request fixtures medium Fixed — scoped to $AGENT == "fix" && $FIXTURE_TYPE == "pull_request"
fetch_pr_files null-safety gap medium Fixed — jq expression now uses [(.files // [])[].path]
eval/code/ additions exceed issue #182 scope medium Resolved — PR base is eval/code-functional-test, so eval/code/ files are in the base, not this PR's diff
Hardcoded HUMAN_INSTRUCTION in shared runner low Fixed — instruction now lives in case input.yaml, propagated through setup-fixture.sh hook outputs
emit_env name parameter not validated low Fixed — regex validation ^[A-Za-z_][A-Za-z0-9_]*$ added

All prior findings have been addressed.

Previous run (4)

Review — approve

PR: #183test(eval): add fix agent human /fs-fix functional eval
Scope: Adds eval/fix/ functional eval for the fix agent pipeline (human /fs-fix trigger), extends shared eval scripts (run-fullsend.sh, capture-fixture.sh, setup-fixture.sh) for fix-specific env, PR-head checkout, and enriched fixture state capture.

Re-review delta

Prior review (at ae8fbe0) raised 5 findings. Three commits were pushed to address them:

Prior finding Severity Resolution
PR-head checkout applies to all pull_request fixtures medium Fixed — scoped to $AGENT == "fix" && $FIXTURE_TYPE == "pull_request"
fetch_pr_files null-safety gap medium Fixed — jq expression now uses [(.files // [])[].path]
eval/code/ additions exceed issue #182 scope medium Resolved — PR base is eval/code-functional-test, so eval/code/ files are in the base, not this PR's diff
Hardcoded HUMAN_INSTRUCTION in shared runner low Fixed — instruction now lives in case input.yaml, propagated through setup-fixture.sh hook outputs
emit_env name parameter not validated low Fixed — regex validation ^[A-Za-z_][A-Za-z0-9_]*$ added

All prior findings have been addressed. The additional commits (49eb3a1, 0889e1d) also fix the branch checkout strategy (use real PR head ref instead of local alias) and add git refs API polling in capture-fixture.sh to handle headRefOid lag after pushes.

Analysis

Correctness: No issues found. The producer/consumer contract for PRE_AGENT_HEAD (env var + sidecar file fallback) is sound. Judge logic handles edge cases (missing keys, null values, type coercion). The polling loop in capture-fixture.sh (up to 21s total) is appropriate for GitHub ref propagation delays. The TRIGGER_SOURCE=eval-human value correctly triggers the human-trigger code path in the fix agent's pre/post scripts.

Security: The PR is a net security improvement. emit_env() replaces raw echo KEY=*** writes with name-format and newline/CR validation, closing a pre-existing dotenv injection surface. Input shape checks for FIXTURE_URL, FIXTURE_NUMBER, and EPHEMERAL_REPOadd defense-in-depth.HEAD_REF validation (^[A-Za-z0-9._/-]+$) is appropriate for eval-generated branch names. HUMAN_INSTRUCTIONis written to.hook-outputs.yamlviayq -iwithstrenv()`, which handles YAML special characters safely.

Intent & coherence: All 7 changed files trace directly to issue #182's acceptance criteria. The stacking on PR #177 is appropriate — after #177 merges to main, rebase and retarget. No scope creep detected.

Style: The new eval/fix/ structure follows the established pattern from eval/code/ (same base branch), including parallelism: 1, EVAL_TIMEOUT in execution env, and case directory naming (001-human-fs-fix-add).

Documentation: No staleness found. The eval system's documentation is inline in script comments and eval.yaml schemas.

Positive observations

  • emit_env() with name and value validation is a genuine security hardening that benefits all eval agents, not just fix.
  • The graceful pr_fetch_failed fallback in capture-fixture.sh ensures judges fail with clear messages rather than hook aborts.
  • The git refs API + polling approach for head_sha capture is a thoughtful fix for a real race condition with GitHub's PR API lag.
  • The HUMAN_INSTRUCTION lifecycle (input.yaml → setup-fixture → hook-outputs → env file → agent) keeps test content with the test case rather than hardcoded in shared scripts.

Labels: PR adds fix agent eval infrastructure and hardens shared eval scripts.

Previous run (5)

Review — comment

PR: #183test(eval): add fix agent human /fs-fix functional eval
Scope: Adds eval/fix/ functional eval for the fix agent pipeline (human /fs-fix trigger), extends shared eval scripts (run-fullsend.sh, capture-fixture.sh), and includes eval/code/ additions from PR #177.

Findings

1. PR-head checkout applies to all pull_request fixtures — medium

File: eval/scripts/run-fullsend.sh (line ~42)
Category: behavioral-change

The new PR-head checkout block runs unconditionally for all pull_request fixtures, not just for the fix agent:

if [[ "$FIXTURE_TYPE" == "pull_request" ]]; then
  git -C "$TARGET_DIR" fetch origin "pull/${FIXTURE_NUMBER}/head:eval-pr-head"
  git -C "$TARGET_DIR" checkout eval-pr-head
fi

The review eval case 001-clean-approve uses fixture.type: pull_request. Previously the clone stayed on main; now it switches to the PR branch. The comment says "Fix (and any PR-driven agent)" suggesting this is intentional, but it's an untested behavioral change for the review pipeline. If the review agent reads source files from --target-repo, it now sees PR-branch content instead of base-branch content.

Remediation: Either scope to agents that need it (if [[ "$AGENT" =~ ^(fix|code)$ ]]; then) or confirm the review eval passes with this change and add a test note documenting the intent.

2. fetch_pr_files null-safety gap — medium

File: eval/scripts/capture-fixture.sh (line ~36)
Category: error-handling

fetch_pr_files uses gh pr view ... --jq '[.files[].path]'. If gh succeeds but .files is null (possible for very recently opened PRs before GitHub computes the file list), the jq expression [.files[].path] errors on stderr (suppressed by 2>/dev/null), and gh may still exit 0. The caller would record files_fetch_failed=false with a non-array value, which is misleading — it looks like the PR has zero changed files rather than "could not determine files."

Remediation: Use a null-safe jq expression: --jq '[(.files // [])[].path]'. This produces [] when .files is null, which is a valid empty result.

3. eval/code additions exceed issue #182 scope — medium

File: eval/code/ (multiple files)
Category: scope-authorization

Issue #182 authorizes eval/fix/ with a human /fs-fix case and shared script extensions. The PR also includes the full eval/code/ directory (eval.yaml, case 001-fix-add, shared tiny-calc repo) which is authorized by issue #180 / PR #177. The PR body transparently acknowledges this: "This branch was cut from eval/code-functional-test (PR #177)... Prefer merging #177 first then rebasing, or close #177 as superseded."

Per AGENTS.md: "Every changed line in your diff must trace directly to the issue scope." The eval/code/ additions trace to #180/#177, not #182.

Remediation: Either merge #177 first and rebase this PR (removing the duplicate eval/code/ commits), or close #177 as superseded and update #182's scope to explicitly authorize landing both evals.

4. Hardcoded HUMAN_INSTRUCTION in shared runner — low

File: eval/scripts/run-fullsend.sh (line ~125)
Category: maintainability

The AGENT=fix block hardcodes the instruction text, TRIGGER_SOURCE, FIX_ITERATION, and TARGET_BRANCH specific to case 001-human-fs-fix-add. Adding a second fix case with a different instruction or trigger mode requires modifying this shared script.

Remediation: Acceptable for v1 with a single case. Consider adding a TODO comment noting the coupling. Future cases should read fix-specific env from the case's input.yaml.

5. emit_env name parameter not validated — low

File: eval/scripts/run-fullsend.sh (line ~63)
Category: defense-in-depth

emit_env() validates values for newlines/CRs but does not validate the name parameter. A name containing = or whitespace would produce a malformed env file line. All current callers use safe hardcoded literals, so this is not exploitable today.

Remediation: Add name validation: if [[ ! "$name" =~ ^[A-Za-z_][A-Za-z0-9_]*$ ]]; then echo "ERROR: invalid env name" >&2; exit 1; fi

Positive Observations

  • The emit_env() function with newline validation is a good defense-in-depth improvement over the raw echo pattern in the base code.
  • Input validation for FIXTURE_URL, FIXTURE_NUMBER, and EPHEMERAL_REPO strengthens the eval infrastructure.
  • The producer/consumer contract for PRE_AGENT_HEAD (sidecar file + env fallback) is well-designed.
  • Judge logic in both eval.yaml files correctly handles edge cases (missing fields, null values, type coercion).
  • The overall architecture (mirroring eval/code/ for eval/fix/, shared hooks/scripts) is clean and consistent with the existing eval/review/ and eval/triage/ patterns.

Labels: PR adds fix and code agent eval infrastructure.

Previous run (6)

Looks good to me

Previous run (7)

Review — approve

PR: #183test(eval): add fix agent human /fs-fix functional eval
Scope: Adds eval/fix/ functional eval for the fix agent pipeline (human /fs-fix trigger), extends shared eval scripts for fix-specific env, PR-head checkout, and enriched fixture state capture. Adds scrub-eval-results.sh for comprehensive secret redaction before artifact upload.

Re-review delta

Prior review (at 0889e1d) approved the PR with all earlier findings resolved. One commit was pushed since:

Commit Description
8b088ff fix(eval): scrub ::add-mask:: tokens from functional-test artifacts

This commit replaces the inline find ... -delete in .github/workflows/functional-tests.yml with a dedicated eval/scripts/scrub-eval-results.sh script that:

  • Deletes .eval-env files (preserving prior behavior)
  • Scrubs all 6 GitHub token prefixes (ghp_, gho_, ghu_, ghs_, ghr_, github_pat_) and x-access-token: credential URLs from text files
  • Runs a fail-closed verification pass to detect surviving tokens

This is a net security improvement over the prior delete-only approach.

Analysis

Correctness: The scrub regex correctly handles all 6 GitHub token prefixes and credential URL patterns. The \S+ match for ::add-mask:: payloads is appropriate since tokens contain no whitespace. Edge cases are handled: empty directories are skipped ([[ -d "$root" ]] || continue), empty files are skipped ([[ -s "$f" ]] || return 0), and the find targets only text file extensions. The workflow change preserves the original .eval-env deletion behavior while adding the broader scrub. GHA steps are strictly sequential, so no race between scrub and upload.

Security: The script is a clear improvement. The perl scrub patterns are comprehensive for GitHub-issued tokens. The x-access-token pattern correctly handles credential URLs. The fail-closed verification pass adds defense-in-depth. One observation: the verification regex (leak_pat) covers fewer standalone patterns than the scrub regex (see finding below), but this is a defense-in-depth gap — the scrub itself is correct for all patterns.

Intent & coherence: The scrub script goes slightly beyond issue #182's explicit acceptance criteria but directly supports the eval infrastructure being added. The commit type fix(eval) correctly signals this as a bug fix (tokens leaking to artifacts). Architecturally well-placed in eval/scripts/.

Style: The script follows all established conventions: #!/usr/bin/env bash, set -euo pipefail, em-dash comment header, uppercase variable names, lowercase function names, stderr error output.

Documentation: No staleness found. The eval system has no existing documentation files that need updating.

Observations

1. Verification regex narrower than scrub regex — low

File: eval/scripts/scrub-eval-results.sh (line 50)
Category: defense-in-depth

The leak_pat verification regex has standalone \b<prefix>_[A-Za-z0-9_]{20,} patterns for ghp_, gho_, and github_pat_ only. The ghu_, ghs_, and ghr_ prefixes are only checked when preceded by ::add-mask::. Similarly, the x-access-token: pattern is not verified. The scrub regex correctly handles all patterns — this gap is only in the verification/alert layer. Practical risk is low: if a bare ghs_ token survived perl scrubbing (unlikely given the regex matches), it would not trigger the fail-closed alert, but the scrub itself would have already redacted it.

Suggested follow-up: Add \bghu_[A-Za-z0-9_]{20,}, \bghs_[A-Za-z0-9_]{20,}, and \bghr_[A-Za-z0-9_]{20,} to leak_pat for parity with the scrub regex.

Positive observations

  • The script is a significant security upgrade over the prior inline find ... -delete which only removed .eval-env files but left tokens in log/JSON output.
  • The fail-closed design (exit 1 on detected leaks) is the right pattern for secret scrubbing.
  • GHA ::add-mask:: runtime masking provides additional defense for any tokens that reach step logs.
  • The --binary-files=without-match flag and extension-based file selection prevent corruption of binary artifacts.

Labels: PR adds fix agent eval infrastructure, extends shared eval scripts, and hardens eval artifact secret scrubbing.


Protected paths detected — this PR modifies files under one or more
protected paths. The review agent cannot approve PRs that touch these paths.
A human reviewer must approve this PR.

Protected files in this PR:

  • .github/workflows/functional-tests.yml
Previous run (8)

Review — approve

PR: #183test(eval): add fix agent human /fs-fix functional eval
Scope: Adds eval/fix/ functional eval for the fix agent pipeline (human /fs-fix trigger), extends shared eval scripts (run-fullsend.sh, capture-fixture.sh, setup-fixture.sh) for fix-specific env, PR-head checkout, and enriched fixture state capture.

Re-review delta

Prior review (at ae8fbe0) raised 5 findings. Three commits were pushed to address them:

Prior finding Severity Resolution
PR-head checkout applies to all pull_request fixtures medium Fixed — scoped to $AGENT == "fix" && $FIXTURE_TYPE == "pull_request"
fetch_pr_files null-safety gap medium Fixed — jq expression now uses [(.files // [])[].path]
eval/code/ additions exceed issue #182 scope medium Resolved — PR base is eval/code-functional-test, so eval/code/ files are in the base, not this PR's diff
Hardcoded HUMAN_INSTRUCTION in shared runner low Fixed — instruction now lives in case input.yaml, propagated through setup-fixture.sh hook outputs
emit_env name parameter not validated low Fixed — regex validation ^[A-Za-z_][A-Za-z0-9_]*$ added

All prior findings have been addressed.

Previous run (9)

Review — approve

PR: #183test(eval): add fix agent human /fs-fix functional eval
Scope: Adds eval/fix/ functional eval for the fix agent pipeline (human /fs-fix trigger), extends shared eval scripts (run-fullsend.sh, capture-fixture.sh, setup-fixture.sh) for fix-specific env, PR-head checkout, and enriched fixture state capture.

Re-review delta

Prior review (at ae8fbe0) raised 5 findings. Three commits were pushed to address them:

Prior finding Severity Resolution
PR-head checkout applies to all pull_request fixtures medium Fixed — scoped to $AGENT == "fix" && $FIXTURE_TYPE == "pull_request"
fetch_pr_files null-safety gap medium Fixed — jq expression now uses [(.files // [])[].path]
eval/code/ additions exceed issue #182 scope medium Resolved — PR base is eval/code-functional-test, so eval/code/ files are in the base, not this PR's diff
Hardcoded HUMAN_INSTRUCTION in shared runner low Fixed — instruction now lives in case input.yaml, propagated through setup-fixture.sh hook outputs
emit_env name parameter not validated low Fixed — regex validation ^[A-Za-z_][A-Za-z0-9_]*$ added

All prior findings have been addressed. The additional commits (49eb3a1, 0889e1d) also fix the branch checkout strategy (use real PR head ref instead of local alias) and add git refs API polling in capture-fixture.sh to handle headRefOid lag after pushes.

Analysis

Correctness: No issues found. The producer/consumer contract for PRE_AGENT_HEAD (env var + sidecar file fallback) is sound. Judge logic handles edge cases (missing keys, null values, type coercion). The polling loop in capture-fixture.sh (up to 21s total) is appropriate for GitHub ref propagation delays. The TRIGGER_SOURCE=eval-human value correctly triggers the human-trigger code path in the fix agent's pre/post scripts.

Security: The PR is a net security improvement. emit_env() replaces raw echo KEY=*** writes with name-format and newline/CR validation, closing a pre-existing dotenv injection surface. Input shape checks for FIXTURE_URL, FIXTURE_NUMBER, and EPHEMERAL_REPOadd defense-in-depth.HEAD_REF validation (^[A-Za-z0-9._/-]+$) is appropriate for eval-generated branch names. HUMAN_INSTRUCTIONis written to.hook-outputs.yamlviayq -iwithstrenv()`, which handles YAML special characters safely.

Intent & coherence: All 7 changed files trace directly to issue #182's acceptance criteria. The stacking on PR #177 is appropriate — after #177 merges to main, rebase and retarget. No scope creep detected.

Style: The new eval/fix/ structure follows the established pattern from eval/code/ (same base branch), including parallelism: 1, EVAL_TIMEOUT in execution env, and case directory naming (001-human-fs-fix-add).

Documentation: No staleness found. The eval system's documentation is inline in script comments and eval.yaml schemas.

Positive observations

  • emit_env() with name and value validation is a genuine security hardening that benefits all eval agents, not just fix.
  • The graceful pr_fetch_failed fallback in capture-fixture.sh ensures judges fail with clear messages rather than hook aborts.
  • The git refs API + polling approach for head_sha capture is a thoughtful fix for a real race condition with GitHub's PR API lag.
  • The HUMAN_INSTRUCTION lifecycle (input.yaml → setup-fixture → hook-outputs → env file → agent) keeps test content with the test case rather than hardcoded in shared scripts.

Labels: PR adds fix agent eval infrastructure and hardens shared eval scripts.

Previous run (10)

Review — comment

PR: #183test(eval): add fix agent human /fs-fix functional eval
Scope: Adds eval/fix/ functional eval for the fix agent pipeline (human /fs-fix trigger), extends shared eval scripts (run-fullsend.sh, capture-fixture.sh), and includes eval/code/ additions from PR #177.

Findings

1. PR-head checkout applies to all pull_request fixtures — medium

File: eval/scripts/run-fullsend.sh (line ~42)
Category: behavioral-change

The new PR-head checkout block runs unconditionally for all pull_request fixtures, not just for the fix agent:

if [[ "$FIXTURE_TYPE" == "pull_request" ]]; then
  git -C "$TARGET_DIR" fetch origin "pull/${FIXTURE_NUMBER}/head:eval-pr-head"
  git -C "$TARGET_DIR" checkout eval-pr-head
fi

The review eval case 001-clean-approve uses fixture.type: pull_request. Previously the clone stayed on main; now it switches to the PR branch. The comment says "Fix (and any PR-driven agent)" suggesting this is intentional, but it's an untested behavioral change for the review pipeline. If the review agent reads source files from --target-repo, it now sees PR-branch content instead of base-branch content.

Remediation: Either scope to agents that need it (if [[ "$AGENT" =~ ^(fix|code)$ ]]; then) or confirm the review eval passes with this change and add a test note documenting the intent.

2. fetch_pr_files null-safety gap — medium

File: eval/scripts/capture-fixture.sh (line ~36)
Category: error-handling

fetch_pr_files uses gh pr view ... --jq '[.files[].path]'. If gh succeeds but .files is null (possible for very recently opened PRs before GitHub computes the file list), the jq expression [.files[].path] errors on stderr (suppressed by 2>/dev/null), and gh may still exit 0. The caller would record files_fetch_failed=false with a non-array value, which is misleading — it looks like the PR has zero changed files rather than "could not determine files."

Remediation: Use a null-safe jq expression: --jq '[(.files // [])[].path]'. This produces [] when .files is null, which is a valid empty result.

3. eval/code additions exceed issue #182 scope — medium

File: eval/code/ (multiple files)
Category: scope-authorization

Issue #182 authorizes eval/fix/ with a human /fs-fix case and shared script extensions. The PR also includes the full eval/code/ directory (eval.yaml, case 001-fix-add, shared tiny-calc repo) which is authorized by issue #180 / PR #177. The PR body transparently acknowledges this: "This branch was cut from eval/code-functional-test (PR #177)... Prefer merging #177 first then rebasing, or close #177 as superseded."

Per AGENTS.md: "Every changed line in your diff must trace directly to the issue scope." The eval/code/ additions trace to #180/#177, not #182.

Remediation: Either merge #177 first and rebase this PR (removing the duplicate eval/code/ commits), or close #177 as superseded and update #182's scope to explicitly authorize landing both evals.

4. Hardcoded HUMAN_INSTRUCTION in shared runner — low

File: eval/scripts/run-fullsend.sh (line ~125)
Category: maintainability

The AGENT=fix block hardcodes the instruction text, TRIGGER_SOURCE, FIX_ITERATION, and TARGET_BRANCH specific to case 001-human-fs-fix-add. Adding a second fix case with a different instruction or trigger mode requires modifying this shared script.

Remediation: Acceptable for v1 with a single case. Consider adding a TODO comment noting the coupling. Future cases should read fix-specific env from the case's input.yaml.

5. emit_env name parameter not validated — low

File: eval/scripts/run-fullsend.sh (line ~63)
Category: defense-in-depth

emit_env() validates values for newlines/CRs but does not validate the name parameter. A name containing = or whitespace would produce a malformed env file line. All current callers use safe hardcoded literals, so this is not exploitable today.

Remediation: Add name validation: if [[ ! "$name" =~ ^[A-Za-z_][A-Za-z0-9_]*$ ]]; then echo "ERROR: invalid env name" >&2; exit 1; fi

Positive Observations

  • The emit_env() function with newline validation is a good defense-in-depth improvement over the raw echo pattern in the base code.
  • Input validation for FIXTURE_URL, FIXTURE_NUMBER, and EPHEMERAL_REPO strengthens the eval infrastructure.
  • The producer/consumer contract for PRE_AGENT_HEAD (sidecar file + env fallback) is well-designed.
  • Judge logic in both eval.yaml files correctly handles edge cases (missing fields, null values, type coercion).
  • The overall architecture (mirroring eval/code/ for eval/fix/, shared hooks/scripts) is clean and consistent with the existing eval/review/ and eval/triage/ patterns.

Labels: PR adds fix and code agent eval infrastructure.

ascerra added a commit that referenced this pull request Jul 15, 2026
Scope PR-head checkout to fix only, move HUMAN_INSTRUCTION into case
input.yaml, harden PR capture with retries/null-safety, validate emit_env
names, and drop superpowers plan/spec docs from the PR.

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

ascerra commented Jul 15, 2026

Copy link
Copy Markdown
Contributor Author

Review follow-up (cc39ea4)

Addressed bot findings:

Finding Action
PR-head checkout for all PR fixtures Scoped to AGENT=fix only — review stays on main
fetch_pr_files null-safety [(.files // [])[].path] + single retried PR view
PR capture lacks retries retry_cmd + one consolidated gh pr view; failure writes pr_fetch_failed state
Hardcoded HUMAN_INSTRUCTION / agent-prompt compliance Moved to case input.yaml (human_instruction); setup forwards via hook-outputs
emit_env name validation Added ^[A-Za-z_][A-Za-z0-9_]*$ check
eval/code/ scope vs #182 PR base is eval/code-functional-test (#177) — fix-only commits; rebase onto main after #177 merges
Superpowers plan/spec in PR Removed from the branch

@fullsend-ai-review

fullsend-ai-review Bot commented Jul 15, 2026

Copy link
Copy Markdown

🤖 Review · ⚠️ Cancelled · Started 3:58 PM UTC · Ended 4:04 PM UTC
Commit: 5cd495a · View workflow run →

@ascerra

ascerra commented Jul 15, 2026

Copy link
Copy Markdown
Contributor Author

CI follow-up — new_commit failure root cause

Run 29430352558: agent fixed calc.py and post-script reported Pushed: yes, but new_commit failed.

Cause: run-fullsend.sh checked out a local branch named eval-pr-head. post-fix.sh pushes git branch --show-current, so it created a new remote branch eval-pr-head instead of updating the PR head (eval-pr-…). PR head_sha stayed at pre_agent_head.

Fix: cc39ea4 follow-up — resolve headRefName via gh pr view and checkout/fetch that ref so the push lands on the PR.

Also: artifact again contains a raw token via ::add-mask:: in stdout — rotate the halfsend/GH_TOKEN secret if not already done after #177.

@fullsend-ai-review

fullsend-ai-review Bot commented Jul 15, 2026

Copy link
Copy Markdown

🤖 Review · ⚠️ Cancelled · Started 4:04 PM UTC · Ended 4:11 PM UTC
Commit: 5cd495a · View workflow run →

@ascerra

ascerra commented Jul 15, 2026

Copy link
Copy Markdown
Contributor Author

CI follow-up 2 — stale headRefOid race

On 29430822410 the checkout fix worked: post-script pushed 24076e9..b0d6923 onto the real PR head branch. Capture still recorded the old SHA because gh pr view --json headRefOid lagged the push.

Fix pushed: resolve head_sha from GET /repos/.../git/ref/heads/{head_ref} (and poll if it still equals pre_agent_head).

@fullsend-ai-review

fullsend-ai-review Bot commented Jul 15, 2026

Copy link
Copy Markdown

🤖 Review · ❌ Terminated · Started 4:12 PM UTC · Ended 4:23 PM UTC
Commit: 5cd495a · View workflow run →

@ascerra

ascerra commented Jul 15, 2026

Copy link
Copy Markdown
Contributor Author

Functional-tests (fix) green

Run: https://github.com/fullsend-ai/agents/actions/runs/29431325042
All judges at 1.0 (new_commit, expected_files, budgets). PR description updated with proof.

fullsend-ai-review[bot]

This comment was marked as outdated.

@fullsend-ai-review fullsend-ai-review Bot added ready-for-merge All reviewers approved — ready to merge and removed requires-manual-review Review requires human judgment labels Jul 15, 2026
@fullsend-ai-review

Copy link
Copy Markdown

🤖 Finished Review · ✅ Success · Started 4:12 PM UTC · Completed 4:23 PM UTC
Commit: 0889e1d · View workflow run →

@fullsend-ai-review

fullsend-ai-review Bot commented Jul 15, 2026

Copy link
Copy Markdown

🤖 Finished Review · ✅ Success · Started 4:54 PM UTC · Completed 5:06 PM UTC
Commit: 8b088ff · View workflow run →

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 and removed ready-for-merge All reviewers approved — ready to merge labels Jul 15, 2026
@fullsend-ai-review

fullsend-ai-review Bot commented Jul 15, 2026

Copy link
Copy Markdown

🤖 Review · ⚠️ Cancelled · Started 5:08 PM UTC · Ended 5:11 PM UTC
Commit: 5cd495a · View workflow run →

@ascerra

ascerra commented Jul 15, 2026

Copy link
Copy Markdown
Contributor Author

Dropped the eval artifact scrub commits from this branch — that fix lives alone in #184 so it isn’t duplicated. After #184 merges (and #177), rebase onto the updated base to pick it up.

@fullsend-ai-review

fullsend-ai-review Bot commented Jul 15, 2026

Copy link
Copy Markdown

🤖 Finished Review · ✅ Success · Started 5:12 PM UTC · Completed 5:26 PM UTC
Commit: 1540d4f · View workflow run →

fullsend-ai-review[bot]

This comment was marked as outdated.

@fullsend-ai-review fullsend-ai-review Bot added ready-for-merge All reviewers approved — ready to merge and removed requires-manual-review Review requires human judgment labels Jul 15, 2026
@ascerra
ascerra force-pushed the eval/code-functional-test branch from 92135ac to 54929aa Compare July 15, 2026 18:16
ascerra added a commit that referenced this pull request Jul 15, 2026
Scope PR-head checkout to fix only, move HUMAN_INSTRUCTION into case
input.yaml, harden PR capture with retries/null-safety, validate emit_env
names, and drop superpowers plan/spec docs from the PR.

Signed-off-by: Adam Scerra <ascerra@redhat.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Signed-off-by: Adam Scerra <ascerra@redhat.com>
@ascerra
ascerra force-pushed the eval/fix-functional-test branch from 1540d4f to 353e640 Compare July 15, 2026 18:16
@fullsend-ai-review

fullsend-ai-review Bot commented Jul 15, 2026

Copy link
Copy Markdown

🤖 Finished Review · ✅ Success · Started 6:17 PM UTC · Completed 6:30 PM UTC
Commit: 353e640 · View workflow run →

fullsend-ai-review[bot]

This comment was marked as outdated.

@fullsend-ai-review fullsend-ai-review Bot added ready-for-merge All reviewers approved — ready to merge and removed ready-for-merge All reviewers approved — ready to merge labels Jul 15, 2026

@maruiz93 maruiz93 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

11 findings (4 medium, 7 low) across eval scripts and fix eval config. 4 carry forward from #177 review comments.

Comment thread eval/scripts/run-fullsend.sh
Comment thread eval/scripts/run-fullsend.sh Outdated
Comment thread eval/fix/eval.yaml
Comment thread eval/scripts/capture-fixture.sh
Comment thread eval/scripts/capture-fixture.sh Outdated
Comment thread eval/scripts/capture-fixture.sh Outdated
Comment thread eval/scripts/capture-fixture.sh Outdated
Comment thread eval/fix/cases/001-human-fs-fix-add/annotations.yaml
Comment thread eval/fix/eval.yaml Outdated
Comment thread eval/scripts/run-fullsend.sh Outdated

@maruiz93 maruiz93 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Added some minor improvements

@ascerra
ascerra force-pushed the eval/code-functional-test branch from a0ecb06 to c62ca8a Compare July 20, 2026 19:41
ascerra and others added 8 commits July 20, 2026 15:45
Signed-off-by: Adam Scerra <ascerra@redhat.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Signed-off-by: Adam Scerra <ascerra@redhat.com>
Signed-off-by: Adam Scerra <ascerra@redhat.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Signed-off-by: Adam Scerra <ascerra@redhat.com>
Signed-off-by: Adam Scerra <ascerra@redhat.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Signed-off-by: Adam Scerra <ascerra@redhat.com>
Signed-off-by: Adam Scerra <ascerra@redhat.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Signed-off-by: Adam Scerra <ascerra@redhat.com>
Scope PR-head checkout to fix only, move HUMAN_INSTRUCTION into case
input.yaml, harden PR capture with retries/null-safety, validate emit_env
names, and drop superpowers plan/spec docs from the PR.

Signed-off-by: Adam Scerra <ascerra@redhat.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Signed-off-by: Adam Scerra <ascerra@redhat.com>
Local branch alias eval-pr-head caused post-fix.sh to push a new remote
branch instead of the PR head, so new_commit always failed.

Signed-off-by: Adam Scerra <ascerra@redhat.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Signed-off-by: Adam Scerra <ascerra@redhat.com>
gh pr view headRefOid can lag behind a successful post-fix push, which
made new_commit fail despite the branch tip moving. Prefer git refs API
and briefly poll when the tip still equals pre_agent_head.

Signed-off-by: Adam Scerra <ascerra@redhat.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Signed-off-by: Adam Scerra <ascerra@redhat.com>
Rebase is already on #177 tip. Retries for fix headRefName fetch; extract
resolve_head_sha with head_ref validation and poll budget comment; harden
retry_cmd (stderr on final attempt); wrap issue-branch gh calls; stagger
EVAL_TIMEOUT; drop redundant mktemp truncate; document shared judges and
fix_expectations.

Signed-off-by: Adam Scerra <ascerra@redhat.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
@ascerra
ascerra force-pushed the eval/fix-functional-test branch from 353e640 to ec1d206 Compare July 20, 2026 19:47
@fullsend-ai-review

fullsend-ai-review Bot commented Jul 20, 2026

Copy link
Copy Markdown

🤖 Finished Review · ✅ Success · Started 7:48 PM UTC · Completed 8:01 PM UTC
Commit: ec1d206 · View workflow run →

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

Labels

code-agent fix-agent ready-for-merge All reviewers approved — ready to merge

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add fix agent human /fs-fix functional eval

2 participants