diff --git a/CHANGELOG.md b/CHANGELOG.md index 2b208a336..eb63f5fa4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -214,6 +214,16 @@ This section accumulates work toward the **2.1.0** milestone subagent's graph state, making `list_uploaded_files` eligible for normal tool-policy filtering (durable `batch_task` workers keep it disabled). ([#5170]) +- **agents:** The read-before-write gate now elides the dead payload of a + blocked `write_file` / `str_replace` call (`content`, `old_str`, `new_str`) + from model-bound requests. A blocked call never ran and must be re-issued + after a re-read, so the original arguments only cost context; stored + history, receipts, and the run journal keep them. Blocked results are + paired with call occurrences (tool-call ids may repeat across turns), and + a request whose history was rewritten drops OpenAI `resp_` response ids so + `use_previous_response_id` chaining cannot resume the original server-side + history. Controlled by `read_before_write.elide_blocked_payloads` (default + on) and `read_before_write.elide_min_chars` (default 2000). #### Memory diff --git a/backend/packages/harness/deerflow/agents/middlewares/AGENTS.md b/backend/packages/harness/deerflow/agents/middlewares/AGENTS.md index 767ee69d5..9f09c5771 100644 --- a/backend/packages/harness/deerflow/agents/middlewares/AGENTS.md +++ b/backend/packages/harness/deerflow/agents/middlewares/AGENTS.md @@ -65,7 +65,7 @@ alongside every behaviour-affecting field. forgeries). Consumers pop it; the publisher and the consumer share only that contract module. 10. **SandboxAuditMiddleware** - Audits sandboxed shell/file operations before tool execution; command classification is **defense-in-depth and audit, not a security boundary** (the sandbox is the isolation boundary). Command substitution is judged by *position*, not the presence of `$(`: **command position** (`$(curl url)`, `` `curl url` ``, the word after `|`/`&&`/`;`, an `eval`/`source` argument) executes fetched content and is blocked; **value position** (`x=$(curl url)`, `echo $(curl url)`, an argument, a `for` word list) only captures output and passes (#4611). So `_HIGH_RISK_COMMAND_POSITION_PATTERNS` is matched anchored against each sub-command from `_split_compound_command(split_pipes=True)`, never the whole string; pipe-spanning rules (`| sh`, `base64 -d | ...`) still use `_classify_command`'s whole-command Pass 1. `_COMMAND_POSITION_PREFIX` extends the anchor over leading assignments and exec wrappers (`FOO=1 $(curl url)`, `env`/`command`/`builtin`/`exec`/`nohup`/`time`/`sudo`/`doas`); its assignment branch requires whitespace before the substitution, which keeps `x=$(curl url)` in value position. Two contexts are deliberately **position-blind** (matched whole-command in Pass 1, since they execute their input anywhere, e.g. `xargs sh -c "$(curl url)"`): an `eval`/`source` argument, and an interpreter **code-string flag** — `-c` (shells, `python`), `-e` (`perl`/`ruby`/`node`), `-p` (`perl`/`node`), `-r` (`php`) — plus the here-string (`<<<`) reaching the same place via stdin. All three substitution spellings (`$(`, `<(`, `` ` ``) share one `_RISKY_SUBSTITUTION` opener. An unquoted newline splits like `;` (else `echo hi\n$(curl url)` evades the anchored rules). Heredoc bodies are data: `_split_compound_command` records headers (`<