diff --git a/harnesses/contexts/agent-repo/v1/finalize.sh b/harnesses/contexts/agent-repo/v1/finalize.sh index 1fbc69a..a10d084 100644 --- a/harnesses/contexts/agent-repo/v1/finalize.sh +++ b/harnesses/contexts/agent-repo/v1/finalize.sh @@ -270,25 +270,37 @@ fi # appear in the diff. Catches the inverse: an agent silently destroying or # refactoring files outside the task scope (real incident: 2026-05-08 task # 4a2f2988 — agent stripped 9 unrelated functions; gotchas item 17/21). +# +# Whole block runs with set +e (and pipefail off) to ensure no diagnostic +# pipeline failure aborts finalize before metadata can be written. We +# explicitly check exit codes where they matter. DIFF_VERIFIED=true DIFF_MISMATCH="" DIFF_SUMMARY="" +set +eo pipefail if [ -d /workspace/reference/main/.git ]; then - # All files actually changed in the agent's commit (vs upstream HEAD). - REF_HEAD=$(git -C /workspace/reference/main rev-parse HEAD 2>/dev/null || echo "") + REF_HEAD=$(git -C /workspace/reference/main rev-parse HEAD 2>/dev/null) if [ -n "$REF_HEAD" ]; then - # Files modified/added/deleted by this commit. - DIFF_SUMMARY=$(git diff --name-only "$REF_HEAD"..HEAD 2>/dev/null | tr '\n' ',' | sed 's/,$//') + # Files modified/added/deleted by the agent vs the upstream HEAD seed. + # Use git diff (working-tree style) plus committed changes — the + # agent commits via finalize.sh later, so the diff against REF_HEAD + # reflects total scope. `|| true` belt-and-braces against unreachable + # SHAs (e.g., if init.sh fell back to fork main without seeding from + # upstream). + DIFF_RAW=$(git diff --name-only "$REF_HEAD"..HEAD 2>/dev/null || true) + # If the .. range fails (rev-parse error) the substitution returns "". + # Fall back to the simpler diff against working-tree HEAD-1 (no good + # answer; just emit empty). + DIFF_SUMMARY=$(printf '%s\n' "$DIFF_RAW" | tr '\n' ',' | sed 's/,$//' || true) - # Required files must each appear in DIFF_SUMMARY. if [ -n "${AGENT_EXPECTED_CHANGED_FILES:-}" ]; then echo "Verifying required changed files: $AGENT_EXPECTED_CHANGED_FILES" IFS=',' read -ra _REQUIRED <<< "$AGENT_EXPECTED_CHANGED_FILES" - for required in "${_REQUIRED[@]}"; do + for required in "${_REQUIRED[@]:-}"; do required="${required#"${required%%[![:space:]]*}"}" required="${required%"${required##*[![:space:]]}"}" [ -z "$required" ] && continue - if ! echo ",$DIFF_SUMMARY," | grep -qF ",$required,"; then + if ! printf ',%s,' "$DIFF_SUMMARY" | grep -qF ",$required,"; then echo "ERROR: Required change to '$required' missing from agent's diff" DIFF_VERIFIED=false DIFF_MISMATCH="$DIFF_MISMATCH missing:$required" @@ -296,15 +308,14 @@ if [ -d /workspace/reference/main/.git ]; then done fi - # Forbidden files must NOT appear in DIFF_SUMMARY. if [ -n "${AGENT_FORBIDDEN_CHANGED_FILES:-}" ]; then echo "Verifying forbidden files unchanged: $AGENT_FORBIDDEN_CHANGED_FILES" IFS=',' read -ra _FORBIDDEN <<< "$AGENT_FORBIDDEN_CHANGED_FILES" - for forbidden in "${_FORBIDDEN[@]}"; do + for forbidden in "${_FORBIDDEN[@]:-}"; do forbidden="${forbidden#"${forbidden%%[![:space:]]*}"}" forbidden="${forbidden%"${forbidden##*[![:space:]]}"}" [ -z "$forbidden" ] && continue - if echo ",$DIFF_SUMMARY," | grep -qF ",$forbidden,"; then + if printf ',%s,' "$DIFF_SUMMARY" | grep -qF ",$forbidden,"; then echo "ERROR: Forbidden file '$forbidden' was modified by agent" DIFF_VERIFIED=false DIFF_MISMATCH="$DIFF_MISMATCH forbidden:$forbidden" @@ -321,6 +332,7 @@ if [ -d /workspace/reference/main/.git ]; then else echo "Note: /workspace/reference/main not present; skipping AR-21 diff verification" fi +set -eo pipefail # AR-19: Push with retry — attempt up to PUSH_RETRIES+1 times (default 2: initial + 1 retry) echo "Pushing branch $BRANCH to $REPO_URL..."