d99eed7d83
The referenced-script walk in cron/lifecycle_guard.py capped each file (1 MiB) and the recursion depth (8) but not the walk: a command referencing hundreds of scripts, or one enormous shlex token, held the GIL for minutes on every gateway terminal call (#78398). Add a per-walk _LifecycleScanBudget (bytes, lines, longest line, unique paths, remote reads) charged BEFORE any text reaches shlex, and cap each referenced read at the remaining byte budget so an oversized file is never read whole. Exhaustion fails closed (the existing contract for one oversized file) and is logged at WARNING so operators can tell it from a genuine lifecycle block. Limits are sized so real wrapper graphs never hit them: a 200-script benign graph is allowed and a restart hidden behind it is still caught. tools/terminal_tool.py gates its optional launchctl pre-scan (which also tokenizes) on the same budget; the full guard still runs afterwards. Redesigned from #83821 by @Riccardo-Vecchi, which introduced the budget idea but blocked benign wide graphs (64-path cap) and bundled a suffix classification change that is left out here. Refs #78398