* docs(specs): read-before-write gate design for issue #3857 output layer
* docs(plans): read-before-write gate implementation plan (#3857)
* refactor(sandbox): extract read_current_file_content helper (#3857)
* feat(middlewares): read-before-write version gate for file tools (#3857)
* test(middlewares): pin async read-before-write gate paths (#3857)
* feat(config): wire ReadBeforeWriteMiddleware into runtime chain, default on (#3857)
* docs(sandbox): document read-before-write gate in tool docstrings and AGENTS.md (#3857)
* docs(plans): align plan doc with landed config_version (17) and drop machine-specific paths
Addresses Copilot review comments on #3912.
* fix(middlewares): read-before-write gate — error-string sandboxes fail open; serialize gate+execution per path (#3912 review)
- AIO/E2B read_file reports failures (incl. missing files) as 'Error: ...'
strings instead of raising; the gate treated that string as existing file
content and blocked first-write creation. Error-string reads now count as
uninspectable: gate fails open, no mark is stamped.
- LangGraph runs one AIMessage's tool calls concurrently, so two same-turn
writes could both pass on one stale mark before either mutation landed
(and a read mark could hash a version the model never saw). Gate check +
tool execution (and read + mark stamping) now share a per-(thread, path)
critical section, separate from the tool-internal file_operation_lock.