Skip to content

perf(tools): bound foreground filesystem work and cancellation - #288

Merged
sambitcreate merged 14 commits into
mainfrom
feature/bounded-foreground-file-tools
Sep 30, 2026
Merged

sambitcreate merged 14 commits into
mainfrom
feature/bounded-foreground-file-tools

Conversation

@sambitcreate

@sambitcreate sambitcreate commented Sep 28, 2026 •

Copy link
Copy Markdown
Owner

Foreground read_file previously read an entire file before returning a 200 KB prefix, while grep ignored cancellation and could run JavaScript regexes on Electron's main thread. list_dir and no-match glob searches could enumerate entire trees despite output limits.

This change bounds descriptor reads, directory enumeration, aggregate grep bytes, matching time and returned output. Cancellation and search deadlines settle callers even while filesystem I/O is pending. Four bounded operation owners retain admission until original I/O and cleanup settle; workers terminate immediately on abort and preserve native JavaScript regex behavior. Issued kernel syscalls cannot be cancelled, so stalled I/O retains its slot. Glob uses pinned minimatch segment parsing with Node-compatible traversal, preserving safe symlinks, mixed absolute/relative brace-expanded prefixes, Windows drive/UNC roots and glob-dependent .. paths. Parent hidden-file and secret policies remain distinct from subagent policy.

Validation:

  • 79 coding-tool and generation tests; 167 tool-output tests; type-check and scoped lint pass.
  • 47 CI policy/inventory tests pass. The pinned-Electron smoke is a registered package command and required Desktop build/diagnostics CI step, with isolated fixtures, a process deadline, signal handling, and close-before-cleanup.
  • Production Electron bundle builds; pinned Electron 43.1.1 / Node 24.18.0 smoke covers glob compatibility, lookbehind/backreferences, repeated worker failures/cancellation, deadlines and zero retained worker ports.
  • Independent Astra medium review cleared the implementation and follow-up fixes; native-glob differential and deferred-I/O tests cover compatibility, concurrent cancellation, late handles, cleanup ownership and admission recovery.
  • Clean pinned-dependency counters: 16 MiB input now reads 200,001 bytes, down from 16,777,216; already-aborted grep rejects with zero bytes read; wide no-match scans stop at 10,000 entries with an explicit incomplete notice.

Tiny grep calls pay roughly 17 ms of worker startup versus sub-millisecond baseline calls in the quiet synthetic run. Full fixtures, raw before/after receipts, compatibility decisions and reproduction commands are in docs/performance/foreground-file-tools-2026-09-28/.

CI follow-up: reuse the exact stream-consumer gate correction from #278 / #280. The test now deliberately runs unrelated progress while the intended stream endpoint is held; reverting the exact endpoint to /events reproduces a progress-observer timeout. All 208 iOS chat tests pass on the explicitly selected iPhone 17 Pro / iOS 27 simulator after the correction. Simulator results are regression evidence, not physical-device acceptance.

The single permitted retry of CI run 36480769658 failed the separate testCompletedUploadsRemainOwnedThroughRemovalAndExplicitCleanup test. That failure remains unreproduced and unresolved: the unchanged local class also passed 208/208. This patch adds per-mode failure labels and preserves failed hosted XCTest result bundles for seven days, with CI policy coverage, while keeping all ownership assertions and timeouts. Both original failures and the later, separate simulator launch errors are recorded in the coordinating audit's papercuts.

Integrated main through ea65d03c3 by ordinary merges, preserving troubleshooting records and both parents' test commands. The workspace bulk metadata FIFO budget and foreground-operation owners remain separate; independent integration review found no nested admission or shared release path. Workspace/Remote validation passed 43 tests with one existing platform skip after building its native helper. Integration validation passed 56 coding-tool/generation tests, 47 CI-policy tests, type-check, advisor source-drift coverage, the Electron bundle build, and 214 iOS chat tests. The Electron smoke now joins original owned operations between cancellation/deadline samples and retains late cleanup failures, matching the production contract where caller cancellation precedes disposal. It passes alongside local build/type-check activity with zero worker ports; a temporary rejection after real worker termination correctly fails the cleanup assertion. Independent Astra medium review cleared the integration and final smoke correction.

@sambitcreate

Copy link
Copy Markdown
Owner Author

/hermes review

