feat(agent-ops): 테스트 라우팅 wrapper를 추가한다

This commit is contained in:
toki 2026-06-10 19:20:21 +09:00
parent a2d05ddb9b
commit c10d83ed4c
10 changed files with 1368 additions and 11 deletions

View file

@ -205,3 +205,26 @@ tools/check_proto_sync.sh
- `--route full` + `docs_only=no`이면 full functional periodic 발동. `performance-full`/`stability-full` 같은 nightly-pending 항목은 별도 기록만 하고 실행하지 않음.
- `run_full_test.sh --dry-run`은 실행 전 보고 전용이다. `### Nightly pending (미실행, PASS 아님)` 항목은 20:00 이후 별도 실행 후보이며 dry-run 또는 daytime full route의 PASS 근거가 아니다.
- `run_full_test.sh`는 classifier -> recommended 확인 -> matrix 실행 workflow를 실행한다.
## user-entrypoint route 정책
### 실행 wrapper (non-dry-run 포함)
| 요청 | 실행 entrypoint | 동작 |
|------|----------------|------|
| `테스트 해봐` | `run_test_by_change.sh --route auto` | dry-run으로 후보 보고 → recommended 항목 실행 → 결과 record 경로 기록. skipped/nightly-pending은 실행 안 함 |
| `속도 테스트 해봐` | `run_speed_test.sh` | dry-run으로 speed 후보 보고 → performance-quick recommended면 `run_performance.sh --quick` 실행. nightly-pending full은 후보 command만 기록 |
| `안정성 테스트 해봐` | `run_stability_test.sh` | dry-run으로 stability 후보 보고 → stability-quick recommended면 `run_stress.sh --quick` hard gate 실행. nightly-pending full은 후보 command만 기록 |
### dry-run 전용 보고
- `테스트 해봐` (dry-run): `bash agent-ops/skills/project/run-proto-socket-test-matrix/scripts/run_test_by_change.sh --route auto --dry-run`으로 변경 파일, 선택된 functional/performance/stability 후보, skipped/nightly-pending 항목을 먼저 보고한다.
- `속도 테스트 해봐` (dry-run): `bash agent-ops/skills/project/run-proto-socket-test-matrix/scripts/run_speed_test.sh --dry-run`으로 `performance-quick` 중심 후보와 `performance-full`/`stability-full` nightly 후보를 분리해 보고한다. `performance-full``nightly-pending`이면 20:00 이전 baseline PASS 근거가 아니다.
- `안정성 테스트 해봐` (dry-run): `bash agent-ops/skills/project/run-proto-socket-test-matrix/scripts/run_stability_test.sh --dry-run`으로 `stability-quick` hard gate 후보를 먼저 보고한다. timeout, nonce/type mismatch, FIFO violation, pending leak, queue/gateway backlog 위반이 있으면 성능 수치가 좋아도 PASS가 아니다.
### 결과 기록 계약
- non-dry-run 실행 시 선택 이유, 실행 명령, 결과 record 경로를 출력에 남긴다.
- 실행하지 않은 skipped/nightly-pending 항목은 PASS로 보고하지 않는다.
- `nightly-pending` 후보는 `## nightly-pending 후보 (미실행, PASS 아님)` 섹션에 후보 command와 함께 기록한다.
- anchor 실행(`functional-server-x5`, `functional-client-x5`, `functional-both-x5`)은 anchor-runner-options 범위로 남기고 `anchor-skipped`로 기록한다.

View file

@ -0,0 +1,123 @@
#!/usr/bin/env bash
set -uo pipefail
# -----------------------------------------------------------------------
# run_speed_test.sh
# 속도(성능) 전용 실행 wrapper
#
# --dry-run: run_test_by_change.sh --route speed --dry-run 출력만 수행한다.
# non-dry-run: performance-quick recommended면 run_performance.sh --quick 실행,
# performance-full / stability-full nightly-pending 후보는 실행하지 않고
# 후보 command만 기록한다.
# -----------------------------------------------------------------------
usage() {
cat <<'USAGE'
Usage: run_speed_test.sh [--dry-run]
속도(성능) 전용 테스트 wrapper.
--dry-run run_test_by_change.sh --route speed --dry-run 출력만 수행
-h, --help 이 도움말 출력
dry-run이 아니면:
- performance-quick recommended → run_performance.sh --quick 실행
- performance-full / stability-full nightly-pending → 후보 command만 기록
USAGE
}
dry_run=0
while [ "$#" -gt 0 ]; do
case "$1" in
--dry-run) dry_run=1 ;;
-h|--help) usage; exit 0 ;;
*)
printf 'Error: unknown option "%s"\n' "$1" >&2
usage >&2
exit 2
;;
esac
shift
done
script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
repo_root="$(cd "$script_dir/../../../../.." && pwd)"
classifier="$script_dir/run_test_by_change.sh"
perf_script="$script_dir/run_performance.sh"
# 1. classifier dry-run 출력 (항상 출력)
printf '## Speed route 분류 결과\n\n'
classify_output="$(bash "$classifier" --route speed --dry-run 2>&1)"
classify_exit=$?
printf '%s\n' "$classify_output"
if [ "$classify_exit" -ne 0 ]; then
printf '\nERROR: classifier 실패 (exit %d)\n' "$classify_exit" >&2
exit "$classify_exit"
fi
# dry-run이면 여기서 종료
[ "$dry_run" -eq 1 ] && exit 0
# 2. 추천 상태 파싱: recommended에 performance-quick이 있는지 확인
has_perf_quick=0
has_nightly_perf_full=0
has_nightly_stab_full=0
while IFS= read -r line; do
case "$line" in
'| recommended | performance-quick |'*)
has_perf_quick=1
;;
'| nightly-pending | performance-full |'*)
has_nightly_perf_full=1
;;
'| nightly-pending | stability-full |'*)
has_nightly_stab_full=1
;;
esac
done <<< "$classify_output"
# 3. 실행 계획 출력
printf '\n## 실행 계획\n\n'
if [ "$has_perf_quick" -eq 1 ]; then
printf '%s\n' '- [실행 예정] performance-quick: run_performance.sh --quick'
else
printf '%s\n' '- [skipped] performance-quick: classifier recommended 없음'
fi
if [ "$has_nightly_perf_full" -eq 1 ]; then
printf '%s\n' '- [nightly-pending] performance-full: 20:00 이후 야간 후보. 후보 command: bash agent-ops/skills/project/run-proto-socket-test-matrix/scripts/run_performance.sh --full'
fi
if [ "$has_nightly_stab_full" -eq 1 ]; then
printf '%s\n' '- [nightly-pending] stability-full: 20:00 이후 야간 후보. 후보 command: bash agent-ops/skills/project/run-proto-socket-test-matrix/scripts/run_stress.sh --full --profile sustained,parallel,payload'
fi
# 4. performance-quick 실행
run_exit=0
if [ "$has_perf_quick" -eq 1 ]; then
printf '\n--- 실행: run_performance.sh --quick ---\n' >&2
(cd "$repo_root" && bash "$perf_script" --quick)
run_exit=$?
printf '\n## 실행 결과: performance-quick\n\n'
printf '%s\n' '- 실행 명령: `bash agent-ops/skills/project/run-proto-socket-test-matrix/scripts/run_performance.sh --quick`'
printf '%s\n' '- 선택 이유: speed route — performance-quick recommended'
printf '%s\n' "- exit code: ${run_exit}"
local_record="$(find "$repo_root/agent-test/runs" -maxdepth 1 -name '*proto-socket-performance-quick*' -type f 2>/dev/null | sort -r | head -n 1)"
if [ -n "$local_record" ]; then
rel="$(realpath --relative-to="$repo_root" "$local_record" 2>/dev/null || printf '%s' "$(basename "$local_record")")"
printf '%s\n' "- 결과 기록: ${rel}"
fi
fi
# 5. nightly-pending 후보 요약 (미실행, PASS 아님)
if [ "$has_nightly_perf_full" -eq 1 ] || [ "$has_nightly_stab_full" -eq 1 ]; then
printf '\n## nightly-pending 후보 (미실행, PASS 아님)\n\n'
[ "$has_nightly_perf_full" -eq 1 ] && \
printf '%s\n' '- performance-full: 20:00 이후 야간 후보. 후보 command: `bash agent-ops/skills/project/run-proto-socket-test-matrix/scripts/run_performance.sh --full`'
[ "$has_nightly_stab_full" -eq 1 ] && \
printf '%s\n' '- stability-full: 20:00 이후 야간 후보. 후보 command: `bash agent-ops/skills/project/run-proto-socket-test-matrix/scripts/run_stress.sh --full --profile sustained,parallel,payload`'
fi
exit "$run_exit"

View file

@ -0,0 +1,133 @@
#!/usr/bin/env bash
set -uo pipefail
# -----------------------------------------------------------------------
# run_stability_test.sh
# 안정성 전용 실행 wrapper
#
# --dry-run: run_test_by_change.sh --route stability --dry-run 출력만 수행한다.
# non-dry-run: stability-quick recommended면 run_stress.sh --quick 실행(hard gate),
# stability-full nightly-pending 후보는 실행하지 않고 후보 command만 기록한다.
# hard gate 판정: timeout, nonce/type mismatch, FIFO, pending leak,
# queue/gateway backlog가 모두 0이어야 PASS.
# -----------------------------------------------------------------------
usage() {
cat <<'USAGE'
Usage: run_stability_test.sh [--dry-run]
안정성 전용 테스트 wrapper.
--dry-run run_test_by_change.sh --route stability --dry-run 출력만 수행
-h, --help 이 도움말 출력
dry-run이 아니면:
- stability-quick recommended → run_stress.sh --quick --profile sustained,parallel,payload 실행 (hard gate)
- stability-full nightly-pending → 후보 command만 기록 (미실행, PASS 아님)
hard gate: timeout / nonce mismatch / response type mismatch /
per-connection FIFO violation / pending leak / queue/gateway backlog leak가 모두 0이어야 한다.
USAGE
}
dry_run=0
while [ "$#" -gt 0 ]; do
case "$1" in
--dry-run) dry_run=1 ;;
-h|--help) usage; exit 0 ;;
*)
printf 'Error: unknown option "%s"\n' "$1" >&2
usage >&2
exit 2
;;
esac
shift
done
script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
repo_root="$(cd "$script_dir/../../../../.." && pwd)"
classifier="$script_dir/run_test_by_change.sh"
stress_script="$script_dir/run_stress.sh"
# 1. classifier dry-run 출력 (항상 출력)
printf '## Stability route 분류 결과\n\n'
classify_output="$(bash "$classifier" --route stability --dry-run 2>&1)"
classify_exit=$?
printf '%s\n' "$classify_output"
if [ "$classify_exit" -ne 0 ]; then
printf '\nERROR: classifier 실패 (exit %d)\n' "$classify_exit" >&2
exit "$classify_exit"
fi
# dry-run이면 여기서 종료
[ "$dry_run" -eq 1 ] && exit 0
# 2. 추천 상태 파싱
has_stab_quick=0
has_nightly_stab_full=0
has_nightly_perf_full=0
while IFS= read -r line; do
case "$line" in
'| recommended | stability-quick |'*)
has_stab_quick=1
;;
'| nightly-pending | stability-full |'*)
has_nightly_stab_full=1
;;
'| nightly-pending | performance-full |'*)
has_nightly_perf_full=1
;;
esac
done <<< "$classify_output"
# 3. 실행 계획 출력
printf '\n## 실행 계획\n\n'
if [ "$has_stab_quick" -eq 1 ]; then
printf '%s\n' '- [실행 예정] stability-quick (hard gate): run_stress.sh --quick --profile sustained,parallel,payload'
printf '%s\n' ' hard gate: timeout / nonce mismatch / response type mismatch / FIFO violation / pending leak / queue/gateway backlog leak 모두 0'
else
printf '%s\n' '- [skipped] stability-quick: classifier recommended 없음'
fi
if [ "$has_nightly_stab_full" -eq 1 ]; then
printf '%s\n' '- [nightly-pending] stability-full: 20:00 이후 야간 후보. 후보 command: bash agent-ops/skills/project/run-proto-socket-test-matrix/scripts/run_stress.sh --full --profile sustained,parallel,payload'
fi
if [ "$has_nightly_perf_full" -eq 1 ]; then
printf '%s\n' '- [nightly-pending] performance-full: 20:00 이후 야간 후보. 후보 command: bash agent-ops/skills/project/run-proto-socket-test-matrix/scripts/run_performance.sh --full'
fi
# 4. stability-quick 실행 (hard gate)
run_exit=0
if [ "$has_stab_quick" -eq 1 ]; then
printf '\n--- 실행: run_stress.sh --quick --profile sustained,parallel,payload ---\n' >&2
(cd "$repo_root" && bash "$stress_script" --quick --profile sustained,parallel,payload)
run_exit=$?
printf '\n## 실행 결과: stability-quick\n\n'
printf '%s\n' '- 실행 명령: `bash agent-ops/skills/project/run-proto-socket-test-matrix/scripts/run_stress.sh --quick --profile sustained,parallel,payload`'
printf '%s\n' '- 선택 이유: stability route — stability-quick hard gate 점검'
printf '%s\n' "- exit code: ${run_exit}"
printf '%s\n' '- hard gate 판정 기준: timeout / nonce mismatch / response type mismatch / FIFO violation / pending leak / queue/gateway backlog leak 모두 0'
local_record="$(find "$repo_root/agent-test/runs" -maxdepth 1 -name '*proto-socket-stress-quick*' -type f 2>/dev/null | sort -r | head -n 1)"
if [ -n "$local_record" ]; then
rel="$(realpath --relative-to="$repo_root" "$local_record" 2>/dev/null || printf '%s' "$(basename "$local_record")")"
printf '%s\n' "- 결과 기록: ${rel}"
fi
if [ "$run_exit" -ne 0 ]; then
printf '%s\n' '- 판정: hard gate 위반 — stability PASS 아님'
else
printf '%s\n' '- 판정: hard gate 통과'
fi
fi
# 5. nightly-pending 후보 요약 (미실행, PASS 아님)
if [ "$has_nightly_stab_full" -eq 1 ] || [ "$has_nightly_perf_full" -eq 1 ]; then
printf '\n## nightly-pending 후보 (미실행, PASS 아님)\n\n'
[ "$has_nightly_stab_full" -eq 1 ] && \
printf '%s\n' '- stability-full: 20:00 이후 야간 후보. 후보 command: `bash agent-ops/skills/project/run-proto-socket-test-matrix/scripts/run_stress.sh --full --profile sustained,parallel,payload`'
[ "$has_nightly_perf_full" -eq 1 ] && \
printf '%s\n' '- performance-full: 20:00 이후 야간 후보. 후보 command: `bash agent-ops/skills/project/run-proto-socket-test-matrix/scripts/run_performance.sh --full`'
fi
exit "$run_exit"

