Skip to content

fix(infra): scope Windows path realpath caches#85264

Closed
211-lee wants to merge 1 commit into
openclaw:mainfrom
211-lee:fix/windows-lstat-global-cache
Closed

fix(infra): scope Windows path realpath caches#85264
211-lee wants to merge 1 commit into
openclaw:mainfrom
211-lee:fix/windows-lstat-global-cache

Conversation

@211-lee

@211-lee 211-lee commented May 22, 2026

Copy link
Copy Markdown

Summary

Windows lstat/realpath calls are expensive enough that repeated path-boundary checks can dominate startup and agent-path flows. The original version tried to fix that with process-wide realpath caches, but those caches sit on plugin, skill, hook, and sandbox containment checks. That lifetime is too broad: stale symlink or ancestor answers can survive after the filesystem changes.

This revision keeps the performance direction while moving the cache boundary to caller-owned operation scopes:

  • src/infra/path-guards.ts remains the direct @openclaw/fs-safe/path export surface; no process-wide realpath cache is installed there.
  • src/infra/boundary-path.ts accepts an optional caller-owned cache for resolvePathViaExistingAncestorSync.
  • Plugin hook/skill resolution and sandbox host-path validation now pass per-operation caches so repeated checks in one operation avoid duplicate canonicalization work.
  • Regression tests assert stale symlink/junction and ancestor changes are detected without global invalidation, including native Windows directory junction cleanup.

Closes #85262

Real behavior proof

Behavior addressed: reduces repeated Windows path canonicalization in plugin hook/skill and sandbox host-path operations without adding stale process-wide path answers to security-sensitive containment checks.

Real environment tested: local linked worktree for focused tests/lint/review; AWS Crabbox native Windows for focused runtime tests; AWS Crabbox Linux for check:changed; WSL2 runner acquisition was attempted on both AWS and Azure but did not produce a usable WSL2 test lane.

Exact steps or command run after this patch:

node scripts/run-vitest.mjs src/infra/path-safety.test.ts src/infra/boundary-path.test.ts src/hooks/plugin-hooks.test.ts src/skills/loading/plugin-skills.test.ts src/agents/sandbox/host-paths.test.ts src/agents/sandbox/validate-sandbox-security.test.ts src/agents/sandbox/workspace-mounts.test.ts src/agents/sandbox/fs-paths.test.ts
node scripts/run-oxlint.mjs --tsconfig config/tsconfig/oxlint.core.json src/infra/path-safety.test.ts src/infra/boundary-path.test.ts src/hooks/plugin-hooks.ts src/skills/loading/plugin-skills.ts src/agents/sandbox/host-paths.ts src/agents/sandbox/validate-sandbox-security.ts src/agents/sandbox/workspace-mounts.ts src/agents/sandbox/fs-paths.ts src/agents/sandbox/fs-paths.test.ts
git diff --check origin/main...HEAD
.agents/skills/autoreview/scripts/autoreview --mode branch --base origin/main
node scripts/crabbox-wrapper.mjs run --provider aws --target windows --id cbx_dc20a584615f --reclaim --no-sync --label windows-realpath-85264-native-tests --idle-timeout 45m --ttl 90m --timing-json --stop-after never --shell -- 'node scripts/run-vitest.mjs src/infra/path-safety.test.ts src/infra/boundary-path.test.ts src/hooks/plugin-hooks.test.ts src/skills/loading/plugin-skills.test.ts src/agents/sandbox/host-paths.test.ts src/agents/sandbox/validate-sandbox-security.test.ts src/agents/sandbox/workspace-mounts.test.ts src/agents/sandbox/fs-paths.test.ts'
node scripts/crabbox-wrapper.mjs run --provider aws --target linux --label windows-realpath-85264-check-changed --idle-timeout 90m --ttl 180m --timing-json --stop-after always --shell -- 'env OPENCLAW_CHECK_CHANGED_REMOTE_CHILD=1 OPENCLAW_CHANGED_LANES_RAW_SYNC=1 CI=1 corepack pnpm check:changed'

Evidence after fix:

  • Local focused Vitest at pushed head 483fc336ad: 5 shards passed, 114 tests.
  • Local oxlint/diff check at pushed head 483fc336ad: passed.
  • Final autoreview at pushed head 483fc336ad: clean, no accepted/actionable findings.
  • AWS Crabbox native Windows focused proof: provider=aws, lease=cbx_dc20a584615f, run=run_b4c210ac8166, hydrate run https://github.com/openclaw/openclaw/actions/runs/26719083996. Focused Vitest passed 5 shards: 111 passed, 3 skipped.
  • AWS Crabbox changed gate: provider=aws, lease=cbx_ab9a2c3903d5, run=run_4137bbc8c85d, pnpm check:changed passed.

Observed result after fix: repeated path canonicalization inside a single plugin/sandbox operation can reuse one caller-owned cache, while a later operation re-reads current filesystem state and blocks stale symlink/junction escapes.

What was not tested: full end-to-end Windows startup profiling at the current rebased head 483fc336ad (performance data was collected at prior heads; the rebase was conflict-resolution only with no logic changes). The manifest-registry-installed lstat hotspot is intentionally out of scope and tracked in #90362.

Remaining performance gap

The largest remaining lstat gap is in manifest-registry-installed.ts, where buildInstalledManifestRegistryIndexKey() is called ~179 times per config validation, each time creating a new scoped Map(). This is intentionally left as a follow-up in #90362 — the current PR focuses on the plugin hook/skill and sandbox containment paths. The manifest-registry optimization can be addressed in a separate PR without changing the security-boundary cache lifetime design landed here.

Runner notes

  • The AWS native Windows image had Node after GitHub Actions hydration but not node_modules; pnpm install --frozen-lockfile hit Windows EMFILE twice near finalization. Vitest was nevertheless present and resolvable, and the focused native Windows test command passed.
  • The current branch was rebased and pushed to 483fc336ad; origin/main continued moving during validation, so the final broad gate is recorded against the rebased head before that later churn.

Windows Performance Proof

Environment

  • Windows 10 Pro, NTFS, Node.js v24.15.0
  • OpenClaw v2026.5.18 (installed version)
  • 94 bundled plugins, 5 enabled (browser, device-pair, phone-control, talk-voice, octo)

Method

CPU profiling via Node.js inspector API, 120s coverage: startup → ready → idle (no webchat connection).

Scoped Cache vs Global Cache vs No Cache

Metric No cache (baseline) Global cache Scoped cache (current head)
lstat total 47,834ms 8,016ms (-83%) 21,376ms (-55%)
Startup to ready ~17s 8.7s 14.0s
Profile gateway-1779357547869.cpuprofile gateway-1779440772524.cpuprofile gateway-1780375536440.cpuprofile

Why scoped cache is slower than global cache (+13s)

The gap is not from "other callers not passing a cache" — it is from the largest single caller manifest-registry-installed.ts:

function buildInstalledManifestRegistryIndexKey(index) {
  const realpathCache = new Map(); // ← new Map on every call
  index.plugins.map((record) => resolvePackageJsonPath(record, realpathCache));
}
// Called ~179 times (once per config validation), each time starting with an empty Map
  • Global cache: 1st call fills ~188 paths, next 178 calls all hit → actual lstat ~188 times
  • Scoped cache: 179 calls × ~188 misses each (new Map) → actual lstat ~33,600 times
  • 33,600 × ~500µs ≈ 16.8s — closely matches the measured 13.4s gap

The scoped-cache approach still delivers a 55% reduction in lstat time and 3s faster startup compared to no cache, while avoiding stale process-wide cache answers in security-sensitive containment checks.

Cache Behavior (instrumented dist, global-cache version, call counting)

Metric Value
safeRealpathSync total calls 66,634
Cache hits 65,784 (98.7%)
Cache misses (actual lstat) 850
isPathInsideWithRealpath calls 15,937
Global cache entries 292

Per-phase breakdown:

Phase safeRealpath CacheHit HitRate isPathInside
startup (→ready) 10,300 9,942 96.5% 2,353
ready-idle 6,706 6,666 99.4% 1,566
webchat-api 9,874 9,822 99.5% 2,614
chat-processing 35,907 35,531 99.0% 8,273
post-reply 3,847 3,823 99.4% 1,131

Cache entries = 3 per plugin (root dir + package.json + entry file).
292 entries × ~200 bytes = ~58KB memory. Bounded by plugin count.

