Commit Graph
894 Commits
Author SHA1 Message Date
OrcaWinandm4air 04b84870ac feat(orcad): reach managed orcad over an SSH stdio bridge where sshd refuses port forwarding (#25120)
* feat(orcad): reach managed orcad over an SSH stdio bridge where sshd refuses port forwarding

Hosts with AllowTcpForwarding no were kept on the relay. The managed tunnel now
probes forwarding each time it starts and, on refusal, serves the same local port
through a second provider: each accepted socket opens one SSH exec channel running
a small bridge on the host's pinned Node, which dials orcad's loopback port.
POSIX hosts run it with node -e; Windows hosts run it as the content-addressed
host script's stdio-bridge op with base64 line framing. Bridges are capped at 8
per connection under sshd's MaxSessions default, and a lost channel only drops its
socket. Only a host where even the bridge cannot run keeps the relay, recorded as
ssh_tunnel_unavailable; the older tcp_forwarding_refused record is retried.

* test(e2e): prove the stdio bridge by refused forwarding plus a working call

* test(e2e): connect the refused-forwarding host without the relay-only repo step

---------

Co-authored-by: m4air <m4air@Mac.localdomain>
2026-10-03 19:17:23 -07:00
m4air f0e3848abe Merge remote-tracking branch 'origin/main' into OrcaWin/node-rt-p3-main-sync
# Conflicts:
#	src/main/persistence/applying-settings/terminal-settings-migrations.ts
#	src/relay/agent-exec-handler.ts
#	src/renderer/src/i18n/locales/en.json
#	src/shared/global-settings-types.ts
2026-10-03 02:54:28 -07:00
2fc517c1c6 feat(cli): add --unread/--read to orca worktree set
Pass validated read/unread flags through the existing workspace metadata update.

Contributor attribution correction: the earlier Ctrl+M squash message placed its related link after the co-author footer, so GitHub did not recognize all contributors. Preserve that credit here for https://github.com/stablyai/orca/pull/24100 and its related contribution https://github.com/stablyai/orca/pull/24143 .

Related CLI link validation retained from https://github.com/stablyai/orca/pull/20036 .

Co-authored-by: Raz Shlomo <12373339+razshlomo@users.noreply.github.com>
Co-authored-by: Neil <neil@stably.ai>
Co-authored-by: Zhichang Yu <yuzhichang@gmail.com>
Co-authored-by: Ahmed Nagy <ahmednagy25t@gmail.com>
2026-10-03 01:59:38 -07:00
Neilandczzczz 4c2cb3cf12 fix(jcode): quote the managed hook path, drop tools from patch prompts
Three fixes, all on paths this PR could not exercise locally.

The managed hook command was stored as a bare path. jcode tokenizes that
string shell-style before exec'ing it directly (parse_hook_command,
crates/jcode-terminal-launch/src/lib.rs): unquoted whitespace splits, and
every unquoted backslash is consumed as an escape. So on Windows
`C:\Users\me\.orca\agent-hooks\jcode-hook.cmd` reached exec as
`C:Usersme.orcaagent-hooksjcode-hook.cmd` and no hook fired at all, and a
POSIX home with a space split into two arguments. Store the path
single-quoted (verbatim, backslashes included), falling back to double
quotes for a path containing a single quote. Existing bare entries are
already repointed by the stale-key path, and getStatus accepts both forms
so the repair is not reported as a user-owned hook. The quoting helper was
previously dead code that only tests called; the three production sites
now use it. isJcodeManagedCommand also normalizes separators, since a
`/`-only needle never matched a Windows entry.

Commit-message generation feeds a staged patch to `jcode run` as the
prompt — attacker-influenced text — while jcode's default profile exposes
shell, read, write, and MCP. Pass `--tool-profile none`, which resolves to
an empty allowed-tool set in jcode's config (base_allowed_tools), matching
the read-only posture claude (plan) and codex (read-only) already take.

