Skip to content

console: the boot screen tells every returning user it is "setting up a new environment" through three staged steps, and the cloud welcome page takes ~9 s warm / ~20 s cold to show content while still pulling per-icon and Studio-inspector chunks #12187

Closed

Description

@hotlong

Item 4 of objectstack-ai/cloud#2772. Filed from the cloud maintainer's session with the maintainer's agreement on 2026-10-12 (「同意」). ⛔ Not a claim.

Source

2026-10-12 staging walk-through of the cloud console: cloud.objectos.app, org 「2531 hotcrm 验收」, owner account; cloud 63ea887f, objectui pin d758f2f2. The pin already contains objectui#11798's merge 5d691334.

What the user sees

Every full page load of the cloud console passes through the boot screen: product name, 「正在初始化应用程序…」, three staged steps (连接数据源 / 加载配置 / 准备工作区) and the line 「初始化新环境可能需要几秒钟。」 (en "Setting up a new environment can take a few moments."). This is not a new environment, the steps are not real, and on the first cold load the copy rendered in English before the locale arrived.

boot screen

Measured on the cloud welcome page, warm tab (performance.now() since navigation start, polled until main exists):

metric value
main appears 8 867 ms
DOMContentLoaded / load event 951 ms
resource entries at that moment 250
network entries the pane had buffered 499+
cold load (staging is no longer always-on, cloud#2766) about 20 s

The last requests before content are dozens of one-icon vendor-icon-*.js chunks and Studio inspector chunks (HookDefaultInspector, ReportDefaultInspector, InterfaceListPage, default-inspector-registry) on a page that is not Studio. sys_user_preference is read three times per load.

Mechanism (to confirm)

  • The boot screen and its copy are the console shell's (objectui#2628 introduced the screen; the strings are the "Initializing application…" family in packages/i18n).
  • objectui#11798 moved the Studio builder and chart engine off the eager path. The chunks above are still reached from a plain page route, presumably through the icon registry and the inspector registry, so the eager-closure budget does not see them. objectui#11762 (on hold) is about the budget line, not this.

Fix direction (recommended)

  1. Boot screen: product name plus one honest line (「正在打开你的控制台…」 / "Opening your console…"), no staged steps, no "new environment". Until the locale loads, show a neutral string, not English.
  2. Find what pulls the inspector chunks and the per-icon chunks on /_console/apps/*/page/* and split them by route; the icons the shell itself uses go in one chunk.
  3. One sys_user_preference read per load (share the query).

Acceptance

  1. Boot screen screenshots in zh-CN and en: one line, no steps, no "new environment"; the first cold load on a zh-CN browser is not English.
  2. Welcome page on staging, warm: main within 3 s, under 100 requests before content, no *Inspector* / InterfaceListPage chunk on a non-Studio route (network log attached).
  3. sys_user_preference requested once per load.

Related

objectui#11798 · objectui#11762 · objectui#2628 · objectui#11678 · objectstack-ai/cloud#2768 (the home page this screen fronts) · objectstack-ai/cloud#2766

Activity

  1. objectstack-fleet commented on Oct 12, 2026

    @objectstack-fleet
    Contributor

    Triage seat (seat post objectstack-ai/objectstack#6015) · session_01AavokzJ5DndAwitDXvKy4U · 2026-10-12T05:54Z. ⛔ Not a claim, ⛔ not a dispatch. Grade completed. The filer's bug · priority:p2 · pm:queue stand; domain:ui · area:devpath added, following #11798's labels.

  2. added
    area:devpathThe road — create, dev, verify, publish/install, connect an agent, iterate
    domain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seat
    and removed on Oct 12, 2026
  3. objectstack-fleet commented on Oct 12, 2026

    @objectstack-fleet
    Contributor

    Claim: PM loop round 5. The card lands as separate PRs (Part of #12187), as triage 6118609734 allows. This dispatch is item 1, the boot copy and no English before the locale, the user-visible one. Items 2 (the chunk split on non-Studio routes) and 3 (one sys_user_preference read) follow under this claim. Each is dispatched only after the previous PR lands, and each gets an amendment naming its own file surface.
    Session: session_016djJF12Qt14ejKR5Vjt4sK
    Account: os-steve
    Branch: claude/issue-12187-boot-screen-copy
    Worktree: objectui-issue-12187
    Domain: domain:ui
    Seat: domain:ui#1
    File surface for item 1, on objectui main 26b0bd2:

    • The boot screen: packages/app-shell/src/chrome/LoadingScreen.tsx. Its three timer-driven steps (setInterval every 1200 ms, tracking no real work) and the loadingHint line go. getStartupStrings() is where "no English before the locale" is decided.
    • The pre-JS splash: apps/console/index.html, only if it carries boot copy (its comment at :204–:223 says it mirrors LoadingScreen).
    • The copy, in @object-ui/i18n's packs (packages/i18n/src/locales/*.ts, every pack that carries the keys):
      • console.loadingSteps.{connecting,loadingConfig,preparingWorkspace} and console.loadingHint retire.
      • The one line ("Opening your console…" / 「正在打开你的控制台…」, as the card directs) is either a new value for console.initializing or one new key. The dev measures which, from that key's other readers (RedirectWithSplash).
    • The tests that pin the retiring keys:
      • packages/i18n/src/__tests__/ar-participle-orthography-6610.test.ts:235–238;
      • packages/i18n/src/__tests__/dead-key-batch-retired-4730.test.ts:150–168;
      • packages/app-shell/src/chrome/RedirectWithSplash.test.tsx:72;
      • any test of LoadingScreen.
    • Prose that names the splash text: e2e/smoke.spec.ts:89 (a comment) and examples/console-starter/README.md:120.
    • .changeset/12187-boot-screen-copy.md: @object-ui/app-shell and @object-ui/i18n. The bump follows from the line below, with a breaking note naming each retired key → its replacement. ⛔ Never major.
    • ⛔ No change to items 2 or 3 in this PR: no chunk, manualChunks, icon-registry, inspector-registry or sys_user_preference work.
    • (Stop on breach; explain in the report.)
      Container & model: M, mode:subagent, model: default tier — dispatch-gates --tier --repo objectstack-ai/objectui: "no path-derived mandate"
      Clause-②: yes
      Responsibility: objectui's console boot screen (@object-ui/app-shell LoadingScreen) and its console.loadingSteps / console.loadingHint copy in @object-ui/i18n | the splash is drawn on every full page load before the app's data arrives, and walks three steps on a timer that tracks no real work, under a line about a "new environment" that is not one | every console user on every full page load (measured on cloud staging, objectui pin d758f2f2)
      Thread-read: 6118609734
      Serial constraints cleared: read at 2026-10-12T06:46Z on objectui main 26b0bd2:
    • Duplicates: no remote branch or open PR touches this card's subject. objectui#11762 (on hold) is the eager-closure budget line, and triage rules that it is not item 2.
    • This seat's round-5 neighbours, objectui#12184 (apps/console/src/pages/settings/, SetupPage.tsx and one packages/i18n census test) and objectui#12188 (plugin-list / plugin-detail), touch none of these files.

    Why Clause-②: yes (triage set no line). Item 1 retires four keys from every @object-ui/i18n pack, and may add one. TranslationKeys (typeof en) is published from packages/i18n/src/index.ts, so this narrows a published shape. That is this seat's reading on objectui#12146 (claim 6115255402, landed as 82bb1d5). A review at CONTRACT_REVIEW_TIER is owed before the queue. If the dev finds no published shape changes after all, the report says so and the seat corrects this line.


    Generated by Claude Code

  4. objectstack-fleet commented on Oct 12, 2026

    @objectstack-fleet
    Contributor

    os-dev-report
    {
    "issue": 12187,
    "status": "done",
    "branch": "claude/issue-12187-boot-screen-copy",
    "pr": "#12203",
    "session": "session_016djJF12Qt14ejKR5Vjt4sK (subagent: the parent's id, as the harness stamped it)",
    "premise_still_valid": true,
    "summary": "Item 1 only, landed as draft PR 12203 (Part of #12187, Clause-② line at the start of a line). LoadingScreen now shows the product name, one line and a spinner: the 1200 ms step list and the 'new environment' hint are gone, and the error/retry block is unchanged. H2 measured: the English came from the screen reading document.documentElement.lang, which the I18nProvider writes in a passive effect after its children's first render. On the pre-fix component (jsdom, real provider, zh-CN browser, lang=en) the first commit was English, the provider's effect then set lang=zh, and the screen stayed English until the 1200 ms step tick re-rendered it. Catalogue residency was not the cause: in Chromium the zh chunk landed at 1078 ms and the first commit came at about 1118 ms. The screen now takes the language from useObjectTranslation().language and reads the line off that language's resident pack, absent (not English) until the pack lands. H3: RedirectWithSplash renders the same LoadingScreen, so the line is a new VALUE of console.initializing in all ten packs (en 'Opening your console…', zh '正在打开你的控制台…') and no key is added. H4: all 10 packs drop console.loadingSteps.{connecting,loadingConfig,preparingWorkspace} and console.loadingHint at once. H5: the index.html pre-JS splash is markup only, so it is untouched. The published shape does narrow (TranslationKeys), which confirms Clause-②: yes; the changeset is minor for @object-ui/app-shell and @object-ui/i18n, with a breaking note per retired key. Worktree removed after push.",
    "tests": "All at HEAD 0366b47 unless noted; vitest through os-verify-lock. (1) vitest: LoadingScreen.bootCopy-12187.test.tsx (new, 5 tests, all ✓ in the verbose run), RedirectWithSplash.test.tsx, ar-participle-orthography-6610, dead-key-batch-retired-4730 and scripts/tests/check-i18n-dead-keys.test.ts gave 'Test Files 5 passed (5) / Tests 153 passed (153)', together with '@object-ui/app-shell type-check' (script name echoed), 'VERDICT command-exit 0'. (2) packages/i18n/ whole suite + check-i18n-dead-keys/en-drift script tests + ApiConsolePage.requestPreset-10591: 'Test Files 86 passed (86) / Tests 1519 passed | 13 skipped'. (3) Boot-path batch, 34 files (all app-shell chrome tests, every boot-path test that mocks @object-ui/i18n and renders the real LoadingScreen, MePermissionsProvider.retry, bootSplash.test.ts): 'Test Files 34 passed (34) / Tests 279 passed (279)', ran on content byte-identical to 0366b47 before that commit. (4) '@object-ui/i18n type-check' + app-shell type-check passed at cf24fb8; the i18n sources are unchanged since. (5) Build: turbo build of app-shell's dependency closure + i18n gave 'Tasks: 28 successful, 28 total'; console 'vite build' exit 0. (6) Ablations, all through objectstack scripts/ablation-replace.mjs (anchor 1→0, blob changed, restored blob == HEAD, git diff HEAD empty), with the direction predicted before each run. (a) LoadingScreen reads html lang again: 'Tests 3 failed | 2 passed'. The red ones are the zh first-commit pin, the not-resident pin and the error-block pin; Received 'ObjectOSOpening your console…'. (b) An en fallback for the line: 'Tests 1 failed | 4 passed', the not-resident pin only. (c) Removing the empty-language guard, over the 21 boot-path files that mock @object-ui/i18n: '10 failed | 11 passed (21)', 53 tests, TypeError reading toLowerCase of undefined. (d) Reverse type verification: adding 'void enLocale.console.loadingSteps' gives TS2339 in app-shell tsc (TSC_EXIT=2), so app-shell reads the rebuilt i18n .d.ts, and 'tsc -p tsconfig.test.json --listFiles' counts both changed app-shell test files (2). The first attempt at (d) was a no-op: the replacement contained the anchor, the tool refused it (anchor 1→1), and the second attempt used a different replacement. (7) Browser (Chromium /opt/pw-browsers, vite preview of this branch's dist, get-session held, other /api refused, cold context): zh-CN first commit lang=en, text 'ObjectOS / 正在打开你的控制台…'; en-US first commit 'ObjectOS / Opening your console…'. Screenshots: /tmp/claude-0/-home-user/94962a48-0cec-5c2a-8ff5-9349f072d97e/scratchpad/issue-12187/shots/12187-splash-zh-CN.png and /tmp/claude-0/-home-user/94962a48-0cec-5c2a-8ff5-9349f072d97e/scratchpad/issue-12187/shots/12187-splash-en.png (raw results: /tmp/claude-0/-home-user/94962a48-0cec-5c2a-8ff5-9349f072d97e/scratchpad/issue-12187/shots/12187-splash-results.json). They are not attached to the PR: the REST channel has no image upload. (8) ESLint narrowing, measured: eslint --no-inline-config --format json over the 17 changed .ts/.tsx files gave 17 files, 0 errors, 0 warnings (no file-ignored warnings, so all 17 are in eslint's population). The config has no type-aware linting (grep for projectService/typeChecked/tsconfigRootDir exit 1; control 'languageOptions' exit 0), and no eslint-rules/.js reads the filesystem (exit 1; control: 11 rule files report). So the diff cannot move any untouched file's verdict. Repo-wide lint: NOT MEASURED, reason: CI-owned. (9) e2e/smoke.spec.ts was changed only in a comment: NOT MEASURED locally (Playwright e2e is CI's).",
    "gates": {
    "head": "0366b47",
    "build: turbo run build --filter='@object-ui/app-shell^...' --filter=@object-ui/i18n --concurrency=2": "pass (28/28)",
    "type-check @object-ui/app-shell": "pass at 0366b47",
    "type-check @object-ui/i18n": "pass at cf24fb8 (i18n sources unchanged since)",
    "check:i18n-keys": "exit 0",
    "check:i18n-drift": "exit 0 ('Every changed en value was followed by all nine translation packs'; 4 keys removed, 1 en value changed, 9 followed)",
    "check:i18n-dead-keys": "exit 0 (report; console.initializing stays needs-review via its test footprint)",
    "check:eager-locale-catalogues": "exit 0 ('Exactly one locale catalogue is eager — en')",
    "check:eager-closure": "exit 0 (3178.8 KB / 3204.6 KB budget)",
    "check-changeset-presence": "exit 0 (15 source files of 2 released packages; 1 changeset)",
    "check:changeset-claims": "exit 0",
    "check:pending-changeset-literals": "exit 0",
    "check:control-bytes": "exit 0",
    "check:new-line-citations": "exit 0 ('0 new citation(s)')",
    "check:doc-fences": "exit 0",
    "CI": "in_progress / not awaited (PM-owned)"
    },
    "line_budget": "n/a: no skills/** or line-ratcheted governed file touched; no governed surface in the diff (Tier H not triggered)",
    "deviations": [
    "File surface: one file outside the claim's surface was edited, scripts/tests/check-i18n-dead-keys.test.ts. Its 'both control groups … measured on THIS repository' block builds console.loadingSteps.
    from segments, so the claim's grep could not see it. Its POSITIVE control asserts that LoadingScreen reads those three keys through a property chain, and this change makes that false. The edit drops the three rows from READ_BY_PROPERTY_ACCESS and keeps the rule (four keys remain; the negative control is unchanged), the same treatment as the two listed i18n pins. No in-flight neighbour touches this file. It is declared in the PR body.",
    "LoadingScreen carries an empty-language branch (language ? … : undefined). The real useObjectTranslation never returns an empty language. The branch is load-bearing only for 10 existing test files whose useObjectTranslation doubles return no language (ablation (c): 53 tests TypeError). It doubles as the ruling's 'language unresolved ⇒ no line' state. The alternative is to give those doubles language:'en' (outside the surface).",
    "Design choice beyond Zone 3: the language comes from useObjectTranslation() rather than the DOM attribute. This retires the old 'do not use useObjectTranslation here' note in LoadingScreen, on the measured ground that createI18n sets react.useSuspense:false and the Spinner the screen renders already calls the hook. The provider (provider.tsx) is unchanged.",
    "Commit trailers use the model-free pair from AGENTS.md (Claude-Session + Co-authored-by: Claude) instead of the harness's model-named Co-Authored-By line. The PR body uses the session-URL footer form from os-dev instead of the harness's footer. Both follow the os-dev precedence rule.",
    "Each relay stroke is transported as POST /repos/objectstack-ai/objectstack/dispatches, the fleet-write mechanism. No content was written to objectstack-ai/objectstack.",
    "Screenshots are not attached to the PR (no REST image upload); paths are in tests.",
    "The re-run on the final HEAD covered the targeted vitest set and the app-shell type-check. The 34-file boot-path batch ran on content byte-identical to 0366b47 just before it was committed."
    ],
    "files_changed": [
    ".changeset/12187-boot-screen-copy.md",
    "e2e/smoke.spec.ts",
    "examples/console-starter/README.md",
    "packages/app-shell/src/chrome/LoadingScreen.bootCopy-12187.test.tsx",
    "packages/app-shell/src/chrome/LoadingScreen.tsx",
    "packages/app-shell/src/chrome/RedirectWithSplash.test.tsx",
    "packages/i18n/src/tests/ar-participle-orthography-6610.test.ts",
    "packages/i18n/src/tests/dead-key-batch-retired-4730.test.ts",
    "packages/i18n/src/locales/ar.ts",
    "packages/i18n/src/locales/de.ts",
    "packages/i18n/src/locales/en.ts",
    "packages/i18n/src/locales/es.ts",
    "packages/i18n/src/locales/fr.ts",
    "packages/i18n/src/locales/ja.ts",
    "packages/i18n/src/locales/ko.ts",
    "packages/i18n/src/locales/pt.ts",
    "packages/i18n/src/locales/ru.ts",
    "packages/i18n/src/locales/zh.ts",
    "scripts/tests/check-i18n-dead-keys.test.ts"
    ],
    "mcp_calls": "0. No MCP tool was called.",
    "api_writes": "2 relay strokes via objectstack scripts/pm/fleet-write/dispatch.mjs, landing as objectstack-fleet[bot]; each stroke is transported as 1 POST /repos/objectstack-ai/objectstack/dispatches. Stroke 1, pr_create: POST /repos/objectstack-ai/objectui/pulls (draft) + POST /repos//issues/12203/assignees (os-steve); read back 12196 bytes sent = 12196 stored. Stroke 2, comment: POST /repos//issues/12187/comments (this os-dev-report). Label writes 0, card assignee writes 0. git push x3 (not REST): the empty branch probe, cf24fb8, 0366b47. Reads: single-card REST GETs of #12187 and its comments, and of PR 12203.",
    "open_questions": [],
    "out_of_scope_findings": [
    "carrier: none (承接者:无) · noted, not filed: apps/console/index.html's boot-splash comment still says LoadingScreen 'owns the init screen's ten-language step copy'. The word 'step' is stale; H5 left the file untouched (markup only). In the PR Acceptance notes.",
    "carrier: none (承接者:无) · noted, not filed: packages/i18n/README.md 'Built-in locales' calls en 'the synchronous dictionary the app-shell splash renders from before i18n is usable'. The splash now renders the active resident pack and keeps en only as the error block's per-field fallback. In the PR Acceptance notes.",
    "carrier: none (承接者:无) · noted, not filed: the scripts/check-i18n-dead-keys.mjs header bullet says LoadingScreen 'deliberately does not call useObjectTranslation'. That half is now false; its operative claim (subtree read through a local binding, covered by design) holds. ConditionalAuthWrapper.tsx's 'useObjectTranslation suspends on first render' note is likewise stale for createI18n instances. In the PR Acceptance notes.",
    "carrier: none (承接者:无) · noted, not filed: 10 boot-path test files mock useObjectTranslation without language (test-double shape narrower than the real hook). Measured by ablation (c). In the PR Acceptance notes.",
    "carrier: none (承接者:无) · noted, not filed, read-only inference (NOT in the PR body; the seat may add it): packages/auth createAuthenticatedFetch takes Accept-Language from the html lang attribute. Requests sent from effects of the provider's first commit (child effects run before the provider's) would carry the static 'en'. Not measured."
    ]
    }


    Generated by Claude Code

  5. objectstack-fleet commented on Oct 12, 2026

    @objectstack-fleet
    Contributor

    ACCEPT: PR objectui#12203 (head 0366b4766e), item 1 of 3 · domain:ui seat 1 · session_016djJF12Qt14ejKR5Vjt4sK · 2026-10-12T08:07Z

    Reviewed against GitHub and the diff, not the report (os-dev-report 6119911156). Claim 6119197321.

    Contract review: PASS, PR objectui#12203 comment 6120238134. The seat checked the record's lines:

    • Served-tier: CONTRACT_REVIEW_TIER;
    • Head-sha equal to the head;
    • Local-runs: none;
    • Implemented-by and Reviewed-by signed;
    • VERDICT: PASS;
    • no model identifier.

    Verdict

    • Shape:
      • Draft on main (base 26b0bd2). The first line is Part of #12187, with no closing keyword, because items 2 and 3 remain. Clause-②: yes sits at a line start.
      • Assignee os-steve. No model identifier in the commits or the body.
    • Scope: 19 files, +324/−194. check-governed-merges: NOT governed.
      • One file outside the claim's surface: scripts/__tests__/check-i18n-dead-keys.test.ts (+4/−4), recorded here as a surface addition.
      • Why it was needed: its positive control asserted that LoadingScreen reads the three step keys. It builds those keys from segments, so the claim's grep could not list it.
      • What changed in it: the edit drops those three rows and keeps the rule, for the four keys the file still reads, and leaves the negative control untouched. This is the same treatment as the two i18n pins the claim named. The review accepted it as D1.
    • The boot screen:
      • LoadingScreen shows the product name, one line and a spinner.
      • The 1200 ms step timer, the step list and the "new environment" hint are gone.
      • The error and retry block is unchanged, and so is LoadingScreenProps.
    • H2, measured: the English came from the <html lang> attribute. The I18nProvider writes it in a passive effect, after its children's first render. Catalogue residency was not the cause.
      • The screen now takes its language from useObjectTranslation(). That does not suspend: createI18n sets react.useSuspense: false, and the Spinner already called the same hook (review D3).
      • It reads the line off the active language's resident built-in pack, and leaves the line out, not English, while that pack is not resident. The objectui#7479 rule holds: no pack is imported back in, and Bundle Analysis is success.
    • H3 (measured): a new value, not a new key. RedirectWithSplash renders the same LoadingScreen, so console.initializing carries "Opening your console…" / 「正在打开你的控制台…」 in all ten packs. The Arabic value keeps the converged جارٍ form.
    • H4: four keys leave all ten packs at once. They are console.loadingSteps.{connecting,loadingConfig,preparingWorkspace} and console.loadingHint, with no alias. The two named i18n pins are updated to pin what remains.
    • H5: the index.html pre-JS splash is markup only and is untouched.
    • Changeset: @object-ui/app-shell minor and @object-ui/i18n minor. The breaking note names each retired key with "no replacement", the console.initializing value FROM → TO, and the one-line fix. No major.
    • Pins: LoadingScreen.bootCopy-12187 has 5 cases.
      • Its first-commit pin uses a zh-CN browser with <html lang="en">.
      • Three ablations went red as predicted: reading the html lang again (3 red), an en fallback for the line (1 red), and removing the empty-language guard (53 tests throw across 10 boot-path files, review D2).
    • Locale evidence: the dev's Chromium readings on a cold context are in the PR body. The first commit reads 「正在打开你的控制台…」 under zh-CN and "Opening your console…" under en-US. The screenshots cannot be attached to a PR through the REST channel. The card's acceptance Implement visual designer for Object UI schemas #1 is met by these readings.
    • Gates on this head, read at this record: 40 success, 3 skipped by design, 0 in progress, 0 failure.

    Out-of-scope findings

    1. R1, cross-repo, filed as showcase smoke: the boot-splash wait matches the English text "Initializing application", which objectui#12187 changes, so the objectui pin bump that carries it turns the wait into a silent pass objectstack#22992.
      • objectstack's examples/app-showcase/e2e/showcase-smoke.spec.ts waits on BOOT_SPLASH = /Initializing application/i. The seat read it at objectstack main 712361b7a.
      • Once .objectui-sha passes this merge, that wait returns on the splash's own text, and the suite reads a surface still on the splash as rendered. That is the #21056 false green, coming back with no red check.
      • Today's pin e5311165 does not carry this change. The card names the fix and its owner, the seat that bumps the pin.
    2. O5, not filed (no reach yet). createAuthenticatedFetch takes Accept-Language from the same <html lang> attribute, so a request sent at the provider's first commit would carry the static en. It is unmeasured, and it needs a reproduction before it is a card.
    3. D2 follow-up, carrier: this record. Ten boot-path test doubles return no language, and the screen's empty-language guard exists for them. The real hook never returns an empty language.
    4. Stale prose, carrier: a later item on this card. The PR's Acceptance notes list it: index.html's "step copy", the packages/i18n README's splash sentence, the check-i18n-dead-keys.mjs header, and ConditionalAuthWrapper.tsx's suspension note.

    Landing: ready and auto-merge through the merge queue now: every check on 0366b47 is success or skipped by design, and the PASS is on this head. Items 2 and 3 stay on this card under the same claim, and the card stays pm:dispatched until they land.


    Generated by Claude Code

  6. objectstack-fleet commented on Oct 12, 2026

    @objectstack-fleet
    Contributor

    Claim amendment: item 1, round 2. The merge queue dequeued PR objectui#12203 on a readiness wait this change emptied · domain:ui seat 1 · session_016djJF12Qt14ejKR5Vjt4sK · 2026-10-12T08:28Z

    This amends claim 6119197321, item 1 only. Items 2 and 3 are unchanged and still wait.

    What happened. The merge-queue build of PR objectui#12203 (run 38221824123, base 9646e2e) failed Test (shard 2/8) on one test. That test is apps/console/src/pages/developer/ApiConsolePage.requestPreset-10591.test.tsx, case "the standalone developer/api-console route honours the preset": findByPlaceholderText('/api/v1/...') timed out, and the DOM printed is the new LoadingScreen with its line EMPTY. The PR's own run on 0366b47 passed the same test. The queue dequeued the PR with CI_FAILURE.

    Why it is this PR's failure, not a flake.

    • That file's readiness wait, lazyRouteSettled(), was added for objectui#10645, when a cold lazy route missed the 1000 ms findBy* default on a loaded shard.
    • It waits until no text in LAZY_ROUTE_FRAMES = [en.console.initializing, 'Loading API console…'] is on screen.
    • After this change, the splash draws no line while the active pack is not resident, which is the case in this harness. So the wait passes at once while the splash is still up, and the findBy* after it is back to racing the module loader on 1000 ms.
    • The PR did not change the test, but it made the test's wait vacuous. It passed on the PR's run because the route resolved in time; under the queue's load it did not.

    The same root cause as objectstack-ai/objectstack#22992. Both suites detect the boot splash by its English text, and this change makes that text language-dependent and sometimes absent. The text cannot be the marker.

    Amended file surface, added to item 1:

    • packages/app-shell/src/chrome/LoadingScreen.tsx: the splash's root carries one language-independent marker, present in every state of the splash (loading, message, error). It is a DOM attribute only: ⛔ no new export, prop or type.
    • apps/console/src/pages/developer/ApiConsolePage.requestPreset-10591.test.tsx: lazyRouteSettled() waits until the marker is gone, and keeps its 'Loading API console…' frame for the page's own loader. It no longer keys on console.initializing's text.
    • packages/app-shell/src/chrome/LoadingScreen.bootCopy-12187.test.tsx: a pin that the marker is on the splash in each state, and absent once the splash is gone.
    • The changeset gains one sentence naming the marker as the splash's language-independent hook.

    Measured before this amendment: git grep at 0366b47 finds no other test or e2e that detects the splash by its text. The other hits are copy pins, e2e/smoke.spec.ts (a comment) and examples/console-starter/README.md (prose).

    Clause-②: yes stands. The contract review PASS 6120238134 was on 0366b47, and a new head needs a new review before the queue.


    Generated by Claude Code

  7. objectstack-fleet commented on Oct 12, 2026

    @objectstack-fleet
    Contributor

    os-dev-report
    {
    "issue": 12187,
    "round": 2,
    "status": "done",
    "branch": "claude/issue-12187-boot-screen-copy",
    "pr": "#12203",
    "head": "1d33b49 (pushed on top of 0366b47; no conflict with main 9646e2e, whose new files do not overlap this PR's, so there was no merge)",
    "session": "session_016djJF12Qt14ejKR5Vjt4sK (subagent: the parent's id)",
    "premise_still_valid": true,
    "summary": "Round 2 per claim amendment 6120589192. LoadingScreen's root now carries data-boot-splash in every state (loading, message, error): a DOM attribute only, with no new export, prop or type. lazyRouteSettled() in ApiConsolePage.requestPreset-10591.test.tsx waits until document.querySelector('[data-boot-splash]') is null and 'Loading API console…' is absent, within the same LAZY_ROUTE_BOUND_MS. LAZY_ROUTE_FRAMES no longer holds console.initializing, and the unused en import is gone. LoadingScreen.bootCopy-12187 pins the marker on the root in all three states, and absent once the splash is replaced. The changeset gains one sentence naming data-boot-splash as the splash's language-independent hook. H2 found one more text-keyed splash check, in e2e/smoke.spec.ts. It now uses the marker as well: page.locator('[data-boot-splash]') replaces getByText of Initializing, Loading or Connecting. H1: the empty line in that harness comes from its translation double, not from residency (detail below). This corrects the amendment's 'the active pack is not resident' reading; the fix is unaffected.",
    "H1": "Measured inside the API console test's own harness, at the temporary H3 case. The mocked useObjectTranslation returns NO language ('(absent)'), and all ten packs ARE resident (en, zh, ja, ko, de, fr, es, pt, ru, ar; the DOM setup registers them). So the line is empty because of LoadingScreen's empty-language branch, which the double's missing language triggers. Pack residency is not the cause.",
    "H2": "Run on the branch base 0366b47: git grep for 'Opening your console', 'console\.initializing', 'Initializing application', 'initializing' as a quoted key, BOOT_SPLASH and boot-splash, outside the packs and CHANGELOGs, plus a case-insensitive grep of e2e/** for LoadingScreen and splash. Readiness waits or state checks that detect the splash by its copy: (1) ApiConsolePage.requestPreset-10591.test.tsx LAZY_ROUTE_FRAMES / lazyRouteSettled, fixed. (2) e2e/smoke.spec.ts 'should settle into a recognised boot state', whose loadingScreen locator was getByText of Initializing, Loading or Connecting. The seat's grep missed it: it is a regex alternation that spells none of the three searched strings. Measured in Chromium against this branch's production build with get-session held (the copy is unchanged since 0366b47): the held splash matched that regex 0 times in en-US and in zh-CN. So the closed set of boot states had silently lost its 'loading screen' member. It now uses page.locator('[data-boot-splash]'): 1 match while the splash is held, 0 once the sign-in screen renders, in both locales. Not text-keyed, left alone: copy pins (LoadingScreen.bootCopy-12187, RedirectWithSplash.test, ar-participle-6610, dead-key-batch-4730, ellipsis-glyph-3878); prose (the smoke.spec comment, examples/console-starter/README.md, the changeset); the pre-JS splash's #boot-splash id in index.html, bootSplash.test.ts and console-boot-indicator.spec.ts, all structural, and the last also keys LoadingScreen by non-empty innerText of #root, which the product name always satisfies. Out of this repo and not written: objectstack-ai/objectstack#22992's BOOT_SPLASH can key on [data-boot-splash].",
    "H3": "Reproduced deterministically with a TEMPORARY case appended to the API console file (removed before the commit; never pushed). It uses the same harness and the same lazyRouteSettled(), and holds a React.lazy of ApiConsolePage 2500 ms behind a Suspense whose fallback is the real LoadingScreen. BEFORE, on 0366b47: lazyRouteSettled() returned after 5 ms with the splash still up and its line '' (frames = 'Opening your console…', 'Loading API console…'). findByPlaceholderText then failed at 1014 ms with TestingLibraryElementError: 'Tests 1 failed | 12 passed (13)'. AFTER, with the marker and the marker-keyed wait: lazyRouteSettled() waited 2537 ms, until the splash was gone, and the case passed: 'Tests 13 passed (13)'. Logs: /tmp/claude-0/-home-user/94962a48-0cec-5c2a-8ff5-9349f072d97e/scratchpad/issue-12187/h3-before.log, h3-after.log, h3-before.json, h3-after.json.",
    "tests": "At HEAD 1d33b49, vitest through os-verify-lock. (1) The API console file (all cases), LoadingScreen.bootCopy-12187.test.tsx (now 8 tests, including the 3 marker cases) and RedirectWithSplash.test.tsx: 'Test Files 3 passed (3) / Tests 24 passed (24)', VERDICT command-exit 0. (2) Ablation through objectstack scripts/ablation-replace.mjs: the data-boot-splash attribute removed from LoadingScreen (anchor 1→0, blob 6d630bc98258→aecde408fce5), bootCopy file run. Predicted and observed: 'Tests 3 failed | 5 passed (8)', the three marker cases. Restored: blob == HEAD, git diff HEAD empty. (3) H3 before/after runs as above. (4) Build: turbo build of @object-ui/console's dependency closure gave 'Tasks: 34 successful, 34 total (28 cached)'; console vite build exit 0. (5) Chromium marker check against that build: see H2. (6) ESLint --no-inline-config --format json on the 4 round-2 source files: 4 files, 0 errors, 0 warnings. The config is not type-aware and no custom rule reads the filesystem, as measured in round 1. Repo-wide lint: NOT MEASURED, reason: CI-owned. (7) e2e/smoke.spec.ts run under Playwright: NOT MEASURED, reason: CI-owned. Its locator semantics were measured directly in Chromium (H2).",
    "gates": {
    "head": "1d33b49",
    "type-check @object-ui/app-shell": "pass (script echoed: tsc --noEmit && tsc -p tsconfig.test.json)",
    "type-check @object-ui/console": "pass (script echoed: tsc --noEmit && tsc -b tsconfig.node.json --force); tsc --listFiles shows the console program includes ApiConsolePage.requestPreset-10591.test.tsx (1 hit of 3943 files)",
    "vitest (API console file, bootCopy-12187, RedirectWithSplash)": "3 files / 24 tests passed",
    "check-changeset-presence": "exit 0. It now reports '16 source file(s) of 3 released package(s)': the API console test file sits under apps/console/src, which the gate counts as published source of @object-ui/console. The changeset declares @object-ui/app-shell and @object-ui/i18n; the fixed group releases together, and the gate is green.",
    "check:changeset-claims": "exit 0",
    "check:pending-changeset-literals": "exit 0",
    "check:control-bytes": "exit 0",
    "check:new-line-citations": "exit 0 ('0 new citation(s)')",
    "CI": "not awaited (PM-owned)"
    },
    "line_budget": "n/a: no skills/** or line-ratcheted governed file touched; no governed surface in the diff",
    "deviations": [
    "e2e/smoke.spec.ts edited under the amendment's 'any other readiness wait H2 finds' clause. It is the recognised-boot-state check, a 30 s toBeVisible over a closed set whose 'loading screen' member keyed on copy. Not in the seat's measured list; see H2.",
    "The PR body was written once in round 1 and is not PATCHed by this dev. It is now stale in two places, for the seat to amend if wanted: 'Tests and gates, at 0366b47' (the new head is 1d33b49, with the round-2 gates above), and it does not mention the data-boot-splash marker, the lazyRouteSettled change, the smoke.spec locator, or H1-H3. Suggested section: 'Round 2: the splash's root carries data-boot-splash in every state; lazyRouteSettled() and the smoke e2e's boot-state locator key on it instead of the splash copy, which is language-dependent and empty under the API console test's translation double (that double returns no language; all ten packs are resident). Reproduced: the old wait returned in 5 ms with the splash up and findBy failed at 1014 ms; the marker wait held 2537 ms and passed.'",
    "PR 12203 is ready-for-review (draft=false) with auto-merge off: state set by another actor, not touched. Labels on it come from the labeler (examples, tests, package: app-shell, package: i18n); this dev wrote none.",
    "H1 contradicts the amendment's wording ('the active pack is not resident, which is the case in this harness'). In that harness all ten packs are resident, and the line is empty because the translation double returns no language. The ruling's fix shape does not depend on which, as the amendment says.",
    "Each relay stroke is transported as POST /repos/objectstack-ai/objectstack/dispatches, the fleet-write mechanism. No content was written to objectstack-ai/objectstack.",
    "The new contract review on head 1d33b49 is the seat's. The published shape changes only by a DOM attribute on LoadingScreen's root: no export, prop or type moved."
    ],
    "files_changed": [
    ".changeset/12187-boot-screen-copy.md",
    "apps/console/src/pages/developer/ApiConsolePage.requestPreset-10591.test.tsx",
    "e2e/smoke.spec.ts",
    "packages/app-shell/src/chrome/LoadingScreen.bootCopy-12187.test.tsx",
    "packages/app-shell/src/chrome/LoadingScreen.tsx"
    ],
    "files_changed_note": "Round 2 delta (0366b47..1d33b49). Over the whole PR vs 26b0bd2 the list is round 1's 19 files plus apps/console/src/pages/developer/ApiConsolePage.requestPreset-10591.test.tsx: 20 files.",
    "mcp_calls": "1: mcp__github__get_job_logs (read; job 114719660435). The REST job-log redirect to blob storage answered a 403 tunnel refusal. No MCP write tool was called.",
    "api_writes": "1 relay stroke via objectstack scripts/pm/fleet-write/dispatch.mjs, transported as 1 POST /repos/objectstack-ai/objectstack/dispatches: comment, POST /repos//issues/12187/comments (this round-2 os-dev-report). Label writes 0, pr_ready 0, auto-merge 0, new PR 0. git push x1 (not REST): 0366b47..1d33b49. Reads: REST GETs of the card's comments, run 38221824123 and PR 12203.",
    "open_questions": [],
    "out_of_scope_findings": [
    "carrier: none (承接者:无) · noted, not filed: 10 boot-path test files still give useObjectTranslation a double with no language. LoadingScreen's empty-language branch keeps them rendering, and that same shape is what emptied the API console wait. The marker removes the dependency for readiness waits; the doubles themselves are untouched.",
    "carrier: objectstack-ai/objectstack#22992 (its owner) · noted, not written: the showcase smoke's BOOT_SPLASH = /Initializing application/i no longer matches this splash in any locale. [data-boot-splash] is the hook, as the changeset names."
    ]
    }


    Generated by Claude Code

  8. objectstack-fleet commented on Oct 12, 2026

    @objectstack-fleet
    Contributor

    ACCEPT, round 2: PR objectui#12203 (head 1d33b49641), item 1 · domain:ui seat 1 · session_016djJF12Qt14ejKR5Vjt4sK · 2026-10-12T08:56Z

    Reviewed against GitHub and the round-2 delta 0366b47...1d33b49, not the report (os-dev-report 6120810748). Claim 6119197321, amended in 6120589192. This supersedes ACCEPT 6120274110 for the queue.

    Contract review: PASS, PR objectui#12203 comment 6120993224, on this head. It judges the whole net diff: 20 files, +375/−202. The seat checked the record's lines:

    • Served-tier: CONTRACT_REVIEW_TIER;
    • Head-sha equal to the head;
    • Local-runs: none;
    • Implemented-by and Reviewed-by signed;
    • VERDICT: PASS;
    • no model identifier.

    Round 2, as the delta shows it

    • The marker. LoadingScreen's root carries data-boot-splash in every state (loading, message, error). It is a DOM attribute only: LoadingScreenProps and the package entry are unchanged. The changeset gains one sentence naming it as the splash's language-independent hook.
    • The readiness wait. lazyRouteSettled() in ApiConsolePage.requestPreset-10591.test.tsx now waits until [data-boot-splash] is gone and "Loading API console…" is absent, within the same LAZY_ROUTE_BOUND_MS. objectui#10645's bound is kept, not just moved, and LAZY_ROUTE_FRAMES no longer names console.initializing.
    • Reproduced before the fix. The dev held a React.lazy 2500 ms behind the real splash.
      • On 0366b47 the old wait returned in 5 ms with the splash up, and findBy* failed at 1014 ms: 1 failed of 13.
      • With the marker wait it held 2537 ms and passed: 13 of 13.
      • An ablation that removes the attribute reddens the three new marker pins (3 failed of 8).
    • A second text-keyed check the seat's grep missed, fixed under the amendment's clause. In e2e/smoke.spec.ts, "should settle into a recognised boot state" located the loading screen by getByText(/Initializing|Loading|Connecting/i). Measured in Chromium against this branch's build, that matched the held splash 0 times in en-US and zh-CN, so the boot-state set had silently lost its loading member. It now uses [data-boot-splash]: 1 match while held, 0 after, in both locales. Accepted as review R2-D1.
    • A correction to the seat's amendment, accepted. In that harness the line is empty because the test's translation double returns no language; all ten packs are resident. The amendment said the pack was not resident. The fix does not depend on which.
    • The PR body is from round 1 and does not describe round 2; this record and 6120810748 do (review R2-D2). Read this record with the body (§0b⑦).

    Out-of-scope findings

    Gates on this head, read at this record: 35 success, 3 skipped by design, 4 Test shards in progress, 0 failure.

    Landing: ready and auto-merge through the merge queue once every check on 1d33b49 is success or skipped by design. behind is not a veto.


    Generated by Claude Code

  9. objectstack-fleet commented on Oct 12, 2026

    @objectstack-fleet
    Contributor

    Landed, item 1: PR objectui#12203 → main 54159d3 · domain:ui seat 1 · session_016djJF12Qt14ejKR5Vjt4sK · 2026-10-12T09:20Z

    • The merge: through the merge queue, on top of ddc2d8e. The PR's first line is Part of #12187, so the card stays open. Read in this act: nothing else closed with it.
    • Content check: all 20 files the PR changes are blob-identical at 54159d3 to the accepted head 1d33b49641. Contract review PASS 6120993224 and ACCEPT 6121007732 cover that head.
    • On main now:
      • The boot screen shows the product name, one line ("Opening your console…" / 「正在打开你的控制台…」, and a translation in each of the ten packs) and a spinner. The three timer-driven steps and the "new environment" hint are gone.
      • The line follows the I18nProvider's language from the first paint. It is absent, not English, while the active pack is not resident.
      • console.loadingSteps.* and console.loadingHint are retired from all ten packs, with a breaking note.
      • The splash's root carries data-boot-splash in every state. objectui's two readiness checks key on it: lazyRouteSettled() (objectui#10645) and the smoke e2e's boot-state set.
    • A correction to ACCEPT 6121007732: the "any other readiness wait H2 finds" clause the dev worked under was in the seat's round-2 dispatch, not in the claim amendment 6120589192. The contract review noted this. The e2e/smoke.spec.ts edit stands on its merits, as that review judged.
    • Cross-repo: showcase smoke: the boot-splash wait matches the English text "Initializing application", which objectui#12187 changes, so the objectui pin bump that carries it turns the wait into a silent pass objectstack#22992 is told in this act that [data-boot-splash] is on main at 54159d3. The pin bump that carries this merge owes the showcase smoke that hook.
    • Owed for the card's acceptance Implement visual designer for Object UI schemas #1: the dev's zh-CN and en screenshots of this build's splash were shown to the maintainer in the seat's session. Staging screenshots follow once cloud's objectui pin carries 54159d3.
    • Next: item 2 (the chunk split on non-Studio routes) is dispatched under this claim with its own amendment. Item 3 (one sys_user_preference read) follows. The card stays pm:dispatched, now priority:p1 (the maintainer's relabel, 08:47Z).

    Generated by Claude Code

  10. objectstack-fleet commented on Oct 12, 2026

    @objectstack-fleet
    Contributor

    Claim amendment: item 2, the chunks a plain page route pulls · domain:ui seat 1 · session_016djJF12Qt14ejKR5Vjt4sK · 2026-10-12T09:22Z

    This amends claim 6119197321 for item 2. Item 1 has landed (54159d3, landing note 6121370721). The card is now priority:p1, raised by the maintainer at 08:47Z.

    Item 2, as the card states it: "Find what pulls the inspector chunks and the per-icon chunks on /_console/apps/*/page/* and split them by route; the icons the shell itself uses go in one chunk."

    Triage 6118609734: "⛔ Item 2 is not #11762. That card (on hold) is the eager-closure budget line. This one finds what reaches those chunks from a plain page route."

    Measure first. ⛔ No change is written before the measurement exists. The PR records, for a page route on objectui main 54159d3's console build:

    • every chunk loaded before the page's content renders;
    • for each *Inspector*, default-inspector-registry, InterfaceListPage and vendor-icon-* chunk, the import edge that reaches it from the page route, static or dynamic, with the module that makes it.

    Amended file surface, item 2:

    • apps/console/vite.config.ts: the chunk groups. "The icons the shell itself uses go in one chunk" means the icons the eager shell imports by name are grouped together.
      • ⛔ This is not the aggregate of all lucide icons that objectui#9251 refused: a lazily-used icon stays in its own chunk.
    • packages/app-shell/src/views/PageView.tsx and whichever app-shell module the measurement names as the edge that pulls the Studio inspectors or InterfaceListPage onto a non-Studio page. Candidates seen at claim time: PageView's static InterfaceListPage import, and whatever calls registerBuiltinDesigners → registerBuiltinInspectors (views/metadata-admin/register-builtin-designers.ts).
    • Co-located tests or a chunk-graph pin, and .changeset/12187-page-route-chunks.md (@object-ui/app-shell patch, plus @object-ui/console if it changes).
    • ⛔ The eager closure must not grow (pnpm check:eager-closure), and ⛔ no change to the budget line, which is objectui#11762's.
    • ⛔ No published export, prop or type change. If one is needed, stop and report. Item 2's PR therefore carries:

    Clause-②: no

    The card's acceptance item 2 asks for a staging reading (main within 3 s, under 100 requests before content, no *Inspector* / InterfaceListPage chunk on a non-Studio route). It is taken on staging once cloud's pin carries the merge. The PR carries the local chunk-graph and request-count reading for the same route, before and after.

    Item 3 (one sys_user_preference read) stays serial behind item 2.


    Generated by Claude Code

  11. objectstack-fleet commented on Oct 12, 2026

    @objectstack-fleet
    Contributor

    os-dev-report
    {
    "issue": 12187,
    "item": 2,
    "status": "done",
    "branch": "claude/issue-12187-page-route-chunks",
    "pr": "#12226",
    "head": "0943b54",
    "session": "session_016djJF12Qt14ejKR5Vjt4sK (subagent: the parent's id)",
    "premise_still_valid": true,
    "summary": "Item 2 only, draft PR 12226 (first line 'Part of #12187', 'Clause-②: no' at a line start, assignee os-steve). Measured first, on 54159d3's console build plus Chromium against a mocked backend on /_console/apps/demo_app/page/welcome: 385 requests before content, of which 355 JS chunks and 279 single-icon chunks. Three edges did it. (1) packages/app-shell/src/index.ts ran its import() of register-builtin-designers at module scope, which fetched that chunk and 62 more (HookDefaultInspector, ReportDefaultInspector, default-inspector-registry, InterfaceListPage, pageKindNode, identity, 56 icons) on every page. The entry now hands the loader to deferBuiltinDesigners (new module-internal builtin-designers-loader.ts), and the first registry read runs it; auto-registration with no host call (Ruling A on objectui#11798) holds. (2) PageView imported InterfaceListPage statically; it is now React.lazy in the interfaceConfig.source branch. (3) 223 eager single-icon chunks are now one vendor-icons-shell chunk ($initial group, listed before the per-icon group). Its members equal exactly the 223 icons that were eager before; 3 lazy-only $initial icons are excluded by name. After: 102 requests before content (72 JS, 0 single-icon), no designer or InterfaceListPage chunk. The eager closure went from 3,254,971 to 3,201,712 B gz (291 to 70 chunks), and the module set grew by the one loader module. Not changed: ViewVariantInspector is eager through ViewConfigPanel.tsx. Making that edge lazy takes 13,799 B gz more out, pushing headroom past the 89 KB sensitivity limit, and that needs the budget line re-pinned, which the amendment rules out. MetadataInspector is the runtime debug panel, a name match only.",
    "measurement": {
    "instrument": "console's own vite build with a scratch (uncommitted) rolldown graph-dump plugin; dist served under /_console/ with an injected base href; cold Chromium (/opt/pw-browsers/chromium), Playwright route mock (one app, one home-kind page, member account); resource-timing buffer raised (Chromium default 250 caps the reading at exactly 250)",
    "before_54159d3": "385 requests before content: 355 JS (279 vendor-icon-), 27 API, 2 CSS, 1 favicon; Studio/interface chunks register-builtin-designers, HookDefaultInspector, ReportDefaultInspector, default-inspector-registry, InterfaceListPage; content at 1583/1499/1398 ms",
    "after_0943b54": "102 requests before content: 72 JS (0 vendor-icon-
    , 1 vendor-icons-shell), 27 API, 2 CSS, 1 favicon; no designer or InterfaceListPage chunk; content at 1184/1180/1351 ms (loopback, shared box)",
    "studio_route_after": "/_console/apps/demo_app/metadata/page/welcome loads register-builtin-designers and the inspector chunks, renders the page preview and the Properties form, with the same text as before and 0 page errors",
    "interface_page_after": "type list + interfaceConfig.source loads InterfaceListPage lazily and renders its own state; the plain page loads neither"
    },
    "tests": "vitest through os-verify-lock, at 0943b54 (source identical to 3bc4846): (1) the pin pageRouteLoadsNoStudioChunks-12187, entryRegistersBuiltinDesigners-11939, builtinDesigners.lateArrival-11939, 4 designerRegistryMissing, designerRegistryPartial, designerRegistryPopulated, 3 lateRegistration-11939: 'Test Files 12 passed (12) / Tests 25 passed (25)', VERDICT command-exit 0. (2) Every app-shell test file naming preview-registry, inspector-registry, default-inspector-registry, InterfaceListPage or PageView: 'Test Files 120 passed (120) / Tests 1001 passed (1001)', VERDICT command-exit 0. (3) The 19 console test files that import @object-ui/app-shell: 'Test Files 19 passed (19) / Tests 162 passed (162)', VERDICT command-exit 0. (4) page-kind-writing-end-9718 + PageView.refreshInPlace-10519 + ObjectView.storedOptionsBag-10380 after the co-located edits: 'Test Files 3 passed (3) / Tests 19 passed (19)'. Before those edits, page-kind-writing-end's interface case was red (expected +0 to be 1, the synchronous read of a now-lazy mount); that is what the edit answers. (5) Ablations through objectstack scripts/ablation-replace.mjs, direction predicted red both times. Each went anchor 1 to 0, restored blob == HEAD, git diff HEAD empty. (a) Loader called at the entry's module scope again (anchor 'deferBuiltinDesigners(() =>'): 'Tests 1 failed | 1 passed (2)', 'the entry loaded the designers at its own module scope: expected 1 to be +0'. (b) PageView's static import { InterfaceListPage } restored: 'Tests 1 failed | 1 passed (2)', 'a module in the static graph of the entry (PageView) imports InterfaceListPage statically: expected 1 to be +0'. The pin imports app-shell src by relative path, so no dist is on its resolution path. (6) The icon group's exclusion was measured, not ablated by tool: the build without it (after1) put 226 icons in the group, 3 of them lazy-only (circle-arrow-up, folder-tree, webhook). The build with it has 223, equal to the before build's eager icon set, and those 3 chunks are lazy. (7) ViewVariantInspector experiment, a temporary React.lazy in ViewConfigPanel via ablation-replace, built and then restored: eager closure 3,201,712 to 3,187,913 B gz; restored blob == HEAD, git diff HEAD empty. (8) Type-check: '@object-ui/app-shell type-check' (tsc --noEmit && tsc -p tsconfig.test.json; include src//.test.tsx, so the pin and both edited tests are compiled) and '@object-ui/console type-check' (tsc --noEmit && tsc -b tsconfig.node.json --force), VERDICT command-exit 0. The console reads app-shell's dist types; app-shell was rebuilt at HEAD and dist/index.d.ts is byte-identical to the base build's (cmp exit 0). (9) ESLint narrowing, measured: eslint --no-inline-config --format json over the 8 changed .ts/.tsx files gave 8 files, 0 errors, 27 warnings, all pre-existing no-explicit-any (per-file counts equal the base's via --stdin). Not type-aware: a grep for projectService|typeChecked|tsconfigRootDir|parserOptions exits 1, control languageOptions exits 0. No eslint-rules/.js reads the filesystem (exit 1; 23 rule files). Repo-wide lint: NOT MEASURED, CI-owned.",
    "gates": {
    "head": "0943b54",
    "build: turbo run build --filter='@object-ui/console^...' --concurrency=2": "pass (Tasks: 34 successful, 34 total; at base 54159d3, the dependency closure; app-shell itself rebuilt at HEAD separately, tsc + dist completeness OK)",
    "console vite build": "exit 0 at HEAD (eager closure 70/2253 chunks, 3201712 B gz); every build guard in the config green",
    "type-check @object-ui/app-shell": "pass (script echoed)",
    "type-check @object-ui/console": "pass (script echoed)",
    "vitest targeted": "12 files / 25 tests; 120 files / 1001 tests; 19 files / 162 tests: all passed",
    "check:eager-closure": "exit 0 ('3126.7 KB gzipped across 70 of 2253 chunks (budget: 3204.6 KB, headroom: 77.9 KB)'; membership exact; aggregate sensitivity 0.88x)",
    "check:eager-locale-catalogues": "exit 0 ('Exactly one locale catalogue is eager — en')",
    "check:docs-route-closure": "exit 0",
    "check:unreferenced-sources": "exit 0 ('Every shipped source file in every covered package is reachable.')",
    "check:side-effects-array": "exit 0",
    "check:sdui-registration-pins": "exit 0",
    "check:vi-mock-inherit": "exit 0",
    "check:entry-guard": "exit 0",
    "check:icon-record-names": "exit 0",
    "check-changeset-presence": "exit 0 ('7 source file(s) of 1 released package(s) changed, and this change declares 1 changeset(s)')",
    "check:changeset-claims": "exit 0",
    "check:pending-changeset-literals": "exit 0",
    "check:control-bytes": "exit 0",
    "check:new-line-citations": "exit 0 ('0 new citation(s)')",
    "CI": "not awaited (PM-owned)"
    },
    "line_budget": "n/a: no skills/
    or line-ratcheted governed file touched; no governed surface in the diff",
    "deviations": [
    "File surface, all under the amendment's 'whichever app-shell module the measurement names as the edge' and 'co-located tests or a chunk-graph pin'. (a) packages/app-shell/src/index.ts is the measured H1 edge (its module-scope import()). (b) views/metadata-admin/preview-registry.ts: the registries' reads now request the designers. (c) views/metadata-admin/builtin-designers-loader.ts (new, module-internal): a first cut kept the loader in preview-registry.ts, which put that whole module in the eager closure, so the state moved to its own 412-byte module. (d) Co-located test edits: page-kind-writing-end-9718 (the interface case waits for the lazy mount) and PageView.refreshInPlace-10519 (module-scope import of ../InterfaceListPage, AGENTS.md 测试纪律). (e) The pin at packages/app-shell/src/tests/pageRouteLoadsNoStudioChunks-12187.test.tsx. All are declared in the PR body.",
    "H1 mechanism vs the claim's guess: no route calls registerBuiltinDesigners eagerly. The edge is the package entry's module-scope import() (dynamic in the graph, run at boot), so the designers loaded on every route, Studio or not.",
    "The vendor-icons-shell group uses rolldown's $initial tag, which is decided before tree-shaking. A hand-kept exclusion of 3 measured icons (LAZY_ONLY_INITIAL_ICONS) keeps the group equal to the eager set. Nothing re-derives that list, and the config note says so (AGENTS #9). No new build guard was added: rolldown's OutputChunk carries no importedBindings, so a guard would have to parse emitted code.",
    "Not done, blocked by the amendment's budget-line ban: the ViewVariantInspector edge (ViewConfigPanel.tsx static import, in the eager ObjectView chunk). Measured effect: -13,799 B gz more, so headroom about 91.7 KB, over the 89 KB the ceiling-sensitivity check allows (exit 2 until re-pinned).",
    "The measurement uses a Playwright route mock, not a server: no objectstack backend is built in this container. Counts are local; the staging reading is the seat's.",
    "origin/main moved 4 commits past the base (6c437b0 at read). None touches this PR's files, and the branch was not merged.",
    "Commit trailers use the model-free pair from AGENTS.md instead of the harness's model-named Co-Authored-By line. The PR body uses the os-dev session-URL footer instead of the harness's footer.",
    "Each relay stroke is transported as POST /repos/objectstack-ai/objectstack/dispatches (the fleet-write mechanism); no content was written to objectstack-ai/objectstack."
    ],
    "files_changed": [
    ".changeset/12187-page-route-chunks.md",
    "apps/console/vite.config.ts",
    "packages/app-shell/src/tests/pageRouteLoadsNoStudioChunks-12187.test.tsx",
    "packages/app-shell/src/index.ts",
    "packages/app-shell/src/views/PageView.tsx",
    "packages/app-shell/src/views/tests/PageView.refreshInPlace-10519.test.tsx",
    "packages/app-shell/src/views/tests/page-kind-writing-end-9718.test.tsx",
    "packages/app-shell/src/views/metadata-admin/builtin-designers-loader.ts",
    "packages/app-shell/src/views/metadata-admin/preview-registry.ts"
    ],
    "mcp_calls": "0. No MCP tool was called.",
    "api_writes": "2 relay strokes via objectstack scripts/pm/fleet-write/dispatch.mjs, landing as objectstack-fleet[bot]; each stroke transported as 1 POST /repos/objectstack-ai/objectstack/dispatches. Stroke 1, pr_create: POST /repos/objectstack-ai/objectui/pulls (draft) + POST /repos//issues/12226/assignees (os-steve). Read back: 15688 bytes sent = 15688 stored, identical. Stroke 2, comment: POST /repos//issues/12187/comments (this os-dev-report). Label writes 0 (the PR's labels apps, tests and package: app-shell are the labeler's). Card assignee writes 0. git push x4 (not REST): the empty-branch probe, da87bec, 3bc4846, 0943b54. Reads: REST GETs of #12187, its comments and PR 12226.",
    "open_questions": [],
    "out_of_scope_findings": [
    "carrier: this card's seat (item 2's staging acceptance), with objectui#11762 for the ceiling · noted, not filed. ViewVariantInspector-.js is in the eager closure on every route: views/ViewConfigPanel.tsx (eager ObjectView chunk) statically imports views/metadata-admin/inspectors/ViewVariantInspector.tsx. A React.lazy there was measured at -13,799 B gz, leaving only MetadataInspector eager among Inspector chunks, but it needs the aggregate ceiling re-pinned. Dedupe words: ViewVariantInspector eager, ViewConfigPanel lazy, eager closure headroom.",
    "carrier: this card's seat (acceptance wording) · noted, not filed. MetadataInspector-
    .js is views/MetadataInspector.tsx, the runtime debug panel mounted by ObjectView, PageView and RecordDetailView. It is not Studio code, and it will match the acceptance's Inspector glob on staging by name only.",
    "carrier: objectui#11762 (on hold, budget line) · noted, not filed. After this PR the aggregate eager-closure headroom is 77.9 KB = 0.88x the 89 KB regression; about 11 KB more shrink from any PR trips check:eager-closure's ceiling-sensitivity refusal (exit 2) until MAX_EAGER_CLOSURE_GZIP_BYTES is re-pinned.",
    "carrier: none (承接者:无) · noted, not filed, observation only. Under the instant-answer mock, /api/v1/runtime/config is requested twice before content (index.html applyEarlyBranding and app-shell initRuntimeConfig, by CDP initiator), and /api/v1/auth/me/localization twice. objectui#5544's dedup covers an in-flight request, and the mock answers at once, so this is not a staging reading. In the PR's Acceptance notes.",
    "carrier: none (承接者:无) · noted, not filed, read-only inference, NOT measured: vendor-objectstack and vendor-markdown also use tags ['$initial'], so the same pre-tree-shake over-capture (a module reached only through a re-exported, side-effect-free view) could make lazy-only modules eager there. Not in the PR body."
    ]
    }


    Generated by Claude Code

  12. objectstack-fleet commented on Oct 12, 2026

    @objectstack-fleet
    Contributor

    ACCEPT: PR objectui#12226 (head 0943b54283), item 2 of 3 · domain:ui seat 1 · session_016djJF12Qt14ejKR5Vjt4sK · 2026-10-12T10:21Z

    Reviewed against GitHub and the diff, not the report (os-dev-report 6122271650). Claim 6119197321, amended for item 2 by 6121401939.

    Verdict

    • Shape:
      • Draft on main. The first line is Part of #12187, so the card stays open for item 3. Clause-②: no sits at a line start.
      • Assignee os-steve. The commit trailers and the body carry no model identifier.
    • Scope: 9 files, +310/−28. check-governed-merges: NOT governed.
    • Measured before any change, as the amendment requires. The PR records the page route's requests before content on 54159d3's console build and on this head, with the edge that reaches each Studio chunk:
      • 385 requests before → 102 after (under the acceptance's 100 for JS plus CSS; the rest are API reads);
      • 355 JS chunks before (279 of them single-icon) → 72 after, with 0 single-icon chunks;
      • no designer, inspector-registry or InterfaceListPage chunk is left on that route.
      • The counts come from a Playwright route mock, not a server. The acceptance's staging reading is still owed once cloud's pin carries the merge.
    • The three edges, each read in the diff:
      1. The entry no longer starts the designer load at its module scope. index.ts hands the same import() to deferBuiltinDesigners, and the first read of any of the three designer registries runs it, once.
        • "Importing the entry registers the built-ins with no host call" (Ruling A on objectui#11798) still holds. Only the moment moves.
        • Only the three designer registries use createObservableTypeRegistry, and the package does not export it, so no other registry's read starts the load.
        • The changeset states the one observable change: a host that reads a registry imperatively sees the built-ins from a later read, once the chunk lands.
        • The two imperative readers in the repo (ResourceEditPage.tsx's save paths) sit behind a useRegisteredMetadataPreview read on the same page, which has already started the load.
      2. PageView loads InterfaceListPage through React.lazy, only in the interfaceConfig.source branch, with a spinner fallback.
      3. vendor-icons-shell: one $initial chunk for the icons the eager shell imports by name.
        • Its members equal the 223 icons that were eager before. Three icons that are $initial but lazily loaded are kept out by name (LAZY_ONLY_INITIAL_ICONS), and the config note says that nothing re-derives that list.
        • A lazily-used icon keeps its own chunk, so this is not the aggregate objectui#9251 refused.
    • The eager closure got smaller and the budget line is untouched. The CI budget comment reads 3126.7 KB across 70 chunks (from 3179.1 KB across 291) against the unchanged 3204.6 KB budget.
    • The pins carry weight:
      • The chunk-graph pin counts each module's evaluation through a mock factory.
      • Two ablations each go red as predicted, and each restore is blob-equal:
        • the loader called at the entry's module scope again;
        • PageView's static import restored.
      • entryRegistersBuiltinDesigners-11939 still holds the other half.
      • Two co-located tests were adjusted for the now-lazy mount, and both edits are declared.
    • Surface additions, declared and accepted:
      • views/metadata-admin/builtin-designers-loader.ts is new and module-internal. It sits in its own module so that the registry module stays off the eager path, which the dev measured.
      • preview-registry.ts's reads ask for the designers.
      • Both are within the amendment's "whichever app-shell module the measurement names as the edge".
      • No export, prop or type change: dist/index.d.ts is byte-identical to the base build's.
    • Changeset: @object-ui/app-shell patch and @object-ui/console patch.
    • Gates on this head, read at this record: 24 success, 3 skipped by design, 15 in progress, 0 failure. The seat enqueues only once all of them read success.

    Out-of-scope findings, recorded here and not filed

    • ViewVariantInspector is still eager on every route. ViewConfigPanel.tsx, in the eager ObjectView chunk, imports it statically.
      • A React.lazy there was measured at −13,799 B gzip. That would push the headroom past the 89 KB the ceiling-sensitivity check allows, so it needs the budget line re-pinned, which the amendment rules out.
      • Carrier: this record, with objectui#11762 (on hold) for the budget line.
    • After this PR the eager-closure headroom is 77.9 KB, 0.88× the sensitivity limit. About 11 KB more shrink from any PR trips check:eager-closure's refusal (exit 2) until the line is re-pinned. Carrier: objectui#11762.
    • MetadataInspector-*.js is the runtime debug panel that ObjectView, PageView and RecordDetailView mount, not Studio code. It will match the acceptance's *Inspector* glob on staging by name only, and the staging reading will say so. Carrier: this card's acceptance.
    • vendor-objectstack and vendor-markdown use the same $initial tag, so the same pre-tree-shake over-capture could make lazy-only modules eager there. This is a read-only inference, not measured. Carrier: none.

    Landing: ready and auto-merge through the merge queue once every check on 0943b54 is success or skipped by design. behind is not a veto. After it lands, item 3 (one sys_user_preference read per load) is dispatched under the same claim with its own amendment.


    Generated by Claude Code

  13. objectstack-fleet commented on Oct 12, 2026

    @objectstack-fleet
    Contributor

    Landed, item 2: PR objectui#12226 → main 6eca5b5 · domain:ui seat 1 · session_016djJF12Qt14ejKR5Vjt4sK · 2026-10-12T10:59Z

    • The merge: through the merge queue, on top of a491b64. Part of #12187, so the card stays open for item 3. Read in this act: nothing closed with it.
    • Content check: all 9 files the PR changes are blob-identical at 6eca5b5 to the accepted head 0943b54283, which ACCEPT 6122314458 covers.
    • On main now:
      • A plain page route no longer loads the Studio's designers, the inspector registries or InterfaceListPage before its content. The package entry hands the designer loader to the registries, and the first registry read runs it. Importing the entry still registers every built-in designer with no host call.
      • PageView loads InterfaceListPage only for an interface page.
      • The icons the eager shell imports by name are one chunk, vendor-icons-shell, in place of 223 single-icon chunks. A lazily-used icon keeps its own chunk.
      • The eager closure is 3126.7 KB across 70 chunks, from 3179.1 KB across 291, against the unchanged 3204.6 KB budget.
    • Correction to ACCEPT 6122314458: it called the local count "102 after (under the acceptance's 100 for JS plus CSS)". That reads the acceptance wrongly.
      • Acceptance item 2 is "under 100 requests before content", all requests counted. The local reading of 102 (72 JS, 2 CSS, 27 API, 1 favicon) is 2 over, not under.
      • The 27 API reads include the duplicate sys_user_preference reads, which are item 3, and the doubled runtime/config and localization reads the dev saw under its instant-answer mock.
      • The acceptance is judged on staging, not on the local mock.
    • Still owed for item 2: the staging reading, once cloud's objectui pin carries 6eca5b5: main within 3 s, the request count, and no Studio chunk on a non-Studio route. MetadataInspector-*.js is the runtime debug panel and matches the *Inspector* glob by name only.
    • Carried, not filed: the eager ViewVariantInspector edge (−13,799 B gzip), which waits on objectui#11762's budget line. It and the other findings are in ACCEPT 6122314458.
    • Next: item 3 (one sys_user_preference read per load) is dispatched under this claim with its own amendment.

    Generated by Claude Code

  14. objectstack-fleet commented on Oct 12, 2026

    @objectstack-fleet
    Contributor

    Claim amendment: item 3, one sys_user_preference read per load · domain:ui seat 1 · session_016djJF12Qt14ejKR5Vjt4sK · 2026-10-12T11:00Z

    This amends claim 6119197321 for item 3. Item 1 landed as 54159d3 (landing 6121370721), and item 2 as 6eca5b5 (landing 6122924767).

    Item 3, as the card states it: "One sys_user_preference read per load (share the query)." Acceptance 3: "sys_user_preference requested once per load." The card measured three reads per load on staging.

    Measure first. ⛔ No change is written before the measurement exists. On objectui main 6eca5b5, the PR records every sys_user_preference request a console page load makes before and after its content, with the module and call that makes each.

    Candidates seen at amendment time, all to be measured:

    • ConsoleShell.tsx builds three createObjectStackUserStateAdapter instances (favorites, recent, flowPaletteRecents), each over the same resource.
    • Their readers are FavoritesProvider, RecentItemsProvider and the flow palette's recents.

    Amended file surface, item 3:

    • packages/data-objectstack/src/userState.ts (the adapter factory) and packages/app-shell/src/console/ConsoleShell.tsx (where the adapters are built), plus whichever reader the measurement names as making its own read.
    • The share: the adapters share ONE read of the user's preference rows per load, and each takes its own key from it. Writes are unchanged: a save still writes its own row.
    • Published surface:
      • Prefer a shape that adds no export, option or type to @object-ui/data-objectstack or @object-ui/app-shell.
      • If the share needs one, add it as a declared surface addition and say so in the PR body. The PR's line is then Clause-②: yes (widening) with at least a minor changeset, and a contract-tier review is owed before the queue.
      • ⛔ Nothing removed or renamed.
    • Co-located tests: a pin that counts sys_user_preference reads across a console boot (1), and a control that each adapter still reads and writes its own key.
    • .changeset/12187-user-preference-one-read.md at the level the diff takes.
    • ⛔ Nothing on the server. ⛔ No change to what is stored, or to the row shape.
    • (Stop on breach; explain in the report.)

    Item 3's PR first line is Fixes #12187, so the card closes with it. Its line, unless the share widens a published surface:

    Clause-②: no


    Generated by Claude Code

  15. objectstack-fleet commented on Oct 12, 2026

    @objectstack-fleet
    Contributor

    os-dev-report
    {
    "issue": 12187,
    "item": 3,
    "status": "done",
    "branch": "claude/issue-12187-user-preference-one-read",
    "pr": "#12241",
    "head": "55be3d7",
    "session": "session_016djJF12Qt14ejKR5Vjt4sK (subagent: the parent's id)",
    "premise_still_valid": true,
    "summary": "Item 3 only. Draft PR 12241: first line 'Fixes #12187', 'Clause-②: no' at a line start, assignee os-steve. I measured first, on main adfbe3b (which contains 6eca5b5), with a jsdom boot of the real ConsoleShell and ConnectedShell over a counting fetch. Before: 3 sys_user_preference GETs per boot, each filtered by user_id and one key with top=1. They come from the FlowPaletteRecentsProvider, RecentItemsProvider and FavoritesProvider hydrate effects, each calling adapter.load(), then findExisting, then ObjectStackAdapter.find. The fix is in packages/data-objectstack/src/userState.ts only. load() joins an open read per (data source, resource, user). Loads issued before the next microtask add their keys, one request goes out, and each adapter takes its own row. One key keeps today's per-key query; several keys go as one 'user_id = U and key in (...)' query with top equal to the key count. Nothing is kept once the read is sent, and save() is unchanged. After: 1 GET per boot, both entries (direct page and '/'). ConsoleShell.tsx needed no change. No export, option or type was added (index.ts unchanged; export lines and the options interface diff exit 0 against base). The two earlier pins that held three reads as correct (objectui#5544's consoleUserPreferenceBudget, objectui#11797's first wire case) were moved to the ruled budget.",
    "measurement": {
    "instrument": "jsdom boot: real ConsoleShell providers + real ConnectedShell (AdapterProvider, ObjectStackAdapter, client, UserStateBridge) over a counting global fetch; entries /apps/demo/page/welcome and / (metadata-gated redirect); only useAuth stood in; call sites from a sync stack at ObjectStackAdapter.find; probe uncommitted",
    "H1_before_adfbe3b": "3 GETs per boot on both entries: top=1&filter=[and,[user_id,=,u1],[key,=,K]] for K = ui.flow.palette.recents (FlowPaletteRecentsProvider hydrate effect), ui.recent (RecentItemsProvider), ui.favorites (FavoritesProvider); each filtered by its own key, not the user's whole set",
    "H1_after_55be3d7": "1 GET per boot on both entries: top=3&filter=[and,[user_id,=,u1],[key,in,[ui.flow.palette.recents,ui.recent,ui.favorites]]]; '/' does not remount ConnectedShell on its redirect (same element type and position), so it was 3 before and 1 after as well",
    "H2": "Chosen: the share inside userState.ts, a module WeakMap keyed by data-source object, then (resource, user); no new export, option or type. Not chosen: a ConsoleShell-built loader, which needs a new factory option (widening). Why key-in and not the whole user set: the whole set carries every other preference (theme, locale, plugin settings) and a page cap could drop a key. Same user_id predicate; the unique index (user_id, key) per organization bounds the answer to one row per key, so top = key count drops none. Server side, read from objectstack 2e11d9006 sources only, no live server: 'in' is an AST_OPERATOR_MAP key behind VALID_AST_OPERATORS, and driver-sql has an 'in' arm. Untagged rows in a multi-key answer are not attributed; each adapter falls back to its own per-key read (pinned).",
    "H3": "No focus or visibility refresh. The hydrate effects re-run only when the adapter or the user id changes; new adapters come on a user id change, a data-source change, or a bridge remount under MetadataProvider key={language}. Writes read nothing back. Account switch u1 to u2: before 6 GETs (3 stale u1 reads from the outgoing adapters, discarded by the hydration token, plus 3 for u2); after 2 (1 plus 1); the u2 read asks for u2's three keys and every consumer ends on u2's rows. A load after the read was sent makes a fresh request. After boot, writes are 3 PATCHes, one to each adapter's own row, with no extra GET.",
    "H4": "Neither runtime/config nor auth/me/localization appears in this boot reading. Their initiators (index.html applyEarlyBranding; initRuntimeConfig from main.tsx) are outside the mounted tree. NOT MEASURED here.",
    "browser": "NOT MEASURED, reason: no runnable signed-in backend in this container; the jsdom boot is the instrument; staging acceptance 3 stays with the seat"
    },
    "tests": "All at 55be3d7, through os-verify-lock. (1) turbo run build --filter='@object-ui/data-objectstack^...' --filter='@object-ui/app-shell^...' --concurrency=2: 'Tasks: 28 successful, 28 total'; data-objectstack rebuilt at head, BUILD-DOS-OK. (2) type-check, both scripts echoed: '@object-ui/data-objectstack type-check' (tsc --noEmit) and '@object-ui/app-shell type-check' (tsc --noEmit && tsc -p tsconfig.test.json); TYPECHECK-OK. --listFilesOnly shows both edited data-objectstack tests (2) and the app-shell pin (1) in the programs. (3) vitest over every test file naming createObjectStackUserStateAdapter, sys_user_preference or UserStateAdapters (14 files, including the new pins): 'Test Files 14 passed (14) / Tests 161 passed (161)', VERDICT command-exit 0. (4) Ablation, fix committed first, via objectstack scripts/ablation-replace.mjs in wrap mode. Mutation: 'const row = await loadExisting();' to 'const row = await findExisting();', which disables the share. Anchor 1 to 0, blob cc27d4d to bc3fb25. Predicted red. Result: 'Tests 12 failed | 8 passed (20)'; every count pin failed with 'expected ... to have a length of 1 but got 3', or 2 for the edge cases. Unaffected cases stayed green: same-key coalescing, user scope, data-source scope, writes. Restore: blob after restore == HEAD (cc27d4d), git diff HEAD empty. The pins resolve @object-ui/data-objectstack through the vitest src alias, so no dist is on their path. (5) ESLint narrowing, measured: eslint --no-inline-config --format json over the 4 changed .ts/.tsx files gave 4 files, 0 errors, 1 warning. That warning is the existing DataSource typed any on the options member; the base file via --stdin also has 1. A new any in joinSharedRead was removed in 55be3d7. Population: eslint.config.js files '/.{ts,tsx}'. Not type-aware: grep projectService|typeChecked|tsconfigRootDir|parserOptions exits 1, control languageOptions count 1. No eslint-rules/.js reads the filesystem; the one regex hit is 'defs.filter' in no-line-address-in-test-name. Repo-wide lint: NOT MEASURED, CI-owned.",
    "gates": {
    "head": "55be3d7",
    "build: turbo run build --filter='@object-ui/data-objectstack^...' --filter='@object-ui/app-shell^...' --concurrency=2": "pass (28 successful); plus turbo build --filter='@object-ui/console^...' 34 successful and console vite build exit 0 for the eager-closure report",
    "type-check @object-ui/data-objectstack": "pass (script echoed: tsc --noEmit)",
    "type-check @object-ui/app-shell": "pass (script echoed: tsc --noEmit && tsc -p tsconfig.test.json)",
    "vitest targeted": "14 files / 161 tests passed",
    "check:eager-closure": "exit 0 ('Console eager closure is 3126.9 KB gzipped across 70 of 2253 chunks (budget: 3204.6 KB, headroom: 77.6 KB)'; chunk membership exact)",
    "check:vi-mock-specifiers": "exit 0",
    "check:vi-mock-inherit": "exit 0",
    "check:vi-mock-override-shape": "exit 0",
    "check:test-path-roots": "exit 0",
    "check-changeset-presence": "exit 0 ('4 source file(s) of 2 released package(s) changed, and this change declares 1 changeset(s)')",
    "check:changeset-claims": "exit 0",
    "check:pending-changeset-literals": "exit 0",
    "check:control-bytes": "exit 0",
    "check:new-line-citations": "exit 0 ('0 new citation(s)')",
    "changeset:check": "exit 0 (no major)",
    "CI": "not awaited (PM-owned)"
    },
    "line_budget": "n/a: no skills/
    or line-ratcheted governed file touched; no governed surface in the diff",
    "files_changed": [
    "packages/data-objectstack/src/userState.ts",
    "packages/data-objectstack/src/userState.inflightShare-11797.test.ts",
    "packages/data-objectstack/src/userState.sharedRead-12187.test.ts (new)",
    "packages/app-shell/src/console/tests/consoleUserPreferenceBudget.test.tsx",
    ".changeset/12187-user-preference-one-read.md (@object-ui/data-objectstack: patch)"
    ],
    "deviations": [
    "The file surface held. ConsoleShell.tsx is unchanged: the bridge already builds the three adapters in one effect. No reader makes its own read, so no reader file changed.",
    "Two existing co-located pins encoded the old budget and were reversed to the ruled one. consoleUserPreferenceBudget.test.tsx (objectui#5544) pinned 3 reads via a bridge copy; it now boots the real shell, pins 1 read, and keeps the each-consumer-gets-its-own-row half. userState.inflightShare-11797.test.ts's first case ('three different questions') now pins the shared read; its other two cases are unchanged. The PR body names the reversal.",
    "The dispatch read main at 6eca5b5. The worktree branched from origin/main adfbe3b, one later commit (a skills tooling change outside this surface).",
    "Browser reading NOT MEASURED; H4 NOT MEASURED in this instrument (initiators outside the mounted tree).",
    "Commit trailers use the model-free pair from AGENTS.md (Claude-Session + 'Co-authored-by: Claude'). The harness reminder asked for a model-named Co-Authored-By; AGENTS.md takes precedence."
    ],
    "mcp_calls": "0. No MCP tool was called.",
    "api_writes": "2 relay strokes via objectstack scripts/pm/fleet-write/dispatch.mjs, landing as objectstack-fleet[bot]; each transported as 1 POST /repos/objectstack-ai/objectstack/dispatches. Stroke 1 (run 38244188530, success), pr_create: POST /repos/objectstack-ai/objectui/pulls (draft) and POST /repos//issues/12241/assignees (os-steve). Read back: 11325 bytes sent, 11325 stored, identical; assignees os-steve. Stroke 2, comment: POST /repos//issues/12187/comments (this os-dev-report). Label writes 0, card assignee writes 0. git push x5 (not REST): the empty-branch probe, then c4b9ac3, 6fffff3, b57a415, 55be3d7. Reads: REST GETs of #12187 and its comments, of #5544 and #11797 (state only), and of PR 12241.",
    "open_questions": [],
    "out_of_scope_findings": [
    "carrier: none (承接者:无) · noted, not filed (PR Acceptance notes): on an account switch, the outgoing adapters still make one read for the previous user before the bridge attaches the new ones. The providers' hydration token discards it, so no wrong answer reaches the UI. Pre-existing; the count goes from 3 to 1 with this PR."
    ],
    "worktree": "removed (node_modules deleted, git worktree remove exit 0, clean)"
    }


    Generated by Claude Code

  16. objectstack-fleet commented on Oct 12, 2026

    @objectstack-fleet
    Contributor

    ACCEPT: PR objectui#12241 (head 55be3d7569), item 3 of 3 · domain:ui seat 1 · session_016djJF12Qt14ejKR5Vjt4sK · 2026-10-12T11:43Z

    Reviewed against GitHub and the diff, not the report (os-dev-report 6123564193). Claim 6119197321, amended for item 3 by 6122942302.

    Verdict

    • Shape:
      • Draft on main. The first line is Fixes #12187, so the card closes with this last item. Clause-②: no sits at a line start.
      • Assignee os-steve. The commit trailers and the body carry no model identifier.
    • Scope: 5 files, +621/−245 (source +136). check-governed-merges: NOT governed.
    • Measured before the change, as the amendment requires. A jsdom boot of the real ConsoleShell and ConnectedShell over a counting fetch, on main adfbe3b, which contains item 2:
      • Before: 3 sys_user_preference GETs per boot on both entries (a direct page and /). Each was user_id = u1 and key = K, $top: 1, from the FlowPaletteRecentsProvider, RecentItemsProvider and FavoritesProvider hydrate effects.
      • After: 1 GET, user_id = u1 and key in (the three keys), $top: 3.
      • On an account switch: 2 reads, from 6 before.
      • After boot, writes are 3 PATCHes, each to its own row, with no extra GET.
    • The share is internal to userState.ts, as the amendment preferred.
      • load() joins an open read per (data source, resource, user), held in a module WeakMap keyed by the data-source object.
      • Loads issued before the next microtask add their keys, and the read closes the moment it is sent. Nothing is kept past the request, so a later load() asks again, and a different user or data source never joins another's read.
      • A lone key keeps today's exact per-key query.
      • save() is unchanged and still finds and writes its own row through findExisting.
      • ConsoleShell.tsx needed no change.
    • The multi-key answer is read defensively. A row is a key's own only when it names that key, and the user when it carries one.
      • An untagged row in a multi-key answer is not guessed at: that adapter falls back to its own per-key read, which is pinned.
      • The object's unique (user_id, key) index per organization bounds the answer to one row per key, so $top equal to the key count drops none.
      • Server support for in was read from objectstack source at 2e11d9006 (AST_OPERATOR_MAP and driver-sql's in arm), not from a live server.
    • Clause-②: no holds. No export, option or type was added. data-objectstack's entry exports createObjectStackUserStateAdapter and its types exactly as on base, and the options interface is unchanged.
    • Two existing pins that encoded the old budget are reversed to the ruled one, and the reversal is declared in the PR body:
      • consoleUserPreferenceBudget (objectui#5544) pinned 3 reads through a copy of the bridge. It now boots the real shell, pins 1, and keeps its each-consumer-gets-its-own-row half.
      • userState.inflightShare-11797's first case now pins the shared read. Its other two cases are unchanged.
      • Acceptance 3 ("sys_user_preference requested once per load") is the ruling that supersedes them.
    • The pins carry weight. With the share disabled (loadExisting → findExisting), 12 rows go red, each with a count of 3, or 2 in the edge cases. The scope, coalescing and write rows stay green, and the restore is blob-equal.
    • The eager closure did not move: 3126.9 KB across 70 chunks against the unchanged 3204.6 KB budget, from the dev's local console build.
    • Changeset: @object-ui/data-objectstack patch.
    • Gates on this head, read at this record: 22 success, 3 skipped by design, 17 in progress, 0 failure. The seat enqueues only once all of them read success.

    Out of scope

    • The doubled runtime/config and auth/me/localization reads item 2 saw under its mock do not appear in this boot reading, because their initiators sit outside the mounted tree. They were not measured here.
    • The card's staging acceptance stays with the seat once cloud's objectui pin carries items 2 and 3:
      • 3: one sys_user_preference request per load;
      • 2: main within 3 s, the request count, and no Studio chunk on a non-Studio route.

    Landing: ready and auto-merge through the merge queue once every check on 55be3d7 is success or skipped by design. behind is not a veto.


    Generated by Claude Code

  17. objectstack-fleet commented on Oct 12, 2026

    @objectstack-fleet
    Contributor

    Landed, item 3: PR objectui#12241 → main d48071e · domain:ui seat 1 · session_016djJF12Qt14ejKR5Vjt4sK · 2026-10-12T12:21Z

    • The merge: through the merge queue, on top of fc1bc66. The card closed as completed through PR objectui#12241's Fixes #12187. Read in this act: nothing else closed with it.

    • Content check: all 5 files the PR changes are blob-identical at d48071e to the accepted head 55be3d7569, which ACCEPT 6123579917 covers.

    • On main now: the console's user-state adapters (favorites, recent items, flow palette recents) share one sys_user_preference read per load. The read is user_id = USER and key in (...), and each adapter takes its own row. A lone key keeps the per-key query, and writes are unchanged.

    • All three items are on main:

      item PR → main record
      1, the boot copy objectui#12203 → 54159d3 landing 6121370721
      2, page-route chunks objectui#12226 → 6eca5b5 landing 6122924767
      3, one preference read objectui#12241 → d48071e this note
    • Still owed, on staging, once cloud's objectui pin carries d48071e:

      • acceptance 1: the zh-CN and en boot screenshots;
      • acceptance 2: main within 3 s, under 100 requests before content, and no Studio chunk on a non-Studio route (the local reading was 102, see landing 6122924767);
      • acceptance 3: one sys_user_preference request per load.

      The card is closed by its PRs. If a staging reading fails one of these, it reopens the card's own question.

    • Carried, not filed: the eager ViewVariantInspector edge and the eager-closure headroom (objectui#11762's budget line), recorded in ACCEPT 6122314458.

    • State: pm:dispatched is removed in this act. The card's other labels stay.


    Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

area:devpathThe road — create, dev, verify, publish/install, connect an agent, iteratebugSomething isn't workingdomain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seatpriority:p1

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions