Resolves#47894
- [X] Changes file added for user-visible changes in `changes/`,
`orbit/changes/` or `ee/fleetd-chrome/changes`.
## Testing
- [X] QA'd all new/changed functionality manually
---
Performance results on my macOS host (between the old an new query):
Clean, dramatic result. Subtracting the ~0.23 s / ~27.5 MB osqueryd
startup baseline to isolate the query cost:
```
┌─────────────────────┬───────────┬──────────┬──────────────────────────┐
│ │ Wall time │ Peak RSS │ Query-attributable work¹ │
├─────────────────────┼───────────┼──────────┼──────────────────────────┤
│ Baseline (SELECT 1) │ 0.23 s │ 27.5 MB │ — │
├─────────────────────┼───────────┼──────────┼──────────────────────────┤
│ OLD (recursive %%) │ ~1.46 s │ 128 MB │ +1.23 s, +100 MB │
├─────────────────────┼───────────┼──────────┼──────────────────────────┤
│ NEW (bounded 2+3) │ 0.24 s │ 27.8 MB │ +0.01 s, +0.3 MB │
└─────────────────────┴───────────┴──────────┴──────────────────────────┘
¹ over baseline
```
Takeaways:
- Memory: ~128 MB → ~28 MB peak (–100 MB). The recursive walk alone
added ~100 MB; the bounded version adds essentially nothing.
- Time: ~1.46 s → ~0.24 s (~6× faster wall clock; the query-attributable
work dropped ~1.23 s → ~0.01 s, effectively free).
- System time tells the story: OLD spends 0.88–0.97 s in sys (the
readdir/stat syscalls from walking the tree); NEW spends ~0.00 s.
And this is with only 6 casks, dominated by gcloud-cli's ~98k-entry SDK
tree (walked twice via the latest → version symlink, plus following the
app back-symlinks into /Applications bundles). The recursive query hit
128 MB peak from a single well-stocked host — already within striking
distance of osquery's 200 MB watchdog limit. On hosts with more or
larger casks (or the /Library//Applications patterns from the issue),
that's exactly what tips it over and kills the worker. The bounded
version is flat regardless.