0092: make 시작 lane 적응형 effort autotune (opt-in, recommendation-only PR1)
0092: make 시작 lane 적응형 effort autotune (opt-in, recommendation-only PR1)
- Status: proposed
- Date: 2026-06-01
- Deciders: User, Claude Code
- Related: ADR 0087 (opt-in runner 백엔드 / (d) runner 산출물 non-load-bearing), ADR 0085 (무한 모드 active-auto-loop), ADR 0086 (lane Tool/Sandbox 정책), ADR 0080 (registry v2 / dual-agent lanes), ADR 0061 (외부/유료 API opt-in 3조건), ADR 0005 (private 데이터 경계), ADR 0001 (baseline byte-identical 보존)
- Issue: #1716
Context
make 시작(active-auto-loop)은 per-(role,agent) lane을 병렬로 실행하지만, lane별 실행시간이
display-only였다 (scripts/agent_loop.py의 claude/codex
lane elapsed는 _emit_progress로만 흘렀다). 어떤 lane이 상대적으로 느린지, 반복적으로
실패하는지에 대한 가시성이 영속되지 않아 운영자가 effort 노브(claude --effort,
codex -c model_reasoning_effort)를 수동 조정할 근거가 없었다. deep-dive trace가 찾은 진짜
갭은 동시성이 아니라 lane 병목 가시성이다.
codex CLI는 -c model_reasoning_effort=<level>을 받고(~/.codex/config.toml이 xhigh까지
사용 확인), claude CLI는 --effort를 받는다. 즉 두 주 병렬 표면 모두 effort actuation이
원리적으로 가능하다. 다만 actuation은 진동(oscillation)·비용·order-correctness(codex -c
삽입 위치) 리스크가 있어 측정/감지와 분리해야 한다.
Decision
make 시작 active-auto-loop에 opt-in per-(role,agent) lane 적응형 effort autotune을
도입한다. 2-PR one-concern 분할:
- PR1 (이 ADR 범위) — Sense + Detect, recommendation-only:
- 새 측정 표면: per-lane
elapsed_s를ActiveCodexRunnerResult.sessions로 흘리고 (item["elapsed_s"]), iteration 경계에서auto_loop_state.json의cycles[].lane_stats로 영속. 신규 sibling 로더_load_active_lane_stats(state_path) -> (list, dict)— 기존_load_active_auto_ledger(3-tuple, 단일 unpack 호출처)는 시그니처 불변. - 순수 컨트롤러
compute_lane_autotune(prior_lane_stats, config) -> (recommendations, events)(cooldown_state 인자 없음): within-agentelapsed_s > K × median(같은 agent active lane)(K 기본 2.0) flag + per-lane(role,agent)fail_rate윈도우(W 기본 3, min-sample 2) + agent-flip 시 lane 윈도우 reset + 같은 agent active lane < 2면 no-op. I/O·env·clock 없음. - recommendation 기록: 병목 lane + 권고 방향(fail_rate>임계 → strengthen / 아니면
accelerate)을
auto_loop_state.json의lane_autotune_recommendations로 기록. effort actuation 없음.
- 새 측정 표면: per-lane
- PR2 (후속 issue, stacked) — Actuate:
_resolve_lane_effort_overridethreading (claude--effort/ codex-c model_reasoning_effort, positional-이전 삽입) + per-agent effort ladder clamp + cooldown 강제. PR2가 컨트롤러를 cooldown_state 시그니처로 확장.
Default OFF == byte-identical: ACTIVE_LANE_AUTOTUNE 미설정 시 컨트롤러는 호출되지
않고, per-lane elapsed_s·lane_stats·recommendations 어느 것도 영속되지 않는다. 산출
codex 명령(-c model_reasoning_effort 미주입)과 auto_loop_state.json 페이로드가 오늘과
바이트 동일하다.
Drivers
- runner 산출물 byte-identical (ADR 0087(d) non-load-bearing) — 기본 경로 무변경. 모든
신규 분기는
ACTIVE_LANE_AUTOTUNEgate 안. (ADR 0001 baseline이 아니라 0087(d)에 re-anchor.) - 테스트 가능성 — 컨트롤러가 순수 함수라 실 spawn 없이 결정론적 단위 테스트.
- 재사용 / SSoT — 신규 sidecar 파일 0; 기존
auto_loop_state.json단일 출처 재사용. PR2 effort threading은_resolve_lane_model_override패턴 미러링.
Alternatives considered
- 컨트롤러를 항상 호출 + 무조건 측정 영속. 기각: off-mode에서
auto_loop_state.json/ runner 상태 파일이 바뀌어 byte-identical 불변식 위반. 측정조차 gate 안으로. _load_active_auto_ledger확장(lane_stats 추가). 기각: 3-tuple 반환을 단일 호출처가 3개로 unpack — 시그니처 변경은 회귀 위험. 별도 sibling 로더로.- sidecar 파일(per-lane timing 별도 저장). 기각:
auto_loop_state.json이 이미 cycle 체크포인트의 단일 출처. 신규 파일은 SSoT 분산. os.environ변이로 effort 주입(PR2). 기각: 멀티-worktree 누수 + 컨트롤러 순수성 파괴. PR2는 param threading(Option A).- claude-only effort (codex는 effort 불가 오판). 기각: codex
-c model_reasoning_effort로 주 병렬 표면도 actuate 가능(PR2). - PR1에 cooldown 포함. 기각: cooldown(재조정 억제)은 actuation이 있어야 의미. PR1은 lane-stats 윈도우만 관리하고 agent-flip 시 reset; cooldown_state set/decrement는 PR2 신설.
Consequences
- opt-in 시 per-lane timing이
auto_loop_state.json에 영속(새 reviewer 계약 —lane_stats,lane_autotune_recommendations키). off 시 byte-identical. - omc runner(ADR 0087)는 단일 worker·per-lane
timing 부재 → autotune은 codex runner 한정, omc 시 컨트롤러는 자연히 no-op(
lane_stats비어있음). - claude
elapsed_s는 artifact/heartbeat 오버헤드 포함, codex는 순수 subprocess wait → 교차-agent 비교 불가. 컨트롤러는 within-agent median만 사용. - codex effort 상한(
xhighvsmax)은 PR2 빌드 smoke로 확정.
Deferred / follow-up
- effort actuation (PR2 — landed). claude
--effort/ codex-c model_reasoning_effortthreading (positional-이전 삽입) + per-agent ladder clamp + cooldown. controller가compute_lane_autotune(prior_lane_stats, cooldown_state, config) -> (effort_overrides, recommendations, new_cooldown_state, events)로 확장됨. codex effort 가드는 controller ladder-clamp 단독(_validate_effort_for_model은 claude lane 전용 — 오인용 금지). - codex
xhighrung (PR3 — landed, #1723)._CODEX_EFFORT_LADDER를high→xhigh상한으로 확장.codex exec --strict-config -c model_reasoning_effort=xhighrc=0 (유효 값 확정) +~/.codex/config.toml이 xhigh 사용 → autotune이 codex 병목을 진짜 ceiling까지 강화 가능. (claude는 PR3 당시 xhigh 상한 — 이후 #1730에서 max로 확장, 아래 항목.) - model-swap actuation. blast radius·비용 가드 필요 → deferred.
- cross-agent 정규화 비교. claude 오버헤드 보정 후 교차 비교 → 별도 측정 작업.
- claude
maxrung (PR B — landed, #1730)._CLAUDE_EFFORT_LADDER를xhigh→max상한으로 확장. CLI 수용 확정(claude -p --effort bogus→ enum 에러가max를 유효값 목록에 열거, rc=0 통과)._validate_effort_for_model확장: 비-Opus-4.7/4.8 모델에서max도high로 보수 강등(xhigh와 동일 per-model gate, #1730 conservative guard).
Verification
python3 -m pytest -q tests/test_agent_loop.py -k 'autotune or lane_effort or active_runner or lane_stats'
python3 scripts/_governance.py --check-adr-readme-parity docs/adr/0092-lane-adaptive-autotune.md
git diff --check