docs/reference/jcode-hook-events.md was never actually in this PR: the
repo ignores docs/** and tracks reference docs by allow-list only, so the
captured-payload evidence four source comments point at was silently
dropped. Allow-list it.

Co-authored-by: czzczz <chanzrz_zbf@foxmail.com>
2026-10-03 01:49:40 -07:00
Neil 668d6d45c4 Reuse measured Electron preparation for current Terminal Perf refs (#24968) 2026-10-03 01:39:58 -07:00
Neil ec47f0c41b Drain removal fixture jobs before resetting and deleting their records (#24977) 2026-10-03 01:15:17 -07:00
c1d403a47b feat(cli): link GitHub and GitLab items on worktree create and set
Expose and validate the existing workspace link fields, preserving omitted values and provider identity checks.

Related: https://github.com/stablyai/orca/pull/22609

Co-authored-by: marco song <marco.song@mvlchain.io>
Co-authored-by: SongMarco <20613630+SongMarco@users.noreply.github.com>
Co-authored-by: Luca Critelli <lucacri@gmail.com>
Co-authored-by: Neil <neil@stably.ai>
2026-10-03 00:51:19 -07:00
NeilandNeil 6486624b44 docs: reference local orca.yaml and .worktreeinclude
Document the existing workspace configuration, include/copy rules and sharing behavior.

Co-authored-by: Neil <neil@stably.ai>
2026-10-03 00:50:36 -07:00
小七andNeil 97fd7edb39 fix(editor): recognize Ruby task and configuration files
Add Ruby task/configuration filenames to the existing generated language associations.

Co-authored-by: ggbdpq <ggbdpq@gmail.com>
Co-authored-by: Neil <neil@stably.ai>
2026-10-03 00:39:39 -07:00
c792386cdc docs(terminal): explain local macOS/Linux shell startup files
Document the actual login/interactive shell startup-file order and existing shell setup behavior.

Co-authored-by: brynnclaw <261708852+brynnclaw@users.noreply.github.com>
Co-authored-by: Neil <neil@stably.ai>
2026-10-03 00:39:34 -07:00
Neil f93808dfff Collect test-selection evidence when full unit tests fail (#24955)
* Collect advisory unit-selection evidence from failed full runs

* Trigger checks after retargeting the evidence fix to main
2026-10-03 00:09:15 -07:00
Neil 30e0ccaba6 Let retired-cache GC observations settle across the existing six-turn budget (#24967) 2026-10-02 23:52:29 -07:00
github-actions[bot] 36d008688a Update README downloads badge 2026-10-03 06:49:10 +00:00
Neil 87f5a98a61 Reuse documentation search excerpts during result navigation (#24574)
Memoize the existing pure excerpt renderer by complete raw text for the current result array, retaining original rendering as a miss fallback.
2026-10-02 23:34:00 -07:00
Neil 7539d19416 Skip impossible link and tag matches in docs search results (#24646)
* Skip impossible HTML matches when formatting docs search results

After the existing link-removal phase, skip the unchanged HTML regex only when the current string has no closing delimiter.

* Skip impossible link and tag matches in docs search results

Skip the five unchanged link regexes when their protected-code input lacks ]; skip the unchanged HTML regex when its post-link input lacks >.
2026-10-02 23:31:09 -07:00
Neil 8f26bfad22 Use the measured pnpm lookup policy automatically in hosted root CI (#24951)
* Select lookup automatically for the measured hosted root-install profile

* Record hosted automatic-mode cold cache publication proof
2026-10-02 22:32:04 -07:00
Neil 6e6f651380 Avoid repeated pnpm archive downloads in cache producers (#24927)
* Let measured cache producers keep stores without downloading them

* Check that restore-only callers do not publish a producer path

* Enable the measured producer mode and record hosted comparisons
2026-10-02 20:37:54 -07:00
Neil 9e27050955 Add verified native Antigravity Accounts on the owning runtime (#24691)
* Add verified native Antigravity accounts on the owning runtime

* Keep Antigravity usage tied to its observed native account

* Refuse oversized encrypted Antigravity snapshots before writing

* fix(antigravity): localize account heading and search terms
2026-10-02 17:48:27 -07:00
Neil 1d5d02e396 Resolve explicitly configured command aliases for workers (#24648)
* feat(orchestration): resolve explicitly configured command aliases

* docs(orchestration): explain configured command aliases

* fix(orchestration): validate configured aliases with target shell grammar

* fix(orchestration): use actual shell and refuse assignment-only aliases

* test: preserve typed calls in configured worker target checks

Replace Reflect.apply with the existing typed prototype call pattern so the unchanged regression cases pass the anti-slop lint gate.
2026-10-02 17:40:48 -07:00
Neil 75f8f34ce3 Overlap independent Linux headless runtime builds (#24910) 2026-10-02 17:18:44 -07:00
Neil 1241ce1b49 Skip slower root package-store restores in macOS PR jobs (#24908)
* Skip slower root package-store restores in macOS PR jobs

* Update the companion cache-policy contract
2026-10-02 17:16:49 -07:00
Neil 533446dde6 Stop mocked renderer imports from qualifying headless CI (#24902)
* Decouple headless running-work tests from the renderer

* Keep the shared running-work probe contract documented
2026-10-02 16:56:43 -07:00
Neil a824fb74ab Reuse the headless detector compiler without installing full dependencies (#24895)
* Reuse the headless detector compiler without full dependency setup

* Keep optional compiler-cache saves from failing cache warming
2026-10-02 16:56:08 -07:00
Neil 58cf72d48e Skip slower root package-store restores in Linux PR jobs (#24896) 2026-10-02 16:09:59 -07:00
Neil add1c55590 Skip slower Windows root package-store restores in CI (#24885)
* Skip slower Windows root package-store restores in CI

* Update reviewed mobile dependency-store cache expression
2026-10-02 15:24:30 -07:00
m4air bcedaca9d6 Merge remote-tracking branch 'origin/main' into OrcaWin/node-rt-phase3
# Conflicts:
#	config/ci/windows-ssh-provider/preview-ssh/prove-preview-openssh.ps1
#	src/main/ipc/parcel-watcher-process-supervisor.ts
2026-10-02 14:38:16 -07:00
Neil 61836f6026 Reduce scheduled CI cache warming to every six hours (#24881)
* Reduce scheduled CI cache warming to every six hours

* Document cache warmer recovery interval and measured tradeoff
2026-10-02 14:35:06 -07:00
Neil cc73c8e1a7 ci: overlap ARM SSH setup and independent observation waits (#24714) 2026-10-02 14:00:49 -07:00
Neil ac28e8c85e Skip dependency installation for known headless build inputs (#24716)
* ci: defer headless dependency installation until graph analysis is needed

* docs: align headless CI rollout with platform and cache policy

* test: isolate headless detector output from the parent CI step
2026-10-02 13:53:56 -07:00
OrcaWinandm4air c0386783b1 fix(telemetry): report Windows security-software refusals and unverifiable or failed runtime checks (#24866)
ssh_remote_runtime_resolved dropped the self-test's security_software refusal to 'none' and
sent nothing when a self-test was unverifiable or failed, because those attempts throw before
a rung settles. Add the refusal value, self_test 'unverifiable', and an outcome field
(resolved | unverifiable | failed) deduplicated per host and outcome per session.

Co-authored-by: m4air <m4air@Mac.localdomain>
2026-10-02 13:35:05 -07:00
Brennan Benson d6d2795da5 chore(worktree): include create timing and spare outcome in the workspace create events (#24483)
* chore(worktree): include create timing and spare outcome in the workspace-created event

The workspace_created and workspace_create_failed events gain optional,
numbers-and-enums-only fields built from what the create already measured:
total and per-phase durations, the prepared-checkout hit/miss and miss
reason, the execution host (local/WSL/SSH), a worktree count bucket, how
many other creates were in flight, whether the repo has a post-checkout
hook (file existence only, probed after the create returns), and for a
failure the phase it died in plus elapsed time. No new git process runs;
consent and opt-out are unchanged.

* fix(worktree): attribute failed_phase by error, label WSL-path repos, skip the hook check with telemetry off

- failed_phase now names the outermost timed step the thrown error (or its cause) left, so a
  caught failure or a concurrent sibling step can no longer be misattributed; the old-relay SSH
  error keeps its cause so it still reads as git_worktree_add.
- execution_host follows the same rule Git routing uses, so a \\wsl.localhost repo reads wsl.
- The post-checkout hook check does not read the repo when telemetry is disabled.
- Privacy page mentions the miss reason code and the failed step.

* test(worktree): pin the old-relay SSH add error to git_worktree_add through its cause

* fix(worktree): name the create event field sets for their role, and type the old-relay test's caught error

* fix(worktree): send create events from runtime creates and record what the spare checkout did

Runtime creates (CLI, agents, phone app, paired clients, orchestration, server
automations) reuse prepared checkouts like the app's own creates, but recorded
no timing and sent no events. Both entry points now start one shared sender
(workspace-create-telemetry.ts), so every create sends exactly one event with
the same fields, plus create_entry_point (app | runtime).

Spare-checkout fields:
- concurrent_preparations: peak prepared-checkout builds and background
  discards running during the create, excluding the one it used; the window
  closes before the create's own re-arm starts.
- prepared_checkout_claim / prepared_checkout_discard phases, so on a miss
  git_worktree_add minus the prepared_checkout_* phases is the plain checkout.
- prepared_checkout_reset (none | base_moved | retargeted) replaces the
  retargeted flag; prepared_checkout_origin (prefetch | rearm) on hits.
- workspace_create_failed carries the spare outcome and its wait.
- repo_index_size_bucket from one stat of .git/index in the existing
  post-create probe (telemetry on, local/WSL only, 2 s cap).

* fix(worktree): add spare build and idle time, the re-arm prefetch origin, and a tracked-file count

- prepared_checkout_build_ms / prepared_checkout_idle_ms on hits: from arming
  the spare to ready, and how long it sat ready before the claim (0 when the
  create waited). readyAt is recorded in the pool's existing ready handler.
- prepared_checkout_origin gains rearm_then_prefetch: an automatic re-arm that
  the dialog prefetch then asked for too, so rearm means the re-arm alone.
- repo_file_count_bucket replaces the index byte size: the entry count from
  the 12-byte index header, which is the same in every index version; left
  out for a split or sparse index.
- The shared sender never lets a failed send change the create's result or
  error; it logs instead and still ends the create's concurrency membership.
- Tests pin the runtime SSH create's timing hand-off and the throwing-send
  cases on both entry points.

* fix(worktree): leave out the file count under any sparse checkout and time spare builds monotonically

- The repo probe also reads .git/config.worktree, where git sparse-checkout
  --sparse-index writes index.sparse, and omits the file count whenever
  sparse checkout or a sparse index is on in either file, with Git's boolean
  spellings. core.hooksPath there is honoured too.
- prepared_checkout_build_ms / _idle_ms use performance.now(), like every
  other duration; the build is timed from its own start (buildStartedAt).
- The origin field comment names all three values.

* fix(worktree): keep the spare's build time on its first build and count worktrees by lock reason

- prepared_checkout_build_ms runs from the first build's start (including any
  wait for the base fetch it is built on) to its first ready; a later tip
  refresh no longer restarts it, though it still counts as new preparation
  work. prepared_checkout_idle_ms runs from the latest ready (build or
  refresh) to the claim.
- The worktree count reads each .git/worktrees entry's locked file and leaves
  out entries whose lock reason names an Orca preparation, the way the
  listing does, instead of subtracting this process's spares. That covers
  spares from other processes, crash leftovers and spares being discarded,
  and cannot run one low while a spare's admin dir does not exist yet. It has
  its own 1.5 s cap inside the probe.
2026-10-02 12:46:13 -07:00
Jinwoo Hong 9503f9de34 fix(runtime): settle Codex tui-idle waits on its hook done, leaving working rows to the rules (#24541)
A headless orca serve has no window to write the Codex ready title, so a
Codex tui-idle wait settled only after three quiet seconds. Rule files gain
profile.hooks: "turn-end": a fresh hook done settles the wait, while a
working or permission row leaves the decision to the rules, so a Codex
whose Esc posts no event (before its Interrupt hook) cannot hang the wait.
Codex moves from identity-only to turn-end.
2026-10-02 15:19:19 -04:00
m4air 304473a549 Merge remote-tracking branch 'origin/main' into OrcaWin/node-rt-phase3 2026-10-02 11:41:34 -07:00
github-actions[bot] 1fc24d3114 Update README downloads badge 2026-10-02 13:21:26 +00:00
Neil 76b1a90ff6 chore(deps): update reviewed dependencies across Orca (#24561)
* chore(deps): update reviewed desktop dependencies and tooling

* chore(deps): update compatible mobile packages and Fastlane

* chore(deps): update cloud transports and enforce release age

* chore(deps): patch documentation dependencies and record review

* chore: remove dependency review reports

* test(linear): smoke-load resolved SDK through CommonJS loader

* fix(deps): keep native rebuilds from reinstalling addon dependencies

* fix(native): invoke installed node-gyp directly for Node rebuilds

* test(cloud): exclude observer probes from row-lock timing budget

* test(mobile): preserve the CSS writer receiver in viewport spy

* test(native): remove obsolete batch-shim fixture exception

* Stream native rebuild output through the process wrapper
2026-10-02 05:05:43 -07:00
Neil cd8d03bc06 fix(dsh): recognize 0.2 profiles and open workspace composer (#24589) 2026-10-02 04:26:00 -07:00
Neil 13ecf051c3 Reuse prepared Windows native builds in SSH CI (#24555)
* ci: reuse qualified Windows server slots for SSH host tests

* ci: reuse prepared relay addons after an exact native cache hit
2026-10-02 03:31:57 -07:00
Neil efbf651c7b Reduce CI setup costs and fixture failures (#24537)
* Let scheduled CI warmers wait and measure WebRTC startup

* Measure a smaller daemon shutdown fixture image

* Counterbalance WebRTC startup and verify retained fixture files

* Record CI fixture measurements and remove temporary pilots

* Clarify fixture build dependency cleanup evidence

* Make coalesced snapshot fixture delivery deterministic

* test: type the PTY write delay observer
2026-10-02 02:46:02 -07:00
OrcaWinandm4air d0d6977644 feat(orcad): run orcad itself on Windows hosts (W2) (#24529)
* feat(orcad): run orcad itself on Windows hosts (W2)

* test(orcad): load the ConPTY smoke's addon from out/orcad so the temp slot can be removed

* test(orcad): skip the foreign-uid lock case when running as root

---------

Co-authored-by: m4air <m4air@Mac.localdomain>
2026-10-02 01:52:51 -07:00
Neil 6153fbcfe4 Reduce redundant headless server CI work (#24527)
* ci: avoid unrelated headless server qualification

* ci: skip headless detection for ineligible draft PRs

* ci: preserve cross-host qualification and skip supplied prerequisites

* ci: include Windows server cache validation in change detection
2026-10-02 01:42:41 -07:00
OrcaWinandm4air b25f36a83f feat(orcad): Windows remote primitives for managed orcad hosts (W1) (#24525)
* feat(orcad): Windows remote primitives for managed orcad hosts (W1)

* refactor(orcad): run Windows host ops as node.exe with plain argv, no PowerShell hop

* fix(orcad): refuse secret-shaped names on the breakaway launcher's --env

* fix(orcad): name the secret env guard for its role

---------

Co-authored-by: m4air <m4air@Mac.localdomain>
2026-10-02 00:53:55 -07:00
m4air 89ab19824f Revert "revert: take the 26 Phase 3 (#16741 port) PRs back out of main (#24559)"
This reverts commit 5f308bfa9c.
2026-10-02 00:52:45 -07:00
OrcaWinandm4air 5f308bfa9c revert: take the 26 Phase 3 (#16741 port) PRs back out of main (#24559)
* Revert "feat(orcad): source-side dormant export of a relay-hosted SSH target (#16741 T6-8) (#24519)"

This reverts commit 783101b304.

* Revert "feat(ssh): update, roll back, recover and stop a managed orcad server (#16741 T6-5 follow-up) (#24463)"

This reverts commit 38c2d1dcb9.

* Revert "feat(ssh): deploy and pair an empty managed orcad server over SSH (#16741 T6-5) (#24453)"

This reverts commit 8b76683b40.

* Revert "fix(ssh): orcad GC honors the activation journal; readiness requires proven daemon coverage (#16741 T6 follow-up) (#24451)"

This reverts commit d3f8c5063b.

* Revert "feat(ssh): remote orcad stop by request file and journaled decommission (#16741 T6-4) (#24449)"

This reverts commit 43d9b43d3f.

* Revert "feat(orcad): supervisable server: stop requests, managed stop receipts and a lifetime that keeps its lock on failed teardown (#16741 T6-3) (#24433)"

This reverts commit b093d3ab20.

* Revert "feat(ssh): crash-safe orcad activation, rollback and recovery (#16741 T6-2) (#24423)"

This reverts commit 1a9ac0e955.

* Revert "feat(runtime): SSH access links for paired servers in a downgrade-safe sidecar (#16741 T5-1+T5-2) (#24420)"

This reverts commit 99db2bfae4.

* Revert "feat(relay): capability-gated owner reset with a durable preparation journal (#16741 T3 R1) (#24418)"

This reverts commit 34a582bd39.

* Revert "feat(ssh): track connection-manager drains, test probes and provider continuations (#16741 T2 P3+P8a) (#24407)"

This reverts commit d53063d2b1.

* Revert "feat(daemon): idle retirement, session census and recovery-only provider (#16741 T2 P4b) (#24409)"

This reverts commit ff212dbbef.

* Revert "feat(ssh): add pty.resumeClient and split SSH PTY process listing (#16741 T2 P5+P6) (#24414)"

This reverts commit 92cb71765e.

* Revert "feat(relay): await owned watcher and agent children on shutdown (#16741 T2 P1) (#24400)"

This reverts commit 6b36e4f85b.

* Revert "feat(session): retry failed renderer session writes and verify local folder PTYs (#16741 T2 P9) (#24406)"

This reverts commit d23ecef301.

* Revert "feat(ssh): remote orcad primitives on the pinned Node runtime (#16741 T6-1) (#24419)"

This reverts commit dd87ae578d.

* Revert "fix(runtime): fence runtime-environment subscriptions and status probes by identity (#16741 T5-3) (#24421)"

This reverts commit ece9e4d2e3.

* Revert "feat(orcad): migration manifest and dormant-state contracts (#16741 T6-7) (#24422)"

This reverts commit 3fbdaba262.

* Revert "feat(ssh): wire SshConnection through the work and transport close ledgers (#16741 T2 P2) (#24401)"

This reverts commit 4e8edc8872.

* Revert "feat(profiles): carry markdown frontmatter visibility in project transfers (#16741 T2 P7) (#24405)"

This reverts commit 60c93263cc.

* Revert "fix(runtime): project the PTY incarnation onto mobile session tabs (#24413)"

This reverts commit 99e0303572.

* Revert "feat(daemon): tag daemon stream data with the PTY incarnation id (#16741 T2 P4a) (#24402)"

This reverts commit 817af768b0.

* Revert "feat(ssh): port the SSH connection work ledger and transport close ledger (#16741 T2) (#24210)"

This reverts commit c9918931c8.

* Revert "feat(relay): fence and drain file and git response streams on shutdown (#24185)"

This reverts commit dc08ffeba9.

* Revert "refactor(runtime-rpc): extract the Node WebSocket lifecycle; opt-in pinned port (#24186)"

This reverts commit a789233bbb.

* Revert "feat(relay): route relay handlers through work admission; producer publication drain (#24181)"

This reverts commit 0b812bd698.

* Revert "feat(relay): land the #16741 T1 seam (work drain, publication drain, release gate) (#24156)"

This reverts commit 3aa2d3af7c.

---------

Co-authored-by: m4air <m4air@Mac.localdomain>
2026-10-02 00:52:32 -07:00
Neil 34ae0933e4 fix(worktrees): keep creation fast in large repositories (#24346)
* fix(worktrees): remove repeated scans and keep prepared checkouts fresh

* fix(worktrees): reclaim unlocked fallback preparations safely

* refactor(worktrees): simplify creation ownership and idle maintenance

* fix(git): keep ref maintenance armed after an index-only pass

An idle attempt that found the pack index due but refs still cooling down
returned without rescheduling, so loose refs from the arming fetch waited
for the next write instead of the ref cooldown.
2026-10-01 23:37:05 -07:00
Jinwoo HongandClaude cdfdadf9ea fix(runtime): settle tui-idle on hook state for agents whose hooks cover the whole turn (#24388)
* fix(codex): install Codex's Interrupt hook so an Esc-cancelled turn settles

Codex 0.150+ fires an Interrupt hook when the user presses Esc on an
approval prompt or mid-tool, and nothing else. Orca did not install it, so
the pane stayed blocked/working until the next prompt.

- Add Interrupt to the managed Codex events and label maps, written with
  Codex's 3s cap (a larger value triggers a startup clamp warning).
- Hash the timeout Codex hashes (Interrupt is clamped to [1,3], default 1)
  so self-computed trust matches Codex; pinned against a real 0.159.3 hash.
- Map a root Interrupt to the existing cancelled-turn record
  (markCodexLeadTurnInterrupted), keeping child work in the fold; a
  child-scoped Interrupt is ignored. Relayed rows take the same path.

* test(runtime): add a readiness census pinning every tui-idle verdict

Replays every recorded agent PTY transcript frame by frame through a real
runtime pane (agent-known and agent-unknown, clocked and clockless) and a
synthetic evidence matrix for all 43 TuiAgents, and compares each verdict
and tui-idle wait outcome to committed run-length-encoded baselines.

Refs STA-9098

* test(runtime): pin the census quiet probes to literal windows

A census that read TUI_IDLE_QUIESCENCE_MS would move with it; fixed 2999/3000 ms
reads and a fixed 2000 ms poll step make a changed window show as changed verdicts.

Refs STA-9098

* test(runtime): say which census probe writes runtime state

Refs STA-9098

* refactor(codex): let the hook builder own Codex's per-event timeout

The managed hook's timeout is now Codex's own normalization of the shared
budget, and every installer derives its trust entry from the hook it wrote,
so no installer repeats the Interrupt special case.

Claude-Session: codex-interrupt-hook review

* refactor(codex): route Interrupt through the Stop lead update with an outcome

Interrupt now writes the lead record through the same setCodexMainAgentTurnState
call as Stop, so markCodexLeadTurnInterrupted keeps its original signature.
Drops the child-scoped Interrupt guard: Codex never runs Interrupt hooks for
subagents and its input schema has no agent_id.

Claude-Session: codex-interrupt-hook review

* test(runtime): observe the census through settled panes and caller-visible waits

- Read each verdict through the runtime's own settle seam (evaluateTuiIdleForLeaf) instead
  of re-wiring evaluateTuiIdle/leafTuiIdleEvidence/buildTerminalWaitText, so the census is
  coupled to one runtime method, not to the module STA-9098 rewrites.
- Let the runtime finish each chunk (one macrotask turn) before reading. The old read raced
  work chained on the paint, so 14 frames pinned a microtask-ordering artefact.
- Record when a wait settles (@start vs @poll), not just its outcome.
- Exit each pane's PTY after reading it so its emulator is freed.
- Replace the hand-grouped families, literal fixture list and per-pane split flag with a
  directory-scanned catalog, one baseline per replayed pane, and size-balanced shards.
- Run the synthetic matrix in one file; it takes about 2 s.

* test(runtime): cross dialog-versus-ready-screen order with every title in the census matrix

Blocked detection is position-ordered (design doc 11.5): the later of a blocker and a ready
anchor wins. The matrix now paints a workspace-trust dialog after, and before, each agent's
ready screen under every title, so a rule engine that loses that ordering fails per agent.

* test(runtime): read the census baseline field without Reflect.get

The anti-slop lint rejects Reflect.get on parsed input.

* refactor(runtime): read Antigravity, Cline, Prime Agent and Cursor readiness from rule files

Adds agent-state-rules/: a zod-validated JSON file per agent, one priority list of
screen rules per agent (idle with strength and requiresQuiet, or hold), and text
anchors that feed the shared, position-ordered blocked layer every pane reads first.

The three screen-ruled agents and Cursor's approval menu and prompt move to data;
the Antigravity text scan stays code as a named anchor. Their old code paths are
deleted. Every other agent still runs through the existing lanes, unchanged.
The readiness census baselines are untouched and pass.

Refs STA-9098

* test(runtime): cover the agent state rule engine's schema, priority, rows, anchors and lanes

Refs STA-9098

* fix(runtime): refuse rule patterns that repeat an optional or alternating group

The load-time regex check only flagged a repeated group whose body held * + or {,
so (a?)* and (a|aa)+ passed though both backtrack exponentially. A repeated
group's body must now be fixed: no quantifier of any kind and no alternation.
The comment states the remaining polynomial gap instead of claiming linearity.

* refactor(runtime): give agent state rules and text anchors one when/answer shape

Every rule and text anchor is now when (a region and what it must show) plus
answer, each a discriminated union, so part (b) adds title, text and status
regions and working or blocked answers as new variants instead of new fields.

- Cursor's prompt is two anchors answering working and idle; the one-off
  workingIfAfter and followedBy fields become a general after test.
- Anchor literals and the probe banner must be lowercase, since they are
  matched against the lowercased tail.
- screenProbeBanner moves under profile, the place for non-detection facts.
- why is required on every rule and anchor.
- A blocked anchor must name a lastOf literal, which the prefilter keys on.

* docs: point the readiness evidence docs at the agent state rule files

* refactor(runtime): read Codex, Claude, OpenCode, Pi, OMP and Gemini readiness from rule files

The rule engine gains the regions and answers these agents need, as closed-list entries:
- rule regions `title` (the classified title status) and `text` (one of the file's idle text
  anchors, settled), and a `predicate` form of the screen region for named engine scans;
- `withoutClock: skip` for strong quiet rules a clockless pane must not believe;
- anchors (renamed from textAnchors) gain a `title` region, and `live` and `hold` answers;
- `profile.screenSource` (trusted grid or live screen), and an `unknown-pane` file for panes
  with no known agent.

Codex's header, composer and provisional-startup checks become named predicates referenced
from codex.json; its ready header, header and startup hold become shared text anchors. Native
idle title markers become shared title anchors; name-only title handling becomes each agent's
idle-title rule. The agent-specific branches in terminal-wait-detection.ts and
tui-idle-evidence.ts are deleted, and the "later live prompt cancels a blocker" rule now reads
only rule-file anchors (plus Muse, which moves in part b2).

No behaviour change: the readiness census baselines are untouched and pass.

Refs STA-9098

* test(runtime): cover the rule engine's title, text and predicate regions and the bundled anchors

Refs STA-9098

* fix(runtime): reject a rule file that repeats an anchor or rule id

A text rule names its anchor by id, so a repeated id let a file pass validation and then throw
while compiling. Also states that engineVersion bumps once a version ships; version 1 is still
being defined.

* refactor(runtime): fold the working anchor answer into live

The engine treated an anchor's working and live answers identically: both mark a live prompt
that cancels an earlier blocker and settles nothing. Cursor's busy prompt now answers live, so
anchors have one non-settling prompt answer.

Refs STA-9098

* refactor(runtime): read the shared π title anchor from pi.json alone

Pi and OMP paint the same `π - <session>` rest title, and title anchors apply to every pane,
so one copy covers both.

Refs STA-9098

* refactor(runtime): key every rule file and read the trusted screen from screenSource alone

readsTrustedScreen no longer also asks for a screen rule (every trusted file has one, and the
schema requires screenSource where it matters), so rule-less files need no filter. A rule's
match is a plain boolean, and compileTitleAnchors is module-private.

Refs STA-9098

* test(runtime): pin that a clocked Codex pane takes no other agent's ready text

No test failed when holdsReadyTextToQuiet was removed; this one does.

Refs STA-9098

* fix(agent-hooks): keep an OMP approval wait until omp resolves it

omp posts tool_execution_start a few milliseconds after
tool_approval_requested, while its Approve/Deny select still holds the
human. Both mapped onto the pane row, so the working event overwrote the
blocked one and the pane read as busy for the whole prompt.

A working event now leaves an OMP approval wait in place; only
tool_approval_resolved or a new turn ends it. An ask row is unchanged:
its own tool_execution_end ends it. The test replays the order a live
omp 17 run posted for a denied bash call.

Refs STA-9100

* refactor(runtime): select the fresh hook row on any of a terminal's handles or pane keys

selectFreshExplicitAgentStatus matched one handle and one pane key and
returned only the mapped status. The row selection now takes sets of
handles and pane keys, an optional received-at floor, and returns the
row itself, so a reader can see the main agent's own state. The old
function keeps its signature and result on top of it.

Refs STA-9100

* feat(runtime): let tui-idle read hook state for agents whose hooks cover the whole turn

tui-idle read no hook state. Hook state reached readiness only through
the `<Agent> ready` titles the window writes, so a headless `orca serve`
never saw it (#16095), and Codex settled only once its screen had been
quiet for three seconds.

Rule files gain `profile.hooks: "authoritative" | "identity-only"`,
defaulting to identity-only. Codex (with its Interrupt hook), OpenCode,
OpenCode 2, Pi and OMP are authoritative. For them a fresh hook-store
row decides ahead of every other lane:

- the main agent's turn decides (`mainAgent.state` when published), so a
  subagent's Stop does not end the lead turn: done settles strong,
  working holds, a permission wait never settles;
- the tail's blocked text goes through the existing permission arbiter
  with the turn as its explicit status, so a denied prompt's dialog left
  in the tail no longer blocks a turn the hook says ended;
- the row joins on every pane key and terminal handle the PTY owns.

No row, a stale, restored or other agent's row, a session-start done,
and a row from before a PTY respawn all fall back to today's lanes. That
keeps startup on the screen and text rules: Codex posts SessionStart
only with the first prompt. Claude, Cursor, Gemini and the rest stay
identity-only.

The readiness census has no hook server, so its frames are unchanged.

Refs STA-9100

* docs(agent-status): record readiness as a reader of the hook store

Refs STA-9100

* fix(runtime): ignore a hook done older than the latest input Orca wrote

A finished turn leaves a fresh `done` row. A caller that sends the next
prompt and waits at once could settle on it before the new turn's first
hook arrives, so the wait returned while the agent was starting work.

Orca's own input writes (terminal send, agent prompts, mailbox pointers)
now stamp a per-PTY input clock, and the hook lane reads no `done`
received before it; the pane falls back to the screen and text rules
until the agent reports again. A `working` row is unaffected.

Refs STA-9100

* docs(agent-status): note the input floor on the hook lane's done

Refs STA-9100

* fix(runtime): take the hook lane's input floor from the PTY run's input record

The hook lane ignored a done older than Orca's latest write to the pane, kept in a
new per-PTY map stamped by a wrapper threaded through four write sites. The PTY
run register already sits on both write funnels, so it now records the last
input (launch writes included, terminal replies not) and the lane reads it.
Keys the user types now count too, which closes the restart-in-the-same-shell
gap: typing `codex` to relaunch no longer lets the previous process's done read
ready while the new one boots.

The respawn floor moves from the shared row join into the lane, beside the
input floor; the freshest row predates a floor exactly when every row does.

* test(runtime): drop runtime hook-lane cases the unit suite already proves

Working over a ready title, a permission wait, and an identity-only agent are
decided inside evaluateTuiIdle and covered there; the runtime suite keeps the
wiring: the join, both floors, Pi's own OSC 133 markers and the arbiter.

* fix(runtime): record a PTY's last input even when main adopted it without a spawn commit

A materialized pane re-adopted by the renderer returns before the spawn-commit
site, so it had no run record and its input never moved the hook lane's floor.
The last input now lives beside the run records: any PTY's input counts, and a
new process's commit still clears it.

* fix(runtime): keep a running process's input time when main reattaches or adopts it

A reattach or adoption commit without an incarnation id cleared the PTY's
last-input time, so a prompt sent just before an SSH adoption was forgotten
and the hook lane could accept the previous turn's done as ready. Only a new
process (or a reattach naming a different incarnation) now starts clean; the
first-input fact follows the same rule.

* docs(runtime): say why a lead turn that ended reads ready while a subagent runs

* fix(runtime): refuse uppercase contains terms in text anchors, which read the lowercased tail

A text anchor's after and lines tests run on the lowercased tail, so an
uppercase contains term loaded and then never matched. Build the text test
schema from the literal it accepts and give anchors the lowercase one. Also
drop a probe-banner early return that no bundled catalog reaches.

* refactor(runtime): state Codex's provisional startup and title anchors as plain rules

The provisional-startup hold becomes a lastOf anchor with an all/none test, so
its TypeScript scan goes. Title anchors drop their status field (every caller
already gates on an idle title), and withoutClock keeps only the value a rule
can set.

* fix(runtime): leave Codex readiness to its title and screen rules

Codex before its Interrupt hook posts nothing for an Esc mid-turn, so its hook
row stays working and a hook-authoritative tui-idle wait hangs until the row
goes stale. Current Codex already settles fast through its ready title.

Co-Authored-By: Claude <noreply@anthropic.com>

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-10-02 01:36:30 -04:00
Neil 8ff6296bc7 Speed up serializer checks and keep native caches stable (#24476)
* Reuse serializer oracle cells and isolate native cache policy

* Preserve native cache post-save paths and record hosted oracle gain

* Record native cache reuse and separate cancel-test startup budget
2026-10-01 21:43:56 -07:00
Jinwoo Hong e3cb32791e refactor(runtime): read four agents' readiness from JSON rule files through one engine (#24348)
* test(runtime): add a readiness census pinning every tui-idle verdict

Replays every recorded agent PTY transcript frame by frame through a real
runtime pane (agent-known and agent-unknown, clocked and clockless) and a
synthetic evidence matrix for all 43 TuiAgents, and compares each verdict
and tui-idle wait outcome to committed run-length-encoded baselines.

Refs STA-9098

* test(runtime): pin the census quiet probes to literal windows

A census that read TUI_IDLE_QUIESCENCE_MS would move with it; fixed 2999/3000 ms
reads and a fixed 2000 ms poll step make a changed window show as changed verdicts.

Refs STA-9098

* test(runtime): say which census probe writes runtime state

Refs STA-9098

* test(runtime): observe the census through settled panes and caller-visible waits

- Read each verdict through the runtime's own settle seam (evaluateTuiIdleForLeaf) instead
  of re-wiring evaluateTuiIdle/leafTuiIdleEvidence/buildTerminalWaitText, so the census is
  coupled to one runtime method, not to the module STA-9098 rewrites.
- Let the runtime finish each chunk (one macrotask turn) before reading. The old read raced
  work chained on the paint, so 14 frames pinned a microtask-ordering artefact.
- Record when a wait settles (@start vs @poll), not just its outcome.
- Exit each pane's PTY after reading it so its emulator is freed.
- Replace the hand-grouped families, literal fixture list and per-pane split flag with a
  directory-scanned catalog, one baseline per replayed pane, and size-balanced shards.
- Run the synthetic matrix in one file; it takes about 2 s.

* test(runtime): cross dialog-versus-ready-screen order with every title in the census matrix

Blocked detection is position-ordered (design doc 11.5): the later of a blocker and a ready
anchor wins. The matrix now paints a workspace-trust dialog after, and before, each agent's
ready screen under every title, so a rule engine that loses that ordering fails per agent.

* test(runtime): read the census baseline field without Reflect.get

The anti-slop lint rejects Reflect.get on parsed input.

* refactor(runtime): read Antigravity, Cline, Prime Agent and Cursor readiness from rule files

Adds agent-state-rules/: a zod-validated JSON file per agent, one priority list of
screen rules per agent (idle with strength and requiresQuiet, or hold), and text
anchors that feed the shared, position-ordered blocked layer every pane reads first.

The three screen-ruled agents and Cursor's approval menu and prompt move to data;
the Antigravity text scan stays code as a named anchor. Their old code paths are
deleted. Every other agent still runs through the existing lanes, unchanged.
The readiness census baselines are untouched and pass.

Refs STA-9098

* test(runtime): cover the agent state rule engine's schema, priority, rows, anchors and lanes

Refs STA-9098

* fix(runtime): refuse rule patterns that repeat an optional or alternating group

The load-time regex check only flagged a repeated group whose body held * + or {,
so (a?)* and (a|aa)+ passed though both backtrack exponentially. A repeated
group's body must now be fixed: no quantifier of any kind and no alternation.
The comment states the remaining polynomial gap instead of claiming linearity.

* refactor(runtime): give agent state rules and text anchors one when/answer shape

Every rule and text anchor is now when (a region and what it must show) plus
answer, each a discriminated union, so part (b) adds title, text and status
regions and working or blocked answers as new variants instead of new fields.

- Cursor's prompt is two anchors answering working and idle; the one-off
  workingIfAfter and followedBy fields become a general after test.
- Anchor literals and the probe banner must be lowercase, since they are
  matched against the lowercased tail.
- screenProbeBanner moves under profile, the place for non-detection facts.
- why is required on every rule and anchor.
- A blocked anchor must name a lastOf literal, which the prefilter keys on.

* docs: point the readiness evidence docs at the agent state rule files

* fix(runtime): refuse uppercase contains terms in text anchors, which read the lowercased tail

A text anchor's after and lines tests run on the lowercased tail, so an
uppercase contains term loaded and then never matched. Build the text test
schema from the literal it accepts and give anchors the lowercase one. Also
drop a probe-banner early return that no bundled catalog reaches.
2026-10-01 22:16:06 -04:00
Neil f69052e113 Reuse qualified Windows server builds and dependency verification records (#24448) 2026-10-01 16:19:40 -07:00
OrcaWinandm4air 43d9b43d3f feat(ssh): remote orcad stop by request file and journaled decommission (#16741 T6-4) (#24449)
Clients stop an orcad that advertises health.stopRequests through its slot-local request file and keep SIGTERM for older builds. Decommission runs through the activation journal and fence: it refuses while the terminal census is live or uncounted, stops the instance with an instance-bound managed request, cancels a stop orcad never acted on, and deactivates the record only on proven exit. orcad gains --cancel-managed-stop and an exclusive per-transaction decision file so a cancel can never race a dispatched stop. POSIX-only and inert: no production caller.

Co-authored-by: m4air <m4air@m4airs-Air.localdomain>
2026-10-01 13:32:25 -07:00
OrcaWinandm4air b093d3ab20 feat(orcad): supervisable server: stop requests, managed stop receipts and a lifetime that keeps its lock on failed teardown (#16741 T6-3) (#24433)
orcad stops through slot-local and instance-bound request files, so a reused PID is never signalled. A managed stop is proven by its completion command and recorded as a receipt. Optional daemon retirement is best effort: an idle daemon retires, while a busy or unverifiable one stays up with its admission fence released. Runtime teardown runs in reverse order and keeps the instance lock and profile admission when any writer fails to stop. Browser discovery no longer delays readiness. Legacy worker recovery and watcher children are drained before the final flush. Headless terminal close no longer waits on a renderer tab that does not exist. No production deployment.

Co-authored-by: m4air <m4air@m4airs-Air.localdomain>
2026-10-01 12:45:34 -07:00