Skip to content
Open
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
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -55,5 +55,6 @@ script-test:
$(call run-timed,bash scripts/gitlint-forbidden-type-scope-test.sh)
$(call run-timed,bash .github/scripts/check-e2e-authorization-test.sh)
$(call run-timed,bash .github/scripts/select-eval-agents-test.sh)
$(call run-timed,python3 scripts/process-fix-result-test.py)

test: script-test
128 changes: 124 additions & 4 deletions scripts/post-review-test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -402,12 +402,16 @@ chmod +x "${MOCK_BIN}/gh"

cat > "${MOCK_BIN}/fullsend" <<MOCKEOF
#!/usr/bin/env bash
# Mock fullsend: log the call, consume stdin if --result - is used.
BODY=""
# Mock fullsend: log the call, consume stdin if --result - is used,
# and copy the result file so tests can inspect the body.
PREV=""
for arg in "\$@"; do
if [[ "\${arg}" == "-" ]] && [[ "\${PREV}" == "--result" ]]; then
BODY=\$(cat)
if [[ "\${PREV}" == "--result" ]]; then
if [[ "\${arg}" == "-" ]]; then
cat > "${TMPDIR}/last-result.json"
elif [[ -f "\${arg}" ]]; then
cp "\${arg}" "${TMPDIR}/last-result.json"
fi
fi
PREV="\${arg}"
done
Expand Down Expand Up @@ -719,6 +723,122 @@ run_label_test_no_pattern "no-op-skip-ready-for-merge-removal" \
'{"action":"approve","pr_number":99,"repo":"test-org/test-repo","head_sha":"abc123","body":"LGTM"}' \
"--remove-label ready-for-merge"

# ---------------------------------------------------------------------------
# Body-content tests: verify the assembled body passed to fullsend post-review
# ---------------------------------------------------------------------------

run_body_test() {
local test_name="$1"
local json_content="$2"
local expected_body_pattern="$3"

local run_dir="${TMPDIR}/run-${test_name}"
mkdir -p "${run_dir}/iteration-1/output"
echo "${json_content}" > "${run_dir}/iteration-1/output/agent-result.json"
: > "${GH_LOG}"
rm -f "${TMPDIR}/last-result.json"

local exit_code=0
# shellcheck disable=SC2030,SC2031
(
cd "${run_dir}"
export PATH="${MOCK_BIN}:${PATH}"
export REVIEW_TOKEN="fake-token"
export PR_NUMBER="99"
export REPO_FULL_NAME="test-org/test-repo"
bash "${POST_SCRIPT}"
) > "${TMPDIR}/stdout-${test_name}.log" 2>&1 || exit_code=$?

if [[ ${exit_code} -ne 0 ]]; then
echo "FAIL: ${test_name} — exit code ${exit_code}"
cat "${TMPDIR}/stdout-${test_name}.log"
FAILURES=$((FAILURES + 1))
return
fi

if [[ ! -f "${TMPDIR}/last-result.json" ]]; then
echo "FAIL: ${test_name} — no result file captured"
FAILURES=$((FAILURES + 1))
return
fi

local body
body="$(jq -r '.body' "${TMPDIR}/last-result.json")"
if ! echo "${body}" | grep -qF "${expected_body_pattern}"; then
echo "FAIL: ${test_name} — expected body pattern '${expected_body_pattern}' not found"
echo "Actual body:"
echo "${body}"
FAILURES=$((FAILURES + 1))
return
fi

echo "PASS: ${test_name}"
}

run_body_count_test() {
local test_name="$1"
local json_content="$2"
local pattern="$3"
local expected_count="$4"

local run_dir="${TMPDIR}/run-${test_name}"
mkdir -p "${run_dir}/iteration-1/output"
echo "${json_content}" > "${run_dir}/iteration-1/output/agent-result.json"
: > "${GH_LOG}"
rm -f "${TMPDIR}/last-result.json"

local exit_code=0
# shellcheck disable=SC2030,SC2031
(
cd "${run_dir}"
export PATH="${MOCK_BIN}:${PATH}"
export REVIEW_TOKEN="fake-token"
export PR_NUMBER="99"
export REPO_FULL_NAME="test-org/test-repo"
bash "${POST_SCRIPT}"
) > "${TMPDIR}/stdout-${test_name}.log" 2>&1 || exit_code=$?

if [[ ${exit_code} -ne 0 ]]; then
echo "FAIL: ${test_name} — exit code ${exit_code}"
cat "${TMPDIR}/stdout-${test_name}.log"
FAILURES=$((FAILURES + 1))
return
fi

if [[ ! -f "${TMPDIR}/last-result.json" ]]; then
echo "FAIL: ${test_name} — no result file captured"
FAILURES=$((FAILURES + 1))
return
fi

local body
body="$(jq -r '.body' "${TMPDIR}/last-result.json")"
local actual_count
actual_count="$(echo "${body}" | grep -cF -- "${pattern}" || true)"

if [[ "${actual_count}" -ne "${expected_count}" ]]; then
echo "FAIL: ${test_name} — expected ${expected_count} occurrences of '${pattern}', found ${actual_count}"
echo "Actual body:"
echo "${body}"
FAILURES=$((FAILURES + 1))
return
fi

echo "PASS: ${test_name}"
}

# request-changes + label_actions → body has label notice (---) AND action-hints footer (---)
LABEL_PLUS_HINTS_JSON='{"action":"request-changes","pr_number":99,"repo":"test-org/test-repo","head_sha":"abc123","body":"Issues found","findings":[{"severity":"high","category":"bug","file":"main.go","description":"nil deref"}],"label_actions":{"reason":"Touches API surface.","actions":[{"action":"add","label":"area/api"}]}}'

run_body_count_test "label-actions-plus-action-hints-two-hrs" \
"${LABEL_PLUS_HINTS_JSON}" "---" "2"

run_body_test "label-actions-plus-action-hints-has-labels-section" \
"${LABEL_PLUS_HINTS_JSON}" "**Labels:** Touches API surface."

run_body_test "label-actions-plus-action-hints-has-next-steps" \
"${LABEL_PLUS_HINTS_JSON}" "**Next steps:**"

# --- Summary ---

echo ""
Expand Down
14 changes: 14 additions & 0 deletions scripts/post-review.sh
Original file line number Diff line number Diff line change
Expand Up @@ -308,6 +308,20 @@ if [[ "${HAS_LABEL_ACTIONS}" == "true" ]]; then
fi
fi

# ---------------------------------------------------------------------------
# Append action-hints footer (request-changes only)
# ---------------------------------------------------------------------------

if [ "${ACTION}" = "request-changes" ]; then
ACTION_HINTS_FOOTER=$'\n\n---\n**Next steps:**\n- `/fs-fix` — agent addresses review findings automatically\n- `/fs-fix <your instruction>` — agent fixes with your specific guidance\n- Push commits directly — review re-runs automatically on push\n- `/fs-fix-stop` — disable automatic fix runs for this PR'
FOOTER_RESULT=$(mktemp)
CLEANUP_FILES+=("${FOOTER_RESULT}")
jq --arg footer "${ACTION_HINTS_FOOTER}" \
'.body = (.body + $footer)' \
"${RESULT_FILE}" > "${FOOTER_RESULT}"
RESULT_FILE="${FOOTER_RESULT}"
fi

# ---------------------------------------------------------------------------
# Post the review. Exit code 10 = stale-head: the PR HEAD moved after the
# agent reviewed it. When this happens, post a /fs-review comment to
Expand Down
4 changes: 4 additions & 0 deletions scripts/post-triage-test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,10 @@ run_test "sufficient-with-info-gaps-fails" \
"" \
"true"

run_test "sufficient-appends-action-hints-footer" \
'{"action":"sufficient","reasoning":"all clear","clarity_scores":{"symptom":0.9,"cause":0.85,"reproduction":0.9,"impact":0.8,"overall":0.87},"triage_summary":{"title":"Fix crash on save","severity":"high","category":"bug","problem":"Crash","root_cause_hypothesis":"Buffer overflow","reproduction_steps":["step 1"],"environment":"Linux","impact":"All users","recommended_fix":"Fix buffer","proposed_test_case":"test_save_crash"},"comment":"## Triage Summary\n\nThis is ready."}' \
"/fs-code"

run_test "sufficient-removes-blocked-label" \
'{"action":"sufficient","reasoning":"all clear","clarity_scores":{"symptom":0.9,"cause":0.85,"reproduction":0.9,"impact":0.8,"overall":0.87},"triage_summary":{"title":"Fix crash on save","severity":"high","category":"bug","problem":"Crash","root_cause_hypothesis":"Buffer overflow","reproduction_steps":["step 1"],"environment":"Linux","impact":"All users","recommended_fix":"Fix buffer","proposed_test_case":"test_save_crash","information_gaps":[]},"comment":"## Triage Summary\n\nThis is ready."}' \
"gh api repos/test-org/test-repo/issues/42/labels/blocked -X DELETE --silent"
Expand Down
11 changes: 11 additions & 0 deletions scripts/post-triage.sh
Original file line number Diff line number Diff line change
Expand Up @@ -442,6 +442,17 @@ if [[ -n "${DEFERRED_LABEL}" ]]; then
add_label "${DEFERRED_LABEL}"
fi

# --- Append action-hints footer (sufficient only) ---

if [[ "${ACTION}" == "sufficient" ]]; then
Comment thread
rh-hemartin marked this conversation as resolved.
Comment thread
rh-hemartin marked this conversation as resolved.
Comment thread
rh-hemartin marked this conversation as resolved.
COMMENT="${COMMENT}
Comment thread
rh-hemartin marked this conversation as resolved.

---
**Next steps:**
- \`/fs-code\` — agent creates a PR to implement this issue
- \`/fs-code <your instruction>\` — agent implements with your specific guidance"
fi

# --- Post comment ---

echo "Posting comment..."
Expand Down
Loading
Loading