Summary
Phase2 autonomy-v2-p2-fix-slice-v2 short smoke (qwen3.5:122b) では、前回の 0-turn completion は解消したが、agent.fix_slice を呼んでも worker-backed success path に入らず、A1/B1 がともに worker_observed=false のまま expectation_mismatch で終了した。
今回の failure は Issue339 の再発ではない。
- Issue339 で直したのは「escalation だけで
worker_observed=true になってしまう false positive」
- 今回は逆で、
worker_observed=false のままなので telemetry semantics 自体は正しい
- それでも Phase2 が落ちるのは、FixSlice worker が success-side の
file.rewrite まで到達できていない ため
artifact 上の確定結果:
- A1:
mutation_observed=true, worker_observed=false, changed_files=2, pack_validation_result=mismatch
- B1:
mutation_observed=true, worker_observed=false, changed_files=1, pack_validation_result=mismatch
- A2:
mutation_observed=false, worker_observed=false, fixslice_escalation_count=14, runner_nonzero_exit
つまり:
- runtime は worker escalation を出している
agent.fix_slice 呼び出しも観測される
- しかし worker success (
file.rewrite) は観測されない
- 代わりに親エージェントの通常
file.edit で mutation するか、何も変えずに落ちる
- そのため
requires_worker_observation gate は正しく失敗する
Why this belongs to Anvil
これは localllm-test の pack / runner 不具合ではない。
autonomy-v2-p2-fix-slice-v2 は pack_expectation=requires_worker_observation を明示しており、runner は telemetry の worker_observed をそのまま評価しているだけ。
今回の mismatch は runner の誤分類ではなく、Anvil runtime が worker success を成立させられていない ことを正しく露出している。
Observed behavior
A1
agent.fix_slice 呼び出しあり
- FixSlice subagent は
./src, ., ./auto-yes-resolver.ts などを読み始める
- 3 iteration で
Reached max iterations (3)
file.rewrite 成功や fix-slice applied は出ない
- その後、親エージェントの
file.edit が src/lib/auto-yes-manager.ts / tests/unit/lib/auto-yes-manager.test.ts を変更
- 結果は
mutation_observed=true だが worker_observed=false
B1
- 同様に
agent.fix_slice 呼び出しあり
- ただし worker success には至らず
- 親エージェントの
file.edit で src/lib/auto-yes-manager.ts を 1 行変更
- 結果は
mutation_observed=true だが worker_observed=false
A2
agent.fix_slice は呼ばれる
fixslice_escalation_count=14
- しかし worker 側は収束せず、loop detector / tool failure で終了
mutation_observed=false, worker_observed=false
Root cause
1. agent.fix_slice 実行時に、worker へ渡す user prompt が goal だけになっている
ToolInput::AgentFixSlice { target_path, goal, max_lines } を受けたとき、runtime は:
goal を subagent への prompt として渡し
target_path の 親ディレクトリ だけを scope に設定し
target_path / max_lines 自体は subagent の user prompt に埋め込んでいない
つまり worker は:
- 「何を直したいか」は聞いている
- しかし どのファイルを第一対象にすべきか を user prompt からは受け取っていない
scope はディレクトリ境界にすぎず、対象ファイルの明示ではない
これは FixSlice worker にとって致命的で、対象ファイルへ収束する前に探索が散る。
2. FixSlice subagent の system prompt は target-specific な proposal を要求するのに、実ランタイムは必要な target context を渡していない
FixSlice subagent の prompt contract は:
target_path
start_line
end_line
replacement_content
を含む FixSliceProposal を返すことを要求している。
さらに role prompt では:
- target file を読め
- minimal local fix を返せ
max_lines budget を守れ
と書いてある。
しかし実際には subagent への user message が goal しかないため、system prompt が期待する target-specific proposal と runtime input が一致していない。
3. この欠落が、A1 の実ログでそのまま再現している
A1 では agent.fix_slice(target_path=\"src/lib/auto-yes-manager.ts\", ...) の直後、worker は:
file.read \"./src\"
file.read \".\"
file.read \"./auto-yes-resolver.ts\"
のように、target file ではなく周辺探索へ流れている。
これは「model が怠けた」よりも、「runtime が worker に target context を渡していない」説明のほうが整合的。
4. worker_observed が立たないのは仕様どおり
Issue339 後の Anvil では worker_observed は request-side ではなく success-side。
handle_fixslice_result() では、record_worker_success() は次の場合にしか呼ばれない:
- worker proposal が存在する
validate_fix_proposal() を通る
file.rewrite が Completed
- rollback なし
- summary が空でも
(no changes) でもない
今回の A1/B1/A2 はここまで達していないため、worker_observed=false は正しい。
Concrete problem areas
Primary hotspot:
src/app/agentic.rs
ToolInput::AgentFixSlice を goal -> prompt に潰している部分
Supporting hotspots:
src/agent/subagent.rs
- FixSlice subagent の session 初期化は
prompt をそのまま user message に積むだけ
- つまり parent が target context を埋めなければ worker は受け取れない
src/app/agentic.rs
handle_fixslice_result()
- ここはむしろ正しく、
file.rewrite success がない限り worker_observed を立てない
What is not the root cause
Not localllm-test
- pack は
requires_worker_observation を正しく宣言している
- runner は
worker_observed をそのまま見ているだけ
- 今回の mismatch は妥当
Not Issue339 regression
- 今回は escalation だけで
worker_observed=true にはなっていない
- false positive ではなく worker success 未達 が本質
Not telemetry bug
- telemetry は正直
- 問題は worker 実行経路が success boundary に到達していないこと
Fix direction
1. agent.fix_slice subagent の user prompt に target_path と max_lines を明示的に埋め込む
最低限、worker に渡す prompt を次の情報を含む固定フォーマットへ変更するべき。
- exact
target_path
- exact
max_lines
goal
- 「まず target file を read せよ」
- 「proposal の
target_path は必ずこの path と一致させよ」
単に goal を渡すのではなく、FixSlice 専用の structured instruction block にする必要がある。
2. scope=parent_dir は維持してよいが、target anchor の代替にはしない
親ディレクトリ scope は sandbox 制約としては有効。
ただし scope だけでは target file selection を強制できないので、target anchor は prompt に別途必要。
3. 可能なら FixSlice subagent 起動時に target file path を system/user の両方で冗長に渡す
この path は correctness-critical なので、モデル任せにしない方がよい。
例えば:
- system prompt: target_path must equal X
- user prompt: fix X according to goal Y
の二重化が安全。
4. 追加回帰テスト
必要な回帰:
agent.fix_slice(target_path=A, goal=...) で subagent 初回 prompt に A が含まれる
- FixSlice worker が target file 以外へ散りにくいことを prompt construction test で固定
- positive test:
- escalation
agent.fix_slice
- successful
file.rewrite
worker_observed=true
- negative test:
- escalation
- parent-side
file.edit salvage only
worker_observed=false
5. Secondary improvement: FixSlice worker budgetの見直し
今回の primary root cause は prompt/context 欠落だが、FixSlice worker が MAX_ITERATIONS=3 / TIMEOUT=60s でかなり早く切られる点も成功率に影響しうる。
ただしこれは secondary。
まず直すべきは target context を渡していないこと であり、budget tuning はその後。
Candidate acceptance criteria
Desk-check: if this issue is cleared, does it achieve the original goal?
Original goal
Phase2 の当初目的は:
- parent autonomy を保ちつつ
- local bounded mutation だけを worker に逃がし
- benchmark 上でも
requires_worker_observation gate を満たす
こと。
Desk-check conclusion
かなり高い確率で、今回の blocker は解消される。
理由:
- 現在の failure は「worker が起動しない」ではなく「起動しても target file に収束できない」
- A1/B1 の mutation 自体は既に親エージェントが到達できているので、task difficulty が不可能なわけではない
- つまり不足しているのは能力そのものより、worker に対する target grounding
- その grounding を追加すれば、worker proposal ->
file.rewrite success path に乗る見込みは高い
But not mathematically guaranteed
この issue だけで 100% Phase2 pass が保証されるわけではない。
残るリスク:
- model が still poor proposal を返す
max_iterations=3 がまだ厳しい
- line-range / JSON proposal quality で別 failure が出る
しかしそれらは 次の層の failure であり、今の front blocker は明確にこの issue。
したがって机上検証の結論は:
- Yes: この issue をクリアすれば、当初目的に対する主要 blocker は除去できる
- Likely yes: Phase2 retest で worker-backed mutation が観測される公算は高い
- Not absolute: もし retest でまだ失敗するなら、その次は worker budget / proposal quality の問題として切り分けられる
Relation to existing issues
#339: telemetry semantics の false positive 修正
- 本 issue はその後に表面化した true negative / success-unreachable 側の問題
#332: escalation policy が narrow すぎる問題
- 本 issue は「escalation 後に worker が正しい target を受け取れていない」問題
要するに:
#332 は when to call fix_slice
#339 は when to mark worker_observed
- this issue は what fix_slice actually knows when it starts
であり、役割が分かれている。
Summary
Phase2
autonomy-v2-p2-fix-slice-v2short smoke (qwen3.5:122b) では、前回の0-turn completionは解消したが、agent.fix_sliceを呼んでも worker-backed success path に入らず、A1/B1 がともにworker_observed=falseのままexpectation_mismatchで終了した。今回の failure は Issue339 の再発ではない。
worker_observed=trueになってしまう false positive」worker_observed=falseのままなので telemetry semantics 自体は正しいfile.rewriteまで到達できていない ためartifact 上の確定結果:
mutation_observed=true,worker_observed=false,changed_files=2,pack_validation_result=mismatchmutation_observed=true,worker_observed=false,changed_files=1,pack_validation_result=mismatchmutation_observed=false,worker_observed=false,fixslice_escalation_count=14,runner_nonzero_exitつまり:
agent.fix_slice呼び出しも観測されるfile.rewrite) は観測されないfile.editで mutation するか、何も変えずに落ちるrequires_worker_observationgate は正しく失敗するWhy this belongs to Anvil
これは
localllm-testの pack / runner 不具合ではない。autonomy-v2-p2-fix-slice-v2はpack_expectation=requires_worker_observationを明示しており、runner は telemetry のworker_observedをそのまま評価しているだけ。今回の mismatch は runner の誤分類ではなく、Anvil runtime が worker success を成立させられていない ことを正しく露出している。
Observed behavior
A1
agent.fix_slice呼び出しあり./src,.,./auto-yes-resolver.tsなどを読み始めるReached max iterations (3)file.rewrite成功やfix-slice appliedは出ないfile.editがsrc/lib/auto-yes-manager.ts/tests/unit/lib/auto-yes-manager.test.tsを変更mutation_observed=trueだがworker_observed=falseB1
agent.fix_slice呼び出しありfile.editでsrc/lib/auto-yes-manager.tsを 1 行変更mutation_observed=trueだがworker_observed=falseA2
agent.fix_sliceは呼ばれるfixslice_escalation_count=14mutation_observed=false,worker_observed=falseRoot cause
1.
agent.fix_slice実行時に、worker へ渡す user prompt がgoalだけになっているToolInput::AgentFixSlice { target_path, goal, max_lines }を受けたとき、runtime は:goalを subagent へのpromptとして渡しtarget_pathの 親ディレクトリ だけをscopeに設定しtarget_path/max_lines自体は subagent の user prompt に埋め込んでいないつまり worker は:
scopeはディレクトリ境界にすぎず、対象ファイルの明示ではないこれは FixSlice worker にとって致命的で、対象ファイルへ収束する前に探索が散る。
2. FixSlice subagent の system prompt は target-specific な proposal を要求するのに、実ランタイムは必要な target context を渡していない
FixSlice subagent の prompt contract は:
target_pathstart_lineend_linereplacement_contentを含む
FixSliceProposalを返すことを要求している。さらに role prompt では:
max_linesbudget を守れと書いてある。
しかし実際には subagent への user message が
goalしかないため、system prompt が期待する target-specific proposal と runtime input が一致していない。3. この欠落が、A1 の実ログでそのまま再現している
A1 では
agent.fix_slice(target_path=\"src/lib/auto-yes-manager.ts\", ...)の直後、worker は:file.read \"./src\"file.read \".\"file.read \"./auto-yes-resolver.ts\"のように、target file ではなく周辺探索へ流れている。
これは「model が怠けた」よりも、「runtime が worker に target context を渡していない」説明のほうが整合的。
4.
worker_observedが立たないのは仕様どおりIssue339 後の Anvil では
worker_observedは request-side ではなく success-side。handle_fixslice_result()では、record_worker_success()は次の場合にしか呼ばれない:validate_fix_proposal()を通るfile.rewriteがCompleted(no changes)でもない今回の A1/B1/A2 はここまで達していないため、
worker_observed=falseは正しい。Concrete problem areas
Primary hotspot:
src/app/agentic.rsToolInput::AgentFixSliceをgoal -> promptに潰している部分Supporting hotspots:
src/agent/subagent.rspromptをそのまま user message に積むだけsrc/app/agentic.rshandle_fixslice_result()file.rewritesuccess がない限りworker_observedを立てないWhat is not the root cause
Not localllm-test
requires_worker_observationを正しく宣言しているworker_observedをそのまま見ているだけNot Issue339 regression
worker_observed=trueにはなっていないNot telemetry bug
Fix direction
1.
agent.fix_slicesubagent の user prompt にtarget_pathとmax_linesを明示的に埋め込む最低限、worker に渡す prompt を次の情報を含む固定フォーマットへ変更するべき。
target_pathmax_linesgoaltarget_pathは必ずこの path と一致させよ」単に
goalを渡すのではなく、FixSlice 専用の structured instruction block にする必要がある。2.
scope=parent_dirは維持してよいが、target anchor の代替にはしない親ディレクトリ scope は sandbox 制約としては有効。
ただし scope だけでは target file selection を強制できないので、target anchor は prompt に別途必要。
3. 可能なら FixSlice subagent 起動時に target file path を system/user の両方で冗長に渡す
この path は correctness-critical なので、モデル任せにしない方がよい。
例えば:
の二重化が安全。
4. 追加回帰テスト
必要な回帰:
agent.fix_slice(target_path=A, goal=...)で subagent 初回 prompt に A が含まれるagent.fix_slicefile.rewriteworker_observed=truefile.editsalvage onlyworker_observed=false5. Secondary improvement: FixSlice worker budgetの見直し
今回の primary root cause は prompt/context 欠落だが、FixSlice worker が
MAX_ITERATIONS=3/TIMEOUT=60sでかなり早く切られる点も成功率に影響しうる。ただしこれは secondary。
まず直すべきは target context を渡していないこと であり、budget tuning はその後。
Candidate acceptance criteria
ToolInput::AgentFixSliceから subagent へ渡す prompt にtarget_pathとmax_linesが含まれるfile.rewriteが観測されるfile.editのみで終わった run は引き続きworker_observed=falseworker_observed=trueかつmutation_observed=trueを達成するDesk-check: if this issue is cleared, does it achieve the original goal?
Original goal
Phase2 の当初目的は:
requires_worker_observationgate を満たすこと。
Desk-check conclusion
かなり高い確率で、今回の blocker は解消される。
理由:
file.rewritesuccess path に乗る見込みは高いBut not mathematically guaranteed
この issue だけで 100% Phase2 pass が保証されるわけではない。
残るリスク:
max_iterations=3がまだ厳しいしかしそれらは 次の層の failure であり、今の front blocker は明確にこの issue。
したがって机上検証の結論は:
Relation to existing issues
#339: telemetry semantics の false positive 修正#332: escalation policy が narrow すぎる問題要するに:
#332は when to call fix_slice#339は when to mark worker_observedであり、役割が分かれている。