`String.prototype.slice` on a long string yields a V8 SlicedString that keeps
a pointer to its parent. Extraction boundaries that park a short result in
long-lived state — an OSC title in pane/tab state, a scan tail in a per-PTY
map, a carry in a per-pane scanner closure — therefore pinned the entire
source PTY chunk for as long as that short string stayed reachable.
Add `detachString` (src/shared/detached-string.ts), which forces V8 to flatten
via `` ` ${value}`.slice(1) ``, and apply it at 22 extraction boundaries across
shared, main, and renderer.
This is memory hygiene, not a crash fix. Production splits renderer-bound PTY
writes at PTY_BATCH_FLUSH_CHUNK_CHARS (16 KiB) and `setRuntimePaneTitle` writes
`[paneId]: title`, an overwrite that releases the previous parent, so live
retention is O(panes) and measures ~0.01 MiB today. It is bounded by that
overwrite, unbounded in principle, and cheap to make robust.
Retention guards resolve a real `gc` binding via `v8.setFlagsFromString`
instead of requiring `--expose-gc`, so they actually run under the plain
`vitest run` CI uses rather than silently skipping. Neutering `detachString`
to `return value` fails all 23 guards.
* fix(agent-status): track Codex rollout subagents
* fix(agent-status): resolve cross-day Codex child rollouts and unblock CI gate
Codex files each rollout under its own local start date, so a session that
runs past midnight spawns children into a sibling day directory. Scanning
only the parent's directory left 13% of real subagent spawns (48/371 across
local rollouts) permanently unresolved, which pinned a phantom "working" row
and re-ran readdirSync every poll tick forever. Resolve the child's own day
directory from occurred_at_ms, and time-box a child whose rollout stays
unreadable so a deleted or never-written file can't leak a working row.
Also make the hook HTTP handler return void: the changed-code quality gate
keys findings by span overlap, so this PR's added line inside the pre-existing
async createServer callback resurfaced no-misused-promises as a new finding.
Tests cover cross-day resolution, grace-period retirement, and that the poll
re-arms across successive roster changes (the prior tests passed even when
the poll died after its first change).
* fix(agent-status): keep the Codex subagent poll alive across nested hooks
A nested non-codex CLI inherits its parent's ORCA_PANE_KEY, so its hook
POST reached scheduleCodexSubagentPoll and tore the timer down before the
source guard, silently ending polling while a rollout child was still live.