Cache growth test (after installing @openclaw/feishu)

Calls cacheSize Hits HitRate
1 0 0
1,000 292 699 early fill phase
5,000 292 4,651 93%
10,000 292 9,635 96.4%
50,000 301 49,338 98.7%

+1 plugin = +3 cache entries (+~600 bytes). Cache is bounded.

Reproducing

# Profile (requires gateway not already running):
node profile-gateway-internal.mjs
# → opens webchat, send a message, wait 120s
# → outputs .cpuprofile file

# Analyze:
node analyze-lstat-deep.mjs <file>.cpuprofile

Rebase note (2026-07-06): Rebased onto latest origin/main (e5a605424e) — conflict-resolution only, no logic changes. New head: 483fc336ad.

@openclaw-barnacle openclaw-barnacle Bot added size: S triage: needs-real-behavior-proof Candidate: external PR needs after-fix proof from a real setup. labels May 22, 2026
@clawsweeper

clawsweeper Bot commented May 22, 2026

Copy link
Copy Markdown
Contributor

Codex review: needs maintainer review before merge. Reviewed July 6, 2026, 4:09 AM ET / 08:09 UTC.

Summary
The PR adds caller-owned realpath and existing-ancestor caches to plugin hook/skill resolution and sandbox host-path checks, with regression tests for stale symlink and junction behavior.

PR surface: Source +77, Tests +127. Total +204 across 10 files.

Reproducibility: yes. source-reproducible with supplied live evidence: current main still uses uncached helper/call-site shapes, and the issue/PR include Windows CPU-profile and Crabbox evidence for the lstat-heavy path. I did not rerun native Windows profiling in this read-only review.

Review metrics: 1 noteworthy metric.

  • Operation-local cache scopes: 6 added. The diff adds caller-owned cache lifetimes across hook, skill, publishing, sandbox validation, workspace mount, and sandbox path-resolution operations, so maintainers should review the cache boundary before merge.

Stored data model
Persistent data-model change detected: persistent cache schema: src/agents/sandbox/host-paths.ts, persistent cache schema: src/hooks/plugin-hooks.ts, persistent cache schema: src/infra/boundary-path.test.ts, persistent cache schema: src/infra/boundary-path.ts, persistent cache schema: src/infra/path-safety.test.ts, persistent cache schema: src/skills/loading/plugin-skills.ts. Confirm migration or upgrade compatibility proof before merge.

Root-cause cluster
Relationship: fixed_by_candidate
Canonical: #85262
Summary: This PR is the active candidate fix for the broader Windows lstat bottleneck issue; the manifest-registry follow-up is related performance work but was handled separately.

Members:

Proposal only: this assessment does not dispatch repair, suppress jobs, mutate sibling items, close, or merge anything.

Merge readiness
Overall: 🐚 platinum hermit
Proof: 🐚 platinum hermit ✨ media proof bonus
Patch quality: 🐚 platinum hermit
Result: ready for maintainer review.

Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch.

Rank-up moves:

  • [P2] Maintainer should explicitly accept or reject the operation-scoped containment cache lifetime before merge.

Risk before merge

  • [P1] The diff intentionally reuses canonical path answers within plugin and sandbox containment operations, so maintainers should explicitly accept that per-operation cache lifetime before merge.
  • [P1] The PR body supplies strong Windows focused proof and profiling, but full Windows startup profiling was not rerun at the latest pushed head; the manifest-registry hotspot is already handled separately by perf(plugins): reuse installed manifest realpaths #96710.

Maintainer options:

  1. Accept the operation-local lifetime (recommended)
    Maintainers can land this once they explicitly accept the per-operation cache lifetime and exact-head checks remain green.
  2. Ask for refreshed Windows profiling
    If performance confidence is the blocker, ask the contributor to rerun the Windows startup profile on the latest head before merge.
  3. Pause for a narrower design
    If containment caching is not acceptable, pause or close this branch and pursue a cache-free containment design plus non-boundary optimizations.

Next step before merge

  • [P2] Human review should decide the security-boundary cache lifetime; I did not find a narrow remaining code repair for an automated worker to make.

Maintainer decision needed

  • Question: Should OpenClaw accept operation-scoped realpath caches inside plugin hook/skill and sandbox containment checks for this Windows lstat fix?
  • Rationale: The implementation is narrower than the original process-wide cache and source/CI evidence now looks sound, but it still changes cache lifetime for security-sensitive path containment checks, which should be an explicit maintainer call.
  • Likely owner: vincentkoc — He is the assigned reviewer and recently handled adjacent fs-safe facade and manifest realpath-cache work.
  • Options:
    • Accept operation-scoped caches (recommended): Land after confirming that one caller-owned cache per hook, skill, bind-validation, and sandbox path-resolution operation is the desired security/performance tradeoff.
    • Require non-containment optimization only: Reject cache reuse in containment checks and limit Windows lstat work to plugin metadata or other non-boundary paths.
    • Pause for a narrower cache contract: Hold this PR until maintainers define the exact allowed cache lifetime for plugin and sandbox path checks.

Security
Cleared: No concrete supply-chain issue or bypass was found; the remaining security point is maintainer acceptance of the operation-scoped containment cache lifetime.

Review details

Best possible solution:

Land this PR, or a maintainer replacement, after explicit security-boundary acceptance of the operation-scoped cache lifetime while keeping the manifest-registry optimization separate as already handled by #96710.

Do we have a high-confidence way to reproduce the issue?

Yes, source-reproducible with supplied live evidence: current main still uses uncached helper/call-site shapes, and the issue/PR include Windows CPU-profile and Crabbox evidence for the lstat-heavy path. I did not rerun native Windows profiling in this read-only review.

Is this the best way to solve the issue?

Yes, with maintainer sign-off: operation-scoped caches are the narrow maintainable alternative to the original process-wide cache proposal, and the remaining manifest-registry hotspot is already handled by a separate merged PR. The unresolved choice is security-boundary acceptance, not a code defect I can support as a finding.

AGENTS.md: found and applied where relevant.

Codex review notes: model internal, reasoning high; reviewed against 535ab05dcd88.

Label changes

Label changes:

  • add proof: sufficient: Contributor real behavior proof is sufficient. The PR body includes Windows Crabbox focused runtime proof, changed-gate output, and lstat profile evidence, while live exact-head CI is now green after the export repair.
  • add rating: 🐚 platinum hermit: Overall readiness is 🐚 platinum hermit; proof is 🐚 platinum hermit and patch quality is 🐚 platinum hermit.
  • add status: 👀 ready for maintainer look: ClawSweeper has no concrete contributor-facing blocker left for this PR. Sufficient (linked_artifact): The PR body includes Windows Crabbox focused runtime proof, changed-gate output, and lstat profile evidence, while live exact-head CI is now green after the export repair.
  • remove rating: 🦪 silver shellfish: Current PR rating is rating: 🐚 platinum hermit, so this older rating label is no longer current.
  • remove status: 📣 needs proof: Current PR status label is status: 👀 ready for maintainer look.

Label justifications:

  • P2: This is a bounded Windows performance and path-boundary improvement with a linked issue and limited blast radius, not an outage or confirmed bypass.
  • merge-risk: 🚨 security-boundary: Merging changes cache lifetimes inside plugin and sandbox realpath containment checks, where overly broad reuse could weaken boundary enforcement if the lifetime is wrong.
  • rating: 🐚 platinum hermit: Overall readiness is 🐚 platinum hermit; proof is 🐚 platinum hermit and patch quality is 🐚 platinum hermit.
  • status: 👀 ready for maintainer look: ClawSweeper has no concrete contributor-facing blocker left for this PR. Sufficient (linked_artifact): The PR body includes Windows Crabbox focused runtime proof, changed-gate output, and lstat profile evidence, while live exact-head CI is now green after the export repair.
  • proof: sufficient: Contributor real behavior proof is sufficient. The PR body includes Windows Crabbox focused runtime proof, changed-gate output, and lstat profile evidence, while live exact-head CI is now green after the export repair.
Evidence reviewed

PR surface:

Source +77, Tests +127. Total +204 across 10 files.

View PR surface stats
Area Files Added Removed Net
Source 7 103 26 +77
Tests 3 131 4 +127
Docs 0 0 0 0
Config 0 0 0 0
Generated 0 0 0 0
Other 0 0 0 0
Total 10 234 30 +204

What I checked:

  • PR head implements scoped boundary-path cache: At the latest PR head, resolvePathViaExistingAncestorSync wraps the upstream fs-safe helper with an optional caller-owned Map, and the duplicate upstream re-export is no longer present. (src/infra/boundary-path.ts:8, 3cf89e1b73e5)
  • PR head scopes plugin hook realpath reuse per operation: Plugin hook directory resolution creates one cache for the resolution pass and passes it into isPathInsideWithRealpath while preserving realpath containment enforcement. (src/hooks/plugin-hooks.ts:47, 3cf89e1b73e5)
  • Current main does not already contain the central change: Current main still re-exports resolvePathViaExistingAncestorSync directly from fs-safe and plugin hook checks call isPathInsideWithRealpath without an operation-local cache. (src/infra/boundary-path.ts:6, 535ab05dcd88)
  • Dependency contract supports the cache parameter: The published @openclaw/[email protected] type surface exposes safeRealpathSync(targetPath, cache?) and isPathInsideWithRealpath(..., { cache? }); resolvePathViaExistingAncestorSync itself has no cache parameter, so the OpenClaw wrapper is the local extension point. (package.json:1991, 535ab05dcd88)
  • Exact-head CI is currently green: Live GitHub status for head 3cf89e1b73e5ca4d4a9a8b81e8ccbd8c7af0f7ff showed 66 successful check runs, including check-prod-types, with no failed check runs in the summarized rollup. (3cf89e1b73e5)
  • Manifest-registry follow-up is separate and merged: Merged PR perf(plugins): reuse installed manifest realpaths #96710 moved the installed manifest registry realpath cache to a lifecycle-owned process cache, but it does not replace this PR's hook, skill, and sandbox containment changes. (src/plugins/manifest-registry-installed.ts:35, 535ab05dcd88)

Likely related people:

  • vincentkoc: Assigned reviewer on this PR; recent history includes fs-safe facade cleanup, sandbox helper export trimming, and the merged manifest-registry realpath follow-up. (role: likely follow-up owner; confidence: high; commits: 89c90210fb90, be4c54117683, 94ae918d8f40; files: src/infra/boundary-path.ts, src/agents/sandbox/host-paths.ts, src/plugins/manifest-registry-installed.ts)
  • steipete: Introduced the fs-safe extraction and merged adjacent plugin package realpath caching, which are central patterns for this PR's cache-boundary design. (role: feature-history and adjacent cache contributor; confidence: medium; commits: 538605ff44d2, 69d728ac4f9c; files: src/infra/boundary-path.ts, src/infra/path-safety.ts, src/plugins/installed-plugin-index-record-builder.ts)
  • brokemac79: Recently changed sandbox skill materialization and workspace mount behavior in the sandbox filesystem area this PR also touches. (role: recent adjacent sandbox contributor; confidence: medium; commits: 3b6bcbfb5045; files: src/agents/sandbox/workspace-mounts.ts, src/agents/sandbox/fs-paths.ts)
What the crustacean ranks mean
  • 🦀 challenger crab: rare, exceptional readiness with strong proof, clean implementation, and convincing validation.
  • 🦞 diamond lobster: very strong readiness with only minor maintainer review expected.
  • 🐚 platinum hermit: good normal PR, likely mergeable with ordinary maintainer review.
  • 🦐 gold shrimp: useful signal, but proof or patch confidence is still limited.
  • 🦪 silver shellfish: thin signal; proof, validation, or implementation needs work.
  • 🧂 unranked krab: not merge-ready because proof is missing/unusable or there are serious correctness or safety concerns.
  • 🌊 off-meta tidepool: rating does not apply to this item.

Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics.

How this review workflow works
  • ClawSweeper keeps one durable marker-backed review comment per issue or PR.
  • Re-runs edit this comment so the latest verdict, findings, and automation markers stay together instead of adding duplicate bot comments.
  • A fresh review can be triggered by eligible @clawsweeper re-review comments, exact-item GitHub events, scheduled/background review runs, or manual workflow dispatch.
  • PR/issue authors and users with repository write access can comment @clawsweeper re-review or @clawsweeper re-run on an open PR or issue to request a fresh review only.
  • Maintainers can also comment @clawsweeper review to request a fresh review only.
  • Fresh-review commands do not start repair, autofix, rebase, CI repair, or automerge.
  • Maintainer-only repair and merge flows require explicit commands such as @clawsweeper autofix, @clawsweeper automerge, @clawsweeper fix ci, or @clawsweeper address review.
  • Maintainers can comment @clawsweeper explain to ask for more context, or @clawsweeper stop to stop active automation.