View file

@ -3,23 +3,23 @@ set -uo pipefail
# -----------------------------------------------------------------------
# run_test_by_change.sh
# 변경 기반 테스트 라우팅 — 분류기 단계
# 변경 기반 테스트 라우팅
#
# 마지막 PASS 테스트 record와 현재 작업트리 변경 파일을 기반으로
# 언어/도메인 분류 결과를 출력한다. 실제 테스트를 실행하지 않는다.
# 후속 라우팅 단계(02+01_risk_routing_rules)가 이 출력을 입력으로 사용한다.
# 언어/도메인 분류와 라우팅 추천을 출력하고, 기본 실행 모드에서는
# 지원 가능한 recommended 후보를 기존 wrapper command로 실행한다.
# -----------------------------------------------------------------------
usage() {
cat <<'USAGE'
Usage: run_test_by_change.sh [--route auto|speed|stability|full] [--classify-only] [--dry-run]
마지막 PASS 테스트 record와 현재 변경 파일을 기반으로 분류 결과를 출력한다.
실제 테스트를 실행하지 않는다.
마지막 PASS 테스트 record와 현재 변경 파일을 기반으로 분류/라우팅 결과를 출력한다.
기본 실행 모드는 지원 가능한 recommended 후보를 실행한다.
Options:
--route ROUTE 라우팅 종류: auto, speed, stability, full (기본값: auto)
--classify-only 분류 결과만 출력하고 종료 (현재 지원 모드)
--classify-only 분류 결과만 출력하고 종료(명령 실행 없음)
--dry-run 분류/라우팅 결과만 출력하고 종료(명령 실행 없음)
-h, --help 이 도움말 출력
@ -721,6 +721,127 @@ main() {
"$(md_escape_cell "${reco_reasons[$i]}")"
done
fi
# classify-only 또는 dry-run이면 여기서 종료 (실제 실행 없음)
[ "$classify_only" -eq 1 ] && return
[ "$dry_run" -eq 1 ] && return
# -----------------------------------------------------------------------
# non-dry-run 실행 분기
# recommended 후보 중 지원 가능한 항목을 기존 wrapper command로 실행한다.
# anchor(functional-server-x5, functional-client-x5, functional-both-x5)는
# anchor-runner-options 범위이므로 skipped로 기록한다.
# -----------------------------------------------------------------------
printf '\n### 실행 계획\n\n'
local supported_kinds="performance-quick stability-quick functional-full runner-docs-selfcheck docs-selfcheck"
local exec_log=""
local skipped_log=""
local nightly_log=""
for ((i = 0; i < ${#reco_statuses[@]}; i++)); do
local st="${reco_statuses[$i]}"
local kd="${reco_kinds[$i]}"
local tg="${reco_targets[$i]}"
local rs="${reco_reasons[$i]}"
case "$st" in
nightly-pending)
nightly_log="${nightly_log}- [nightly-pending] ${kd} / ${tg}: ${rs}\n"
continue
;;
skipped-candidate|noop)
skipped_log="${skipped_log}- [${st}] ${kd} / ${tg}: ${rs}\n"
continue
;;
esac
# recommended
local is_supported=0
for sup in $supported_kinds; do
[ "$kd" = "$sup" ] && is_supported=1 && break
done
if [ "$is_supported" -eq 0 ]; then
skipped_log="${skipped_log}- [anchor-skipped] ${kd} / ${tg}: anchor 실행은 anchor-runner-options 범위\n"
continue
fi
exec_log="${exec_log}- [실행 예정] ${kd} / ${tg}: ${rs}\n"
done
if [ -n "$exec_log" ]; then
printf '#### 실행 예정\n\n'
printf '%b' "$exec_log"
fi
if [ -n "$skipped_log" ]; then
printf '\n#### 미실행 (skipped / anchor)\n\n'
printf '%b' "$skipped_log"
fi
if [ -n "$nightly_log" ]; then
printf '\n#### nightly-pending (미실행, PASS 아님)\n\n'
printf '%b' "$nightly_log"
fi
# 실행 단계
local run_exit=0
for ((i = 0; i < ${#reco_statuses[@]}; i++)); do
local st="${reco_statuses[$i]}"
local kd="${reco_kinds[$i]}"
[ "$st" != "recommended" ] && continue
local is_supported=0
for sup in $supported_kinds; do
[ "$kd" = "$sup" ] && is_supported=1 && break
done
[ "$is_supported" -eq 0 ] && continue
local cmd="" exit_code=0 record_path=""
case "$kd" in
performance-quick)
cmd="bash $(printf '%q' "$script_dir/run_performance.sh") --quick"
printf '\n--- 실행: %s ---\n' "$cmd" >&2
(cd "$repo_root" && bash "$script_dir/run_performance.sh" --quick) >&2
exit_code=$?
record_path="$(find "$repo_root/agent-test/runs" -maxdepth 1 -name '*proto-socket-performance-quick*' -type f 2>/dev/null | sort -r | head -n 1)"
;;
stability-quick)
cmd="bash $(printf '%q' "$script_dir/run_stress.sh") --quick --profile sustained,parallel,payload"
printf '\n--- 실행: %s ---\n' "$cmd" >&2
(cd "$repo_root" && bash "$script_dir/run_stress.sh" --quick --profile sustained,parallel,payload) >&2
exit_code=$?
record_path="$(find "$repo_root/agent-test/runs" -maxdepth 1 -name '*proto-socket-stress-quick*' -type f 2>/dev/null | sort -r | head -n 1)"
;;
functional-full)
cmd="bash $(printf '%q' "$script_dir/run_matrix.sh") --all"
printf '\n--- 실행: %s ---\n' "$cmd" >&2
(cd "$repo_root" && bash "$script_dir/run_matrix.sh" --all) >&2
exit_code=$?
record_path="$(find "$repo_root/agent-test/runs" -maxdepth 1 -name '*proto-socket-full-matrix*' -type f 2>/dev/null | sort -r | head -n 1)"
;;
runner-docs-selfcheck|docs-selfcheck)
cmd="bash -n $(printf '%q' "$script_dir/run_test_by_change.sh")"
printf '\n--- 실행: %s ---\n' "$cmd" >&2
bash -n "$script_dir/run_test_by_change.sh" >&2
exit_code=$?
;;
esac
if [ "$exit_code" -ne 0 ]; then run_exit="$exit_code"; fi
printf '\n### 실행 결과: %s\n\n' "$kd"
printf '%s\n' "- 실행 명령: \`${cmd}\`"
printf '%s\n' "- 선택 이유: ${reco_reasons[$i]}"
printf '%s\n' "- exit code: ${exit_code}"
if [ -n "$record_path" ]; then
local rel_record
rel_record="$(realpath --relative-to="$repo_root" "$record_path" 2>/dev/null || printf '%s' "$(basename "$record_path")")"
printf '%s\n' "- 결과 기록: ${rel_record}"
fi
done
if [ -n "$nightly_log" ]; then
printf '\n### nightly-pending 후보 (미실행, PASS 아님)\n\n'
printf '%b' "$nightly_log"
fi
return "$run_exit"
}
main

View file

@ -63,10 +63,10 @@
사용자가 길게 지정하지 않아도 요청 문장으로 테스트 의도를 안정적으로 고른다.
- [ ] [auto-test-route] `테스트 해봐`는 마지막 PASS 지점과 현재 diff를 분석해 functional/performance/stability 중 필요한 범위를 자동 선택한다. 검증: 변경 내용 분석 결과와 선택한 테스트 범위를 실행 전에 보고한다.
- [ ] [speed-test-route] `속도 테스트 해봐`는 performance 중심으로 라우팅하고, 낮 시간 quick과 야간 full 후보를 분리한다. 검증: 장시간/1MB/full이 20:00 이전에 baseline으로 처리되지 않는다.
- [ ] [stability-test-route] `안정성 테스트 해봐`는 timeout, nonce/type mismatch, FIFO, pending leak, queue/gateway backlog 중심으로 라우팅한다. 검증: 성능 수치가 좋아도 hard gate 위반 row는 PASS가 아니다.
- [ ] [full-test-route] `전체 테스트 해봐`는 functional full 5x5를 기본으로 실행하고, performance/stability full은 시간대에 따라 즉시 실행 또는 nightly pending으로 분리한다. 검증: 실행하지 않은 야간 full 항목을 PASS로 보고하지 않는다.
- [x] [auto-test-route] `테스트 해봐`는 마지막 PASS 지점과 현재 diff를 분석해 functional/performance/stability 중 필요한 범위를 자동 선택한다. 검증: 변경 내용 분석 결과와 선택한 테스트 범위를 실행 전에 보고한다.
- [x] [speed-test-route] `속도 테스트 해봐`는 performance 중심으로 라우팅하고, 낮 시간 quick과 야간 full 후보를 분리한다. 검증: 장시간/1MB/full이 20:00 이전에 baseline으로 처리되지 않는다.
- [x] [stability-test-route] `안정성 테스트 해봐`는 timeout, nonce/type mismatch, FIFO, pending leak, queue/gateway backlog 중심으로 라우팅한다. 검증: 성능 수치가 좋아도 hard gate 위반 row는 PASS가 아니다.
- [x] [full-test-route] `전체 테스트 해봐`는 functional full 5x5를 기본으로 실행하고, performance/stability full은 시간대에 따라 즉시 실행 또는 nightly pending으로 분리한다. 검증: 실행하지 않은 야간 full 항목을 PASS로 보고하지 않는다.
### Epic: [skill-and-runner-contract] 스킬과 runner 계약
@ -114,4 +114,6 @@
- 완료(직접 처리): `functional-routing` anchor 보강 -> `anchor-language-x5`, `anchor-language-both-x5`; 검증=`bash -n .../run_test_by_change.sh`, focused dry-run server/client/transport, public-api unit smoke
- 완료(직접 처리): `performance-stability-routing` daytime quick 보강 -> `daytime-performance-quick`, `daytime-stability-quick`; 검증=`bash -n .../run_test_by_change.sh`, focused temp repo route smoke(auto/speed/stability/full), `rg --sort path ...`
- 계획 작성: `agent-task/m-change-aware-test-routing/03_nightly_periodic_contract/PLAN-cloud-G07.md` -> `nightly-heavy-routing`, `periodic-full-routing`
- 계획 작성: `agent-task/m-change-aware-test-routing/04_user_entrypoints_full_route/PLAN-local-G01.md` -> `full-test-route`
- 완료: `agent-task/archive/2026/06/m-change-aware-test-routing/04_user_entrypoints_full_route/complete.log` -> `full-test-route`
- 완료(직접 처리): `user-entrypoints` auto/speed/stability dry-run 정책 보강 -> `auto-test-route`, `speed-test-route`, `stability-test-route`; 검증=`bash -n .../run_test_by_change.sh`, focused temp repo route smoke(auto/speed/stability), `rg --sort path ...`
- 계획 작성: `agent-task/m-change-aware-test-routing/05_user_entrypoint_runner_contract/PLAN-cloud-G07.md` -> `routing-skill`, `auto-test-shell`, `speed-test-shell`, `stability-test-shell`, `test-profile-docs`, `result-report-contract`

View file

@ -0,0 +1,280 @@
<!-- task=m-change-aware-test-routing/05_user_entrypoint_runner_contract plan=0 tag=USER_ROUTE_RUN -->
# Code Review Reference - USER_ROUTE_RUN
> **[IMPLEMENTING AGENT - READ FIRST] Filling in this file is the mandatory final step of implementation.**
> The task is NOT complete until every implementation-owned section below is filled in.
> Complete the `구현 체크리스트`; the final checklist item is mandatory before saving.
> Fill implementation-owned sections, then stop with active files in place and report ready for review.
> If implementation is blocked by a user-only decision, user-owned external environment prerequisite, or scope conflict, fill `사용자 리뷰 요청` with evidence and stop with active files in place; code-review decides whether to write `USER_REVIEW.md`. Evidence gaps that a follow-up agent can close by rerunning commands or collecting artifacts are normal follow-up issues, not user-review blockers by themselves.
> Do not ask the user directly, present choices in chat, or call `request_user_input` during implementation; record the needed decision in `사용자 리뷰 요청` and stop for code-review.
> Finalization (`코드리뷰 결과`, log rename, `complete.log`, archive moves, `코드리뷰 전용 체크리스트`) is review-agent-only, even after compaction/resume.
> Follow the ownership table at the bottom of this file for which sections you own.
## 개요
date=2026-06-10
task=m-change-aware-test-routing/05_user_entrypoint_runner_contract, plan=0, tag=USER_ROUTE_RUN
## Roadmap Targets
- Milestone: `agent-roadmap/milestones/change-aware-test-routing.md`
- Task ids:
- `routing-skill`: 프로젝트 스킬 또는 기존 `run-proto-socket-test-matrix` 스킬에 "작업된 내용을 바탕으로 테스트" 요청 라우팅 절차를 추가한다.
- `auto-test-shell`: `run_test_by_change.sh` 자동 라우팅 shell을 추가해 `테스트 해봐` 요청의 기본 실행 단위로 쓴다.
- `speed-test-shell`: `run_speed_test.sh` 속도 전용 shell을 추가해 quick/daytime과 full/nightly 후보를 관리한다.
- `stability-test-shell`: `run_stability_test.sh` 안정성 전용 shell을 추가해 quick stress와 nightly long-run 후보를 관리한다.
- `test-profile-docs`: `agent-test/local/rules.md`와 관련 profile 문서에 4개 shell entrypoint와 주야간 분리 기준을 반영한다.
- `result-report-contract`: 결과 보고에 선택 이유, 실행 명령, 결과 record, skipped/nightly-pending 항목을 남긴다.
- Completion mode: check-on-pass
## 이 파일을 읽는 리뷰 에이전트에게
> **[REVIEW AGENT ONLY]** 아래 종결 절차는 코드리뷰 에이전트 전용이다. 구현 에이전트는 이 섹션을 실행하지 않는다.
각 항목의 구현을 실제 소스 파일과 대조하고, `검증 결과` 섹션의 출력이 코드와 일치하는지 확인하세요.
리뷰 완료는 아래 순서까지 끝난 상태를 의미합니다.
1. 판정을 append한다.
2. `CODE_REVIEW-cloud-G07.md` -> `code_review_cloud_G07_N.log`, `PLAN-cloud-G07.md` -> `plan_cloud_G07_M.log`로 아카이브한다.
3. PASS이면 `complete.log` 작성 후 active task 디렉터리를 `agent-task/archive/YYYY/MM/m-change-aware-test-routing/05_user_entrypoint_runner_contract/`로 이동한다.
4. PASS이고 task group이 `m-<milestone-slug>`이면 완료 이벤트 메타데이터를 보고한다. roadmap 상태 체크와 `update-roadmap` 호출은 런타임 책임이다.
5. 적용 가능한 `코드리뷰 전용 체크리스트` 항목을 최종 `.log` 위치에서 체크한 뒤 보고한다.
---
## 구현 항목별 완료 여부
| 항목 | 완료 여부 |
|------|---------|
| [USER_ROUTE_RUN-1] Auto route execution contract | [x] |
| [USER_ROUTE_RUN-2] Speed route wrapper | [x] |
| [USER_ROUTE_RUN-3] Stability route wrapper | [x] |
| [USER_ROUTE_RUN-4] Skill and local test docs | [x] |
| [USER_ROUTE_RUN-5] Route smoke and final verification | [x] |
## 구현 체크리스트
- [x] [USER_ROUTE_RUN-1] `run_test_by_change.sh`의 dry-run 계약을 보존하면서 non-dry-run auto route가 실행 계획, 실행 결과, record 경로를 남기게 한다.
- [x] [USER_ROUTE_RUN-2] `run_speed_test.sh`를 추가해 speed route dry-run 보고 후 낮 시간 quick 성능 실행과 nightly-pending full 후보 보고를 수행한다.
- [x] [USER_ROUTE_RUN-3] `run_stability_test.sh`를 추가해 stability route dry-run 보고 후 quick stability 실행과 hard gate/nightly-pending 후보 보고를 수행한다.
- [x] [USER_ROUTE_RUN-4] `run-proto-socket-test-matrix` skill과 `agent-test/local` profile 문서를 새 실행 wrapper 및 결과 보고 계약과 일치시킨다.
- [x] [USER_ROUTE_RUN-5] shell syntax, focused temp repo route smoke, deterministic `rg --sort path`로 검증하고 실제 stdout/stderr를 review stub에 남긴다.
- [x] CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채운다. 이 항목이 완료되기 전에는 구현이 완료된 것이 아니다.
## 코드리뷰 전용 체크리스트
> **[REVIEW AGENT ONLY]** 이 체크리스트는 코드리뷰 에이전트만 사용한다.
> 구현 에이전트는 이 섹션을 수정하거나 체크하지 않는다.
- [x] `코드리뷰 결과`에 `PASS`, `WARN`, `FAIL` 중 하나의 판정을 append한다.
- [x] 판정과 `차원별 평가`, Required/Suggested/Nit 분류가 서로 일치한다.
- [x] active `CODE_REVIEW-*-G??.md`를 `code_review_cloud_G07_N.log`로 아카이브한다.
- [x] active `PLAN-*-G??.md`를 `plan_cloud_G07_M.log`로 아카이브한다.
- [x] `.gitignore`의 Agent-Ops 관리 block이 `agent-task/**/*.md`와 `agent-task/**/*.log`를 unignore하고 `agent-roadmap/current.md`를 ignore하는지 확인한다.
- [ ] PASS이면 `complete.log`에 `Roadmap Completion` 섹션과 대상 Task ids를 기록한다.
- [ ] PASS이면 active task 디렉터리를 `agent-task/archive/YYYY/MM/m-change-aware-test-routing/05_user_entrypoint_runner_contract/`로 이동한다.
- [ ] PASS이고 task group이 `m-<milestone-slug>`이면 런타임이 읽을 완료 이벤트 메타데이터를 보고하고, roadmap 수정이나 `update-roadmap` 직접 호출을 하지 않는다.
- [x] FAIL이고 user-review gate가 트리거되지 않았으므로 다음 active `PLAN-cloud-G07.md`와 `CODE_REVIEW-cloud-G07.md`를 작성하고 `complete.log`를 작성하지 않는다.
## 계획 대비 변경 사항
- `run_speed_test.sh`의 분류 출력 파싱: 계획은 `run_test_by_change.sh --route speed --dry-run` 출력에서 추천 상태를 파싱하는 방식을 명시하지 않았다. stdout의 `| recommended | performance-quick |` 패턴을 `while IFS= read -r line; do case "$line" in ... esac; done` 으로 파싱했다. `run_stability_test.sh`도 같은 방식 적용.
- `run_test_by_change.sh` non-dry-run에서 `runner-docs-selfcheck`와 `docs-selfcheck` 모두 `bash -n <self>` 로 처리했다. 계획의 `runner-docs-selfcheck` 단일 항목을 `docs-selfcheck` alias도 같이 처리한 것이다. 동작 동일.
## 주요 설계 결정
- `run_test_by_change.sh`의 non-dry-run 실행 분기는 `main()` 함수 내 결과 출력 이후에 추가했다. `[ "$dry_run" -eq 1 ] && return`으로 dry-run 계약을 보존한다.
- anchor 실행(`functional-server-x5`, `functional-client-x5`, `functional-both-x5`)은 `anchor-runner-options` 범위이므로 `anchor-skipped`로 기록하고 실제 command를 실행하지 않는다.
- `run_speed_test.sh`와 `run_stability_test.sh`는 각각 classifier를 subshell로 호출해 출력을 캡처한 뒤 추천 상태를 파싱한다. classifier stdout/stderr를 합산하지 않고 stdout만 추천 파싱에 사용한다.
- nightly-pending 후보는 실행하지 않고 후보 command와 함께 `## nightly-pending 후보 (미실행, PASS 아님)` 섹션으로 기록한다.
## 사용자 리뷰 요청
_기본값은 `없음`이다. 구현 중 사용자 결정, 사용자 소유 외부 환경/secret/서비스 준비, 또는 계획 범위 변경 없이는 안전하게 진행할 수 없으면 아래 항목을 실제 내용으로 교체하고, 구현을 중단한 뒤 active 파일을 그대로 둔 채 리뷰를 요청한다. 구현 에이전트는 사용자에게 직접 질문하거나 선택지를 제시하거나 `request_user_input`을 호출하지 않는다. 후속 에이전트가 명령 재실행이나 산출물 수집으로 해소할 수 있는 검증 증거 공백만으로는 사용자 리뷰 요청을 작성하지 않는다._
- 상태: 없음
- 사유 유형: 없음
- 결정 필요: 없음
- 차단 근거: 없음
- 실행한 검증/명령: 없음
- 자동 후속 불가 이유: 없음
- 재개 조건: 없음
## 리뷰어를 위한 체크포인트
- `--dry-run` 동작이 기존처럼 테스트를 실행하지 않는지 확인한다.
- non-dry-run wrapper가 실행한 항목과 skipped/nightly-pending 항목을 PASS로 섞지 않는지 확인한다.
- `run_speed_test.sh`와 `run_stability_test.sh`가 full/nightly 후보를 즉시 실행하지 않는지 확인한다.
- 결과 record에 선택 이유, 실행 명령, record path, skipped/nightly-pending 항목이 남는지 확인한다.
## 검증 결과
_구현 에이전트가 각 중간 검증 및 최종 검증 명령 실행 후 출력을 여기에 붙여 넣는다._
필수 규칙:
- 검증 명령은 고정된 계약이다. 임의로 대체하지 않는다.
- 대체가 필요하면 `계획 대비 변경 사항`에 이유와 대체 명령을 기록한다.
- `검증 결과`에는 실제 stdout/stderr를 붙여 넣는다.
- 사용자 리뷰 요청으로 명령을 끝까지 실행하지 못했다면 `사용자 리뷰 요청`에 실행한 명령, 실제 출력, 미실행 명령의 사유를 기록한다.
### USER_ROUTE_RUN-1~3 shell syntax
```text
$ bash -n agent-ops/skills/project/run-proto-socket-test-matrix/scripts/run_test_by_change.sh
exit:0
$ bash -n agent-ops/skills/project/run-proto-socket-test-matrix/scripts/run_speed_test.sh
exit:0
$ bash -n agent-ops/skills/project/run-proto-socket-test-matrix/scripts/run_stability_test.sh
exit:0
```
### USER_ROUTE_RUN-4 deterministic contract search
```text
$ rg --sort path -n "run_test_by_change.sh|run_speed_test.sh|run_stability_test.sh|run_full_test.sh|nightly-pending|PASS 아님|결과 기록|hard gate" agent-ops/skills/project/run-proto-socket-test-matrix agent-test/local
agent-ops/skills/project/run-proto-socket-test-matrix/SKILL.md:25:...run_test_by_change.sh --route <mode> --dry-run...run_full_test.sh --dry-run...
agent-ops/skills/project/run-proto-socket-test-matrix/SKILL.md:199:- `nightly-pending`: 야간 별도 실행 후보. 실행하지 않은 것을 PASS로 보고하지 않음.
agent-ops/skills/project/run-proto-socket-test-matrix/SKILL.md:204:...stability-quick을 추천하고 timeout, nonce/type mismatch, FIFO, pending leak, queue/gateway backlog를 hard gate로 본다.
agent-ops/skills/project/run-proto-socket-test-matrix/SKILL.md:215:| `테스트 해봐` | `run_test_by_change.sh --route auto` | dry-run으로 후보 보고 → recommended 항목 실행 → 결과 record 경로 기록. skipped/nightly-pending은 실행 안 함 |
agent-ops/skills/project/run-proto-socket-test-matrix/SKILL.md:216:| `속도 테스트 해봐` | `run_speed_test.sh` | ...nightly-pending full은 후보 command만 기록 |
agent-ops/skills/project/run-proto-socket-test-matrix/SKILL.md:217:| `안정성 테스트 해봐` | `run_stability_test.sh` | ...stability-quick hard gate 실행. nightly-pending full은 후보 command만 기록 |
agent-ops/skills/project/run-proto-socket-test-matrix/SKILL.md:225:### 결과 기록 계약
agent-ops/skills/project/run-proto-socket-test-matrix/SKILL.md:228:- 실행하지 않은 skipped/nightly-pending 항목은 PASS로 보고하지 않는다.
agent-ops/skills/project/run-proto-socket-test-matrix/SKILL.md:229:- `nightly-pending` 후보는 `## nightly-pending 후보 (미실행, PASS 아님)` 섹션에 후보 command와 함께 기록한다.
agent-ops/skills/project/run-proto-socket-test-matrix/scripts/run_full_test.sh:8:# run_test_by_change.sh --route full --dry-run...
agent-ops/skills/project/run-proto-socket-test-matrix/scripts/run_full_test.sh:72: printf '\n### Nightly pending (미실행, PASS 아님)\n\n'
agent-ops/skills/project/run-proto-socket-test-matrix/scripts/run_speed_test.sh:8:# --dry-run: run_test_by_change.sh --route speed --dry-run 출력만 수행한다.
agent-ops/skills/project/run-proto-socket-test-matrix/scripts/run_speed_test.sh:73: '| nightly-pending | performance-full |'*)
agent-ops/skills/project/run-proto-socket-test-matrix/scripts/run_speed_test.sh:90: printf '- [nightly-pending] performance-full: 20:00 이후 야간 후보. 후보 command: ...run_performance.sh --full\n'
agent-ops/skills/project/run-proto-socket-test-matrix/scripts/run_speed_test.sh:110: printf '- 결과 기록: %s\n' "$rel"
agent-ops/skills/project/run-proto-socket-test-matrix/scripts/run_speed_test.sh:114:# 5. nightly-pending 후보 요약 (미실행, PASS 아님)
agent-ops/skills/project/run-proto-socket-test-matrix/scripts/run_stability_test.sh:9:# non-dry-run: stability-quick recommended면 run_stress.sh --quick 실행(hard gate),
agent-ops/skills/project/run-proto-socket-test-matrix/scripts/run_stability_test.sh:88: printf '- [실행 예정] stability-quick (hard gate): ...
agent-ops/skills/project/run-proto-socket-test-matrix/scripts/run_stability_test.sh:89: printf ' hard gate: timeout / nonce mismatch / response type mismatch / FIFO violation / pending leak / queue/gateway backlog leak 모두 0\n'
agent-ops/skills/project/run-proto-socket-test-matrix/scripts/run_stability_test.sh:115: printf '- 결과 기록: %s\n' "$rel"
agent-ops/skills/project/run-proto-socket-test-matrix/scripts/run_stability_test.sh:124:# 5. nightly-pending 후보 요약 (미실행, PASS 아님)
agent-ops/skills/project/run-proto-socket-test-matrix/scripts/run_test_by_change.sh:29: stability stress/performance PASS record (stability hard gate 기준)
agent-ops/skills/project/run-proto-socket-test-matrix/scripts/run_test_by_change.sh:777: printf '\n#### nightly-pending (미실행, PASS 아님)\n\n'
agent-ops/skills/project/run-proto-socket-test-matrix/scripts/run_test_by_change.sh:834: printf '- 결과 기록: %s\n' "$rel_record"
agent-ops/skills/project/run-proto-socket-test-matrix/scripts/run_test_by_change.sh:839: printf '\n### nightly-pending 후보 (미실행, PASS 아님)\n\n'
agent-test/local/proto-socket-full-matrix.md:53:- user-entrypoint (변경 기반 자동): `bash ...run_test_by_change.sh --route auto`
agent-test/local/proto-socket-full-matrix.md:56:- user-entrypoint (안정성): `bash ...run_stability_test.sh`
agent-test/local/proto-socket-performance-baseline.md:43:- user-entrypoint (속도 테스트): `bash ...run_speed_test.sh`
agent-test/local/proto-socket-performance-baseline.md:45: - performance-quick recommended → `run_performance.sh --quick` 자동 실행. nightly-pending full은 후보 command만 기록 (PASS 아님)
agent-test/local/proto-socket-performance-baseline.md:56:- full route에서 `performance-full`이 `nightly-pending`이면 미실행 항목이며 PASS 아님으로 보고한다.
agent-test/local/proto-socket-performance-baseline.md:68:- stability hard gate: timeout, nonce mismatch, response type mismatch, per-connection FIFO violation, pending leak, queue/gateway backlog leak가 모두 0이어야 한다.
agent-test/local/rules.md:50:| `테스트 해봐` | `run_test_by_change.sh --route auto` | ...결과 record 경로 기록 |
agent-test/local/rules.md:51:| `속도 테스트 해봐` | `run_speed_test.sh` | ... |
agent-test/local/rules.md:52:| `안정성 테스트 해봐` | `run_stability_test.sh` | ... |
agent-test/local/rules.md:53:| `전체 테스트 해봐` | `run_full_test.sh` | ... |
agent-test/local/rules.md:55:### 결과 기록 계약
agent-test/local/rules.md:58:- 실행하지 않은 skipped/nightly-pending 항목은 PASS로 보고하지 않는다.
agent-test/local/rules.md:59:- `nightly-pending` 후보는 `## nightly-pending 후보 (미실행, PASS 아님)` 섹션에 후보 command와 함께 기록된다.
agent-test/local/rules.md:61:- stability-quick hard gate: timeout / nonce mismatch / response type mismatch / FIFO violation / pending leak / queue/gateway backlog leak가 모두 0이어야 PASS.
```
### USER_ROUTE_RUN-5 temp repo smoke
```text
$ tmp="$(mktemp ...)" && ... && printf 'package transport\n' > go/transport/stress_payload_1mb.go \
&& bash run_test_by_change.sh --route auto --dry-run \
&& bash run_speed_test.sh --dry-run \
&& bash run_stability_test.sh --dry-run
=== run_test_by_change.sh --route auto --dry-run ===
## 변경 기반 분류 결과
route: auto
last_pass_record: agent-test/runs/20260610-000000-proto-socket-stress-quick.md
last_pass_ref: 5b2ff62
fallback_reason: (없음)
changed_file_count: 4
detected_languages: go
detected_domains: other,transport
docs_only: no
untracked_included: yes
### 변경 파일 목록
| 파일 | 언어 | 도메인 |
|------|------|--------|
| agent-test/runs/20260610-000000-proto-socket-full-matrix.md | | other |
| agent-test/runs/20260610-000000-proto-socket-performance-quick.md | | other |
| agent-test/runs/20260610-000000-proto-socket-stress-quick.md | | other |
| go/transport/stress_payload_1mb.go | go | transport |
### 라우팅 추천 결과
| 상태 | 테스트 후보 | 대상 | 근거 |
|---|---|---|---|
| recommended | functional-both-x5 | go | transport/codec/communicator/public API 변경은 수정 언어 기준 both x5 |
| recommended | functional-both-x5 | transport/queue | transport/queue 변경은 both x5로 확장 |
| recommended | stability-quick | queue, gateway, concurrency | transport/queue 변경은 timeout, nonce/type mismatch, FIFO, pending leak, backlog hard gate 점검 필요 |
| recommended | performance-quick | performance baseline | 성능 영향 가능 변경은 낮 시간 quick 참고값을 남기되 야간 baseline 근거로 쓰지 않음 |
| nightly-pending | performance-full | performance baseline | sustained/high parallel/1MB payload 지표는 20:00 이후 야간 full 후보. 후보 command: run_performance.sh --full |
| nightly-pending | stability-full | queue/gateway/transport | 장시간 leak/backlog 확인은 20:00 이후 야간 후보. 후보 command: run_stress.sh --full --profile sustained,parallel,payload |
=== run_speed_test.sh --dry-run ===
## Speed route 분류 결과
route: speed
last_pass_record: agent-test/runs/20260610-000000-proto-socket-performance-quick.md
last_pass_ref: 5b2ff62
...
### 라우팅 추천 결과
| recommended | performance-quick | performance baseline | 성능 영향 가능 변경... |
| nightly-pending | performance-full | performance baseline | ... |
| nightly-pending | stability-full | queue/gateway/transport | ... |
=== run_stability_test.sh --dry-run ===
## Stability route 분류 결과
route: stability
last_pass_record: agent-test/runs/20260610-000000-proto-socket-stress-quick.md
last_pass_ref: 5b2ff62
...
### 라우팅 추천 결과
| recommended | stability-quick | queue, gateway, concurrency | transport/queue 변경... |
| nightly-pending | stability-full | queue/gateway/transport | ... |
```
### 최종 검증
```text
$ git diff --check
exit:0
```
---
> **[IMPLEMENTING AGENT - BEFORE SAVING] Have you filled in every implementation-owned section: completion table, implementation checklist, changes from plan, design decisions, and verification output?**
> If anything is blank, go back and fill it in before saving this file.
> Leave review-agent-only sections unchanged.
## 소유권 표
| 섹션 | 구현 에이전트 | 리뷰 에이전트 |
|---|---:|---:|
| 구현 항목별 완료 여부 | 예 | 검토 |
| 구현 체크리스트 | 예 | 검토 |
| 계획 대비 변경 사항 | 예 | 검토 |
| 주요 설계 결정 | 예 | 검토 |
| 사용자 리뷰 요청 | 예 | 검토 |
| 검증 결과 | 예 | 검토 |
| 코드리뷰 결과 | 아니오 | 예 |
| 코드리뷰 전용 체크리스트 | 아니오 | 예 |
## 코드리뷰 결과
- 종합 판정: FAIL
- 차원별 평가:
- correctness: Fail
- completeness: Fail
- test coverage: Fail
- API contract: Fail
- code quality: Warn
- plan deviation: Pass
- verification trust: Fail
- 발견된 문제:
- Required: `agent-ops/skills/project/run-proto-socket-test-matrix/scripts/run_test_by_change.sh:828`, `agent-ops/skills/project/run-proto-socket-test-matrix/scripts/run_speed_test.sh:85`, `agent-ops/skills/project/run-proto-socket-test-matrix/scripts/run_stability_test.sh:88` 등 새 non-dry-run 출력에서 `printf '- ...'` 형식 문자열을 사용한다. Bash `printf`는 선행 `-`를 option으로 해석하므로 실제 non-dry-run smoke에서 `printf: - : invalid option`이 반복되고, 실행 명령/선택 이유/exit code/결과 record 라인이 출력되지 않았다. 모든 dash-leading format은 `printf -- '- ...\n'` 또는 `printf '%s\n' '- ...'` 형태로 고치고, auto/speed/stability non-dry-run temp repo smoke로 `invalid option`이 없고 결과 record 라인이 남는지 검증해야 한다.
- Required: `agent-ops/skills/project/run-proto-socket-test-matrix/scripts/run_test_by_change.sh:725`는 `--dry-run`만 조기 반환하고 `--classify-only`는 반환하지 않는다. 사용법의 "`--classify-only` 분류 결과만 출력하고 종료" 계약과 달리 `bash .../run_test_by_change.sh --classify-only`가 `### 실행 계획`까지 출력했다. `classify_only=1`도 라우팅 추천/실행 분기 전에 종료하도록 복구하고, classify-only smoke를 검증에 추가해야 한다.
- 다음 단계:
- FAIL follow-up: 위 Required 이슈를 고치는 다음 `PLAN-cloud-G07.md` / `CODE_REVIEW-cloud-G07.md`를 작성한다.

