Repository navigation
Sync 259 upstream commits to 71beca947 (includes #34) - #35
Merged
Merged
Conversation
* never set git identity - the ambient auth owns the attribution * extend the identity rule: no co-authored-by trailers ever * scope the identity rule to commits that land in this repo * AGENTS.md: the identity comes from the ambient git config, not auth --------- Co-authored-by: Sebastian <sebastian@primeintellect.ai> Co-authored-by: Seth Karten <32787133+sethkarten@users.noreply.github.com>
…-ai#3156) * pa-daemon: supervisor_roster.rs split - under 1,000 lines The 1,799-row roster-serving module becomes its 30-row facade plus two test-family children at the same tree position (supervisor_roster::{passivation,delta_push}): - The facade keeps the product whole (the zero-move cut): the `WorkerRosterDelta` record, the entire `impl Supervisor` (the subscribe handling, the delta merge, the stop-path passivation, the roster pushes, the `write_roster_summary` arms), and the free fns (`passivated_summary`, `normalize_model_to_durable_pair`). - passivation.rs (650): the passivation + snapshot family - the stop-path passivation (the anchored-child preservation, the live-field stripping, the family pruning), the rewrite/diff-baseline snapshots, the registration-mark + re-registration rules, with the seed-tests fixtures the family drives; the shared drain fixture resolves through the facade. - delta_push.rs (514): the roster-delta push family - the supervisor fixture, the sequence-drop, the flip/push batching, and the push benchmark. - The shared `drain_roster_pushes` fixture (both families drive it, 23 passivation call sites) rides in the facade under `#[cfg(test)]` per the agents_view shared-fixture precedent; the children reach it through `use super::*`. ZERO product moves: the facade's crate::supervisor_roster::X paths (WorkerRosterDelta and every impl member) resolve unchanged; the test families reach the product through `use super::*` with the supervisor_roster_seed::tests fixture block riding in the passivation child (its sole consumer). Byte-proof: each family child is byte-identical to the tip block modulo the enumerated headers, the uniform dedent, one fmt-canonical signature wrap, and the seed use block (verify_supervisor_roster.py); the facade is the tip minus the test mass plus the two cfg(test) decls; the tip blob reassembles ZERO-DELTA. External-path audit: the only external reference (supervisor/clients.rs's crate::supervisor_roster::WorkerRosterDelta) resolves unchanged. * ci: the empty-commit retrigger (the shard 4/8 tui_dispatches_slash_commands_menu_and_suggestions red is the adjudicated view-render/data-arrival ordering flake, red-slashmenu-tui-dispatch-parallel-flake-20260930-1 - solo x3 GREEN at the exact head cf8f86f plus the pristine-tip control x2 GREEN in the lane sandbox; this diff is the pa-daemon supervisor_roster pure-structure split, zero pa-cli/tui surface; the rerun-failed route is banned by the fleet retrigger policy) * pa-daemon: drop the split-narration doc leftovers --------- Co-authored-by: Sebastian <sebastian@primeintellect.ai> Co-authored-by: Seth Karten <32787133+sethkarten@users.noreply.github.com>
…ync (write_file_atomic gains the per-call-site sync option) (PrimeIntellect-ai#3283) * perf(pa-daemon): the supervisor-config persist drops the TS-absent fsync (L1 prebuild) write_file_atomic made TS writeFileAtomicSync's per-call-site OPT-IN fsync unconditional at every call site. The supervisor-config persist is the only pre-bind durable write on the daemon boot path (Supervisor::new, before bind_transport) and its TS counterpart (persistSupervisorConfig, daemon-supervisor.ts) passes no fsync option: the unsynced rename is the TS daemon's own posture for this write. One trapped fresh+sync_all+rename fsync is the ~39-40ms class the daemon-init bind-span decompose measures on the warm-create path. Scope: TempSync enum (the per-site posture, the worker journal's Finalize-enum shape) with the synced default preserved for every other caller (worker descriptors, identity-pending, update_prepare); only persist_supervisor_config moves to write_file_atomic_unsynced. The boot error contract is unchanged (a failed write still fails the boot; only the sync is dropped). The persisted config has no in-tree readers (load_supervisor_config has zero callers) - a write-only parity mirror. Tests: the unsynced arm replaces an existing destination with temp cleanup, and persist_supervisor_config round-trips through load_supervisor_config (parseability through the unsynced write). * test(pa-daemon): the config round-trip compares fields, not the non-PartialEq struct The prebuild test used assert_eq! on PersistedSupervisorConfig, which derives no PartialEq - a test-compile E0369 under clippy --all-targets. Compare the three fields instead (same oracle: the unsynced persist stays parseable and the loaded record belongs to its socket). * style(pa-daemon): rustfmt shape for the round-trip test's field tuple cargo fmt --all --check wants the 3-tuple broken across lines (it exceeds the width on one line).
* make release-prepare use the pinned toolchain and drop the ignored toolchain inputs - release-prepare.yml: swap dtolnay/rust-toolchain to the 1.98.1 action pin (same fix as PrimeIntellect-ai#3233); the old pin ignored the toolchain input and installed 1.95.0. - ci.yml: delete the ignored toolchain inputs (the action SHA selects 1.98.1). - ci.yml: fix the shared cache comment; the shards' dev-dependencies differ, so the first leg to save defines the entry and other legs get a partial hit. * drop the ignored toolchain input in the windows triage workflow * retrigger ci * retrigger ci
…llect-ai#3293) * let the down arrow always reach the menus under the prompt * keep the escape test off the tray and wait on what the tray tests check
…ai#3289) * select the top search hit when the agents view query changes Typing a query kept the previous row selected by identity, or clamped its index onto the last hit when that row was filtered out, so the best match sat above the cursor. Every query edit now selects the first row (the top-ranked hit); clearing the query returns to the session selected before the search, or the top if it is gone. A move while searching keeps the user's pick through the clear. * select the topmost row on every agents view query change Drop the pre-search restore: the clear is a query change like any other and selects the top row too. * Revert "select the topmost row on every agents view query change" This reverts commit b530f41.
…TS fsyncs neither install-id site) (PrimeIntellect-ai#3295)
…ect-ai#3281) The e2e socket helpers poll the daemon socket with a 100 ms read timeout in a loop, clearing the line buffer at the top of every iteration. BufRead::read_line keeps the bytes that arrived before the timeout fires and returns Err, so the next iteration discarded the first half of the line and parsed only the tail: parse response line: Error("expected value", line: 1, column: 1) A long line straddling the timeout, like a chunked attach snapshot, then failed the suite: attach::chunked_snapshot_attach_streams_begin_chunk_end flaked three times in CI (PR PrimeIntellect-ai#3258 run 36817673817, PR PrimeIntellect-ai#3249 run 36898991027, and once more on PrimeIntellect-ai#3258). Clear the buffer only after a complete line was consumed, so partial bytes survive the timeout; the deadline is unchanged. The pa-cli e2e helpers use the same loop and get the same fix: continue_guard_e2e.rs re-created the buffer inside the loop, so the buffer moves out of the loop instead.
…lect-ai#3245) * ci(test): run the idle passivation e2e and the release-dir kernel suites The merged bootstrap step readies the product's kernel venv, but the idle passivation e2e still self-skipped: its private PA_TEST_KERNEL_PYTHON lookup had no HOME fallback and CI set nothing. It now uses the crate's standard PA_E2E_KERNEL_PYTHON-else-default-path lookup, so the venv the bootstrap builds reaches it (PA_TEST_KERNEL_PYTHON goes away). The kernel suites that read an installed release dir run too: pa-core's abort_kernel_cell and turn_boundary_kernel already honored PI_PACKAGE_DIR, and the pa-daemon abort_kernel/steer_boundary e2es and the agent-engine abort test now take the same branch. The shard step exports PI_PACKAGE_DIR at the checkout (the runtime dir the bootstrap itself resolves), and the Install uv step names its real consumer. * fix two racy e2e tests and drop the release-dir gates Both tests failed on this branch and on other branches that never set PI_PACKAGE_DIR; the races are in the tests: - read_goldens threw away events that arrive before the prompt reply. The turn can finish first, so its turn_end was lost and the test waited out its 15s deadline. It now keeps those events, like lifecycle.rs does. - worker_fd_count_stable_across_prompts counted the worker's fds at the moment the prompt returned, while the turn's short-lived roster-push sockets were still open. Each sample now waits for the count to drop back to the baseline plus slack; a leaked fd never closes, so a leak still fails. wait_until's panic now prints the deadline and points at the caller. The five live-kernel suites (pa-daemon abort_kernel_e2e, steer_boundary_batch_e2e and the lib abort test; pa-core abort_kernel_cell and turn_boundary_kernel) do not need a release dir: a debug build finds the checkout's runtime and skills on its own. They now run whenever the kernel venv exists. * ci: stop setting PI_PACKAGE_DIR for the test step The live-kernel suites no longer read a release dir, so the job-wide variable has no reader that needs it.
…meIntellect-ai#3282) The pa-daemon e2e helpers poll the daemon socket with a short read timeout in a retry loop and either clear the line buffer at the top of every iteration or re-create it inside the loop. BufRead::read_line keeps the bytes that arrived before the timeout fires and returns Err, so the next iteration discarded the first half of the line and parsed only the tail. Same fix as PrimeIntellect-ai#3281, swept over the remaining helpers: clear the buffer only after a complete line was consumed, so the fresh-per-iteration buffer in the drain loops moves out of the loop instead. Deadlines and messages are unchanged.
… of panicking (PrimeIntellect-ai#3252) decode_csi_with_modifier split `last` with split_at at a char count, which split_at reads as a byte offset: when a multi-byte character sits before the last char (the Kani counterexample ESC [ ; я ; - Option presses interleaved with Cyrillic or accented text), the split panicked with "byte index 1 is not a char boundary" and took down the TUI. Split at the byte index of the last char instead, which also makes the separate empty-tail check redundant (the ? on next_back returns None for an empty last). Fixes PrimeIntellect-ai#3175
…rimeIntellect-ai#3284) read_line polled the daemon socket with a 50ms read timeout and started a fresh buffer on every poll iteration. BufRead::read_line keeps the bytes that arrived before a poll times out and returns WouldBlock, so the next iteration dropped the start of a slow line and the client parsed only its tail. A truncated tail is unparseable JSON that callers skip, so the command hung until its 30s timeout (15s for the handshake) instead of showing a result, e.g. `list` against a busy daemon sending a large response slowly. Keep the partial bytes in a byte buffer on the client across polls and across reads (probe_daemon keeps using a client after a swallowed hello timeout), fill it with read_until, and decode the line as UTF-8 only when it is complete: decoding per poll drops the bytes again when a timeout lands inside a multi-byte character. Deadlines and error messages are unchanged. Regression test: read_line_keeps_bytes_across_poll_timeouts replays a line split by poll timeouts, one inside a multi-byte character, with no sleeps and no production test hooks.
…Intellect-ai#3217) * beta channel promotes without the release-environment approval - the rolling beta stays automatic, the stable cut keeps the reviewer gate * update the release security notes for the automatic beta publish The R2 secrets are repo-level, so the environment was never a credential boundary. Stable keeps the release environment's reviewer approval as a process gate; beta tags publish automatically from release-beta. The release.yml security block and the two nightly.yml notes said every s3 cp waits for the approval, which is no longer true for beta. * retrigger ci --------- Co-authored-by: Seth Karten <32787133+sethkarten@users.noreply.github.com>
* add the herdr connector - pa-types: the HERDR_* client-env allowlist contract (TS DAEMON_CLIENT_ENV_KEYS), collect on the client, re-filter on the daemon (the socket peer is untrusted) - pa-tui: the create/attach sites carry the allowlisted pane identity (create only; attach adopts-if-absent) - pa-daemon: the supervisor re-filters and rides the env on the durable create; the worker binds the HerdrReporter per session from the create payload (never the boot env - the TS boot-context bug class), maps the turn lifecycle to working/idle/blocked with the retry grace and the idle debounce, releases on quit/kill as the last write, rebinds on replacement, adopts on attach, and skips RLM subagents - tests: the reporter machine + wire unit battery (11), the allowlist battery (3), and the supervisor e2e against a hostile boot pane proving payload-pane-only reporting across the lifecycle plus env-less silence and attach adoption (2) * fix the herdr connector's bot findings - the session replacement resets the predecessor's failure state (a successor starts clean, never the old block/error) and the abort/failed settles always settle the pane (the suppressed-run class could strand it working forever; Done(Err) without agent_end now blocks with the error) - the reporter task is generation-gated: a replaced reporter's queued or racing boundary events are dropped at process time, so only the current reporter writes; concurrent attaches cannot install two reporters (one-lock check-and-install) - every send phase is time-bounded (connect/write/first-byte) so a wedged peer can never stall the reporter or delay the release past its ack window - the idempotent re-create without a pane env keeps the installed reporter instead of silencing the session; the kill swaps the slot to the disabled no-op so a later attach can adopt the pane again - the first-seed seq race CAS-advances (no duplicate seqs under concurrency) and the tuning keys ride the client-env allowlist so HERDR_PI_* reach the reporter (with the trust-model doc note) * harden the herdr reporter against the round-2 bot findings - the tuning envs cap at the JS setTimeout bound (u64::MAX no longer panics the deadline arithmetic and kills the task) - a stale-generation reporter never releases the successor's pane from the post-send drain path, and a dropped release acks so the quit close does not stall on the timeout - the settle's pane fallback keys on the reporter's own run-end flag, so an agent_end the abort gate swallowed still settles the pane * fix the herdr lane's round-3 cursor findings - the pane run-end flag clears on an in-turn run start, so an abort that swallows a retry's agent_end still settles the pane (it stranded working after the first run's end set the flag) - the reporter's child skip keys on the create payload's rlmDepth (the TS sessionOptionsOverride spawn context), never the persisted file depth, so a resumed subagent file opened top-level reports for its own pane - the create-time rebind sits past the create's last fallible step, so a failed create never leaves the pane ghost-claimed * fence the herdr pane socket against redirected targets - the reporter connects only to a Unix socket the daemon's own effective uid owns (lstat, no symlink follow): a regular file, a symlink (even one pointing at a legitimate socket), or a foreign-owned socket never reports — the session stays unreported and the refusal logs once per process - the effective uid is derived std-only (the crate forbids unsafe): a file the process creates carries its effective uid - tests: the fence decision battery (own-uid socket accepted; a foreign owner, a regular file, and a symlink rejected; a missing target passes through), a reporter aimed at a non-socket target stays silent, and the e2e proves the normal same-uid socket keeps reporting * make the herdr uid probe fail closed - a probe that cannot create or read its file yields None and the fence rejects (no report) — never a fall-back to uid 0, which would have accepted a root-owned socket * harden the herdr reporter against the round-4 bot findings - a send that never leaves the process (herdr down) no longer marks the state published: the publish-dedup keys on the wire state, recorded only after a successful write, so the same state re-sends at the next boundary - the fence's lstat moves off the async runtime (spawn_blocking) under the same 500ms bound, so a pathological client-supplied path cannot stall the reporter - the non-socket-target test binds a LIVE listener and points the reporter at a symlink to it (the strongest impostor case), and the stale-reporter asserts no longer hold a mutex across their own failure-path relock * close the herdr fence's absent-target race and the hung-lstat leak - a missing pane target now refuses its send instead of passing through to the connect: no connect is ever attempted on a path the lstat did not validate, so the check-then-use window stays closed; the cheap NotFound re-checks on every send, so reporting still starts the moment herdr boots - the fence verdict is tri-state and checked at the task level: a lstat that hangs past the 500ms bound fails closed for the reporter's life instead of leaking a blocking-pool thread per retry (tokio cannot cancel it); the release write is gated by the same fence - a regression test drives a full turn with the socket down and proves the same states re-send after the socket appears (fails on the old queue-time published marking) * retrigger ci * polish the herdr round-5 test and the fence lint - the socket-comes-up regression test drops its fixed 150ms sleep: phase 2 ends in an error block (a state the clean down-turn can never deliver), and the assertion keys on the observed blocked frame and its re-sent working predecessor — timing-independent through the sequential reporter task, and still failing on the old queue-time published marking - the fence verdict's windows-only dead_code allow names its reason (only Accepted is constructed there; named pipes keep their connect-time ACL model)
* ship windows support: the msvc release target, the Windows installer pair, the channel row Closes the shipped-product gap: the port compiled + tested green on windows-latest, but no user could install it (CI-verified source support was not shipped-product support). - release.yml: build-windows (windows-2022, x86_64-pc-windows-msvc, the .exe livecheck; the pinned label mirrors build-gnu's reviewed-container posture), promote needs it, the channel emission gains the completeness gate (every known platform must carry a row: the platform list the installer reads matches the built set), and the R2 publish renders + serves install.ps1/install-beta.ps1 beside the sh pair. - assemble_artifacts.py / verify_release.py / package_release.py: the .exe arms (binary_name_for_target) and the win32-x64 platform alias. - install-rust.sh: the Windows uname rows (MINGW*/MSYS/CYGWIN -> msvc / win32-x64), the mkdir publication lock (MSYS ln -s deep-copies), the daemon stop before the publish (a Windows process holds its binary open), the TS-takeover no-op gates (TS never shipped on Windows), the .exe payload check, the Git Bash launcher + the .cmd twin, the cygpath prefix arm, the MSYS-form store guard. - install.ps1 (new): the PowerShell-native route (irm | iex; PS 5.1-safe, env-knob only) with the same channel contract, checksum verification, tar.exe extraction, the mkdir lock, the one-generation rollback, and the launcher pair; both routes publish one interoperable layout. - pa-core update: target_for gains the windows pair (prime-agent update --check on Windows), the refusal names the five-target matrix; the funnel resolves Git Bash via the platform module on Windows (never bare PATH) and probes the .cmd launcher. - Three banked windows compile reds fixed (the PrimeIntellect-ai#3004 shapes, never landed on main): the kitty probe's unix-only call + imports (pa-tui), the unix-only PrepareState/ClientRouting imports (pa-daemon), the unix-gated test-only probe imports (pa-core venv). - Pins: installer_platform_map.rs (new - the uname map through the script's own case text), the 5-target promote gates + the build-windows structural contract (release_workflow.rs), the missing-row refusal + the five-platform chain (release_channel_manifest.rs), the packaged layout's Windows arms (packaged_layout_e2e.rs); the windows-runtime triage battery gains the install e2e (both routes against the real win32-x64 artifact over a local channel); Makefile gains windows-msvc-cross (cargo xwin check); README carries the Windows install forms. TS parity context: the TS product shipped no Windows form at all (releasePlatforms darwin/linux; the installer refuses other OSes; the PowerShell-installer attempt PrimeIntellect-ai#2403 was closed unmerged), so the port owns the Windows decisions; the TS reference decides the idiomatic question - install.ps1 is the Windows-native route, the sh one-liner serves Git Bash. * fix the windows review wave (the bots' findings) Cursor Bugbot (4) + Macroscope (12) on the pushed head - all real, all fixed append-only: - release.yml: the build-windows rust-cache pin was 39 chars (a dropped character from the 40-char pin every other job uses; the action ref could not resolve). - install.ps1: create the prefix instead of requiring it (a fresh Windows profile has no $HOME\.local; the one-liner died on first run); the WOW64 shape (32-bit PowerShell on x64 reports PROCESSOR_ARCHITECTURE=x86 - check PROCESSOR_ARCHITEW6432 first); the pinned-version path skips the channel manifest (a historical pin must install from its own versioned prefix - the naming contract + SHA256SUMS, install-rust.sh parity) and the unpinned path retries the pointer/manifest pair once (the publish's consistency window); the rollback sweep checks the ownership marker before deleting; a failed publish restores the previous payload before the lock releases; the launcher pair gains the unowned-file preserve discipline (a launcher this installer did not write is never overwritten). - install-rust.sh + install.ps1: PRIME_AGENT_ALLOW_HTTP - the explicitly named escape hatch from the https rule (a local channel under the operator's control; the e2e + any local channel otherwise dies at the https check), loud warning when active. - install-rust.sh: the Windows child-root store guard resolves through physical_path too (a native python round-trip through C:\... spelling the MSYS-form comparison can never match - the guard was silently disarmed); the .cmd preserve slot rides the on_exit restore; a failed install that stopped the daemon names the recovery (the next invocation boots it from the restored payload). - pa-core update/installer: the funnel's Windows shell resolution is the kernel resolver's TRUSTED Git Bash roots (hardcoded install-dir literals, never PATH and never `where bash.exe` - the get_shell_config fallback would let a repo-controlled PATH place the interpreter that receives the inherited GITHUB_TOKEN). - test_windows_install.ps1: the e2e rides the allow-http knob for both routes. The PowerShell parse gates now run in the sandbox (pwsh 7.6.6 via the parser API - the $var: scoped-reference class was caught and fixed in both files). * fix the second review wave (the trusted stop, the launcher lifecycle) Macroscope + Cursor on the wave-fix head - 7 findings, all real, all fixed append-only: - THE TRUSTED STOP (both installers): the pre-publish daemon shutdown runs the previous payload's OWN binary - the marked share tree's prime-agent.exe - never the launcher at bin\prime-agent(.cmd). An unowned file at the launcher path is exactly the untrusted-execution shape (the ownership check had not run yet when the stop exec'd it), and the share tree's .prime-agent-install marker now gates the stop. - install.ps1: the lock comes BEFORE the stop (a failed lock claim must never have stopped a daemon - the stop-for-nothing downtime); the preserved-launcher slots ride a restore-on-failure catch (a failed launcher write never leaves the machine without its command); the installed: --version verify checks $LASTEXITCODE (a broken exe no longer reports as installed). - install-rust.sh: the .cmd twin's preserved slot is cleared once the fresh launcher is live (the EXIT trap would otherwise restore the old .cmd over the new one at exit - the success-path clobber). - pa-core update/installer: the no-Git-Bash refusal stops promising the settings shellPath (the funnel, like its unix side's hardcoded /bin/sh, resolves only the trusted roots; the promise would lie). The PowerShell parser gate (pwsh 7.6.6, the Language.Parser API) passes on both installer files. * fix the third review wave (the scratch sweep, the lock-scope stop) Round 3 on efe2d4d: three new real findings (the rest are stale replays of fixed Bugbot IDs, auto-marked "no longer relevant"): - install.ps1: the download scratch (the tarball + SHA256SUMS) rides every exit path now - the success sweep, the Fail sweep (the function cleans before exiting), and a script-scoped trap for terminating errors (accumulated release tarballs in the temp folder). - install.ps1: the daemon stop moves INSIDE the lock's try/finally (a terminating error in the stop no longer leaks the lock directory - the stale-lock manual recovery class). - install.ps1: the failed-launcher restore removes the destination's partial file before moving the preserved one back (Set-Content can create/truncate before throwing; the broken new file otherwise blocks the restore). * fix the fourth review wave (the lock, the launcher snapshots, the scoped sweep) Round 4 on 17505ea: four new real findings (the rest are stale replays of fixed Bugbot IDs): - install.ps1: the Fail/trap sweep deletes ONLY the scratch this script created (a created-flag guards it: under `irm | iex` the script scope is the caller's session, and an ambient `$download` variable must never be deleted). - install.ps1: a failed lock-PID write releases the freshly claimed lock (the leaked-lock manual recovery class). - install.ps1: `$rollback` is pre-initialized (a terminating error before its assignment no longer turns the finally's own Test-Path into the leaked-lock failure) and the finally's restore guards on it. - install.ps1: the INSTALLER-OWNED launchers get pre-write snapshots too (a Set-Content I/O failure can truncate a working launcher; the catch restores from the snapshot - the machine never loses its command on a failed launcher write). * fix the fifth review wave (the scripted stop, the failure notes, the sweeps) Round 5 on 0f140b0: four new real findings (the replay class re-anchors fixed Bugbot threads per head - those are resolved in place): - BOTH installers: the pre-publish stop is `shutdown --force` - the CLI's bare `shutdown` prompts for confirmation interactively and REFUSES a non-interactive terminal ("Shutdown requires confirmation in an interactive terminal. Use prime-agent shutdown --force"); the installer's context is the scripted one, so --force (the daemon's own forced shutdown, with its internal drain budgets) is the only correct form. - install.ps1: a failed install that stopped the daemon names the recovery (the next invocation boots it from the restored payload) and sweeps its stage tree (no accumulated prime-agent.stage-* directories). - install.ps1: the owned-launcher snapshots sweep on success (no .install-backup leftovers). * ci: retrigger (the rpc_fork prompt-admission flake on shard 8: solo x2 + the full-file green locally) * fix the sixth review wave (the preflight, the ambient-safe scratch, the restore) Round 6 on 9ba4277: five new real findings (the macro assistant re-checked the current revision - the replay class re-anchors resolved threads): - install.ps1: THE PREFLIGHT - every ownership refusal (the unmarked share, the unmarked rollback) runs BEFORE the daemon stop: a refused install never stops a daemon (the avoidable downtime class). - install.ps1: the installer's scratch bookkeeping is ambient-safe (unique script-scoped names, both initialized before any Fail can run: under `irm | iex` the script scope is the caller's session and an ambient $download/$downloadCreated pair must never be deleted as this installer's scratch). - install.ps1: the stage tree rides the Fail + trap paths (a failed extraction/validation leaves no prime-agent.stage-* behind). - install.ps1: a failed RESTORE reports the manual recovery instead of throwing (an error inside the finally would skip the lock release - the stale-lock class). - install.ps1: the channel pointer tolerates the `v`-prefixed historical form (TrimStart after the read; the manifest comparison + the release prefix + the artifact names carry no extra v). * hold the lock through the launcher transaction; the Fail sweep releases it The conductor's fold-in (the two unresolved threads on d5ddf27): - install.ps1: THE LAUNCHER TRANSACTION JOINS THE PUBLICATION LOCK - the lock is now held from the stop through the launcher writes (a second installer can no longer slip between this payload's publish and its launcher write; either installer's later restore would otherwise clobber the other's launcher - the cross-installer pairing race). - install.ps1: the publication lock rides the Fail sweep (the preflight's ownership refusals are Fail paths OUTSIDE the publish's try/finally - a refused install now releases the lock it claimed instead of leaking the stale-lock manual recovery). A launcher-write failure keeps the published payload (the new tree is valid; the restored launchers point at the new payload's exe and keep working) and restores the launchers; the finally releases the lock on every path. * bump the windows battery timeout to 240 minutes (the pa-cli e2e set outgrew the 120-minute cap measured on the first dispatch) * order the windows battery: the install e2e before the pa-cli marathon; the 480-minute budget (three dispatches measured the pa-cli e2e set past three hours) * install.ps1 repo default base follows install-rust.sh to the bucket root * print the windows path hint in the windows spelling; cap the windows battery at the six-hour hosted limit * join the windows no-git-bash message across its line break * run install.ps1 in a child scope and throw on refusal, so irm | iex leaves the caller's session as it was * reset the launcher recovery arrays in the scope the helpers append to * retrigger ci (wave_b10_catalog_slices_served_without_reforwarding flaked on shard 4; solo-green x3 at this head and at main) * exit 1 on any install.ps1 failure when run as a file; rethrow to the caller under irm | iex * retrigger ci (fd_lifecycle_e2e supervisor_restart_loop_leaves_no_orphan_workers: registered flaky) * record and probe the shared windows install lock by windows pid, so a live install.ps1 never reads as stale * read the windows lock pid as digits, wait out a claim in progress, quote the recovery paths * windows shutdown finds an idle daemon on the default pipe; install.ps1 sweeps on one failure path; packaging e2e resolves python discover_daemons now probes the fixed named pipe on Windows, so shutdown --force stops a daemon with no tracked workers (an absent pipe is not reported as an orphan file). install.ps1 drops its trap: the bottom catch sweeps the scratch, stage, and lock on every failure and clears the script-scope names. The packaging dry-run e2e runs python3 or python, whichever exists. * retrigger ci
…rimeIntellect-ai#3197) The provider (the internal glm-5.3 route, openai-completions) ends response streams mid-block without an error event - no stop signal (finish_reason), no [DONE] marker, no error frame - and the port swallowed it: end-of-stream-without-stop settled as a completed turn (partial or no content) with no error anywhere. That killed fleet lanes silently (~1-in-5 fresh spawns die at their first thinking block: the child session logs end mid-thinking with zero error rows - daemon, worker stderr, session file all silent) and is user-visible the same way (a turn can end mid-answer with no error shown). - The detection (pa-ai openai-completions stream): StreamingState tracks the two completion markers - a chunk's finish_reason and the SSE [DONE] terminal. The post-loop handling distinguishes COMPLETED (either marker arrived) from DROPPED (neither); a dropped body returns the new retryable stream_drop failure instead of settling as a completed message. Abort and error-frame checks keep precedence; the open block at drop time (thinking / text / tool-call / none) names the detail. - The disclosure (pa-ai stream-failure): the new StreamDrop kind (serialized stream_drop) + stream_drop_failure(); the failure row reads "Provider dropped the response stream (stream_drop): the stream ended inside a thinking block before the stop signal" - the class named in the message and in the provider_stream_failure diagnostic, so the retry arms re-issue the same request and the exhaustion surfaces through the existing failure-scoped disclosure (never a silent empty turn). - The metrics (pa-telemetry + the pa-core classifier): stream_drop joins ERROR_SUBTYPES/ERROR_CODES (ERROR_CLASSIFIER_REVISION bumps to 2); the classifier maps the drop messages to the stream_drop subtype (category network, retryable) with the fixed diagnostic riding and the raw text never uploading. - The pins: the dropped-mid-thinking SSE fixture classifies as the retryable stream_drop (mid-text and empty-body variants pin too); the full arc (the real provider + the real adapter + the retry driver) retries the drop and completes on the retry; the exhaustion surfaces the class in the failure row; the healthy stream is unchanged (stop signal + [DONE] completes, and either marker alone completes - gateway variance tolerated). - The auto_retry unit battery moves to the auto_retry/tests child (byte-exact, the established split pattern) so the file stays under the 1,000-line discipline.
…3251) * count agents as running while their subagents still work * publish the running-subagents flag atomically and wait on the real signal in its test * wait out a child's subagents before settling or collecting it --------- Co-authored-by: Seth Karten <32787133+sethkarten@users.noreply.github.com>
…3296) * keep the spinner's frame wake armed across paints so quiet turns animate * arm the spinner boundary before the select so handled input cannot park the loop * keep the spinner boundary arithmetic bounded on narrow targets * re-arm the spinner wake before the select and test that a quiet turn keeps animating * drop the test's cast so it needs no clippy allow
…llect-ai#3257) * fix(kernel): share in-flight startup across first touch and teardown * fix(kernel): close the panic wedge and the stop-gate gap in the shared startup Review follow-ups on PR PrimeIntellect-ai#3257 (both blockers independently verified by both adversarial reviewers at 21da7aa): - F1 panic wedge: a panic in run_startup or a progress listener skipped the memo clear and the done send, which closed the watch and wedged every later ensure() on the dead memo. The boot now runs on its own JoinHandle, so the publisher always clears the memo and sends the result, converts a panicked boot into a "kernel startup task failed" failure, and clears the listener state so the next ensure() boots fresh (self-heal; the memo re-arms on close). The watch now carries the startup result itself: joined callers keep the manager even when a concurrent stop takes the provisioner's live owner (TS managerPromise), and a dispose-raced boot rejects with the honest disposed-startup cause instead of handing callers a dead manager. - F2 stop-gate gap: stop_kernel took the manager and installed the pending_stop gate in two separate lock passes; a revival ensure in the gap captured the previous gate and could restore against a snapshot still being flushed. The gate is now installed in the same lock block that takes the manager. - F3 dispose fixture vacuity: the dispose leg pins the absolute interpreter count at dispose-return (exactly one spawn; the aborted retry never ran) in addition to the stasis assert. - Fixtures: a panicking progress handler must not poison the next boot (the re-arm regression leg), and a revival boot must wait for the in-flight stop's held host request before its first progress stage (exact ordering barrier, not flush timing). * only clear our own startup memo and chain concurrent stop gates A stale boot no longer clears a newer boot's startup memo after a defunct-manager replacement, and a stop's revival gate now also waits for the earlier stop's gate, so concurrent stops joining one boot cannot release a revival while the other stop is still flushing the snapshot. * retrigger ci * check the revival ordering without a timeout The stop-revive ordering test now drives the revival boot to its first await with yields on the single-threaded runtime and checks that its first progress stage came after the held host request was released, instead of passing on a 200ms timeout. * show a progress stage while a revival waits for the previous stop A revival that has to wait for the previous kernel's stop now reports it as a startup stage. The stop-revive ordering test waits for that stage instead of a fixed number of yields, then checks the boot only starts after the held host request is released.
…i#3291) * test(pa-daemon): the replaced-socket oracles for the exit cleanups (failing-first) The bind-choreography parity audit (D1) found the three exit cleanups - supervisor.rs run()'s tail, worker.rs exit_after_close, supervisor_lost.rs exit_orphaned - passing a cleanup-time socket_identity(path) read as their own expected guard: the guard compares a fresh read with itself, so it never discriminates, and any file REPLACED at the path after the bind is unlinked by the dying owner. TS captures the identity at LISTEN time (daemon-supervisor.ts:879, daemon-mode.ts:718) and compares THAT at exit, so a replaced file survives the old owner's exit. These oracles pin the replaced-file direction at each call site against the real binary (the survivor-wakes worker scenario, the routed-shutdown worker scenario, and the external-sweep supervisor scenario), each with a served-path precondition (the replacement is bound before the exit fires) and a rename-aside bind that keeps the original inode allocated, so the identities provably differ and the oracle can never pass vacuously on inode reuse. The still-ours direction stays pinned by the in-tree controls (worker_orphan_exit_e2e, supervisor_e2e::shutdown) plus the routed-shutdown control here. On this tree the oracles fail: the vacuous guard unlinks each replacement's live socket. The fix rides the next commit. * fix(pa-daemon): bind-time socket identity at the exit cleanups (TS D1 parity) The three exit cleanups - supervisor.rs run()'s tail, worker.rs exit_after_close, supervisor_lost.rs exit_orphaned - passed a cleanup-time socket_identity(path) read as their own expected guard: the guard compared a fresh read with itself, so it never discriminated, and any file REPLACED at the path after the bind was unlinked by the dying owner's exit. TS captures the identity at LISTEN time (daemon-supervisor.ts:879, daemon-mode.ts:718) and compares THAT at exit (daemon-mode.ts:1078-1080), so a replaced file survives the old owner. This carries the same bind-time capture to both rust bind sites - supervisor run() right after bind_transport and before restrict, the worker serve() in the same TS order - stores it on Supervisor and Worker, and passes the STORED value at all three call sites. The reachable failures this closes: a force-stopped worker that survives its stop verdict wakes after the supervisor relaunches its replacement on the same deterministic worker-socket path, and its late orphan/shutdown exit unlinks the replacement's live socket - every route to the replacement fails and the session bounces through the failure loop; on the supervisor side, an external sweep removes the socket file under a serving supervisor, a successor binds the path, and the original's graceful exit unlinks the successor's live socket - every new connect fails ENOENT while the socket looks alive. Daemon-internal ownership bookkeeping only: no wire, TUI, prompt, or behavior bytes change; the cleanup gate itself (cleanup_socket_path) is unchanged - it was already a faithful port of TS's cleanupDaemonSocketPath. The failing-first oracles for exactly this divergence ride the previous commit: they fail at the pre-fix tree (gate_1790878419_10591, the three replacements unlinked) and pass here.
…rimeIntellect-ai#3249) Co-authored-by: Kevin Thomas <kevin.jt2007@gmail.com>
* fix keys dying in the /settings menu search
TS SettingsList.handleInput's final arm hands every non-intercepted key
to the search Input, whose edit bindings (Backspace first) match on their
multi-character key ids. The port's single-character gate dropped every
one of them, so after garbage filtered the settings list to its no-match
row the query could never be corrected: Backspace typed nothing away and
Space had no row left to activate (the operator's 2026-10-02 report).
Forward the whole key id to the tab's SearchInput (the bare Space stays
intercepted above as the row activation, TS's sanitized input) and drive
the operator's exact sequence through a headless ladder plus unit guards.
* fix the search input dropping the typed space key id
TS `Input.handleInput`'s regular-character arm reads the RAW key data,
where the space byte is a plain printable that inserts. The port's
SearchInput receives TS's `space` key id instead, and its final
single-character gate dropped it ("space" is five characters), so every
picker that mounts this input — the model picker, the mcp/plugins view,
the onboarding provider picker, the auth panels — silently ignored typed
spaces where TS typed them into the filter. Decode the id through the
editor's printable decode (which maps `space` back) exactly like the
other text surfaces do; derive Clone so the composite surfaces can hold
the input. Red-first: `the_space_key_id_types_a_space`.
* fix the config selector filter dropping every multi-char edit key
TS `ConfigSelectorComponent.handleInput`'s final arm hands every
non-intercepted key to the search `Input`, whose edit bindings —
Backspace, Delete, ctrl+w, ctrl+u, undo — dispatch on their whole
multi-character key ids. The port kept a bare query string behind a
single-character gate with a hard-coded backspace arm, so ctrl+w, ctrl+u,
undo, and the cursor motions never reached the filter (the PrimeIntellect-ai#3309 key
class, this surface's shape), and a rebound deleteCharBackward kept the
freed key dead. Mount the SearchInput as the sub-input — the same
right-layer fix the settings menu took — keeping the intercepted
bindings (up/down/page/cancel/clear/space-toggle) above the forward; the
paste loop rides the input's own paste instead of replaying characters
as fresh key ids. Red-first: `word_and_line_edits_reach_the_filter`,
`cursor_and_undo_bindings_reach_the_filter`,
`a_remapped_backspace_binding_edits_the_filter`, with the operator's
no-match recovery kept as the guard.
* fix the tree selector inputs dropping every multi-char edit key
TS `LabelInput.handleInput` hands every key but confirm/cancel to the
`Input`, and the custom-prompt flow's `ExtensionEditorComponent` hands
everything but cancel to the full editor — their edit bindings dispatch
on whole multi-character key ids. The port's two single-line inputs
gated typing through a printable()-style single-character decode with a
backspace arm, so ctrl+w, ctrl+u, undo, and typed spaces never reached
the drafts (the PrimeIntellect-ai#3309 class), and a mistyped label or summarization
prompt could only be corrected one Backspace at a time. Mount the
SearchInput as each mode's sub-input and forward the non-intercepted
keys; the label editor prefills the current label with the caret at its
end, keeping the pre-fix backspace-deletes-the-tail behavior.
Red-first: `label_input_edits_through_the_full_key_grammar`,
`custom_prompt_edits_through_the_full_key_grammar`.
* fix the tree search appending named key ids as query text
TS's tree search reads the RAW key data in its final arm: the space byte
is a plain printable that joins the query, and every special key arrives
as an escape sequence — a control character — and drops. The port
receives parsed ids, and its hand-rolled gate (no control chars, no
plus) let the bare multi-character ids join the query as their own
names: the `space` key typed the literal "space", `delete`/`home`/`end`
and the f-keys typed theirs, so a query that filtered the tree to
nothing polluted itself further on every correction attempt. Gate the
append on the editor's printable decode — the same mapping the other
text surfaces use — so a space types a space and named ids join nothing.
Red-first: `named_key_ids_never_join_the_search_query`,
`the_space_key_id_types_a_space`, plus the headless ladder
`the_tree_search_types_spaces_and_stays_correctable` driving the
operator's sequence through the real interactive stack.
* fix the agents-view search dropping the editor word-delete key
TS's agents-view search editor is the full editor, whose
deleteWordBackward (ctrl+w / alt+backspace) deletes the trailing word.
The port's search field decodes only single printable characters —
backspace and ctrl+u have their own arms — so the multi-character
word-delete id dropped (the PrimeIntellect-ai#3309 class) and a multi-word query could
only be corrected one Backspace at a time. Give the query the editor's
word-delete arm: delete the trailing word plus the whitespace before
it, mirroring the editor's caret-at-end semantics (this view's query is
append-only), with the same no-op re-arm guard the backspace arm
carries. Red-first: `ctrl_w_deletes_the_query_s_trailing_word`.
* fix the agents-view word-delete taking whole dotted words
Macroscope thread (data_input.rs): with a query like error.rs, ctrl+w removed the entire query instead of the trailing word run rs — truncate_trailing_word scanned whitespace-only, while TS Editor.deleteWordBackwards (and the search input's own delete_word_backward, whose move_word_backward walk classifies the run by the last grapheme: a punctuation run or a word run) keeps error. Extract that walk as search_input::word_walk_start (the search input's move_word_backward now calls it) and let the agents-view delete use it, so the binding is consistent everywhere: error.rs loses rs and keeps error. Red-first: ctrl_w_loses_only_the_trailing_word_run_in_a_dotted_query.
* fix the pasted search filter storing control bytes
Macroscope thread (config_selector.rs): the bracketed-paste path stored raw control bytes in the query, so an embedded ESC/OSC sequence would be re-emitted to the terminal on the next render of the field. The old char-by-char paste path dropped them (its is_control gate) and the editor's handle_paste filters them, but SearchInput::paste stripped only CR/LF and expanded tabs. Filter the control bytes in SearchInput::paste — the component every surface pastes a filter through (config selector, model picker, onboarding) — matching the editor's paste rule. Red-first: paste_rejects_control_bytes.
* fix a control-only paste adding an empty undo step
Review follow-up: the control-byte filter ran after the undo push, so a paste that filtered to nothing pushed a snapshot of the unchanged state and the next undo was a no-op instead of undoing the typing. The editor's handle_paste checks the filtered payload before its snapshot — mirror that order: normalize, filter, return on the empty payload, then reset the action, push the undo step, insert. Red-first: a_control_only_paste_leaves_the_undo_stack_alone.
* fix the tree label/custom prompt caret not rendering
* fold the settings search e2e into the settings harness, drop the tree e2e
* trim fix-history comments
* trim the remaining fix-history test comments
* unify the settings re-filter on the config selector rule
The settings search re-ran its filter after every forwarded key, so a caret-only key (ctrl+left in the query) reset the selection to the top row, while the config selector re-filters only on a value change. Use the config rule in both pickers: the filter re-runs when the query changed, a caret move keeps the selection.
* route the bracketed paste into the settings and tree inputs
A paste while the settings menu or the tree selector owned the frame landed in the hidden prompt composer. Route it like their key dispatch: the settings search takes it with TS space sanitize, the tree label and custom-prompt inputs take it, the tree search appends its printable text, and the summarize list consumes it.
* guard the settings paste against the submenu and the empty menu
Macroscope follow-ups on the new paste path: it edited the hidden parent search while a submenu owned the frame, and panicked on the tab-less empty-menu state (active_mut with no tabs). The submenu takes the paste first like its key dispatch, and the empty menu ignores it like the navigation keys.
* route the paste through every frame-owning overlay
Review follow-up: the paste routing covered the tree and settings surfaces but still fell through to the hidden composer behind the /login provider selector (the pasted API key never reached the prompt), the /effort search, and the input-less overlays (the fork selector, the confirm, the heartbeats picker, the share loader, the reload box). The routing now lives on AgentView (route_paste) in the key dispatch order: the input-bearing overlays take it (provider_auth prompt or search, effort picker, model picker, mcp view), the input-less ones consume it, and only the bare dock editor sees it.
---------
Co-authored-by: Sebastian <sebastian@primeintellect.ai>
…t-ai#3195) * perf(pa-tui): handoff exits break the run loop this iteration - chat->agents 119ms -> 67ms (#2893) The terminal loop's exit-key break only left the input-drain loop, so the handoff fell into the select below it and parked on the 50ms idle tick before the loop-tail exit check ran — measured as ~50ms of added latency on every chat -> agents view switch (strace: the key is handled in ~0.1ms, the teardown starts on the next tick wake ~51ms later; the code's own comment already demanded the teardown run "this iteration"). A handoff (agents-back, /resume, the scoped view, /resume <selector>) now breaks the outer loop immediately: the next surface's mount clears the alt screen, so the tail pass paints nothing the user can see. A non-handoff exit (/exit, /quit) keeps the tail pass — its frame gate paints the final chat frame the exit's main-screen flush shows — and headless runs keep the tail pass so captured frame sequences stay identical. * perf(pa-daemon): borrow message content as RawValue - kill the second full catalog parse, cold -25% (#2882) Co-authored-by: perf-catalog-second-parse-fast <hillclimb@local> * pa-daemon: agent_engine.rs split 1/11 - the tests concern moves out of src/agent_engine.rs (#2889) 51bd18583e17merge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * perf(pa-cli/pa-daemon): tighten the two cold-open connect-probe grids from 25ms to 5ms (#2891) Cold-open boot-floor decomposition at 7064d039a (bench hillclimb record 20260926-194800-startup-boot-floor-decompose) measured two pure-wait probe grids on every cold launch, each quantized 0-25ms (mean ~12.5ms): - ensure_daemon_running_with polls the freshly spawned supervisor's socket every 25ms; a cold supervisor binds ~39ms after spawn. - probe_worker_socket polls a freshly forked session worker's socket every WORKER_CONNECT_BACKOFF_MS=25ms; the worker binds ~1-3ms after the fork. Both grids tighten to 5ms. Timing-only: probes, 30s budgets, auth floor, and all error paths are unchanged; wire and user-visible behavior are identical (TS polls at 25ms in both places - the deliberate divergence is the perf port's, flagged for review). * perf(pa-tui): return the first-frame heap of a resumed transcript; store settled messages rows once (#2895) * perf(pa-tui): return the first-frame heap of a resumed transcript; drop settled messages duplicate block-cache copy * test(pa-tui): settled messages keep no block-cache copy; streaming keeps its replay cache --------- Co-authored-by: perf-tui-memory-fast <perf-tui-memory-fast@hillclimb.local> * perf(pa-daemon): zero-copy relay for routed responses - share the payload bytes, splice the client id (#2897) * pa-daemon: relay routed responses by bytes - supervisor splices the client id onto the worker line * fmt: the two supervisor.rs forms CI rustfmt wants * perf: the cross-process runtime-ready probe memo - on-disk, same identity key, damage-aware (#2881) * pa-core: the cross-process runtime-ready probe memo (on-disk, same identity key) * pa-core: fix the xproc memo commit's test-module paths and escape damage * pa-core: rustfmt the cross-process memo * pa-core: clippy fixes for the cross-process memo tests * pa-core: move the memo-walk helper to test-mod scope (clippy items-after-statements) * pa-core: fix the disk-memo oracles (missing-dir semantics, fallback sequence) and serialize the memo-state tests * pa-core: the disk-memo repair-to-verified-content hits (oracle fix) * pa-core: the live closure-freeze allowlist covers the real runtime's stdlib imports (18 modules found on first live run) * pa-tui: agents-view summary rows drop the model mix; the inactive line bills the descendant aggregate (operator directive) (#2894) 9168514c8384merge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * pa-daemon: supervisor.rs facade cut SS3 - the adoption/register concern byte-moves into supervisor/adoption.rs (#2901) 450cf50aeb31merge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * perf(pa-daemon): share client-event payloads on the supervisor broadcast (Arc) - sup CPU -60% at N=100 (#2896) * perf(pa-daemon): share client-event payloads on the supervisor broadcast (Arc) Baseline at origin/rust 7064d039a on the concurrent-io lane: supervisor CPU per append_custom_message is Theta(N) in resident sessions - 536us/append at N=1 rising to ~2636us at N=100 live sessions (a+21us*N fits all four N and both trials), because every session event (2 per append: message_start + message_end, each carrying the full message payload) is published on the one daemon-wide tokio broadcast channel, and every connected client's event arm wakes, deep-clones the (ClientRouting, Value) frame, locks its attached-list mutex, checks, and discards. Aggregate daemon CPU for equal per-session traffic is Theta(N^2). Share the payload instead of cloning it per receiver: the channel carries (ClientRouting, Arc<Value>). Nothing else changes - same channel, same ring capacity, same routing decisions in the same recv order, same wire frames (write_line serializes from the shared Value; the worker-side EventPump already shares its frames this way via Arc<OutboundFrame>). The per-receiver cost for a non-matching connection drops from a full serde_json::Value deep clone to an atomic refcount bump. Measured on the 16c/32GB ubuntu:22.04 VM (hillclimb-perf-concurrent-io): same-vm ABBA at N in {1,100} follows in the lane record; the claim is daemon CPU per session event, not wall latency (append wall is fsync-dominated on the measurement host). * fix(pa-daemon): wrap the two missed client-event send sites + test compile - supervisor.rs shutdown-signal daemon_closing broadcast and the supervisor_roster.rs RosterSubscribers push missed the Arc wrap; both now share the payload like every other events.send site. - Test fixtures compile against the shared-payload channel: the roster drain helper derefs back to owned Values (tests keep comparing Values), and the daemon_closing assert compares through the Arc. * fix(pa-daemon): compile + rustfmt the shared-payload channel's test helpers - supervisor_roster_seed tests' drain helper takes the Arc-typed receiver and derefs back to owned Values (same pattern as supervisor_roster). - rustfmt the Arc-wrapped send sites (line-width wrap only, no semantics). No product behavior changes: whitespace + cfg(test) code only. * style(pa-daemon): rustfmt the seed-test drain helper + clippy semicolon One-liner receiver type per rustfmt, trailing semicolon per clippy::semicolon_if_nothing_returned. cfg(test)-only change. * pa-core: anchor compaction summaries to kept-tail state and stop re-summarizing file lists (TS #2385) (#2768) a1c236c05df8merge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * test(pa-tui): the bang-during-streaming-turn e2e gates the mock's turn end on the ack bang, not a wall clock - every awaited state is causal or terminal, closing the two-channel load red (red-bang-stream-flush-20260926-1) (#2904) a02c3aa25cdamerge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * pa-ai/pa-daemon: the faux repeat-last knob + the goal-recovery e2e opts in and pins the exhaustion race deterministically - closes red-goal-recovery-faux-exhaustion-20260926-1 (#2902) 1e236ad703efmerge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * pa-tui: the inline pickers' selection wash reads off the surface (operator directive) (#2908) c7a54e058c31merge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * perf(pa-daemon): return the supervisor relay and catalog-scan heap to the OS (#2899) The supervisor process relays every routed worker response through a serde_json Value tree (from_slice in the worker-frame reader, a DaemonResponse through the pending-reply channel, response_line to the client write) and the saved-session catalog scan folds a parse tree per file line; both phases free their trees when the phase ends, but nothing in the supervisor process ever returned the freed pages, so a grown session relay (a ~9.5MiB get_messages wire leaves +71MiB resident; a routed attach adds +42MiB more) and every grown catalog scan stayed at the arena high-water for the daemon lifetime. Mirror the merged #2872 session-memory pattern on the two daemon-side phase boundaries: write_line reports the serialized byte count and the client write loop trims when a routed line carried >=1MiB (the frame is out and the tree is dropped first), and the saved-session scan trims at its join (the per-line trees are folded and freed inside the blocking task; the per-file cached scan states are live cache and stay untouched). Allocator plumbing only - no data, protocol, wire, or behavior changes; non-glibc/Linux builds are no-ops via pa_types::memory_release. Co-authored-by: perf-daemon-rss-fast <hillclimb@prime-intellect.local> * perf(pa-tui): stream the exit/suspend main-screen flush - zero exit RSS spike, byte-identical output (#2913) * perf(pa-tui): stream the exit flush in bounded chunks - the inline repaint never materializes the whole frame * pa-tui: fmt + the flush errors doc (gate nits) * pa-tui: fmt + the flush errors doc (gate nits) * perf(pa-core): serialize same-process auth-lock holders - first-turn slow-class 50% to 12% (#2915) The TS product runs acquireLockSyncWithRetry on a single thread, so the 10x20ms retry only ever fires against another process. The Rust engine is threaded: two worker threads racing AuthStorage::create on a fresh session's first turn (model-resolution registry build vs a concurrent auth read, strace-verified: openat O_CREAT|O_EXCL -> EEXIST within 47us, loser clock_nanosleeps the full 20ms) pay the TS retry sleep against each other, a ~20ms first-turn latency class in 4/6 msgsettle trials. A process-local mutex keyed by the auth document path serializes same-process callers for the microseconds the small read/modify/write holds. The file protocol, staleness judgment, and retry semantics are untouched: a foreign holder (another process) still surfaces WouldBlock and still takes the 10x20ms retry. The mutex is a leaf (the locked section performs only the document's own fs ops plus the caller's callback; no callback re-enters with_lock), and poisoning is recovered because the file protocol is the correctness mechanism. Co-authored-by: perf-model-resolve-cache-fast <hillclimb@prime-intellect.ai> * perf(pa-daemon): per-session subscriber registry - send-time attached check, sup CPU -20% at N=100 (#2914) * perf(pa-daemon): share client-event payloads on the supervisor broadcast (Arc) Baseline at origin/rust 7064d039a on the concurrent-io lane: supervisor CPU per append_custom_message is Theta(N) in resident sessions - 536us/append at N=1 rising to ~2636us at N=100 live sessions (a+21us*N fits all four N and both trials), because every session event (2 per append: message_start + message_end, each carrying the full message payload) is published on the one daemon-wide tokio broadcast channel, and every connected client's event arm wakes, deep-clones the (ClientRouting, Value) frame, locks its attached-list mutex, checks, and discards. Aggregate daemon CPU for equal per-session traffic is Theta(N^2). Share the payload instead of cloning it per receiver: the channel carries (ClientRouting, Arc<Value>). Nothing else changes - same channel, same ring capacity, same routing decisions in the same recv order, same wire frames (write_line serializes from the shared Value; the worker-side EventPump already shares its frames this way via Arc<OutboundFrame>). The per-receiver cost for a non-matching connection drops from a full serde_json::Value deep clone to an atomic refcount bump. Measured on the 16c/32GB ubuntu:22.04 VM (hillclimb-perf-concurrent-io): same-vm ABBA at N in {1,100} follows in the lane record; the claim is daemon CPU per session event, not wall latency (append wall is fsync-dominated on the measurement host). * fix(pa-daemon): wrap the two missed client-event send sites + test compile - supervisor.rs shutdown-signal daemon_closing broadcast and the supervisor_roster.rs RosterSubscribers push missed the Arc wrap; both now share the payload like every other events.send site. - Test fixtures compile against the shared-payload channel: the roster drain helper derefs back to owned Values (tests keep comparing Values), and the daemon_closing assert compares through the Arc. * fix(pa-daemon): compile + rustfmt the shared-payload channel's test helpers - supervisor_roster_seed tests' drain helper takes the Arc-typed receiver and derefs back to owned Values (same pattern as supervisor_roster). - rustfmt the Arc-wrapped send sites (line-width wrap only, no semantics). No product behavior changes: whitespace + cfg(test) code only. * style(pa-daemon): rustfmt the seed-test drain helper + clippy semicolon One-liner receiver type per rustfmt, trailing semicolon per clippy::semicolon_if_nothing_returned. cfg(test)-only change. * pa-daemon: per-session subscriber registry - session events resolve delivery at publish time (TS handleWorkerFrame parity) TS evaluates the attached predicate in the same synchronous pass that writes the socket (daemon-supervisor.ts handleWorkerFrame l.6353; attach flips the flag and writes session_attached in one tick, l.5586->l.5608). The Rust ring evaluated it at RECV time in every connection event arm - a superset in the attach/detach race window TS cannot produce (an event published before an attach could still land after it, duplicating a row the attach snapshot already carried). Session events now route through a supervisor-side subscriber index (session id -> connection id -> bounded per-connection queue): publish enqueues to the attached set under one lock, unattached connections never wake (the ~5.9us/session/append wakeup floor at N=100 from the concurrent-io lane), per-(session,connection) order stays publish order, and a full queue drops with a one-line-per-stall-cycle log (finding 4a visibility). Broadcast / BroadcastExcept / RosterSubscribers keep the ring; ClientRouting::AttachedSession is removed so a stale session-event publish fails at compile time. Session events without an active session id are dropped (TS l.6296 !activeSessionId guard), not broadcast. The dormant supervisor/clients.rs split copy carries the same change (re-homing at the fold will take one of the two). * pa-daemon: fmt + clippy fixes for the subscriber registry (if-let for the single-pattern session-event relay) * pa-daemon: fix the registry idempotency test - drain the delivered frame before the post-detach empty check * pa-daemon: rustfmt the registry rebind call and the idempotency assert * pa-daemon: rustfmt the registry call sites exactly as rustfmt asks * pa-daemon: convert the zero-copy splice arm's attach push to the subscriber registry #2897's raw-splice attach family added a SECOND attach-success push site on the tip's routing.rs; it arrived through the fold with the old vec semantics (the pre-fold grep could not have seen it). Same conversion as the typed arm: registry + session list in one attach() call, the registry insertion is the delivery boundary. * pa-tui: the operator's touch follow-ups - the card click opens the card, the follow hint re-derives at the mode exit, the prompt bar's indicators paint on the bar (#2911) 0c526d534fcamerge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * pa-ai: the codex dead-callback tests stage the registered port checked, not blind (settle-race hardening) (#2906) c38824288cf2merge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * pa-tui/pa-cli: the first-run login frames render the TS login dialog (frame-parity r3) (#2845) 11365e57484dmerge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * pa-tui: session_ui.rs split 1/14 - the heartbeats concern moves out of src/session_ui.rs (#2886) 9f1cfc73550amerge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * pa-tui: the hover affordance - ?1003 any-event tracking delivers the buttonless motion, the hovered clickable card row brightens (muted to the theme fg, dim to muted) (#2918) d81f3d2c7c07merge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * perf(pa-ai/pa-agent): StreamingJsonAccumulator - stop re-parsing streamed tool-call JSON on every delta (TS #2783 port) (#2912) dbec3a6eb0b7merge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge); optional lane gate evidence: gate_1790470828_1252847 GREEN. * pa-daemon: agent_engine.rs split 3/11 - the artifacts concern moves out of src/agent_engine.rs (#2905) 95e10f8ea95emerge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * pa-tui: session_ui.rs split 2/14 - the stream concern moves out of src/session_ui.rs (#2920) 6aecfb087453merge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * pa-tui: session_ui.rs split 5/14 - the auth concern moves out of src/session_ui.rs (#2923) 70abcc702d14merge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * pa-cli/pa-daemon: implement the RPC stdio mode over the in-process session engine (TS modes/rpc parity, stub S5) (#2801) 25b657908b38merge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * pa-daemon: supervisor.rs split 2/8 R2 (remediation) - the client-connection cut actually lands on the facade (#2885) 21304589206amerge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * pa-tui/pa-cli: the agents-view e2e settles its daemon-driven rows by synchronization, not a timing budget (AgentsStep::WaitRender - the registered ranked-hits render/data-arrival race closes by construction) (#2910) f22938c1e0aamerge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * perf(pa-tui): packed cached entry layouts - scroll retention RSS -42%, byte-identical output (#2921) * perf(pa-tui): store cached entry layouts packed - byte-exact rows, one blob + dense span records The transcript layout cache retains every visited entry's rendered rows for the process lifetime. A 2600-key scroll walk over the canonical 10MiB session retained 5,428 entries' rows as 604k fragment-sized spans holding 5.2MB of text (+64.6MB heap, fully retained after return-to-tail; the tui-scroll-retain census: 8.3 spans/line, content capacity already exact, 44% line-buffer slack, per-span Vec/String chunk overhead the retained mass). Merging adjacent same-style spans would shrink the storage but changes the exit-flush inline scrollback's ANSI bytes (per-span SGR re-emission; the exit flush is the TS-parity-frozen output), so the cache stores the same rows packed instead: one content blob plus dense (offset, len, style) records, expanded byte-exactly on read - only the intersecting row range is expanded, so a frame inside a huge entry pays its visible rows, never the whole row set. The pad entry's own 109k-span row set (the resumed ready-state footprint) packs the same way. * perf(pa-tui): exact pack blob capacity + size-gated post-pack trim The pack's blob grew by String doubling (2x capacity: 33.6MB held for a 17.45MB row set at 40MiB); the first pass now sizes it exactly. A huge entry's rendered rows are the transcript's biggest single transient and the pack just freed them - the freed pages only return to the OS when the allocator's trim can reach them (the 40MiB ready RSS measured bimodal 181/205 on the same build); the pack now returns them immediately, gated at 8192 rows so ordinary entries never pay a trim. * fix(pa-tui): EntryRows::is_empty for the touch surface's shows-tail peek (fold resolution completion) The #2911 fold introduced the empty-section peek (a window that exactly ends on the final chat entry re-checks whether any non-empty section remains before declaring shows-tail); its section source is the EntryRows handle since the packing fold, which needs the is_empty form. * test(pa-tui): fix the pack tests' clippy findings (untyped Vec::new, shadowed view helper) * test(pa-tui): drop the pack test closure's unused mut --------- Co-authored-by: perf-tui-scroll-retain-fast <perf-tui-scroll-retain-fast@hillclimb.local> * pa-daemon: agent_engine.rs split 2/11 - the config concern moves out of src/agent_engine.rs (#2909) 07cbb0febb74merge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * pa-daemon: agent_engine.rs split 4/11 - the model concern moves out of src/agent_engine.rs (#2907) 5c530e66cef9merge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * pa-tui: session_ui.rs split 3/14 - the queue concern moves out of src/session_ui.rs (#2900) e673275046dfmerge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * pa-daemon: supervisor.rs split 7/8 - the update/restart concern moves out of src/supervisor.rs (#2903) 268c1fba26c0merge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * pa-tui/pa-cli: dock panel exits restore the dock's own group, not the prompt bar (operator ruling 2026-09-26) (#2864) a12c2847335bmerge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * pa-daemon: agent_engine.rs split 5/11 - the goalcore concern moves out of src/agent_engine.rs (#2924) c95a239b9eb3merge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * perf(pa-tui): handoff drains park on observed input, not a fixed wait - chat-to-agents -79% (#2916) * perf(pa-tui): a handoff drain consumes buffered input instead of parking on the idle window The chat->agents handoff teardown pays the enhanced_keys drain's fixed 50ms DRAIN_IDLE poll on every switch (chat->agents measured 67ms p50 at #2893, ~50ms of it this window). The idle window guards a kitty key release that lands after raw mode is off - a leak that is unreachable on a handoff: raw mode stays on (the adopting surface's reader takes the same tty) and every surface's dispatch drops release events (input::filter_enhanced_key_events, TS tui.ts). The handoff now consumes what the terminal has already written with zero-timeout polls and returns as soon as the buffer is observed empty; only when input IS flowing does it fall through to the bounded drain, so a burst around a handoff is coalesced exactly like before. True exits (drain, drain_for_exit) keep the TS drainInput(1000, 50) contract untouched. Adds a real-pty e2e that arms the kitty protocol, injects the handoff trigger's release in flight, and audits the byte stream (no visible release, no post-exit kitty flags, no echo after the restore). * test(pa-cli): fix the kitty-release e2e gate lints (fmt shape, unit let-binding, unused import) * test(pa-cli): the kitty-release mock supervisor serves every connection in turn The chat surface holds one daemon connection and the agents view opens its own after the handoff; a single-accept mock refused the second (the first run of the e2e failed on exactly that: connection refused at run_agents_view connect). * test(pa-cli): qualify the mock supervisor connection handler call * test(pa-cli): handle the listener incoming result in the mock supervisor * test(pa-cli): the kitty-release editor probe waits for the painted cell The frame paints typed cells as styled positioned cells (escape bytes between characters), so the two-byte zz needle never appears; wait for the painted z cell instead. * test(pa-cli): the kitty-release harness reaps the pty child on panic paths too * test(pa-cli): the kitty-release exit drives the CSI-u escape form With disambiguate armed a kitty terminal encodes its Esc presses as CSI 27 u; the raw lone ESC byte is the legacy form the reader arms its meta-wrapper hold for. Drive the realistic encoding and separate the exit key from the release injection. * fix(pa-tui): the handoff drain's bounded phase runs on the budget the zero-timeout loop left The zero-timeout consume loop can spend the whole DRAIN_MAX under continuous input before falling through to drain_until_idle, which then started a fresh budget - the handoff could block nearly two seconds, past the documented one-second hard cap. The bounded phase now runs on what remains of the original budget (Macroscope thread PRRT_kwDOSXZbXs6mWWqM). * perf(pa-daemon): borrow the catalog fold metadata and single-open the scan - cold scan -7%, syscalls -22% (#2919) * perf(pa-daemon): borrow the catalog fold's entry metadata, kill the per-line tail Vec The post-#2879/#2882 cold roster scan still typed-parsed every line into owned strings and materialized `Value` trees for fields the fold reads once or discards: 3 `String` allocations per line (type, id, timestamp) plus a `Value` tree per message row (role, provider, model, timestamp) and per session_info/state/model_change/thinking_level row. The resume tail added one `Vec` allocation per line sized line.len()+17 to keep 16 bytes. Both costs are gone without changing a row byte: - SessionInfoEntry's scalar fields borrow as `Cow<str>` (zero-copy when unescaped, owned fallback identical to the old String), its object fields ride raw spans like #2882's content: each arm parses back only the span it reads, with exactly `Value::as_str`/`as_u64` semantics (present-and-string/number, absent and non-string both read None, the model_change abort arm keeps its exact two-step None). - advance_tail copies inside the fixed 16-byte window: the same bytes (a rolling-reference lockstep test pins the old Vec semantics), no per-line allocation. Differential ground truth: the new in-tree shape matrix pins every borrowed read to the full-parse Value read per row (escaped scalars, non-string roles/timestamps, null/absent/whitespace names, hidden/sleep states, abort shapes) and folds the accepted rows end to end against the legacy full-parse reference fold; the VM census ran the same differential over 177,798 real fixture lines (100/1000/4096 tiers) with zero divergence in acceptance, fields, or fold states both directions. * perf(pa-daemon): share one open between the roster header gate and the fold The roster scan opened every file twice: the bounded header gate opened, read its first line, and closed, then the fold opened the same path again for the scan — an openat+close per file per scan (plus the second metadata read the fold always paid). The gate now reads the first line from the same fresh handle the fold rewinds and scans, so one open serves both. The TOCTOU the double-open carried is disclosed: with two opens, a rename/replace landing between them judged one file and folded another; the shared handle pins the judgment and the fold to the same inode — the fold's cursor, generation, and certification re-stat now read the file the gate judged, never a replacement that raced in between. The listing stat (`stats.mtime`, the `modified` fallback of last resort) is read lazily now: the fold only reaches it when a row has neither message timestamps nor a parseable header timestamp, so the eager per-file stat the scan always paid serves only the rows that read it. The `or_else` chain keeps its order and its None semantics (the existing fallback tests pin every arm of the chain). * pa-daemon: fmt + clippy for the catalog fold lane (test-import move, lockstep test polish, matrix lint allows) * pa-daemon: supervisor.rs split 4/8 - the saved-session concern moves out of src/supervisor.rs (#2883) 9f9146b74371merge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * pa-tui: the #2921 review follow-ups - RowPack::pack refuses unrepresentable entries, the huge-entry trim drops the expanded rows first (fold of rust 9b62f26af) (#2925) df34ea19dbb3merge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * pa-tui: session_ui.rs split 10/14 - the bash concern moves out of src/session_ui.rs (#2928) 481b2f28553cmerge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * skills/prime-intellect: sync vendored sandbox docs to the VM-only surface (TS #2456 doc half) (#2751) a4e997e2e803merge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * fix(pa-cli): remove the duplicated restore_dock_focus initializer the #2751 squash double-applied The #2751 squash (1a9fd16b9) landed the heal rider line onto a tip that already carried the identical line from #2925 (e6e7a26e4) - the squash applied the stale pre-fold diff, duplicating the field (E0062). This restores the fixture to the parent 84dbb51e0 state (exactly one field). The label rider and the docs in the same squash are intended and stay. * pa-daemon: agent_engine.rs split 7/11 - the SessionEngine trait impl moves out whole (#2926) 2b07a22bd1d3merge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * pa-core + runtime: the harness-digest family - IDF-ranked digest/search, state-fingerprint staleness, newest-only digest contexts, validated kernel harness writes (TS #2392/#2400/#2394/#2463 parity) (#2750) bff9fa6ff122merge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * fix(pa-cli): the kitty handoff e2e fixture initializes restore_dock_focus (#2927) 962ff3097575merge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * pa-tui: session_ui.rs split 7/14 - the settings concern moves out of src/session_ui.rs (#2930) fd71eaf2dfeamerge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * pa-tui: session_ui.rs split 6/14 - the model-picker concern moves out of src/session_ui.rs (#2929) 2038abcf5754merge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * pa-daemon/pa-cli: ACP model and effort pickers - configOptions at session/new, session/set_config_option, config_option_update (TS #2455) (#2758) fd977cb13ee6merge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * perf(pa-core): consolidate auth-lock reads - 36 lock cycles per first turn to 2, settings mutex closes the unmasked stall class (#2932) * perf(pa-core): consolidate auth-document reads through a validated cache * perf(pa-core): serialize same-process settings-lock holders (the #2915 pattern) The auth read-through cache on this lane unmasks a pre-existing stall: two worker threads racing the same settings.json pay the full TS 10x20ms retry sleep against each other (strace-verified: mkdir attempts 11us apart, the loser clock_nanosleeps the full 20ms; the paired census shows same-process overlapping settings acquisitions 2 on the base and 5 with the auth cache, sleep20 1 vs 2, and the timing legs pay a ~20ms-class stall on 3/6 fresh turns vs 0/6 base). The auth-lock cycles 150-300us same-process serialization was pacing the threads apart by accident; that masking is not a mechanism to keep. TS runs its synchronous settings lock single-threaded, so same-process settings contention is a Rust-port artifact, the exact class #2915 ruled on for the auth lock: a process-local mutex keyed by the document path serializes same-process callers for the microseconds the small read/modify/write holds. The file protocol, staleness judgment, and retry semantics are untouched: a foreign holder (another process) still surfaces WouldBlock and still takes the 10x20ms retry. The mutex is a leaf (the locked section performs only the document's own filesystem operations plus the caller's update callback; no settings callback re-enters with_lock - every callback is a pure JSON transform), and poisoning is recovered because the file protocol is the correctness mechanism. --------- Co-authored-by: perf-auth-lock-fast <hillclimb@prime-intellect.ai> * perf(pa-daemon): zero-copy worker response path - routed msgs -17%, attach -22%, worker RSS -20% (#2935) * perf(pa-daemon): zero-copy worker response handoff - serialize the line from the borrowed trees, write the frame without re-buffering the payload * fmt(pa-types): the segments test write_frame call in the form CI rustfmt wants * fmt(pa-daemon): the response-path call forms CI rustfmt wants (VM cargo fmt at the exact head) * fix(pa-daemon): restore the response_line TS-key-order test the new-test insert orphaned (clippy empty_line_after_doc_comments was the symptom) * fmt(pa-daemon): the restored test doc comment indent * fmt(pa-daemon): single trailing newline at file end --------- Co-authored-by: wc <wc@fleet.local> * pa-daemon: agent_engine.rs split 6/11 - the Turn types move out of src/agent_engine.rs (#2931) b2ca4deea5afmerge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * perf(pa-daemon): batch the queue-checkpoint journal pair - 4 syncs per warm turn to 2, crash window strictly narrowed (#2936) * perf(pa-daemon): batch the queue-checkpoint journal pair into one durable append The queue checkpoint (prompt/steer/follow-up admission, turn settle, queue mutations) appends two records to the worker recovery journal - the queue snapshot and the busy/operation verdict - as two separate open+write+fsync cycles, paying two journal flushes per checkpoint. Both records describe one atomic checkpoint, and the busy verdict must never publish over a snapshot that did not persist, so the pair can ride ONE open+write+fsync: the batch is all-or-nothing durable, the on-disk line order matches the sequential form exactly (snapshot first, then the verdict), and an unchanged verdict keeps appending the snapshot alone. Measured on the warm-turn admission path (the wave-5 warm-durable-append decomposition): the two journal fsyncs sit inside the TUI-ack-to-user-row phase together with the session append's fdatasync; batching removes one of the three durable syncs per warm turn without weakening any durability guarantee (the session append's per-row fdatasync is untouched). * test: rustfmt the batched-checkpoint test call sites (gate fmt finding) * fix(pa-tui): the exit watchdog holds fire while the flush drains - healthy slow drains no longer truncate scrollback, TS-convergent (#2937) * perf(pa-tui): the exit guard holds its force-quit while the exit path drains - slow terminals keep the whole scrollback flush On a terminal that consumes the exit flush slowly (a laggy ssh at ~0.5-2MB/s), the flush of a large transcript outlasts the 1500ms FORCE_QUIT_AFTER_MS deadline that arms at the second Ctrl+C, and the watchdog fires mid-flush: strace shows its restore writes winning the pty FIFO race at a flush-chunk boundary, exit_group(0) landing while the writer still holds ~64-82% of the transcript (40k rows: 8.74MB flush truncated to 1.5-3.1MB), 'shutdown stalled; forced exit.' printing on a healthy drain, and the restore bytes queueing mid-stream behind the flushed rows. TS has no watchdog at all (its handleCtrlC second press runs the async shutdown, and slow writes simply wait), so both the message and the truncation are port-only. The guard becomes drain-aware: the flush writer reports progress per completed 32KiB chunk (view.rs FlushSink), the release tail and the resume hint report theirs, and the watchdog holds its fire while progress landed within EXIT_PROGRESS_GRACE_MS (500ms) - the hard 1500ms ceiling stays for the silent case (the wedged loop the guard was built for). Flush chunks shrink 256KiB -> 32KiB so a drain of at least ~65KB/s completes chunks inside the grace window; the flush byte stream is unchanged (the exit-flush lane's byte-identity oracle). The truncated scrollback contract is restored on slow drains: the flush completes byte-identically, the release tail lands after the last row, and the message prints only for a genuinely stalled drain. The exit-guard unit tests grow the hold/fire decision table; a new real-pty e2e (pa-cli slow_drain_exit_guard_e2e, the kitty-release harness pattern) drives the real chat surface over a paced pty master and asserts both sides: a draining terminal flushes the whole transcript with no forced exit, and a stalled drain still fires. Rider (disclosed): kitty_release_handoff_e2e grows the restore_dock_focus field the #2916 squash dropped from its fold-time heal - the tip's pa-cli test target does not compile without it. * test(pa-cli): the slow-drain e2e asserts the forced fire structurally The re-executed test binary's libtest harness captures stderr per test, so the watchdog's 'shutdown stalled' line never reaches the pty in the harness child (the real binary writes it to fd 2 - the lane's VM bench legs assert it there). The stalled-drain leg instead asserts the forced exit structurally: the forced restore's own alt-screen leave lands on top of the exit path's (a clean exit leaves it exactly once), the flush never reaches the transcript tail (one copy of the last user row, the startup viewport's), and the process dies with the guard's exit code inside the stall window. Harness needles use the user-message rows (assistant rows carry per-word SGR spans) and the post-exit drain reads the pty's kernel-held bytes before asserting. * fmt: the slow-drain e2e needles and the watchdog's progress read * clippy: doc backticks + checked Duration subtraction in the guard tests; the e2e's needle check takes the direct is_none --------- Co-authored-by: perf-slowdrain-exitguard-fast <lane@hillclimb.local> * perf(pa-core): consolidate settings-lock reads - 32 lock cycles per first turn to 2 (#2941) * pa-ai/pa-core/pa-cli/pa-tui: grok-4.7 on every serving surface (TS #2505) + Claude Code 2.1.281 + Anthropic subscription ban-risk warning (TS #2645) + one owner for the Prime team header, retry failed !command credentials (TS #2497) (#2755) 7373eb471670merge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * test(pa-cli): the interactive_daemon_e2e wedge root-kill - PDEATHSIG + orphan sweep + the 300s headless wall (#2942) dbed1170fa2bmerge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * pa-tui/pa-cli/pa-daemon: session opens wait through a daemon update restart (TS #2391) + the failed-restart hint (TS #2515) (#2763) e7a84e749089merge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * perf(pa-daemon): the all-idle compaction fires like TS and rides the TS compact sync class - journals bounded (#2944) * perf(pa-daemon): settle-tail compact consolidation - the all-idle compaction fires like TS and rides the TS compact sync class The worker recovery journal's all-idle gate ran BEFORE the record insert, so a single-session journal's own busy admission record blocked every settle's compaction: the compact never fired on the dominant shape and the journal grew append-only for the session's lifetime (TS computes the gate POST-insert and compacts at every changed-idle record). The gate now matches TS, bounding the file. Where the compact fires, its temp sync_all was a sync class TS's compact does not pay (TS worker-recovery-journal: writeFileSync + renameSync, no fsync; the command journal's writeFileAtomicSync counterpart does carry fsync). The Finalize seam now encodes the sync class per owner: RetryBusy keeps its fsync (command journal), Synced keeps the Rust-native terminal-compaction journal's belt, and Bare is the TS worker shape - temp write + rename, no fsync. Durability is owned by the append path (the fresh-write class is untouched): the compacted form holds only records the append path already made durable, so a lost compact falls back to the append-only history, which replays identically. * test-only rustfmt of the new test call site (the gate's one fmt finding) * runtime/kernel: vendored-runtime hardening + kernel stderr owner-only (TS #2372/#2423/#2500/#2471/#2478/#2425 parity) (#2744) ea5abd1bbe1bmerge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * pa-tui: session_ui.rs split 11/14 - the prompt submit pipeline moves out of src/session_ui.rs (#2943) 3bafbc007b74merge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * perf(pa-tui): 8-byte packed span records with per-pack style table - scroll retention -7.5MB, byte-identical output (#2939) * perf(pa-tui): denser packed span records - style table + derived offsets (8B/span), byte-exact range expansion * test(pa-tui): rustfmt the exhaustive row-pack range oracle * fix(pa-tui): clippy - if-let style dedup + drop redundant test clones * pa-tui: fix the submit-outlived-by-switch idle-gate race - the turn-end watermark restarts with the mounted stream (#2945) c661290b1b77merge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * pa-daemon: hold spawn-name reservations until admission is durable; collect returns cancelled envelopes for just-deleted targets (TS #2396 + #2388 F4) (#2757) 18aa772bd3b2merge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * pa-ai/pa-core/pa-daemon: codex stale-chain retry after metadata (TS #2374) + safety failures permanent (TS #2472) + quota park until reset with auto-resume (TS #2375) (#2761) dc9892ffbc1emerge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * test(pa-tui): the headless settle bound names its stuck member in 60s - defense-in-depth inside the wedge wall (#2949) The interactive_daemon_e2e exit-gate wedge family is root-killed upstream (#2945: the turn-end watermark restarts with the mounted stream) and the harness carries the 300s wall (#2942). This closes the remaining gap: the headless settle was the run loop's only unbounded wait on the product side — a settle member that never drains parked the run forever with no failure name (TS exits the process at shutdown and lets in-flight work dangle, so the settle has no TS counterpart). The gate's twelve settle members are now snapshotted (HeadlessSettle: settled() is the old gate exactly; blockers() names them), and after the plan completes a stuck member fails the run within HEADLESS_SETTLE_TIMEOUT_MS (60s) with the member named — e.g. 'a turn still active' — instead of waiting out the harness's 300s wall with a generic timeout. Green settles are milliseconds after HeadlessDone (the suite's green wall is ~15s; the last submit's own ack bound is 10s), and terminal runs never arm the bound (HeadlessDone exists only on the headless harness; a live terminal ends the run on exit_requested + the exit guard). Proven end-to-end by the lane's matrix: the wedge converted to a 98.4s attributable red naming the latched member (the bound-only diagnostic arm), and the full candidate stayed clean at 30/30 interleaved trials vs 3/30 wedges at the lane parent (record 20260927-085200-interaction-exit-gate-hang-remediation, bench hillclimb). * perf(pa-daemon/rpc): warm the model registry at RPC session boot - first get_available_models 1170.6ms to 58.9ms (#2953) TS session boot resolves the initial model through refreshAvailableModels (model-resolver.ts), which also fetches the live Prime Inference catalog in the background and caches it on disk; the daemon worker fires the same fire-and-forget refresh from its create path (worker/create.rs). The RPC mode hosts the session in-process with no create command, so nothing warmed the caches: an integration's FIRST get_available_models call paid the whole awaited refresh chain on its response path (measured 812-1296ms on the bench VM; the 15s fetch-timeout worst case on a degraded network) while the same command on the daemon and ACP surfaces answers from the validated snapshot. Mirror the daemon worker boot spawn: the caches warm during the session's first turn, and the first call serves the same snapshot. Write behavior is unchanged: the same cache files, the same write-on-fetch-success conditions, the same cadence (hour-gated catalog refresh, 5-min private-authorization TTL), only started at boot. Co-authored-by: perf-rpc-models-persist <lane@hillclimb> * pa-tui: session_ui.rs split 4/14 - the share concern moves out of src/session_ui.rs (#2922) b0d72b29a700merge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * pa-daemon: agent_engine.rs split 8/11 - the turn-execution impl moves out (#2934) a59d3389dfbamerge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * pa-daemon: supervisor.rs split 5/8 - the worker-lifecycle concern moves out of src/supervisor.rs (#2956) 205f4d0f469cmerge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * pa-tui: session_ui.rs split 8/14 - the sessions concern moves out of src/session_ui.rs (#2957) 7d19e9832120merge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * pa-daemon: supervisor.rs split 6/8 - the signals concern moves out (#2960) a6562bc252efmerge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * pa-daemon: agent_engine.rs split 10/11 - the lifecycle concern moves out of src/agent_engine.rs (#2962) 17d3573c5a58merge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * pa-tui: session_ui.rs split 12/14 - the keys concern moves out of src/session_ui.rs (#2958) bc6b7d82cb0bmerge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * pa-daemon: agent_engine.rs split 11/11 - the facade trim: the last product free fns move out; the file ends as the composition root (#2964) 1fe6a6791030merge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * pa-daemon: supervisor.rs split 8/8 - the facade trim: the notes concern moves out, the test battery re-homes (#2963) 8a5274baa0d9merge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * pa-tui: session_ui.rs split 9/14 - the panels concern moves out of src/session_ui.rs (#2961) 377eda9ded15merge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * pa-tui: session_ui.rs split 13/14 - the apply concern moves out of src/session_ui.rs (#2965) c10a44e407cdmerge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * pa-core: cap kernel host-request cell source at 2 KiB (the TS #2475 port) (#2966) 96f689fc38femerge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * pa-tui: the /model picker resolves by provider, never the first same-id catalog entry (fixes the operator report) (#2967) 24411964739emerge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * pa-tui: session_ui.rs split 14/14 - the facade trim: the file ends as the composition root (#2968) 60cbb4fbb642merge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * perf(pa-core): the oauth refresh leaves the auth lock - fetch under single-flight, hold-sum 396ms to 0.09ms (#2971) An expired stored OAuth credential refreshes its token inside AuthStorageBackend::with_lock: the OAuthIntegration seam is synchronous by contract, so the network round trip runs under the document lock AND under the process mutex that spans the whole critical section, stalling every other same-process auth read and write for the fetch (the RPC cycle_model path measured 194-201ms auth.json.lock holds per switch on the bench VM; the assembly read pays one ~0.2ms cycle, the switch pays the fetch). The TS product holds its own lock across the same await (refreshOAuthTokenWithLock -> withLockAsync), but its single-threaded runtime never blocks other work on it; this engine is threaded, so the port narrows the lock scope instead: load-then-lock. The document loads through the consolidated read arm, the token fetch runs outside every lock behind a per-provider single-flight gate (the in-process serialization TS gets from its single-threaded runtime, with the expiry re-checked under the gate so a second caller never spends a single-use refresh token after the first flight landed), and the write re-enters the same locked read-modify-write protocol - now held only for the re-read, insert, and atomic write, and skipping the write entirely when a peer refreshed while the fetch ran. File protocol, read results, and every resolution outcome are unchanged. * pa-daemon: the supervisor roster broadcasts only on content change (the TS #2481 port P3) (#2974) 054553b8ca12merge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * pa-cli/pa-tui: prime-agent update - the TS->Rust migration path (uninstall TS, install Rust, sessions preserved) (#2981) 739ed7f7d015merge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * perf(pa-core/pa-daemon): a settled RLM child releases its kernel at the settle park - ~27MB reclaimed per settled child, TS #2483 port (#2983) * perf(pa-core/pa-daemon): a settled RLM child releases its kernel at settle - snapshot-flushing stop_kernel, revivable (TS #2483) The rust port of the stale perf PR #2483's inline arm (the supersession analysis: the not-superseded claim - settled children hold a worker and a kernel until parent close; nothing at the tip releases them; the daemon-mode whole-worker passivation stays deferred to the orchestrator): - IpythonKernelProvisioner::stop_kernel (TS stopKernel): shuts the owned kernel down with a final namespace snapshot WITHOUT marking the provisioner disposed; a kernel still starting up is joined first and shut down the same way (the TS managerPromise arm). The stop records a pending-stop gate (TS pendingStop) that the next start_kernel_impl awaits before reading the snapshot back, so a follow-up turn's fresh boot revives the flushed namespace instead of racing the flush; a completed stop awaits instantly and each stop supersedes the previous (a clonable watch receiver: multiple revival waiters gate on it). - The session engine gains stop_kernel_snapshot (the TS stopKernel({snapshot:true}) seam beside dispose_kernel), and the SessionEngine trait gains release_settled_child_kernel (default no-op): the AgentSessionEngine arm evaluates the canPassivateSettledSession gates engine-side - no unsettled descendants (has_unsettled_rlm_work), no registered cron/heartbeat jobs (a worker-wired probe over the shared cron store) - then fires the per-build release probe (a weak provisioner reference, the background-bash-probe adoption pattern, cleared on retire/close). - The turn runner's park arm fires it best-effort when the worker core proves the parent-owned, unattached, unqueued idle state (rlm_depth>0, no attached clients, not compacting, no lane work - the park arm's own construction). The divergence the port discloses: rust children are worker processes (the parent has no in-process reach and the wire is frozen), so the release triggers at the child's own idle park instead of the TS parent's run-settle hook - the same revivability semantics (the next kernel use boots fresh from the flushed snapshot), and the roster/collect surfaces are untouched by design. Tests: the provisioner stop flushes the snapshot and the next ensure revives the namespace (live-kernel, ambient-venv-gated); the park arm's policy matrix (a parent-owned child releases, a root/attached/compacting session stays resident); the engine gates (a registered-jobs probe defers the release, the probe fires otherwise). * test(pa-daemon): the park-arm release test waits on observable readiness (the review advisories) Two BUGBOT test advisories on the first review: the park-arm test's bounded poll used fixed sleeps (a retry-to-green readiness wrapper). The recording engine now notifies on every release fire, so the test waits for the observable readiness - the notification is the pass condition, the bounded timeout is only the failure bound for the positive arm and the absence bound for the gated arms (no fixed sleep ever makes a pass). The commit also lands the VM's cargo fmt output on the touched files (the first commit's hand-written formatting failed the review's fmt pre-flight: the lane builds on the VM only, and the formatted sources must sync back before every commit). * perf(pa-core): provider auth answers once per provider - the #2479 memoization ports, per-model probe -66% (#2973) * perf(pa-core): provider auth answers once per provider and the private PI authorization cache parses once per file identity (TS #2479) The rust port of the four unclaimed mechanisms of the stale perf PR #2479 (the supersession analysis: the rest of that PR's premise landed via #2932's storage read-cache): - get_available's per-model has_configured_auth becomes a per-provider memo: the catalog walks hundreds of models over a few dozen providers and each probe rebuilds the provider's auth-source candidates, while a same-registry probe is stable by construction (&self, no mutation between models). TS getAvailable's authByProvider map. - get_rlm_searchable_models' per-model get_auth_status becomes the same per-provider memo (TS _authenticatedRlmModels' selectableByProvider). - read_private_prime_authorization_cache serves from a process-wide stat-identity snapshot (dev/ino/mtime_ns/len, the TS CatalogFileIdentity) while the file is unchanged; the port builds a fresh registry per resolution touchpoint (the TS session kept one long-lived registry), so the parse would otherwise re-run on every resolution. Only a successful parse bracketed by one identity is pinned, a failed read unpins (retries), and the write path's atomic rename supersedes (new identity). - AuthStorage memoizes auth-source candidates keyed by the hashed material itself (TS authCandidateMemos): reuse skips only the SHA-256 work, env values are deliberately re-read on every call, command values resolve before the memo, and stale checks run against the memoized candidate (candidates are immutable). Tests: the per-provider status memo gates one stale provider across all its models while a second authed provider keeps its models; the private-cache snapshot pins stable parses, re-parses rewrites, and never pins a failed read or resurrects a deleted file; the candidate memos supersede exactly when the hashed material changes (a stale marking from an old value never gates a changed one). * test(pa-core): the stale-provider memo test asserts the tip's stale-aware has_auth The memo regression test claimed a stale-marked provider's models stay in get_available ("stale is only the searchable-set's gate") - but AuthStorage::has_auth is stale-aware at the tip (available_candidate skips candidates matching a marked stale token), so get_available gates the stale provider too, and the tip's get_rlm_searchable_models gates it twice over. The memo preserves exactly those semantics; assert them: the stale provider is gated across all its models from BOTH sets, and a second authed provider keeps its models. Discovered by the full-suite fleet gate (gate_1790546015_945232) - the lane's local legs had not run the test suite; the three other gate reds (kernel_restore_guards x2, tui_prime_login_escape) are SOLO-GREEN on the exact head content (co-scheduling class, the standing family from gate_1790531716). * test(pa-core): behavior-focused wording in the candidate-memo test comments (the review advisory) The BUGBOT history-narration advisory asked for comments that state the current behavior rather than the sequence of edits: the env-change arm now says what the memo key does (a changed value changes the key, so the rebuilt candidate's value fingerprint differs from the stale token's) and the return arm says the marked material's candidate re-serves when its value returns. * pa-cli/docs: the update fetch source flips to the official domain at the rust-to-main merge (#2984) 309dd96b1f96merge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * pa-tui: agents_view.rs split stages 1-2 - the test mass re-homes + the delete concern moves out (#2985) bd221cb5e70amerge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * perf(pa-daemon): saved_session_context reads windowed-first - worker resume CPU -140ms, the parse signature (#2969) * perf(pa-daemon): windowed-first saved_session_context - the create-path model restore reads the windowed store (restored_settings + has_thinking_level) instead of full-parsing the session history; open_windowed's full-open fallback keeps unsupported/malformed files identical; differential oracle keeps the pre-change full-parse reader as the reference across no-boundary/in-window/model-only-before/thinking-only-before/malformed-prefix fixture classes * perf(pa-daemon): address the Bugbot findings on the windowed saved_session_context - comments describe current behavior only, the oracle helper returns the owned TempDir so fixture scratch trees clean up at test scope end --------- Co-authored-by: perf-launch-open-fast <hillclimb@primeintellect.ai> * pa-core: compact_session.rs split - the tests re-home + the summarization, anchor-selection, and boundary cuts (#2987) f43aebc9c50dmerge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * pa-tui: agents_view.rs split stage 3 - the render concern moves out (#2988) 03a6fcc07793merge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * install: the Rust port takes over the prime-agent keyword - clean TS daemon shutdown, config preserved (#2972) 737e52dc7695merge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * pa-daemon: the scheduling catalog fans out per-worker (the TS port P4) (#2979) 1e78bb715fddmerge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * pa-tui: agents_view.rs split stage 4 - the open + incident concerns move out (#2991) 0ef076a06131merge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * pa-daemon: session_store.rs split - the index, read, write, view, info, tests children (#2990) 7b58b0acb457merge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * pa-tui: agents_view.rs split stage 5 - the data + input concerns move out; the file ends as the composition root (#2992) cadb8b4f33d6merge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * docs: the README becomes the Rust product's own; the port-process docs are removed (#2993) fe891d188ad0merge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * pa-tui: snapshot.rs split stages 1-2 - the test mass re-homes + the tool-fold concern moves out (#2995) eaa4b672f2f8merge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * pa-tui: snapshot.rs split stage 3 - the decoder concern moves out; the file ends as the composition root (#2996) 1564648986edmerge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * pa-daemon: rlm_children.rs split - the composition root (host, lifecycle, usage, registry, tests) (#2997) 4ee722d403b6merge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * pa-tui: interactive.rs split - the tests, onboarding, headless, render, reconnect, run children (#2998) d592a0672d5dmerge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * perf(pa-daemon): share the open's artifacts + skip the depth scan's full parse (cold-open-residual) (#2970) 5b75513ff7fbmerge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * pa-tui: every session-exit route restores the terminal - the kitty-mode leak into the shell is fixed (#3001) 8f84a46233cdmerge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * pa-cli: the family-seeding e2e spawns pin the daemon's session dir (the flash e2e's seeded-family red) (#3003) c54ff2a09a84merge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * pa-tui: undo the condensed activity runs - the collapse mode becomes details mode minus thinking blocks (#2999) a6d8414d818cmerge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * pa-cli: print_boundary.rs split - the 4 stages: events, compaction_arms, autorefine, tests (#2989) 2292af8f1cefmerge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * pa-tui: bash_view.rs split - under 1,000 lines (#3008) 15d9c1a659efmerge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * pa-tui: auth_panel.rs split - under 1,000 lines (#3009) 8c3061a5db29merge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pi…
* perf(pa-daemon): the create-path descriptor fan-out collapses - the spawn record rides the TS persistWorker shape and the boot registration persists in memory only The fresh-create census (record 20261001-031500's io leg) attributes five fsyncs to one create window: three worker-descriptor persists to the same path (spawn Starting 39.2ms, boot-registration Ready 39.9ms, post-create identity 39.6ms), the session jsonl's create rewrite (74.6ms), and the worker recovery journal's append (38.0ms, TS-parity - TS fsyncs it too). TS pays exactly one fsync per fresh create: the journal. The descriptor family's fsyncs are the port's unconditional-fsync divergence from TS's writeFileAtomicSync (fsync opt-in, never requested at these call sites), and TS has no boot-registration write at all. The cut, per-site: - The spawn record now uses the TS persistWorker call shape (write_file_atomic_unsynced: atomic temp+rename, 0600, no pre-rename fsync). A pre-completion record only has to outlive a supervisor crash, which the rename in the page cache does; a power-crash loss dies with the worker and costs the create its retry - the window TS tolerates for the same write. - The boot registration refreshes the resident in memory only: its persist was durably redundant with the create-completion persist (its only on-disk delta was a premature Ready while the create replay was still in flight), and the Starting record it leaves behind is the state already on disk for the spawn-to-registration span of every launch. - The create-completion persist (launch_worker's post-create write) KEEPS its fsync: the metadata-survival barrier - Ready + root_session_id + session_file + create_command.session_path durable before the create response reaches the client. The session jsonl rewrite's fsync (the session family's deliberate strengthening) and the journal append's fsync (TS parity) are untouched. Fan-out per fresh create: fsyncs 5 -> 3 (jsonl + journal + the final descriptor barrier, all at the create-completion boundary), descriptor writes 3 -> 2. The supervisor-config and update_prepare sites keep the durable write_file_atomic (the rejected daemon-boot cut is not resurrected; update_prepare is out of this change's scope). * fix(pa-daemon): the relaunch keeps the durable spawn record - the unsynced TS shape serves fresh creates only The Macroscope HIGH (supervision.rs:483): the fan-out cut's unsynced spawn record also served every relaunch path (crash restart, boot adoption, update restart, retry), where it REPLACES an established, already-durable descriptor - a power crash in the torn window loses the descriptor's whole payload (recovery journal pointer + durable create command), and with it the next boot's revival/replay. The remedy keeps the measured fresh-create win intact and closes the relaunch window: spawn_worker_process now takes the spawn record's durability per launch class (TempSync - the single optional-fsync source of truth the PrimeIntellect-ai#3283 write family already dispatches on); launch_worker passes Unsynced (the TS persistWorker shape, the cut's measured path - no relaunch occurs in the ABBA's measured trials), relaunch_worker passes Synced. Served-path witness (cfg(test) atomic_write_probe): the durability class is not observable in the persisted bytes, so the probe records every atomic write's class; the oracles drive the real relaunch_worker and launch_worker paths (probe-fail fast via the connect-budget seam) and assert the synced/unsynced writer actually served. The adoption comment claiming the spawn record holds the registering worker's instance id is corrected (a fresh uuid the worker mints at boot, refreshed in memory only). * fix(pa-daemon): drop the unused async from the spawn-record witness harness (clippy -D warnings, gate_1790895904) * fix(pa-daemon): the write probe drains per oracle root; the unused unsynced persist helper retires The Bugbot pair on 264a5d5 (descriptor.rs): The medium race: atomic_write_probe::take() drained the whole process-wide record, so a parallel oracle (cargo runs the crate tests in parallel) could steal another test's writes and fail its durability assertion even when the writer was correct. take_under(root) drains only the records under the caller's own root - each oracle's per-test uuid tempdir descriptor path or directory - leaving every other test's records in place; the oracles keep their served-path assertions. The low unused export: persist_worker_unsynced was a new pub entry point advertising the fresh-create durability contract, but production launch code dispatches on TempSync through spawn_worker_process -> persist_worker_at; only tests called the helper. It is deleted, and its two test callers write the spawn record through persist_worker_at directly - persist_worker stays the only pub persist entry point. * chore: retrigger CI - shard 5/8 hit a pa-cli TUI settle timeout (the inline auth panel, 60ms window) on a test this lane does not touch; main is green at the merged tip a0c1315 * fix(pa-daemon): the launch oracles pin their own probe budget; the durability tests move to their module The bot pair on b13aabe, plus the review follow-ups: The budget seam: the spawn-record oracles forced their 1 ms probe budget through the process-wide PA_DAEMON_WORKER_CONNECT_TIMEOUT_MS, racing every parallel test's deadline reads (the env var is one value for the whole test binary — one test's override is another's stalled launch). Supervisor now carries a per-supervisor budget override the launch paths consult (connect_deadline): None rides the env seam unchanged, a pinned budget keeps an oracle's probe immediate and isolated. The oracles pin 1 ms on their witness supervisor; no test mutates the env var anymore. The module split: the spawn-record oracles (relaunch synced, fresh create unsynced, registration no-write) move from handshake_tests.rs to spawn_record_tests.rs — the handshake module keeps its channel boundary oracles, the durability oracles live beside their concern. The relaunch descriptor's probe socket is the per-test tempdir's own path (a leftover listener on the old hardcoded /tmp socket could defeat the expected probe failure). The comment discipline: the adoption registration-skip comment and the touched test docs describe the current contract only (the durability class split, the in-memory registration refresh) — no deleted-write history, no review-finding narration. * fix(pa-daemon): drop the leftover split-history sentence from the handshake module doc
The shared-key change (PrimeIntellect-ai#3233 + the follow-up sweep) deduped the 8 per-shard entries into one per ref, but every PR wave still saves its own ~500 MB PR-ref copy of that entry - and PR-ref shard entries are the eviction pressure that colded the darwin build cache (restored at 19:32Z, gone by 20:17Z right after PR PrimeIntellect-ai#3157's shard saves; the repo sits over its 10 GB Actions-cache quota and the fleet holds ~30 open PRs, so the PR class alone can oversubscribe it). save-if limits the write to the push wave: PR and merge-queue legs restore - the env-hash restore key (prefix + shared-key + OS-arch + env-hash, verified from rust-cache's config.ts/restore.ts at the pinned SHA) falls back to the push wave's entry - and save nothing. PR refs stop contributing shard entries entirely; the release-build caches stop being eviction victims.
…ellect-ai#3004) * pa-tui: session_ui.rs split 10/14 - the bash concern moves out of src/session_ui.rs (#2928) 481b2f28553cmerge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * skills/prime-intellect: sync vendored sandbox docs to the VM-only surface (TS #2456 doc half) (#2751) a4e997e2e803merge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * fix(pa-cli): remove the duplicated restore_dock_focus initializer the #2751 squash double-applied The #2751 squash (1a9fd16b9) landed the heal rider line onto a tip that already carried the identical line from #2925 (e6e7a26e4) - the squash applied the stale pre-fold diff, duplicating the field (E0062). This restores the fixture to the parent 84dbb51e0 state (exactly one field). The label rider and the docs in the same squash are intended and stay. * pa-daemon: agent_engine.rs split 7/11 - the SessionEngine trait impl moves out whole (#2926) 2b07a22bd1d3merge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * pa-core + runtime: the harness-digest family - IDF-ranked digest/search, state-fingerprint staleness, newest-only digest contexts, validated kernel harness writes (TS #2392/#2400/#2394/#2463 parity) (#2750) bff9fa6ff122merge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * fix(pa-cli): the kitty handoff e2e fixture initializes restore_dock_focus (#2927) 962ff3097575merge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * pa-tui: session_ui.rs split 7/14 - the settings concern moves out of src/session_ui.rs (#2930) fd71eaf2dfeamerge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * pa-tui: session_ui.rs split 6/14 - the model-picker concern moves out of src/session_ui.rs (#2929) 2038abcf5754merge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * pa-daemon/pa-cli: ACP model and effort pickers - configOptions at session/new, session/set_config_option, config_option_update (TS #2455) (#2758) fd977cb13ee6merge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * perf(pa-core): consolidate auth-lock reads - 36 lock cycles per first turn to 2, settings mutex closes the unmasked stall class (#2932) * perf(pa-core): consolidate auth-document reads through a validated cache * perf(pa-core): serialize same-process settings-lock holders (the #2915 pattern) The auth read-through cache on this lane unmasks a pre-existing stall: two worker threads racing the same settings.json pay the full TS 10x20ms retry sleep against each other (strace-verified: mkdir attempts 11us apart, the loser clock_nanosleeps the full 20ms; the paired census shows same-process overlapping settings acquisitions 2 on the base and 5 with the auth cache, sleep20 1 vs 2, and the timing legs pay a ~20ms-class stall on 3/6 fresh turns vs 0/6 base). The auth-lock cycles 150-300us same-process serialization was pacing the threads apart by accident; that masking is not a mechanism to keep. TS runs its synchronous settings lock single-threaded, so same-process settings contention is a Rust-port artifact, the exact class #2915 ruled on for the auth lock: a process-local mutex keyed by the document path serializes same-process callers for the microseconds the small read/modify/write holds. The file protocol, staleness judgment, and retry semantics are untouched: a foreign holder (another process) still surfaces WouldBlock and still takes the 10x20ms retry. The mutex is a leaf (the locked section performs only the document's own filesystem operations plus the caller's update callback; no settings callback re-enters with_lock - every callback is a pure JSON transform), and poisoning is recovered because the file protocol is the correctness mechanism. --------- Co-authored-by: perf-auth-lock-fast <hillclimb@prime-intellect.ai> * perf(pa-daemon): zero-copy worker response path - routed msgs -17%, attach -22%, worker RSS -20% (#2935) * perf(pa-daemon): zero-copy worker response handoff - serialize the line from the borrowed trees, write the frame without re-buffering the payload * fmt(pa-types): the segments test write_frame call in the form CI rustfmt wants * fmt(pa-daemon): the response-path call forms CI rustfmt wants (VM cargo fmt at the exact head) * fix(pa-daemon): restore the response_line TS-key-order test the new-test insert orphaned (clippy empty_line_after_doc_comments was the symptom) * fmt(pa-daemon): the restored test doc comment indent * fmt(pa-daemon): single trailing newline at file end --------- Co-authored-by: wc <wc@fleet.local> * pa-daemon: agent_engine.rs split 6/11 - the Turn types move out of src/agent_engine.rs (#2931) b2ca4deea5afmerge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * perf(pa-daemon): batch the queue-checkpoint journal pair - 4 syncs per warm turn to 2, crash window strictly narrowed (#2936) * perf(pa-daemon): batch the queue-checkpoint journal pair into one durable append The queue checkpoint (prompt/steer/follow-up admission, turn settle, queue mutations) appends two records to the worker recovery journal - the queue snapshot and the busy/operation verdict - as two separate open+write+fsync cycles, paying two journal flushes per checkpoint. Both records describe one atomic checkpoint, and the busy verdict must never publish over a snapshot that did not persist, so the pair can ride ONE open+write+fsync: the batch is all-or-nothing durable, the on-disk line order matches the sequential form exactly (snapshot first, then the verdict), and an unchanged verdict keeps appending the snapshot alone. Measured on the warm-turn admission path (the wave-5 warm-durable-append decomposition): the two journal fsyncs sit inside the TUI-ack-to-user-row phase together with the session append's fdatasync; batching removes one of the three durable syncs per warm turn without weakening any durability guarantee (the session append's per-row fdatasync is untouched). * test: rustfmt the batched-checkpoint test call sites (gate fmt finding) * fix(pa-tui): the exit watchdog holds fire while the flush drains - healthy slow drains no longer truncate scrollback, TS-convergent (#2937) * perf(pa-tui): the exit guard holds its force-quit while the exit path drains - slow terminals keep the whole scrollback flush On a terminal that consumes the exit flush slowly (a laggy ssh at ~0.5-2MB/s), the flush of a large transcript outlasts the 1500ms FORCE_QUIT_AFTER_MS deadline that arms at the second Ctrl+C, and the watchdog fires mid-flush: strace shows its restore writes winning the pty FIFO race at a flush-chunk boundary, exit_group(0) landing while the writer still holds ~64-82% of the transcript (40k rows: 8.74MB flush truncated to 1.5-3.1MB), 'shutdown stalled; forced exit.' printing on a healthy drain, and the restore bytes queueing mid-stream behind the flushed rows. TS has no watchdog at all (its handleCtrlC second press runs the async shutdown, and slow writes simply wait), so both the message and the truncation are port-only. The guard becomes drain-aware: the flush writer reports progress per completed 32KiB chunk (view.rs FlushSink), the release tail and the resume hint report theirs, and the watchdog holds its fire while progress landed within EXIT_PROGRESS_GRACE_MS (500ms) - the hard 1500ms ceiling stays for the silent case (the wedged loop the guard was built for). Flush chunks shrink 256KiB -> 32KiB so a drain of at least ~65KB/s completes chunks inside the grace window; the flush byte stream is unchanged (the exit-flush lane's byte-identity oracle). The truncated scrollback contract is restored on slow drains: the flush completes byte-identically, the release tail lands after the last row, and the message prints only for a genuinely stalled drain. The exit-guard unit tests grow the hold/fire decision table; a new real-pty e2e (pa-cli slow_drain_exit_guard_e2e, the kitty-release harness pattern) drives the real chat surface over a paced pty master and asserts both sides: a draining terminal flushes the whole transcript with no forced exit, and a stalled drain still fires. Rider (disclosed): kitty_release_handoff_e2e grows the restore_dock_focus field the #2916 squash dropped from its fold-time heal - the tip's pa-cli test target does not compile without it. * test(pa-cli): the slow-drain e2e asserts the forced fire structurally The re-executed test binary's libtest harness captures stderr per test, so the watchdog's 'shutdown stalled' line never reaches the pty in the harness child (the real binary writes it to fd 2 - the lane's VM bench legs assert it there). The stalled-drain leg instead asserts the forced exit structurally: the forced restore's own alt-screen leave lands on top of the exit path's (a clean exit leaves it exactly once), the flush never reaches the transcript tail (one copy of the last user row, the startup viewport's), and the process dies with the guard's exit code inside the stall window. Harness needles use the user-message rows (assistant rows carry per-word SGR spans) and the post-exit drain reads the pty's kernel-held bytes before asserting. * fmt: the slow-drain e2e needles and the watchdog's progress read * clippy: doc backticks + checked Duration subtraction in the guard tests; the e2e's needle check takes the direct is_none --------- Co-authored-by: perf-slowdrain-exitguard-fast <lane@hillclimb.local> * perf(pa-core): consolidate settings-lock reads - 32 lock cycles per first turn to 2 (#2941) * pa-ai/pa-core/pa-cli/pa-tui: grok-4.7 on every serving surface (TS #2505) + Claude Code 2.1.281 + Anthropic subscription ban-risk warning (TS #2645) + one owner for the Prime team header, retry failed !command credentials (TS #2497) (#2755) 7373eb471670merge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * test(pa-cli): the interactive_daemon_e2e wedge root-kill - PDEATHSIG + orphan sweep + the 300s headless wall (#2942) dbed1170fa2bmerge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * pa-tui/pa-cli/pa-daemon: session opens wait through a daemon update restart (TS #2391) + the failed-restart hint (TS #2515) (#2763) e7a84e749089merge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * perf(pa-daemon): the all-idle compaction fires like TS and rides the TS compact sync class - journals bounded (#2944) * perf(pa-daemon): settle-tail compact consolidation - the all-idle compaction fires like TS and rides the TS compact sync class The worker recovery journal's all-idle gate ran BEFORE the record insert, so a single-session journal's own busy admission record blocked every settle's compaction: the compact never fired on the dominant shape and the journal grew append-only for the session's lifetime (TS computes the gate POST-insert and compacts at every changed-idle record). The gate now matches TS, bounding the file. Where the compact fires, its temp sync_all was a sync class TS's compact does not pay (TS worker-recovery-journal: writeFileSync + renameSync, no fsync; the command journal's writeFileAtomicSync counterpart does carry fsync). The Finalize seam now encodes the sync class per owner: RetryBusy keeps its fsync (command journal), Synced keeps the Rust-native terminal-compaction journal's belt, and Bare is the TS worker shape - temp write + rename, no fsync. Durability is owned by the append path (the fresh-write class is untouched): the compacted form holds only records the append path already made durable, so a lost compact falls back to the append-only history, which replays identically. * test-only rustfmt of the new test call site (the gate's one fmt finding) * runtime/kernel: vendored-runtime hardening + kernel stderr owner-only (TS #2372/#2423/#2500/#2471/#2478/#2425 parity) (#2744) ea5abd1bbe1bmerge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * pa-tui: session_ui.rs split 11/14 - the prompt submit pipeline moves out of src/session_ui.rs (#2943) 3bafbc007b74merge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * perf(pa-tui): 8-byte packed span records with per-pack style table - scroll retention -7.5MB, byte-identical output (#2939) * perf(pa-tui): denser packed span records - style table + derived offsets (8B/span), byte-exact range expansion * test(pa-tui): rustfmt the exhaustive row-pack range oracle * fix(pa-tui): clippy - if-let style dedup + drop redundant test clones * pa-tui: fix the submit-outlived-by-switch idle-gate race - the turn-end watermark restarts with the mounted stream (#2945) c661290b1b77merge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * pa-daemon: hold spawn-name reservations until admission is durable; collect returns cancelled envelopes for just-deleted targets (TS #2396 + #2388 F4) (#2757) 18aa772bd3b2merge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * pa-ai/pa-core/pa-daemon: codex stale-chain retry after metadata (TS #2374) + safety failures permanent (TS #2472) + quota park until reset with auto-resume (TS #2375) (#2761) dc9892ffbc1emerge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * test(pa-tui): the headless settle bound names its stuck member in 60s - defense-in-depth inside the wedge wall (#2949) The interactive_daemon_e2e exit-gate wedge family is root-killed upstream (#2945: the turn-end watermark restarts with the mounted stream) and the harness carries the 300s wall (#2942). This closes the remaining gap: the headless settle was the run loop's only unbounded wait on the product side — a settle member that never drains parked the run forever with no failure name (TS exits the process at shutdown and lets in-flight work dangle, so the settle has no TS counterpart). The gate's twelve settle members are now snapshotted (HeadlessSettle: settled() is the old gate exactly; blockers() names them), and after the plan completes a stuck member fails the run within HEADLESS_SETTLE_TIMEOUT_MS (60s) with the member named — e.g. 'a turn still active' — instead of waiting out the harness's 300s wall with a generic timeout. Green settles are milliseconds after HeadlessDone (the suite's green wall is ~15s; the last submit's own ack bound is 10s), and terminal runs never arm the bound (HeadlessDone exists only on the headless harness; a live terminal ends the run on exit_requested + the exit guard). Proven end-to-end by the lane's matrix: the wedge converted to a 98.4s attributable red naming the latched member (the bound-only diagnostic arm), and the full candidate stayed clean at 30/30 interleaved trials vs 3/30 wedges at the lane parent (record 20260927-085200-interaction-exit-gate-hang-remediation, bench hillclimb). * perf(pa-daemon/rpc): warm the model registry at RPC session boot - first get_available_models 1170.6ms to 58.9ms (#2953) TS session boot resolves the initial model through refreshAvailableModels (model-resolver.ts), which also fetches the live Prime Inference catalog in the background and caches it on disk; the daemon worker fires the same fire-and-forget refresh from its create path (worker/create.rs). The RPC mode hosts the session in-process with no create command, so nothing warmed the caches: an integration's FIRST get_available_models call paid the whole awaited refresh chain on its response path (measured 812-1296ms on the bench VM; the 15s fetch-timeout worst case on a degraded network) while the same command on the daemon and ACP surfaces answers from the validated snapshot. Mirror the daemon worker boot spawn: the caches warm during the session's first turn, and the first call serves the same snapshot. Write behavior is unchanged: the same cache files, the same write-on-fetch-success conditions, the same cadence (hour-gated catalog refresh, 5-min private-authorization TTL), only started at boot. Co-authored-by: perf-rpc-models-persist <lane@hillclimb> * pa-tui: session_ui.rs split 4/14 - the share concern moves out of src/session_ui.rs (#2922) b0d72b29a700merge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * pa-daemon: agent_engine.rs split 8/11 - the turn-execution impl moves out (#2934) a59d3389dfbamerge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * pa-daemon: supervisor.rs split 5/8 - the worker-lifecycle concern moves out of src/supervisor.rs (#2956) 205f4d0f469cmerge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * pa-tui: session_ui.rs split 8/14 - the sessions concern moves out of src/session_ui.rs (#2957) 7d19e9832120merge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * pa-daemon: supervisor.rs split 6/8 - the signals concern moves out (#2960) a6562bc252efmerge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * pa-daemon: agent_engine.rs split 10/11 - the lifecycle concern moves out of src/agent_engine.rs (#2962) 17d3573c5a58merge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * pa-tui: session_ui.rs split 12/14 - the keys concern moves out of src/session_ui.rs (#2958) bc6b7d82cb0bmerge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * pa-daemon: agent_engine.rs split 11/11 - the facade trim: the last product free fns move out; the file ends as the composition root (#2964) 1fe6a6791030merge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * pa-daemon: supervisor.rs split 8/8 - the facade trim: the notes concern moves out, the test battery re-homes (#2963) 8a5274baa0d9merge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * pa-tui: session_ui.rs split 9/14 - the panels concern moves out of src/session_ui.rs (#2961) 377eda9ded15merge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * pa-tui: session_ui.rs split 13/14 - the apply concern moves out of src/session_ui.rs (#2965) c10a44e407cdmerge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * pa-core: cap kernel host-request cell source at 2 KiB (the TS #2475 port) (#2966) 96f689fc38femerge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * pa-tui: the /model picker resolves by provider, never the first same-id catalog entry (fixes the operator report) (#2967) 24411964739emerge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * pa-tui: session_ui.rs split 14/14 - the facade trim: the file ends as the composition root (#2968) 60cbb4fbb642merge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * perf(pa-core): the oauth refresh leaves the auth lock - fetch under single-flight, hold-sum 396ms to 0.09ms (#2971) An expired stored OAuth credential refreshes its token inside AuthStorageBackend::with_lock: the OAuthIntegration seam is synchronous by contract, so the network round trip runs under the document lock AND under the process mutex that spans the whole critical section, stalling every other same-process auth read and write for the fetch (the RPC cycle_model path measured 194-201ms auth.json.lock holds per switch on the bench VM; the assembly read pays one ~0.2ms cycle, the switch pays the fetch). The TS product holds its own lock across the same await (refreshOAuthTokenWithLock -> withLockAsync), but its single-threaded runtime never blocks other work on it; this engine is threaded, so the port narrows the lock scope instead: load-then-lock. The document loads through the consolidated read arm, the token fetch runs outside every lock behind a per-provider single-flight gate (the in-process serialization TS gets from its single-threaded runtime, with the expiry re-checked under the gate so a second caller never spends a single-use refresh token after the first flight landed), and the write re-enters the same locked read-modify-write protocol - now held only for the re-read, insert, and atomic write, and skipping the write entirely when a peer refreshed while the fetch ran. File protocol, read results, and every resolution outcome are unchanged. * pa-daemon: the supervisor roster broadcasts only on content change (the TS #2481 port P3) (#2974) 054553b8ca12merge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * pa-cli/pa-tui: prime-agent update - the TS->Rust migration path (uninstall TS, install Rust, sessions preserved) (#2981) 739ed7f7d015merge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * perf(pa-core/pa-daemon): a settled RLM child releases its kernel at the settle park - ~27MB reclaimed per settled child, TS #2483 port (#2983) * perf(pa-core/pa-daemon): a settled RLM child releases its kernel at settle - snapshot-flushing stop_kernel, revivable (TS #2483) The rust port of the stale perf PR #2483's inline arm (the supersession analysis: the not-superseded claim - settled children hold a worker and a kernel until parent close; nothing at the tip releases them; the daemon-mode whole-worker passivation stays deferred to the orchestrator): - IpythonKernelProvisioner::stop_kernel (TS stopKernel): shuts the owned kernel down with a final namespace snapshot WITHOUT marking the provisioner disposed; a kernel still starting up is joined first and shut down the same way (the TS managerPromise arm). The stop records a pending-stop gate (TS pendingStop) that the next start_kernel_impl awaits before reading the snapshot back, so a follow-up turn's fresh boot revives the flushed namespace instead of racing the flush; a completed stop awaits instantly and each stop supersedes the previous (a clonable watch receiver: multiple revival waiters gate on it). - The session engine gains stop_kernel_snapshot (the TS stopKernel({snapshot:true}) seam beside dispose_kernel), and the SessionEngine trait gains release_settled_child_kernel (default no-op): the AgentSessionEngine arm evaluates the canPassivateSettledSession gates engine-side - no unsettled descendants (has_unsettled_rlm_work), no registered cron/heartbeat jobs (a worker-wired probe over the shared cron store) - then fires the per-build release probe (a weak provisioner reference, the background-bash-probe adoption pattern, cleared on retire/close). - The turn runner's park arm fires it best-effort when the worker core proves the parent-owned, unattached, unqueued idle state (rlm_depth>0, no attached clients, not compacting, no lane work - the park arm's own construction). The divergence the port discloses: rust children are worker processes (the parent has no in-process reach and the wire is frozen), so the release triggers at the child's own idle park instead of the TS parent's run-settle hook - the same revivability semantics (the next kernel use boots fresh from the flushed snapshot), and the roster/collect surfaces are untouched by design. Tests: the provisioner stop flushes the snapshot and the next ensure revives the namespace (live-kernel, ambient-venv-gated); the park arm's policy matrix (a parent-owned child releases, a root/attached/compacting session stays resident); the engine gates (a registered-jobs probe defers the release, the probe fires otherwise). * test(pa-daemon): the park-arm release test waits on observable readiness (the review advisories) Two BUGBOT test advisories on the first review: the park-arm test's bounded poll used fixed sleeps (a retry-to-green readiness wrapper). The recording engine now notifies on every release fire, so the test waits for the observable readiness - the notification is the pass condition, the bounded timeout is only the failure bound for the positive arm and the absence bound for the gated arms (no fixed sleep ever makes a pass). The commit also lands the VM's cargo fmt output on the touched files (the first commit's hand-written formatting failed the review's fmt pre-flight: the lane builds on the VM only, and the formatted sources must sync back before every commit). * perf(pa-core): provider auth answers once per provider - the #2479 memoization ports, per-model probe -66% (#2973) * perf(pa-core): provider auth answers once per provider and the private PI authorization cache parses once per file identity (TS #2479) The rust port of the four unclaimed mechanisms of the stale perf PR #2479 (the supersession analysis: the rest of that PR's premise landed via #2932's storage read-cache): - get_available's per-model has_configured_auth becomes a per-provider memo: the catalog walks hundreds of models over a few dozen providers and each probe rebuilds the provider's auth-source candidates, while a same-registry probe is stable by construction (&self, no mutation between models). TS getAvailable's authByProvider map. - get_rlm_searchable_models' per-model get_auth_status becomes the same per-provider memo (TS _authenticatedRlmModels' selectableByProvider). - read_private_prime_authorization_cache serves from a process-wide stat-identity snapshot (dev/ino/mtime_ns/len, the TS CatalogFileIdentity) while the file is unchanged; the port builds a fresh registry per resolution touchpoint (the TS session kept one long-lived registry), so the parse would otherwise re-run on every resolution. Only a successful parse bracketed by one identity is pinned, a failed read unpins (retries), and the write path's atomic rename supersedes (new identity). - AuthStorage memoizes auth-source candidates keyed by the hashed material itself (TS authCandidateMemos): reuse skips only the SHA-256 work, env values are deliberately re-read on every call, command values resolve before the memo, and stale checks run against the memoized candidate (candidates are immutable). Tests: the per-provider status memo gates one stale provider across all its models while a second authed provider keeps its models; the private-cache snapshot pins stable parses, re-parses rewrites, and never pins a failed read or resurrects a deleted file; the candidate memos supersede exactly when the hashed material changes (a stale marking from an old value never gates a changed one). * test(pa-core): the stale-provider memo test asserts the tip's stale-aware has_auth The memo regression test claimed a stale-marked provider's models stay in get_available ("stale is only the searchable-set's gate") - but AuthStorage::has_auth is stale-aware at the tip (available_candidate skips candidates matching a marked stale token), so get_available gates the stale provider too, and the tip's get_rlm_searchable_models gates it twice over. The memo preserves exactly those semantics; assert them: the stale provider is gated across all its models from BOTH sets, and a second authed provider keeps its models. Discovered by the full-suite fleet gate (gate_1790546015_945232) - the lane's local legs had not run the test suite; the three other gate reds (kernel_restore_guards x2, tui_prime_login_escape) are SOLO-GREEN on the exact head content (co-scheduling class, the standing family from gate_1790531716). * test(pa-core): behavior-focused wording in the candidate-memo test comments (the review advisory) The BUGBOT history-narration advisory asked for comments that state the current behavior rather than the sequence of edits: the env-change arm now says what the memo key does (a changed value changes the key, so the rebuilt candidate's value fingerprint differs from the stale token's) and the return arm says the marked material's candidate re-serves when its value returns. * pa-cli/docs: the update fetch source flips to the official domain at the rust-to-main merge (#2984) 309dd96b1f96merge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * pa-tui: agents_view.rs split stages 1-2 - the test mass re-homes + the delete concern moves out (#2985) bd221cb5e70amerge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * perf(pa-daemon): saved_session_context reads windowed-first - worker resume CPU -140ms, the parse signature (#2969) * perf(pa-daemon): windowed-first saved_session_context - the create-path model restore reads the windowed store (restored_settings + has_thinking_level) instead of full-parsing the session history; open_windowed's full-open fallback keeps unsupported/malformed files identical; differential oracle keeps the pre-change full-parse reader as the reference across no-boundary/in-window/model-only-before/thinking-only-before/malformed-prefix fixture classes * perf(pa-daemon): address the Bugbot findings on the windowed saved_session_context - comments describe current behavior only, the oracle helper returns the owned TempDir so fixture scratch trees clean up at test scope end --------- Co-authored-by: perf-launch-open-fast <hillclimb@primeintellect.ai> * ci: unify workflows under .github/ + port the vouch gate The staged-copy era ends (operator-authorized workflow-scope push): .github/workflows/ is the one home for workflow files. - ci.yml: the staged windows-cross/windows/deny jobs promoted from ci/workflows/ci.yml as the windows job set (the deny job pinned to the live continuous.yml shape: cargo-deny --all-features --workspace check advisories licenses, the `make deny` mirror); ci/workflows/ deleted entirely (benchmark.yml goes with it - it needed self-hosted `prime-sandbox` runner labels no registered runner carries; the wave stays runnable via `make perf-wave`). - ci.yml + codebase-health.yml: the contributor-trust gate ported from main (mitchellh/vouch/action/check-user@v1, allow-fail): push events always allowed, PR authors must be bot/collaborator/vouched - every job keys on the trust output, so unvouched PRs never bill a minute. The vouched list resolves from the repo default branch's .github/VOUCHED.td (main) - nothing local on this branch. - contribution-gate.yml ported VERBATIM from main: unvouched PRs and issues auto-close (check-pr/check-issue) - the admin-spam killer. - CONTRIBUTING.md ported from main (vouched-contributor policy; the TS-repo-only sections adapted to this branch) + the PR template gains main's vouch line. - Makefile: actionlint lints all five live workflow files; activate-workflows removed (obsolete). Stale staging references in docs/ and the battery scripts made truthful. * pa-core: compact_session.rs split - the tests re-home + the summarization, anchor-selection, and boundary cuts (#2987) f43aebc9c50dmerge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * pa-tui: agents_view.rs split stage 3 - the render concern moves out (#2988) 03a6fcc07793merge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * install: the Rust port takes over the prime-agent keyword - clean TS daemon shutdown, config preserved (#2972) 737e52dc7695merge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * pa-daemon: the scheduling catalog fans out per-worker (the TS port P4) (#2979) 1e78bb715fddmerge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * pa-tui: agents_view.rs split stage 4 - the open + incident concerns move out (#2991) 0ef076a06131merge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * pa-daemon: session_store.rs split - the index, read, write, view, info, tests children (#2990) 7b58b0acb457merge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * pa-tui: agents_view.rs split stage 5 - the data + input concerns move out; the file ends as the composition root (#2992) cadb8b4f33d6merge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * docs: the README becomes the Rust product's own; the port-process docs are removed (#2993) fe891d188ad0merge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * pa-tui: snapshot.rs split stages 1-2 - the test mass re-homes + the tool-fold concern moves out (#2995) eaa4b672f2f8merge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * pa-tui: snapshot.rs split stage 3 - the decoder concern moves out; the file ends as the composition root (#2996) 1564648986edmerge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * pa-daemon: rlm_children.rs split - the composition root (host, lifecycle, usage, registry, tests) (#2997) 4ee722d403b6merge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * pa-tui: interactive.rs split - the tests, onboarding, headless, render, reconnect, run children (#2998) d592a0672d5dmerge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * perf(pa-daemon): share the open's artifacts + skip the depth scan's full parse (cold-open-residual) (#2970) 5b75513ff7fbmerge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * pa-tui: every session-exit route restores the terminal - the kitty-mode leak into the shell is fixed (#3001) 8f84a46233cdmerge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * pa-cli: the family-seeding e2e spawns pin the daemon's session dir (the flash e2e's seeded-family red) (#3003) c54ff2a09a84merge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * pa-tui: undo the condensed activity runs - the collapse mode becomes details mode minus thinking blocks (#2999) a6d8414d818cmerge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * ci+pa-types: the first real windows runs surface tip cfg-hygiene gaps - unix-gate the pa-types sites the cross-check flagged (the #2833 pattern, zero unix behavior change): terminal.rs unix imports + the non-linux OLCUC arm, memory_release trim param, process.rs the redundant unsafe on the safe winapi wrapper; drop dangling pointers to the tip-deleted port-process docs (windows-readiness.md/installer-ci-design.md) from ci.yml/continuous.yml * pa-cli: print_boundary.rs split - the 4 stages: events, compaction_arms, autorefine, tests (#2989) 2292af8f1cefmerge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * pa-tui: bash_view.rs split - under 1,000 lines (#3008) 15d9c1a659efmerge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * pa-tui: auth_panel.rs split - under 1,000 lines (#3009) 8c3061a5db29merge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * pa-daemon+pa-core+pa-cli: the second windows-cross run pins the remaining cross-target lint surface - cfg-gate the unix-only reaping/signal/socket helpers their unix callers prove dead on the cross target, add the # Errors docs the windows stubs never carried, and fix the two doc/code-order nits (the #2833 pattern, zero unix behavior change) - pa-daemon: boot_reap gates the reaping census family (is_product_binary, is_worker_argv, supervisor_argv_names_socket, normalize_socket_spelling - its doc now states the darwin truth the gate keeps, all(unix, not(linux)) on the proc-environ stub, dead-code-allowed ReapKind::Supervisor whose one constructor is linux), rpc/mod.rs gates spawn_signal_handlers' call+fn and its SIGTERM/SIGHUP exit consts, signal_drain.rs gates the unix signal imports and recv_opt, socket.rs gates unlink_stale_socket and the LOCK_* lease consts + documents the windows no-op stub, accept_loop.rs gates the four unix socket-pair stand-in tests, signals_shutdown.rs gates begin_signal_drain (its only lib caller is the unix drain loop) + the two drain-state tests, supervisor.rs splits the unix-only PrepareState import, the venv/download/installer unix-test helpers and the supervisor/roster test imports carry their platform truth, session_store/info.rs marks the windows twin's unused identity param - pa-core: perms.rs/shell.rs give the cfg(windows)/cfg(not(unix)) stubs the # Errors sections their unix siblings have + backtick ProgramFiles/SystemRoot + hoist the windows gh-command consts above the statements, export_share.rs hoists CREATE_NO_WINDOW - pa-types: the windows is_process_alive stubs get their # Errors sections, STILL_ACTIVE backticks, swallow_sigint and the non-linux STDIN_TTY_PATH arm take their platform cfgs - pa-cli: the DaemonProbe probe-result enum waives large_enum_variant (the windows pipe client's transport state crosses the budget; the probe value is a rare one-shot) - pa-models: refresh_compat's snapshot metadata binds only its unix mode reader uses cargo clippy --locked --workspace --target x86_64-pc-windows-gnu --all-targets -- -D warnings: clean; native clippy -D warnings: clean; fmt: clean * pa-tui: heartbeats_picker.rs split - under 1,000 lines (#3011) 13849ce9138cmerge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * pa-tui: the queue groups internal prompts in the summary; the edit surface is user-origin only (#3012) b19ffd2ff84fmerge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * docs: docs/ ends empty per the operator's ruling; the README's install detail goes with it (#3007) d89e319660c4merge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * pa-tui: the terminal-state differential - every armed mode restores on every exit route (#3002) aba71e8b491dmerge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * pa-daemon: the worker test mass splits by family - under 1,000 lines (#3014) f011aaac54c7merge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * pa-tui/pa-ai/pa-agent: /tier command + Default service tier settings row + footer badge + completions service_tier forwarding + proxy serviceTier (TS #2144 half + #2491 half) (#2735) e8cdef33d443merge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * pa-core/pa-daemon/pa-types: the Windows platform gaps close - the tilde arm, the win32 path resolution, the TS launch budgets (#3016) 438012e04c27merge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * pa-tui: the agents_view test mass splits by family - under 1,000 lines (#3018) 7c488aca640bmerge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * fix(pa-daemon): the compacting admission gate - a racing turn defers through the compaction window, the parked work delivers after it (#3021) b15dc777d141merge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * perf(pa-core): cut the refine pre-LLM full-entries snapshot clone (-9.5ms / -30.4% pre-LLM at 10MiB) (#3013) f9c343f8d7a5merge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge); optional lane gate evidence: gate_1790621761_1065006 GREEN. * perf(tui): slice the kitty-probe reader-lock window to 10ms polls - early typing delivers while the probe listens (#3010) 07be8ffbcc74merge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * install: the installer bootstraps its own Python via uv; the output flow; the bash-3.2 parse fix; the test suite moves lane-side (#3017) a2c94944cc40merge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * perf(pa-core): refine pushes its appended rows instead of rebuilding the context (-25.4ms / -35% at 10MiB; TS-parity restoring) (#3020) f3a9757dd30dmerge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * fix(pa-core): the digest terms' window direction - TS slice(-4) keeps the NEWEST four texts, not truncate(4)'s oldest four (#3019) f310e1c9bc42merge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * test(pa-core): the compact digest-capture placement oracles - the ENTER capture is the TS-parity shield (byte-identity across placements in frozen windows; the racing class) (#3006) ae542c6a56bcmerge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * pa-core/pa-agent/pa-daemon/pa-tui: settings.imageModel routes image turns to a configured image model + the [python-skills-unavailable] notice (TS #2453 + #2381) (#2741) 5098db88b8f8merge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * install: the TS daemon always stops on install - busy daemons get the forced shutdown (#3028) 78b0b58de028merge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * pa-core: per-call-site durability for the shared atomic_write - the TS WriteFileAtomicOptions shape (#3023) 2acae69edf1fmerge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * docs: the last docs/ file goes - the terminal-leak audit repo copy (the ruling final straggler) (#3026) 0d72ff3d77d0merge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * perf(pa-daemon): flush the RPC compaction_start frame before the pre-summarizer CPU span (client-visibility: +48.8ms p50 -> +0.143ms, 341x) (#3024) ddf75643ab00merge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge); optional lane gate evidence: gate_1790634676_1065157 GREEN. * pa-tui: agents_view_forest.rs split - under 1,000 lines (#3040) 741be982e655merge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * privacy: scrub personal machine paths and identity data from docs + fixtures (the security-scan lane) (#3046) ba9ea3b7eb5amerge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * pa-tui: the subagent surfaces - one running count on the prompt bar, one dropdown in the agents view (#3031) b1ee386c0ddemerge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * ci: the windows runtime triage workflow - on-demand Windows battery runs on any ref (#3022) 425b1751cb67merge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * pa-core: manager.rs split - under 1,000 lines (#3039) 5220b3c2f589merge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * clippy: pa-cli is pedantic-clean (#3050) f2fdb439d3demerge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * clippy: pa-daemon is pedantic-clean (#3029) c233c84b62dcmerge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * skills: the parity quick-fixes (#3058) 4de8f9c2acc9merge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * pa-tui: info_commands.rs split - under 1,000 lines (#3057) febdcffc7cbbmerge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * pa-daemon: fold 3's auto-merge doubled the gated PrepareState import (both sides added #[cfg(unix)] use crate::update_prepare::PrepareState at different spots and git kept both) - keep the commented one, drop the bare twin (E0252) * pa-core: agent_traces.rs split - under 1,000 lines (#3061) 5518a73acaf0merge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * pa-tui: markdown.rs split - under 1,000 lines (#3066) f23b3d05c93dmerge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * pa-cli: interactive_mode.rs split - under 1,000 lines (#3055) b559cd018f80merge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * pa-tui: the settings page pass - spacing, arrow value-cycling, the tab keys, the white selection, the fullscreen retirement, two regressions (#3051) 286006389509merge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * pa-daemon: the folded signals_shutdown imports PrepareState from super ungated while the fold's parent keeps the re-export behind #[cfg(unix)] - E0432 on both windows targets; gate the import to its one unix use (the #2833 pattern, zero behavior change) * skills/runtime: the generic mcp skill + the discovery/tooling surface (#3063) 563c576e8123merge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * perf(pa-core): the recurring capture-freshness memo - skip the redundant kernel re-dump while the namespace provably cannot have changed (#3037) 09043ae3b2b4merge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * pa-core: telemetry.rs split - under 1,000 lines (#3074) 2aeda90ba25bmerge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * pa-tui: model_picker/mod.rs split - under 1,000 lines (#3070) 867dfa067633merge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * pa-core: session_engine/mod.rs split - under 1,000 lines (#3062) fe1ee606180bmerge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * pa-core: the compact_session test mass splits by family - under 1,000 lines (#3073) e27835fee7f4merge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * pa-daemon: rlm_ledger.rs split - under 1,000 lines (#3078) 758ea09ebc34merge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * pa-core: auth/manager.rs split - under 1,000 lines (#3071) 36a261afd673merge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * pa-tui: queued.rs split - under 1,000 lines (#3079) 91873baa42cbmerge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * pa-daemon: the promoted windows-cross finally reaches the merged tip surface - the tip's own ci.yml never ran these jobs, so its signals_shutdown kept ClientRouting in the ungated import list (its only use sits in the unix begin_signal_drain arm) and the fold carried my #[cfg(unix)] gates onto the four accept-loop tests whose tip versions are portable duplex tests - gate the ClientRouting import, un-gate the four tests to the tip's shape (the #2833 pattern, zero behavior change) * pa-tui: ctrl+s stashes and restores the prompt draft (#3072) 443ab531022amerge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * pa-core: venv.rs split - under 1,000 lines (#3077) d6ae9a7770e9merge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * comments: the CI-unification surfaces drop the migration-era staging narration - the ci.yml header, the Makefile perf-wave gate, and the two perf-wave script headers describe current behavior only (one home for workflows; the perf wave is command-line-only because a hosted run would need self-hosted prime-sandbox labels no registered runner carries); the historical record stays in the docs (bugbot 65dfc19a) * pa-tui: sequence_guard.rs split - under 1,000 lines (#3083) 430d6141a0ccmerge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * pa-core: session_engine/request_timing.rs split - under 1,000 lines (#3084) fdd1f5bbfbcamerge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * pa-tui: the session_ui composition root trims under 1,000 lines (#3064) b068d7a48a13merge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * pa-tui: chat.rs split - under 1,000 lines (#3081) 65525952ae25merge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * pa-tui: daemon_client.rs split - under 1,000 lines (#3086) ddef55111f26merge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * make: the actionlint target lints every live workflow file - add .github/workflows/windows-runtime-triage.yml to the invocation (the #3022 on-demand windows triage workflow arrived with the fold; it pre-verifies LINT-CLEAN under actionlint 1.7.12, so 'lints every workflow' is true again) (macroscope d2cf164e) * pa-daemon: supervisor_e2e.rs splits by test family - under 1,000 lines (#3067) 81b928e55a00merge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * pa-tui: view.rs split - the 3,888-line god-file ends as an 841-line composition root + 5 concern children (#3088) 0ff470e08385merge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * pa-daemon: the agent_engine test mass splits by family - under 1,000 lines (#3059) 9cabd79136demerge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * runtime: blocking usage beyond the auto-bg threshold degrades to a handle - bash awaits and python execution alike (#3076) b17703d1425cmerge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * pa-tui: chrome.rs split - under 1,000 lines (#3087) 7af1b5840f32merge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * pa-ai/ci: the TS-parity sweep-2 quick-fixes - Gemma 4 thinkingLevel on Vertex (TS #2946), Azure store:false (TS #2948), the staleness gate live (TS #2567) (#3068) b5cf6ec2b29cmerge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * pa-tui: tree_list.rs split - under 1,000 lines (#3091) d54b591b12a2merge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * pa-tui: autocomplete.rs split - under 1,000 lines (#3092) 6a90ccf77948merge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * pa-tui: keybindings.rs split - under 1,000 lines (#3090) 337d2efcc712merge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * pa-tui: mcp_view.rs split - under 1,000 lines (#3094) 500fcd9581a9merge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * pa-core: the fold-5 tip restructured the venv probe surface and its windows-cross gate pair went inconsistent - the venv.rs test import list carried clear_in_process_probe_memo_for_tests and installed_package_dir at cfg(test) while their defs/callers sit at cfg(all(test, unix)) - E0432 + unused-import on the windows cross target (tip debt the promoted job surfaces: the tip's own ci.yml never runs it); split both names to the matching all(test, unix) gate (the #2833 pattern, zero behavior change). Pre-verified on-box: cargo check+clippy --locked --workspace --target x86_64-pc-windows-gnu --all-targets -D warnings BOTH GREEN * pa-daemon: worker/turn_stream_tests.rs split - under 1,000 lines (#3095) 2b9778a0dc6emerge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * clippy: pa-core is pedantic-clean (#3093) 273b29234448merge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * pa-core: the goal timer counts from the goal creation; the goal continuation fires once per boundary (#3048) f116a6b5a849merge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * pa-tui: the termios + process-tree exit audit - no raw-mode/flow/orphan/fd leaks (#3089) 13683dba140dmerge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * pa-daemon: agent_engine/turn.rs split - under 1,000 lines (#3102) c8af2dd96ba0merge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * pa-core: the per-model layer trims to the minimal format reference - the empty block gone (#3106) bd3b03f57b6bmerge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * pa-daemon: scheduled_jobs.rs split - under 1,000 lines (#3105) 67ea4b6ff782merge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * pa-tui/pa-core: the image-heavy session-open fix - the render-path skip + the measured fast paths (#3098) 3325e22b396emerge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * pa-tui: settings_menu.rs split - under 1,000 lines (#3108) b789ea8dc265merge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * clippy: the small crates are pedantic-clean (pa-ai, pa-agent, pa-types, pa-telemetry, pa-models) (#3110) 25ab57d2829fmerge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * pa-tui: the hover + click affordances - the dock groups, the hints, the agents-view rows, the dropdowns; every clickable thing shows it (#3109) 0f871da2e8a1merge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * install/pa-daemon: the takeover completes - the rust daemon stops on update; the schema-family match; the no-auto-resume contract (#3107) 29645e1b9bb7merge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * pa-daemon: supervisor_restart_e2e.rs splits by test family - under 1,000 lines (#3114) 9434853a18e7merge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * pa-telemetry: the #2117 tracking intent lands clean - the modular catalog, the accurate firing, the edge cases pinned (#3100) 942f003642b0merge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * pa-ai: stream_failure.rs split - under 1,000 lines (#3116) 4b7300a6147dmerge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * pa-core: engine.rs split - under 1,000 lines (#3118) 8b6dda11865dmerge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * pa-daemon: the handshake channel stays private until the auth answer installs it - the launch-storm connect-budget wedge closes (#3075) 80e9fe60091emerge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * pa-core: harness_digest.rs split - under 1,000 lines (#3119) c806bee6fe79merge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * pa-tui/pa-daemon: the bare /skill: invocation guards - the TUI hint + the empty-args notice + the engine floor (#3113) 2d72de5cef32merge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * pa-core: agent_messaging.rs split - under 1,000 lines (#3120) 691e0785cca3merge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * perf(pa-tui): the cross-view layout handoff - reuse the visible-window packs on the agents->chat re-entry (-100.1ms / -35.7% at canon) (#3103) cd55ae21aefemerge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * pa-daemon: session_stats.rs split - under 1,000 lines (#3122) af8138eaee3amerge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * pa-core: models/registry.rs split - under 1,000 lines (#3124) 4c4d622bcb8dmerge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * pa-daemon: compaction_arms.rs split - under 1,000 lines (#3125) 16d6c239ae3amerge bar v23: mandatory CI green on the exact head + zero unresolved bot threads + head unmoved (verified by fleet_pipeline.fleet_merge). * perf(pa-ai): append streamed Responses mirror text and reasoning-details fragments in place instead of re-copying per delta (#3035) * perf(pa-core): scan only new bytes for newlines - linear line framing (TS #2781 twin) (#3042) * test(pa-core): the multi-MiB protocol-line timing tests for the kernel reader and the extension LineDecoder (TS #2781 twin) A 4 MiB decoder line fed in 1 KiB chunks and a 31 MiB blank kernel line read through the 64 KiB pipe reader must complete under the computed bounds: while every chunk rescans the buffered prefix, they scan >= 8.6 GB and >= 8 GB and overrun them. The blank line never reaches parse_event, so the bound separates pure scanning from the quadratic rescan. Failing runs report their real duration in the assertion message. * perf(pa-core): the kernel protocol reader and the extension LineDecoder scan each byte once - linear line framing (TS #2781 twin) Both readers keep only the newline-free tail of earlier chunks, so the newline scan resumes at the old buffer length instead of restarting at zero: while one line accumulates, every chunk rescanned bytes already known to hold no newline. The decoder also consumes lines by offset and drains once per feed instead of one O(remaining) drain per line. Measured (8-core sandbox, prebuilt debug test binaries, medians of 3): a 4 MiB decoder line in 1 KiB feeds 14.27s -> 0.014s (~1000x); a 31 MiB blank kernel line 13.85s -> 0.65s (the ~13.2s quadratic rescan eliminated; the remainder is the one-pass scan plus the UTF-8 and trim checks the blank line still pays). Frame handling is byte-identical: same oversize checks and order, CR and blank-line rules, invalid-UTF-8 endings, and post-error buffers. * perf(pa-daemon): mint session entry ids against the by_id index instead of rebuilding an id map per append (#3053) append_entry and persist_entry_at rebuilt a HashMap of every entry id on each call just to check the new id for collisions. The store's by_id index already holds the same ids, so check against it: appends drop from O(n) to O(1). The fork and branch paths in session_tree reuse by_id the same way instead of keeping their own id copies. * perf(pa-ai): Anthropic stream edits the output blocks directly instead of copying a second block list per delta (#3056) * pa-ai(anthropic): mutate output.content directly instead of copying a duplicate block list per delta * pa-ai(anthropic): trim the stream snapshot test per review (struct-update expected values, one-line terminal assert) * pa-ai(anthropic): state why the stream snapshot test allows too_many_lines * pa-cli/pa-daemon: daemon-attached ACP honors the CLI session flags (#3096) The daemon-attached ACP path dropped --append-system-prompt, --system…
…(fix the millisecond-tick race) (PrimeIntellect-ai#3299)
…lect-ai#3410) * forbid no-op tool calls and sanction text-only turns in the prompt An agent repeatedly ended acknowledgment turns with a bare `pass` Python cell; five user corrections relapsed every time. The done-state rule only covers the frame where the agent already knows it is finished - acks (heartbeat acks, checker confirmations, idle waits) never classify as done, and nothing in the prompt said a turn may end without a tool call, so the model invented a minimal no-op tool call to end the turn. Add two mandatory-rule bullets to the usage layer: text-only turns are sanctioned for messages that need no action, and placeholder/no-op tool calls are forbidden. Regenerate the golden prompt snapshot and pin both bullets in prompt_guards. * drop the duplicate magic-string prompt pin flagged in review The usage-layer sentence test restated static layer text; the golden snapshot already pinned the assembled prompt at the time, and main has since removed the golden entirely (exact wording coverage intentionally relinquished in PrimeIntellect-ai#3433), leaving no convention for static-sentence pins. * usage: the text-only turn rule defers to the silent harness-notice rule --------- Co-authored-by: Sebastian <sebastian@primeintellect.ai>
… (started, heartbeat, elapsed-on-abort) (PrimeIntellect-ai#3689) * feat(trace): tool-call lifecycle rows in the session trace A stalled tool call left the session trace blank between issuance and its result row: the Oscar incident showed a 13-minute recursive grep with nothing visible while it ran, and the abort showed no elapsed time. - tool_started row at call issuance (call id, tool name, the command args), written by the session-engine persistence listener - tool_progress heartbeat row on a bounded cadence (default 60s tick, configurable via AgentOptions::tool_progress) while a call runs - aborted/killed completions carry {status, durationMs} details so the trace shows how long the call ran * style: cargo fmt * feat(trace): extract heartbeat and drain helpers for clippy bounds * fix(trace): abort the heartbeat on every exit path A cancelled or panicking tool-call frame dropped the heartbeat JoinHandle without aborting it, detaching the unbounded tick task: it kept emitting ToolExecutionProgress (and pinning the event sink) after the run that owned it was gone. A Drop guard now aborts the task on every exit path; the explicit stop() keeps the normal-path ordering. Pinned by agent_loop::tool_call::tests::cancelling_the_call_frame_stops_ the_heartbeat (mutation-checked: removing the Drop impl fails it). * test(trace): bound the heartbeat test's waits and settle the abort race The first-tick poll was unbounded (a broken heartbeat hung the suite instead of failing) and the post-abort sample raced abort's async drop. Bounded the wait with a 2s timeout, and settle after awaiting the cancelled frame (guard Drop guaranteed) with a 50ms absorb window before the 200ms quiet-window assertion. 10/10 green locally; Drop-impl-removal mutation still fails it. * test(trace): bound the abort test's entered poll with a timeout
…ag perf; pid-scope the bash journal polls; unbound the harness lock budget (PrimeIntellect-ai#3707)
…attach fallback warning (PrimeIntellect-ai#3714) * test: pin the marker-turn tail and the paged roster settle (red) * pa-perf: short marker replies; roster settles on loaded + unloaded
…aused runs apart in the TUI (PrimeIntellect-ai#3713) * factory: deliver run milestone notices to the owning session; count paused runs apart in the TUI The kernel factory executor sends every run milestone (paused, failed, finished, budget/max-* pauses) as a factory.progress host request, but no Rust handler existed, so the kernel swallowed the error and the owning session never heard about a paused or failed run. Register a factory.progress handler on the existing kernel-notice seam (the bash.completed steering delivery) that admits a "[factory-progress run:<id>] <kind>: <detail>" row. resume() now re-arms the paused notice, so a second escalate pause after a resume notifies too. The TUI activity dock and the agents view counted paused factory runs as running. One is_paused predicate now splits the live runs: the collapsed dock shows the running count plus an amber paused cluster, and the agents view line appends the paused count. is_live keeps its meaning for the page actions and the live-run guard. * prompt guard: factory.progress is host-internal, like the bash notice pair
…ce across transcript replaces (PrimeIntellect-ai#3698) * tui: paint no escape sequences or control characters from content Every painted line passes markdown::to_ratatui_line. It stripped only the OSC 133 and OSC 8 markers, so any other escape sequence or control character in assistant text, tool output or status rows reached ratatui cells. ratatui counts each such char as one column, width::str_width counts it as zero, and the terminal executes it. An ESC[2J (or ESC c) in message text erased the whole alternate screen while the differential paint believed it was drawn, so the pane stayed blank and only changed cells came back, with characters missing inside words. Backspace, VT, CR and BEL in tool output shifted or overwrote cells the same way. normalize_terminal_output (the TS applyLineResets port, run on every painted span) now drops escape sequences through the shared width::escape_len grammar and the remaining C0/C1 controls, so the painted cells agree with str_width. * tui: blank both cells of a multi-codepoint wide cluster before painting it Terminals disagree on the width of a VS16 emoji (U+26A0 U+FE0F), a ZWJ sequence or a flag. The paint and str_width give them two columns. iTerm2 and vt100 advance one column, so the second cell kept whatever the previous frame showed there: a stale character next to the glyph. The paint backend now writes two spaces and moves back before such a cluster. A terminal that measures two columns paints the same result. * tui: keep a mid-history reader on their entry across a transcript replace /reload, import, tree navigation and fork rebuild the transcript from the tail, and a worker or daemon re-attach rebuilds it from the attach snapshot. Each one reset the window to the tail and jumped a reader who was scrolled up to the live end. Before the replace, the reader's top entry is captured against the window. If it is inside a resident chunk, that chunk's own page request (now kept on the chunk) is replayed while the old rows stay on screen. The replay is validated against the old branch anchor and placed above the rebuilt tail, with the gap row when it no longer joins the tail. If the entry is inside the tail, the view returns to it while the rebuilt tail starts at the same row. When the place is gone (another branch, a tail that moved past it), the view follows the tail as before. The page fetch is shared with the window's page task. * tui: mark the top of the resident rows while an older page loads While an older (or head) page is in flight, the top section above the first entry, which is empty once a transcript has suppressed the splash, holds a "Loading older history..." row styled like the gap row's status row. The stale rows stay rendered below it. The marker clears when the page applies or fails, or when the window is collapsed, rebuilt or cleared. * tui: keep eight transcript chunks resident and prefetch 256 entries ahead The window held three 256-message chunks above the tail and asked for the next page 128 entries before the resident edge. It now keeps eight chunks and starts the page 256 entries ahead, on both sides as before, so long scrolls reach the resident edge less often. The window tests grow their fixtures to still evict. * tui: bound the reader-anchor page by the UI budget and fetch it with the tail The anchor page is awaited on the interactive loop. It used the client's 30 s default plus one retry, and in rebuild_transcript it ran after the tail fetch, so a busy worker doubled the freeze. On the resync paths it also ran outside the attach budget. It is now bounded by UI_REQUEST_TIMEOUT_MS; a late page follows the tail. rebuild_transcript fetches it concurrently with the tail page, since it is validated against the old branch and does not depend on the tail. * tui: anchor a tail reader only when the tail has an older-history anchor A transcript that fits in the tail has no first-row id, so after a navigation to another short branch the None == None match restored the old numeric position in unrelated rows. Without that id the reader now follows the tail. * tui: rejoin the back chunk with a newer page's retry seam * tui: an empty anchor page leaves the reader following the tail restore_reader scrolled to the old chunk-relative entry even when the reloaded chunk page came back empty, so the reader landed on unrelated tail rows. restore_chunk now reports an empty page and the reader follows the tail. * tui: drop the soft hyphen at the paint boundary str_width measures U+00AD as zero columns. iTerm2 and vt100 give it no cell, but glibc wcwidth terminals and pyte give it one, so on those terminals every later cell of the row landed one column right. The hyphen is an invisible break hint: normalize_terminal_output now drops it together with the control characters, so the painted cells agree with str_width on every terminal. * tui: place the cell after an ambiguous-width character explicitly East Asian Ambiguous characters (dashes, curly quotes, ellipsis, arrows, bullets, box drawing) are one column in str_width and ratatui but two in iTerm2 with "ambiguous characters are double-width". ratatui writes adjacent one-column cells without a cursor move, so each such character shifted the rest of the row right and the run wrapped into the next row. After each grapheme whose base character is ambiguous (width_cjk() != width()), the paint backend now moves to the column it accounts for (CHA; the row never changes inside a run). Later cells land in their own column under either setting. * tui: drop the ambiguous-width cursor moves — per-glyph escapes bloat every block-glyph frame
…ed crossterm) (PrimeIntellect-ai#3704) * fix: keep a keystroke that lands in the same poll as a resize (vendored crossterm) * docs: trim the poll-token comments and the test note
…rimeIntellect-ai#3705) A get_messages page held the worker core mutex for an O(session) display walk (full branch(), every display row, anchor scans, settle_cut over all rows) plus an O(session) branch() for the historyLeafId check: ~190 ms per page at 500K messages. - index.rs: each entry gets a ChainLink (parent, depth, skew-binary jump pointer) where by_id is maintained; index_entry / unindex_last / clear_index own both. ancestor_at is O(log N). - view.rs: branch(), the page walks and the membership check share one walk step; the window stop rule is the old branch() condition. Membership is the leaf's ancestor at the entry's depth (branch_contains). - End pages walk back from their anchor; Start pages read forward in doubling chunks. settle_cut runs over a local slice (page, the run its first row continues, up to `limit` rows each side); a call more than a page from its result no longer moves the cut. - last_user_prompt_ms moves to attach (SessionFile::last_user_prompt_ms). Pins: a cfg(test) step counter bounds tail/deep End, deep/head Start and the historyLeafId check on a 120K-entry store (base: 120000 steps each); an equivalence test checks every page boundary against a full-walk reference. Co-authored-by: Seth Karten <32787133+sethkarten@users.noreply.github.com>
Version bump + the .changes/ fragment fold, cut by the release-prepare workflow off the main tip 2efd2d6. Merging this PR ships v0.10.1: the tag act creates the annotated tag at this PR's squash-merge commit, and the tag-triggered release.yml runs the promote gate (the protected release environment). Co-authored-by: release-prepare <41898282+github-actions[bot]@users.noreply.github.com>
…PrimeIntellect-ai#3679) * ACP: classify transport failures in prompt error responses The worker's failed-turn text reaches the ACP prompt handler as a bare string flattened into internal_error details, so a host cannot programmatically separate retryable model-transport failures from harness bugs. The failure now also runs through the PrimeIntellect-ai#2117 classifier (pa-core session_engine::error_classify) and the reply data carries its typed category and retryable verdict as {kind, retryable} alongside the existing details (the nano-rlm PrimeIntellect-ai#200 kind/retryable contract; retryable is advisory). * ACP: the PrimeIntellect-ai#200 host contract — kind model_transport only for the exhausted connection family, category beside it, retryable gated to transport; fixed pa-ai transport disclosures classify; every failed-prompt arm classified * ACP: a 408 keeps its provider category (HTTP-status classifications are not the connection family); the roster-read and publish-failure arms carry the typed contract too
…rimeIntellect-ai#3511) * Pin the async turn contract: 60s commands go to background bash, turns end on notification wakes The async-discipline baseline (hosted run xdhf6w72abxj8xjuvb7ldzzs) shows the D3 turn-held/sleep/poll violation rate at 0.85: agents slept 97-157s through turns and held turns 166s while builds ran inline, against the grader's 60s inline-span contract. The usage layer's two overlapping bash/await bullets now carry the contract explicitly: a command expected to run longer than 60 seconds is never inline-awaited; the turn ends with a short text reply when long work runs or nothing actionable remains; await stays bounded to immediately-needed results; and bash completion notifications, subagent replies, and heartbeats are named as the trusted wake mechanism. Guarded by usage_layer_pins_the_async_turn_contract (mutation-checked red on the old text). * Scope the async turn contract to notification sessions (review fix) Bugbot (PRRT_kwDOSXZbXs6rU49z): the static-layer turn-end rule was unscoped, so daemonless sessions — which are told to await commands before ending the turn because nothing wakes them — were also told to end the turn while long work runs. Fixed by the update from main: PrimeIntellect-ai#3523 superseded this PR's static-layer wording with the yield_after runtime plus a daemon-only role line, so the merged usage.md keeps only the conditional daemonless sentence and the poll bullet's collect-on-notice rule. The guard test now pins the contract per session: daemon prompts carry the end-turn-on-[bash-done] contract, daemonless prompts carry the await rules, and an unscoped static turn-end sentence fails the test (mutation-checked red on this PR's old text). * Make the turn-end scope guard sentence-structural (review round 2) Bugbot (PRRT_kwDOSXZbXs6uJGeD): the exact-phrase pin only forbade this PR's old wording; any other unscoped static turn-end sentence stayed green, and a same-bullet mutation slipped past a line-level check. The guard now scans every usage-layer sentence that instructs ending the turn and requires it to mention notifications — catching any phrasing, not one magic string. Bugbot (PRRT_kwDOSXZbXs6uJGeJ): the doc comment also dropped the eval-run narration (baseline id, D3 rate, sleep/hold durations); it states the contract, and the provenance stays in the PR/commit history. Mutation-checked red on the old PR text, on a same-line unscoped rewording, and on a fresh unscoped sentence; 7/7 green otherwise. * Re-pin the async-turn guard on the [bash-done] wake model of main PrimeIntellect-ai#3640 Main e8dc899 (persistent bash() shells, PrimeIntellect-ai#3640) rewrote the daemonless role line: background bash() completions now wake the agent with a queued [bash-done] turn instead of the await-before-turn-end rule, so the guard test's pin on 'await them before ending your turn' failed CI twice (documented in PR comment 6303541129). Re-express the guard in the new model's terms: the daemonless role line must name the [bash-done] wake, the daemonless prompt must carry the same collect-on-notice turn-end contract as the daemon one, the stale await rule must not come back, and the structural invariant stays — every usage-layer sentence that instructs ending the turn must mention the notification wake. The changeset line is aligned with the same model. Mutation-checked red: reverting the guard reproduces the CI panic (:659, 'the daemonless role line must repeat the await rule'); stripping the wake phrase from the role line trips the new pin (:647); unscoping a usage-layer turn-end sentence trips the structural loop (:667); the poll bullet's collect-on-notice pin also stays load-bearing (:639). Gate: cargo fmt --all --check, clippy -p pa-core --all-targets -D warnings, prompt_guards 7/7 green. * Rescope: drop the stale no-notification await rule; end turns on the done notification Main PrimeIntellect-ai#3640 landed the wake model for every session kind (daemonless runs get a queued [bash-done] turn), so the usage layer's pre-PrimeIntellect-ai#3640 rule - 'In sessions without completion notifications, await commands before ending the turn' - describes a session kind that no longer exists and contradicts the no-polling rule right below it. Delete it and pin the surviving collect-on-notice contract; drop the colliding USAGE_LAYER sentence loop (it fired on PrimeIntellect-ai#3410's text-only-response turn-end rule). * fix the wake attribution: the daemonless bash-done wake came from PrimeIntellect-ai#3580, not PrimeIntellect-ai#3640 --------- Co-authored-by: Sebastian <sebastian@primeintellect.ai>
…tial (PrimeIntellect-ai#3677) * Fix: default the bundled websearch skill off The websearch skill ships enabled by default, but it cannot run without a Serper API key, so fresh installs advertise a tool that errors on use. The exclusion path in packages/resolve already had it right: "Web search stays disabled until explicitly enabled." Now the default matches. - packages/manager.rs: bundled_websearch_enabled() defaults to false; the skill is opt-in via bundledSkills.websearch in settings.json. - prompts/layers/core.md: drop the static websearch core-tool bullet. On installs that enable the skill, the dynamic available-skills inventory renders it; on default installs the prompt no longer documents a tool that cannot run. - Tests: default-settings resolve excludes websearch from the enabled skill list; bundledSkills.websearch: true resolves it; prompt guard pins that the core layer never documents the settings-gated skill; the stored-Serper-key kernel-env test now opts in explicitly. * Review fix: the /mcp Serper key flow enables the bundled websearch skill Making the bundled websearch skill opt-in left the `/mcp` credential flow answering "Web search is ready." while nothing flipped `bundledSkills.websearch`: on default settings the skill stayed excluded after the key landed, so the flow's promise (and the skill's own SKILL.md setup path) was false. The user supplies the key in exactly one place, so that flow now flips the gate: - settings: `set_bundled_websearch_enabled` persists `bundledSkills.websearch` in the global scope through the same locked read-modify-write path as the other setters. - mcp_login: the api-key flow (Serper is its only credential) enables the skill after the key is stored. - test: `the_api_key_flow_enables_the_bundled_websearch_skill` pins the settings write (mutation-checked: dropping the call fails it). * Review fix 2: surface a failed settings write and state the /new gate Two review findings on the previous fix: - Macroscope (High): `save_global` records an unparseable global settings file as an error and returns `Ok(())` without writing, so the flow could still answer "Web search is ready." with the gate unmoved. The manager is now kept and a global-scope error fails the flow, like the API-key store just above it. Regression: `the_api_key_flow_fails_when_the_settings_file_cannot_be_parsed` (mutation-checked). - Cursor Bugbot (Medium): the gate resolves at session build, so the current session keeps the skill excluded (the key also reaches the kernel only at build). The message now carries the activation state the sibling MCP login flow states: "Its skill activates in new sessions (/new)." * Gate websearch with its credential; drop the settings-write flow and the tautological guard Unset bundledSkills.websearch now resolves with the Serper credential (stored auth slot or nonblank ambient SERPER_API_KEY) instead of reading as disabled: existing logged-in users keep the skill across the upgrade, keyless installs stay silent, and removing the credential drops it. The /mcp paste flow no longer needs to write settings, and the explicit false override stays the hard off switch. - manager.rs: bundled_websearch_enabled rides with the credential when the setting is unset; unit tests pin ambient/stored/malformed states. - mcp_login.rs: remove the paste-flow settings write and its tests; the saved key is the gate. - interactive_settings.rs: remove the now-unused setter. - resolve tests: pin default-off on keyless machines, stored-key enablement, explicit true, and explicit-false beating the credential. - prompt_guards: drop the tautological websearch core-layer guard (review: the enabled-path half tested the dynamic inventory with an empty skills list, the default-off half duplicated the resolve test).
…s toward bash() (PrimeIntellect-ai#3691) * feat(kernel): per-cell watchdog teaches over-budget python cells toward bash() python_repl cells cannot be interrupted mid-execution without killing the kernel, so a cell that runs for minutes blocks the serial execution queue and returns looking like a quiet success. Add a host-side per-cell watchdog: when an armed cell outlives its budget, its settled result is annotated as a CellTimeout error with teaching text (long work belongs in bash(), which can auto-background), while the kernel, the queue, and the namespace survive untouched. The budget rides ExecuteOptions.cell_timeout_ms; only the python_repl tool path arms it (resolved from PRIME_AGENT_PYTHON_CELL_TIMEOUT_S, default 60s, 0 disables), so the runtime bootstrap, snapshot/restore, and repair cells are exempt. The cell window is measured from the wire write to the done event, so kernel boot and queue wait cannot trip it. * fix(kernel): pad watchdog durations; snapshot watchdog-flipped cells Two review findings: - Macroscope (low): humanize_ms printed a sub-100ms remainder without padding, so 60,005ms read as 60.5s. Pad to three digits; unit test pins the 60.005s case. - Bugbot (medium): flipping a settled-ok overage to Error skipped the post-cell auto-snapshot (execute_bounded keys it on Ok), so a crash before the next successful cell would revive a namespace missing the overage cell's committed changes, contradicting the teaching text. Carry a watchdog_flipped flag on InternalExecuteResult and schedule the snapshot for flipped cells too; the live-kernel test proves the snapshot file still flushes (mutation-checked: reverting the condition fails it). * watchdog: teach with a stderr note on an ok cell, not a CellTimeout error A completed cell reported as a timeout error invites a duplicate run of finished work and corrupts error-based telemetry (snimu: 3691 review). The over-budget cell now keeps its ok status and its own result; the teaching note rides stderr (the kernel lane's degrade-hint precedent) and names the real mechanism (bash() auto-backgrounds past its yield window, intentional long awaits can ignore it). - budget moves to the shared settings family: pythonCellTimeoutMs (default 60s, 0 disables), resolved once at the engine build; the undocumented PRIME_AGENT_PYTHON_CELL_TIMEOUT_S env var is gone - the watchdog arms only in daemon-backed sessions: daemonless ones keep await bash() unbounded by design (PrimeIntellect-ai#3523) - new pins: queue wait excluded from the budget, an overage error cell keeps its own error, the daemonless/settings arming gate * settings: register pythonCellTimeoutMs in the known-fields list The watchdog's settings key joins the other settings fields in KNOWN_FIELDS (cursor bot: 3691), and a wrong-typed value is pinned to load as unset instead of riding extra into a later save.
…edge (PrimeIntellect-ai#3680) * rlm children: record child cancellation as a parent->child semantic edge Port nano-rlm PrimeIntellect-ai#202 to the Rust daemon: a child the parent cancels, deletes mid-run, or kills at close now leaves a child_cancelled line on the parent's semantic-edge ledger (anchored to the cancelling request, at most once per child), instead of vanishing from the training graph. * rlm children: gate the cancel edge on the confirmed abort; settle close-killed runs Review fixes for PR PrimeIntellect-ai#3680: - the cancel site records child_cancelled only when the abort reached the child or its session is already gone (a real abort failure keeps the edge absent, so a later successful cancel can still record); - a close that kills a live run settles the row cancelled, so a settle watcher parked mid-wait can never refresh the killed run back to done and record a clean child_returned beside the cancel line. * daemon: undo the pre-kill close settle when the kill fails A real close kill failure left the row settled cancelled with no ledger line (PR PrimeIntellect-ai#3680 review finding): the still-live child was misreported cancelled on the roster, and a later successful stop saw was_running as false, so the parent -> child cancel edge was never recorded. Undo the pre-kill settle on a real failure; success and already-gone paths keep the settle that stops a parked watcher appending a clean child_returned beside the cancel line. * daemon: coordinate delete/cancel settles so a confirmed cancel always records Two PR PrimeIntellect-ai#3680 review findings, the same class as the close-path fix in 03a0553: a pre-emptive settle that is never undone poisons a later confirmed path. - delete_subagent settles the row `cancelled` before its kill (the same coordination the close walk uses), so a settle watcher that wakes inside the delete's in-flight window cannot refresh the killed run back to `done` and append a clean `child_returned` beside the cancel line. A real kill failure undoes the settle: the child stays live and retryable. - cancel_child_run undoes the pre-abort settle when the abort is refused for a real reason: the still-live child is not misreported cancelled, and a later confirmed cancel (a retry, a close, a delete) can still record the parent -> child edge. The test fake gains `FakeKill::SuccessAfterMs`, which holds the kill response so a test can put the watcher's wake provably inside the delete's in-flight window. Mutation-pinned: removing the delete pre-settle fails a_deleted_live_child_never_records_a_clean_return (the spurious child_returned line reappears); removing either undo fails its regression test on the row status. * daemon: gate the delete's return edge on a retirement mark; release nothing on a refused abort Three PR PrimeIntellect-ai#3680 review findings, all consequences of the round-2 settle changes. - A refused abort released everything the cancel had claimed: the row was reverted, but `notice_delivered` stayed claimed and `fire_settle_hook` still ran, marking the row settled — the quiescence barrier could return while the worker was still running, an owed goal continuation was released, and the child's later natural finish got no terminal notice. The refused path now restores the notice claim and returns before the hook. - The delete's pre-kill settle could drop the watcher: a watcher that woke inside the kill window saw the faked `cancelled`, ran its settle tail and exited, so a failed kill left a live, tracked, unwatched child. `delete_subagent` no longer fakes a settle. It sets a new `ChildRecord::retiring` mark before the kill, and `record_child_return` refuses while the mark is set — the same coordination (a watcher cannot append a clean `child_returned` beside the cancel line) without lying about the row, so the watcher survives and a failed kill just clears the mark. Mutation-pinned: dropping the return gate fails a_deleted_live_child_never_records_a_clean_return; dropping the early return fails the refused-abort test on the quiescence barrier; dropping the mark clear fails a_failed_delete_leaves_the_child_watched_and_its_later_return_able_to_land. * daemon: mark only live deletes; republish a restored cancel row; settle the goal test through the funnel Three PR PrimeIntellect-ai#3680 review findings on the round-3 changes. - `retiring` was set on EVERY delete, so a settled child torn down inside its settle grace lost its `ChildReturned` edge (its delete records no `child_cancelled` line either, so nothing replaced it). The mark is now set only when the delete cancels a LIVE run. - `cancel_child_run`'s refused-abort branch restored the registry row but did not republish it, so subscribers kept showing a still-running child as `cancelled`. The restored row is emitted before returning. - `agent_engine::tests::goal::running_children_owe_the_continuation_and_settle_delivers_it` drove the settle through `cancel_child_run` on a synthetic child whose supervisor link is a dead socket, so the abort can never confirm and (by design, per the same review) the cancel no longer settles it. The test now settles the child through `settle_test_child`, which fires the same settle funnel a real settle does. The test's intent (a running child owes the continuation; the child's settle delivers it) is unchanged. Mutation-pinned: marking every delete fails a_deleted_settled_child_still_records_its_return; dropping the republish fails the refused-abort test on the last published row. * child_cancelled gains its parent-side actor (parent_delete/user_cancel/close:killed); only the kill close records the line; the watcher grace re-check wipes only its own premature done; a refused cancel answers false and restores the notice claim; the delete e2e moves to its own file * rlm children: park the settle watcher inside a delete's kill window A run settling while a delete's kill is pending no longer runs the watcher's settle tail: the settled branch checks the retiring mark and parks. A failed kill clears the mark and the still-watching loop settles the run normally, so its return edge still lands; a confirmed kill keeps the delete's finish_retirement the sole terminal bookkeeping (cancel line, roster row, notice, settle hook) with no premature notice or extra hook fire racing it. Addresses the Cursor review finding 'Watcher can exit while retiring' on PR PrimeIntellect-ai#3680. * tests: land the delete-turn e2e 93f8e7c moved out of parent_death 93f8e7c removed the delete e2e from rlm_children_parent_death_e2e.rs to move it to its own file, but the new rlm_children_delete_e2e.rs was never committed, dropping the coverage. Restore it. * semantic edges: unknown cancelled-reason values deserialize instead of disabling the recorder --------- Co-authored-by: Sebastian <sebastian@primeintellect.ai>
Merge 170 commits at 71beca9 on top of the pending PR #34, preserving upstream ancestry and the fork capabilities. Keep the exact transport retry episode, session policies, tool selection, model fallback, memory and affinity behavior. Carry the still-open upstream PrimeIntellect-ai#3201 compatibility patch. Include the Tokio 1.53.3 I/O-safety fix and integration regressions found by native validation.
Treat dead X and zombie Z states consistently and confirm disappearance after a proc-entry read race. Unreadable, live and stopped owners remain protected. Add a red-first state regression and prove the stop verifier targets the actual lease-holder PID without extending its escalation bound.
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configuration
You can disable this status message by setting the Use the checkbox below for a quick retry:
Comment |
Separate generated launcher path data from its tracked executable so concurrent process launches cannot retain a writable executable descriptor. Keep the runtime data writer open through real daemon startup and preserve the exact refusal RPC and no-artifact assertion. No production retry or deadline changes.
Keep every encoded append and repaint write within 4 KiB, including oversized rows, without changing the emitted bytes. Preserve the 1500ms exit deadline and 500ms silence grace. Add a controlled 400ms reader-pause regression, structural forced-restore evidence and byte-parity/write-bound coverage; keep healthy completeness and the stalled-drain control intact.
Measure the actual reader pause, read gaps and effective drain rate. Reserve kernel write-completion time within the unchanged 500ms progress budget by using a 250ms injected pause. Verify old 32KiB mode fails and freshly rebuilt 4KiB mode passes on Darwin and Linux, retaining every original completion, ordering, force-stall, deadline and rate assertion.
olety
marked this pull request as ready for review
October 23, 2026 22:28
|
This PR is too large for Bugbot to review. It changes 42,484 lines and 3,953,393 characters. Split the change into smaller pull requests to get a review. |
Upstream added paged get_messages and the persistent-shell commands without changing its schema id, so the merged build still advertised the revision-32 id that the previous fork release answers with. A new client then read the old daemon as current and sent it the new wire. Revision 33 takes a fresh id. A revision-32 daemon is now stale to this build and the reverse; the hosted seat test pins that a busy revision-32 daemon gets the stale-daemon refusal and no create.
The goal no-progress cap sets exit 1, and upstream then keeps every answer off stdout. The fork helper started its own exit code at 0, so a later prompt's answer still printed after the cap; an empty-text filter hid that from the cap test but also dropped the newline an empty answer prints. The helper now takes the caller's exit code and the filter is gone. Tests cover a later answer after the cap and an empty answer.
The failover switch and restore install the armed route through install_armed_route_target, which wrote the route's stored target as is. A transport switch that had reached the session but not yet the armed route was then undone for that turn. The helper now reads the session transport under the provider slot lock, like the apply and clear paths; a test pins the window.
- The --tools error lists python_repl, the built-in tool's name now. - The --verbose exit trace again marks the compaction and refinement boundary end and the goal boundary end, as its header says. - The slow-drain test writes its raw output file only on a failure. - RUST-BASE names python_repl in the tool-selection row.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Merge pinned upstream main
71beca9478f552dc6fc898bba9685f9ce00515cfinto the Oneiron Rust fork without rebasing or squashing. This adds 170 upstream-only commits on top of PR #34 and brings 259 upstream commits (89 + 170) intorust-oneiron. All contents of #34 remain in the ancestry. Merge this PR with a merge commit, never squash or rebase; #34 must not be merged separately.Resolved 112 initial conflict paths. Upstream structure stays: unlocked compaction, inline print RLM, paged transcripts, bundled runtime validation, and process-generation cleanup. Fork transport retries, policies, tool selection, short worker sockets, custom models, memory, affinity, factory surfaces, and self-update refusal stay available. Upstream PrimeIntellect-ai#3201 is still open and its compatibility merge is retained; PrimeIntellect-ai#3197 is already upstream-merged.
Additional integration fixes
python_replwhile retainingipython/pythonlaunch-selection aliases and no-tools/no-kernel behavior.X/Zprocess states from lease liveness and confirmed disappearance after a proc-entry read race, while keeping unknown/live/stopped owners protected. Strengthened the stop verifier's target-owner identity and safe failure diagnostics without extending escalation bounds.Ownership and compatibility
Provider/cache behavior stays in pa-ai; session retry/resource/memory/compaction policy in pa-core; hosted execution and durable launch policy in pa-daemon; wire vocabulary in pa-types; rendering and retry rollback in pa-tui; pa-cli remains the composition root. No new fork dependency or cross-crate re-export was added. Imported upstream dependencies include Cargo.lock; the local security adjustment changes only Tokio's version/checksum.
The fork retains protocol 7 / combined schema 32 and its capability-gated policy, tool-selection and worker-startup metadata. This sync adds no new fork wire field or startup command. Existing wire identifiers such as PI_PACKAGE_DIR, provider IDs and ai.primeintellect.prime-agent remain unchanged.
Verification
24fbf9089dc6408cc43fe51e29fb4c401d10712a/ tree9c34e5af18685a009315f48907201dc3f5df9375; original signed two-parent merge and all fork ancestry remain intact. Rust 1.98.1 matches pinned upstream CI; no identity changes or attribution trailers.cargo test --workspace --no-fail-fast -- --test-threads=4passed: 6,130 passed / 0 failed / 20 ignored (240 test executables; workspace stage 1,623.945s). Fresh owned workspace-crate artifacts, one Cargo writer. Fmt/check/strict Clippy also passed; focused self-update 4/4, stop-lease 2/2, slow-drain 4/4 and registration-heal 3/3 passed before the full suite. Source blobs/executable modes verified before and after. Fleet job1024-065033-4a10on nelly exited 0.Required fork-capability results
Parity-diff evidence
The captured TS no-tools prompt is still compared byte-for-byte, including custom/child prompt cases. Native tests exercise retry ladders, committed tool history, failed partial replacement, socket boundaries, policies, headless exit and model fallback. No fresh TS frame comparison is claimed for this upstream rollup; upstream's canonical tool rename and new UI behavior are imported deliberately.
Release safety
Mac ARM64 release 0.10.1-oneiron.20261024.1 was built from this clean published head, packaged with real catalogs (1,208 models / 42 transport tuples / 69 MCP services), and installed side by side with
--no-activate. Binary SHA25685e5d394f39c4066e756f0e56050ef49a2e73b5ee33a4317130890ffffb07c1a; stamped tarball SHA2561f66703e1e5cc63de1c017391d82a95da141ade876f145b8a4b95cd2f221efd9. All 61 tarball files match the installed payload; source, receipt and catalog hashes agree.Isolated scratch-launcher checks passed: version, custom cpa-r model list, Sol and DeepSeek plain no-tools answers exactly
probe ok, then JSONpython_replexecution of6*7returned42and final answer exactlytool probe 42. No kernel venv existed through the no-tools checks; only the tool turn created it. Own agent, socket and venv paths were used.No current/previous or installed launcher flip, live daemon restart, or live agent-configuration write was performed. PID 34585 still runs 0.9.8-oneiron.20261006.1 with its original start identity and production socket. No protected configuration hash changed between finish admission and the end-of-smokes snapshot. A later metadata-only recheck saw another concurrent MCP catalog hash change; that and the three earlier deltas are disclosed in the local report, not reverted. Activation and rollback remain owner decisions after review and merge in a quiet window. Installation, probe and validation receipts were written; no activation receipt.
Conflict resolution ledger — 112 paths
crates/pa-agent/src/agent.rscrates/pa-agent/src/proxy.rscrates/pa-agent/src/types.rscrates/pa-ai/README.mdcrates/pa-ai/src/providers/anthropic/mod.rscrates/pa-ai/src/providers/faux/mod.rscrates/pa-ai/src/providers/openai_codex_responses/errors.rscrates/pa-ai/src/providers/openai_codex_responses/mod.rscrates/pa-ai/src/providers/openai_codex_responses/websocket.rscrates/pa-ai/src/providers/openai_responses.rscrates/pa-ai/src/utils_inner/stream_failure.rscrates/pa-cli/src/args.rscrates/pa-cli/src/daemon_discovery/mod.rscrates/pa-cli/src/headless_autonomous.rscrates/pa-cli/src/piped_stdin.rscrates/pa-cli/src/print_goal.rscrates/pa-cli/src/print_runtime.rscrates/pa-cli/src/prompt_command.rscrates/pa-cli/src/public_command.rscrates/pa-cli/src/self_update.rscrates/pa-cli/src/update_flow/update_command.rscrates/pa-cli/tests/interactive_daemon_e2e.rscrates/pa-cli/tests/interactive_fork_e2e.rscrates/pa-cli/tests/kitty_verdict_time_e2e.rscrates/pa-cli/tests/packaged_layout_e2e.rscrates/pa-cli/tests/print_runtime_e2e.rscrates/pa-cli/tests/termios_process_exit_e2e.rscrates/pa-core/README.mdcrates/pa-core/src/auth/manager/tests.rscrates/pa-core/src/kernel/bootstrap/mod.rscrates/pa-core/src/kernel/bootstrap/venv.rscrates/pa-core/src/kernel/bootstrap/venv/probe.rscrates/pa-core/src/kernel/bootstrap/venv/tests.rscrates/pa-core/src/kernel/manager/mod.rscrates/pa-core/src/kernel/manager/requests.rscrates/pa-core/src/kernel/manager/snapshot.rscrates/pa-core/src/kernel/provisioner.rscrates/pa-core/src/platform/mod.rscrates/pa-core/src/prompts/mod.rscrates/pa-core/src/prompts/system_prompt.rscrates/pa-core/src/resources/mod.rscrates/pa-core/src/session_engine/auto_retry.rscrates/pa-core/src/session_engine/compact_session.rscrates/pa-core/src/session_engine/compact_session/tests.rscrates/pa-core/src/session_engine/compaction_arms.rscrates/pa-core/src/session_engine/compaction_exec.rscrates/pa-core/src/session_engine/engine.rscrates/pa-core/src/session_engine/engine/tests.rscrates/pa-core/src/session_engine/error_classify.rscrates/pa-core/src/session_engine/headless.rscrates/pa-core/src/session_engine/mod.rscrates/pa-core/src/session_engine/provider_adapter.rscrates/pa-core/src/session_engine/provider_failover.rscrates/pa-core/src/session_engine/provider_retry.rscrates/pa-core/src/session_engine/runtime_wiring.rscrates/pa-core/src/session_engine/telemetry.rscrates/pa-core/src/session_engine/wiring.rscrates/pa-core/src/tools/golden_replay.rscrates/pa-core/src/tools/ipython.rscrates/pa-core/tests/golden/system_prompt.rscrates/pa-daemon/src/acp/daemon.rscrates/pa-daemon/src/agent_engine.rscrates/pa-daemon/src/agent_engine/config.rscrates/pa-daemon/src/agent_engine/lifecycle.rscrates/pa-daemon/src/agent_engine/session_engine_impl.rscrates/pa-daemon/src/agent_engine/tests.rscrates/pa-daemon/src/agent_engine/turn/model.rscrates/pa-daemon/src/boot_reap.rscrates/pa-daemon/src/branch_navigation.rscrates/pa-daemon/src/create_reuse.rscrates/pa-daemon/src/engine.rscrates/pa-daemon/src/platform/paths.rscrates/pa-daemon/src/prompt_admission.rscrates/pa-daemon/src/registry.rscrates/pa-daemon/src/session_navigation.rscrates/pa-daemon/src/setting_switches.rscrates/pa-daemon/src/supervisor.rscrates/pa-daemon/src/supervisor/clients.rscrates/pa-daemon/src/supervisor/root_identity.rscrates/pa-daemon/src/supervisor/routing.rscrates/pa-daemon/src/supervisor/supervision.rscrates/pa-daemon/src/supervisor/worker_lifecycle.rscrates/pa-daemon/src/worker/create.rscrates/pa-daemon/src/worker/tests/summary_tests.rscrates/pa-daemon/src/worker_stderr.rscrates/pa-daemon/tests/provider_failover_e2e.rscrates/pa-daemon/tests/provider_failure_e2e.rscrates/pa-daemon/tests/supervisor_e2e/lifecycle.rscrates/pa-daemon/tests/supervisor_e2e/tool_results.rscrates/pa-daemon/tests/worker_stderr_e2e.rscrates/pa-telemetry/src/catalog.rscrates/pa-telemetry/src/events.rscrates/pa-telemetry/src/lib.rscrates/pa-tui/src/daemon_client/errors.rscrates/pa-tui/src/interactive/run.rscrates/pa-tui/src/session_ui.rscrates/pa-tui/src/session_ui/apply.rscrates/pa-tui/src/session_ui/lifecycle.rscrates/pa-tui/src/session_ui/panels.rscrates/pa-tui/src/snapshot.rscrates/pa-tui/src/snapshot/tool_fold.rscrates/pa-tui/tests/daemon_rejection_headless.rscrates/pa-tui/tests/drag_select_perf.rscrates/pa-types/src/daemon/mod.rscrates/pa-types/src/daemon/outbound.rscrates/pa-types/src/incident/classify.rscrates/pa-types/src/incident/patterns.rscrates/pa-types/src/platform/transport.rsprime-agent-runtime/src/rlm/__init__.pyprime-agent-runtime/src/rlm/bash.pyprime-agent-runtime/src/rlm/repl.pyprime-agent-runtime/test/test_bash.py