mirror of
https://github.com/stablyai/orca.git
synced 2026-11-13 09:27:29 +00:00
hide-codex-error-msg
16
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
a489ef5ba3 |
test: reconcile approved test removals with current main (#40176)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com> |
||
|
|
19043a3d76 |
refactor(mobile): organize pairing, session, RPC and host owners (#39846)
* refactor(mobile): give relay and encryption concrete owners * refactor(mobile): organize session and review feature owners * refactor(mobile): organize RPC and host ownership * test(mobile): point render fixtures at concrete owners * refactor(mobile): use explicit type-only owner imports |
||
|
|
ff416c2f6c |
test: remove 181 low-value mobile, CI and runtime tests (#39351)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com> |
||
|
|
4cccf7b04a |
perf(native-chat): reuse unchanged phone transcript rows (#38956)
* perf(native-chat): reuse unchanged phone transcript rows * fix(native-chat): narrow retained projection output reuse * refactor(native-chat): isolate phone session status type * Document source comparison key safety * Use last-member array accessor * test(native-chat): check phone captures across source boundaries * ci(mobile): route recorded transcript decoder inputs |
||
|
|
b17646a5d9 |
test: remove 2191 low-value test declarations (#38113)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com> |
||
|
|
e98c6a439a |
test: remove 2816 low-value test declarations (#38030)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com> |
||
|
|
d5f2d9269f |
test: remove 454 low-value test declarations and copied benchmarks (#38014)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com> |
||
|
|
7b45308ee8 |
fix(mobile): type desktop replies from shared contracts and keep phone list facts beside the desktop row (#37917)
* refactor(mobile): keep phone list facts beside the desktop's worktree row
The phone wrote its own list facts (lineage depth, host labels, list keys
and so on) onto the worktree.ps row object it got from the desktop, so a
desktop field with one of those names would be read as the phone's own.
List items are now { row, view }: the row is the desktop's, typed from the
shared RuntimeWorktreePsSummary contract, and view holds what the phone
works out. Host labels are a lookup beside the rows instead of fields on
them. A type test fails if the desktop row gains a view field's name or a
type the phone row would not accept, and a contract test feeds rows from
the desktop's own worktree.ps builder through the phone list.
* fix(mobile): type desktop replies from shared contracts and reject unchecked rows (#37923)
* wip: contract guards
* fix(mobile): type desktop replies from the shared contracts and ban unchecked z.custom
Session tabs, the createSupport reply and native-chat frames were typed by
hand on the phone, so a desktop change could leave the phone compiling
against a stale shape. They are now Pick/Partial of shared types; the
createSupport reply and native-chat transcript frames gain shared types the
desktop uses too, which also gives the phone the 'chat-program' reason it
was missing. Type tests fail when a desktop tab gains a phone-only name or
a field type the phone would not accept.
Catalog rows were admitted with z.custom<Worktree>() and no check. They now
need a string worktreeId, and an ast-grep rule rejects a z.custom with no
check anywhere in mobile/src.
* test(mobile): the desktop contract check also catches a null the phone would not accept
|
||
|
|
a56e6de883 |
Keep phone fork pull requests on their selected repository (#36762)
* Keep opened GitHub work items bound to their exact repository
* Bind GitHub work item ownership through consumers and dispatch
* Keep empty mention lists from consuming selection keys
* Preserve GitHub action and consumer ownership across resource changes
* Exercise repository account updates through their production store action
* Exercise account publication and cache settlement through GitHub consumers
* Simplify fork PR contract verification
* Make contract verification imports and clocks deterministic
* Correct mobile task test fixtures and model types
* Correct task recording fixtures and CI types
* Correct task fixture types and static checks
* Consolidate replay test RPC imports
* Separate GitHub metadata imports from Linear hooks
* Scope mobile PR sidebar reads to the selected resource
* Separate desktop GitHub changes from phone updates
* Preserve complete phone GitHub repository identity updates
* Fix relay authority probe census across topology cases
* Repair repository owner proof fixtures and compiler allocation
* Preserve repository row observation in host lookup
* Seed metadata fixture before server-side store acquisition
* Preserve nullable fixture settings and discover mixed test types
* Refetch phone reviewer list after a connection change
A disconnect or session change while the reviewer list loaded left the drawer showing an empty list until it was reopened. The drawer now shows its loading state while disconnected and fetches the same repository again once connected, still ignoring the cancelled load's result. Also merges a duplicate type import that failed mobile lint.
* Keep phone reviewer rows through connection changes
The reviewer picker now owns one query per open visit of a client, worktree and repository. A connection or session change retires the in-flight request at once but keeps the people already loaded; reconnecting refreshes them in the background. Without loaded people the drawer shows its spinner, or the existing connection explanation once an outage is revealed, and never a false empty list. Closing, retargeting or reopening starts a fresh visit that no earlier reply can paint. Also wraps the synchronous bridge teardown steps so the cleanup loop awaits only promises.
* Keep the viewed phone PR through connection changes
A relay/direct switch or reconnect selected a fresh, hidden PR observation in Source Control and Diff Review, so the next render unmounted the PR, closed the reviewer picker and erased an unsent comment. The PR observation is now scoped to the client, worktree and branch. One connection listener retires the in-flight reads when the connection changes and repeats the query the screen already asked for once connected, so accepted content stays mounted and refreshes in place. A failed background refresh keeps the accepted result. Task PR files likewise keep their loaded contents and expansion across a connection loss and read an interrupted file again on reconnect.
* Show a failed PR refresh over kept content; recover task files on every connection change
A failed refresh of an accepted PR (or no-PR) result now keeps the content and shows the existing "Failed to refresh pull request." line with Retry above it, whoever started the read, until the next good read. Task PR file reads are retired and re-read from the task selection's own connection listener, so a reconnect batched into one render or a connection switch at the same state also recovers an interrupted file. The reviewer-picker contract test leaves the React Native test program for now; its checked owner follows.
* Typecheck the phone/host contract tests through emitted declarations
The reviewer-picker contract test and the recorded request params test import real desktop sources, which do not typecheck under the phone's React Native libraries. Both source graphs now emit declarations under their own compiler settings, and a strict Node program checks the two test bodies against them; Vitest still runs them against the original sources through path aliases. The tests typecheck ratchet runs this program and fails unless both bodies are in it and it passes, the CI test runner checks that Bun ran and passed both, and the Mobile workflow finishes compiler work before starting tests. The six other excluded tests stay runtime-only and are labelled that way.
* Name the types phone declaration emission needs
Declaration emission for the phone/host contract program could not name the i18n instance's type or the buffered terminal draft send type; annotate the one and export the other. Also types the drawer mock's children in the Source Control scenario so the React Native test program checks it.
* Stub every icon in the Source Control scenario
Source Control modules read icons at import time, so the scenario's fixed icon list failed to load the file under Bun.
* Give the recorded params check's stand-in method a permission
The recorded request params test is now typechecked and its stand-in method lacked the permission every RPC method declares; parsing never reads it.
* Use the real composer styles in the Source Control scenario
Source Control's list styles read composer style constants at import time, so stubbing that module failed the file under Bun.
* Mock the PR sidebar hooks without loading their native modules
Only the PR sidebar reads these hooks, so the Source Control scenario's mocks need not load the real modules, whose imports reach Expo native code that does not run under Vitest.
* Count recording-internal observations apart from recorded ordinals
The scripted transport runs the real request tracker, and its connection wait, id allocation, completion, late-reply and terminal observations each took the shared write ordinal that requests, frames and effects record. Every recording's ordinals shifted although the same frames went out in the same order. Those observations now use their own counter, keeping their association with the native request, so recorded ordinals match the existing recordings again.
* Record a cleanup checkpoint only when teardown adds effects
Comparing the whole snapshot before and after teardown added a cleanup checkpoint whenever a pending request settled at dispose, which changed about 166 recordings without new evidence. Restore the condition the recordings were made with: teardown effects alone add the checkpoint.
* Run the bridged recording corpus on Node
Its goldens hold V8's TypeError wording, which the Bun pass reports differently, so ten exact error comparisons failed only on engine text. It now runs with family-recordings on Node; the comparison stays exact.
* Bind the probe test's fresh status.get by its actual child
* Edit the GitLab status scenario's GitHub issue only after opening it
* Type the Source Control scenario's composer adapters with the real component props
* Mock the Source Control scenario's icons and protocol gates without loading the real modules
* Give the PR sidebar probe test the shared typed fake client
* Select the GitLab status scenario's GitHub issue as a typed task item
* Declare the buffered terminal draft send as an exported type
* Run the Source Control scenario's focus effect only when its callback changes, as the router does
The router mock ran the loaders' focus effect after every commit, so each status read re-rendered and re-ran it. Also mock AppState for the comments section and stop act from awaiting held PR reloads.
* Re-record the GitHub and Tasks goldens for the selected-repository requests
Re-recorded with pnpm --dir mobile rpc:record for the 71 scenario IDs: 66 changed and 5 added for the exact-target status.get probe, 0 removed. The goldens now carry the selected repository on GitHub requests, the exact-target probe before GitHub operations, the skipped hidden metadata loads and the new item-detail failure copy.
* Declare the probed GitHub operations' params in the order the app sends them
The bridge probe test compares the forwarded frame byte for byte with the declared params, so tk-item-detail-github, tk-item-status-gitlab and tk-project-row-files-merge now declare the exact key order their goldens record. Values are unchanged, and completion matching ignores key order.
* Close the native connection before the page in recordings, and make late replies and inherited timers explicit
Recording teardown now closes the native client, flushes its rejection through the bridge, then closes the page, so page callers see the relayed native close. Sibling rejections name the stable logical site in every mode. Replies scripted after a timeout or disconnect are explicit late replies that must resolve nothing. Four product timers inherited from main are declared by producer, scenario, owner and delay and still reported; every other run keeps zero residual timers. The bridge probe oracle for tk-item-status-gitlab expects the published deadline failure and the exact retained issue.
* Judge unchanged bridged recordings as main does and changed ones by their own outcomes
Unchanged producers follow main's order again: identical earns identical, History keeps its strict path, and other divergences take a legacy label from the reply-meta counterfactual's typed evidence. A bounded guard pins zero unclassified, small-class membership and the branch-base tally less each named moved or removed producer; eight moved producers without a base pin are named as old-class-pending until their baseline replay. The re-recorded producers are judged directly in both page modes against their reviewed goldens, with only the page's refusal of the injected absent result applied, or by their exact strict own-undefined stop, and are pinned as bridge contracts. Bridge-only preludes are observed after their action, and the pending invocation's relayed native close is read from its own page promise. Every producer must be routed exactly once.
* Say what to do when the GitHub server check fails, and share one deadline with the action
The exact-target check runs before a GitHub action is sent, so a timeout or lost connection now shows the existing 'The Orca server connection changed. Try again.' and a refused or unreadable answer shows the existing 'Update Orca on the executing server' message, instead of raw text naming status.get. The check's own connection-changed error passes through. On native, the checks and the action share one 30-second budget, so a dead server fails in 30 seconds instead of 60.
* Pass the scenario manifest to the changed-producer comparison
* Correct the bridged corpus repairs from their first full run
The re-recorded producers no longer stop on the strict own-undefined matcher and all replay in bridge mode, so they are all judged directly; the page's refusal of the GitHub server check now expects the connection-changed copy. Unchanged legacy labels read their first difference from the replay without injected metadata. The sibling timeout and each interruption, including the cutover, end the requests the goldens record as ended, so those replies are explicit late replies. New producers in pinned families get their bridge-contract pins, and an unexpected timer or changed outcome now names its scenario and values.
* Restore six unchanged scenarios to their single own-undefined steps
tw-smart-search-all-providers, tw-smart-search-linear-listed, tk-list-gitlab-items, review-mark-reviewed-persists, review-mark-reviewed-rolls-back and session-create-terminal-without-active-tab had their own-undefined steps split into native and bridge copies, so the page replay no longer reached the strict own-undefined stop and these unchanged producers left their baseline labels. Their steps are the branch-base steps again; native recordings are unchanged.
* Fill the eight moved producers' base classes from the admitted baseline replay
pr-read-surface was identical and the seven github.pr-read matrices were result-absent-settlement at the branch base, so the unchanged tally is exact again with no pending members.
* Deliver the sibling disconnect's trailing replies as late replies too
A disconnect rejects preflight.check, linear.status and jira.status before the suffix replays their replies, exactly as the sibling timeout does, so those declared replies are late in both variants; the cutover stays strict.
* Expect the page's refusal in the two Linear producers' result-absent checkpoints
Natively the injected { ok: true } reads as an empty result, so the Linear detail and status update finish; the page refuses that frame and the screen shows the refusal instead. Each producer now has one finite expectation for that checkpoint, guarded on the reviewed golden's final effects, and everything else must still equal the golden.
* Share one deadline between the shell's server check and the GitHub action
The shell gave the exact-target check and the forwarded action each the page's full timeout unless the page asked otherwise, so a dead server took twice as long to fail on the hosted page as on native. The two legs now always share the page's one deadline; the forwarded options are unchanged.
* Deliver the sibling client cutover's trailing replies as late replies too
* Build the changed producers' page expectations from one finite table before comparing
* Re-record the three exact-target check goldens for the mapped copy
The GitHub check now shows the update-server or connection-changed copy instead of raw reply text; the item detail's empty-message cases now also record their detailError effect. Recorded on the admitted run (check-3949 Job 1).
* Declare the traced inherited timers per inner scenario and recording mode
Each declaration now names the modes where its inner scenario leaves the timer. Adds the inner scenarios traced in check-3949/qa-report-trace.md Job 2, with the ruled delays and owner chains: the reveal's 300 ms first-poll timer for all ten reply partitions of tabs.list-1 and tabs.activate-1 in both modes, and the pr-triage 20,000 ms reconnect waiter for transport-rejection and transport-rejection-no-message in both modes and result-absent through the page only. Exact counts, owners and delays stay enforced.
* Expect the compiler wait before Mobile verify's tests and only the fastlane tools after
* Call recorded timer callbacks through a typed signature
* Show the reviewer picker's no-rows wait with the screen header's connection verdict
The drawer classified only its client's state and counters, so during relay recovery it flipped between Disconnected and Connecting on every dial and never showed relay or pairing verdicts. The source control and diff review screens now pass the host's own verdict inputs (reconnect attempts, last connect, relay recovery status), re-read on host state and path changes, so the drawer shows the same steady verdict as the header.
* Say a timed-out GitHub target check timed out, on native and in the shell
A server check that ran out its own deadline on a connection that never changed now reads "Timed out confirming the executing Orca server.", as the shell's budget already did, and the native shared budget running out uses the same copy. A lost or changed connection still reads "The Orca server connection changed. Try again."
* Name the paired desktop when it is the build missing the exact-target check
When the phone's paired desktop relays to an updated executing server but lacks the exact-target capability itself, the edit now says "Update Orca desktop" instead of pointing at the executing server. An old executing server still gets the executing-server copy.
* Preserve GitHub detail argument types and optional capabilities
* Say what updating the paired desktop enables, as the executing-server copy does
* Drop the tab-reveal timer declarations now that main removed the reveal operation
* Let keyed details queries own pending read replacement
* Repair GitHub RPC and relay test fixture boundaries
* Own the new PR tab's caches, sheets, confirmations and polls by the complete PR
Fork #N and upstream #N were one owner to the tab: check details, open sheets and confirmations keyed by worktree and number survived a repository change, so a fork draft or decision could act on upstream and fork check data could show for upstream. Each is now owned by the PR incarnation (client, worktree, branch and full resource key), selected during render, so a departure closes old requests without retargeting them, A -> B -> A starts fresh, an outgoing sheet renders nothing and sends nothing, a late save closes only its own request, and a departed PR's poll neither blocks nor re-arms its successor.
* Load the reviewers sheet's people through the selected repository's resource-owned query
The new sheet read people once on the first search with no repository, connection recovery or retry, so a fork PR listed the wrong repository and a search while reconnecting stuck on an error. The first search of an open sheet now demands the selected repository's list through the exact-target helper; the query reads only while connected, retires its attempt on every real state or generation change, recovers on reconnect, keeps accepted rows and search through refreshes, and shows the header's own calm connection verdict while it has no candidates. Closing or a PR departure ends the visit; reopening starts fresh.
* Mark a failed PR discovery from every caller, polls included, and keep a poll's checks-only failure quiet
Main's poller made a failed background discovery silent, narrowing the ruled all-caller contract. Any current failed discovery over an accepted PR or no-PR result now keeps it and shows the one refresh-failed row with Retry, and the poll still backs off on 'failed'. A poll whose discovery succeeded but whose checks read failed for the same complete PR lands its discovery (clearing an older warning) and keeps the prior checks, reporting 'failed' once; equal numbers in another repository no longer count as the same PR. A viewed-file update from a departed observation changes nothing.
* Send the phone's addressed details reads with the server's read intent where it is advertised
github.workItemDetails accepts optional canonical:false (ordinary) / true (Refresh), advertised by github.exact-details-read-intent.v1; missing intent means ordinary. The phone's addressed details reads (PR tab and Tasks) now pass that intent through the existing exact-target preparation: a host advertising it gets canonical:false for ordinary loads, recovery and polls and canonical:true for the user's explicit Refresh; a canonical-only host gets ordinary reads without the owner and Refresh with the owner only; hosts with neither keep today's params, and an explicit Refresh there is refused as unsupported. Refresh intent travels only with the Refresh command, never as reconnect demand. The poll's checks-only settling moves into pr-sidebar-load-result to keep the controller within its size limit.
* Keep today's details params for a host with neither read-intent capability, Refresh included
* Drive the reviewer target contract through the new tab's reviewers sheet, first search included
* Cover a poll's discovery warning, its clearing, and a same-PR checks-only poll failure in the controller
* Prove the Source Control PR tab's demand, retained sheet and draft, failure line and fork/upstream request ownership on the new navigation
* Cover the details read intent the phone sends to explicit-intent, canonical-only and older hosts
* Fix the round's test typecheck and assertion findings: awaited controller loads, the diff review props, typed doubles
* Send Refresh's owner to a canonical-only server outside the exact-target check, as the desktop does
* Restore the base's mobile change-scope test, which the base merge dropped by mistake
* Prove the PR poller keeps each fork/upstream incarnation's poll, backoff and cadence its own
* Verify expected GitHub account at repository execution capture
* Give the Linear detail recording adapter the detail Refresh request its loader reads
* Keep the detail Refresh request ref out of the recorded owner projection, like the other ref
* Count cancelled GitHub probes against the desktop request cap main introduced
* Keep the comment tree out of the diff review controller test, as its drawers already are
* Restore the Source Control action icons the scenario rewrite dropped from its icon mock
* Supply the settled-list setter main added to the Tasks list fixture
* Preserve captured GitHub account expectations through client dispatch
* Re-record the Linear team-context goldens for this PR's actionItem owner effect
* Retain observed runtime status after switching environments
* Fix account contract fixture types and RPC setup timing
* Restore the negative-capability switch probe assertion
* Align account fixtures with runtime identity and configured origin
* Consolidate details test imports
* Type the reviewer test's search stand-in locally so native declarations stay out of its Node-checked program
* Add the PR tab Retry label's English entry the localization check requires
* Restore the PR tab Retry label's translations in the other mobile locales
* Pass the phone write reread through the reviewer contract.
The sheet fixture omitted the required reread, so the phone typecheck failed. Desktop settlement tests that main already removed were still on this branch and pulled telemetry into the web typecheck.
* Declare the phone pull request refresh failure.
The sidebar already shows this sentence when a refresh fails. The English catalog omitted it, and the boot bundle still carried two strings no startup call needs.
* Let the phone sidebar tests subscribe to connection state.
The sidebar records the client's connection before it loads a pull request. These tests drive that through the screen's connection prop, so the stand-in client only has to accept the subscription.
* Justify the phone sidebar test client.
The changed-code check rejects a new cast unless the line says why it is sound. These tests still only subscribe and read connection state.
* Name the repository on the phone sidebar details fixture.
A same-numbered pull request in another repository is not this one. The loaded body has to name the repository the test selected.
* Keep phone review-thread feedback on its accepted detail revision
* Capture phone review actions from the current render
* Align phone recording fixtures with the integrated detail loader
* Keep provider-switch detail fixtures addressed to the selected item
* Preserve same-turn bridge refusal evidence across client call shapes
* Publish phone detail revisions through one synchronous owner
* Type the queued publication regression with its provider contract
* Conform phone regression and relay types to static analysis
* Trim duplicate phone RPC tests and focus recorded observations
|
||
|
|
5228bff55c | refactor(mobile): group web bundle transfer owners (#37124) | ||
|
|
f0d55e7319 |
Nest chat-UI orchestration workers under the agent that started them (#34601)
* 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 * Batch public lineage verification after exact recency selection * 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 * fix(test): render worker lineage fixture with production list |
||
|
|
ec49e9fac0 |
fix(native-chat): list OMP skills in the / menu as /skill:<name> (#31999)
* fix(native-chat): list OMP skills in the / menu as /skill:<name> * test(native-chat): OMP now carries the Pi-shaped skill profile * Publish native OMP skills with compatible command catalogs * Index native skill descriptions once per picker build * Combine catalog test composer imports * Correct native catalog test types and project inputs * Run cross-platform picker scaling contract with mobile tests * fix: discover native commands before the first chat message * test: isolate native command discovery from mobile typechecking * fix: release command discovery ownership after managed root exit * refactor: reuse the ACP child owner during shutdown drain * test(acp): load filesystem implementation before test execution * test: drive discovery close completion explicitly * test: await discovery admission cleanup between demand waves * test: control discovery close ordering in demand waves --------- Co-authored-by: Brennan Benson <79079362+brennanb2025@users.noreply.github.com> |
||
|
|
52e413ec85 |
fix(mobile): finish bundle downloads over slow links with smaller ranges (#32174)
* fix(mobile): serve bundle ranges within slow-link stall budget * test(mobile): consolidate range compatibility coverage and typed dispatch |
||
|
|
1912c90141 |
Extract subprocess handling into @orca/process-host (#26963)
Extract subprocess execution and process contracts into @orca/process-host with explicit public entry points, independent checks, and one Node 18 compatible CommonJS runtime. Migrate application consumers and integrate package builds, dependency selection, import enforcement, and runtime resource staging. Preserve daemon startup ownership and profile isolation, and qualify development rebuild recovery and concurrent output publication. Remove unnecessary aliases, test forwarding exports, and a duplicate output scan. Validation: full typechecks, changed-code quality, package and artifact checks, native Windows builds/types plus 306 runtime tests, and independent native reviews. Matched full E2E controls on original main and unchanged reviewed head both pass all 17 applicable tests (nine skips). Earlier intermittent E2E failures are documented in the PR; no assertions were weakened. The final combined-tree audit preserves both branches with no import-boundary violations. |
||
|
|
e594cb06af |
test(mobile): record RPC goldens without a pinned commit, and check recorded requests against the desktop's params rules (#23732)
* test(mobile): add rpc:diff to decode what a recording change moved
The RPC recording goldens are content-addressed JSON, so their raw git diff is
pool hashes. `pnpm --dir mobile rpc:diff [<base>]` decodes both sides and prints,
per golden, the checkpoint, field and JSON path that moved with both values,
grouped across checkpoints, plus added and removed goldens. `--summary <file>`
appends a Markdown report capped for GitHub's step-summary limit.
It reads any pooled format, so it can prove the next commit's format change
moves no recorded value. Checkpoints are matched by occurrence because an id can
repeat within one golden.
This commit adds files under the recorder directory, which moves the header
digest every golden pins; the next commit removes that header.
* test(mobile): record RPC goldens without a pinned commit or input digests
Every golden carried a pinned `baseline` commit plus digests of the recorder,
its mount adapter and its scenario, and the record script refused to run unless
the product tree matched the pin. So every behaviour change repinned to its own
branch commit and rewrote all ~790 files, the squash made that commit
unreachable, and main's pin job stayed red until a hand-made repin pull request
landed (22 of them in 12 days). The digests could only fail when an input moved
and the recording did not, which is exactly the change that carries no
information; every run already re-derives each golden from the current tree and
compares it.
Format 6 keeps the format version, operation, family, named deltas, the value
pool and the recording. Removed: the pin and fence, the three digest modules and
their test, the pin guard and its CI job, and the dead scenario `version` field
(the manifest reader now refuses `baseline` and `version` with a message).
- `pnpm --dir mobile rpc:record [<golden-id>...] [--prune]` records all or some
goldens; orphans are listed, and deleted only with `--prune`. Every derived
test title now starts with its golden id so an id selects it.
- `compareGolden` reports every difference in one failure (identity fields by
name, the checkpoint list, each checkpoint/field/path grouped), keeps the
final byte compare, and ends with the command to re-record that golden.
- `unhandled-recording.test.ts` now drives a detached rejection through
`runRecording` into a checkpoint and the cleanup checkpoint; no golden carries
one, and disconnecting the capture passed every suite before.
- Seam rules that existed only to keep a digest honest are gone; the
mutant-reachability, register-completeness and one-exposure rules stay.
- CI: `Mobile tests on main` runs the whole mobile suite on every merge that
touches mobile/, src/shared/, the root lockfile or the host RPC paths, since
`verify` never runs on main. A new `Mobile RPC Recording Replay` workflow
replays the recordings on pull requests that touch src/shared/ or the root
lockfile without touching mobile/. `verify` writes the `rpc:diff` report to
the job summary.
Proof: `rpc:diff` against the parent reports no recorded behaviour moved; each
golden only loses its ten header lines.
* test(mobile): check every recorded request against the host's params contract
The goldens script the host's replies, so a scenario could record a success
for a request the real host would refuse, and a desktop change that tightens a
params schema moved no golden at all.
`recorded-request-params.test.ts` parses every distinct request the corpus puts
on the wire with the host dispatcher's own `parseRpcRequestParams` and the
schema `rpc-params-catalog.generated.ts` binds to that method. It fails on a
method the host lacks, params it refuses, params sent to a method that takes
none (the dispatcher never reads them), and keys the schema silently strips
unless an inventory entry gives the reason; a stale entry fails too. Each rule
is also shown firing on a made-up request, since the corpus has no instance of
three of them. It imports the desktop dispatcher, so it sits beside the other
Node-side tests outside the RN test program, and the params-contract boundary
now exempts test files, which are never bundled.
It found twelve requests the host would refuse, all from invented fixture
values, not product code, fixed at their source:
- git.branchDiff sent `base-oid`/`head-oid`/`merge-base` where the host needs
full object ids (diff-review and source-control adapters, and the branch
compare replies in the manifest that feed them);
- an iOS push registration without `apnsEnvironment`, which a real iOS token
always carries (`push-token.ts`); the adapter now defaults to `production`;
- `settings.update` given Linear's `assigned` filter as a GitHub preset, which
the product type forbids; the scenario now picks `my-issues`;
- GitLab `projectRef` as a string where the host and the product type take
`{ host, path }` (7 methods, 5 adapters and the manifest).
46 goldens move, and a decoded comparison of every one of them shows no change
other than those substitutions; `rpc:diff` lists them.
* ci(mobile): detect a mobile change without a SIGPIPE-prone grep pipe
Under the runner's pipefail, grep -q exiting on its first match SIGPIPEs git
diff on a long file list, so a large pull request touching mobile/ read as
uncovered and replayed the recordings a second time.
* test(mobile): drop comments that still describe the golden header and digests
Eleven adapters justified an import rule by the header a golden no longer
carries, and that rule's test is gone. The census failure now names the
rpc:record and --prune commands.
* test(mobile): refuse a golden that keeps a key no recording writes
Decoding dropped unknown top-level keys, so an old header left behind by a
hand-resolved merge conflict passed every compare unseen.
* ci(mobile): summarize RPC recording changes after a failed test step too
* test(mobile): stream rpc:record output instead of capturing it
A captured run stayed silent for its whole duration and clipped its tail,
where the failure summary sits, past 8 MB.
* test(ci): let the Ruby-gate contract skip the always-run RPC summary step
|
||
|
|
40b2230508 |
test(mobile): typecheck the test files on a ratchet, and pin the reply enums where tsc looks (#21298)
* fix(mobile): move the last six reply-enum pins where tsc looks mobile/tsconfig.json excludes *.test.ts, so a `Record<HostUnion, true>` coverage record in a schema test is never typechecked: the two that existed (SshConnectionStatus, GitHubProjectOwnerType) checked nothing, and the four closed enums beside them had only a doc citation of the host type. Each arm list moves into its schema module as hostUnionArms<Union>(), which #21269 introduced for the same reason, and each test iterates the exported list instead of holding its own copy: - SSH_CONNECTION_STATUS to SshConnectionStatus - PROJECT_OWNER_TYPE to GitHubProjectOwnerType - DETAIL_FILE_STATUS to GitHubPRFile['status'] - PUSH_TEST_REFUSAL_REASONS and PUSH_REGISTER_REFUSAL_REASONS to the refusal arms of MobilePushTestResult and MobilePushRegisterResult - SETUP_RUN_POLICIES to SetupRunPolicy openEnum's parameter widens from a non-empty tuple to `readonly string[]` so a hostUnionArms list can feed it. z.enum already accepts the same, so the tuple constraint only excluded callers zod itself takes; behaviour unchanged. Twelve mutations prove the pins: dropping one arm and adding a bogus one each fail mobile tsc in all six places. Zero goldens move, the schemas' behaviour being unchanged, and the 21 recording suites pass at the existing baseline. Claude-Session: https://claude.ai/code/session_01JNnE9qzUZMMnqpZWCqM3nb * test(mobile): fix the type errors in eighteen test files Found by typechecking the tests for the first time (see the config that follows). All mechanical, none weakens a product type: - 67 `act(() => vi.advanceTimersByTime(...))` callbacks return VitestUtils where act wants void, so each becomes a block. The async ones await only a genuinely promise-returning call, so no extra microtask tick is introduced. - Four fixtures were stale against a product type that gained a required member: MobileViewState.alwaysShowDefaultBranch, PrSidebarData.checksError, the branch-compare summary's errorMessage, and SessionOptionDescriptor's transport, which #20884 added precisely so a producer could not inherit the wrong lane's rendering by omission. - `getLastConnectedAt` on the shared relay fake was typed `() => null`, which refused the timestamp two escalation suites assign to it. - Two holders used before assignment take `!`, one `advance!.kind === ...` becomes `advance?.kind`, one widened status arm takes `as const`, and the Expo notification fixture keeps `data` required because the dismissal cases assign through it. 631 test files pass, 6222 tests, unchanged. Claude-Session: https://claude.ai/code/session_01JNnE9qzUZMMnqpZWCqM3nb * test(mobile): typecheck the test files, on a ratchet mobile/tsconfig.json excludes *.test.ts so Metro never compiles tests into the release bundle, and vitest transpiles without checking types. Nothing had ever typechecked a mobile test, which is why a `Record<HostUnion, true>` pin written in one proved nothing and why 144 of the 630 test files had drifted. tsconfig.test.json is that program with the tests put back, behind `typecheck:tests`. Four files stay out: they import the desktop main process or src/shared/child-process, which are written against @types/node, and this program's libs are React Native's, where setTimeout answers a number rather than a NodeJS.Timeout. Pulling that graph in reports ~280 errors about the desktop rather than about mobile; vitest runs those four under Node, which is where they belong. The CI gate is a ratchet rather than the raw typecheck, modelled on check-ts-nocheck-ratchet.mjs: 126 files still fail, so the gate freezes that set and fails when a file that checks today stops checking, or when a baseline entry starts checking and was not pruned. The list may only shrink. Why not zero: 180 of the remaining 510 errors are one seam — tests locate mocked react-native components by string name, which `ElementType` does not admit — and closing it means either 180 casts or a global JSX declaration for the mocked names. That is a design decision, not a mechanical fix, so it is left for a follow-up rather than made here. The rest are smaller clusters of the same kind: vi.fn mocks assigned into typed slots, call-arg tuple indexing, and createElement props fixtures. Claude-Session: https://claude.ai/code/session_01JNnE9qzUZMMnqpZWCqM3nb * docs(mobile-recorder): correct the corpus counts and the salvage claim The oracle section still quoted the corpus as 368 scenarios and 727 goldens; it is 393 and 778, and the three replay suites report 781 tests. Each number now names the command that measures it. "No golden carries one" was the load-bearing error: 44 goldens carry a recorded `reply-salvage` today, starting with the push-test unknown-reason scenario #21176 added for exactly that purpose. The paragraph claimed the observation pins an absence when on those families it pins a recorded drop. Claude-Session: https://claude.ai/code/session_01JNnE9qzUZMMnqpZWCqM3nb * test(mobile): pin the tests-typecheck ratchet's parser The gate reads tsc's output, and tsc indents the "Overload 1 of 2, ..." detail under an error. Counting those as filenames would write unparseable entries into the baseline and leave the gate unprunable, so the parser is pinned on that shape as well as on the added/stale diff. Written against the gate itself: it flagged this file before the directive it carried was removed, which is the end-to-end proof the spawn half works. Claude-Session: https://claude.ai/code/session_01JNnE9qzUZMMnqpZWCqM3nb * test(mobile): await the timer advances the act() rewrite dropped Rewriting `await act(async () => vi.advanceTimersByTimeAsync(n))` into a braced body left the returned promise floating at 27 sites, so the advance was no longer ordered before the assertions that follow it. Claude-Session: https://claude.ai/code/session_01JNnE9qzUZMMnqpZWCqM3nb * test(mobile): unshadow MobileHostCard's .tsx suite A wildcard `include` keeps only the higher-priority extension, so MobileHostCard.test.tsx sat outside every tsc program while MobileHostCard.test.ts existed beside it. Its one error is the same react-test-renderer seam its sibling is baselined for. Claude-Session: https://claude.ai/code/session_01JNnE9qzUZMMnqpZWCqM3nb * test(mobile): census every test file into the typecheck program The ratchet diffs only files that error, so a test excluded from tsconfig.test.json or shadowed by a sibling extension left the gate silently. Every *.test.ts(x) on disk must now be in the program or named in TESTS_OUTSIDE_PROGRAM with its reason. Claude-Session: https://claude.ai/code/session_01JNnE9qzUZMMnqpZWCqM3nb * fix(shared): make the enum helpers refuse the ways they can prove nothing openEnum takes a `const` T so a bare literal keeps its arms rather than widening to string. hostUnionArms blocks inference of U with NoInfer and defaults it to never, so a call that omits the host union — where the record would only pin itself — no longer compiles. Claude-Session: https://claude.ai/code/session_01JNnE9qzUZMMnqpZWCqM3nb * docs(mobile): describe the census and correct the baseline count Claude-Session: https://claude.ai/code/session_01JNnE9qzUZMMnqpZWCqM3nb * test(mobile): give the push fixture cast its SAFETY rationale Widening the pre-existing cast made the changed-code gate attribute it as a new finding. Claude-Session: https://claude.ai/code/session_01JNnE9qzUZMMnqpZWCqM3nb * test(mobile): build the push fixtures as typed notifications Replaces the `as unknown as` cast with Expo's own types, filling FirebaseRemoteMessage and its notification once in two builders, and passes the data payload in rather than mutating through an optional member. Typing the fixture showed one assertion comparing the scheduled content against the whole arriving content, which only held while the cast let the fixture omit the two members the presenter drops; it now names the four members the presenter forwards. Claude-Session: https://claude.ai/code/session_01JNnE9qzUZMMnqpZWCqM3nb * test(mobile): keep the grouped-question advance read non-optional `advance?.kind` let an absent advance take the null-draft branch instead of failing. Claude-Session: https://claude.ai/code/session_01JNnE9qzUZMMnqpZWCqM3nb * fix(mobile): run the tests-typecheck ratchet on Windows Spawns tsc's JS entry on this Node instead of the node_modules/.bin shim, which is a POSIX shell script that Windows resolves to tsc.CMD and then appends .exe to. Parsed paths are normalised to POSIX so a Windows run does not read every baseline entry as both stale and added. Claude-Session: https://claude.ai/code/session_01JNnE9qzUZMMnqpZWCqM3nb * test(mobile): close the ratchet's @ts-nocheck hole and read tsc once tsc exits 0 on a @ts-nocheck file, so a baselined test could be "fixed" with one line, pruned, and never checked again; the census now names any program test file whose leading comment carries the directive. `--noEmit --listFiles` answers both questions in one pass, so the gate spawns tsc once rather than twice. Corrects the two stale counts, and states hostUnionArms' real reason for living in the schema module now that tests are typechecked. Claude-Session: https://claude.ai/code/session_01JNnE9qzUZMMnqpZWCqM3nb |