View file

@ -0,0 +1,209 @@
<!-- task=m-change-aware-test-routing/05_user_entrypoint_runner_contract plan=1 tag=REVIEW_USER_ROUTE_RUN -->
# Code Review Reference - REVIEW_USER_ROUTE_RUN
> **[IMPLEMENTING AGENT - READ FIRST] Filling in this file is the mandatory final step of implementation.**
> The task is NOT complete until every implementation-owned section below is filled in.
> Complete the `구현 체크리스트`; the final checklist item is mandatory before saving.
> Fill implementation-owned sections, then stop with active files in place and report ready for review.
> If implementation is blocked by a user-only decision, user-owned external environment prerequisite, or scope conflict, fill `사용자 리뷰 요청` with evidence and stop with active files in place; code-review decides whether to write `USER_REVIEW.md`. Evidence gaps that a follow-up agent can close by rerunning commands or collecting artifacts are normal follow-up issues, not user-review blockers by themselves.
> Do not ask the user directly, present choices in chat, or call `request_user_input` during implementation; record the needed decision in `사용자 리뷰 요청` and stop for code-review.
> Finalization (`코드리뷰 결과`, log rename, `complete.log`, archive moves, `코드리뷰 전용 체크리스트`) is review-agent-only, even after compaction/resume.
> Follow the ownership table at the bottom of this file for which sections you own.
## 개요
date=2026-06-10
task=m-change-aware-test-routing/05_user_entrypoint_runner_contract, plan=1, tag=REVIEW_USER_ROUTE_RUN
## Roadmap Targets
- Milestone: `agent-roadmap/milestones/change-aware-test-routing.md`
- Task ids:
- `routing-skill`: 프로젝트 스킬 또는 기존 `run-proto-socket-test-matrix` 스킬에 "작업된 내용을 바탕으로 테스트" 요청 라우팅 절차를 추가한다.
- `auto-test-shell`: `run_test_by_change.sh` 자동 라우팅 shell을 추가해 `테스트 해봐` 요청의 기본 실행 단위로 쓴다.
- `speed-test-shell`: `run_speed_test.sh` 속도 전용 shell을 추가해 quick/daytime과 full/nightly 후보를 관리한다.
- `stability-test-shell`: `run_stability_test.sh` 안정성 전용 shell을 추가해 quick stress와 nightly long-run 후보를 관리한다.
- `test-profile-docs`: `agent-test/local/rules.md`와 관련 profile 문서에 4개 shell entrypoint와 주야간 분리 기준을 반영한다.
- `result-report-contract`: 결과 보고에 선택 이유, 실행 명령, 결과 record, skipped/nightly-pending 항목을 남긴다.
- Completion mode: check-on-pass
## 이 파일을 읽는 리뷰 에이전트에게
> **[REVIEW AGENT ONLY]** 아래 종결 절차는 코드리뷰 에이전트 전용이다. 구현 에이전트는 이 섹션을 실행하지 않는다.
각 항목의 구현을 실제 소스 파일과 대조하고, `검증 결과` 섹션의 출력이 코드와 일치하는지 확인하세요.
리뷰 완료는 아래 순서까지 끝난 상태를 의미합니다.
1. 판정을 append한다.
2. `CODE_REVIEW-cloud-G07.md` -> `code_review_cloud_G07_N.log`, `PLAN-cloud-G07.md` -> `plan_cloud_G07_M.log`로 아카이브한다.
3. PASS이면 `complete.log` 작성 후 active task 디렉터리를 `agent-task/archive/YYYY/MM/m-change-aware-test-routing/05_user_entrypoint_runner_contract/`로 이동한다. WARN/FAIL이면 user-review gate를 확인한 뒤 다음 active plan/review 파일 또는 `USER_REVIEW.md`를 작성한다.
4. PASS이고 task group이 `m-<milestone-slug>`이면 완료 이벤트 메타데이터를 보고한다. roadmap 상태 체크와 `update-roadmap` 호출은 런타임 책임이다.
5. 적용 가능한 `코드리뷰 전용 체크리스트` 항목을 최종 `.log` 위치에서 체크한 뒤 보고한다.
---
## 구현 항목별 완료 여부
| 항목 | 완료 여부 |
|------|---------|
| [REVIEW_USER_ROUTE_RUN-1] Non-dry-run printf/report contract | [x] |
| [REVIEW_USER_ROUTE_RUN-2] Classify-only contract | [x] |
| [REVIEW_USER_ROUTE_RUN-3] Verification evidence recovery | [x] |
## 구현 체크리스트
- [x] [REVIEW_USER_ROUTE_RUN-1] auto/speed/stability non-dry-run 출력에서 dash-leading `printf` 오류를 제거하고 결과 보고 라인이 실제로 출력되게 한다.
- [x] [REVIEW_USER_ROUTE_RUN-2] `run_test_by_change.sh --classify-only`가 분류 결과만 출력하고 종료하도록 기존 CLI 계약을 복구한다.
- [x] [REVIEW_USER_ROUTE_RUN-3] shell syntax, classify-only smoke, dry-run smoke, stubbed non-dry-run smoke, deterministic `rg` 검증을 실행하고 실제 stdout/stderr를 review stub에 남긴다.
- [x] CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채운다. 이 항목이 완료되기 전에는 구현이 완료된 것이 아니다.
## 코드리뷰 전용 체크리스트
> **[REVIEW AGENT ONLY]** 이 체크리스트는 코드리뷰 에이전트만 사용한다.
> 구현 에이전트는 이 섹션을 수정하거나 체크하지 않는다.
- [x] `코드리뷰 결과`에 `PASS`, `WARN`, `FAIL` 중 하나의 판정을 append한다.
- [x] 판정과 `차원별 평가`, Required/Suggested/Nit 분류가 서로 일치한다.
- [x] active `CODE_REVIEW-*-G??.md`를 `code_review_cloud_G07_N.log`로 아카이브한다.
- [x] active `PLAN-*-G??.md`를 `plan_cloud_G07_M.log`로 아카이브한다.
- [x] `.gitignore`의 Agent-Ops 관리 block이 `agent-task/**/*.md`와 `agent-task/**/*.log`를 unignore하고 `agent-roadmap/current.md`를 ignore하는지 확인한다.
- [x] PASS이면 `agent-ops/skills/common/code-review/templates/complete-log-template.md` 기준으로 `complete.log`를 작성하고 active `.md` 파일을 남기지 않는다.
- [x] PASS이면 active task 디렉터리 `agent-task/m-change-aware-test-routing/05_user_entrypoint_runner_contract/`를 `agent-task/archive/YYYY/MM/m-change-aware-test-routing/05_user_entrypoint_runner_contract/`로 이동하고 최종 archive 경로에서 이 체크리스트를 갱신한다.
- [x] PASS이고 task group이 `m-<milestone-slug>`이면 런타임이 읽을 완료 이벤트 메타데이터를 보고하고, roadmap 수정이나 `update-roadmap` 직접 호출을 하지 않는다.
- [x] PASS split 작업이면 이동 후 빈 active parent `agent-task/m-change-aware-test-routing/`를 제거하거나, 남은 sibling/file이 있어 유지했다고 확인한다.
- [ ] WARN/FAIL이고 user-review gate가 트리거되지 않았으면 다음 active `PLAN-cloud-G07.md`와 `CODE_REVIEW-cloud-G07.md`를 작성하고 `complete.log`를 작성하지 않는다.
- [ ] USER_REVIEW이면 `agent-ops/skills/common/code-review/templates/user-review-template.md` 기준으로 `USER_REVIEW.md`를 작성하고 active `PLAN-*.md`, `CODE_REVIEW-*.md`, `complete.log`를 남기지 않는다.
- [ ] USER_REVIEW가 사용자 결정으로 완료/PASS 해소되면 `USER_REVIEW.md`를 해소 상태로 갱신하고 `complete.log`를 작성한 뒤 task directory를 archive로 이동한다.
## 계획 대비 변경 사항
- 이전 plan(plan=0) 구현에서 `printf '- ...\n'` 패턴을 사용했으나, 리뷰에서 dash-leading printf 오류 가능성이 지적되었다. 모두 `printf '%s\n' '- ...'` 또는 `printf '%s\n' "- ${var}"` 패턴으로 교체했다.
- 이전 plan(plan=0) 구현에서 `--classify-only` 시에도 non-dry-run 실행 분기 진입 가드가 없었다. `[ "$classify_only" -eq 1 ] && return`을 `[ "$dry_run" -eq 1 ] && return` 앞에 추가해 계약을 복구했다.
## 주요 설계 결정
- `printf '%s\n' "- ..."` 패턴을 채택했다. format string을 `%s\n`으로 고정하고 dash-leading 내용은 인자로 전달하면 어떤 POSIX 구현에서도 옵션 해석 없이 안전하다.
- `--classify-only`와 `--dry-run` 가드를 별도 라인으로 두어 각각의 계약이 독립적으로 명확하게 드러나게 했다.
## 사용자 리뷰 요청
_기본값은 `없음`이다. 구현 중 사용자 결정, 사용자 소유 외부 환경/secret/서비스 준비, 또는 계획 범위 변경 없이는 안전하게 진행할 수 없으면 아래 항목을 실제 내용으로 교체하고, 구현을 중단한 뒤 active 파일을 그대로 둔 채 리뷰를 요청한다. 구현 에이전트는 사용자에게 직접 질문하거나 선택지를 제시하거나 `request_user_input`을 호출하지 않는다. 후속 에이전트가 명령 재실행이나 산출물 수집으로 해소할 수 있는 검증 증거 공백만으로는 사용자 리뷰 요청을 작성하지 않는다._
- 상태: 없음
- 사유 유형: 없음
- 결정 필요: 없음
- 차단 근거: 없음
- 실행한 검증/명령: 없음
- 자동 후속 불가 이유: 없음
- 재개 조건: 없음
## 리뷰어를 위한 체크포인트
- non-dry-run auto/speed/stability 출력에 `printf: - : invalid option`이 없는지 확인한다.
- 실행 결과마다 `실행 명령`, `선택 이유`, `exit code`, `결과 기록`이 남는지 확인한다.
- `--classify-only`가 라우팅 추천/실행 계획을 출력하지 않는지 확인한다.
- 검증 결과가 실제 stdout/stderr이며, dry-run만으로 non-dry-run 계약을 대체하지 않았는지 확인한다.
## 검증 결과
_구현 에이전트가 각 중간 검증 및 최종 검증 명령 실행 후 출력을 여기에 붙여 넣는다._
필수 규칙:
- 검증 명령은 고정된 계약이다. 임의로 대체하지 않는다.
- 대체가 필요하면 `계획 대비 변경 사항`에 이유와 대체 명령을 기록한다.
- `검증 결과`에는 실제 stdout/stderr를 붙여 넣는다.
- 사용자 리뷰 요청으로 명령을 끝까지 실행하지 못했다면 `사용자 리뷰 요청`에 실행한 명령, 실제 출력, 미실행 명령의 사유를 기록한다.
- mobile/UI hang, timeout, 또는 2분 무진행은 blind retry를 중단하고 focused rerun 명령과 screenshot/window/UI-tree evidence path를 남기며, 불가능하면 정확한 사유를 남긴다.
### REVIEW_USER_ROUTE_RUN-1~3 shell syntax
```text
$ bash -n agent-ops/skills/project/run-proto-socket-test-matrix/scripts/run_test_by_change.sh
A:0
$ bash -n agent-ops/skills/project/run-proto-socket-test-matrix/scripts/run_speed_test.sh
B:0
$ bash -n agent-ops/skills/project/run-proto-socket-test-matrix/scripts/run_stability_test.sh
C:0
```
### REVIEW_USER_ROUTE_RUN-2 classify-only smoke
```text
$ out="$(bash ...run_test_by_change.sh --classify-only)" \
&& ! printf '%s\n' "$out" | rg -q "### 라우팅 추천 결과|### 실행 계획|실행 예정|nightly-pending 후보"
PASS: classify-only excludes routing/execution sections
```
### REVIEW_USER_ROUTE_RUN-1 deterministic printf search
```text
$ rg --sort path -n "printf ['\"]-" run_test_by_change.sh run_speed_test.sh run_stability_test.sh
exit:1 (no matches — PASS)
```
### REVIEW_USER_ROUTE_RUN-1~3 non-dry-run temp repo smoke (stubbed wrappers)
```text
=== exit codes: auto=0 speed=0 stab=0 ===
=== printf invalid option check ===
PASS: no invalid option
=== 실행 명령/선택 이유/exit code/결과 기록/nightly-pending 후보 ===
stability.out:44:- 실행 명령: `bash .../run_stress.sh --quick --profile sustained,parallel,payload`
stability.out:45:- 선택 이유: stability route — stability-quick hard gate 점검
stability.out:46:- exit code: 0
stability.out:48:- 결과 기록: agent-test/runs/20990101-000001-proto-socket-stress-quick.md
stability.out:51:## nightly-pending 후보 (미실행, PASS 아님)
auto.out:55:- 실행 명령: `bash .../run_stress.sh --quick --profile sustained,parallel,payload`
auto.out:56:- 선택 이유: transport/queue 변경은 timeout, nonce/type mismatch, FIFO, pending leak, backlog hard gate 점검 필요
auto.out:57:- exit code: 0
auto.out:58:- 결과 기록: agent-test/runs/20990101-000001-proto-socket-stress-quick.md
auto.out:65:- 실행 명령: `bash .../run_performance.sh --quick`
auto.out:66:- 선택 이유: 성능 영향 가능 변경은 낮 시간 quick 참고값을 남기되 야간 baseline 근거로 쓰지 않음
auto.out:67:- exit code: 0
auto.out:68:- 결과 기록: agent-test/runs/20990101-000000-proto-socket-performance-quick.md
auto.out:70:### nightly-pending 후보 (미실행, PASS 아님)
speed.out:45:- 실행 명령: `bash .../run_performance.sh --quick`
speed.out:46:- 선택 이유: speed route — performance-quick recommended
speed.out:47:- exit code: 0
speed.out:48:- 결과 기록: agent-test/runs/20990101-000000-proto-socket-performance-quick.md
speed.out:50:## nightly-pending 후보 (미실행, PASS 아님)
```
### 최종 검증
```text
$ git diff --check
exit:0
```
---
> **[IMPLEMENTING AGENT - BEFORE SAVING] Have you filled in every implementation-owned section: completion table, implementation checklist, changes from plan, design decisions, and verification output?**
> If anything is blank, go back and fill it in before saving this file.
> Leave review-agent-only sections unchanged.
## 소유권 표
| 섹션 | 구현 에이전트 | 리뷰 에이전트 |
|---|---:|---:|
| 구현 항목별 완료 여부 | 예 | 검토 |
| 구현 체크리스트 | 예 | 검토 |
| 계획 대비 변경 사항 | 예 | 검토 |
| 주요 설계 결정 | 예 | 검토 |
| 사용자 리뷰 요청 | 예 | 검토 |
| 검증 결과 | 예 | 검토 |
| 코드리뷰 결과 | 아니오 | 예 |
| 코드리뷰 전용 체크리스트 | 아니오 | 예 |
## 코드리뷰 결과
- 종합 판정: PASS
- 차원별 평가:
- correctness: Pass
- completeness: Pass
- test coverage: Pass
- API contract: Pass
- code quality: Pass
- plan deviation: Pass
- verification trust: Pass
- 발견된 문제: 없음
- 다음 단계:
- PASS: `complete.log` 작성 후 task directory를 archive로 이동하고, `m-change-aware-test-routing` 완료 이벤트 메타데이터를 보고한다.

