Skip to content

fix(#6415): add fix-stage environment for GitLab dispatch - #6417

Merged
ggallen merged 1 commit into
mainfrom
agent/6415-gitlab-fix-review-body
Aug 20, 2026
Merged

fix(#6415): add fix-stage environment for GitLab dispatch#6417
ggallen merged 1 commit into
mainfrom
agent/6415-gitlab-fix-review-body

Conversation

@fullsend-ai-coder

@fullsend-ai-coder fullsend-ai-coder Bot commented Aug 20, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Add a STAGE=fix gated block in the GitLab agent template (fullsend-agent.yml) that pre-fetches the review body from the GitLab Notes API and exports all fix-stage environment variables required by the harness
  • Pre-fetch uses paginated Notes API queries, bot identity verification, defense-in-depth author checks, size validation (1 MB max), and non-empty validation for bot-triggered runs using is_bot from the event payload (not PIPELINE_SOURCE, since all GitLab fix dispatches are API-triggered)
  • Export all fix harness env vars: TARGET_BRANCH, TRIGGER_SOURCE, HUMAN_INSTRUCTION, FIX_ITERATION, PRE_AGENT_HEAD, REPO_FULL_NAME, MR_NUMBER, GITLAB_MR_URL, PUSH_TOKEN, PUSH_TOKEN_SOURCE, GIT_BOT_EMAIL
  • Gate human instruction extraction on non-bot triggers (matching reusable-fix.yml)
  • Paginate fix commit counting (up to 500 commits)
  • Guard GITLAB_MR_URL against MR_IID=0
  • Propagate MAX_REVIEW_BYTES named constant to the review-stage pre-fetch block for consistency
  • Add TestGitLabAgentTemplateFixReviewBodyPreFetch test covering all new fix-stage elements

Context

The fix agent was entirely non-functional on GitLab because the harness requires REVIEW_BODY_FILE via host_files and multiple env vars via env.runner, but the GitLab dispatch pipeline never set any of them. The GitHub reusable workflow (reusable-fix.yml) handles this correctly; this change adds the equivalent for GitLab using the Notes API and GitLab CI variables.

Testing

  • go test ./internal/scaffold/ -run TestGitLab — all 17 tests pass including the new TestGitLabAgentTemplateFixReviewBodyPreFetch
  • go vet ./internal/scaffold/ — clean
  • Secret scan — clean
  • Pre-commit hooks — all pass

Closes #6415

@fullsend-ai-coder
fullsend-ai-coder Bot requested a review from a team as a code owner August 20, 2026 16:16
@fullsend-ai-coder fullsend-ai-coder Bot added the ready-for-review Agent PR ready for human review label Aug 20, 2026
@ggallen
ggallen force-pushed the agent/6415-gitlab-fix-review-body branch from 87d59a9 to 8039bb8 Compare August 20, 2026 16:17
@fullsend-ai-review

fullsend-ai-review Bot commented Aug 20, 2026

Copy link
Copy Markdown

🤖 Finished Review · ✅ Success · Started 4:19 PM UTC · Completed 4:35 PM UTC

Commit: 8039bb8 · View workflow run →

@codecov

codecov Bot commented Aug 20, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@ggallen ggallen added the fullsend-no-fix Skip bot-triggered fix agent runs label Aug 20, 2026
@fullsend-ai-review

fullsend-ai-review Bot commented Aug 20, 2026

Copy link
Copy Markdown

Review

Findings

Low

  • [api-contract] internal/scaffold/fullsend-repo-gitlab/.gitlab/ci/fullsend-agent.yml:594 — The fix block exports MR_NUMBER but the GitHub equivalent (reusable-fix.yml line 362) exports PR_NUMBER. MR_NUMBER is not referenced anywhere in this codebase — the Go telemetry code in run.go reads PR_NUMBER as a fallback. The GITLAB_ISSUE_URL export (also set by this block) provides an alternative telemetry resolution path for non-zero MR IIDs. Verify that the external agents repo fix harness forge.gitlab block references MR_NUMBER (not PR_NUMBER).

  • [scope-alignment] internal/scaffold/fullsend-repo-gitlab/.gitlab/ci/fullsend-agent.yml:366 — The MAX_REVIEW_BYTES named constant extraction in the existing review-stage block is a minor refactor outside the strict scope of issue GitLab fix dispatch: pre-fetch review body and set REVIEW_BODY_FILE #6415. Sensible consistency improvement but tangential.

  • [naming-convention] internal/scaffold/fullsend-repo-gitlab/.gitlab/ci/fullsend-agent.yml:403 — Temporary variables in the fix block use _UPPER_CASE naming (_FIX_BOT_USERNAME, _IS_BOT_TRIGGER, etc.) while the single existing scoped temporary variable uses _lower_case with a namespace prefix (_fs_mr_iid). Minor divergence from the single existing precedent.

Previous run

Review

Findings

Critical

High

  • [breaking-api] internal/poll/dispatch.go:116 — The signedDispatchKeys list is reduced from 11 to 9 keys and the YAML template's HMAC_MESSAGE is updated to match. However, already-deployed templates in consumer repos verify with 11 keys — the HMAC_MESSAGE printf includes ORIGINATING_URL=%s\nREPO_FULL_NAME=%s. After the poller is upgraded, HMAC verification will fail with "HMAC verification failed — dispatch variables may be forged (fail-closed)" on all GitLab installations with FULLSEND_DISPATCH_SECRET configured that have not re-scaffolded. This finding is contingent on the critical findings above — if the dispatch variable removal is reverted, this issue disappears.
    Remediation: If the removal proceeds, deploy in two phases: first keep the keys in signedDispatchKeys as empty-value placeholders while the variables are no longer sent, then remove after re-scaffolding.

Medium

  • [stale-reference] internal/poll/dispatch.go:61REPO_FULL_NAME is removed from dispatch variables but internal/cli/run.go (resolveMintRepos) reads os.Getenv("REPO_FULL_NAME") as the fallback when MINT_REPOS is unset. The fix-stage block exports REPO_FULL_NAME="${CI_PROJECT_PATH}" but only inside STAGE=fix. Other stages (triage, code, review, retro) no longer receive REPO_FULL_NAME, breaking token minting unless MINT_REPOS is explicitly configured. See also: [scope-exceeded] finding at this location.

  • [accidental-removal] internal/scaffold/fullsend-repo-gitlab/.gitlab/ci/fullsend-agent.yml:293 — The RETRO_COMMENT extraction block is removed without replacement. The retro harness expects ${RETRO_COMMENT} in its env.sandbox configuration and its absence causes host variable RETRO_COMMENT is not set during env validation. See also: [scope-exceeded] finding at this location.

  • [scope-exceeded] internal/scaffold/fullsend-repo-gitlab/.gitlab/ci/fullsend-agent.yml:164 — The HMAC_MESSAGE format string removes ORIGINATING_URL and REPO_FULL_NAME. This is a necessary consequence of the dispatch variable removal — if that removal is reverted per the critical findings above, this change must also be reverted.

Low

  • [injection-prevention] internal/scaffold/fullsend-repo-gitlab/.gitlab/ci/fullsend-agent.yml:388MR_IID derived from CI_MERGE_REQUEST_IID or STATUS_IID is used in curl URL interpolations without explicit numeric validation. STATUS_IID is HMAC-signed and the pattern is pre-existing from the review stage — the HMAC signature provides adequate protection.

  • [naming-consistency] internal/scaffold/fullsend-repo-gitlab/.gitlab/ci/fullsend-agent.yml:440NOTE_AUTHOR_ID (no prefix) is used for the defense-in-depth author check, while _NOTE_AUTHOR_ID (underscore prefix) is used for trigger-source resolution. The scoping distinction is reasonable but creates a mixed convention within the fix-stage block.

  • [authorization-alignment] internal/scaffold/fullsend-repo-gitlab/.gitlab/ci/fullsend-agent.yml:379 — Fix-stage env vars (TARGET_BRANCH, TRIGGER_SOURCE, HUMAN_INSTRUCTION, FIX_ITERATION, etc.) beyond what issue GitLab fix dispatch: pre-fetch review body and set REVIEW_BODY_FILE #6415 explicitly lists are justified for functional parity with reusable-fix.yml.


Next steps:

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

Review

Findings

Medium

  • [scope-creep] internal/scaffold/fullsend-repo-gitlab/.gitlab/ci/fullsend-agent.yml:290 — The removal of the RETRO_COMMENT extraction block is outside the scope of issue GitLab fix dispatch: pre-fetch review body and set REVIEW_BODY_FILE #6415, which authorizes only fix-stage environment changes. This block was added by PR fix(#6418): pass ORIGINATING_URL and REPO_FULL_NAME in GitLab dispatch #6419 (merged the same day) to fix issue GitLab retro dispatch does not pass required env vars to pipeline #6418, making the retro agent functional on GitLab. Removing it reverses that fix and would break GitLab retro runs that depend on RETRO_COMMENT being set in the environment. The GitHub reusable workflows (reusable-dispatch.yml, reusable-retro.yml) still set RETRO_COMMENT, confirming it remains a required env var for the retro agent.
    Remediation: Restore the RETRO_COMMENT extraction block. It is unrelated to the fix-stage work authorized by GitLab fix dispatch: pre-fetch review body and set REVIEW_BODY_FILE #6415 and was intentionally added by the recently merged fix(#6418): pass ORIGINATING_URL and REPO_FULL_NAME in GitLab dispatch #6419.

  • [breaking-api] internal/scaffold/fullsend-repo-gitlab/.gitlab/ci/fullsend-agent.yml:167 — The HMAC dispatch signature is a cross-component contract between the Go poller (producer) and the shell verifier in consumer repos (scaffolded from this template). This PR changes the signed key set from 11 keys to 9 keys by removing ORIGINATING_URL and REPO_FULL_NAME. While the Go and shell sides are consistent within this PR, existing consumer repos scaffolded before this change still have the 11-key HMAC verifier. Once the updated poller deploys, those repos' HMAC verification will fail (fail-closed) until the consumer re-syncs by running fullsend init.
    Remediation: Document the required re-scaffolding in release notes, or coordinate deployment so consumer repos are re-scaffolded first.

Low


Next steps:

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

Review

Findings

Medium

  • [API contract / inconsistent value] internal/scaffold/fullsend-repo-gitlab/.gitlab/ci/fullsend-agent.yml:575PUSH_TOKEN_SOURCE is set to "bot-pat", a value that does not exist anywhere else in the codebase. The established GitLab value is "pat" (set by mintAgentToken in internal/cli/run.go). While PUSH_TOKEN_SOURCE appears to be primarily informational/passthrough, introducing a third value without evidence that consumers handle it could cause unexpected behavior in downstream harness consumers.
    Remediation: Change the value to "pat" to match the established convention: export PUSH_TOKEN_SOURCE="pat"

Low

  • [variable naming / underscore prefix convention] internal/scaffold/fullsend-repo-gitlab/.gitlab/ci/fullsend-agent.yml:396 — The fix block introduces underscore-prefixed local variables (_FIX_BOT_USERNAME, _IS_BOT_TRIGGER, etc.) while the review-stage block uses unprefixed variables (BOT_ID, REVIEW_NOTE, etc.). The blocks are gated by mutually exclusive STAGE checks so there is no runtime collision. The mixed prefixing is a minor readability nit; the underscore convention in the fix block is arguably an improvement.

  • [variable naming convention] internal/scaffold/fullsend-repo-gitlab/.gitlab/ci/fullsend-agent.yml:455 — The review block uses soft degradation for oversized bodies (truncate + warn), while the fix block exits with error (hard failure). This is an intentional behavioral difference matching GitHub reusable-fix.yml — a fix agent cannot operate without a review body.

  • [Novel env var with zero consumers] internal/scaffold/fullsend-repo-gitlab/.gitlab/ci/fullsend-agent.yml:581GITLAB_MR_URL and MR_NUMBER are exported but have zero references elsewhere in this codebase. These are presumably consumed by harness YAML files in the external agents repo.

  • [Error handling gap] internal/scaffold/fullsend-repo-gitlab/.gitlab/ci/fullsend-agent.yml:468 — When TARGET_BRANCH is resolved via the MR API (for API-dispatched runs), a curl failure silently falls back to CI_DEFAULT_BRANCH. A warning message would aid debugging. This mirrors the GitHub reusable-fix.yml fallback behavior.

  • [API path injection (defense-in-depth)] internal/scaffold/fullsend-repo-gitlab/.gitlab/ci/fullsend-agent.yml:466_NOTE_AUTHOR_ID from EVENT_PAYLOAD_B64 is interpolated into the Users API URL without explicit numeric validation. Risk is mitigated by bot identity check (mitigation docs: Add agent-compatible code problem document #1), HMAC signature verification (mitigation Add problem areas: Tekton pipeline review, migration path, multi-tenancy #2), GitLab server-side validation, curl -sf failure handling, and TRIGGER_SOURCE being informational only.

  • [error message convention] internal/scaffold/fullsend-repo-gitlab/.gitlab/ci/fullsend-agent.yml:442 — The review block silently sets provenance on author-mismatch (unverifiable-wrong-user), while the fix block emits a WARNING echo for the same scenario. The fix block's approach (explicit warning) is arguably better practice.

  • [variable reuse / BOT_RESPONSE coupling] internal/scaffold/fullsend-repo-gitlab/.gitlab/ci/fullsend-agent.yml:394 — The fix block references BOT_RESPONSE from the bot identity verification section ~280 lines earlier, creating a subtle cross-block data dependency. For parent_pipeline sources, BOT_RESPONSE is never set, so _FIX_BOT_USERNAME falls through to the BOT_RESP fallback path correctly.

  • [code organization] internal/scaffold/fullsend-repo-gitlab/.gitlab/ci/fullsend-agent.yml:381 — The fix and review blocks share substantial duplicated logic (bot ID resolution, Notes API pagination, author verification). The YAML CI script format lacks function extraction precedent in this codebase.

  • [scope-creep] internal/scaffold/fullsend-repo-gitlab/.gitlab/ci/fullsend-agent.yml:357 — The MAX_REVIEW_BYTES named constant extraction in the review-stage pre-fetch block is a minor refactor not part of the issue scope. Low-risk consistency improvement.

  • [provenance-warning] — Prior review context discarded: provenance validation failed (unverifiable-wrong-app). This review treats all findings as first-time assessments.

Previous run (4)

Review

Findings

Low

  • [naming-consistency] internal/scaffold/fullsend-repo-gitlab/.gitlab/ci/fullsend-agent.yml:445 — The fix-stage pre-fetch introduces a named constant MAX_REVIEW_BYTES=1048576 for the size limit, while the analogous review-stage pre-fetch (line 358) uses the literal 1048576 inline. This creates a mixed pattern between two blocks that otherwise mirror each other exactly.
    Remediation: Propagate the named constant to the review block for consistency, or use the inline literal in both. The named constant is clearer, so updating the review block is the preferred direction.

fullsend-ai-review[bot]

This comment was marked as outdated.

@fullsend-ai-review fullsend-ai-review Bot added the ready-for-merge All reviewers approved — ready to merge label Aug 20, 2026
@ggallen ggallen changed the title fix(#6415): pre-fetch review body for GitLab fix dispatch fix(#6415): add fix-stage environment for GitLab dispatch Aug 20, 2026
@ggallen
ggallen force-pushed the agent/6415-gitlab-fix-review-body branch from 8039bb8 to 553f939 Compare August 20, 2026 17:34
@fullsend-ai-review

fullsend-ai-review Bot commented Aug 20, 2026

Copy link
Copy Markdown

🤖 Finished Review · ✅ Success · Started 5:37 PM UTC · Completed 6:14 PM UTC

Commit: 553f939 · View workflow run →

@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 Aug 20, 2026
@ggallen
ggallen force-pushed the agent/6415-gitlab-fix-review-body branch from 553f939 to 8654e46 Compare August 20, 2026 18:18
@github-actions

github-actions Bot commented Aug 20, 2026

Copy link
Copy Markdown

Site preview

Preview: https://b8cb3e12-site.fullsend-ai.workers.dev

Commit: e3a7238a45201b595bb2bea837bcaeea65181314

@fullsend-ai-review

fullsend-ai-review Bot commented Aug 20, 2026

Copy link
Copy Markdown

🤖 Finished Review · ✅ Success · Started 6:20 PM UTC · Completed 6:56 PM UTC

Commit: 8654e46 · View workflow run →

fullsend-ai-review[bot]

This comment was marked as outdated.

@fullsend-ai-review fullsend-ai-review Bot removed the requires-manual-review Review requires human judgment label Aug 20, 2026
@ggallen
ggallen force-pushed the agent/6415-gitlab-fix-review-body branch from 8654e46 to e3a7238 Compare August 20, 2026 19:02
@fullsend-ai-review

fullsend-ai-review Bot commented Aug 20, 2026

Copy link
Copy Markdown

🤖 Finished Review · ✅ Success · Started 7:04 PM UTC · Completed 7:24 PM UTC

Commit: e3a7238 · View workflow run →

fullsend-ai-review[bot]

This comment was marked as outdated.

Wire all fix-stage environment variables into the GitLab CI
agent template (fullsend-agent.yml) for poller-dispatched fix
pipelines. Parallels the GitHub reusable-fix.yml contract.

Key changes:
- Pre-fetch review body from MR notes API with pagination
- Decode is_bot from EVENT_PAYLOAD_B64 (not PIPELINE_SOURCE)
- Resolve TRIGGER_SOURCE from event payload (bot username or
  note author), with numeric validation on note_author_id
- Extract HUMAN_INSTRUCTION from /fs-fix note body
- Count prior fix-agent commits with pagination (up to 500)
- Export all forge.gitlab env vars (REPO_FULL_NAME, MR_NUMBER,
  GITLAB_MR_URL, PUSH_TOKEN, PUSH_TOKEN_SOURCE, GIT_BOT_EMAIL)
- Guard GITLAB_MR_URL against MR_IID=0
- Set PUSH_TOKEN_SOURCE to "pat" (matching run.go convention)

Closes #6415

Signed-off-by: Greg Allen <ggallen@users.noreply.github.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Greg Allen <gallen@redhat.com>
@ggallen
ggallen force-pushed the agent/6415-gitlab-fix-review-body branch from e3a7238 to 1878f39 Compare August 20, 2026 19:31
@fullsend-ai-review

fullsend-ai-review Bot commented Aug 20, 2026

Copy link
Copy Markdown

🤖 Finished Review · ✅ Success · Started 7:33 PM UTC · Completed 7:50 PM UTC

Commit: 1878f39 · View workflow run →

@fullsend-ai-review
fullsend-ai-review Bot dismissed stale reviews from themself August 20, 2026 19:50

Superseded by updated review

@fullsend-ai-review fullsend-ai-review Bot added the ready-for-merge All reviewers approved — ready to merge label Aug 20, 2026
@ggallen
ggallen added this pull request to the merge queue Aug 20, 2026
Merged via the queue into main with commit ba690ac Aug 20, 2026
83 checks passed
@ggallen
ggallen deleted the agent/6415-gitlab-fix-review-body branch August 20, 2026 20:53
@fullsend-ai-retro

fullsend-ai-retro Bot commented Aug 20, 2026

Copy link
Copy Markdown

🤖 Finished Retro · ✅ Success · Started 8:55 PM UTC · Completed 9:10 PM UTC

Commit: 1878f39 · View workflow run →

@fullsend-ai-retro

Copy link
Copy Markdown

Retro: PR #6417 — add fix-stage environment for GitLab dispatch

Verdict: workflow went well. No novel improvement proposals — all identified opportunities map to existing open issues. Evidence for those issues is noted below.

Timeline

Time (UTC) Event
15:58 Issue #6415 filed by human — GitLab fix dispatch entirely non-functional (missing REVIEW_BODY_FILE)
16:04 Triage completed (6 min) — correctly identified high severity and root cause
16:16 Code agent completed (12 min) — produced PR #6417 with 280-line fix
16:35 Review #1 (run 32391134719): APPROVED with 1 low finding (naming consistency)
17:37–18:56 Reviews #2#3: intermediate commits introduced rebase artifacts — review agent dismissed its own approval and flagged critical regressions (removed RETRO_COMMENT block, reduced HMAC keys)
19:24 Review #4 (run 32406515997): found additional critical scope-exceeded issues in dispatch.go (removed ORIGINATING_URL, REPO_FULL_NAME, reduced signedDispatchKeys from 11→9)
19:30 Human reverted dispatch.go changes, restored all missing blocks
19:50 Review #5 (run 32409153544): APPROVED with 3 low findings
20:41 Human approved — no additional findings beyond what the agent surfaced
20:53 Merged

What went well

  1. Code agent quality: Initial commit was clean and approved on first review. The 280-line GitLab CI template addition with security considerations (HMAC, pagination, bot identity verification, size validation) was correctly implemented.
  2. Review agent caught real regressions: All critical/high findings were genuine — the removed RETRO_COMMENT block, dispatch variable deletions, and HMAC key reduction would have broken production GitLab deployments. Zero false positives at critical/high severity.
  3. Review self-correction: The agent correctly dismissed its own prior approval when new commits introduced regressions, preventing a stale approval from gating merge.
  4. Test coverage: Codecov confirmed all modified and coverable lines were covered. The new TestGitLabAgentTemplateFixReviewBodyPreFetch test validates all key strings in the fix-stage block.
  5. Autonomy readiness: On the final commit, the human review added zero findings beyond what the agent surfaced. The agent's 3 low findings were all acknowledged as valid observations. Strong evidence that the review agent's quality matches or exceeds human review for CI template changes.

What could go better (evidence for existing issues)

  1. Rebase artifacts drove 3 extra review rounds: The code agent's initial commit was clean. Subsequent human rebasing introduced regressions from a concurrent PR (#6419). This is further evidence for agents#144 (intent-coherence sub-agent should flag unrelated content removals as potential rebase artifacts) and agents#112 (detect when previously-fixed findings regress after a rebase).
  2. Review coverage gap between rounds: Review docs: Add codebase context problem document and trim CLAUDE.md #3 found issues only in fullsend-agent.yml, while Review Use AI to help formalise intent after rapid local prototyping #4 found additional critical issues in dispatch.go. This may indicate incomplete file coverage in a single review pass — evidence for agents#378 (detect and analyze file-level scope changes between review iterations). Uncertainty: dispatch.go changes may have been introduced between the two review commits rather than missed.
  3. Token cost from 5 review runs: Each review that found issues was finding real problems, but debouncing could have reduced the total from 5 to ~3 runs. Evidence for #4960 (debounce review runs on rapid force-pushes).
  4. Agent version mismatch: The code agent resolved fullsend-ai/agents at SHA d56f413 while the review agent used the config-pinned SHA 56e0a7b. Both ran within minutes of each other on the same repo state. This is direct evidence for #6386 (per-repo agent fallback fetches agents at floating version instead of installed workflow version).

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

Labels

fullsend-no-fix Skip bot-triggered fix agent runs ready-for-merge All reviewers approved — ready to merge ready-for-review Agent PR ready for human review

Projects

None yet

Development

Successfully merging this pull request may close these issues.

GitLab fix dispatch: pre-fetch review body and set REVIEW_BODY_FILE

1 participant