Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions internal/harness/scaffold_integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -287,9 +287,9 @@ func TestLoadRaw_GeneratedWrapperFormat(t *testing.T) {
}

// TestResolveForge_ScaffoldRunnerEnvMerge verifies that forge resolution
// produces the expected merged runner_env for each scaffold template, with
// both top-level (platform-neutral) and forge.github (platform-specific)
// keys present in the final merged state.
// produces the expected merged env.runner (or legacy runner_env) for each
// scaffold template, with both top-level (platform-neutral) and
// forge.github (platform-specific) keys present in the final merged state.
func TestResolveForge_ScaffoldRunnerEnvMerge(t *testing.T) {
dir := t.TempDir()
harnessDir := extractScaffoldHarnessDir(t, dir)
Expand Down
51 changes: 0 additions & 51 deletions internal/scaffold/fullsend-repo/env/fix-agent.env
Original file line number Diff line number Diff line change
@@ -1,54 +1,3 @@
export PR_NUMBER="${PR_NUMBER}"
export REPO_FULL_NAME="${REPO_FULL_NAME}"
export TRIGGER_SOURCE="${TRIGGER_SOURCE}"
export HUMAN_INSTRUCTION="${HUMAN_INSTRUCTION}"
export FIX_ITERATION="${FIX_ITERATION}"

# GH_TOKEN in the sandbox is a READ-ONLY scoped app installation token
# (contents:read, issues:read, pull_requests:read). Set by
# setup-agent-env.sh from FIX_GH_TOKEN. This token CANNOT push code
# or create PRs — the read-only scope is the actual enforcement layer.
# The separate write-enabled PUSH_TOKEN (runner_env) never enters the sandbox.
export GH_TOKEN="${GH_TOKEN}"

# Author name is "fullsend-fix" (not "fullsend-code") so fix-agent
# commits are distinguishable for iteration counting. Both agents share
# the same GitHub App (coder role), so GIT_BOT_EMAIL resolves to the
# same bot noreply address. This makes the Probot DCO app auto-exempt
# agent commits (author.type === "Bot").
export GIT_AUTHOR_NAME="fullsend-fix"
export GIT_AUTHOR_EMAIL="${GIT_BOT_EMAIL}"
export GIT_COMMITTER_NAME="fullsend-fix"
export GIT_COMMITTER_EMAIL="${GIT_BOT_EMAIL}"

# Retry budget — the agent re-runs secret scan + tests on failure.
# Pre-commit is capped at 2 runs total (not per retry).
export MAX_RETRIES=1

# Hard timeout for the sandbox session in seconds. Must match
# timeout_minutes in harness/fix.yaml.
export TIMEOUT_SECONDS=1500

# Strategy escalation: after this many fix iterations, the agent should
# try a fundamentally different approach.
export STRATEGY_ESCALATION_THRESHOLD=3

# Iteration caps: bot-triggered runs (review→fix loop) have a tighter cap
# than human-triggered runs (/fix commands). When the iteration count
# approaches the bot cap, the 'needs-human' label is added and a human can
# still direct the agent with /fix up to ITERATION_CAP_HUMAN total iterations
# (bot + human combined).
export ITERATION_CAP=5
export ITERATION_CAP_HUMAN=10

# Go toolchain — PATH is set in the sandbox image via Containerfile ENV.
# Do NOT set PATH here: this file uses expand: true (harness host_files), so
# ${PATH} would be replaced with the GitHub Actions runner's PATH by
# os.ExpandEnv, clobbering /sandbox/workspace/bin and breaking sandbox-local
# binaries. See code-agent.env lines 27-33 for the full explanation.
export GOPATH="/sandbox/go"
export GOMODCACHE="/sandbox/go/pkg/mod"

# SSL certs — same workaround as code agent for OpenShell TLS termination.
if [ -f /etc/openshell-tls/ca-bundle.pem ]; then
export GIT_SSL_CAINFO=/etc/openshell-tls/ca-bundle.pem
Expand Down
51 changes: 36 additions & 15 deletions internal/scaffold/fullsend-repo/harness/fix.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -42,25 +42,46 @@ host_files:
skills:
- skills/fix-review

runner_env:
TARGET_BRANCH: "${TARGET_BRANCH}"
TRIGGER_SOURCE: "${TRIGGER_SOURCE}"
HUMAN_INSTRUCTION: "${HUMAN_INSTRUCTION}"
FIX_ITERATION: "${FIX_ITERATION}"
REVIEW_BODY_FILE: "${REVIEW_BODY_FILE}"
PRE_AGENT_HEAD: "${PRE_AGENT_HEAD}"
FULLSEND_OUTPUT_SCHEMA: ${FULLSEND_DIR}/schemas/fix-result.schema.json
FULLSEND_OUTPUT_FILE: fix-result.json
env:
runner:
TARGET_BRANCH: "${TARGET_BRANCH}"
TRIGGER_SOURCE: "${TRIGGER_SOURCE}"
HUMAN_INSTRUCTION: "${HUMAN_INSTRUCTION}"
FIX_ITERATION: "${FIX_ITERATION}"
REVIEW_BODY_FILE: "${REVIEW_BODY_FILE}"
PRE_AGENT_HEAD: "${PRE_AGENT_HEAD}"
FULLSEND_OUTPUT_SCHEMA: ${FULLSEND_DIR}/schemas/fix-result.schema.json
FULLSEND_OUTPUT_FILE: fix-result.json
sandbox:
MAX_RETRIES: "1"

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

[medium] scope-creep

The PR moves hardcoded config constants (MAX_RETRIES, TIMEOUT_SECONDS, STRATEGY_ESCALATION_THRESHOLD, ITERATION_CAP, ITERATION_CAP_HUMAN, GOPATH, GOMODCACHE) from fix-agent.env into env.sandbox. ADR 0055 Phase 2 authorizes moving 'simple passthrough vars' but these are hardcoded constants, not passthroughs from the host environment.

TIMEOUT_SECONDS: "1500"
STRATEGY_ESCALATION_THRESHOLD: "3"
ITERATION_CAP: "5"
ITERATION_CAP_HUMAN: "10"
GOPATH: "/sandbox/go"
GOMODCACHE: "/sandbox/go/pkg/mod"

timeout_minutes: 25

forge:
github:
pre_script: scripts/pre-fix.sh
post_script: scripts/post-fix.sh
runner_env:
PUSH_TOKEN: "${PUSH_TOKEN}"
PUSH_TOKEN_SOURCE: "${PUSH_TOKEN_SOURCE}"
REPO_FULL_NAME: "${REPO_FULL_NAME}"
PR_NUMBER: "${PR_NUMBER}"
REPO_DIR: "${GITHUB_WORKSPACE}/target-repo"
env:
runner:
PUSH_TOKEN: "${PUSH_TOKEN}"
PUSH_TOKEN_SOURCE: "${PUSH_TOKEN_SOURCE}"
REPO_FULL_NAME: "${REPO_FULL_NAME}"
PR_NUMBER: "${PR_NUMBER}"
REPO_DIR: "${GITHUB_WORKSPACE}/target-repo"
sandbox:
PR_NUMBER: "${PR_NUMBER}"
REPO_FULL_NAME: "${REPO_FULL_NAME}"
TRIGGER_SOURCE: "${TRIGGER_SOURCE}"
HUMAN_INSTRUCTION: "${HUMAN_INSTRUCTION}"
FIX_ITERATION: "${FIX_ITERATION}"
GH_TOKEN: "${GH_TOKEN}"
GIT_AUTHOR_NAME: "fullsend-fix"
GIT_AUTHOR_EMAIL: "${GIT_BOT_EMAIL}"
GIT_COMMITTER_NAME: "fullsend-fix"
GIT_COMMITTER_EMAIL: "${GIT_BOT_EMAIL}"
Loading