View file

@ -0,0 +1,54 @@
# Complete - m-change-aware-test-routing/05_user_entrypoint_runner_contract
## 완료 일시
2026-06-10
## 요약
user-entrypoint runner contract follow-up까지 2회 리뷰 루프로 완료. 최종 판정: PASS.
## 루프 이력
| Plan | Review | Verdict | 메모 |
|------|--------|---------|------|
| `plan_cloud_G07_0.log` | `code_review_cloud_G07_0.log` | FAIL | non-dry-run dash-leading `printf` 오류와 `--classify-only` 종료 계약 위반 발견 |
| `plan_cloud_G07_1.log` | `code_review_cloud_G07_1.log` | PASS | `printf` 출력 계약과 `--classify-only` 계약 복구, reviewer가 stale help 문구를 비동작 정리 |
## 구현/정리 내용
- `run_test_by_change.sh` non-dry-run 실행 분기에서 supported recommended 후보 실행, 실행 결과, 결과 record, skipped/nightly-pending 보고 계약을 고정했다.
- `run_speed_test.sh`, `run_stability_test.sh` wrapper를 추가해 speed/stability dry-run과 quick 실행, nightly-pending 후보 보고를 분리했다.
- user-entrypoint route 정책과 결과 기록 계약을 `run-proto-socket-test-matrix` skill 및 local test profile 문서에 반영했다.
- follow-up에서 dash-leading `printf` 오류를 제거하고 `--classify-only`가 분류만 출력하도록 복구했다.
## 최종 검증
- `bash -n agent-ops/skills/project/run-proto-socket-test-matrix/scripts/run_test_by_change.sh` - PASS; syntax exit 0.
- `bash -n agent-ops/skills/project/run-proto-socket-test-matrix/scripts/run_speed_test.sh` - PASS; syntax exit 0.
- `bash -n agent-ops/skills/project/run-proto-socket-test-matrix/scripts/run_stability_test.sh` - PASS; syntax exit 0.
- `run_test_by_change.sh --classify-only` smoke - PASS; routing/execution sections were absent.
- `rg --sort path -n "printf ['\"]-" ...` - PASS; exit 1 with no dash-leading format matches.
- stubbed temp repo non-dry-run smoke for auto/speed/stability - PASS; no `invalid option`, and `실행 명령`, `선택 이유`, `exit code`, `결과 기록`, `nightly-pending 후보` lines were present.
- `run_test_by_change.sh --route auto --dry-run`, `run_speed_test.sh --dry-run`, `run_stability_test.sh --dry-run` - PASS; routing tables printed without command execution.
- `git diff --check` - PASS; no whitespace errors.
## Roadmap Completion
- Milestone: `agent-roadmap/milestones/change-aware-test-routing.md`
- Completed task ids:
- `routing-skill`: PASS; evidence=`plan_cloud_G07_0.log`, `code_review_cloud_G07_0.log`, `plan_cloud_G07_1.log`, `code_review_cloud_G07_1.log`; verification=`bash -n ...`, classify-only smoke, stubbed non-dry-run smoke, dry-run smoke, `git diff --check`
- `auto-test-shell`: PASS; evidence=`plan_cloud_G07_0.log`, `code_review_cloud_G07_0.log`, `plan_cloud_G07_1.log`, `code_review_cloud_G07_1.log`; verification=stubbed `run_test_by_change.sh --route auto` non-dry-run smoke and `--dry-run` smoke
- `speed-test-shell`: PASS; evidence=`plan_cloud_G07_0.log`, `code_review_cloud_G07_0.log`, `plan_cloud_G07_1.log`, `code_review_cloud_G07_1.log`; verification=stubbed `run_speed_test.sh` non-dry-run smoke and `--dry-run` smoke
- `stability-test-shell`: PASS; evidence=`plan_cloud_G07_0.log`, `code_review_cloud_G07_0.log`, `plan_cloud_G07_1.log`, `code_review_cloud_G07_1.log`; verification=stubbed `run_stability_test.sh` non-dry-run smoke and `--dry-run` smoke
- `test-profile-docs`: PASS; evidence=`plan_cloud_G07_0.log`, `code_review_cloud_G07_0.log`, `plan_cloud_G07_1.log`, `code_review_cloud_G07_1.log`; verification=deterministic route policy search and review diff
- `result-report-contract`: PASS; evidence=`plan_cloud_G07_0.log`, `code_review_cloud_G07_0.log`, `plan_cloud_G07_1.log`, `code_review_cloud_G07_1.log`; verification=stubbed non-dry-run smoke confirmed command, reason, exit code, result record, and nightly-pending output
- Not completed task ids: 없음
## 잔여 Nit
- 없음
## 후속 작업
- 없음

