Skip to content

feat(warmup): tier-conditional acquisition (S10-d) - #297

Merged
KnockOutEZ merged 4 commits into
studio-handofffrom
slice-s10d-tier-acquisition
Aug 11, 2026
Merged

feat(warmup): tier-conditional acquisition (S10-d)#297
KnockOutEZ merged 4 commits into
studio-handofffrom
slice-s10d-tier-acquisition

Conversation

@KnockOutEZ

@KnockOutEZ KnockOutEZ commented Aug 11, 2026

Copy link
Copy Markdown
Owner

S10-d — tier-conditional acquisition

Base 45c0e671 (S10-c). Targets studio-handoff.

Makes acquisition depend on the rung the machine resolved to (D-S10-3, D-S10-5), and fixes the three gates my predecessors measured as unreachable.

What each tier now acquires

tier desktop component browser engine verified live
desktop acquired — and it takes the engine's slot skipped {"browserEngine":"skipped","desktopComponent":"acquired"}
desktop, component already installed (D13) nothing downloaded skipped browserTierReason:"installed_substrate_present"
desktop, no component available nothing acquired eagerly degrades via substrate_unavailable, exit 0
no-display zero bytes acquired eagerly (it is this host's rung) substrate/ absent even with a source available
browser / --browser zero bytes acquired eagerly keeps browser-acquire.ts's lazy path working

installedSubstrateExists() is real: it answers from an acquisition record written only after the executable it names is probed on disk. A directory that merely exists proves nothing — a half-extracted archive would otherwise make the resolver defer acquisition (D13) in favour of a rung that can never start.

The three gate corrections

  1. G-ACQUIRE's replacement pair is now scoped to a narrower artifact, not given a bigger number. <=320 and ==0 were derived from the browser engine alone, but 218 MiB of the 764 is models and models are tier-independent. Both gates are now stated over the component directory alone, where 320 keeps its ~6.7% headroom over a measured 300 and ==0 is exact and achievable. G-ACQUIRE (total, 800) is kept unchanged — it prices the models and still catches the doubling regression at 1064.
    Neither arm is wired without the other: read alone, <=320 passes trivially on a host that acquired nothing. The claim is the differential — same command, same artifact, same job, opposite tier.
  2. G-TOTAL-DESKTOP is dropped, not silently inherited and not re-derived. Rationale in G_TOTAL_DESKTOP_DROPPED: G-DIET (≤720) and G-ACQUIRE (≤800) already jointly bound the composed total at 1520, and the lowest value it can currently take is 1464 — so the entire window in which it could fail while both components pass is 56 MiB, against a sum of two measurements each carrying tens of MiB of churn. It becomes derivable (~1280) once the desktop arm acquires a real component; the arithmetic is recorded.
  3. G-RSS-SUBSTRATE stays report-only at 510. Untouched. A 40 MiB blocking gate needs a 19 MiB window against a statistic whose own spread is 21.0, it has no ci-runner observation, and it cannot run on clean-machine-smoke, which installs the published package.

Deliberately not built, and why it is not an omission

There is no published artifact to download — a version channel, a URL and a checksum manifest are all products of S16-alpha, which is the phase that decides what the component is. Writing a downloader now would choose an artifact identity on S16-alpha's behalf and then rewrite it (the program's own "build twice" flag). So the fetch step is a named SubstrateSource seam and everything around it ships: dispatch, install, verify, record, idempotent re-run, D13, and the degradation path.

⚠️ Pre-flight #4 is still unchecked in the tracker, and D-S10-3's reverses-if turns on it: if an npm-fetched component cannot run unsigned on a mainstream platform, acquisition has no product without signing and S10's component half merges into S16-alpha. Flagged, not acted on.

CI

Today's default desktop run finds no source, degrades, and installs the browser engine — so clean-machine-smoke's browserEngine: ok assertion is unchanged on every row. The two forced-tier budget arms are what exercise both branches.


Falsifiability — 11/11 probes red, exact counts

Each mutated, run, exact red count recorded, reverted by reverse-edit, git diff -- src/ scripts/ confirmed empty.

