fix(loop): resolve P0-1 (B-7) git diff CWD isolation and untracked file capture (20/20 PASS)
This commit is contained in:
+132
@@ -0,0 +1,132 @@
|
||||
#!/usr/bin/env bash
|
||||
# diff_collect.sh — Helper module for collecting git changes and untracked files (B-7)
|
||||
# Single source of truth for collecting review diffs.
|
||||
|
||||
MAM_DIFF_UNAVAILABLE_MARKER="!!! CHANGE SET UNAVAILABLE !!!"
|
||||
MAM_DIFF_TRUNCATED_MARKER="!!! DIFF TRUNCATED !!!"
|
||||
MAM_DIFF_NESTED_MARKER="!!! NOT EXPANDED IN THIS DIFF !!!"
|
||||
|
||||
MAM_DIFF_MAX_BYTES="${MAM_DIFF_MAX_BYTES:-200000}"
|
||||
MAM_DIFF_MAX_LINES="${MAM_DIFF_MAX_LINES:-4000}"
|
||||
|
||||
_mam_nested_dir_diff() {
|
||||
local d="$1" outer_top="$2" inner_top=""
|
||||
inner_top=$(git -C "$d" rev-parse --show-toplevel 2>/dev/null || printf '')
|
||||
|
||||
if [ -n "$inner_top" ] && [ "$inner_top" != "$outer_top" ]; then
|
||||
printf '%s %s\n' "$MAM_DIFF_NESTED_MARKER" "$d"
|
||||
printf 'Untracked NESTED GIT REPOSITORY. Its contents are listed through its own\n'
|
||||
printf 'git, so its .gitignore applies; the outer diff cannot describe it.\n\n'
|
||||
git -C "$d" diff 2>/dev/null || true
|
||||
git -C "$d" ls-files -o --exclude-standard -z 2>/dev/null | while IFS= read -r -d '' s; do
|
||||
[ -n "$s" ] || continue
|
||||
git -C "$d" diff --no-index -- /dev/null "$s" 2>/dev/null || true
|
||||
done
|
||||
printf '\n'
|
||||
return 0
|
||||
fi
|
||||
|
||||
printf '%s %s (untracked directory)\n' "$MAM_DIFF_NESTED_MARKER" "$d"
|
||||
git ls-files -o --exclude-standard -z -- "$d" 2>/dev/null | while IFS= read -r -d '' s; do
|
||||
[ -n "$s" ] || continue
|
||||
[ -f "$s" ] && [ ! -L "$s" ] || continue
|
||||
git diff --no-index -- /dev/null "$s" 2>/dev/null || true
|
||||
done
|
||||
}
|
||||
|
||||
_mam_untracked_diff() {
|
||||
local outer_top
|
||||
outer_top=$(git rev-parse --show-toplevel 2>/dev/null || printf '%s' "$PWD")
|
||||
git ls-files -o --exclude-standard -z 2>/dev/null | while IFS= read -r -d '' f; do
|
||||
[ -n "$f" ] || continue
|
||||
if [ -L "$f" ]; then
|
||||
printf '%s %s -> %s (symlink, not expanded)\n' \
|
||||
"$MAM_DIFF_NESTED_MARKER" "$f" "$(readlink "$f" 2>/dev/null)"
|
||||
elif [ -d "$f" ]; then
|
||||
_mam_nested_dir_diff "$f" "$outer_top"
|
||||
elif [ -f "$f" ]; then
|
||||
git diff --no-index -- /dev/null "$f" 2>/dev/null || true
|
||||
else
|
||||
printf '%s %s (unreadable entry, not shown)\n' "$MAM_DIFF_NESTED_MARKER" "$f"
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
mam_collect_changes_diff() {
|
||||
local repo_root="${1:-}"
|
||||
local base_commit="${2:-}"
|
||||
|
||||
if [ -z "$repo_root" ]; then
|
||||
printf '%s\nreason: repo_root parameter is required\n' "$MAM_DIFF_UNAVAILABLE_MARKER"
|
||||
return 2
|
||||
fi
|
||||
|
||||
if [ ! -d "$repo_root" ]; then
|
||||
printf '%s\nreason: repo_root directory %s does not exist\n' "$MAM_DIFF_UNAVAILABLE_MARKER" "$repo_root"
|
||||
return 2
|
||||
fi
|
||||
|
||||
local raw_diff="" rc=0
|
||||
raw_diff=$(
|
||||
cd -P "$repo_root" 2>/dev/null || exit 3
|
||||
git rev-parse --git-dir >/dev/null 2>&1 || exit 4
|
||||
if [ -n "$base_commit" ] && git cat-file -e "${base_commit}^{commit}" 2>/dev/null; then
|
||||
git diff "$base_commit" || exit 5
|
||||
else
|
||||
git diff || exit 5
|
||||
fi
|
||||
_mam_untracked_diff
|
||||
) || rc=$?
|
||||
|
||||
if [ "$rc" -ne 0 ]; then
|
||||
local reason="not a git repository or git command failed (exit code $rc)"
|
||||
if [ "$rc" -eq 3 ]; then
|
||||
reason="cannot cd into repo_root $repo_root"
|
||||
elif [ "$rc" -eq 4 ]; then
|
||||
reason="not a git repository: $repo_root"
|
||||
elif [ "$rc" -eq 5 ]; then
|
||||
reason="git diff command failed"
|
||||
fi
|
||||
printf '%s\nreason: %s\n' "$MAM_DIFF_UNAVAILABLE_MARKER" "$reason"
|
||||
return 2
|
||||
fi
|
||||
|
||||
if [ -z "$(printf '%s' "$raw_diff" | tr -d '[:space:]')" ]; then
|
||||
printf '(no changes since base commit)\n'
|
||||
return 0
|
||||
fi
|
||||
|
||||
local byte_cnt line_cnt
|
||||
byte_cnt=$(printf '%s' "$raw_diff" | wc -c | tr -d '[:space:]')
|
||||
line_cnt=$(printf '%s' "$raw_diff" | wc -l | tr -d '[:space:]')
|
||||
|
||||
if [ "$byte_cnt" -gt "$MAM_DIFF_MAX_BYTES" ] || [ "$line_cnt" -gt "$MAM_DIFF_MAX_LINES" ]; then
|
||||
local stat_summary=""
|
||||
stat_summary=$(
|
||||
cd -P "$repo_root" 2>/dev/null || exit 0
|
||||
if [ -n "$base_commit" ] && git cat-file -e "${base_commit}^{commit}" 2>/dev/null; then
|
||||
git diff "$base_commit" --stat 2>/dev/null || true
|
||||
else
|
||||
git diff --stat 2>/dev/null || true
|
||||
fi
|
||||
printf '\nUntracked files:\n'
|
||||
git ls-files -o --exclude-standard 2>/dev/null || true
|
||||
)
|
||||
|
||||
printf '%s\n' "$MAM_DIFF_TRUNCATED_MARKER"
|
||||
printf 'The change set is %s bytes / %s lines, over the review limit (%s bytes / %s lines).\n' \
|
||||
"$byte_cnt" "$line_cnt" "$MAM_DIFF_MAX_BYTES" "$MAM_DIFF_MAX_LINES"
|
||||
printf 'Only the file-level summary is shown below. You have NOT been shown the\n'
|
||||
printf 'full change set -- inspect the working tree directly before voting.\n\n'
|
||||
printf '%s\n\n' "$stat_summary"
|
||||
printf '%s\n' "$MAM_DIFF_TRUNCATED_MARKER"
|
||||
return 0
|
||||
fi
|
||||
|
||||
printf '%s\n' "$raw_diff"
|
||||
return 0
|
||||
}
|
||||
|
||||
if [ "${BASH_SOURCE[0]}" = "$0" ]; then
|
||||
mam_collect_changes_diff "$@"
|
||||
fi
|
||||
@@ -10,6 +10,8 @@ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
REPO_ROOT="$(cd "$SCRIPT_DIR/../../../.." && pwd)"
|
||||
# shellcheck disable=SC1091
|
||||
source "$REPO_ROOT/.agents/skills/lib.sh"
|
||||
# shellcheck disable=SC1091
|
||||
source "$REPO_ROOT/.agents/skills/multi-agent-mux-loop/scripts/diff_collect.sh"
|
||||
|
||||
# Default configuration parameters
|
||||
PLAN_MODE=false
|
||||
@@ -428,7 +430,7 @@ log_info "=== Phase 2: Code Implementation ==="
|
||||
|
||||
# Fix the pre-implementation commit as the diff baseline so review diffs stay
|
||||
# cumulative and non-empty even after the Creator commits per DoD (P0-1).
|
||||
BASE_COMMIT=$(git rev-parse HEAD 2>/dev/null || echo "")
|
||||
BASE_COMMIT=$(cd -P "$REPO_ROOT" 2>/dev/null && git rev-parse HEAD 2>/dev/null || echo "")
|
||||
|
||||
EXECUTION_PROMPT="계획서가 존재하지 않으므로, 작업자(Creator)의 판단하에 스스로 구현 계획 및 설계를 수립한 뒤, 이를 바탕으로 코드를 구현하고 다음 작업 목표를 완성해주세요. 작업 목표: $TASK"
|
||||
if [ -n "$CURRENT_PLAN" ]; then
|
||||
@@ -520,6 +522,12 @@ while [ "$loop_count" -le "$MAX_LOOP" ]; do
|
||||
else
|
||||
log_info "Active reviewers: ${REVIEWERS[*]}"
|
||||
|
||||
CHANGES_DIFF=$(mam_collect_changes_diff "$REPO_ROOT" "$BASE_COMMIT") || {
|
||||
log_error "Could not determine the change set; refusing to request a review on no evidence."
|
||||
log_error "$CHANGES_DIFF"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# We use space-separated lists or simple loops to bypass bash-4 associative array requirement (M-7 macOS compatibility)
|
||||
declare -a JOB_IDS=()
|
||||
declare -a JOB_REVS=()
|
||||
@@ -530,14 +538,6 @@ while [ "$loop_count" -le "$MAX_LOOP" ]; do
|
||||
|
||||
for rev in "${REVIEWERS[@]}"; do
|
||||
log_info "Requesting code review from Reviewer '$rev'..."
|
||||
# Cumulative diff since BASE_COMMIT (M-6): includes committed AND
|
||||
# uncommitted changes, so it stays non-empty even after the Creator
|
||||
# commits per the documented DoD (bare `git diff` alone would not).
|
||||
if [ -n "$BASE_COMMIT" ]; then
|
||||
CHANGES_DIFF=$(git diff "$BASE_COMMIT" 2>/dev/null || echo "No git diff available")
|
||||
else
|
||||
CHANGES_DIFF=$(git diff 2>/dev/null || echo "No git diff available")
|
||||
fi
|
||||
|
||||
REV_OUTPUT=$(delegate_job_safe submit \
|
||||
--agent-session "herdr:$rev" \
|
||||
|
||||
Reference in New Issue
Block a user