* fix(orcad): fit orcad inside a `ulimit -v` address-space limit
On hosts that cap virtual memory (ulimit -v 8 GiB on an HPC node), the
managed orcad crash-looped with "Failed to reserve virtual memory for
CodeRange" whenever it started a worker thread.
Two reservations used up the limit:
- undici's WASM HTTP parser, loaded by the first fetch, reserves a
trap-handler guard region (4-9 GiB). The pinned-Node orcad launch now
passes --disable-wasm-trap-handler --wasm-max-mem-pages=1024.
- each Worker isolate reserves V8's default CodeRange (512 MB on x64,
~600 MB of address space per worker). Main-process workers now go
through spawnWorkerThread(), which caps the code range at 64 MB, and
a lint rule keeps new sites on it.
Fixes#37538. Thanks to lin-tianyu for the report and logs.
* fix(orcad): keep the runtime selector one command; enforce spawnWorkerThread with ast-grep
Refs #37538
* test(orcad): run the address-space regression on Node
Refs #37538
* docs(orcad): note the WASM memory cap at the pinned-Node flags
Refs #37538
* 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
* fix(i18n): format renderer dates and numbers in the UI language
About 80 renderer sites formatted with the OS locale: Intl constructors
given undefined (or nothing) and argless toLocale*String calls, while
nearby text followed the UI language.
- toLocale*String calls pass getIntlLocale().
- Module-level Intl formatters and collators use new ui-intl-formatters
helpers, cached per options object and rebuilt on language switches;
per-call constructors pass getIntlLocale().
- ReleaseBuildPicker's memoized labels re-run on language changes.
- An ast-grep rule (renderer-intl-ui-locale) rejects undefined/omitted
locales in src/renderer; machine-facing code passes a fixed locale.
* fix(i18n): collators check their own locale support; re-sort memoized lists on language changes; widen the Intl guard
* fix(i18n): name the formatter options type
* fix(i18n): reuse the CSV viewer's existing language subscription
---------
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
* test: load real modules before timed waits, and ratchet in-test vi.importActual
Two tests paid a cold real-module load inside their timed wait:
- the empty-remote wake test's 1s vi.waitFor raced the post-create refresh's
lazy session-tabs import; it now loads those modules in beforeAll;
- the runtime label-only create tests called vi.importActual inside each test
(19-23s of the 30s budget on the first case); it now runs in beforeAll.
test-no-in-test-import-actual flags vi.importActual outside vi.mock/doMock/
hoisted factories, beforeAll and module scope; the 50 existing findings are
grandfathered in the flaky-test ratchet baseline.
* test: flag vi.importActual in a doMock factory registered inside a test
* test: flag vi.importActual in any vi.doMock factory; its load runs on the next import
* perf(lint): keep JS plugins out of default oxlint and adopt ast-grep
Any jsPlugin makes Oxlint hand every file's AST to Node, so the seven custom
plugins cost the default `oxlint` run several times its native time.
- Move app-store-performance, quadratic-buffer-concat, renderer-scrollbar-style
and ime-enter-guard (scope- or dataflow-aware) to config/oxlint-js-plugins.json,
run by `pnpm lint:js-plugins`, CI, lint-staged and the changed-lines gate.
- Port sort-comparator-performance, mobile-pairing and native-chat-design-tokens
to ast-grep rules with rule tests, and delete the plugins.
- Add @ast-grep/cli, config/sgconfig.yml, `pnpm lint:ast-grep` / `test:ast-grep`,
a CI step, and an ast-grep pass in check-changed-code-quality.
- Add flaky-test rules (wall-clock reads, real-time waits, polling loops,
unquarantined skips, unexplained timeout bumps), baselined by a count ratchet.
* Enforce flaky-test ratchet on changed files; refresh baseline
* docs(agents): keep custom-rule details out of AGENTS.md
* Resolve ast-grep from the repo so gate scans of other roots work