Skip to content

Make session scratch an operable, confined agent filesystem - #1007

Merged
softmarshmallow merged 5 commits into
mainfrom
chore/916-operable-image-attachments
Jul 31, 2026
Merged

Make session scratch an operable, confined agent filesystem#1007
softmarshmallow merged 5 commits into
mainfrom
chore/916-operable-image-attachments

Conversation

@softmarshmallow

@softmarshmallow softmarshmallow commented Jul 30, 2026

Copy link
Copy Markdown
Member

Closes #916

What changed

  • establishes host-owned, per-session scratch as an operable AgentFs root for workspace-bound Desktop sessions
  • routes raster uploads through two correlated representations:
    • provider-native image input for immediate perception and durable replay
    • a byte-exact scratch file for view_image, structured filesystem tools, and optional command work
  • routes other browser byte files to scratch without pretending they are provider-native media
  • preserves durable attachment descriptors while deriving their current available state from the ephemeral filesystem
  • makes scratch staging no-clobber and atomic with incoming-message persistence, including rollback on validation, collision, and human-input races
  • removes a session's scratch under the same admission lease as session deletion and sweeps stale scratch/command-temp state at host startup
  • exposes safe, non-overwriting scratch-local cp/mv without approval while keeping workspace promotion under the normal supervision policy

Codex grounding

This intentionally generalizes several filesystem-backed Codex patterns; it is not a claim that Codex has one universal attachment filesystem.

Research against the local openai/codex clone at fea2d8b18f5f found:

  • ordinary turn input has Image / LocalImage (and audio), but no generic File variant; LocalImage reads its original path and becomes provider-native input_image content (source, lowering)
  • TUI Goals separately materializes pasted text, images, and oversized objectives under $CODEX_HOME/attachments/<uuid> (source)
  • generated images and inline visualizations have their own feature-specific filesystem stores
  • command cancellation uses per-attempt sandboxing and POSIX process-group termination, but deliberately detached setsid(2) descendants are not a hard-revocation guarantee

Grida's result is therefore a coherent per-session scratch contract: incoming operable copies, generated output, structured filesystem access, cleanup, and command confinement share one host-owned authority.

The proprietary Codex Desktop frontend is not in that repository, so this comparison establishes the open-source core/TUI/app-server behavior, not undocumented frontend upload preprocessing.

Capability and compatibility behavior

  • Desktop advertises base64 scratch staging on every platform.
  • Raster files remain usable without shell support through provider perception and view_image.
  • Structured text and SVG remain usable through structured filesystem tools.
  • On Windows, where Desktop does not yet have an equivalent confined binary command worker, opaque binary formats such as PDF/ZIP are rejected instead of accepting an inert scratch-only attachment.
  • The web-daemon and external ACP paths do not claim this Desktop scratch binding.
  • Per-turn scratch ingress remains bounded to 64 files / 8 MiB decoded bytes.

This PR shows image thumbnails, attachment filename chips, and tool media. It does not add a user-facing scratch browser or “Reveal in Finder” action.

Security and lifecycle

  • predictable scratch authority levels are created non-recursively, reject symlinks/foreign ownership/unsafe parents, and are verified owner-only on POSIX
  • lexical and physical overlap with the agent secret root fails before mutation
  • scratch cleanup revalidates authority and unlinks child symlinks instead of following them
  • run_command is exposed only through a host-injected ShellExecutor; a boolean sandbox claim cannot enable raw spawn
  • Electron main creates a fresh no-network SRT profile for each finite command, denies the shared scratch parent and userData, and re-allows only the exact workspace, own-session scratch, and private command temp
  • command abort remains pending until the worker exits and per-command temp/SRT cleanup completes; a terminal command.aborted acknowledgement and the model-pump settlement barrier prevent a replacement turn or session deletion from overlapping cleanup
  • ordinary POSIX background descendants are terminated as a process group; deliberate macOS setsid(2) escape remains documented rather than overstated
  • a fully compromised sidecar can still name paths on the private command frame; main canonicalizes shape/overlap but this version does not replace those paths with opaque main-issued grants

Validation

  • pnpm fmt:check
  • pnpm lint — 0 errors; 3 existing Vitest todo warnings
  • builds: @grida/daemon, @grida/agent, @grida/desktop-bridge
  • typechecks: daemon, agent (node/neutral/browser-backends), desktop bridge, Desktop, editor
  • editor attachment/router/bridge tests: 74 passed
  • desktop bridge tests: 1 passed
  • full daemon suite: 164 passed
  • full agent suite: 1,079 passed; 25 skipped; 2 todo
  • full Desktop suite: 365 passed
  • real macOS SRT integration: 2 passed (own scratch allowed; sibling scratch and userData denied)
  • docs build: all locales succeeded; existing tag/anchor warnings only
  • live OpenRouter coverage: provider perception, exact scratch correlation/copy, later-turn DB rebuild, and process resume

Manual verification

Verified in the running Desktop app:

  • standard raster drop/paste, later-turn scratch operations, and provider-native replay
  • large raster provider-limit fallback behavior
  • generic structured-file scratch routing
  • scratch-local copy without approval and workspace promotion with approval
  • UI restoration from SQLite
  • after an app restart, durable messages/provider images survived while prior ephemeral scratch was unavailable

The corresponding manual cases are:

  • test/desktop-agent-chat-image-drop.md
  • test/desktop-agent-chat-large-raster-drop.md
  • test/desktop-agent-chat-generic-file-drop.md

@vercel

vercel Bot commented Jul 30, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

6 Skipped Deployments
Project Deployment Actions Updated (UTC)
backgrounds Ignored Ignored Preview Jul 31, 2026 11:51am
blog Ignored Ignored Preview Jul 31, 2026 11:51am
code Ignored Ignored Jul 31, 2026 11:51am
docs Ignored Ignored Preview Jul 31, 2026 11:51am
grida Ignored Ignored Preview Jul 31, 2026 11:51am
viewer Ignored Ignored Preview Jul 31, 2026 11:51am

Request Review

@coderabbitai

coderabbitai Bot commented Jul 30, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 06d0482c-043a-4f6c-9fbd-d3b578aa442b

📥 Commits

Reviewing files that changed from the base of the PR and between 9a6c4a6 and 9f34fb7.

📒 Files selected for processing (1)
  • desktop/package.json

Walkthrough

Attachment routing now supports provider-and-scratch delivery, bounded scratch twins, provider-file correlation, secure scratch lifecycle management, confined finite commands, rollback-safe staging, liveness reporting, and stricter continuation validation.

Changes

Attachment, scratch, and command execution

Layer / File(s) Summary
Composite attachment routing and ingress
docs/wg/ai/agent/compositor.md, editor/lib/agent-chat/*, editor/scaffolds/desktop/shared/*, packages/grida-ai-agent/src/protocol/context.ts
Provider-and-scratch routes, bounded retention, stable resource identities, provider-file correlation, and capability-aware fallbacks are implemented.
Scratch authority and runtime lifecycle
docs/wg/ai/agent/scratch.md, packages/grida-ai-agent/src/session/*, packages/grida-ai-agent/src/runtime/*, packages/grida-ai-agent/src/agent/*
Scratch roots are validated and isolated, writes support no-overwrite staging, cleanup fails closed, staged files roll back on failure, and model-visible attachment availability reflects live scratch files.
Finite command execution and confinement
packages/grida-daemon/src/shell/*, packages/grida-ai-agent/src/runtime/command-backend.*, packages/grida-ai-agent/src/tools/*, desktop/src/agent-sidecar-*, desktop/src/main/agent-command-host.*
Commands use injected scoped executors, bounded sidecar frames, cancellation handshakes, exact workspace and scratch roots, per-command sandbox profiles, and scratch-local approval rules.
Continuation validation and persistence
packages/grida-ai-agent/src/runtime/run-input.*, packages/grida-ai-agent/src/http/routes/*, packages/grida-ai-agent/src/session/store.ts
Continuation scratch inputs and provider-file indexes are validated, incoming persistence is transactional, and session deletion waits for runtime cleanup.
Security, perception, and desktop specifications
SECURITY.md, docs/wg/ai/agent/vision.md, docs/wg/desktop/*, desktop/README.md, test/desktop-agent-chat-*.md
Perception retention, command security, platform capability differences, scratch durability, and attachment interaction scenarios are documented and tested.

Estimated code review effort: 5 (Critical) | ~120 minutes

Possibly related issues

  • #985: Describes the supervisor-owned, per-command confined worker architecture and command lifecycle implemented here.

Possibly related PRs

Suggested labels: security, documentation, desktop, enhancement, ai

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 34.86% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the primary change: making session scratch an operable and confined agent filesystem.
Description check ✅ Passed The description directly explains the scratch filesystem, routing, lifecycle, security, compatibility, and validation changes.
Linked Issues check ✅ Passed The implementation satisfies issue #916 by adding host-owned per-session scratch, bounded access, default working-file support, and lifecycle cleanup.
Out of Scope Changes check ✅ Passed The changes remain aligned with issue #916 and its supporting requirements for routing, confinement, cleanup, compatibility, and validation.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch chore/916-operable-image-attachments

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Comment thread packages/grida-ai-agent/src/runtime/index.ts Fixed
@softmarshmallow
softmarshmallow marked this pull request as ready for review July 30, 2026 05:01
@coderabbitai coderabbitai Bot added ai AI models, prompts, and pricing documentation Improvements or additions to documentation enhancement New feature or request security labels Jul 30, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (3)
test/desktop-agent-chat-image-drop.md (1)

43-49: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Split the additional behaviors into separate manual cases.

Large-raster provider-limit handling and generic .txt routing are independent from the standard image-drop flow. Move them into separately named test cases with their own IDs.

Based on coding guidelines, “Ensure each manual test case file covers only one independent behavior—if a test case covers multiple independent behaviors, split it into separate files.”

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@test/desktop-agent-chat-image-drop.md` around lines 43 - 49, Split the large
high-resolution image/provider-limit scenario and the plain .txt generic-file
routing scenario from the standard image-drop manual test. Place each
independent behavior in its own separately named test file with a unique
test-case ID, preserving the existing steps and expected outcomes.

Source: Coding guidelines

packages/grida-ai-agent/src/session/scratch.ts (1)

251-262: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Consider logging the swallowed readdir error.

Failing closed is right, but an EACCES/EIO is currently indistinguishable from "scratch was swept" — the model just sees available: false with no host-side trace.

♻️ Suggested tweak
-  } catch {
+  } catch (err) {
+    if ((err as NodeJS.ErrnoException).code !== "ENOENT") {
+      console.warn(`[agent] scratch listing failed for ${scratchDir}:`, err);
+    }
     return new Set();
   }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/grida-ai-agent/src/session/scratch.ts` around lines 251 - 262,
Update listScratchFilePaths to capture the readdir error and log it through the
module’s existing logging mechanism before returning the empty Set, preserving
the current failing-closed behavior for all read failures.
packages/grida-ai-agent/src/runtime/index.ts (1)

418-435: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Minor: the "reverse order" intent doesn't survive Promise.allSettled.

[...created].reverse() only orders task creation; all unlink calls start concurrently. Harmless for independent files — either drop the reverse() or make the loop sequential if the ordering is meant to be meaningful.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/grida-ai-agent/src/runtime/index.ts` around lines 418 - 435, Update
rollbackScratchSeeds so its cleanup behavior matches the intended ordering:
either remove the unnecessary reverse ordering and keep parallel
Promise.allSettled cleanup, or replace it with sequential unlink processing when
reverse deletion order is required. Preserve ENOENT handling and aggregate
cleanup failures.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/grida-ai-agent/src/runtime/message-view.test.ts`:
- Around line 249-252: Strengthen the assertions in the message-view test around
the marker text so each attachment’s name is verified together with its expected
availability value. Replace the independent contains checks near the live.bin
and expired.bin assertions with object-level or paired assertions that cannot
pass when the availability values are swapped.

In `@packages/grida-ai-agent/src/runtime/runtime.live.test.ts`:
- Around line 296-315: Update the commandInput selection in the test to search
run_command chunks for the invocation whose parsed input command is “cp”, rather
than choosing the first shell invocation. Keep the existing commandTrace,
approval assertion, and path assertions anchored to that selected cp command.

---

Nitpick comments:
In `@packages/grida-ai-agent/src/runtime/index.ts`:
- Around line 418-435: Update rollbackScratchSeeds so its cleanup behavior
matches the intended ordering: either remove the unnecessary reverse ordering
and keep parallel Promise.allSettled cleanup, or replace it with sequential
unlink processing when reverse deletion order is required. Preserve ENOENT
handling and aggregate cleanup failures.

In `@packages/grida-ai-agent/src/session/scratch.ts`:
- Around line 251-262: Update listScratchFilePaths to capture the readdir error
and log it through the module’s existing logging mechanism before returning the
empty Set, preserving the current failing-closed behavior for all read failures.

In `@test/desktop-agent-chat-image-drop.md`:
- Around line 43-49: Split the large high-resolution image/provider-limit
scenario and the plain .txt generic-file routing scenario from the standard
image-drop manual test. Place each independent behavior in its own separately
named test file with a unique test-case ID, preserving the existing steps and
expected outcomes.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 0f7e43ad-2ad6-4117-93cb-2861950156a6

📥 Commits

Reviewing files that changed from the base of the PR and between 2e0d276 and ccf2d18.

📒 Files selected for processing (42)
  • docs/wg/ai/agent/compositor.md
  • docs/wg/ai/agent/scratch.md
  • docs/wg/ai/agent/vision.md
  • editor/kits/agent-chat/group-parts.ts
  • editor/kits/agent-chat/message.tsx
  • editor/lib/agent-chat/build-agent-send.test.ts
  • editor/lib/agent-chat/build-agent-send.ts
  • editor/lib/agent-chat/file-attachment.test.ts
  • editor/lib/agent-chat/file-attachment.ts
  • editor/lib/agent-chat/image-attachment.ts
  • editor/lib/agent-chat/input-resource-policy.test.ts
  • editor/lib/agent-chat/input-resource-policy.ts
  • editor/lib/agent-chat/input-resource-router.test.ts
  • editor/lib/agent-chat/input-resource-router.ts
  • editor/lib/agent-chat/use-turn-queue-controller.ts
  • editor/scaffolds/desktop/shared/agent-composer-input.tsx
  • editor/scaffolds/desktop/shared/agent-composer-resource-id.test.ts
  • editor/scaffolds/desktop/shared/agent-composer-resource-id.ts
  • packages/grida-ai-agent/src/agent/image-gen-capability.test.ts
  • packages/grida-ai-agent/src/agent/index.ts
  • packages/grida-ai-agent/src/agent/scratch-capability.test.ts
  • packages/grida-ai-agent/src/http/routes/agent.test.ts
  • packages/grida-ai-agent/src/prompts.ts
  • packages/grida-ai-agent/src/protocol/context.ts
  • packages/grida-ai-agent/src/runtime/index.ts
  • packages/grida-ai-agent/src/runtime/message-view.test.ts
  • packages/grida-ai-agent/src/runtime/message-view.ts
  • packages/grida-ai-agent/src/runtime/run-agent.ts
  • packages/grida-ai-agent/src/runtime/run-input.test.ts
  • packages/grida-ai-agent/src/runtime/run-input.ts
  • packages/grida-ai-agent/src/runtime/runtime.live.test.ts
  • packages/grida-ai-agent/src/runtime/workspace-agent-bindings.test.ts
  • packages/grida-ai-agent/src/runtime/workspace-agent-bindings.ts
  • packages/grida-ai-agent/src/session/scratch.test.ts
  • packages/grida-ai-agent/src/session/scratch.ts
  • packages/grida-ai-agent/src/tools/index.ts
  • packages/grida-ai-agent/src/tools/run-command.ts
  • test/desktop-agent-chat-busy-image-blocked.md
  • test/desktop-agent-chat-image-drop.md
  • test/desktop-agent-chat-image-paste.md
  • test/desktop-agent-chat-multi-image.md
  • test/desktop-agent-chat-screenshot-drop.md

Comment thread packages/grida-ai-agent/src/runtime/message-view.test.ts Outdated
Comment thread packages/grida-ai-agent/src/runtime/runtime.live.test.ts
@softmarshmallow softmarshmallow changed the title Make raster attachments operable through session scratch Make session scratch an operable, confined agent filesystem Jul 30, 2026
@coderabbitai coderabbitai Bot added the desktop this is a Grida Desktop App related issue label Jul 30, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
packages/grida-ai-agent/src/runtime/runtime.live.test.ts (1)

119-121: 🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Use the alternate auth directory as secrets_root too.

When LIVE_AUTH_DIR is active, AuthStore reads credentials from that directory, but AgentRuntime still receives secrets_root: baseDir on Line 136. Because this host injects runUnsandboxedShell, a model command can read the real auth files outside the configured secret-root guard. Derive one authDir and use it for both AuthStore and secrets_root; keep baseDir for the temporary database and scratch.

Proposed fix
-  const auth = new AuthStore(
-    PROVIDER_KEY ? baseDir : (LIVE_AUTH_DIR ?? baseDir)
-  );
+  const authDir = PROVIDER_KEY ? baseDir : (LIVE_AUTH_DIR ?? baseDir);
+  const auth = new AuthStore(authDir);
...
-    secrets_root: baseDir,
+    secrets_root: authDir,
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/grida-ai-agent/src/runtime/runtime.live.test.ts` around lines 119 -
121, Define a shared authDir from PROVIDER_KEY, LIVE_AUTH_DIR, and baseDir, then
pass it to both AuthStore and AgentRuntime’s secrets_root. Continue using
baseDir for the temporary database and scratch paths, and update the existing
AuthStore construction accordingly.
test/desktop-agent-chat-image-drop.md (1)

29-53: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Make the byte-exact assertion objectively verifiable.

The procedure asks for a byte-for-byte copy but never compares the original and copied bytes. Add a concrete check, such as matching sha256sum values or exact byte counts, so a transformed provider preview cannot falsely pass the manual test.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@test/desktop-agent-chat-image-drop.md` around lines 29 - 53, Update the “Use
the attachment's scratch path” step in the documented test procedure to require
an objective byte-level comparison between the original attachment and
`dropped-copy`, preferably by matching their `sha256sum` values. Keep the
existing filename-extension and byte-count checks, and make the expected result
explicitly require identical hashes.
🧹 Nitpick comments (3)
editor/lib/agent-chat/input-resource-policy.ts (2)

391-412: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

scratch-unavailable conflates two different rejection causes.

if (!scratch) return { reason: "scratch-unavailable" }; and the new binary-tools guard both return the same "scratch-unavailable" reason:

if (scratch.binaryTools === false && requiresScratchBinaryTools(resource)) {
  return { reason: "scratch-unavailable" };
}

Downstream code that maps UnavailableReason to a user-facing message (e.g. resourceLoweringNotice/resourcePreparationNotice in agent-composer-input.tsx) can't distinguish "no scratch binding at all" from "scratch exists but this file type needs binary tools that aren't available." A dedicated reason would preserve the diagnostic signal already captured by UnavailableReason.

♻️ Suggested new reason
   export type UnavailableReason =
     | "representation-unavailable"
     | "reference-capability-unavailable"
     | "provider-capability-unavailable"
     | "scratch-unavailable"
+    | "scratch-binary-tools-required"
     | "file-too-large"
     | "scratch-file-count-exceeded"
     | "scratch-budget-exceeded"
     | "draft-operable-copy-budget-exceeded"
     | "directory-cannot-be-attached"
     | "directory-reference-required";
 ...
     if (scratch.binaryTools === false && requiresScratchBinaryTools(resource)) {
-      return { reason: "scratch-unavailable" };
+      return { reason: "scratch-binary-tools-required" };
     }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@editor/lib/agent-chat/input-resource-policy.ts` around lines 391 - 412,
Update the binary-tools guard in scratchRoute to return a distinct
UnavailableReason from the scratch-missing case, while keeping if (!scratch)
mapped to "scratch-unavailable". Add the new reason to the UnavailableReason
definition and update downstream notice mappings such as resourceLoweringNotice
and resourcePreparationNotice to provide the appropriate message for this
specific rejection.

459-486: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Keep .ts off the text-only extension allowlist unless the MIME is TypeScript.

video/mp2t MPEG-2 Transport Stream segments use the .ts extension, so a bare .ts without application/typescript MIME should not fall through as text-safe. Remove .ts from the fallback extension allowlist, or gate it by application/typescript.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@editor/lib/agent-chat/input-resource-policy.ts` around lines 459 - 486,
Update requiresScratchBinaryTools so the fallback filename-extension allowlist
no longer treats .ts as text-safe; only classify .ts as safe when the parsed
MIME is application/typescript. Preserve the existing MIME checks and all other
extension handling.
packages/grida-daemon/src/shell/runner.ts (1)

349-371: 🚀 Performance & Scalability | 🔵 Trivial | 💤 Low value

finish now signals the process group on every normal exit and blocks on a poll wait.

Correct for revoking background descendants, but note the added latency is folded into duration_ms (reported to the model) and processGroupExists treats a non-ESRCH error (e.g. EPERM) as "still alive", so such a case polls until the full grace deadline instead of returning promptly.

♻️ Optional: capture duration before the teardown wait
     const finish = async (
       exitCode: number | null,
       exitSignal: NodeJS.Signals | null,
       spawnError?: Error
     ) => {
       if (settled) return;
       settled = true;
       cleanupListeners();
+      const durationMs = Date.now() - startedAt;
-        duration_ms: Date.now() - startedAt,
+        duration_ms: durationMs,
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/grida-daemon/src/shell/runner.ts` around lines 349 - 371, Update
finish so duration_ms is captured before the process-group teardown wait,
excluding polling latency from the reported command duration. Adjust
processGroupExists to avoid treating non-ESRCH errors such as EPERM as evidence
that the group remains alive; return promptly for those errors while preserving
normal existence detection.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/grida-ai-agent/src/runtime/sandbox-repro.live.test.ts`:
- Line 243: Update the comment adjacent to the shell_executor configuration to
remove references to the obsolete shell_execution_allowed boolean and describe
that the desktop supplies an OS-confined shell executor.

In `@packages/grida-ai-agent/src/session/scratch.ts`:
- Around line 602-609: Update sweepScratch to wrap each removeAuthorityEntrySync
call in its own try/catch, logging a warning for failures while continuing to
process the remaining session entries. Preserve the existing fail-closed
authority validation performed before the deletion loop.

In `@test/desktop-agent-chat-large-raster-drop.md`:
- Around line 27-32: Update the large-raster test scenario to use a
deterministic oversized image fixture with recorded pixel dimensions and byte
size, rather than the variable “over 5 MB or 2000 pixels” criterion. Ensure the
fixture is known to exercise the bounded provider representation while
preserving the expected successful thumbnail and image-description outcomes.

---

Outside diff comments:
In `@packages/grida-ai-agent/src/runtime/runtime.live.test.ts`:
- Around line 119-121: Define a shared authDir from PROVIDER_KEY, LIVE_AUTH_DIR,
and baseDir, then pass it to both AuthStore and AgentRuntime’s secrets_root.
Continue using baseDir for the temporary database and scratch paths, and update
the existing AuthStore construction accordingly.

In `@test/desktop-agent-chat-image-drop.md`:
- Around line 29-53: Update the “Use the attachment's scratch path” step in the
documented test procedure to require an objective byte-level comparison between
the original attachment and `dropped-copy`, preferably by matching their
`sha256sum` values. Keep the existing filename-extension and byte-count checks,
and make the expected result explicitly require identical hashes.

---

Nitpick comments:
In `@editor/lib/agent-chat/input-resource-policy.ts`:
- Around line 391-412: Update the binary-tools guard in scratchRoute to return a
distinct UnavailableReason from the scratch-missing case, while keeping if
(!scratch) mapped to "scratch-unavailable". Add the new reason to the
UnavailableReason definition and update downstream notice mappings such as
resourceLoweringNotice and resourcePreparationNotice to provide the appropriate
message for this specific rejection.
- Around line 459-486: Update requiresScratchBinaryTools so the fallback
filename-extension allowlist no longer treats .ts as text-safe; only classify
.ts as safe when the parsed MIME is application/typescript. Preserve the
existing MIME checks and all other extension handling.

In `@packages/grida-daemon/src/shell/runner.ts`:
- Around line 349-371: Update finish so duration_ms is captured before the
process-group teardown wait, excluding polling latency from the reported command
duration. Adjust processGroupExists to avoid treating non-ESRCH errors such as
EPERM as evidence that the group remains alive; return promptly for those errors
while preserving normal existence detection.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 97b79955-f263-4bb3-9a86-f989dfc0eb9e

📥 Commits

Reviewing files that changed from the base of the PR and between ccf2d18 and d9a1906.

📒 Files selected for processing (61)
  • SECURITY.md
  • desktop/README.md
  • desktop/docs/agent-authority.md
  • desktop/src/agent-sidecar-channel.test.ts
  • desktop/src/agent-sidecar-channel.ts
  • desktop/src/agent-sidecar-network.test.ts
  • desktop/src/agent-sidecar-network.ts
  • desktop/src/agent-sidecar.ts
  • desktop/src/main/agent-command-host.srt.test.ts
  • desktop/src/main/agent-command-host.test.ts
  • desktop/src/main/agent-command-host.ts
  • desktop/src/main/agent-network-host.test.ts
  • desktop/src/main/agent-network-host.ts
  • desktop/src/main/agent-sidecar-supervisor.ts
  • desktop/src/main/sandbox/manager.ts
  • desktop/src/preload-contract.test.ts
  • desktop/src/preload.ts
  • docs/wg/ai/agent/scratch.md
  • docs/wg/desktop/agent-security.md
  • editor/lib/agent-chat/input-resource-policy.test.ts
  • editor/lib/agent-chat/input-resource-policy.ts
  • editor/lib/agent-chat/input-resource-router.ts
  • editor/lib/desktop/bridge.test.ts
  • editor/lib/desktop/bridge.ts
  • editor/scaffolds/desktop/shared/agent-composer-input.tsx
  • packages/grida-ai-agent/README.md
  • packages/grida-ai-agent/src/__public-api__.test.ts
  • packages/grida-ai-agent/src/e2e-approval-resume.test.ts
  • packages/grida-ai-agent/src/http/routes/agent.test.ts
  • packages/grida-ai-agent/src/http/routes/sessions-lifecycle.test.ts
  • packages/grida-ai-agent/src/http/routes/sessions.ts
  • packages/grida-ai-agent/src/prompts.ts
  • packages/grida-ai-agent/src/runtime/command-backend.test.ts
  • packages/grida-ai-agent/src/runtime/command-backend.ts
  • packages/grida-ai-agent/src/runtime/image-gen.live.test.ts
  • packages/grida-ai-agent/src/runtime/index.ts
  • packages/grida-ai-agent/src/runtime/message-view.test.ts
  • packages/grida-ai-agent/src/runtime/run-agent.ts
  • packages/grida-ai-agent/src/runtime/run-input.test.ts
  • packages/grida-ai-agent/src/runtime/run-input.ts
  • packages/grida-ai-agent/src/runtime/runtime.live.test.ts
  • packages/grida-ai-agent/src/runtime/runtime.test.ts
  • packages/grida-ai-agent/src/runtime/sandbox-repro.live.test.ts
  • packages/grida-ai-agent/src/runtime/scratch.live.test.ts
  • packages/grida-ai-agent/src/runtime/workspace-agent-bindings.test.ts
  • packages/grida-ai-agent/src/runtime/workspace-agent-bindings.ts
  • packages/grida-ai-agent/src/server.test.ts
  • packages/grida-ai-agent/src/server.ts
  • packages/grida-ai-agent/src/session/scratch.test.ts
  • packages/grida-ai-agent/src/session/scratch.ts
  • packages/grida-ai-agent/src/session/store.ts
  • packages/grida-ai-agent/src/tools/run-command.test.ts
  • packages/grida-ai-agent/src/tools/run-command.ts
  • packages/grida-daemon/src/__public-api__.test.ts
  • packages/grida-daemon/src/server.ts
  • packages/grida-daemon/src/shell/runner.test.ts
  • packages/grida-daemon/src/shell/runner.ts
  • packages/grida-desktop-bridge/src/index.ts
  • test/desktop-agent-chat-generic-file-drop.md
  • test/desktop-agent-chat-image-drop.md
  • test/desktop-agent-chat-large-raster-drop.md
🚧 Files skipped from review as they are similar to previous changes (5)
  • docs/wg/ai/agent/scratch.md
  • packages/grida-ai-agent/src/runtime/run-agent.ts
  • packages/grida-ai-agent/src/prompts.ts
  • packages/grida-ai-agent/src/runtime/run-input.test.ts
  • editor/lib/agent-chat/input-resource-router.ts

Comment thread packages/grida-ai-agent/src/runtime/sandbox-repro.live.test.ts
Comment thread packages/grida-ai-agent/src/session/scratch.ts
Comment thread test/desktop-agent-chat-large-raster-drop.md Outdated
@coderabbitai coderabbitai Bot removed ai AI models, prompts, and pricing enhancement New feature or request labels Jul 30, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@editor/lib/agent-chat/input-resource-policy.ts`:
- Around line 484-486: Update the structured-text filename fallback regex in the
resource policy to include the .ts extension alongside the existing .tsx entry,
so TypeScript files with empty or unknown MIME types remain allowed without
binary tools.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 55e4bea1-d76e-412b-9782-df1c1ca5e3f8

📥 Commits

Reviewing files that changed from the base of the PR and between d9a1906 and 88ddac9.

📒 Files selected for processing (12)
  • editor/lib/agent-chat/input-resource-policy.test.ts
  • editor/lib/agent-chat/input-resource-policy.ts
  • editor/lib/agent-chat/input-resource-router.test.ts
  • editor/scaffolds/desktop/shared/agent-composer-input.tsx
  • packages/grida-ai-agent/src/runtime/runtime.live.test.ts
  • packages/grida-ai-agent/src/runtime/sandbox-repro.live.test.ts
  • packages/grida-ai-agent/src/session/scratch.test.ts
  • packages/grida-ai-agent/src/session/scratch.ts
  • packages/grida-daemon/src/shell/runner.test.ts
  • packages/grida-daemon/src/shell/runner.ts
  • test/desktop-agent-chat-image-drop.md
  • test/desktop-agent-chat-large-raster-drop.md
🚧 Files skipped from review as they are similar to previous changes (2)
  • test/desktop-agent-chat-large-raster-drop.md
  • packages/grida-ai-agent/src/runtime/sandbox-repro.live.test.ts

Comment thread editor/lib/agent-chat/input-resource-policy.ts Outdated
@vercel
vercel Bot temporarily deployed to Preview – blog July 31, 2026 11:18 Inactive
@vercel
vercel Bot temporarily deployed to Preview – backgrounds July 31, 2026 11:18 Inactive
@vercel
vercel Bot temporarily deployed to Preview – viewer July 31, 2026 11:18 Inactive
@coderabbitai coderabbitai Bot added ai AI models, prompts, and pricing enhancement New feature or request labels Jul 31, 2026
@softmarshmallow
softmarshmallow merged commit a2c460c into main Jul 31, 2026
17 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ai AI models, prompts, and pricing desktop this is a Grida Desktop App related issue documentation Improvements or additions to documentation enhancement New feature or request security

Projects

None yet

Development

Successfully merging this pull request may close these issues.

RFD: session scratch directory — ephemeral per-session working/output area for the agent

1 participant