@very-hermes-bot

very-hermes-bot commented Sep 28, 2026 •

Copy link
Copy Markdown
Collaborator

Hermes Review Bot

Confidence: 5

Engine: agy/gemini-3.8-flash-high
Review mode: full
Head: e980e5993a4674739ccccf7e43ff9c65eb8523b2
Generated: 2026-09-30T01:49:43+00:00
Reviews: 1

Summary

Bounds foreground filesystem operations (read_file, list_dir, glob, grep) to prevent Electron main-process event-loop starvation, unbounded descriptor reads, runaway directory enumeration, and unconstrained regex backtracking. A process-wide admission gate (ForegroundReadOperations) caps concurrent foreground work to four slots, while native JavaScript regex evaluation and Node-compatible glob traversal are offloaded into dedicated, short-lived worker threads with a 32 MB heap limit. Descriptor reads are capped at 200 KB for read_file and 512 KB per file (10 MiB aggregate) for grep, while directory scans halt deterministically at 10,000 entries or 5 seconds with structured truncation notices. Descriptors and worker handles are closed through closeForegroundResource, ensuring pending kernel syscalls and late cancellations retain admission until cleanup completes or quarantines failed descriptors. Maintainers should double-check that the 5,000 ms search deadline and 32 MB worker memory cap leave sufficient headroom on constrained host machines when multiple foreground searches run concurrently.

Confidence Score: 5/5

Every changed file, boundary condition, and edge case was inspected and traced end-to-end against parent/subagent security models, concurrency scopes, and test contracts.

📁 Important Files Changed
  • main/services/foreground-read-scope.ts: Implements ForegroundReadOperations (a four-slot concurrency scope tracking active operations through pending I/O and cleanup) and closeForegroundResource, which quarantines capacity on cleanup failure.
  • main/services/coding-tool-matcher.ts: Spawns and manages short-lived Worker threads for native JS regex evaluation (grep) and glob step execution (glob), enforcing 32 MB memory limits, lifetime deadlines, and worker termination.
  • main/services/coding-tool-glob-worker.ts: Implements Node.js-compatible segment traversal logic using pinned minimatch 9.0.9, preserving Windows UNC/drive roots and symlink bounds while keeping filesystem access on the host.
  • main/services/coding-tools.ts: Wraps parent read_file, list_dir, glob, and grep in the foreground scope, enforcing descriptor limits (200 KB), scan limits (10,000 entries), aggregate byte ceilings (10 MiB), and clean UTF-8 sequence truncation.
  • main/services/coding-tools.test.ts: Adds unit and regression suites covering byte/entry limits, catastrophic backtracking cancellation, handle cleanup ownership, admission quarantine, and Windows drive/UNC roots.
  • scripts/smoke-foreground-file-tools.ts & scripts/run-foreground-file-tools-smoke.mjs: Bundles and runs an isolated Electron smoke test verifying native glob/regex matching, worker termination, and zero retained message ports.
  • .github/workflows/ci.yml & scripts/check-ci-policy.test.mjs: Integrates the Electron smoke test into Desktop CI and adds xcresult artifact capture for failed iOS simulator test runs.
  • ios/AidenOnTheGoTests/AidenChatTests.swift: Adds test mode labels to assertions in testCompletedUploadsRemainOwnedThroughRemovalAndExplicitCleanup to improve simulator diagnostic output without altering test assertions.

Findings

No findings.

Sequence Diagram

sequenceDiagram
  autonumber
  actor Agent as Agent Turn
  participant Scope as ForegroundReadScope
  participant Tool as Parent Tool (Grep/Glob)
  participant Worker as Matcher Worker
  participant FS as Filesystem

  Agent->>Scope: execute(params, signal)
  Scope->>Tool: run(operationSignal)
  Tool->>Worker: spawn & initialize worker
  Worker-->>Tool: ready (seeds / ack)
  loop Traversal & Content Scan
    Tool->>FS: open / opendir (bufferSize: 1)
    FS-->>Tool: entries / file chunk
    Tool->>Worker: match(lines) / step(request)
    Worker-->>Tool: matched indices / next tasks
  end
  Tool->>Worker: terminate()
  Worker-->>Tool: exit
  Tool-->>Scope: formatted bounded result
  Scope-->>Agent: textResult(matches + warnings)
Loading
[]

Last reviewed commit: e980e5993a46
Reviews (1) · Comment /hermes review to trigger a new review · /hermes review full for full re-review

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Important

The new parent glob traversal drops results for valid brace patterns that mix absolute and relative alternatives, so native fs.glob compatibility is incomplete.

Reviewed changes I reviewed the bounded foreground file-tool implementation and its worker-backed cancellation and glob traversal changes at b37b4b2.

  • Bounded filesystem work adds capped descriptor reads, directory enumeration, aggregate grep input, match counts, and output.
  • Worker-backed matching moves JavaScript regex matching off the Electron main thread and terminates workers on cancellation and deadlines.
  • Native glob traversal replaces direct fs.glob iteration with bounded segment-state traversal and differential tests.

Pullfrog  | Fix all ➔ | Fix 👍s ➔ | View workflow run | Using GPT Luna | 𝕏

Comment thread main/services/coding-tool-glob-worker.ts Outdated

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Important

This PR has a glob result regression and foreground filesystem calls that can outlive cancellation or deadlines.

Reviewed changes This review covers bounded parent filesystem reads and scans, worker-isolated grep/glob matching, compatibility handling, and the new tests and performance evidence.

  • Bounded filesystem tools. read_file now reads only a capped descriptor prefix; list_dir, glob, and grep cap enumeration, grep bytes, results, elapsed work, and output.
  • Isolated search matching. Grep and glob use disposable workers, while glob traversal uses minimatch segments and host-side workspace checks.
  • Compatibility and evidence. The PR adds behavioral tests, benchmark receipts, an Electron smoke harness, and the pinned minimatch dependency.

Pullfrog  | Fix all ➔ | Fix 👍s ➔ | View workflow run | Using GPT Luna | 𝕏

Comment thread main/services/coding-tool-glob-worker.ts Outdated
Comment thread main/services/coding-tools.ts
@sambitcreate

Copy link
Copy Markdown
Owner Author

/hermes review

@sambitcreate

Copy link
Copy Markdown
Owner Author

/hermes review

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

✅ No new issues found.

Reviewed changes Re-reviewed the follow-up changes since the prior Pullfrog review at b37b4b2.

  • Corrected mixed-root glob expansion. Derived each brace-expanded alternative's root independently and added native differential and workspace-confinement coverage.
  • Bounded cancellation and pending I/O. Added foreground operation ownership across read_file, list_dir, glob, and grep, retaining admission until I/O and cleanup settle while callers and workers respond to cancellation and deadlines.

Pullfrog  | View workflow run | Using GPT Luna | 𝕏

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

✅ No new issues found.

Reviewed changes Re-reviewed the Windows glob-root correction added since the prior Pullfrog review at b1bc608.

  • Normalized Windows glob roots. Counted slash-normalized minimatch root segments so drive and UNC alternatives skip the parsed prefix correctly, with Windows-semantics worker fixtures for drive, UNC, and mixed-root patterns.

Pullfrog  | View workflow run | Using GPT Luna | 𝕏

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Important

The final offset fix still mis-seeds a valid UNC glob whose pattern is exactly a share root without a trailing slash. This can return a duplicated share component rather than the requested root.

Reviewed changes Re-reviewed the final Windows normalized glob-root offset fix and behavioral fixtures against the full PR at exact head b28f681e863ecdccabd7aba551b8cc79c71f6535.

  • Normalized Windows root offsets. Replaced host-separator counting with normalized slash counting and added production-worker fixtures for drive, UNC, and mixed-root patterns.

Pullfrog  | Fix all ➔ | Fix 👍s ➔ | View workflow run | Using GPT Luna | 𝕏

Comment thread main/services/coding-tool-glob-worker.ts Outdated
@sambitcreate

Copy link
Copy Markdown
Owner Author

/hermes review

@sambitcreate

Copy link
Copy Markdown
Owner Author

/hermes review

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

ℹ️ No critical issues — one minor suggestion inline.

Reviewed changes Re-reviewed the Electron smoke runner, CI registration, and refreshed evidence added since the prior Pullfrog review at b28f681.

  • Registered the Electron smoke runner. Added an isolated pinned-Electron package command as a required Desktop verification step, with CI-policy coverage.
  • Refreshed the runtime evidence. Updated the benchmark and smoke receipts; one now records an author-local absolute workspace path.

