Skip to content

[2/9] Preserve collision-safe output paths#63

Draft
hi-michael-li wants to merge 2 commits into
michael-li/stirrup-01-command-allowlistfrom
michael-li/stirrup-02-output-paths
Draft

[2/9] Preserve collision-safe output paths#63
hi-michael-li wants to merge 2 commits into
michael-li/stirrup-01-command-allowlistfrom
michael-li/stirrup-02-output-paths

Conversation

@hi-michael-li

@hi-michael-li hi-michael-li commented Jul 13, 2026

Copy link
Copy Markdown

Why

Output collection could flatten nested paths, overwrite same-named files, or misclassify valid POSIX filenames that resemble Windows paths. Users could lose or fail to receive generated artifacts.

What

  • Preserve source-relative paths across Local, Docker, and E2B backends.
  • Select path flavor from the backend's declared roots.
  • Reject paths outside managed roots and protect against collisions, symlinks, and hard-link aliases.

Testing

  • Focused Local/Docker/E2B coverage: 128 passed, 2 skipped.
  • Final stack: 419 passed, 2 skipped.
  • Ruff, format, type checks, strict docs, and package build pass.

Stack

Part 2 of 9. Previous: #62. Next: #64.

@hi-michael-li hi-michael-li force-pushed the michael-li/stirrup-01-command-allowlist branch from 183e5cd to 302c59a Compare July 14, 2026 06:27
@hi-michael-li hi-michael-li force-pushed the michael-li/stirrup-02-output-paths branch from bfb5111 to 1215758 Compare July 14, 2026 06:27
@hi-michael-li hi-michael-li force-pushed the michael-li/stirrup-01-command-allowlist branch from 302c59a to f7ca694 Compare July 14, 2026 13:24
@hi-michael-li hi-michael-li force-pushed the michael-li/stirrup-02-output-paths branch from 1215758 to edf5641 Compare July 14, 2026 13:24
Visibility (critical): output-save rejections were invisible at default
log levels — the root agent logged result.failed only at DEBUG, and the
E2B path regressed from WARNING/ERROR to DEBUG when its override was
removed. Rejections now log at WARNING (expected ValueError /
FileNotFoundError) or ERROR with traceback (unexpected), the root agent
warns per failed file and exposes last_output_files_result, and subagent
results now tell the parent model which files failed to transfer.

Robustness: a post-write destination-identity refresh failure no longer
marks a delivered file as failed; identity helpers only swallow
FileNotFoundError (other OSErrors warn instead of silently weakening
hard-link collision detection); host-backed saves snapshot sources to a
temp directory under the output root instead of buffering whole files in
RAM; collision errors name the claiming source; E2B realpath failures
include exit code and stderr.

Contract: output_source_roots() now returns typed OutputSourceRoot
entries (explicit posix/windows flavor and host_path), replacing the
implicit ordering and Path-vs-str conventions; destination identities
are typed DestinationIdentity values instead of prefix-formatted
strings; both are exported for backend implementers. Docstrings and
docs/extending/code_backends.md updated: stale "silently overwritten"
claims corrected, the Windows-drive rejection claim qualified by flavor,
the validate_output_destination double-call protocol and move-vs-copy
semantics documented.

Tests: new unit coverage for the Windows/POSIX/mixed flavor matrix on
POSIX hosts, E2B and Docker as transfer destinations, direct-save and
case-alias collisions, file-mode preservation, and the base-class
default hooks; the docker to_thread mock now always invokes its
function. CI gains a pytest job (it previously ran only lint and type
checks, so the mocked E2B suite never ran anywhere).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant