test(mobile): re-measure the web app's script sweep after agent.launch's capabilities moved out of protocol-version

The mobile web bundle check failed at 124 assets against a ceiling of 123. Main already sat
exactly on that ceiling: its sweep table read 69 scripts at 16 routes while the tree builds 73,
the whole margin of 4. This branch imports the agent.launch capabilities from their own module,
so protocol-version is no longer pulled into the root layout and four other routes. That moves
which routes share which modules, and the Qoder capability module, imported by protocol-version
and the AI-vault resume path, no longer shares an importer set with anything, so it gets a chunk
of its own: 74 scripts.

The fence says to re-derive the bound rather than raise it, so the sweep is re-measured on this
head (every prefix of the sorted route list). The worst route now adds 10 scripts (session), not
9, which moves the pinned shell crossing from 32 to 30 routes; main re-measured on its own lands
on the same crossing.
This commit is contained in:
Brennan Benson
2026-10-05 00:02:49 -07:00
parent 0811b347ca
commit 6c16914035
2 changed files with 22 additions and 22 deletions
@@ -539,10 +539,10 @@ describe('the Phase C budget', () => {
key
).toBeGreaterThanOrEqual(measured)
}
// 1 to 9 per route, which is why four per route was a bound rather than a fit and why the
// 1 to 10 per route, which is why four per route was a bound rather than a fit and why the
// envelope cannot be a line through the measurement either.
expect(Math.min(...MOBILE_WEB_APP_BUNDLE_ROUTE_SCRIPT_SPREAD)).toBe(1)
expect(Math.max(...MOBILE_WEB_APP_BUNDLE_ROUTE_SCRIPT_SPREAD)).toBe(9)
expect(Math.max(...MOBILE_WEB_APP_BUNDLE_ROUTE_SCRIPT_SPREAD)).toBe(10)
})
it('sits exactly one margin over the swept tree and grants the worst route beyond it', () => {
@@ -614,13 +614,13 @@ describe('the Phase C budget', () => {
it('fails the build when the derived ceiling passes what the phone will accept', async () => {
// The shell hands back null for a manifest over its own ceiling, so a derived ceiling above
// that ships a green build no device can open. At the 42 images the tree carries, the envelope
// plus 42 plus the document crosses 256 at 32 routes, which Phase C reaches. The crossing came
// plus 42 plus the document crosses 256 at 30 routes, which Phase C reaches. The crossing came
// in from 50 with the envelope: it grants the worst swept route to each one past the sweep,
// where `4r + 16` granted four, so re-measuring a tree whose routes share more moves it out.
expect(await readMobileWebBundleMaxAssets()).toBe(MOBILE_WEB_BUNDLE_MAX_ASSETS)
expect(assertAssetCeilingFitsShell(31, 42, MOBILE_WEB_BUNDLE_MAX_ASSETS)).toBe(251)
expect(() => assertAssetCeilingFitsShell(32, 42, MOBILE_WEB_BUNDLE_MAX_ASSETS)).toThrow(
/260 .*256/
expect(assertAssetCeilingFitsShell(29, 42, MOBILE_WEB_BUNDLE_MAX_ASSETS)).toBe(251)
expect(() => assertAssetCeilingFitsShell(30, 42, MOBILE_WEB_BUNDLE_MAX_ASSETS)).toThrow(
/261 .*256/
)
})
})
+16 -16
View File
@@ -50,9 +50,9 @@ export const MOBILE_WEB_APP_BUNDLE_MAX_TOTAL_BYTES = 9 * 1024 * 1024
* A chunk is emitted per distinct set of importers, not per route, so a route's marginal cost is
* what it fails to share rather than what it weighs. Re-measured on this head by building
* `routes.slice(0, n)` for every n, which is what the fence below is derived from rather than
* fitted to. The spread it shows is 1 to 9: `pr` and `web` add one script each, `review` adds nine.
* fitted to. The spread it shows is 1 to 10: `pr` and `web` add one script each, `session` adds ten.
* The root `./_layout.tsx` (the page's web sibling of the native root) sorts first; with it the
* swept tree reads 69 scripts at 16 routes, the old 15 read 67 on the same head.
* swept tree reads 74 scripts at 16 routes.
*
* This table is the fence's only input, so a route added to the tree stales it and the pins beside
* the fence fail until it is re-measured. That is the point: the bound is re-derived, never bumped.
@@ -61,19 +61,19 @@ export const MOBILE_WEB_APP_BUNDLE_SCRIPT_SWEEP = [
['./_layout.tsx', 3],
['./h/[hostId]/[...page].tsx', 7],
['./h/[hostId]/accounts.tsx', 9],
['./h/[hostId]/agent-history/[worktreeId].tsx', 13],
['./h/[hostId]/edit.tsx', 18],
['./h/[hostId]/files/[worktreeId].tsx', 21],
['./h/[hostId]/files/preview/[worktreeId].tsx', 28],
['./h/[hostId]/history/[worktreeId].tsx', 30],
['./h/[hostId]/index.tsx', 35],
['./h/[hostId]/pr/[worktreeId].tsx', 36],
['./h/[hostId]/review/[worktreeId].tsx', 45],
['./h/[hostId]/session/[worktreeId].tsx', 54],
['./h/[hostId]/source-control/[worktreeId].tsx', 59],
['./h/[hostId]/tasks.tsx', 66],
['./h/[hostId]/web.tsx', 67],
['./h/_layout.tsx', 69]
['./h/[hostId]/agent-history/[worktreeId].tsx', 14],
['./h/[hostId]/edit.tsx', 19],
['./h/[hostId]/files/[worktreeId].tsx', 24],
['./h/[hostId]/files/preview/[worktreeId].tsx', 32],
['./h/[hostId]/history/[worktreeId].tsx', 34],
['./h/[hostId]/index.tsx', 39],
['./h/[hostId]/pr/[worktreeId].tsx', 40],
['./h/[hostId]/review/[worktreeId].tsx', 48],
['./h/[hostId]/session/[worktreeId].tsx', 58],
['./h/[hostId]/source-control/[worktreeId].tsx', 63],
['./h/[hostId]/tasks.tsx', 71],
['./h/[hostId]/web.tsx', 72],
['./h/_layout.tsx', 74]
]
const sweptScripts = MOBILE_WEB_APP_BUNDLE_SCRIPT_SWEEP.map(([, scripts]) => scripts)
@@ -191,7 +191,7 @@ export async function readMobileWebBundleMaxAssets() {
* shells return null for a manifest over MOBILE_WEB_BUNDLE_MAX_ASSETS rather than dropping the
* extra assets, so a route count that pushes the chunk envelope plus images plus the document past
* it would pass this build and fail on the device with nothing to read. At today's 42 images that
* is 31 routes, inside what Phase C adds, which is why this is a build failure and not a comment.
* is 29 routes, inside what Phase C adds, which is why this is a build failure and not a comment.
* The envelope grants the worst swept route to each one past the sweep, so re-measuring a tree
* whose routes share more moves that crossing out again.
*/