feat(session): claude attachment --add-dir + settings-derived spawn mode (ELECTRON-3R4) - #689
Open
BlackKeyZ wants to merge 2 commits into
Open
feat(session): claude attachment --add-dir + settings-derived spawn mode (ELECTRON-3R4)#689BlackKeyZ wants to merge 2 commits into
BlackKeyZ wants to merge 2 commits into
Conversation
added 2 commits
July 27, 2026 15:14
…ode (ELECTRON-3R4) Pasted/uploaded attachments land in $TMPDIR/aionui/<conv>/ (home-page uploads in .../general) — outside the workspace cwd, so under the fail-closed `--permission-mode default` the model's Read of an attachment dead-ends on an out-of-cwd permission prompt: the pasted image displays in the UI but is never recognized by the agent. F1 — grant exactly the two upload staging dirs at spawn: - aionui-common: new `paths::uploads_dir(Option<&str>)`, the single source of the upload layout; aionui-file rewired onto it (byte-identical layout). - The claude open path appends `--add-dir <tmp>/aionui/<conv>` + `--add-dir <tmp>/aionui/general` (mkdir-before-spawn, WARN-only on failure). Fresh, Resume and the wake-recipe respawn all inherit the grant (shared init args). F2 — spawn mode honors claude settings `permissions.defaultMode`: - The direct-CLI path hard-coded `--permission-mode default` whenever no mode was persisted, silently overriding the user's machine-level settings — a regression against the legacy ACP adapter, which resolved that setting per session. - New `aionui_session::claude_settings` resolver: precedence + alias table verbatim from the official adapter 0.33.1 (managed > local project > project > user; fallback "default"). - `build_session_instance` applies it as the LAST precedence step (snapshot > config > settings), still passing an explicit flag. No bespoke persist/UI writes: open seeds caps.current_mode from config.mode, and claude's init echo persists via the existing sniff_mode → ConfigChanged → save_runtime_state chain. - Drift tripwire: WARN when the first observed permissionMode differs from the spawn-requested flag value. - Clean-env probe (2.1.220): omitting the flag makes the CLI resolve its own settings hierarchy — NOT a hard bypassPermissions default; the stale comment claiming otherwise is rewritten with the corrected evidence.
…RON-3R4) Productionizes the fix-validation probe as an #[ignore] live test: the real ClaudeConnection::open_session + dispatch(Send) path, blank config (fail-closed --permission-mode default), an image staged in the out-of-cwd upload dir, the exact production ResourceLink lowering. Asserts the turn completes with ZERO permission prompts and the model answers from the image content — the frame that dead-ended on a can_use_tool(Read) ask before the --add-dir grant. Verified against claude 2.1.220: passes in ~37s.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Sentry ELECTRON-3R4 (user feedback, 2.1.41): a pasted image displays in the UI but the agent never recognizes it, while absolute-path images work.
Root cause: pasted/uploaded attachments are staged in
$TMPDIR/aionui/<conv>/(home-page uploads in.../general) — outside the workspace cwd — and delivered to the model as a path reference. Under the fail-closed--permission-mode default, the model's out-of-cwdReadof that path raises a permission prompt; denied/unanswered, the attachment is simply "unreadable". Live-probed end to end (claude 2.1.220): the identical frame succeeds with--add-dirand dead-ends without it.A second, related regression: the direct-CLI path hard-coded
--permission-mode defaultwhenever no mode was persisted, silently overriding the user's machine-level claude settingspermissions.defaultMode— the legacy ACP adapter resolved that setting per session.Fix
F1 — grant exactly the two upload staging dirs at spawn
aionui_common::paths::uploads_dir(Option<&str>): single source of the upload layout;aionui-filerewired onto it (byte-identical layout).--add-dir <tmp>/aionui/<conv>+--add-dir <tmp>/aionui/general(mkdir-before-spawn, WARN-only on failure). Fresh, Resume and the wake-recipe respawn all inherit the grant (shared init args). Everything else stays fail-closed.F2 — spawn mode honors claude settings
permissions.defaultModeaionui_session::claude_settingsresolver — precedence + alias table verbatim from the official adapter 0.33.1 (managed > local project > project > user; fallback"default").build_session_instanceapplies it as the LAST precedence step (persisted switch > create-time seed > settings), still passing an explicit flag.caps.current_modefromconfig.mode(picker shows the value from the firstruntime/ensure), and claude's init echo persists via the existingsniff_mode→ConfigChanged→save_runtime_statechain.permissionModediffers from the spawn-requested flag value.bypassPermissionsdefault; the stale comment claiming otherwise is rewritten with corrected evidence.With no settings present, emitted spawn args are byte-identical to before except the two
--add-dirpairs (pinned-args golden test re-pinned).Tests
claude_settings: 7 unit tests (precedence matrix, alias normalization, bad JSON fall-through, on-disk layering, spawn-whitelist invariant).open_session_grants_add_dir_for_upload_dirs/..._resume_grants_same_add_dirs: both spawn branches emit the two pairs, dirs created up-front.claude_mode_fallback_applies_only_when_unset: fallback fires only for claude with no resolved mode; resolver provably not invoked otherwise.open_seeds_current_mode_from_config_before_any_wire_frame: picker truth at open, before any wire frame.sniff_mode_warns_when_first_observed_mode_differs_from_requested: exactly one drift WARN on first-observation mismatch, none on match, behavior unchanged.-D warnings, fmt.