The diff-review dock has no next-step bar, so its bottom action now offers
Resolve with <agent> for a conflicting pull request, with the launch notice.
In the hub the bar shows its agent launch notice on the Pull request tab
too, since the removed box was the one that showed it there, and an Unlink
failure reaches the bar's notice now that the PR tab has no footer.
* fix(ui): notification cards lift only for the chat input they would cover
The lift measured the composer's full-width wrapper, so with the right
sidebar open the update card rose above an input it never covered. Measure
the centred input column instead, and keep observing the full-width strip so
a sidebar toggle that moves the column still re-measures.
* fix(ui): notification cards re-measure when only the chat input column resizes
Changing the chat width setting resizes the centred input column while its
full-width pane keeps its size, so the cards could stay over Send and Stop
or stay lifted for nothing. Observe the measured column as well as the pane.
* test: drop a type assertion in the notification card stack test
* Show the native default effort for OpenCode models
* Show the effort OpenCode 1.x actually runs when none is picked
OpenCode 1.x ACP runs a listed default variant, else the first listed
one, so declare that same variant instead of a no-override Default. The
draft and launch default stay as on main; the resting fallback now shows
it too. Shared declared-effort consumers expect no effort for a readback
without that model's menu.
* Name the recorded OpenCode listing test for what it checks
* fix(sidebar): invalidate activity summaries on every source snapshot
* test(sidebar): cover status pings and title writes in the activity summary perf contract
* test(sidebar): drop the double cast in the activity summary perf contract
* test(sidebar): type the perf contract counter without a broad object
* test(sidebar): key perf contract rows by worktree id
* fix(emulator): keep the live session and prefer a booted device when reopening
An untargeted attach chose a default device before checking the workspace's
live session, and that default took any iPhone over a booted Android
emulator. Reopening the tab could stop a running Android session and boot an
iPhone. The host now reuses the live session first and its default prefers an
already-booted device on either platform. The pane's mount auto-attach leaves
the choice to the host instead of picking its own iPhone-first default.
* fix(emulator): keep the workspace's booted device when its stream went stale
* refactor(emulator): let the default attach device resolver own the no-device error
Keeps orca-runtime-emulator.ts under the 300-line cap after rebasing onto main,
and matches the attach test to main's backend-stamped session info.
* test(emulator): type the AVD fallback mock for an optional device
* Save native chat state and restore only its journal tail
Publish versioned reducer checkpoints atomically, checkpoint through the chat write queue, and backfill closed chats without retiring journal rows.
Co-Authored-By: Codex <noreply@openai.com>
* Keep checkpoint recovery durable and skip unchanged captures
* Keep journal timer and restart fixtures compatible with checkpoints
* Keep checkpoint performance tests focused on operation contracts
* Remove unused benchmark import
* Restore journal append interception and control Stop fixture time
* Compare saved reducer state without a key assertion
* Supply thread scope in checkpoint test appends
* Compact checkpointed native chat journal revisions
Delete fully superseded item and lifecycle rows inside the paced checkpoint job, retain first/latest cursor touches and current witnesses, and reclaim incremental-vacuum pages. Allow catch-up to cross retired prefix rows.
Co-Authored-By: Codex <noreply@openai.com>
* Prove restored journal consumer paths
* Validate checkpoint authority before retiring journal copies
* test: exercise restored consumer backward pagination
* Skip unused open-chat checkpoint replay during maintenance
* fix: pace journal backfill with a monotonic clock
* Repair compacted history test fixtures and paging expectations
* Verify paced backfill through journal retirement and restore
* Admit shared journal fixtures before use and separate performance contracts
* test(native-chat): verify request publisher lifetimes after reopen
* refactor(native-chat): type the history journal read surface
* refactor: keep journal opening cursor checks together
* refactor(native-chat): colocate journal history read types
* test: align journal compaction integration ownership
* refactor: project chat journal state in the append transaction
Track isolated reducer mutations and persist keyed changes under a savepoint before adopting committed state. Keep appends working through projection lag and repair coverage on the write lane, including legacy bootstrap.
Co-Authored-By: Codex <noreply@openai.com>
* fix: keep reducer objects live across journal commits
The draft isolates every write until COMMIT, then writes each dirty copy back
onto its original, so submissions, items and queue cards handed out before a
commit keep reading current values as they did with in-place folding. A failed
COMMIT still leaves live state untouched. Also replaces banned Reflect.get uses
and adds braces the lint rule requires.
* fix: bound projection repair and check the invariant after notification
Failed publications and savepoints back off from 1 s up to an hour, reset by a
healthy incremental write or a reopen. open() no longer waits for a legacy
chat's publication; the scheduled repair publishes it on the write lane. A
failed open closes its handle. The equality check runs after commit
notification, only when projection tests opt in or, log-only and sampled, in
development, and it requires the saved coverage to match. Removes the unused
streamed commit argument.
* fix: keep the background projection pass proportional to chats
The orphan sweep reads one state row per chat and clears orphans by session
key. A chat whose fold cannot publish stops at its first damage and is skipped
until its epoch or newest row changes.
* fix: version the keyed projection layout as codec 2
This branch's earlier whole-state layout used version 1; it now decodes to null
and the chat replays.
* test: follow the append-with-fold contract and deferred publication
A submission whose fold throws now rolls back with its receipt before any
dispatch, so those sends are refused and nothing is recorded. The unconfirmed
continuation outcome is pinned through its real cause: the agent admits the
message and no delivery proof arrives. Tests that need saved state right after a
chat opens publish it explicitly, the history reload clears the saved state
covering its edited row, and the codex stream bound matches its capture.
* test: pin projection repair backoff, background pass and N/10N costs
Covers the production repair timer under a persistent failure, a legacy open
that publishes after it resolves, a failed open leaving no timer, a damaged
closed chat skipped until a new row, and equal per-write, reopen, sweep and
closed-chat publication work at N and 10N. Projection tests opt into the
per-commit equality check.
* refactor: inline draft write-back helpers
The repo lint bans object-typed parameters; the copy and write-back now run in
the closure that already holds the wrapped value.
* fix: write a new epoch's saved state in its own transaction
New chats, rollovers and rewinds publish the new epoch's projection beside its
rows, inside the same statement-only savepoint the append path uses, so they
start covered instead of waiting a second for a repair. A projection failure
there still keeps the epoch and leaves the scheduled repair to publish it.
* fix: keep the sampled development check log-only on any failure
A read failing inside the check must not reject an append that already
committed and notified.
* fix: typecheck the draft copy without closure narrowing
Assign the lazily created copy through a local so strict programs that do not
narrow a captured variable after ??= still see an object.
* test: catch whole-table sweeps and an undecodable projection
The sweep contract now records exec statements too and pins its exact keyed
statement list, so a NOT EXISTS scan through exec fails it. A projection whose
item stops decoding fails the per-commit check on coverage although a full
replay still matches. Also fixes two test lint findings.
* refactor: drop draft casts the types can carry
Overlay maps and sets finish from their own typed touched keys, and present map
entries are read through one helper. The two remaining generic boundaries, a
draft standing for its object and finishing back to it, carry the repo's SAFETY
directive.
* test: show a parked damaged chat publishes after a clean epoch replaces it
The replacement ends at the parked chat's newest sequence, so only the epoch in
the skip key re-arms it.
* test: give the seeded queued card its enqueue cursor
Production records queuedAt as the cursor before the queue row; the fixture
now does too.
* fix: catch lagging saved chat state up in atomic pages
Repair of a legacy, lagging or undecodable chat, open or closed, no longer
republishes the whole chat. One runner folds the rows after the saved coverage
onto a private copy of the saved prefix, at most 32 rows or about 1 MiB of row
text per page, and commits each page's changed entries with the new coverage in
one FULL transaction. That transaction first checks the chat's epoch and the
exact saved row the page was folded from, so a page from a retired epoch or a
stale base writes nothing. Pages rest between slices, and the saved prefix is
decoded in pages too.
An open chat runs the pages on its write lane; sends keep committing between
them and skip the projection until coverage reaches the tip, then project
incrementally again. The background pass hands a chat over to its open owner at
a page boundary. Damage parks the chat after the pages before it, and a failed
page keeps the committed ones and retries from them on the existing backoff.
Whole-chat publication now runs only inside epoch transactions.
* test: pin the draft layer's tracked nodes per streamed revision and acceptance
A transition now reports how many objects and collections its fold reached. The
scaling chat gains accepted sends (receipts and aliases) and waiting, dispatched
and returned queue cards at N and 10N. A streamed revision's only growing term
is the card scan, one node per card plus each returned card's body; an echo
also reads every item with its body and every submission.
* test: append the between-pages send by item identity
appendItem takes the provider identity, not its key.
* test: check every catch-up prefix of the recorded Claude and Codex streams
A runner can page single rows, so the recorded streams' aliases, Stop settlement
and per-row timestamps are each checked at a committed prefix against a full
replay.
* test: measure each backfill pass's row reads on its own
The parked-chat test counted its own replay checks: 64 pass rows plus 68, 68
and 100 oracle rows made the 300 CI saw. Each timer window is now measured
alone, and coverage is read from its saved row, so the unchanged pass reads 0
rows and the re-armed one reads one page.
* fix: bound catch-up reads, release the finished prefix, and keep unreadable views
- A catch-up page now stops reading rows at the row whose text reaches about
1 MiB, so rows past the budget are never fetched and fetched again; saved-view
item and entry pages use the same budget.
- An open chat drops its private prefix once coverage reaches the tip and keeps
it only across a failed or parked page.
- A present current-epoch view this build cannot read (another codec version or
corrupt content) is no longer cleared by the first page. Its whole history
must fold cleanly through the tip first; otherwise it parks untouched. A
storage error while reading the view fails with backoff instead of reading
as a missing view.
- The pace charges only the runner's own work units, so time spent waiting on
an open chat's catch-up or the write lane no longer lengthens the next rest.
* test: cover takeover, epoch replacement and stop in the middle of a pass
A chat opened while the pass rests is caught up by its own runner from the
committed page; the pass pages it no further and does not charge the wait to
its pace. A replacement leaves its new view untouched, and a stopped pass
resumes after its last committed page.
* test: fail the takeover test without the handover break, and the replacement test without the stale-runner guard
The takeover test asserts the pass asks the open owner only twice for the
handed-over chat, and pins performance.now so the open runner's pace never
waits on a fake timer. The replacement now lands while the open runner is
resting in its saved-view decode, so its page reaches the lane after the
replacement; the test asserts no transaction opens.
* test: read saved-view pages with the page budget, and await database closes
The paged-decode round trip passes the row-and-text budget and checks the
view decoded. Projection, scaling and ACP launch tests await the now-async
test database close, so a closing checkpoint worker cannot close the next
test's database.
* Persist native chat outcomes with a rebuildable cache
Store immutable keyed transition results with canonical ordering, fence outcome epochs, and convert legacy inputs through paced invisible generations. Rebuild disposable caches from validated outcomes and read sparse logical sequence groups without changing the wire.
Co-Authored-By: Codex <noreply@openai.com>
* test: repair the split suites so they parse, lint clean and find their setup
Restores the describe blocks the split truncated, the loop variable it renamed, the
fixture references and imports it dropped, and a stray argument pair. Moves the
grandfathered flaky-pattern counts with the code that moved.
* test: read outcome epochs as outcomes where the adapted assertions read input rows
A replaced epoch restates its Stop in the saved pause marks, the sparse-group batch
test needs an outcome epoch rather than the input-format fixture, and a revised item
keeps its first place, so the held-write order is read from the replayed groups.
* test: expect saved queue cards as whole values in the queue-history assertions
The adapted helpers read card outcomes, which store each card's whole state, so an
import or refusal shows as the card's own state change rather than as an input row.
* style: format the files this PR changed
* test: import each module once in two journal suites
* fix: decode saved outcomes with a frozen format-1 schema, independent of the cache codec
Outcome values decode through a versioned format-1 schema that never follows the live reducer type; an unknown field reads as saved by a newer Orca, and the cache codec only delegates to it, so a codec bump rebuilds the cache and nothing else.
* fix: key outcomes by an integer generation and keep the cache stamp in its state row
Each outcome row names its generation, the attempt's id, instead of repeating the chat id, epoch and a UUID; the cache stamp is a column of the cache's own state row, so there is one stamp to keep in step; cache ordinals are text like the outcomes they copy. Orphaned caches are swept from the per-chat state row with indexed per-chat deletes. The WSL census lists both schema files.
* fix: finalize queue ownership before publishing a new epoch, and reject unreadable outcome rows
Epoch replacement and rollover adopt the committed state, keep attachment claims and finalize the queue receipt before the fallible publication step, as before outcomes. Every persisted outcome row is read back through the row reader, so a row it rejects fails as journal_row_rejected. Publishing an epoch checks the epoch it replaces is still current. A key deleted and re-created in one write moves to the end of the pending changes, matching its new ordinal.
* fix: open a chat synchronously and unpaced, and classify read failures by cause
A user's open reads the cache or rebuilds from outcomes in one synchronous pass, like replay on main, so no background rebuild can interleave with it and nothing paces or bills it. Only an outcome decode failure is damage; a value from a newer format is refused as newer; storage errors propagate as unavailable. Writes derive cache currency from the stamp instead of a latch and ask the maintenance runner when it lags.
* fix: run all journal maintenance through one paced runner per database
One runner serves requested chats first, then lagging ones, one catch-up at a time, open or closed, so an open chat keeps its conversion's progress. A busy or replaced chat is skipped and the pass continues; content that cannot convert parks until the chat's rows change; storage failures back off. Background work alone pays the duty cycle. Conversion verifies the whole input once, then only the outcome tail; cache rebuilds copy outcome pages to the moving tip and stamp from the scalar outcomes.
* test: adapt journal suites to generation-keyed outcomes, the merged cache stamp and the publication order
Queries read outcomes by generation; the bootstrap test expects the queue receipt to finalize before publication; queue-import-scaling states the reopen's constant two key visits when it retries a failed import; append-delivery reads the outcome change index's item ids.
* test: pin outcome format 1 with checked-in rows, and cover open consistency, transient reads and re-created keys
A golden fixture of format-1 outcome rows covering every field and scalar must restore to the pinned chat; a cache codec bump only rebuilds the cache; an unknown field reads as newer. An open between two pages of a cache rebuild reads the whole chat from outcomes. A transient read error during open is unavailable, not damage, and the next open loads the chat. A key deleted and re-created around a new key in one row keeps live order, written or converted.
* refactor: check a converting chat's epoch once, in the catch-up step that runs each page
The catch-up reads the chat's epoch in the same synchronous step as the page's transaction, for conversion and cache rebuild alike, so the conversion's second copy of the check is dropped.
* test: drive the maintenance runner over a real database, each guard killed by a mutation
Startup sweeps, closed chats converted one at a time with a busy chat skipped, an open chat writing between conversion pages, a stop between pages, an epoch replaced mid-conversion, content parked until the chat writes again and then delivered, and a storage failure backed off rather than parked.
* test: N/10N contracts for outcome appends, opens, conversion, publication, idle passes, sweeps, tail verify and wire catch-up
Each counts statements through prepare and exec, rows read per table and rows and bytes written, never time, and requires the same work for a chat ten times larger: a streamed revision, a Codex plan update and an acceptance; a cached open reads no outcome; a conversion page reads one page of input and publication none; an idle background pass reads no history; a retired generation and an orphaned cache are deleted one indexed page at a time; a second verify reads only the new outcomes; a wire catch-up reads only the groups asked for.
* test: shipped builds keep a new or converted outcome chat untouched
The newest release refuses the chat as a newer Orca's and leaves every byte of the database as it was; a build from before that reason opens it read-only with nothing shown, refuses writes, and changes no saved row.
* test: an epoch publication over an epoch the caller did not see is refused, and damage at row 1 still yields to a newer row
Publishing a new epoch checks, inside its transaction, the epoch the caller last saw, and writes nothing when it changed. A chat whose first row is unreadable keeps reading for a newer build's row, as main does, and is refused as a newer Orca's.
* test: old-build probes fold input rows only, and the interrupted-call probe writes inputs
* test: import the state layout once in the cache test support
* fix: type the tail verify's live lookups per collection, and two test call shapes
The tail verify looked keys parsed from stored JSON up in a union of live maps, which does not typecheck; each format-1 collection now has a typed lookup that narrows the parsed key first, and the table is checked complete against the format's collection list.
* fix: wake the maintenance runner for a request or a due retry ahead of the periodic pass
One timer now wakes the runner at the earlier of the next periodic pass and the first due request or storage retry, re-derived from the waiting chats after each pass, so a request after the first pass is served within a second and a backoff retry is no longer replaced by the six-hour pass. A chat whose load swept a retired page keeps its turn instead of waiting for the next pass. Tests drive start(), requests and timers on fake time.
* test: pin the draft's tracked nodes per streamed revision and acceptance at N and 10N
The scaling chat gains dispatched and returned queue cards. A streamed revision's only growing term is the queue card scan, one node per card plus each returned card's body; an acceptance echo also reads every item with its body and every submission. Main's reducer makes the same scans on these rows; the draft adds one node per value reached.
* test: cross-version probes read a new chat's turn end as one outcome sequence, and the kept-card downgrade uses an unconverted chat
* fix: store every new write as format-tagged outcome records after an existing chat's rows, with no conversion
An existing chat keeps its input rows byte for byte; its first write appends one marker row that
shipped builds refuse, and its records follow. New chats hold only their marker and records. Each
record carries its own format and the epoch keeps the highest format it holds, checked before a
cache is used or anything is written. Opening a chat with an input prefix folds the prefix as main
does and applies the records over it, deletions included, keeping prefix keys in place; catch-up
pages the prefix rows, then the record groups. Background conversion and its attempts, staging,
verification and publication are gone; the maintenance runner rebuilds only caches of chats without
a prefix, parks a rebuild on its epoch's records rather than the newest sequence, and looks a
requested chat up by its key.
* test: pin the marker, prefix-plus-records reopen, record admission before the cache, cache-only runner parking and N/10N work
Input fixtures stand for a chat an older build wrote: their input epoch keeps taking input rows, so
the input reader still meets writer-made rows; epochs this build founds are written as it writes
them. Conversion tests give way to a mixed chat whose prefix keys are deleted, recreated and updated
in place, the runner's rebuild parking that later writes never re-arm, and contracts for writing
to, opening and rebuilding chats at N and 10N.
* fix: refuse a chat whose outcome marker is a newer version as a newer Orca's, not as damage
* test: shipped builds refuse an existing chat at its appended marker, its input rows unchanged, and this build reads it whole again
The probe writes three items as input rows the way an older build did, then this build's writes
append one marker and outcome records; the newest release refuses the chat as a newer Orca's with
every byte unchanged, the writable baseline latches read-only at the marker, and the re-upgraded
build reads all six items with the prefix rows as they were.
* test: read the runner's rebuild instances as rebuilds, so the parked-chat test typechecks
* fix: admit saved outcome records and the cache only through a strict storage schema
A saved record or cached value holding a key or union tag this build does not declare, at any depth, now refuses the chat as a newer Orca's before the cache is used or anything is written. The storage schema reuses the wire's shared definitions, completes the keys they leave out (failure facts, senders, edit patches and the rest), and closes every object and open union; string vocabularies and opaque payloads keep the wire's meaning. A compile-time check fails CI when a persisted type gains a key storage does not declare, and a checked-in corpus of every declared shape replaces the schema fingerprint, so an added optional key needs no new format.
* fix: refuse an input row or legacy card holding a key this build does not declare before folding it
Restating a chat on a new epoch is safe only if the open chat holds nothing this build half understands. An input row of a known kind (an existing chat's frozen prefix, with or without outcome records after it) is now checked key by key against what this build declares before main's reader normalizes it, and refuses the chat as a newer Orca's; values keep main's checks and execution options their legacy meaning. A legacy queued card whose saved body holds an undeclared key stays on disk, unadopted, as an unreadable card does. Client sends already arrive through strict request schemas, and their options through a reader that drops choices this build does not use.
Main's tests that kept a newer build's unknown body kind, subject or key readable and writable now expect the refusal; the three that drove a newer Orca's approval or item through this build's own writers are removed, since this build can no longer hold one. A checked-in input prefix pins how this build folds older rows, and every value it folds into is one storage admits.
* test: a persisted type holding a key storage does not declare, nested included, fails to compile
* test: this build refuses a newer build's body or subject kind as a newer Orca's, keeping the row an older build deletes
* fix: fold each outcome write from the row a reload reads, so an annotation the reader drops never fails the strict record write
An ACP usage report with size 0 (allowed by the protocol) reached the model as an unusable window, the strict encoder refused it, and the agent was stopped mid-turn. Main writes that row and drops the annotation on reload; folding the read-back row keeps live state equal to that reload for every annotation the reader drops.
* test: an echo declared without a known original is stored as null, the shape a reload reads
* test: probe the downgrade refusal on both releases in the downgrade window, not only the newest
* test: both releases in the downgrade window write a Claude and a Codex chat through their own writers, and this build admits every row and opens the chat as that release had it
* test: rewind, replacement and rollover of a chat holding old rows, the marker and records keep what the user kept and delete the retired epoch whole
* test: phone and paired catch-up over a chat holding old rows then records, from a cursor inside the old rows, draws as the clients render it
* test: ACP launch decisions read an outcome chat from its cache and from its records alone, and a newer one as unreadable
* Open new and mixed chats from each key's newest record and drop the saved-state cache
The cache copied each key's newest record into a second set of tables and needed stamps, a paced
rebuild, a savepoint fallback and a repair runner to stay usable. The records' key index already
answers the same read: an open seeks from one key to the next, taking each key's newest record
(deletions included) and never reading superseded revisions. A mixed chat still folds its frozen
input prefix first. A send now writes only its records, the epoch's coverage and its receipt, so
any failure among them refuses the send as main's row insert does.
The background runner keeps only the paced sweep of retired generations, its one remaining job.
The cache tables are no longer created; they never shipped.
* Derive an outcome chat's last sequence from its coverage instead of recording it
Every write recorded the sequence scalar beside its own records, about half the records on
streamed paths. The epoch's coverage already holds it, so a read supplies it from there and a write
no longer stores it. Records an earlier build stored still decode.
* test: count strict admission per open, catch-up page and write of an existing chat at N and 10N
Admission walks each input row it reads once (on top of main's parse), and each outcome record it
reads or writes once: the open of a mixed chat walks exactly its prefix rows and admits one record
per key, a catch-up page walks one row per input row it returns, and a write walks its row's
read-back and admits each record it inserts. Linear in what is read, with a constant of one.
* Keep a record that updated a prefix key when a later prefix fold no longer yields that key
A tail record with the prefix ordinal is the key's newest value. If a later
build's reducer reads the old rows differently and no longer produces that
key, the value is appended instead of refusing the whole chat as damaged;
only that key's place can change.
* Resume each sweep page at the generation it is deleting
After a page of records the sweep went back to its start position, so every
later page rescanned every live chat's generation numbered below the retired
one. It now resumes at that generation; a contract at N and 10N live chats
pins that only a pass's first page walks them.
* test: the sweeper rests nine times each page's work
* Start the retired-record sweep from the chat database the attachments already take
The sweep was wired through an optional parameter, so dropping it at the one
production caller would have left retired records forever with every test
passing. It now runs on the required journal database, and a wiring test
checks that installing starts it and stopping ends it.
* test: an existing chat whose first write fails keeps no marker, and the newest release still opens and writes it
* test: chats the window's releases and the oldest release with this chat database wrote are edited, sent to and rewound by this build as the newest release does
Each release writes a Claude and a Codex chat through its own writers. This
build opens it, edits a card the old rows hold (its first write: the marker
and an in-place update), sends, rewinds (every kept message and card saved
again through the strict encoder) and reopens, with every commit restoring
to the live chat. The result equals the newest release's after the same
steps. The oldest release is resolved from tags, as the window is.
* test: the released-chat writer resumes the queue after every Stop it records, and the probe reads each step's result once
* test: the released-chat probe checks this build's edit, send and rewind on its own result
Comparing the carried chat with the newest release's would fail the required
cross-version check for any legitimate main change to those flows until the
next release ships. The probe still admits every released row, opens the chat
as the release and the newest release do, keeps the release's rows byte for
byte with one marker, and restores to live after every commit; after that it
checks the edited card, the accepted send and the rewind's survivors. The
oldest release with the per-host database is named directly: it never changes.
* test: the golden input prefix holds data in every keyed collection
Six collections folded empty, so a change to how old rows derive their keys
went unnoticed there. Eight rows v1.4.245 wrote through its own journal (an
item with an execution owner, a declared echo, a removed turn, and a queued
card handed over with carried history, then cancelled in doubt) follow the
existing rows unchanged, and the test now requires every collection to be
non-empty.
* Say once, beside the marker version, that the reading of old rows under it is frozen
The fold comment claimed an unheld prefix-ordinal value only moves that key;
a prefix read differently can also show a key twice or bring back one the
tail deleted. The marker version now states the rule: a build that reads old
rows into different keys or values keys that reading off a new marker
version, and duplication or resurrection is never intended.
* test: the released-chat probe compares what the release wrote, not fields this build adds
The open check compared whole snapshots, so a field main starts setting would
fail the required cross-version job until a release ships it. It now compares
the release's items, sends and cards, in order and by value, allowing added
fields; the byte-identity and restore-equals-live checks are unchanged.
* test: say why the first-write-failure downgrade test needs a longer timeout
* Type the open-union fallback check by schema, not a bare object
* Check each outcome-format key set separately so no check reads as a redundant union member
* Read an open or branded string as a value in the storage key check, not as an object
* Decode each newest outcome record from the value admission parsed, without parsing or walking it again or keeping its text
* Match each encoded record to its change by position, so a settlement batch's encode stays linear in its mutations
* Encode each changed value as the draft holds it, without reading it through the draft's tracking
* test: rewind, replacement and rollover restate a chat with fixed statements and work linear in what they restate
* Compact superseded chat outcome records in paced background pages
* Bound outcome retention and isolate unreadable cleanup sources
* Detach historical consumer snapshots and type replay results
* Refuse outcome prefix bindings with missing keys
* Make saved-row test table-name conversion explicit
* Keep outcome cleanup compatible across declared record formats
* fix(native-chat): keep main's reading of a prefix-position record the prefix lacks
Cleanup never deletes a key's newest record or touches the input prefix, so it
needs no new reader check. Refusing the whole chat over one such key reversed
main's deliberate append fallback and is out of this change's scope.
* test(native-chat): prove the failed cleanup page is retried, drop two checks that cannot fail
---------
Co-authored-by: Codex <noreply@openai.com>
Co-authored-by: Kelvin Amoaba <97001695+AmoabaKelvin@users.noreply.github.com>
* fix(activity): keep running workers listed after their coordinator ends its turn
Child agents are hidden from the Agents list by default. Since coordinators
now end their turn while their workers run, a finished coordinator hid every
running worker and the list had no Working row for that work. A live child
now stays listed unless a live ancestor already represents it.
* fix(activity): keep every running child agent listed regardless of its coordinator's state
* chore: drop local lockfile churn picked up by the main merge
The Source Control hub's next-step bar is now the only bottom action on the
PR tab: the tab body takes its footer from the caller, and only the
diff-review dock passes the old bottom action. The legacy Conflicts box is
gone, since the gate row and the bar's Resolve already cover it, so a
conflicting PR no longer says so four times. The bar keeps its reason line
only where its button does not name the blocker.
* fix(terminal): observe foreground at the physical PTY owner
* fix(terminal): keep existing inventory, inspection and display semantics around master-group foreground
Review round 1 fixes for the physical-owner foreground observation:
- Stop and liveness verification keep complete-inventory proof: the router's
scoped listProcesses({ptyIds}) is owner resolution again (absent = []).
Only the launch guard's old-owner fallback asks for an established
target's owner via an internal targetOwnerOnly option.
- Degraded daemon mode routes foreground observations and target reads to
the established owner, so an unreachable unrelated daemon cannot refuse a
known terminal there either.
- Display and name refreshes read the master's foreground group but take
member rows from the shared single-flight process-table snapshot; no
per-terminal ps per refresh. Recognized agent names skip the confirm scan
again, and builds without the native accessor keep the existing reader.
- Ordinary inspections keep their first-match routing; strict owner and
incarnation checks apply only to foreground decisions. The unused
foregroundOnly preload/IPC/RPC surface is removed.
- Local inventory forwards only the target scope, never caller deadlines.
- An interpreter running an agent script counts as that agent, as before;
a blank argv row no longer voids a terminal capture outside the
foreground group.
- Bump the packaged compatibility contract to daemon protocol 55 and move
the node-pty accessor above the process getter's doc comment.
* fix(terminal): keep the node-pty patch hunk well-formed and drop redundant foreground tests
Remove two stray context lines from the src/unixTerminal.ts hunk so its body
matches its header (strict patch parsers reject the mismatch), and update the
lockfile patch hash. Prune foreground tests whose rows repeat branches the
parity table already covers.
* fix(terminal): index the shared snapshot by TTY once and keep observation age nonnegative
Display refreshes filtered the whole shared process table per pane, so
work grew with panes times processes. Group each snapshot by normalized
TTY once, memoized by array identity, and look each pane up directly;
the scaling contract now counts row TTY reads at N and 10N panes.
Both foreground observation producers clamp capturedAgeMs at zero, so a
wall-clock step back during the read no longer yields an envelope the
validator rejects and the launch guard refuses.
* test: move foreground-observation compat tests into the protocol compatibility suite
Main removed daemon-pty-adapter-steady-state-compat.test.ts; the merge restored it with only this branch's block. Reuse the suite's existing inspection adapter helper so no new type assertion is added.
Collapsed parents each walked their full subtree per render, which was
quadratic on deep lineage chains. Build all parents' signal states once per
lineage tree identity instead.
Fixes STA-13325
* Show the retry command when worker_done times out on a frozen Orca
* Say nothing was sent when only the contract check timed out
* Say nothing was sent even when the retry command cannot be printed
Rows lead with the file name and put its folder under it, so names stop
truncating. The whole row opens the diff, one quiet button stages or
unstages, and discard moves to a left swipe that still asks first. A
status line, a Commits row and a conflict banner with Abort sit above
Uncommitted and Staged sections that carry Stage all and Unstage all.
The rarer git actions move into the header's grouped menu.
* fix(git): apply textconv filter to original blob in diff view (#37100)
Apply git cat-file --textconv when reading non-previewable blobs for diffs so that encrypted or filtered files (git-crypt, sops, etc.) are rendered as readable text instead of binary.
Fixes#37100
* fix(git): apply textconv to binary working-tree files for unstaged diffs
* fix(git): textconv only diffs whose editable side stays byte-exact
Unstaged diffs keep raw bytes unless the path's driver leaves the working
tree unchanged (clean/smudge encryption such as git-crypt); the check runs
in a scratch object store so nothing is written to the repo. Drops the
binary working-tree textconv, which made converted text editable.
* fix(git): read the stored blob first and convert only paths with a driver
cat-file --textconv pretty-prints trees, so a directory replaced by a file
showed a tree listing. Reading the blob first keeps absence and type
handling unchanged, and drivers are looked up in parallel so paths without
one cost no extra wait. Driver failures are kept out of the settled cache,
deleted files convert, and the clean-filter probe gets a read deadline.
* fix(git): never settle-cache diffs that ran a textconv driver
Driver output depends on config, keys and tools the worktree stamp does not
cover, so a locked key or failing driver could pin a raw result. Deleted
files stay raw, since Monaco's revert arrows would restore converted text,
and drivers run off the WSL direct-read route so profile variables reach
them.
* fix(git): show the editable unstaged side against checkout bytes
A worktree that the driver leaves unchanged does not make the converted
original safe: Monaco's revert copies the original into the editable side,
and a driver like `tr a-z A-Z` would restore ONE where checkout writes
one. Unstaged diffs now read the Git side with `cat-file --filters`, which
is exactly what checkout writes and decrypts clean/smudge encryption, so
the scratch-store probe is gone.
* fix(git): share one driver lookup per path and keep editable ranges in checkout form
check-attr is a read, so it no longer counts as a worktree mutation or
waits on WSL write probes. Commit, branch and submodule diffs look the
driver up once per path, the unstaged submodule range shows checkout bytes
like the rest of the editable side, and a staged rename stays out of the
settled cache when either path has a driver.
* test(git): age the diff stamp with a fixed timestamp
---------
Co-authored-by: Hrithik <hrithik@Hrithiks-MacBook-Pro.local>
Co-authored-by: Kelvin Amoaba <97001695+AmoabaKelvin@users.noreply.github.com>
* fix(native-chat): keep received output when the journal queue is busy
The journal sink refused its 1,025th outstanding write, and the
fire-and-forget append, publish and tombstone paths dropped that
refusal, so a reply or tool result vanished on reopen while the drain
still reported success. Pressure now only pauses provider reading; the
sink no longer refuses output it has already received. The final-tail
reservation existed only to get past that refusal, so it goes too.
Pi relied on refusals to pause its reader, so it now binds the sink's
reading control after startup, alongside the lane's own hold.
* test(pi): prove a command start keeps a journal-paused reader paused
* test(native-chat): drop pressure tests that no longer guard a contract
fire() fell back to its loop snapshot when a concurrent learn (no enabled
automations left) or forget had cleared the entry during an earlier host's
wake, which could wake a distro for a deleted automation. A cleared entry
is now skipped.
* fix(emulator): report Device Hub blocking iOS simulator input instead of a silent success
* fix(emulator): keep the session backend so the pane input check sees iOS sessions
* test(emulator): pin the pane input check to active iOS sessions
* fix(emulator): probe Device Hub via process-host and recheck on pane keyboard input
* refactor(emulator): use the shared RPC error-code predicate in the pane input check
* fix(emulator): key the pane input check on the live stream after the session hook stopped returning session
Main's session hook no longer returns session and sits at its line cap, so the pane keys the check on the live preview URL. The iOS-only session check moves into its own module to keep the runtime commands under the cap.
The close button sat at a fixed 16pt from the right edge and ignored the
window's right safe-area inset, which on the iPhone Duo is the status
column holding the clock and the camera. Offset it by that inset, and size
it to 44pt itself because page Pressables ignore hitSlop.
* fix(web): give the web client a plugins API so the update-review toast cannot crash
The web preload has no plugins namespace, so its fallback proxy answers
takeUpdateReviewNotices() with undefined and the startup watcher threw
reading .length. Plugins run only in the desktop app; the web client now
reports no held updates, an empty auto-update state and no install counts.
* test(web): drive install counts through the store; tighten comment
Subscribing to the whole settings object re-rendered DiffViewer and rebuilt its
options object on every unrelated settings write, which made @monaco-editor/react
call updateOptions on the diff editor each time. Select the three diff fields and
memoize the options, mirroring the combined diff fix (#36921).
* Clarify Git operation status across workspaces
* fix translation
* Clarify when a Git operation is running in another workspace
* Clarify Git operation feedback in Chinese translations
* Clarify which Git operations can block another workspace
* Show Git operation waiting feedback during PR preparation
* rm file
* Fix remote operation ownership test setup
* Fix remote operation ownership test setup
* fix(cli): keep inferred worktree creation in the caller project
* Fix caller checkout ranking and creation guidance
* Share caller-host containment preparation across CLI selections
* Correct Windows CLI fixture syntax and snapshot command
* Match worktree fixture output to typed execution hosts
* Regenerate bundled workspace placement guidance
* Refuse ambiguous workspace ownership and preserve launch replay
* Scope runtime filesystem mocks to their aggregate tests
* Preserve launch proof semantics under strict test diagnostics
* Keep launch proof imports within their compiler project boundary
* Consolidate journal cleanup test imports
* Adapt launch fixtures to the current host settings contract
* Keep the CLI error formatter under the file-size limit
Move the selector-ambiguity workspace-choice check into selector-ambiguity-recovery.ts, which already owns that error's recovery text. Behavior is unchanged.
* Expect main's concise orchestration output in the workspace-choice CLI tests
Orchestration commands now print the one-line failure on stderr and the workspace choices and next steps on stdout (or compact JSON plus the stderr line with --json), and print concise success fields.
---------
Co-authored-by: Orca QA <orca-qa@users.noreply.github.com>
* fix(emulator): scope emulator list to the worktree's sessions
emulator list ignored --worktree and returned serve-sim's global iOS helper list. It now lists the session registry's attached sessions (iOS and Android) for the selected worktree, or every worktree's for --worktree all.
* fix(emulator): drop stopped devices before listing sessions
* fix(emulator): point the no-active hint at emulator devices
* test(emulator): assert list results, not serve-sim calls
* refactor(emulator): prune stopped devices inside the registry listing
* Nest chat-UI orchestration workers under the agent that started them
Main's lineage projection only walked terminal panes, so workers running
in the chat UI never got a parent link and listed flat in the sidebar.
It now also projects chat workers, keyed by their visible chat row, and
resolves a chat creator or coordinator to that chat's visible row
instead of its handle or private mailbox pane key.
* Fix public worker lineage across assignment and row identities
* Complete terminal lineage provenance and bound active session selection
* Repair lineage test runtime boundaries and SQLite counters
* Provide read-only crew snapshots for each agent
* Batch public lineage verification after exact recency selection
* Derive crew relations once per meaningful host change
* Remove package manager lockfile churn from hook
* Use checked runtime values in lineage integration tests
* Document the trusted Dispatch SQL row boundary
* Keep lineage integration imports within their test programs
* Load native lineage fixtures before test execution
* test: complete lineage inputs in runtime and sidebar fixtures
* test: seed benchmark facts from active dispatches
* test: replace partial orchestration DB casts with typed fixtures
* test: complete stale-leaf mailbox fixture session input
* Derive durable crew parents from retained assignment proof
* fix(test): render worker lineage fixture with production list
* Add scoped terminal identity acquisition and preserve crew source wakes
* Share raw crew identity inputs through scoped production readers
* Exercise crew generation retirement through actual source owners
* Retire crew inputs on consumed ownership and visibility writes
* Use typed crew mutation and fixture access
* Repair crew fixture and RPC type contracts
* Align crew integration fixtures and RPC parameter contracts
* Encapsulate terminal identity mutations and captured reader contracts
* Seed terminal identity fixtures through canonical mutations
* Fix terminal identity fixture return type
* Cover terminal identity lifecycle schedules
* Align terminal fixtures with canonical identity sources
* Repair runtime fixture source contracts
* Use checked database fixtures for federation contracts
* Update crew source inventories and exit fixtures
* Preserve crew setup outcomes at existing subscription owners
* Match managed restore fixture to its nullable async return type
* Keep absent setup observations distinct from undefined failures
* Drive pending Crew questions from existing metadata
* Preserve nested pairing repair outcomes for shared callers
* Route attached workers to explicit local recipients
* Type Crew pending-question measurement receipts
* Match SSH repair fixture target absence to store contract
* Bound cold terminal layout construction and finite pane acquisition
* test: use public runtime identity in pane acquisition fixture
* Avoid repeated searches in cold workspace layout loading
* Verify cold loader fault identity and hook claimant effects
* Revert "Route attached workers to explicit local recipients"
This reverts commit f1335d1c06.
Keep attached workers on the existing Run-home routing path for this change.
* Omit crew peer addresses outside the active home route
* Keep crew retries on the verified runtime session
* Bound cold layout retirement and recorded-key construction
* Verify original cold layout failure identity
* fix: preserve surviving layout split references
* test: use typed retirement instrumentation properties
* test: preserve pane and retirement fixture contracts with checked types
* Prepare Crew record admission and wake identity changes
* Derive Crew recipient actions from current target owners
* Keep nested Crew process facts within selected acquisition
* Defer Crew legacy facts to consumers and complete raw coverage on success
* Use deterministic time in Crew command fixtures
* Document schema-owned Dispatch row assertions
* test: align Crew authority fixtures with typed project boundaries
* test: place Crew CLI integration in cross-surface project
* Type retained identity test meters with canonical source maps
* Document suffix Dispatch row boundary and preserve fixture unbinding
* test: migrate Crew authority arguments and mailbox observations
* Derive Crew attention and actions from complete recipient authority
* Fix Crew public-command fixture type contracts
* Align Crew fixtures with runtime reader and routing contracts
* Narrow receiving fixture calls to unary RPC methods
* Age pending question fixtures from every actual answer timestamp
* Complete Crew public-command workspace fixture result
* Test delegated helper follow-up through Crew advertised address
* Qualify Crew follow-up addresses through shared command admission
* Complete finite follow-up authority and lifetime evidence
* Assert exact remote authority acquisition error identity
* Consolidate Crew SQL test fixture imports
* Trim Crew read-model tests to the high-impact set
Keep the real CLI/RPC/database command paths, one regression per review-found bug, the cross-version contracts and one N vs 10N operation contract per scaling piece. Drop permutation matrices, equivalence oracles, near-duplicate scenarios and diagnostic output, and return the SSH, managed-server and WSL test files to main, since their production changes were reverted earlier in this PR.
* Drop diagnostic output and a duplicate error case from Crew tests
Remove two leftover console.log diagnostics, an unused 2x2 sample matrix and unused return fields in the follow-up cost contract, and the subscription AbortError serialization case that the subscription identity and preload tests already cover.
* Pass the recorded-leaf reader in main's check-details loader test
* test: remove 462 low-value test declarations
* Shrink flaky test pattern baseline after audit896 test removal
* Remove two empty hook-only suites after audit896 test removal
---------
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
* fix(emulator): show a dead Android preview as disconnected so Connect restarts it
When the scrcpy session ended, the video registry dropped its subscribers silently and a later subscribe was a no-op, so the pane kept saying Connected over a blank 'Stream disconnected' screen with no way to retry. The registry now tells subscribers the session ended, the IPC relays it on the stream error channel, and the pane marks the session disconnected so the toolbar's Connect button restarts scrcpy.
* fix(emulator): retry a lost Android preview by AVD name and keep stale errors off new streams
* fix(emulator): keep a live emulator serial and fall back to its AVD name only once it is gone
* fix(emulator): keep the AVD target across failed reconnects and reused serials
* fix(emulator): reboot a vanished emulator by AVD name only when the host no longer finds its serial
Replaces the pre-attach device refresh: the live serial always goes first, and the AVD name is tried only after the host answers emulator_device_not_found.
* refactor(emulator): read the host error code plainly in the AVD fallback
* refactor(emulator): type the attach result without a cast and derive WebCodecs support in render
* fix(emulator): type the fallback test's attach result and allowlist the WebCodecs diagnostic
The PR tab and the Checks and Comments screens refresh by themselves while
they are open and the app is in the foreground, on desktop's checks-panel
cadence (policy moved to src/shared). A failed background read keeps the
PR on screen and backs off instead of replacing it with an error.
Review threads show the lines they are about: the host forwards the tail
of each thread root's diff hunk, and mobile numbers it back from the
thread's line. Bot findings get "Ask <agent> to fix", which launches
desktop's Resolve comments prompt (moved to src/shared) for that thread.
Fix and Ask buttons name the agent that would start.
* Allow automation CLI setup choices for new workspaces
* Explain automation --setup refusals and read back the saved choice
Name why --setup is refused and what to pass, show the setup choice in
text output, document --setup in the CLI guide, fail when a host drops
the choice, and cover the app-open Terminal dispatch.
* Refuse automation --setup on hosts that can't keep it, and fence the edit's mode
Explicit --setup now needs the host's new setup-choice capability, checked
before any write; commands without --setup are unchanged. An edit whose
setup choice relies on the current new-per-run mode sends a mode
precondition the store checks against the saved record, so a concurrent
switch to an existing worktree refuses the whole edit. Text output shows
the saved choice or "not set", the existing-workspace refusal offers a
remedy that works for every input, and the after-write readback is gone.
* Make the too-old --setup message true for edit and cover a saved setup edit
Omitting --setup on edit keeps the saved choice, so the refusal now says
to run the command without --setup. A new test saves a --setup run edit
through the controller into the store and reads it back after reload.
The PR tab now leads with the PR's identity, one row per merge gate
(checks, unresolved threads, approvals, conflicts) that opens the screen or
sheet that resolves it, a changes card and a collapsed description. Close,
Unlink, Auto-merge, Edit title and Copy link move into the ⋯ menu.
Checks and Comments become pushed screens: failures open with their
annotation and Fix / Rerun / Open / Log on the failure, running checks
next, passed folded; comments filter by Unresolved / All / Hide bots with
Resolve and Reply on each thread and a comment box at the bottom.
Merge opens a sheet that lists only the methods the repo allows, starting
on its default. Reviewers move into a sheet with search to add and remove.
Every Create PR entry point opens one sheet: title and description seeded
from the branch's commits (shared seed rule in src/shared, GitHub's own
default), Write with AI, base picker and draft. It pushes first when
needed, works for all five providers and lands on the PR tab for GitHub.
* fix(wsl): the Codex quota poll gates the distro it probes, not the default
The poll's gate asked whether the wsl -l default was running, then the
home lookup resolved its own default (and could name an account home in
another distro), so the probe could start a stopped distro the gate never
read. The distro is now resolved once, gated, and pinned for the home
lookup; a home in any other distro skips the poll.
* fix(wsl): pin the gated distro for paths only; keep the account lane
Pinning the resolved default into the target also moved the account
lookup off the default lane, so a default-lane account read the system
home. The distro is now pinned for paths and probes only: the account is
that distro's lane, then the default lane the target named. The default
distro comes from resolveWslDefaultDistro, as the exec gate's does.
* fix(wsl): the pinned quota poll reads the account lane launch reads
Drop the default-lane fallback: a pin names the distro, so the account is
that distro's lane, exactly as launch reads its named target. The test now
asserts the poll and launch's own home lookup agree.
* fix(chat): move forward readers to the covered tip after a no-op save
A write whose fold changes nothing stores no outcome record, so its
sequence never appears in a forward read. Readers placed themselves at
the last returned row and stayed behind the live cursor, so open chats
re-read an empty page and recomputed the prompt projection on every
later delivery until the next real save.
Forward journal reads now report the highest sequence they covered.
History pages move there when the read was complete, prompt reuse and
native responses compare against it, and a read cut short by its limit,
byte budget or damage still stops at the last returned row.
* fix(chat): append unlimited outcome reads without spreading, and report coverage from the mobile journal fake
* fix(chat): skip the retention scan for batches that change no journal items
The pane's keyboard only sent serve-sim HID frames over the iOS WebSocket.
Android sessions have no serve-sim socket, so every key was dropped and every
paste failed with "device is not ready".
Android panes now send typed characters, paste and editing keys over a new
emulator:scrcpyKeyboard IPC beside emulator:scrcpyTouch, keyed by the streamed
serial. Main writes them straight to the live scrcpy control socket (text
injection, and keycodes with SHIFT_LEFT held for Shift), so keys keep their
order with touches. iOS keeps the HID path.