Review history (2 earlier review cycles)
  • reviewed 2026-06-29T07:46:34.341Z sha 66ae676 :: needs real behavior proof before merge. :: [P1] Remove the duplicate boundary-path export
  • reviewed 2026-07-06T06:53:24.363Z sha 483fc33 :: needs real behavior proof before merge. :: [P1] Remove the duplicate boundary-path export

@clawsweeper clawsweeper Bot added rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. P2 Normal backlog priority with limited blast radius. merge-risk: 🚨 security-boundary 🚨 May affect sandboxing, authorization, credentials, or sensitive data. labels May 22, 2026
@clawsweeper

clawsweeper Bot commented May 22, 2026

Copy link
Copy Markdown
Contributor

ClawSweeper PR egg

🎁 Pass real behavior proof to wake the egg and unlock a hatchable treat.

Where did the egg go?
  • The egg game starts only after the PR passes the real-behavior proof check.
  • Before that, no creature or rarity is rolled. The treat waits for real proof.
  • This is still just collectible flavor: proof affects review readiness, not creature quality.

@211-lee
211-lee force-pushed the fix/windows-lstat-global-cache branch from a8f8cd9 to dd1631b Compare May 22, 2026 08:19
@openclaw-barnacle openclaw-barnacle Bot added size: L proof: supplied External PR includes structured after-fix real behavior proof. size: M and removed size: M triage: needs-real-behavior-proof Candidate: external PR needs after-fix proof from a real setup. size: L labels May 22, 2026
@RomneyDa

Copy link
Copy Markdown
Member

Heads up: this PR needs to be updated against current main before the new required Dependency Guard check can pass.

@211-lee
211-lee force-pushed the fix/windows-lstat-global-cache branch 2 times, most recently from 0517140 to 807dd1c Compare May 30, 2026 06:07
@vincentkoc vincentkoc self-assigned this May 30, 2026
@vincentkoc
vincentkoc force-pushed the fix/windows-lstat-global-cache branch from 807dd1c to e6a2e83 Compare May 30, 2026 18:21
@vincentkoc
vincentkoc requested a review from a team as a code owner May 30, 2026 18:21
@openclaw-barnacle openclaw-barnacle Bot added the agents Agent runtime and tooling label May 30, 2026
@vincentkoc vincentkoc changed the title fix(infra): add global realpath cache to eliminate redundant lstat on Windows fix(infra): scope Windows path realpath caches May 30, 2026
@clawsweeper clawsweeper Bot added rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. and removed rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. labels May 30, 2026
@211-lee

211-lee commented May 30, 2026

Copy link
Copy Markdown
Author

@vincentkoc Hi! The latest force-push introduced 9 CI failures (check-prod-types, check-lint, check-test-types, check-guards, etc.). It looks like the re-export change in path-guards.ts (from @openclaw/fs-safe/path to ./path-safety.js) is causing cascading type errors. Could you take a look? Thanks!

@openclaw-barnacle openclaw-barnacle Bot removed the triage: needs-real-behavior-proof Candidate: external PR needs after-fix proof from a real setup. label Jun 4, 2026
@clawsweeper clawsweeper Bot added status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action. and removed status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. labels Jun 4, 2026
@211-lee

211-lee commented Jun 4, 2026

Copy link
Copy Markdown
Author

@clawsweeper re-review

@clawsweeper

clawsweeper Bot commented Jun 4, 2026

Copy link
Copy Markdown
Contributor

🦞🧹
ClawSweeper re-review requested.

I asked ClawSweeper to review this item again.
Action: item re-review queued (workflow sweep.yml, event repository_dispatch).
Result: the existing ClawSweeper review comment will be edited in place when the review finishes.

Re-review progress:

@openclaw-barnacle openclaw-barnacle Bot added triage: needs-real-behavior-proof Candidate: external PR needs after-fix proof from a real setup. and removed proof: sufficient ClawSweeper judged the real behavior proof convincing. labels Jun 4, 2026
@clawsweeper clawsweeper Bot added the proof: sufficient ClawSweeper judged the real behavior proof convincing. label Jun 4, 2026
@openclaw-barnacle openclaw-barnacle Bot added proof: supplied External PR includes structured after-fix real behavior proof. and removed triage: needs-real-behavior-proof Candidate: external PR needs after-fix proof from a real setup. proof: sufficient ClawSweeper judged the real behavior proof convincing. labels Jun 5, 2026
@clawsweeper clawsweeper Bot added proof: sufficient ClawSweeper judged the real behavior proof convincing. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. and removed status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action. labels Jun 5, 2026
@211-lee
211-lee force-pushed the fix/windows-lstat-global-cache branch from 51d9c02 to 2c3031b Compare June 9, 2026 02:59
@openclaw-barnacle openclaw-barnacle Bot removed the proof: sufficient ClawSweeper judged the real behavior proof convincing. label Jun 9, 2026
@clawsweeper clawsweeper Bot added the proof: sufficient ClawSweeper judged the real behavior proof convincing. label Jun 9, 2026
@211-lee

211-lee commented Jun 9, 2026

Copy link
Copy Markdown
Author

@steipete Hi Peter! I noticed you recently merged #86517 which caches plugin package realpaths in manifest-registry-installed.ts — that's exactly the hotspot we identified in our performance profiling (the ~179 calls to buildInstalledManifestRegistryIndexKey).

Our PR here takes a complementary approach: scoping realpath/existing-ancestor caches per-operation in the plugin hook/skill resolution and sandbox host-path validation paths. Since you're familiar with this area and the security-boundary tradeoffs, would you be able to take a look when you have a moment?

CI is all green now (131 checks passing), and ClawSweeper rates it 🐚 platinum hermit with 🦞 diamond lobster proof. The main blocker is explicit maintainer/security acceptance for the operation-scoped cache lifetime.

Thanks!

@openclaw-barnacle

Copy link
Copy Markdown

This assigned pull request has been automatically marked as stale after being open for 27 days.
Please add updates or it will be closed.

@211-lee

211-lee commented Jun 22, 2026

Copy link
Copy Markdown
Author

Still relevant — this fix is a prerequisite for #90362. Keeping open while review is in progress.

@openclaw-barnacle

Copy link
Copy Markdown

This assigned pull request has been automatically marked as stale after being open for 27 days.
Please add updates or it will be closed.

1 similar comment
@openclaw-barnacle

Copy link
Copy Markdown

This assigned pull request has been automatically marked as stale after being open for 27 days.
Please add updates or it will be closed.

Move realpath cache boundary from process-wide to caller-owned scopes to
prevent stale symlink/ancestor answers in security-sensitive containment
checks while maintaining performance.

Changes:
- Add hostPathCache to fs-paths.ts mount resolution
- Accept cache parameter in resolvePathViaExistingAncestorSync
- Create per-operation caches in plugin hooks and skills resolution
- Use scoped caches in sandbox host-path validation
- Fix boundary-path.ts export conflict (remove duplicate export)
- Add regression tests for stale symlink/junction detection

Performance: 55% reduction in lstat time on Windows (21,376ms vs 47,834ms baseline)

Fixes openclaw#85262
@openclaw-barnacle

Copy link
Copy Markdown

This assigned pull request has been automatically marked as stale after being open for 27 days.
Please add updates or it will be closed.

@openclaw-barnacle

Copy link
Copy Markdown

Closing due to inactivity.
If you believe this PR should be revived, post in #clawtributors on Discord to talk to a maintainer.
That channel is the escape hatch for high-quality PRs that get auto-closed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agents Agent runtime and tooling merge-risk: 🚨 security-boundary 🚨 May affect sandboxing, authorization, credentials, or sensitive data. P2 Normal backlog priority with limited blast radius. proof: sufficient ClawSweeper judged the real behavior proof convincing. proof: supplied External PR includes structured after-fix real behavior proof. rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. size: M stale Marked as stale due to inactivity status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Windows: lstat bottleneck causes 2-3x slower performance vs Mac (59% of CPU time)

3 participants