Pullfrog  | Fix all ➔ | Fix 👍s ➔ | View workflow run | Using GPT Luna | 𝕏

Comment thread docs/performance/foreground-file-tools-2026-09-28/electron.json Outdated
@sambitcreate

Copy link
Copy Markdown
Owner Author

/hermes review

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

✅ No new issues found.

Reviewed changes Re-reviewed the two commits added since the prior Pullfrog review at 73f8664.

  • Fixed bare UNC share-root matching. Consumed the complete Windows share root and added worker fixtures for bare roots with and without a trailing slash, including mixed relative arms.
  • Normalized Electron smoke receipts. Replaced the synthetic workspace's absolute prefix with <workspace> in emitted glob fixtures while retaining real paths in runtime assertions.

Focused native glob and Windows worker tests and npm run type-check passed. Electron smoke could not run in this Linux environment because the SUID sandbox helper was not configured.

Pullfrog  | View workflow run | Using GPT Luna | 𝕏

@sambitcreate

Copy link
Copy Markdown
Owner Author

/hermes review

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

✅ No new issues found.

Reviewed changes Re-reviewed the commit added since the prior Pullfrog review at 5059c78.

  • Isolated the recovery-stream gate. Held the exact stream-consumer endpoint and exercised the unrelated progress stream first, preventing it from consuming the test gate.
  • Preserved simulator diagnostics. Added an .xcresult output and seven-day failure artifact, with CI-policy coverage for the configuration.
  • Added mode-specific failure context. Included upload-lifecycle mode names in assertion messages without changing the assertions or timeouts.

The CI policy suite passed (47 tests). iOS simulator XCTest could not be run in this Linux review environment.

Pullfrog  | View workflow run | Using GPT Luna | 𝕏

@sambitcreate

Copy link
Copy Markdown
Owner Author

/hermes review

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

✅ No new issues found.

Reviewed changes Re-reviewed the PR at 0beec58, including the commits added since the prior Pullfrog review at 30b042b.

  • Joined foreground cleanup in the Electron smoke. Added observation and joining of the underlying operations after caller cancellation or deadline, and retained late cleanup errors so sequential samples do not race the four-operation admission limit.
  • Integrated current main. Merged main at 137ce6bd1 and retained the combined CI/test registration and audit notes.

The focused coding-tool and generation-runtime suites passed (79 tests), as did type-check, smoke-script lint, and CI policy (47 tests). The Electron smoke bundled successfully but could not launch in this Linux environment because its SUID sandbox helper is not configured; Electron exited with SIGTRAP.

Pullfrog  | View workflow run | Using GPT Luna | 𝕏

@sambitcreate

Copy link
Copy Markdown
Owner Author

/hermes review

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

ℹ️ No critical issues — one minor documentation suggestion.

Reviewed changes Re-reviewed the merge and cleanup commits added after the previously checked head ad38615.

  • Merged current main. Integrated main at 4d0d982.
  • Removed PR-specific troubleshooting notes. Dropped 47 lines from .papercuts/troubleshooting.md; foreground-tool behavior is unchanged.

ℹ️ The worker lifecycle test rationale was dropped

The new commit removes the only durable note that a live idle worker's MessagePort may be absent from _getActiveHandles(). The actual-termination test remains, but retaining why that oracle matters would help prevent future tests from mistaking an unreported port for a terminated worker.

Technical details
# Preserve the worker-lifecycle test oracle rationale

## Affected sites
- `.papercuts/troubleshooting.md` — commit `e980e599` removes the note that a live idle worker's `MessagePort` may be absent from Node's `_getActiveHandles()`.
- `main/services/coding-tools.test.ts:2480-2503` — the lifecycle test awaits actual `Worker.terminate()` promises but does not explain why active-handle inspection is insufficient.

## Required outcome
- Retain this reusable testing pitfall in durable project guidance or next to the lifecycle test.

Pullfrog  | Fix it ➔ | View workflow run | Using GPT Luna | 𝕏

@sambitcreate
sambitcreate merged commit 1833b89 into main Sep 30, 2026
43 of 45 checks passed
@sambitcreate
sambitcreate deleted the feature/bounded-foreground-file-tools branch September 30, 2026 18:33
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.

2 participants