* fix(runtime): hold tui-idle until a cold-starting Claude has painted (STA-2380)
A shell auto-title (oh-my-zsh preexec) names the pane `claude` the moment
the command execs. Claude's `idle_title` rule counts that bare name as weak
idle once output has been quiet for 3s, so a Claude that took >3s to draw
its first frame settled `terminal wait --for tui-idle` on a blank screen.
`dispatch --inject` then pasted into a TUI that had not mounted yet and the
prompt was lost.
Name-only idle lanes (agent rule verdicts that require quiet, and the
sustained-title lane) now also require that the running command has painted
something since the shell's OSC 133;C command-start marker. Shells without
the marker keep today's behavior.
* fix(runtime): corroborate Claude's name-only idle with its own composer marker (STA-2380, C1 F1)
Orca's zsh OSC 133;C hook is first in preexec_functions, so a later user or
framework preexec hook (zsh-you-should-use, a custom echo) prints after the
command-start marker and before Claude runs. The any-visible-byte paint latch
counted that text as Claude's paint, so a silent cold start under such a hook
still settled tui-idle ready-weak on the shell's bare `claude` title.
For agents whose worker start already trusts their composer marker (Claude),
"painted" now means that marker (`❯`+NBSP after DECSET 2031, which no shell
sends) arrived since the command started. Other agents keep any-byte paint;
markerless shells and output gaps keep the permissive default.
Evidence: a real-zsh live-shell test under the production wrapper with
oh-my-zsh title-only, p10k/starship-style silent, and you-should-use-style
printing hooks, replayed through the real wait; runtime tests for the hook
text, a boot banner, the positive bare-title + composer path, and worker-start
readiness plus brief delivery timing.
* fix(ci): route command-paint attribution sources to shell_contracts; attribute live-shell bytes by stream offset (STA-2380, C2 F1/F2)
- pr-shell-contract-prefixes: the live-shell test, terminal-command-paint.ts,
tui-idle-evidence-source.ts and draft-paste-ready-scanner.ts route to the
shell_contracts job; a routing test reads the job's step from pr.yml and
asserts every listed test routes there.
- tui-idle-zsh-preexec-hook-order.live-shell.test: locate the DECSET 2031
anchor by offset in the accumulated stream, split a straddling read, carry
pending escapes across the shell/agent halves, and assert attribution is
invariant under coalescing and 3-byte re-chunking.
- terminal-command-paint: disclose the accepted trade-off (a known Claude with
marker history but no supported composer signal times out; markerless shells
and output gaps still fail open; no version cutoff claimed).
* test(ci): stream-offset launch-order proof, route tui-idle-evidence.ts, parse the whole shell-contracts step (STA-2380, C3-1/2/3)
- live-shell test: assert the launch order on the joined bytes by stream
offset (133;C, then the user hook's output, then the agent's anchor and
composer); no read-boundary or timestamp assertions remain. Re-chunk
cases add a split anchor and a shell-tail/agent-start coalesced read.
- pr-shell-contract-prefixes: route tui-idle-evidence.ts, the readiness
evaluator the live-shell replay exercises.
- routing ratchet: read the step's run script through the YAML parser so
a blank line or later command cannot truncate it; cross-check against
the real-shell tests UNIT_EXCLUDE drops so a dropped entry fails rather
than a smaller count; fixture tests for blank line, exact list, missing
step.
* test(ci): answer compinit's insecure-directory prompt in the zsh preexec live-shell test (STA-2380)
Ubuntu's global zshrc runs a plain compinit, which on CI runners stops at
"Ignore insecure directories and continue [y] or abort compinit [n]?"
before zle exists, so the stand-in never launched and the shell-contracts
job failed with "no composer frame from the stand-in". Answer the prompt
with y as zsh-startup-hook-pty-harness.ts does. The prompt bytes precede
Orca's OSC 133;C marker, so stream-offset attribution is unchanged.
* refactor: organize browser guest lifecycle owners
* test: resolve cross-version client owners and pre-ticket baseline
* test: record the released terminal registry path
* refactor: organize remaining terminal pane features by owner
* refactor(terminal): consolidate replay guard type imports
* refactor(terminal): retarget notification mocks and generated consumer import
* refactor(terminal): repair benchmark owner lookup and stale mock export
* Bound every pull request CI job with timeout-minutes
* ci: bound the PR-triggered jobs added since #28784 with timeout-minutes
Sized from recent run times: containers 1.2 min max, mac-native-owner-smoke 5.5,
contract 1.2. Secret scan (1.8 max) and mobile_web_app (5.4 max) get roomier limits.
* ci: check PR job time limits in code_paths so workflow-only PRs are covered
A PR that changes only mobile.yml or cloud-verify.yml skips the root unit
shards, so the timeout test never ran for it. Run the check from code_paths,
which runs on every PR, as check-required-pr-context already does.
* ci: use a uniform 3h ceiling on newly bounded PR jobs to stop runaway jobs
The goal is only to stop jobs that would otherwise run to GitHub's 6h
default, not to tune per-job limits. The guard keeps requiring a limit
below 360 minutes on every PR job but no longer enforces a lower value.
---------
Co-authored-by: Kelvin Amoaba <97001695+AmoabaKelvin@users.noreply.github.com>
Co-authored-by: Neil <neil@stably.ai>
* fix(serve): keep `orca serve` running while it probes the login shell
`orca serve` started from an interactive terminal stopped itself ("[1]+
Stopped") before printing its pairing link. orcad inherits the terminal
and probes the login shell with `$SHELL -ilc`; an interactive bash 5 or
zsh takes the terminal's foreground job, so orcad's next terminal access
raised SIGTTOU/SIGTTIN. Give both shell probes (login environment and
PATH) a POSIX session of their own so they never hold a controlling
terminal. Windows keeps attached spawns, where `detached` would open a
console.
Refs #38347
* fix(serve): end a detached shell probe with its owner and on timeout
A probe in its own session no longer receives the terminal's Ctrl+C or
hangup, so a hung rc could outlive `orca serve`. Kill the probe's process
group by its own pid when it times out and when its owner exits while it
still runs; orcad and Electron turn INT/TERM into an exit, so a Ctrl+C
reaches it that way. No signal listeners: one would replace Electron's
graceful signal quit. The timeout now also ends what the rc started, not
just the shell.
Refs #38347
Prepare requested immutable historical snapshots before timed extraction and direct reads, using the existing acquisition/process helpers and local-only consumers. Move four suites' historical module setup into per-pin hooks without changing pins, compatibility assertions, workers, extraction/assertion deadlines or publication ownership.
Independent reviews and the binding design settlement passed. The cold comparison and normal uninstrumented final-head CI each passed49files197tests; normal Checkout62s/job276s. All temporary probes removed; brennan-ready READY.
Tracked in STA-13683. Outer-hook failure attribution limitation tracked in STA-13703. No application, saved-data or wire behavior change.
Follow-up to #37699: pr.yml computes defer_shadow once, unit-plan.yml
uses only that input and exposes selection_planned, and the test and
evidence jobs read that output instead of repeating the condition.
Emit the full matrix without dependency installation or graph discovery; retain independent full test discovery and selected-draft provenance. Reuse existing draft plans, and disable unpublished transform writes on warm misses. Automatic cache production was removed after review because the near-quota cache store has no budgeted retention plan. Full required PR CI passed on 658ea5275c.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* ci: full checks on main pushes, changed-file lint on PRs, Slack alert when main breaks
PR Checks now also runs on every push to main, with each commit in its own
concurrency group so main runs never cancel one another. On a push the path
router gets an empty diff, which already fails closed to every job, and the
input-scoped steps (localization extraction, VM rollback replay, orcad smoke)
run in full. Advisory E2E lanes stay PR-only.
On PRs the per-file passes (root oxlint, JS-plugin oxlint, anti-slop, ast-grep
and oxfmt) check only the changed paths. Everything is checked when the diff
cannot be resolved, a lint toolchain input changes (oxlint/oxfmt/ast-grep
configs and plugins, package.json, the lockfile, .gitignore, pr.yml), or more
than 1500 paths change. Whole-program checks stay unscoped.
A new workflow follows completed main runs and posts to the release Slack
webhook only when main turns red, and once when it turns green again.
* ci: alert once per main health streak and tolerate a malformed Slack mapping
Fixes#34312. Takes over naufaldi/orca#1 by @naufaldi, with the main.css part dropped because #34932 already covers it.
- SshTargetCard and the reasoning chevron now use the scoped `[[class~='group/x']:has(:focus-visible)_&]` shape. Tailwind's `group-has-*` compiles to a non-subject `:has()` whose subject is `*`, and that rule made Blink restyle whole subtrees on every mutation. This change is the entire measured win: 19.4 → 1.6 ms, 12.5 → 3.6 ms and 8.0 → 2.4 ms per mutation.
- rich-markdown-editor.css drops a redundant `:has()` on the TOC header, as defence in depth.
- Adds a guard, check-has-restyle-scope.mjs. It compiles the renderer's Tailwind CSS, adds plain stylesheets and the listed vendor stylesheets, and fails on any non-subject `:has()` whose subject has no class, id or attribute. Three pdf.js rules are baselined after being measured as harmless. It runs in lint, check:changed and PR CI in about 1.5 s.
Co-authored-by: Naufaldi <naufaldi.rafif@gmail.com>
* feat(wsl): bridge sh/dash/ash panes report their folder (OSC 7) at every prompt
bash, zsh, fish and nushell panes already tell the terminal daemon their
folder; a bridge pane whose login shell is sh, dash or busybox ash did
not, so restores fell back to the starting folder.
dash has no rcfile flag or prompt hook, but an interactive sh reads $ENV
after ~/.profile, and dash 0.5.8+ (plus ash and bash-as-sh) expand $(...)
in PS1. The bridge now points ENV at a new sh/env file in the published
wrapper tree, saving the user's own ENV. That file hands ENV back to the
user's value (so children see theirs), sources it, and inside WSL only
prefixes PS1 with the report. A root containing $, ` or \ is skipped,
since the shell expands ENV's value.
A non-interactive sh -c never reads ENV, and a missing file (Orca
updated away or uninstalled) is silently ignored by dash, ash and bash.
* fix(wsl): sh ENV hook survives quotes in the user's ENV and keeps prompt width
- The user's ENV is expanded through a here-document, so a value with a
quote, $ or space no longer breaks startup with a syntax error.
- bash-as-sh and busybox ash (fancy prompt) get the report inside \[ \]
so its invisible bytes don't count toward the prompt width; dash has no
line editor to miscount and would print \[ literally, so it stays bare.
- Tests: a user ENV of `$HOME/u "q" sp/env`, a user PS1 with $, a quote
and a backslash, and reports read through the daemon's WSL parser.
- CI: edits to the sh hook and the bridge launch trigger the shell
contracts job (its prefix list moves to its own module, keeping the
scope script under its line limit), and the sh and fish WSL pty tests
leave the unit shards.
* ci: check out the shell-contract prefix module in the change detector
The detector job sparse-checks-out a fixed file list; the new
pr-shell-contract-prefixes.mjs that pr-code-change-scope.mjs imports was
missing from it, so the job failed with ERR_MODULE_NOT_FOUND. A contract
test now walks the scope script's local imports and requires each in
that list.
* ci: list the shell-contract prefix module wherever the scope script's modules are listed
Two config-script suites copy pr-code-change-scope.mjs and its sibling
modules into a fixture repo; without the new pr-shell-contract-prefixes.mjs
the copied script failed to load, and the detector fell back to running
everything. Also lists it with the scope script's other modules in the
mobile workflow trigger and the mobile non-test file set.
Unit shards now wait for a standalone plan job instead of preflight, and
packaging and the layout oracle start immediately, so preflight's slower
free runner no longer delays the PR gate.
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>