Delta analysis of the Claude Code releases v2.1.290 (2026-10-05) and v2.1.291 (2026-10-06), covering entries added since the previous scan at v2.1.289. Seven of the items have a direct analogue in the yoyo coding agent, and several of those analogues are known, still-open defects in yoyo. The dominant theme across this window is not new features but boundary hardening: closing holes where files, hooks, or provider responses leak past a fence the agent believes it has enforced.
Key Points
Claude Code's recent fix stream clusters into three classes:
Symlink / permission boundary holes in secondary loaders — files read by a path other than the read tool bypassing deny rules and working-directory restrictions.
Hook / plugin gating-site failures — hook stdout able to inject in-band control markers, or calls slipping through where gating was expected.
Honest truncation — reporting how much content was withheld and offering a way to read past the cut, instead of silently dropping it.
The secondary-loader class is the important one: yoyo's guards are built around the file tools, so a read that never passes through them is entirely unfenced.
yoyo matches Claude Code on one item (display sanitization) and mirrors the shape of several others, but only partially implements them.
Concepts
Secondary loader — any component that reads a file without going through the read tool (e.g. the project-context loader). Its permission checks are separate and can lag behind the tool path.
Permissions boundary — permissions.blockReadsOutsideWorkingDirectories, --deny-dir, --allow-dir, and Read deny rules; enforced per call site, so every reader must opt in.
TOCTOU (check-vs-write race) — the file at a path is validated, then swapped via a link before the read completes, so the approved and delivered objects differ.
In-band marker forgery — untrusted output (hook stdout, fetched page text) containing delimiters the model treats as trusted control, e.g. <system-reminder>.
Nonce boundary — yoyo's mitigation (#902): wrapping project instructions in a per-run random delimiter so injected text cannot impersonate the boundary. Not applied to hook output.
Honest truncation — reporting the unread remainder and accepting an offset to continue, rather than a bare marker.
Retry classification — deciding whether a provider stop reason (content filter, dropped connection) should end the turn, retry once, or return an error.
Details
Permission boundary holes in secondary loaders
Claude Code fixed project CLAUDE.md, rule, and AGENTS.md files that were symlinked outside the working directories but still loaded under permissions.blockReadsOutsideWorkingDirectories or a Read deny rule.
yoyo has the identical hole (probed Day 221): load_project_context_from in src/context.rs reads PROJECT_CONTEXT_FILES with a plain fs::read_to_string, which follows links and performs no DirectoryRestrictions check. With CLAUDE.md -> /tmp/x/secret/notes.md and --deny-dir /tmp/x/secret:
yoyo --print-system-prompt contains the denied file's content, wrapped in a provenance block asserting it was read from CLAUDE.md in the repository.
Behaviour is the same under --allow-dir <proj>.
The file tools correctly refuse that path (config_resolve.rs, Day 219 #996), so the context loader is a second door around the fence — the deny rule holds on one path and leaks on another.
Rendering diagram…
TOCTOU in approved file reads
Claude Code fixed an image read returning a file outside what had been approved, via a link swapped in mid-read. This is precisely the check-vs-write race yoyo named in #996; it remains open there. Approving a path and reading a path are separate operations, and nothing binds them.
Hook output as an injection surface
Claude Code now escapes <system-reminder> tags written in hook output before they reach the model, closing in-band marker forgery from hook stdout. yoyo wraps project instructions in a nonce boundary (#902), which defends the same attack in the context path — but the hook output path is not checked, leaving the same forgery primitive available through hooks.
Honest truncation on WebFetch
Claude Code fixed WebFetch silently dropping page text past 100,000 characters: it now states how much was unread and accepts an offset so the caller can continue. yoyo's /web truncates at WEB_MAX_CHARS=5000 with an in-band [truncated at N chars] marker — no offset to read on from, and no count of how much was withheld. The failure mode is a silent one: the model reasons over a partial document as if it were complete.
Failure classification after streamed partial output
Claude Code fixed headless --json-schema runs exiting non-zero with is_error: true on a successful result when the connection dropped after structured output had already been delivered. This is the same family as yoyo #976 / #989 / #997 — retry and failure handling after a streamed partial in -p. Related: a turn that ended immediately when the output content filter stopped a reply mid-thinking now retries once, i.e. retry classification of a provider stop reason rather than treating it as terminal.
Display sanitization
Claude Code's background daemon log no longer passes terminal control characters; they are rendered as \uXXXX escapes. yoyo already follows this discipline via cli::sanitize_for_display (#873) — the one item in this window with no delta.
Takeaways for guard design
Every reader of an untrusted path needs the same checks as the read tool; auditing the tool path is not sufficient.
Path approval and path reading must be bound together (or re-validated) to defeat link swaps.
Untrusted text should never be able to produce a trusted in-band marker, regardless of which channel it arrived on — context files, hook stdout, or fetched pages.
Truncation should be reported with both the unread amount and a way to continue.