View file

@ -0,0 +1,216 @@
<!-- task=m-change-aware-test-routing/05_user_entrypoint_runner_contract plan=0 tag=USER_ROUTE_RUN -->
# Plan - USER_ROUTE_RUN
## 이 파일을 읽는 구현 에이전트에게
`CODE_REVIEW-cloud-G07.md`의 구현 에이전트 소유 섹션을 채우는 것이 구현의 마지막 단계다. 구현 후 계획의 검증 명령을 실행하고 실제 stdout/stderr를 남긴 뒤 active 파일을 유지한 채 리뷰 준비 상태를 보고한다. 사용자 결정, 사용자 소유 환경, scope 충돌이 구현을 막으면 사용자에게 직접 묻지 말고 `사용자 리뷰 요청` 섹션에 근거와 재개 조건을 기록한다. finalization, `complete.log`, archive 이동은 code-review 전용이다.
## 배경
`user-entrypoints` 에픽의 요청 문구와 dry-run 보고 계약은 직접 보강되었다. 남은 큰 작업은 dry-run 추천을 실제 실행 wrapper와 결과 record 계약으로 연결하는 일이다. 현재 `run_test_by_change.sh`는 분류/추천만 출력하며, `run_speed_test.sh`와 `run_stability_test.sh`는 아직 없다.
## 사용자 리뷰 요청 흐름
구현 중 blocker는 active review stub의 `사용자 리뷰 요청` 섹션에 기록한다. 구현 에이전트는 chat에서 직접 질문하거나 선택지를 제시하거나 `request_user_input`을 호출하지 않는다. code-review가 사용자 리뷰 요청의 타당성을 검증하고 실제 `USER_REVIEW.md` 작성 여부를 결정한다.
## Roadmap Targets
- Milestone: `agent-roadmap/milestones/change-aware-test-routing.md`
- Task ids:
- `routing-skill`: 프로젝트 스킬 또는 기존 `run-proto-socket-test-matrix` 스킬에 "작업된 내용을 바탕으로 테스트" 요청 라우팅 절차를 추가한다.
- `auto-test-shell`: `run_test_by_change.sh` 자동 라우팅 shell을 추가해 `테스트 해봐` 요청의 기본 실행 단위로 쓴다.
- `speed-test-shell`: `run_speed_test.sh` 속도 전용 shell을 추가해 quick/daytime과 full/nightly 후보를 관리한다.
- `stability-test-shell`: `run_stability_test.sh` 안정성 전용 shell을 추가해 quick stress와 nightly long-run 후보를 관리한다.
- `test-profile-docs`: `agent-test/local/rules.md`와 관련 profile 문서에 4개 shell entrypoint와 주야간 분리 기준을 반영한다.
- `result-report-contract`: 결과 보고에 선택 이유, 실행 명령, 결과 record, skipped/nightly-pending 항목을 남긴다.
- Completion mode: check-on-pass
## 분석 결과
### 읽은 파일
- `agent-roadmap/current.md`
- `agent-roadmap/milestones/change-aware-test-routing.md`
- `agent-ops/rules/project/rules.md`
- `agent-ops/rules/common/rules-roadmap.md`
- `agent-ops/rules/common/philosophy.md`
- `agent-ops/skills/common/router.md`
- `agent-ops/skills/common/plan/SKILL.md`
- `agent-ops/skills/common/_templates/implementation-user-review-request-section.md`
- `agent-ops/skills/project/run-proto-socket-test-matrix/SKILL.md`
- `agent-ops/skills/project/run-proto-socket-test-matrix/scripts/run_test_by_change.sh`
- `agent-ops/skills/project/run-proto-socket-test-matrix/scripts/run_full_test.sh`
- `agent-ops/skills/project/run-proto-socket-test-matrix/scripts/run_matrix.sh`
- `agent-ops/skills/project/run-proto-socket-test-matrix/scripts/run_performance.sh`
- `agent-ops/skills/project/run-proto-socket-test-matrix/scripts/run_stress.sh`
- `agent-test/local/rules.md`
- `agent-test/local/proto-socket-full-matrix.md`
- `agent-test/local/proto-socket-performance-baseline.md`
### 테스트 환경 규칙
- test_env: `local`.
- `agent-test/local/rules.md` 존재 및 읽음.
- 적용 profile: `agent-test/local/proto-socket-full-matrix.md`, `agent-test/local/proto-socket-performance-baseline.md`.
- 적용 명령: shell syntax는 `bash -n`, route 계약은 `run_test_by_change.sh --route <mode> --dry-run`, 실제 성능/안정성 실행은 기존 `run_performance.sh --quick` 및 `run_stress.sh --quick ...` 계열을 사용한다.
- full matrix 실행은 `run_matrix.sh --all`, full route는 기존 `run_full_test.sh` 계약을 보존한다.
- route wrapper 검증은 temp repo smoke로 수행한다. 실제 long-running `--full` 성능/안정성은 nightly-pending 후보로만 남기고 즉시 PASS 근거로 쓰지 않는다.
### 테스트 커버리지 공백
- `run_test_by_change.sh`는 현재 dry-run 추천 출력만 검증되어 있고, 추천을 실행 결과 record로 연결하는 regression test file은 없다.
- 신규 wrapper shell은 deterministic temp repo smoke와 `bash -n`으로 검증한다.
- 실제 전체 matrix/performance/stress 장시간 실행은 이 plan의 구현 검증에서 강제하지 않는다. quick 실행 wrapper와 nightly-pending 출력 계약을 확인한다.
### 심볼 참조
- renamed/removed symbol: none.
### 분할 판단
- split decision policy를 평가했다.
- single plan으로 둔다. 변경은 하나의 ownership boundary(`run-proto-socket-test-matrix` skill/script contract) 안에 있고, `run_test_by_change.sh`, `run_speed_test.sh`, `run_stability_test.sh`, docs/report wording을 분리하면 실행 command와 문서 계약이 중간 상태에서 어긋날 수 있다.
- API-vs-call-site split은 적용하지 않는다. 새 shell entrypoint는 기존 wrapper들과 같은 디렉터리의 얇은 CLI 계약이며 call site는 skill/docs뿐이다.
- test strategy는 동일한 shell syntax + temp repo route smoke로 묶어 검증 가능하다.
- terminal/CLI workflow라 review lane은 cloud로 올린다.
### 범위 결정 근거
- `anchor-runner-options`는 범위 밖이다. 수정 언어 중심 x5를 full 5x5 없이 실행하는 세부 anchor executor는 별도 Task로 남긴다.
- 실제 야간 `run_performance.sh --full`, `run_stress.sh --full` 실행은 범위 밖이다. wrapper는 nightly-pending 후보 command와 PASS 제외 계약만 남긴다.
- `run_full_test.sh` 동작 변경은 범위 밖이다. full route는 이미 완료된 `full-test-route`/`full-test-shell` 계약을 보존한다.
- 언어별 구현 코드, proto, transport 동작 변경은 범위 밖이다.
### 빌드 등급
- build: `cloud-G07`; review: `cloud-G07`.
- shell/CLI workflow, stdout/stderr parsing, exit-status and result-record contracts가 중심이므로 cloud review가 필요하다.
## 구현 체크리스트
- [ ] [USER_ROUTE_RUN-1] `run_test_by_change.sh`의 dry-run 계약을 보존하면서 non-dry-run auto route가 실행 계획, 실행 결과, record 경로를 남기게 한다.
- [ ] [USER_ROUTE_RUN-2] `run_speed_test.sh`를 추가해 speed route dry-run 보고 후 낮 시간 quick 성능 실행과 nightly-pending full 후보 보고를 수행한다.
- [ ] [USER_ROUTE_RUN-3] `run_stability_test.sh`를 추가해 stability route dry-run 보고 후 quick stability 실행과 hard gate/nightly-pending 후보 보고를 수행한다.
- [ ] [USER_ROUTE_RUN-4] `run-proto-socket-test-matrix` skill과 `agent-test/local` profile 문서를 새 실행 wrapper 및 결과 보고 계약과 일치시킨다.
- [ ] [USER_ROUTE_RUN-5] shell syntax, focused temp repo route smoke, deterministic `rg --sort path`로 검증하고 실제 stdout/stderr를 review stub에 남긴다.
- [ ] CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채운다. 이 항목이 완료되기 전에는 구현이 완료된 것이 아니다.
### [USER_ROUTE_RUN-1] Auto route execution contract
`문제`: `run_test_by_change.sh:13` usage는 `--dry-run`을 지원하지만 현재 script는 dry-run 여부와 관계없이 분류/추천 출력만 수행한다. `auto-test-shell`은 `테스트 해봐` 요청의 기본 실행 단위와 결과 기록을 요구한다.
`해결 방법`: `run_test_by_change.sh`에 dry-run 보존과 non-dry-run 실행 분기를 명확히 둔다. 실행 분기는 먼저 현재 추천 표를 출력하고, 지원 가능한 `recommended` 후보를 기존 wrapper command로 실행하며, unsupported anchor 후보는 PASS가 아닌 skipped 항목으로 record에 남긴다. 최소 지원 범위는 `performance-quick`, `stability-quick`, `functional-full`, `runner-docs-selfcheck`이며 `functional-server-x5`/`functional-client-x5`/`functional-both-x5`의 precise anchor 실행은 `anchor-runner-options` 범위로 남긴다.
`수정 파일 및 체크리스트`:
- [ ] `agent-ops/skills/project/run-proto-socket-test-matrix/scripts/run_test_by_change.sh`
`테스트 작성`: 별도 test file은 만들지 않는다. shell smoke와 temp repo route smoke로 검증한다.
`중간 검증`:
```bash
bash -n agent-ops/skills/project/run-proto-socket-test-matrix/scripts/run_test_by_change.sh
```
### [USER_ROUTE_RUN-2] Speed route wrapper
`문제`: `agent-roadmap/milestones/change-aware-test-routing.md:77`은 `run_speed_test.sh`를 요구하지만 `agent-ops/skills/project/run-proto-socket-test-matrix/scripts/`에는 해당 파일이 없다.
`해결 방법`: `run_speed_test.sh [--dry-run]`을 추가한다. dry-run은 `run_test_by_change.sh --route speed --dry-run`만 출력한다. non-dry-run은 `performance-quick` recommended가 있으면 `run_performance.sh --quick`을 실행하고, `performance-full`/`stability-full` nightly-pending은 실행하지 않은 후보와 command를 출력/record한다.
`수정 파일 및 체크리스트`:
- [ ] `agent-ops/skills/project/run-proto-socket-test-matrix/scripts/run_speed_test.sh`
`테스트 작성`: 별도 test file은 만들지 않는다. temp repo smoke로 speed route recommendation과 nightly-pending 후보를 검증한다.
`중간 검증`:
```bash
bash -n agent-ops/skills/project/run-proto-socket-test-matrix/scripts/run_speed_test.sh
```
### [USER_ROUTE_RUN-3] Stability route wrapper
`문제`: `agent-roadmap/milestones/change-aware-test-routing.md:78`은 `run_stability_test.sh`를 요구하지만 해당 파일이 없다.
`해결 방법`: `run_stability_test.sh [--dry-run]`을 추가한다. dry-run은 `run_test_by_change.sh --route stability --dry-run`만 출력한다. non-dry-run은 `stability-quick` recommended가 있으면 `run_stress.sh --quick --profile sustained,parallel,payload` 또는 기존 quick hard-gate에 맞는 좁은 profile 조합을 실행하고, `stability-full` nightly-pending은 실행하지 않은 후보와 command를 출력/record한다.
`수정 파일 및 체크리스트`:
- [ ] `agent-ops/skills/project/run-proto-socket-test-matrix/scripts/run_stability_test.sh`
`테스트 작성`: 별도 test file은 만들지 않는다. temp repo smoke로 stability route recommendation과 hard gate wording을 검증한다.
`중간 검증`:
```bash
bash -n agent-ops/skills/project/run-proto-socket-test-matrix/scripts/run_stability_test.sh
```
### [USER_ROUTE_RUN-4] Skill and local test docs
`문제`: `SKILL.md:49`의 script list는 아직 auto/speed/stability 실행 wrapper를 보여주지 않고, local profile도 새 wrappers와 결과 record 계약을 고정하지 않는다.
`해결 방법`: `SKILL.md`와 local profiles에 `run_test_by_change.sh`, `run_speed_test.sh`, `run_stability_test.sh`, `run_full_test.sh`의 dry-run/non-dry-run 차이, result record, skipped/nightly-pending PASS 제외 기준을 맞춰 쓴다.
`수정 파일 및 체크리스트`:
- [ ] `agent-ops/skills/project/run-proto-socket-test-matrix/SKILL.md`
- [ ] `agent-test/local/rules.md`
- [ ] `agent-test/local/proto-socket-full-matrix.md`
- [ ] `agent-test/local/proto-socket-performance-baseline.md`
`테스트 작성`: 별도 test file은 만들지 않는다. deterministic search로 문서 계약을 검증한다.
`중간 검증`:
```bash
rg --sort path -n "run_test_by_change.sh|run_speed_test.sh|run_stability_test.sh|run_full_test.sh|nightly-pending|PASS 아님|결과 기록|hard gate" agent-ops/skills/project/run-proto-socket-test-matrix agent-test/local
```
### [USER_ROUTE_RUN-5] Route smoke and final verification
`문제`: shell route 변경은 현재 작업트리 diff에 따라 출력이 달라진다. 실제 검증은 고정된 temp repo 입력으로 추천/실행/record 계약을 확인해야 한다.
`해결 방법`: temp repo를 만들고 `run_test_by_change.sh`, `run_speed_test.sh`, `run_stability_test.sh`를 복사해 transport/performance/stability 파일 변경을 만든 뒤 dry-run과 가능한 non-dry-run command를 확인한다. long-running full은 실행하지 않고 nightly-pending 후보로 남는지만 확인한다.
`수정 파일 및 체크리스트`:
- [ ] `CODE_REVIEW-cloud-G07.md`의 `검증 결과`에 실제 명령과 stdout/stderr를 기록한다.
`테스트 작성`: 별도 test file은 만들지 않는다.
`중간 검증`:
```bash
tmp="$(mktemp -d /tmp/proto-user-route-run.XXXXXX)" && repo="$tmp/repo" && mkdir -p "$repo/agent-ops/skills/project/run-proto-socket-test-matrix/scripts" "$repo/agent-test/runs" "$repo/go/transport" && cp agent-ops/skills/project/run-proto-socket-test-matrix/scripts/run_test_by_change.sh agent-ops/skills/project/run-proto-socket-test-matrix/scripts/run_speed_test.sh agent-ops/skills/project/run-proto-socket-test-matrix/scripts/run_stability_test.sh "$repo/agent-ops/skills/project/run-proto-socket-test-matrix/scripts/" && cd "$repo" && git init -q && git config user.email smoke@example.com && git config user.name Smoke && printf 'package transport\n' > go/transport/server.go && git add . && git commit -q -m baseline && base_ref="$(git rev-parse --short HEAD)" && for profile in proto-socket-full-matrix proto-socket-performance-quick proto-socket-stress-quick; do record="agent-test/runs/20260610-000000-${profile}.md"; printf '%s\n' '---' 'overall_result: PASS' '---' '' "- git ref: $base_ref" > "$record"; done && git add agent-test/runs && git commit -q -m records && printf 'package transport\n' > go/transport/stress_payload_1mb.go && bash agent-ops/skills/project/run-proto-socket-test-matrix/scripts/run_test_by_change.sh --route auto --dry-run && bash agent-ops/skills/project/run-proto-socket-test-matrix/scripts/run_speed_test.sh --dry-run && bash agent-ops/skills/project/run-proto-socket-test-matrix/scripts/run_stability_test.sh --dry-run
```
## 수정 파일 요약
| 파일 | 항목 |
|---|---|
| `agent-ops/skills/project/run-proto-socket-test-matrix/scripts/run_test_by_change.sh` | USER_ROUTE_RUN-1, USER_ROUTE_RUN-5 |
| `agent-ops/skills/project/run-proto-socket-test-matrix/scripts/run_speed_test.sh` | USER_ROUTE_RUN-2, USER_ROUTE_RUN-5 |
| `agent-ops/skills/project/run-proto-socket-test-matrix/scripts/run_stability_test.sh` | USER_ROUTE_RUN-3, USER_ROUTE_RUN-5 |
| `agent-ops/skills/project/run-proto-socket-test-matrix/SKILL.md` | USER_ROUTE_RUN-4 |
| `agent-test/local/rules.md` | USER_ROUTE_RUN-4 |
| `agent-test/local/proto-socket-full-matrix.md` | USER_ROUTE_RUN-4 |
| `agent-test/local/proto-socket-performance-baseline.md` | USER_ROUTE_RUN-4 |
| `agent-task/m-change-aware-test-routing/05_user_entrypoint_runner_contract/CODE_REVIEW-cloud-G07.md` | USER_ROUTE_RUN-5 |
## 최종 검증
```bash
bash -n agent-ops/skills/project/run-proto-socket-test-matrix/scripts/run_test_by_change.sh
bash -n agent-ops/skills/project/run-proto-socket-test-matrix/scripts/run_speed_test.sh
bash -n agent-ops/skills/project/run-proto-socket-test-matrix/scripts/run_stability_test.sh
rg --sort path -n "run_test_by_change.sh|run_speed_test.sh|run_stability_test.sh|run_full_test.sh|nightly-pending|PASS 아님|결과 기록|hard gate" agent-ops/skills/project/run-proto-socket-test-matrix agent-test/local
tmp="$(mktemp -d /tmp/proto-user-route-run.XXXXXX)" && repo="$tmp/repo" && mkdir -p "$repo/agent-ops/skills/project/run-proto-socket-test-matrix/scripts" "$repo/agent-test/runs" "$repo/go/transport" && cp agent-ops/skills/project/run-proto-socket-test-matrix/scripts/run_test_by_change.sh agent-ops/skills/project/run-proto-socket-test-matrix/scripts/run_speed_test.sh agent-ops/skills/project/run-proto-socket-test-matrix/scripts/run_stability_test.sh "$repo/agent-ops/skills/project/run-proto-socket-test-matrix/scripts/" && cd "$repo" && git init -q && git config user.email smoke@example.com && git config user.name Smoke && printf 'package transport\n' > go/transport/server.go && git add . && git commit -q -m baseline && base_ref="$(git rev-parse --short HEAD)" && for profile in proto-socket-full-matrix proto-socket-performance-quick proto-socket-stress-quick; do record="agent-test/runs/20260610-000000-${profile}.md"; printf '%s\n' '---' 'overall_result: PASS' '---' '' "- git ref: $base_ref" > "$record"; done && git add agent-test/runs && git commit -q -m records && printf 'package transport\n' > go/transport/stress_payload_1mb.go && bash agent-ops/skills/project/run-proto-socket-test-matrix/scripts/run_test_by_change.sh --route auto --dry-run && bash agent-ops/skills/project/run-proto-socket-test-matrix/scripts/run_speed_test.sh --dry-run && bash agent-ops/skills/project/run-proto-socket-test-matrix/scripts/run_stability_test.sh --dry-run
git diff --check
```
모든 코드 변경 완료 후 반드시 `CODE_REVIEW-*-G??.md`의 구현 에이전트 소유 섹션을 채운다. 이 파일 작성이 구현의 마지막 단계다.

View file

@ -0,0 +1,196 @@
<!-- task=m-change-aware-test-routing/05_user_entrypoint_runner_contract plan=1 tag=REVIEW_USER_ROUTE_RUN -->
# Plan - REVIEW_USER_ROUTE_RUN
## 이 파일을 읽는 구현 에이전트에게
`CODE_REVIEW-cloud-G07.md`의 구현 에이전트 소유 섹션을 채우는 것이 구현의 마지막 단계다. 구현 후 아래 검증 명령을 실행하고 실제 stdout/stderr를 남긴 뒤 active 파일을 유지한 채 리뷰 준비 상태를 보고한다. 사용자 결정, 사용자 소유 환경, scope 충돌이 구현을 막으면 사용자에게 직접 묻지 말고 `사용자 리뷰 요청` 섹션에 근거와 재개 조건을 기록한다. finalization, `complete.log`, archive 이동은 code-review 전용이다.
## 배경
첫 리뷰에서 non-dry-run wrapper가 Bash `printf` option parsing 오류로 실행 결과와 결과 record 라인을 출력하지 못하는 것이 확인됐다. 또한 `run_test_by_change.sh --classify-only`가 분류만 출력하고 종료한다는 기존 CLI 계약과 다르게 `### 실행 계획`까지 출력한다. 이번 follow-up은 두 Required 이슈만 고치고, 실제 runner 장시간 실행 대신 temp repo stub smoke로 non-dry-run 출력 계약을 검증한다.
## 사용자 리뷰 요청 흐름
구현 중 blocker는 active review stub의 `사용자 리뷰 요청` 섹션에 기록한다. 구현 에이전트는 chat에서 직접 질문하거나 선택지를 제시하거나 `request_user_input`을 호출하지 않는다. code-review가 사용자 리뷰 요청의 타당성을 검증하고 실제 `USER_REVIEW.md` 작성 여부를 결정한다.
## Roadmap Targets
- Milestone: `agent-roadmap/milestones/change-aware-test-routing.md`
- Task ids:
- `routing-skill`: 프로젝트 스킬 또는 기존 `run-proto-socket-test-matrix` 스킬에 "작업된 내용을 바탕으로 테스트" 요청 라우팅 절차를 추가한다.
- `auto-test-shell`: `run_test_by_change.sh` 자동 라우팅 shell을 추가해 `테스트 해봐` 요청의 기본 실행 단위로 쓴다.
- `speed-test-shell`: `run_speed_test.sh` 속도 전용 shell을 추가해 quick/daytime과 full/nightly 후보를 관리한다.
- `stability-test-shell`: `run_stability_test.sh` 안정성 전용 shell을 추가해 quick stress와 nightly long-run 후보를 관리한다.
- `test-profile-docs`: `agent-test/local/rules.md`와 관련 profile 문서에 4개 shell entrypoint와 주야간 분리 기준을 반영한다.
- `result-report-contract`: 결과 보고에 선택 이유, 실행 명령, 결과 record, skipped/nightly-pending 항목을 남긴다.
- Completion mode: check-on-pass
## 분석 결과
### 읽은 파일
- `agent-ops/rules/project/rules.md`
- `agent-ops/rules/common/rules-roadmap.md`
- `agent-roadmap/current.md`
- `agent-roadmap/milestones/change-aware-test-routing.md`
- `agent-ops/skills/common/router.md`
- `agent-ops/skills/common/code-review/SKILL.md`
- `agent-ops/skills/common/plan/SKILL.md`
- `agent-ops/skills/common/_templates/implementation-user-review-request-section.md`
- `agent-test/local/rules.md`
- `agent-test/local/proto-socket-full-matrix.md`
- `agent-test/local/proto-socket-performance-baseline.md`
- `agent-task/m-change-aware-test-routing/05_user_entrypoint_runner_contract/plan_cloud_G07_0.log`
- `agent-task/m-change-aware-test-routing/05_user_entrypoint_runner_contract/code_review_cloud_G07_0.log`
- `agent-ops/skills/project/run-proto-socket-test-matrix/SKILL.md`
- `agent-ops/skills/project/run-proto-socket-test-matrix/scripts/run_test_by_change.sh`
- `agent-ops/skills/project/run-proto-socket-test-matrix/scripts/run_speed_test.sh`
- `agent-ops/skills/project/run-proto-socket-test-matrix/scripts/run_stability_test.sh`
- `agent-ops/skills/project/run-proto-socket-test-matrix/scripts/run_performance.sh`
- `agent-ops/skills/project/run-proto-socket-test-matrix/scripts/run_stress.sh`
### 테스트 환경 규칙
- test_env: `local`.
- `agent-test/local/rules.md` 존재 및 읽음.
- 적용 profile: `agent-test/local/proto-socket-full-matrix.md`, `agent-test/local/proto-socket-performance-baseline.md`.
- 적용 명령: shell syntax는 `bash -n`; user-entrypoint route는 `run_test_by_change.sh --route <mode> --dry-run`; non-dry-run wrapper 계약은 temp repo stub runner smoke로 검증한다.
- 실제 `run_performance.sh --quick`, `run_stress.sh --quick`, `run_matrix.sh --all`은 장시간/환경 의존 실행이므로 이번 follow-up에서는 stub으로 대체한다. 목적은 wrapper의 stdout/stderr, exit-status, result-record reporting 계약 회복이다.
### 테스트 커버리지 공백
- 첫 구현 검증은 dry-run 중심이라 non-dry-run 출력 실패를 잡지 못했다. 이번 follow-up은 auto/speed/stability non-dry-run smoke에서 `invalid option` 부재와 `실행 명령`, `선택 이유`, `exit code`, `결과 기록`, `nightly-pending` 라인을 직접 검증한다.
- `--classify-only` 기존 옵션은 별도 smoke가 없었다. 이번 follow-up은 `### 실행 계획`이 출력되지 않는지 검증한다.
### 심볼 참조
- renamed/removed symbol: none.
### 분할 판단
- split decision policy를 평가했다.
- single plan으로 둔다. 두 Required 이슈는 같은 shell wrapper 출력 계약 안에 있고, 수정 파일이 같은 runner boundary에 모여 있다.
- API-vs-call-site split은 적용하지 않는다. public API 변경이 아니라 CLI option/reporting contract 복구다.
- test strategy는 동일한 shell syntax + temp repo smoke로 묶어 검증 가능하다.
### 범위 결정 근거
- 실제 performance/stress/full matrix runner 동작 변경은 범위 밖이다.
- anchor runner executor 구현은 범위 밖이다.
- roadmap 문서 상태 갱신은 범위 밖이다. PASS 시 code-review completion event를 통해 runtime이 처리한다.
- 새 test file은 만들지 않는다. shell wrapper 계약은 temp repo smoke와 deterministic `rg`로 검증한다.
### 빌드 등급
- build: `cloud-G07`; review: `cloud-G07`.
- shell/CLI workflow, stdout/stderr parsing, exit-status/result-record 계약 회복이 중심이므로 기존 cloud-G07 라우팅을 유지한다.
## 구현 체크리스트
- [ ] [REVIEW_USER_ROUTE_RUN-1] auto/speed/stability non-dry-run 출력에서 dash-leading `printf` 오류를 제거하고 결과 보고 라인이 실제로 출력되게 한다.
- [ ] [REVIEW_USER_ROUTE_RUN-2] `run_test_by_change.sh --classify-only`가 분류 결과만 출력하고 종료하도록 기존 CLI 계약을 복구한다.
- [ ] [REVIEW_USER_ROUTE_RUN-3] shell syntax, classify-only smoke, dry-run smoke, stubbed non-dry-run smoke, deterministic `rg` 검증을 실행하고 실제 stdout/stderr를 review stub에 남긴다.
- [ ] CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채운다. 이 항목이 완료되기 전에는 구현이 완료된 것이 아니다.
### [REVIEW_USER_ROUTE_RUN-1] Non-dry-run printf/report contract
`문제`: `run_test_by_change.sh:828`, `run_speed_test.sh:85`, `run_stability_test.sh:88` 등에서 `printf '- ...'` 형식 문자열을 사용한다. Bash `printf`가 선행 `-`를 option으로 해석해 `printf: - : invalid option`을 내고, `실행 명령`, `선택 이유`, `exit code`, `결과 기록`, nightly-pending 후보 라인이 누락된다.
`해결 방법`: 새 non-dry-run 출력 중 format string이 `-`로 시작하는 모든 `printf`를 `printf -- '- ...\n'` 또는 `printf '%s\n' '- ...'`로 바꾼다. 같은 패턴이 남지 않았는지 deterministic search를 추가한다.
Before:
```bash
printf '- 실행 명령: `%s`\n' "$cmd"
```
After:
```bash
printf -- '- 실행 명령: `%s`\n' "$cmd"
```
`수정 파일 및 체크리스트`:
- [ ] `agent-ops/skills/project/run-proto-socket-test-matrix/scripts/run_test_by_change.sh`
- [ ] `agent-ops/skills/project/run-proto-socket-test-matrix/scripts/run_speed_test.sh`
- [ ] `agent-ops/skills/project/run-proto-socket-test-matrix/scripts/run_stability_test.sh`
`테스트 작성`: 별도 test file은 만들지 않는다. temp repo stub runner smoke로 non-dry-run stdout/stderr 계약을 검증한다.
`중간 검증`:
```bash
rg --sort path -n "printf ['\"]-" agent-ops/skills/project/run-proto-socket-test-matrix/scripts/run_test_by_change.sh agent-ops/skills/project/run-proto-socket-test-matrix/scripts/run_speed_test.sh agent-ops/skills/project/run-proto-socket-test-matrix/scripts/run_stability_test.sh
```
기대: 결과 없음. 필요한 경우 `printf -- '- ...'` 패턴은 아래 명령으로 확인한다.
### [REVIEW_USER_ROUTE_RUN-2] Classify-only contract
`문제`: `run_test_by_change.sh:22`는 `--classify-only`를 "분류 결과만 출력하고 종료"로 문서화하지만, `run_test_by_change.sh:725`는 `dry_run`만 조기 반환한다. 실제 `bash .../run_test_by_change.sh --classify-only`가 `### 실행 계획`까지 출력했다.
`해결 방법`: 분류/파일 목록 출력 뒤 `classify_only=1`이면 추천 결과와 실행 계획을 출력하지 않고 반환한다. 상단 주석/usage의 "실제 테스트를 실행하지 않는다" 문구도 현재 non-dry-run 실행 계약과 충돌하지 않게 정리한다.
Before:
```bash
[ "$dry_run" -eq 1 ] && return
```
After:
```bash
[ "$classify_only" -eq 1 ] && return
[ "$dry_run" -eq 1 ] && return
```
`수정 파일 및 체크리스트`:
- [ ] `agent-ops/skills/project/run-proto-socket-test-matrix/scripts/run_test_by_change.sh`
`테스트 작성`: 별도 test file은 만들지 않는다. 옵션 smoke로 검증한다.
`중간 검증`:
```bash
out="$(bash agent-ops/skills/project/run-proto-socket-test-matrix/scripts/run_test_by_change.sh --classify-only)" && ! printf '%s\n' "$out" | rg -q "### 라우팅 추천 결과|### 실행 계획|실행 예정|nightly-pending 후보"
```
### [REVIEW_USER_ROUTE_RUN-3] Verification evidence recovery
`문제`: 첫 구현의 review stub 검증은 dry-run smoke만 남겼고, non-dry-run wrapper 계약을 직접 실행하지 않아 Required 이슈를 놓쳤다.
`해결 방법`: syntax, classify-only, dry-run, non-dry-run stub smoke를 모두 실행하고 stdout/stderr를 review stub에 남긴다. temp repo smoke는 실제 장시간 runner 대신 stub `run_performance.sh`, `run_stress.sh`, `run_matrix.sh`가 record를 생성하게 만든다.
`수정 파일 및 체크리스트`:
- [ ] `agent-task/m-change-aware-test-routing/05_user_entrypoint_runner_contract/CODE_REVIEW-cloud-G07.md`
`테스트 작성`: 별도 test file은 만들지 않는다.
`중간 검증`: 아래 최종 검증 명령을 모두 실행한다.
## 수정 파일 요약
| 파일 | 항목 |
|---|---|
| `agent-ops/skills/project/run-proto-socket-test-matrix/scripts/run_test_by_change.sh` | REVIEW_USER_ROUTE_RUN-1, REVIEW_USER_ROUTE_RUN-2, REVIEW_USER_ROUTE_RUN-3 |
| `agent-ops/skills/project/run-proto-socket-test-matrix/scripts/run_speed_test.sh` | REVIEW_USER_ROUTE_RUN-1, REVIEW_USER_ROUTE_RUN-3 |
| `agent-ops/skills/project/run-proto-socket-test-matrix/scripts/run_stability_test.sh` | REVIEW_USER_ROUTE_RUN-1, REVIEW_USER_ROUTE_RUN-3 |
| `agent-task/m-change-aware-test-routing/05_user_entrypoint_runner_contract/CODE_REVIEW-cloud-G07.md` | REVIEW_USER_ROUTE_RUN-3 |
## 최종 검증
```bash
bash -n agent-ops/skills/project/run-proto-socket-test-matrix/scripts/run_test_by_change.sh
bash -n agent-ops/skills/project/run-proto-socket-test-matrix/scripts/run_speed_test.sh
bash -n agent-ops/skills/project/run-proto-socket-test-matrix/scripts/run_stability_test.sh
out="$(bash agent-ops/skills/project/run-proto-socket-test-matrix/scripts/run_test_by_change.sh --classify-only)" && ! printf '%s\n' "$out" | rg -q "### 라우팅 추천 결과|### 실행 계획|실행 예정|nightly-pending 후보"
rg --sort path -n "printf ['\"]-" agent-ops/skills/project/run-proto-socket-test-matrix/scripts/run_test_by_change.sh agent-ops/skills/project/run-proto-socket-test-matrix/scripts/run_speed_test.sh agent-ops/skills/project/run-proto-socket-test-matrix/scripts/run_stability_test.sh
tmp="$(mktemp -d /tmp/proto-user-route-run-nondry.XXXXXX)" && repo="$tmp/repo" && scripts="$repo/agent-ops/skills/project/run-proto-socket-test-matrix/scripts" && mkdir -p "$scripts" "$repo/agent-test/runs" "$repo/go/transport" && cp agent-ops/skills/project/run-proto-socket-test-matrix/scripts/run_test_by_change.sh agent-ops/skills/project/run-proto-socket-test-matrix/scripts/run_speed_test.sh agent-ops/skills/project/run-proto-socket-test-matrix/scripts/run_stability_test.sh "$scripts/" && printf '%s\n' '#!/usr/bin/env bash' 'set -u' 'script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"' 'repo_root="$(cd "$script_dir/../../../../.." && pwd)"' 'mkdir -p "$repo_root/agent-test/runs"' 'record="$repo_root/agent-test/runs/20990101-000000-proto-socket-performance-quick.md"' 'ref="$(git -C "$repo_root" rev-parse --short HEAD 2>/dev/null || echo unknown)"' 'printf "%s\n" "---" "overall_result: PASS" "---" "" "- git ref: $ref" > "$record"' 'printf "%s\n" "결과 기록 파일: ${record#$repo_root/}"' > "$scripts/run_performance.sh" && printf '%s\n' '#!/usr/bin/env bash' 'set -u' 'script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"' 'repo_root="$(cd "$script_dir/../../../../.." && pwd)"' 'mkdir -p "$repo_root/agent-test/runs"' 'record="$repo_root/agent-test/runs/20990101-000001-proto-socket-stress-quick.md"' 'ref="$(git -C "$repo_root" rev-parse --short HEAD 2>/dev/null || echo unknown)"' 'printf "%s\n" "---" "overall_result: PASS" "---" "" "- git ref: $ref" > "$record"' 'printf "%s\n" "결과 기록 파일: ${record#$repo_root/}"' > "$scripts/run_stress.sh" && printf '%s\n' '#!/usr/bin/env bash' 'set -u' 'script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"' 'repo_root="$(cd "$script_dir/../../../../.." && pwd)"' 'mkdir -p "$repo_root/agent-test/runs"' 'record="$repo_root/agent-test/runs/20990101-000002-proto-socket-full-matrix.md"' 'ref="$(git -C "$repo_root" rev-parse --short HEAD 2>/dev/null || echo unknown)"' 'printf "%s\n" "---" "overall_result: PASS" "---" "" "- git ref: $ref" > "$record"' 'printf "%s\n" "결과 기록 파일: ${record#$repo_root/}"' > "$scripts/run_matrix.sh" && chmod +x "$scripts"/*.sh && cd "$repo" && git init -q && git config user.email smoke@example.com && git config user.name Smoke && printf 'package transport\n' > go/transport/server.go && git add . && git commit -q -m baseline && base_ref="$(git rev-parse --short HEAD)" && for profile in proto-socket-full-matrix proto-socket-performance-quick proto-socket-stress-quick; do record="agent-test/runs/20260610-000000-${profile}.md"; printf '%s\n' '---' 'overall_result: PASS' '---' '' "- git ref: $base_ref" > "$record"; done && git add agent-test/runs && git commit -q -m records && printf 'package transport\n' > go/transport/stress_payload_1mb.go && bash agent-ops/skills/project/run-proto-socket-test-matrix/scripts/run_test_by_change.sh --route auto > "$tmp/auto.out" 2>&1 && bash agent-ops/skills/project/run-proto-socket-test-matrix/scripts/run_speed_test.sh > "$tmp/speed.out" 2>&1 && bash agent-ops/skills/project/run-proto-socket-test-matrix/scripts/run_stability_test.sh > "$tmp/stability.out" 2>&1 && ! rg -n "invalid option" "$tmp" && rg -n "실행 명령:|선택 이유:|exit code:|결과 기록:|nightly-pending 후보" "$tmp/auto.out" "$tmp/speed.out" "$tmp/stability.out"
git diff --check
```
모든 코드 변경 완료 후 반드시 `CODE_REVIEW-*-G??.md`의 구현 에이전트 소유 섹션을 채운다. 이 파일 작성이 구현의 마지막 단계다.