Repository navigation
Seam: one request opens a record — a record-page payload (record + related counts and first rows + field access + lock) and an app-scoped metadata bundle, so a record open is 2–3 requests instead of 23–45 serialized in three stages #27627
Description
epic:#26676#1 · zhuangjianguo · session_cdb7a717def74e719988f089fbaa18ff
Filed from the record-page epic #26676 as a sub-issue after the maintainer's 「别人的界面很丝滑,但是我们的界面总觉得卡顿,云端更卡」 and the seat's measurement (2026-10-29). Ruling: 「立…B(接缝卡:记录页一次取齐 + 元数据打包)两张卡,p1」. A Seam: card: the producer is the REST surface (packages/rest / plugin-hono-server, the data and metadata routes), the consumer is the console's data layer (ui/packages/data-objectstack) and the record page; the seat that claims it declares both ends. The client-side waste on the same path is #27626.
Measured
Local (console main 273137d227, dev mode, HotCRM on localhost:4001): opening one contact = 45 requests cold / 23 warm, in three serial stages — ① the record (GET /data/crm_contact?populate=…) + security/explain ×2 + approvals/requests; ② after the record arrives (+130 ms of client work): one GET /meta/object/<child> per related object (9 on a contact), field-access ×4, the approvals lock; ③ after the metadata arrives: one GET /data/<child>?top=1&filter=… count probe per related list (10 on a contact) + attachments + the related rows query + the account. Locally each stage is tens of milliseconds; the drawer is visible at 300 ms.
Cloud (huayan.objectos.app, Cloudflare colo ARN, h2, prod bundle 2.2 MB JS in 93 scripts): the same endpoints cost 0.5–1.4 s each when called alone (GET /api/v1/runtime/config, 293 bytes: 555 / 604 / 729 / 1068 / 1377 ms over five sequential calls; GET /meta/app 0.9–1.8 s; GET /meta/view 1.8–3.8 s; no cache-control, no server-timing). The HotCRM contacts list route fired 42 API calls on load, of which auth/me/localization 8.2 s, packages 7.9 s, sys_inbox_message 7.5 s, meta/dashboard 6.1 s, meta/object/sys_user 5.3 s, data/crm_contact 5.3 s — the same calls that take ~1 s alone take 5–8 s when fifteen of them run at once, and the list had not rendered after 50 s. A three-stage, 23-request record open on that path is a multi-second wait by arithmetic alone.
Linear, Attio and Twenty open a record with one aggregated request (counts and permissions ride with the record), load metadata once at boot, and prefetch on hover.
Target
- A record-page payload endpoint (shape to be designed by the claiming seat and recorded under
packages/spec/contracts/**):GET /api/v1/data/<object>/<id>/page(or aquerybody) returns in ONE response — the record with its populated lookups; for every related list the console would draw (the inbound lookups, in the object's declared order) the count and the first N rows (N = 3, the compact panel's face) with the related-list columns; the caller's field access for the record; the approval lock state; the record's security verdict (explain) for the actions the header draws. One request, one round trip, one server-side transaction. - An app-scoped metadata bundle:
GET /api/v1/meta/app/<appId>/bundlereturns the app, its navigation, every object the app's navigation and those objects' inbound relations reach, their views, pages and dashboards, with an ETag; the console loads it once per session and sendsIf-None-Matchafter. Today's per-objectGET /meta/object/<name>stays for Studio and for objects outside the bundle. - The console consumes both: the record page (split pane, overlay, full page, Record page v4: same-shaped related panels with no collapse, a persistent tab row under the header (the enlarged state is the active tab), Activity as the first panel and a tab, one top bar on every face, tiers by container width #27524 / Record drawer v4: a bounded peek over the list — md cap instead of the field-count bucket, no dim overlay, the list stays readable and clickable, ⤢ maximizes in place at the same URL; the full page is reached only from the row ↗ and the header ⋯ #27545) opens from the page payload with no second stage; stepping ↓ ↑ prefetches the next and previous records' payloads; the per-related
top=1count probes, the per-open child metadata loads and the separatefield-access/lock/explaincalls on open retire (startup posture: no dual path kept). - Server-side observability for the cloud reading: the REST layer emits
Server-Timing(db, meta, total) on every response, so the next measurement separates origin time from the network path; metadata responses carryCache-Control+ETag. - Clause-②: yes (new REST routes, declared in the spec contracts); Metadata-protocol: added (the bundle's shape).
File surface
Producer: packages/rest/src/** (routes), packages/plugin-hono-server/** (wiring), packages/spec/contracts/** (the two shapes), packages/objectql only if a batched count query is needed, tests beside, changeset. Consumer: ui/packages/data-objectstack/src/index.ts, ui/packages/app-shell/src/views/RecordDetailView.tsx + recordDrawerStack.tsx (prefetch), ui/packages/plugin-detail/src/renderers/recordBinding.tsx + RelatedCardStack.tsx (counts and rows from the payload), tests beside, changeset.
Acceptance
- Contract tests for both shapes; a console test that a record open issues exactly one page-payload request (plus at most one metadata bundle on a cold session) and zero
top=1probes. - The cloud reading re-run by the epic seat on
huayan.objectos.appafter landing: record open under 1 s warm, list route under 3 s cold, withServer-Timingin the PR body. - The epic seat verifies in the console preview before ACCEPT (maintainer: 「车队开发完后你审核效果」).
Activity
objectstack-fleet commentedon Oct 29, 2026
epic:#26676#1 · zhuangjianguo · session_cdb7a717def74e719988f089fbaa18ff
Deployment half filed · 2026-10-29T15:22Z · objectstack-ai/cloud#3378 (Ops, p1,
pm:queue): the path and origin reading forhuayan.objectos.app— the ~0.5 s floor per call, the Stockholm (ARN) colo for a China user, the 5–8 s per call under a 15-call burst, edge caching for/meta/*. Item 4 of this card (RESTCache-Control+ETag+Server-Timing) is what that card's edge rule and timing split consume; the two land independently.objectstack-fleet commentedon Oct 29, 2026
domain:spec#3 · os-support-ai · session_01WGufzgbJhFoXYsLSe5WSPP
Claim: PM loop round 3 · 2026-10-29T15:31Z
Session:
session_01WGufzgbJhFoXYsLSe5WSPPAccount:
os-support-aiBranch:
claude/project-thread-2m7jqd(card thread; the platform assigns the thread's branch and it can push only that one, written as measured instead ofclaude/issue-27627-<slug>)Worktree:
objectstack-27627Domain:
domain:specSeat:
domain:spec#3Ruling-ref: the maintainer's ruling on epic #26676 quoted in the card body (「立…B(接缝卡:记录页一次取齐 + 元数据打包)两张卡,p1」); two PRs from this branch, the first
Part of #27627File surface: producer:
packages/rest/src/**,plugin-hono-server,packages/spec/contracts/**(the two shapes),packages/objectqlonly for a batched count; consumer:ui/packages/data-objectstack,RecordDetailView.tsx,recordDrawerStack.tsx,recordBinding.tsx,RelatedCardStack.tsx; tests; one root changeset per touched published package (stop on breach; explain in the report)Container & model:
L,mode:thread,model: TIER_DEFAULT — --tier: no path-derived mandate (new REST routes; the contract review is triage's),effort: highClause-②: yes (widening)
Metadata-protocol: added (the app bundle's shape), as measured by the dev
Responsibility: an unclaimed p1
domain:speccard; seat 1 is off dutyThread-read: none
Premise: to be measured first by the dev on
origin/main178b5238: one record open issues 23 (warm) to 45 (cold) requests in three serial stagesSerial constraints cleared: #27626 (client-side waste, same path) and cloud#3378 (deployment half) are left untouched; the dev re-checks open PRs on these files before editing
objectstack-fleet commentedon Oct 29, 2026
domain:spec#3 · os-support-ai · session_01WGufzgbJhFoXYsLSe5WSPP
Claim amendment: one declaration and a surface extension (PR 1, #27713) ·
domain:specseat 3 · sessionsession_01WGufzgbJhFoXYsLSe5WSPP· 2026-10-29T20:18Z · same claim 6501011060, same branchclaude/project-thread-2m7jqdMetadata-protocol: added, as measured by the dev: the two new shapes enterpackages/spec/authorable-surface/api.json, andcheck-changeset-no-majorrefusesnone. Every moved package isminor.types, thecomponentsrelated-count store,plugin-detail(useRecordEditable,queueClaim,recordFieldAccess,RelatedList,index,package.jsonsideEffects), and app-shelluseRecordApprovalsplus a newrecordPagePayload.ts. It also covers the dogfood fixture and test, the rest census tests andrest-server-registrar-files.ts, thescripts/check-route-envelope.mjsMODULES row, the generated spec artifacts andcontent/docs/references/api. The PR body gives the reason. Size 2980 lines (under the 3000 human-merge threshold), 0 governed paths.objectstack-fleet commentedon Oct 30, 2026
domain:spec#3 · os-support-ai · session_01WGufzgbJhFoXYsLSe5WSPP
ACCEPT → PR #27713 comment 6524688486 (Tier H: approved by the maintainer, enqueued)
objectstack-fleet commentedon Oct 30, 2026
domain:spec#3 · os-support-ai · session_01WGufzgbJhFoXYsLSe5WSPP
Landed (PR 1 of 2) ·
domain:specseat 3 ·os-support-ai· 2026-10-30T21:07Z6293d95ef, merge commit0027c4a2b8origin/maingit merge-base --is-ancestor)Delivered:
POST /api/v1/data/{object}/{id}/pageanswers in one request everything a record page needs when it opens: the record with its lookups expanded, each related list's total and first rows, field access, approvals and lock, and the header actions' permission verdicts. Each part is computed as the same caller, through the same function as the read it replaces.Released. PR 2 of this card (metadata bundling) is not started. Spec seat 3 goes off duty with this landing, so it releases its claim (6501011060) and assignee here. The card stays open with
pm:queuefor the next seat. The deployment half is cloud#3378.9 remaining items
objectstack-fleet commentedon Oct 31, 2026
domain:spec#1 · os-tesla · session_01L9qibwb6hBqszPTYJobitm
Claim correction · 2026-10-31T03:10Z · amends claim 6538108232 (branch
claude/project-thread-hw8j7d), append-onlyFile surface, amended by seat ruling: also
packages/client(meta.getAppBundle(appId)), so the route ledger row takes dispositionsdk. PR 1'sdata.recordPageis the precedent. PR: #28287 (draft,Part of #27627). Shape:packages/spec/src/api/app-bundle.zod.tsAppMetadataBundleResponseSchema.objectstack-fleet commentedon Oct 31, 2026
domain:spec#1 · os-tesla · session_01L9qibwb6hBqszPTYJobitm
Claim correction · 2026-10-31T03:11Z · amends claim 6538102504 (branch
claude/project-thread-dd5lh4), append-onlyFile surface, amended by seat ruling. Both additions are forced by the dependency graph, and the PR body should name both:
packages/types/src/representation-validator.ts(new), plus one export line inpackages/types/src/index.ts. This is the one copy of the body-hash ETag /If-None-Matchrule.rest,plugin-hono-serverandcloud-connectionall depend ontypes, and onlyrestkeeps the/metawrapper.packages/cloud-connection/package.jsongains@objectstack/observability(workspace:*), plus its lockfile lines. It is needed for the existing admin perf-disclosure gate onruntime/config.objectstack-fleet commentedon Oct 31, 2026
domain:ui#2 · os-tesla · session_01L9qibzFu8iUogiZhxL9tAo
os-dev-report
Console half of #27627 (PR 3, metadata bundle consumer): draft #28321, head
c6e775cf, reported 2026-10-31T04:33Z. Lands after #28287.{ "card": 27627, "pr": 28321, "branch": "claude/project-thread-xoio4p", "head": "c6e775cf5b508d2f3a6e4cd878eada5584c8a7a8", "draft": true, "lands_after": [28287], "declarations": { "clause_2": "no", "metadata_protocol": "none" }, "gates": { "derived": 67, "run": 67, "exit_0": 67, "not_measured": 0, "unrun": 0, "reconcile_exit": 0, "extra": ["check:new-line-citations :: exit 0", "check:nul-bytes :: exit 0"] }, "type_check": { "data-objectstack": 0, "app-shell": 0 }, "tests": { "card_files": 3, "card_tests": 20, "importer_files_run": 695, "importer_files_green_after_fix": 695 }, "acceptance": { "warm_record_open": { "page_requests": 1, "metadata_requests": 0 }, "cold_record_open": { "page_requests": 1, "bundle_requests": 1, "by_name_metadata": 0, "waves": 1 } }, "ablations": [ { "off": "bundle read in fetchObjectSchemaFresh", "red": 7 }, { "off": "AppContent loadAppBundle call", "red": 2 }, { "off": "write-door staleness", "red": 1 } ], "line_budget": { "limit": 3000, "used": 894, "additions": 864, "deletions": 30 }, "files_changed": 12, "deviations": [ "withheld vs outside: the bundle names nothing withheld, so an absent name keeps its by-name read (seat and spec seat 1 agreed)", "adapter fetches the bundle directly: client meta.getAppBundle had no If-None-Match/304; switch when the conditional method lands on #28287", "AppMetadataBundleResponse type not imported until #28287 is on main", "live boot NOT MEASURED: the route exists only on #28287's branch" ], "writes": { "relay": 2, "mcp_calls": 0 } }objectstack-fleet commentedon Oct 31, 2026
domain:spec#1 · os-tesla · session_01L9qibz5qPfjVU7Mns3iE1H
os-dev-report
{ "issue": 27627, "status": "done", "branch": "claude/project-thread-dd5lh4", "pr": "https://github.com/objectstack-ai/objectstack/pull/28320", "session": "session_01L9qibz5qPfjVU7Mns3iE1H", "premise_still_valid": true, "summary": "Target 4 only (Part of). The /meta type list, every /meta/:type list, the uncached item exit (app/dashboard/doc/book, drafts, ?package=, member-scoped), /auth/me/localization and /runtime/config answer a weak body-hash ETag over the served bytes, Cache-Control private, no-cache and a bodiless 304; the rule is one module in @objectstack/types. Every timed response carries db and meta beside total (zero members when nothing ran); /runtime/config opens the per-request gate for an admin only when X-OS-Debug-Timing is sent. Step 1 correction: the app/dashboard/doc/book item doors had no ETag on main. Dispatcher /meta twin: private, no-cache, no ETag, no 304.", "tests": "head 6d31fbb1 under os-verify-lock VERDICT command-exit 0: rest 360 files / 7127 passed (351 skipped); cloud-connection 62 / 765; plugin-hono-server 36 / 457; types 35 / 846. runtime meta/timing targeted 31 / 1451 (before the gate fix, which touched no runtime/rest logic). New: representation-validator.test.ts 10, meta-representation-etag.test.ts 13, server-timing-seeded-marks.test.ts 4, localization validator block 5, runtime-config-etag.test.ts 7. Ablation: list chain hashing the pre-gate list (metaRepresentationCaching(raw, cacheControl)) -> 1 failed / 12 passed, exactly 'two callers whose gate differs get different tags'; restored, blob == HEAD. Live HotCRM: main 0/58 lists+bootstrap ETag; branch 58/58 ETag, 57/58 304 (flow 200 by design, same on main), db/meta/total on 58/58 for the admin header.", "gates": "local: dispatch-gates --commands on the final tree -> 94 commands, each run with </dev/null, '<command> :: exit <code>' recorded first; --ran -> 94 run, 0 NOT-MEASURED, 0 UNRUN, all exit 0. First sweep (76) reds fixed in 6d31fbb1: check:route-envelope (helper declared {}; localization/runtime-config bodies kept as call-site literals) and check:test-source-alias (observability alias in cloud-connection). check:dts-closure, check:dual-build-cjs-loads, check:lean-entry-closure exit 0 after a full dts build. check-governed-merges --branch HEAD: 0 of 23 governed, 1025 lines. CI: PR check-runs not yet concluded at report time; the seat reads them.", "dogfood_battery": "n/a — no `!` in the PR title and no (narrowing) arm", "line_budget": "23 files, +991 / -34 (1025 changed lines incl. 3 lockfile lines)", "files_changed": 23, "deviations": [ "Rebase onto main could not be force-pushed (auto-mode classifier refused --force-with-lease); history kept as merge origin/main + fix commit, tree byte-identical to the rebased tree.", "PR body footer: the session-URL `_Generated by_` line is present but without the preceding `---` rule line; dev writes the body once, so the seat may add the rule line if the platform needs the whole block.", "Branch live re-measure was taken before the main merge (head e7bd43ac); the merge brought no overlapping file." ], "mcp_calls": "13 — all reads: issue_read x5, list_pull_requests x3, search_pull_requests x3, pull_request_read x2 (transcript grep); 0 write tools", "api_writes": "2 relay writes so far — pr_create (fleet-write run 41168920329, #28320) and this os-dev-report comment via post-stamped --comment=27627; plus git push (not REST)", "open_questions": [], "out_of_scope_findings": [ "carrier: none · noted, not filed — the flow item answers an ETag that never revalidates (registration read live beside the document is in no validator); by design per meta-item-read-routes.ts, recorded in the PR body only" ] }Generated by Claude Code
objectstack-fleet commentedon Oct 31, 2026
domain:spec#1 · os-tesla · session_01L9qibwM9YxDuiRDQYmA1Yd
os-dev-report
{ "issue": 27627, "part": "PR 2 of #27627 (bundle producer)", "pr": "https://github.com/objectstack-ai/objectstack/pull/28287", "draft": true, "branch": "claude/project-thread-hw8j7d", "head": "28ac68c20651a0ac549956e52c8e3c85de16ab7c", "base_merged": "53749673ba7a0005d09e8a79544da10d5faa10bc", "claim": 6538108232, "gates": { "derived": 125, "run": 125, "exit_0": 125, "not_measured": 0, "unrun": 0, "reconcile": "dispatch-gates --ran: 125 derived, 125 run, 0 NOT-MEASURED, 0 UNRUN (exit 0)", "reruns_after_prerequisite": [ "node scripts/check-plugin-teardown-shape.mjs --self-test (pinned fixture commit fetched into the shallow clone)", "pnpm --filter @objectstack/spec run check:skill-examples (after pnpm build)", "pnpm check:dual-build-cjs-loads (after pnpm build)" ], "finding_fixed": "pnpm check:doc-authoring: tracker id in the ledger row note string, moved to a // comment, rerun exit 0" }, "tests": { "rest_bundle_route": "14/14", "client_suite": "685/685 (53 files)", "spec_shape": "3/3", "rest_census_set": "307 passed (10 files)", "dogfood_authz": "70/70", "typecheck": { "rest": 0, "client": 0, "spec": 0 } }, "ablation": { "mutation": "bundleValidator(JSON.stringify(body)) -> bundleValidator(JSON.stringify(Object.keys(body)))", "tool": "scripts/ablation-replace.mjs", "red": "2/14", "restored_blob_equals_head": true, "green_after": "14/14" }, "line_budget": { "limit": 3000, "changed": 1215, "additions": 1202, "deletions": 13 }, "files_changed": [ ".changeset/27627-app-metadata-bundle.md", "content/docs/references/api/app-bundle.mdx", "content/docs/references/api/index.mdx", "content/docs/references/api/meta.json", "content/docs/references/index.mdx", "docs/audits/2026-07-unknown-key-strictness-ledger.counts/api.md", "packages/client/src/index.ts", "packages/client/src/meta-app-bundle.test.ts", "packages/rest/src/meta-app-bundle-routes.test.ts", "packages/rest/src/meta-app-bundle-routes.ts", "packages/rest/src/rest-config-mount-table.pin.test.ts", "packages/rest/src/rest-route-ledger.ts", "packages/rest/src/rest-server-canonical-query-ast.test.ts", "packages/rest/src/rest-server-docblock-position.test.ts", "packages/rest/src/rest-server-registrar-files.ts", "packages/rest/src/rest-server.ts", "packages/spec/api-surface/api.json", "packages/spec/authorable-surface/api.json", "packages/spec/declaration-map/api.json", "packages/spec/export-origins/api.json", "packages/spec/json-schema.manifest/api.json", "packages/spec/llms.txt", "packages/spec/src/api/app-bundle.test.ts", "packages/spec/src/api/app-bundle.zod.ts", "packages/spec/src/api/index.ts", "scripts/check-route-envelope.mjs" ], "deviations": [ "ETag = SHA-256 of the served body after every gate instead of folding per-dimension fingerprints (seat-confirmed; the Target 4 rule; switch to its helper if it lands first)", "meta.getAppBundle(appId, { ifNoneMatch }) answers a conditional {notModified, data?, etag} in getCached's spelling rather than bare data (seat note from the ui seat 2 consumer); private fetch gains opt-in admitNotModified", "metaItemAnswerSources gains an optional 5th type argument defaulting to req.params.type" ], "out_of_scope_findings": [ { "class": "a", "what": "meta.getCached 304 branch in packages/client is unreachable: private fetch throws on non-ok before it runs", "dedupe": [ "getCached", "notModified", "304", "If-None-Match", "client fetch" ] } ], "writes": { "relay": 3, "relay_ops": [ "pr_create #28287", "issue_patch #28287 body", "comment #27627 (this report)" ], "mcp_calls": { "writes": 0, "reads": "issue_read, pull_request_read only" } }, "contract_review_subagent": false, "ready_flip": false, "automerge": false }objectstack-fleet commentedon Oct 31, 2026
domain:spec#1 · os-tesla · session_01L9qibwb6hBqszPTYJobitm
Claim correction · 2026-10-31T04:35Z · amends claim 6538102504 (branch
claude/project-thread-dd5lh4, PR #28320), append-onlyFile surface, amended by seat ruling: plus two doc edits the docs-drift list surfaced, both incomplete after this change rather than wrong.
docs/OBSERVABILITY.md: the Server-Timing members table gains themetarow, and notes thatdbandmetaare sent as zero members.content/docs/api/metadata-api.mdx:GET /metaandGET /meta/:typegain theETag,private, no-cacheand304answer.objectstack-fleet commentedon Oct 31, 2026
domain:spec#1 · os-tesla · session_01L9qibwM9YxDuiRDQYmA1Yd
os-dev-report
{ "issue": 27627, "part": "PR 2 of #27627 (bundle producer)", "pr": "https://github.com/objectstack-ai/objectstack/pull/28287", "draft": true, "branch": "claude/project-thread-hw8j7d", "head": "1e7a1b104ea5f7afccee6cb52f21b1c5fc01c501", "base_merged": "53749673ba7a0005d09e8a79544da10d5faa10bc", "claim": 6538108232, "gates": { "derived": 125, "run": 125, "exit_0": 125, "not_measured": 0, "unrun": 0, "reconcile": "dispatch-gates --ran: 125 derived, 125 run, 0 NOT-MEASURED, 0 UNRUN (exit 0)", "reruns_after_prerequisite": [ "node scripts/check-plugin-teardown-shape.mjs --self-test (pinned fixture commit fetched into the shallow clone)", "pnpm --filter @objectstack/spec run check:skill-examples (after pnpm build)", "pnpm check:dual-build-cjs-loads (after pnpm build)" ], "finding_fixed": "pnpm check:doc-authoring: tracker id in the ledger row note string, moved to a // comment, rerun exit 0", "taken_at": "28ac68c2", "after_head_commits": "2 commits, packages/client and the changeset only: the derived set is unchanged (diffed); client tsc 0; check:doc-authoring, issue-citations, nul-bytes, test-source-alias, agent-test-spelling, route-envelope, closed-ceremony-text, type-check-coverage, undeclared-dep-imports, empty-changeset, changeset-no-major all exit 0" }, "tests": { "rest_bundle_route": "14/14", "client_suite": "687/687 (53 files) at 1e7a1b10", "spec_shape": "3/3", "rest_census_set": "307 passed (10 files)", "dogfood_authz": "70/70", "typecheck": { "rest": 0, "client": 0, "spec": 0 }, "client_react": "34/34" }, "ablation": { "mutation": "bundleValidator(JSON.stringify(body)) -> bundleValidator(JSON.stringify(Object.keys(body)))", "tool": "scripts/ablation-replace.mjs", "red": "2/14", "restored_blob_equals_head": true, "green_after": "14/14" }, "line_budget": { "limit": 3000, "changed": 1240, "additions": 1226, "deletions": 14 }, "files_changed": [ ".changeset/27627-app-metadata-bundle.md", "content/docs/references/api/app-bundle.mdx", "content/docs/references/api/index.mdx", "content/docs/references/api/meta.json", "content/docs/references/index.mdx", "docs/audits/2026-07-unknown-key-strictness-ledger.counts/api.md", "packages/client/src/index.ts", "packages/client/src/meta-app-bundle.test.ts", "packages/rest/src/meta-app-bundle-routes.test.ts", "packages/rest/src/meta-app-bundle-routes.ts", "packages/rest/src/rest-config-mount-table.pin.test.ts", "packages/rest/src/rest-route-ledger.ts", "packages/rest/src/rest-server-canonical-query-ast.test.ts", "packages/rest/src/rest-server-docblock-position.test.ts", "packages/rest/src/rest-server-registrar-files.ts", "packages/rest/src/rest-server.ts", "packages/spec/api-surface/api.json", "packages/spec/authorable-surface/api.json", "packages/spec/declaration-map/api.json", "packages/spec/export-origins/api.json", "packages/spec/json-schema.manifest/api.json", "packages/spec/llms.txt", "packages/spec/src/api/app-bundle.test.ts", "packages/spec/src/api/app-bundle.zod.ts", "packages/spec/src/api/index.ts", "scripts/check-route-envelope.mjs" ], "deviations": [ "ETag = SHA-256 of the served body after every gate instead of folding per-dimension fingerprints (seat-confirmed; the Target 4 rule; switch to its helper if it lands first)", "meta.getAppBundle(appId, { ifNoneMatch }) answers a conditional {notModified, data?, etag} in getCached's spelling rather than bare data (seat note from the ui seat 2 consumer); private fetch gains opt-in admitNotModified", "metaItemAnswerSources gains an optional 5th type argument defaulting to req.params.type", "meta.getCached passes admitNotModified, so its 304 answers { notModified: true } instead of throwing (spec seat 1 asked for this; the class (a) finding is now fixed in this PR)" ], "out_of_scope_findings": [], "writes": { "relay": 5, "relay_ops": [ "pr_create #28287", "issue_patch #28287 body", "comment #27627 (first report)", "issue_patch #28287 body (getCached)", "comment #27627 (this report)" ], "mcp_calls": { "writes": 0, "reads": "issue_read, pull_request_read only" } }, "contract_review_subagent": false, "ready_flip": false, "automerge": false, "ablation_getcached": { "mutation": "drop { admitNotModified: true } from getCached's fetch", "red": "1/5", "restored_blob_equals_head": true }, "supersedes_report_comment": 6539061874 }objectstack-fleet commentedon Oct 31, 2026
domain:spec#1 · os-tesla · session_01L9qibwM9YxDuiRDQYmA1Yd
os-dev-report
{ "issue": 27627, "part": "PR 2 of #27627 (bundle producer)", "pr": "https://github.com/objectstack-ai/objectstack/pull/28287", "draft": true, "branch": "claude/project-thread-hw8j7d", "head": "170b86ad19fb0e32fa0fc1462ece83ab32ed28d0", "base_merged": "f49b4787 (main with #28320)", "claim": 6538108232, "gates": { "derived": 125, "run": 125, "exit_0": 125, "not_measured": 0, "unrun": 0, "taken_at": "170b86ad", "derived_set_changed": false, "reconcile": "dispatch-gates --ran: 125 derived, 125 run, 0 NOT-MEASURED, 0 UNRUN (exit 0)", "reruns_after_prerequisite": [ "spec dist-reading checks + check:docs/check:generated after check:generated --fix rebuilt spec and regenerated app-bundle.mdx", "check:skill-examples after client + client-react builds", "check:type-check-debt after pnpm install --frozen-lockfile (cloud-connection's new observability link)" ] }, "tests": { "rest_bundle_route": "15/15", "client_suite": "687/687 (53 files) at 1e7a1b10", "spec_shape": "3/3", "rest_census_set": "307 passed (10 files)", "dogfood_authz": "70/70", "typecheck": { "rest": 0, "client": 0, "spec": 0 }, "client_react": "34/34", "rest_full_suite": "7148 passed (361 files)" }, "ablation": { "mutation": "metaRepresentationCaching(body, undetermined) -> metaRepresentationCaching(Object.keys(body), undetermined)", "tool": "scripts/ablation-replace.mjs", "red": "3/15", "restored_blob_equals_head": true, "green_after": "15/15" }, "line_budget": { "limit": 3000, "changed": 1230, "additions": 1216, "deletions": 14 }, "files_changed": [ ".changeset/27627-app-metadata-bundle.md", "content/docs/references/api/app-bundle.mdx", "content/docs/references/api/index.mdx", "content/docs/references/api/meta.json", "content/docs/references/index.mdx", "docs/audits/2026-07-unknown-key-strictness-ledger.counts/api.md", "packages/client/src/index.ts", "packages/client/src/meta-app-bundle.test.ts", "packages/rest/src/meta-app-bundle-routes.test.ts", "packages/rest/src/meta-app-bundle-routes.ts", "packages/rest/src/rest-config-mount-table.pin.test.ts", "packages/rest/src/rest-route-ledger.ts", "packages/rest/src/rest-server-canonical-query-ast.test.ts", "packages/rest/src/rest-server-docblock-position.test.ts", "packages/rest/src/rest-server-registrar-files.ts", "packages/rest/src/rest-server.ts", "packages/spec/api-surface/api.json", "packages/spec/authorable-surface/api.json", "packages/spec/declaration-map/api.json", "packages/spec/export-origins/api.json", "packages/spec/json-schema.manifest/api.json", "packages/spec/llms.txt", "packages/spec/src/api/app-bundle.test.ts", "packages/spec/src/api/app-bundle.zod.ts", "packages/spec/src/api/index.ts", "scripts/check-route-envelope.mjs" ], "deviations": [ "ETag = the /meta reads' shared validator (#28320: metaRepresentationCaching + sendMetaRepresentation, weak representationEtag of the served body) instead of folding per-dimension fingerprints; the route's own SHA-256 rule is gone", "meta.getAppBundle(appId, { ifNoneMatch }) answers a conditional {notModified, data?, etag} in getCached's spelling rather than bare data (seat note from the ui seat 2 consumer); private fetch gains opt-in admitNotModified", "metaItemAnswerSources gains an optional 5th type argument defaulting to req.params.type", "meta.getCached passes admitNotModified, so its 304 answers { notModified: true } instead of throwing (spec seat 1 asked for this; the class (a) finding is now fixed in this PR)" ], "out_of_scope_findings": [], "writes": { "relay": 7, "relay_ops": [ "pr_create #28287", "issue_patch #28287 body", "comment #27627 (first report)", "issue_patch #28287 body (getCached)", "comment #27627 (this report)", "issue_patch #28287 body (helper switch)", "comment #27627 (this report)" ], "mcp_calls": { "writes": 0, "reads": "issue_read, pull_request_read only" } }, "contract_review_subagent": false, "ready_flip": false, "automerge": false, "ablation_getcached": { "mutation": "drop { admitNotModified: true } from getCached's fetch", "red": "1/5", "restored_blob_equals_head": true }, "supersedes_report_comment": 6539142744, "delta_since_review": { "reviewed_head": "1e7a1b10", "record": 6539412174, "files": [ "packages/rest/src/meta-app-bundle-routes.ts", "packages/rest/src/meta-app-bundle-routes.test.ts", "packages/rest/src/rest-route-ledger.ts", "packages/rest/src/rest-server-docblock-position.test.ts", "packages/spec/src/api/app-bundle.zod.ts", "scripts/check-route-envelope.mjs", ".changeset/27627-app-metadata-bundle.md", "content/docs/references/api/app-bundle.mdx" ], "served_members_changed": false, "etag": "strong SHA-256 -> weak W/ representationEtag", "enableCache_false": "no validator, as the item reads" } }objectstack-fleet commentedon Oct 31, 2026
domain:ui#2 · os-tesla · session_01L9qibxgfM8p8t3fo6y9eFK
Claim amendment (same console-half claim, same branch
claude/project-thread-xoio4p, PR #28321) · 2026-10-31T10:02Z8441a01277, which clears the consumer-after-producer constraint.Part of #27627toFixes #27627(spec seat 1 agreed; the card stays open until feat(console): entering an app loads its metadata bundle once, and a record open reads no metadata #28321 merges).origin/main, switch to the conditionalgetAppBundle(appId, { ifNoneMatch }), and bind the spec typeAppMetadataBundleResponseSchema(name approved by the maintainer). Clause-② is re-measured on the built declarations after the type binding.objectstack-fleet commentedon Oct 31, 2026
domain:ui#2 · os-tesla · session_01L9qibzFu8iUogiZhxL9tAo
os-dev-report
Console half of #27627, final pass: draft #28321, head
07e67218, reported 2026-10-31T10:58Z. Producer #28287 is on main; the PR body now saysFixes #27627(claim amendment 6541997127). Supersedes report 6539052883.{ "card": 27627, "pr": 28321, "branch": "claude/project-thread-xoio4p", "head": "07e672183d2728b1ac2d51cae149ab00772f7ece", "draft": true, "closing": "Fixes #27627", "declarations": { "clause_2": "yes (widening)", "metadata_protocol": "none", "changeset_level": "patch" }, "clause_2_measure": { "on": "built ui/packages/data-objectstack/dist/index.d.ts", "new_public_members": ["ObjectStackAdapter.loadAppBundle(appId: string): Promise<void>"], "app_shell_new_declarations": 0, "dispatch_expected": "no" }, "gates": { "derived": 67, "run": 67, "exit_0": 67, "not_measured": 0, "unrun": 0, "reconcile_exit": 0, "extra": ["check:new-line-citations :: exit 0", "check:nul-bytes :: exit 0"] }, "type_check": { "data-objectstack": 0, "app-shell": 0, "app-shell-tests": 0 }, "tests": { "card_files": 3, "card_tests": 21, "wide_run_files": 419, "wide_run_tests": 3336, "failed": 0 }, "acceptance": { "warm_record_open": { "page_requests": 1, "metadata_requests": 0 }, "cold_record_open": { "page_requests": 1, "bundle_requests": 1, "by_name_metadata": 0, "waves": 1 } }, "ablations": [ { "off": "weak flag in the rebuilt validator", "red": 4 }, { "off": "no-ETag (no-store) branch", "red": 1 }, { "off": "bundle read in fetchObjectSchemaFresh", "red": 7 }, { "off": "AppContent loadAppBundle call", "red": 2 }, { "off": "write-door staleness", "red": 1 } ], "line_budget": { "limit": 3000, "used": 955, "additions": 923, "deletions": 32 }, "files_changed": 12, "deviations": [ "Clause-② measured yes (widening), dispatch expected no: loadAppBundle is a new public member of the exported adapter", "withheld vs outside: the bundle names nothing withheld, so an absent name keeps its by-name read (seat and spec seat 1 agreed)", "no-store detected as a 200 with no ETag: the client does not expose Cache-Control", "live boot NOT MEASURED" ], "writes": { "relay": 6, "mcp_calls": 0 } }objectstack-fleet commentedon Oct 31, 2026
domain:ui#2 · os-tesla · session_01L9qibxgfM8p8t3fo6y9eFK
Claim amendment (same console-half claim, same branch
claude/project-thread-xoio4p, PR #28321 head07e67218) · 2026-10-31T10:59ZAppMetadataBundleResponse, replacing the claim'sno: the exported ObjectStack adapter of@object-ui/data-objectstackgains one public member,loadAppBundle(appId: string): Promise<void>; app-shell's declarations add nothing. The PR owes a contract review atTIER_DEFAULT; it carriesneeds:contract-review.Fixes #27627(amendment 6541997127).relay: 6reads 5).objectstack-fleet commentedon Oct 31, 2026
domain:ui#2 · os-tesla · session_01L9qibxgfM8p8t3fo6y9eFK
Landed — console half (PR 3, last part) · 2026-10-31T14:46Z
07e67218(PASS 6542690057, ACCEPT 6542699351), merge commita9f1452192; after producer #28287 (8441a01277)origin/maina9f1452192(git merge-base --is-ancestor)Delivered: entering an app loads its metadata bundle once (conditional on the weak
ETag); a warm record open reads no metadata, a cold one adds one bundle request in the page's first wave. Card closed byFixes;pm:dispatchedremoved. Not owed before landing, recorded per the contract review's boundary flag: one live open on a cloud box when a seat next has one.objectstack-fleet commentedon Oct 31, 2026
domain:spec#1 · os-tesla · session_01L9qibwb6hBqszPTYJobitm
Ruled: keep the Server-Timing gate · 2026-10-31T15:13Z
The maintainer said 「同意」 at 2026-10-31T15:10Z. That was the reply to the consolidated decision list (
decisions/2026-10-31-director-rulings.md, item 8, recommendation 保持), which he accepted in full as recommended. It answers the seat's question of 2026-10-31T02:56Z.Server-Timingkeeps being sent only whenOS_SERVER_TIMING=trueis set, or when an admin caller sendsX-OS-Debug-Timing. It is not opened to every caller. That is the behaviour PR #28320 shipped, so nothing more is owed on this card.