probe mutation reds
P-1 acquire the component and the browser engine (D1's doubling) 1
P-2 make the no-display branch acquire the component 4
P-3 installedSubstrateExists() back to hardcoded false 2
P-4 skip verification, write the record unconditionally 2
P-5 trust the record without probing the executable 2
P-6 re-scope the desktop gate to the full acquisition set 1
P-7 loosen the headless gate from ==0 to <=1 1
P-8 silently re-inherit G-TOTAL-DESKTOP ≤1000 3
P-9 make the presence probe delegate to the rung resolver 3
P-10 drop doctor's component line 2
P-11 remove the presence memo 2

The self-satisfaction check paid for itself twice

P-2 initially red only 3 of 4. The survivor was "acquires the browser engine eagerly, because that is this host's rung" — it set no component source, so with nothing to acquire the run degraded and installed the engine anyway. It was true for a reason unrelated to the tier, and would have passed on a build whose no-display branch was never written. Fixed by putting a component there ready to install, so the engine can only be acquired if the tier actually refused it. P-2 then red 4/4.

A real perf regression found by reading the call graph, not by a test. resolveBrowserTier() is consulted at the single exit of SmartRouter.fetch, so making installedSubstrateExists() answer from a record turned a free constant into a readFileSync + stat per fetched page — and crawl fans out through that same seam. Memoized behind a 5 s TTL with explicit invalidation on acquisition. Its test uses an outside signal (delete the record under a warm cache; the answer must hold; then reset proves the deletion was real) rather than a spy, because ESM cannot be spied and a mock-call count would assert on the mock.

Verification

  • core npm test: 10192 collected / 10165 passed / 20 skipped / 7 todo / 864 files (base 45c0e671 = 10130 / 10103 / 860)
  • npm test -w apps/studio: 345 passed (39 files) · npm run lint -w apps/studio clean
  • contract: 30 passed (2 files) — matches the stated baseline
  • tsc --noEmit 0 · gate:studio green · typecheck:debt 412 (3 pre-existing StatusBag fixtures needed the new required field — fixed, not ratcheted)
  • no new console.log / as any in src/ (the 3+1 greps hits are comment false positives, present at base)
  • CI arms rehearsed locally end to end: desktop +1 MiB / desktopComponent: acquired / browserEngine: skipped; no-display +0 MiB / no component attempt — same command, same available component.

Counts: predicted +42, actual +62

Explained rather than waved at: +4 are auto-generated (it.each(ids) over gate ids gives every new gate 2 protocol tests — spotted during P-8, when adding one gate moved the collected count 138→140); +3 are the unplanned presence-cache tests from the perf regression above; the rest is finer-grained assertions so each probe reds exactly one thing.

Windows

No new URL(...).pathname and no POSIX mode bits anywhere in the new code or tests. The new tests use real tmpdir() + join, never exec the fixture executable, and the platform-specific browser-path cases inject platform/exists rather than touching the filesystem. The CI arms are macos-latest-gated, so no Windows row runs them.

The desktop tier acquires the desktop component and it TAKES the browser
engine's slot rather than being added to it; the no-display tier acquires
zero component bytes and eagerly acquires the browser engine, which is the
rung it will actually use.

installedSubstrateExists() is made real (D-S10-3): it answers from an
acquisition record written only after the executable it names is probed on
disk, so D13 deferral now has a true answer instead of a hardcoded false.

A failed or absent component degrades to the browser rung through the
resolver's own substrateUnavailable branch, so the reason and the remedy come
from one place and warmup still exits 0.
@coderabbitai

coderabbitai Bot commented Aug 11, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 9f5dc8b1-542d-491f-b526-b01a3c3d29ef

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

… artifact

The spec's replacement pair was unreachable as written: <=320 and ==0 were
derived from the browser engine alone, but 218 MiB of the 764 is models and
models are tier-independent. Both are now stated over the component directory,
where 320 keeps its headroom and ==0 is exact. G-ACQUIRE stays at 800 over the
full artifact, where it still prices the models and still catches the doubling.

G-TOTAL-DESKTOP is dropped rather than inherited or re-derived: the two gates
that already block bound the composed total at 1520 and the lowest value it can
take is 1464, so its entire failure window is 56 MiB.

CI runs both arms of the pair as a differential — same command, same artifact,
same component available to install, only the resolved tier differs.
…le component

Both passed under a mutation that made the no-display branch acquire the
component, because with no source configured the run degrades and installs the
engine anyway — so "engine acquired" was true for a reason unrelated to the
tier. With a component sitting there ready, the engine can only be acquired if
the tier actually refused it.
resolveBrowserTier() is consulted at the single exit of SmartRouter.fetch, so
answering installedSubstrateExists() from a record turned a free constant into
a readFileSync plus a stat on every fetched page — and crawl fans out through
the same seam, so one crawl of a static docs site would add several hundred
synchronous filesystem calls.

A 5s TTL costs nothing, since the answer changes at most once per install, and
an acquisition in this process invalidates it explicitly so warmup never
reports a rung it just stopped being on.
@KnockOutEZ
KnockOutEZ merged commit bc0ccf4 into studio-handoff Aug 11, 2026
18 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant