Skip to content

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

Closed

Description

@objectstack-fleet

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

  1. 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 a query body) 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.
  2. An app-scoped metadata bundle: GET /api/v1/meta/app/<appId>/bundle returns 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 sends If-None-Match after. Today's per-object GET /meta/object/<name> stays for Studio and for objects outside the bundle.
  3. 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=1 count probes, the per-open child metadata loads and the separate field-access / lock / explain calls on open retire (startup posture: no dual path kept).
  4. 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 carry Cache-Control + ETag.
  5. 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

  1. 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=1 probes.
  2. The cloud reading re-run by the epic seat on huayan.objectos.app after landing: record open under 1 s warm, list route under 3 s cold, with Server-Timing in the PR body.
  3. The epic seat verifies in the console preview before ACCEPT (maintainer: 「车队开发完后你审核效果」).

Activity

  1. objectstack-fleet commented on Oct 29, 2026

    @objectstack-fleet
    ContributorAuthor

    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 for huayan.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 (REST Cache-Control + ETag + Server-Timing) is what that card's edge rule and timing split consume; the two land independently.

  2. objectstack-fleet commented on Oct 29, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:spec#3 · os-support-ai · session_01WGufzgbJhFoXYsLSe5WSPP

    Claim: PM loop round 3 · 2026-10-29T15:31Z
    Session: session_01WGufzgbJhFoXYsLSe5WSPP
    Account: os-support-ai
    Branch: claude/project-thread-2m7jqd (card thread; the platform assigns the thread's branch and it can push only that one, written as measured instead of claude/issue-27627-<slug>)
    Worktree: objectstack-27627
    Domain: domain:spec
    Seat: domain:spec#3
    Ruling-ref: the maintainer's ruling on epic #26676 quoted in the card body (「立…B(接缝卡:记录页一次取齐 + 元数据打包)两张卡,p1」); two PRs from this branch, the first Part of #27627
    File surface: producer: packages/rest/src/**, plugin-hono-server, packages/spec/contracts/** (the two shapes), packages/objectql only 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: high
    Clause-②: yes (widening)
    Metadata-protocol: added (the app bundle's shape), as measured by the dev
    Responsibility: an unclaimed p1 domain:spec card; seat 1 is off duty
    Thread-read: none
    Premise: to be measured first by the dev on origin/main 178b5238: one record open issues 23 (warm) to 45 (cold) requests in three serial stages
    Serial 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

  3. objectstack-fleet commented on Oct 29, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:spec#3 · os-support-ai · session_01WGufzgbJhFoXYsLSe5WSPP

    Claim amendment: one declaration and a surface extension (PR 1, #27713) · domain:spec seat 3 · session session_01WGufzgbJhFoXYsLSe5WSPP · 2026-10-29T20:18Z · same claim 6501011060, same branch claude/project-thread-2m7jqd

    • Metadata-protocol: added, as measured by the dev: the two new shapes enter packages/spec/authorable-surface/api.json, and check-changeset-no-major refuses none. Every moved package is minor.
    • File surface extends to every reader that retires its separate read in this PR. There is no dual path, so each reader takes its part of the payload: ui types, the components related-count store, plugin-detail (useRecordEditable, queueClaim, recordFieldAccess, RelatedList, index, package.json sideEffects), and app-shell useRecordApprovals plus a new recordPagePayload.ts. It also covers the dogfood fixture and test, the rest census tests and rest-server-registrar-files.ts, the scripts/check-route-envelope.mjs MODULES row, the generated spec artifacts and content/docs/references/api. The PR body gives the reason. Size 2980 lines (under the 3000 human-merge threshold), 0 governed paths.
  4. objectstack-fleet commented on Oct 30, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:spec#3 · os-support-ai · session_01WGufzgbJhFoXYsLSe5WSPP

    ACCEPT → PR #27713 comment 6524688486 (Tier H: approved by the maintainer, enqueued)

  5. objectstack-fleet commented on Oct 30, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:spec#3 · os-support-ai · session_01WGufzgbJhFoXYsLSe5WSPP

    Landed (PR 1 of 2) · domain:spec seat 3 · os-support-ai · 2026-10-30T21:07Z

    reading value
    PR #27713 seat ACCEPT (6524688486, re-issued 6530577529 and verified again 6532601590) on triage's PASS (6514375644, then 6526284371); Tier H, approved by the maintainer (os-zhuang); merged through the merge queue at 2026-10-30T21:06Z, head 6293d95ef, merge commit 0027c4a2b8
    origin/main contains the merge commit (git merge-base --is-ancestor)

    Delivered:

    • POST /api/v1/data/{object}/{id}/page answers 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.
    • The console record page (full page, split pane and drawer) asks only that request, and warms both neighbours in the v4 pane. A cold open went from 13 requests in two serial batches to 1 data request plus the object definition read.

    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:queue for the next seat. The deployment half is cloud#3378.

  6. 9 remaining items

  7. objectstack-fleet commented on Oct 31, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:spec#1 · os-tesla · session_01L9qibwb6hBqszPTYJobitm

    Claim correction · 2026-10-31T03:10Z · amends claim 6538108232 (branch claude/project-thread-hw8j7d), append-only

    File surface, amended by seat ruling: also packages/client (meta.getAppBundle(appId)), so the route ledger row takes disposition sdk. PR 1's data.recordPage is the precedent. PR: #28287 (draft, Part of #27627). Shape: packages/spec/src/api/app-bundle.zod.ts AppMetadataBundleResponseSchema.

  8. objectstack-fleet commented on Oct 31, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:spec#1 · os-tesla · session_01L9qibwb6hBqszPTYJobitm

    Claim correction · 2026-10-31T03:11Z · amends claim 6538102504 (branch claude/project-thread-dd5lh4), append-only

    File 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 in packages/types/src/index.ts. This is the one copy of the body-hash ETag / If-None-Match rule. rest, plugin-hono-server and cloud-connection all depend on types, and only rest keeps the /meta wrapper.
    • packages/cloud-connection/package.json gains @objectstack/observability (workspace:*), plus its lockfile lines. It is needed for the existing admin perf-disclosure gate on runtime/config.
  9. objectstack-fleet commented on Oct 31, 2026

    @objectstack-fleet
    ContributorAuthor

    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 }
    }
  10. objectstack-fleet commented on Oct 31, 2026

    @objectstack-fleet
    ContributorAuthor

    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

  11. objectstack-fleet commented on Oct 31, 2026

    @objectstack-fleet
    ContributorAuthor

    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
    }
  12. objectstack-fleet commented on Oct 31, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:spec#1 · os-tesla · session_01L9qibwb6hBqszPTYJobitm

    Claim correction · 2026-10-31T04:35Z · amends claim 6538102504 (branch claude/project-thread-dd5lh4, PR #28320), append-only

    File 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 the meta row, and notes that db and meta are sent as zero members.
    • content/docs/api/metadata-api.mdx: GET /meta and GET /meta/:type gain the ETag, private, no-cache and 304 answer.
  13. objectstack-fleet commented on Oct 31, 2026

    @objectstack-fleet
    ContributorAuthor

    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
    }
  14. objectstack-fleet commented on Oct 31, 2026

    @objectstack-fleet
    ContributorAuthor

    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"
     }
    }
  15. objectstack-fleet commented on Oct 31, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:ui#2 · os-tesla · session_01L9qibxgfM8p8t3fo6y9eFK

    Claim amendment (same console-half claim, same branch claude/project-thread-xoio4p, PR #28321) · 2026-10-31T10:02Z

  16. objectstack-fleet commented on Oct 31, 2026

    @objectstack-fleet
    ContributorAuthor

    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 says Fixes #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 }
    }
  17. objectstack-fleet commented on Oct 31, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:ui#2 · os-tesla · session_01L9qibxgfM8p8t3fo6y9eFK

    Claim amendment (same console-half claim, same branch claude/project-thread-xoio4p, PR #28321 head 07e67218) · 2026-10-31T10:59Z

    • Clause-②: yes (widening) — re-measured by the dev on the built declarations after binding AppMetadataBundleResponse, replacing the claim's no: the exported ObjectStack adapter of @object-ui/data-objectstack gains one public member, loadAppBundle(appId: string): Promise<void>; app-shell's declarations add nothing. The PR owes a contract review at TIER_DEFAULT; it carries needs:contract-review.
    • Metadata-protocol: none (unchanged); changeset stays patch. Closing keyword stays Fixes #27627 (amendment 6541997127).
    • Dev report 6542507828 supersedes 6539052883 (its relay: 6 reads 5).
  18. objectstack-fleet commented on Oct 31, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:ui#2 · os-tesla · session_01L9qibxgfM8p8t3fo6y9eFK

    Landed — console half (PR 3, last part) · 2026-10-31T14:46Z

    reading value
    PR #28321 merged through the merge queue at 2026-10-31T14:45:11Z, head 07e67218 (PASS 6542690057, ACCEPT 6542699351), merge commit a9f1452192; after producer #28287 (8441a01277)
    landing go the maintainer, 2026-10-31T14:22Z in the ui seat 2 thread: 「使用 pm-dispatch 技能审核和落地pr」
    origin/main contains a9f1452192 (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 by Fixes; pm:dispatched removed. 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.

  19. objectstack-fleet commented on Oct 31, 2026

    @objectstack-fleet
    ContributorAuthor

    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-Timing keeps being sent only when OS_SERVER_TIMING=true is set, or when an admin caller sends X-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.

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

Metadata

Metadata

Assignees

Labels

area:recordsBusiness objects, records, the views that show data, usable forms, searchdomain:specenhancementNew feature or requestpriority:p1High: required for production / M2

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions