9a21d0e3f2
_extract_parallel_scope_path used Path.cwd() (process cwd) instead of the tool's actual execution cwd, and os.path.abspath() instead of os.path.realpath(), so symlink aliases and relative/absolute path pairs that resolve to the same physical file were treated as distinct targets and placed in the same parallel segment. On case-insensitive platforms (Windows) os.path.normcase() was also absent, allowing Foo.txt and foo.txt to race. Changes: - agent/tool_dispatch_helpers.py: introduce _canonical_path(raw_path, execution_cwd) applying expanduser->abspath->realpath->normcase; thread execution_cwd through _extract_parallel_scope_path and _plan_tool_batch_segments - agent/tool_executor.py: pass get_active_env(effective_task_id).cwd as execution_cwd to _plan_tool_batch_segments; add pathlib.Path import - run_agent.py: pass active env cwd to _plan_tool_batch_segments at the second call site inside _execute_tool_calls - tests/run_agent/test_tool_batch_segmentation.py: add 5 regression tests covering relative/absolute same target, symlink alias, execution_cwd vs process cwd, symlink parent + nonexistent write target, and Windows case-insensitive alias (skipped on non-Windows) Fixes a file-corruption / lost-update race introduced by the mixed tool-batch segmentation feature (perf commit #64460).