You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
rest/i18n: GET /i18n/translations/:locale serves the whole locale bundle (288–361 KB raw, 80–88 KB compressed) on every console open with no ETag or Cache-Control, and carries Studio's metadataForms (46.8 KB) into the boot read #25785
Business reason. On staging, the translations call is the slowest leg of the console open's third wave: it took 1128 → 3091 ms in the ops seat's reading (https://github.com/objectstack-ai/cloud/issues/2914#issuecomment-6392341684). Every open re-downloads the full locale bundle, and nothing lets the browser revalidate it.
Reader who acts. A framework dev for the /i18n/translations route and the boot bundle's composition.
The CPU cost is small (12–14 ms). The cost is bytes and re-download on every open.
Composition (tenant):
objects 109.7 KB raw: every object, not the page's;
metadataForms 46.8 KB: Studio's metadata forms, which no console boot reads;
settings 17.2 KB;
dashboards 5.5 KB;
apps 4.9 KB.
On the control plane, cloud's own sys_environment and sys_package are 76.6 KB of the bundle.
Fix sketch
Serve an ETag with Cache-Control: private, no-cache, so warm opens answer 304.
Keep metadataForms out of the boot bundle and load it with Studio.
Optional: scope objects to what the current app needs. That is a bigger contract change; say so if it is taken.
Acceptance
A warm second open of the same locale gets 304 for /i18n/translations/<locale>.
The boot bundle no longer carries metadataForms.
Studio still renders its forms translated.
Expected saving: 80–88 KB per warm open, about 0.2–0.27 s on the ops seat's measured link (326–464 KB/s).
Dedupe
search_issues for 'i18n translations endpoint ETag cache whole locale bundle every console open metadataForms' returned 24 hits, all closed and all about missing keys or wrong leaves. None covers caching or composition.
p1: the platform half of objectstack-ai/cloud#2914 (p1). The translations call is the slowest leg of the open's third wave.
First step:ETag / Cache-Control on /i18n/translations/:locale. That is not a new contract, so it can go first. Splitting the bundle, if proposed, is a wire-shape change and goes to spec.
Claim: PM loop round 1 · card thread · 2026-10-26T03:38Z
Session: session_01HFAuCZPty5SsvseoPRgukQ (the card thread, mode:thread; the seat writes this claim for it: seat session session_01TFnDdepdwyDJeM2kJ4GtMy)
Account: os-elon-musk (the seat's linked user as GET /user answers it; the card's assignee)
Branch: claude/project-thread-icw4tr (platform-assigned to the card thread; a thread can push only its assigned branch, a measured platform exception to claude/issue-<n>-<slug>)
Worktree: objectstack-issue-25785
Domain: domain:server
Seat: domain:server#2 (seat post #20966; 由 os-elon-musk 账户的项目负责)
File surface: the GET /i18n/translations/:locale serving path, packages/runtime/src/domains/i18n.ts (the translations branch, read on origin/maincb0a2fcf) and, if the headers belong at the HTTP layer, the dispatcher's response path that carries them; their tests; one changeset. Scope = the triage comment's first step: ETag + Cache-Control: private, no-cache + 304 on a matching If-None-Match, as Part of #25785. ⛔ Not this claim: moving metadataForms out of the boot bundle (a wire-shape change, per triage 6397341079 it goes to domain:spec); report it as an out-of-scope finding with its carrier. The expected landing point is the file above; if measurement shows the producer elsewhere, fix it there and say so in the report and PR body. Stop on a breach and explain it.
Container & model: M, mode:thread, model: default tier (dispatch-gates --tier on this surface: "no path-derived mandate"), effort: xhigh (p1)
Clause-②: no
Metadata-protocol: none
Basis for the Clause-② line: no accept set narrows or widens; an existing route answers the same body, plus a validator header and a conditional 304. Re-read against AGENTS.md on the measured diff; if the route's response is declared in a published schema and the diff touches it, stop and report (that is spec-lane work and owes a contract-tier review).
Responsibility: the runtime i18n domain (packages/runtime/src/domains/i18n.ts) produces the cost | no platform path covers it: no ETag or Cache-Control is set anywhere on the route | every console open on every hosted tenant reaches it today (cloud#2914 measurement, per the card)
Thread-read: 6397341079
Premise: holds (card measured on framework pin 888d6865; origin/maincb0a2fcfdomains/i18n.ts :137–:147 still answers getTranslations(locale) with no caching header set in that branch; the thread re-measures)
Writes: PR only through the relay pr_create; comments, labels and bodies only through the relay write tools (post-stamped.mjs, label-write.mjs, fleet-write/dispatch.mjs). ⛔ No GitHub MCP write tool. Report both counts (writes, mcp_calls).
Serial constraints cleared: none. #25783's card thread works on /meta (packages/rest, packages/metadata-protocol), not on the i18n domain; no open PR names packages/runtime/src/domains/i18n.ts.
Resume-from: none
File surface adds one row in scripts/check-route-envelope.mjs: DISPATCHER_DOMAINS['i18n.ts'] goes from handBuilt: 0 to 2, with a REQUIRED note. This is the gate's own kind 1 ("Enveloped, but the helper cannot express the response"), the classification meta.ts took for Vary: Accept-Language. deps.success takes no headers, so the 200 carrying ETag / Cache-Control is hand-built around the declared envelope. A 304 carries no body by HTTP rule, so it has no envelope to emit.
The note names both. ⛔ No other row moves, and the gate's logic is unchanged. ⛔ No new DomainHandlerDeps member: growing the deps interface is a design decision outside this card. The PR body names this row as a declared surface addition. Every other line of the claim stands.
os-dev-report
{
"issue": 25785,
"status": "done",
"branch": "claude/project-thread-icw4tr",
"pr": "#25956",
"session": "session_01HFAuCZPty5SsvseoPRgukQ",
"premise_still_valid": true,
"summary": "Part of #25785, per claim 6407675488. GET /i18n/translations/:locale (path and ?locale= spellings, direct and zh->zh-CN fallback exits) now answers 200 with ETag W/"base64url sha256 of the exact served envelope, computed every read" and Cache-Control: private, no-cache, and answers a matching If-None-Match (comma list, weak comparison, *) with a body-less 304 carrying both headers. The anonymous floor stays first (401, no headers). Only packages/runtime/src/domains/i18n.ts changes in source; no transport, spec or response-schema change. One declared surface addition per amendment 6408228005: scripts/check-route-envelope.mjs i18n.ts handBuilt 0->2 (kind 1). Measured on examples/app-crm: zh-CN 200 220,391 B -> 304 0 B; en 213,264 B -> 304 0 B; recomputed ETag equals the header. #25785 stays open for its metadataForms half (domain:spec).",
"tests": "New: runtime domains/i18n-translations-etag.test.ts 21 tests, runtime i18n-translations-etag.hono.integration.test.ts 4 tests (real socket, LiteKernel + HonoServerPlugin + createDispatcherPlugin: 304 has a 0-byte body), adapters/hono hono-not-modified-response.test.ts 3 tests (toResponse characterization pins). Ablation at a373155: i18n.ts replaced on disk by origin/main cb0a2fc blob -> 23 of 25 runtime tests red (2 green are the 400/401 controls); restored blob bb41d094 == HEAD, diff clean. Suites at 0b2e659: pnpm --filter @objectstack/runtime test under the verify lock VERDICT command-exit 0, 446 files, 7125 passed, 19 skipped; pnpm --filter @objectstack/hono test 13 files, 228 passed; typecheck both packages exit 0 (runtime re-run green at 7b2a1a2 after the check:test-typecheck fix). Real composition: pnpm dev:crm -- --fresh after full pnpm build (VERDICT 0), 25 cold reads one ETag, 25 conditional reads all 304.",
"gates": "Local: node scripts/pm/dispatch-gates.mjs --commands at 773c3f3 derives 87 families on 6 paths, all 87 exit 0 (codes captured before any pipe); --ran reconciliation 87 derived, 87 run, 0 NOT-MEASURED, 0 UNRUN, exit 0. check:route-envelope was red at 7b2a1a2 (i18n.ts handBuilt found 2, declared 0) until the amendment row; check-plugin-teardown-shape --self-test and check:dual-build-cjs-loads exited 3 until the fixture commit fetch and a full build, then 0. eslint --no-inline-config on the 5 code files exit 0. check-governed-merges --branch HEAD: NOT governed. CI on PR head 773c3f3: 46 check runs, 0 failed: Build Core success; Test Core 1/8..8/8 success and Test Core success; TypeScript Type Check success (workspace, source gates, consumer gates, debt ledger all success); Lint & Repo Gates success (ESLint, repo & tooling gates, docs & code guards, CI release & engine gates, PM dispatch-gates, three scoped lanes all success); Dogfood Regression Gate success; Check Changeset success; Governed Surface Queue Guard success; Part-of PR must not also close its card success; The card this PR closes must claim this branch success; No other open PR may claim the same issue success; No other open PR may claim the same single-writer path success; Check PR Size, Check Documentation Links, Flag docs affected by code changes, Auto Label success; UI, docs build, temporal, dogfood shards, opt-in smoke lanes skipped by the path filter. mergeable_state clean.",
"dogfood_battery": "n/a — no ! in the PR title and no (narrowing) arm",
"mcp_calls": "8 — all reads: issue_read x4, search_pull_requests x1, pull_request_read x3 (get_check_runs x2, get x1); no MCP write",
"api_writes": "3 relay actions in 2 strokes — POST /repos/objectstack-ai/objectstack/pulls (pr_create, assignee os-elon-musk, run 40274520812, read back identical 9764 B); POST /repos/objectstack-ai/objectstack/pulls/25956/requested_reviewers (pr_request_reviewers os-elon-musk, the requester); POST /repos//issues/25785/comments (this report). Plus git push of the branch (not REST).",
"open_questions": [],
"out_of_scope_findings": [
"carrier: domain:spec (#25785 stays open) — the card's second half, keeping metadataForms (46.8 KB raw on the measured tenant) out of the boot bundle and the optional scoping of objects to the current app; both change the GET /i18n/translations/:locale wire shape · noted, not filed",
"carrier: none — /i18n/locales and /i18n/labels/:object/:locale carry no validator; not measured on the open path and not asked by the card · noted in PR Acceptance notes, not filed",
"carrier: none — docs-drift bot comment 6408979046 lists content/docs/permissions/system-context.mdx row 52 via handleI18nRequest; re-read: it states the anonymous-deny seam, which still holds (401 first, pinned by tests), so no doc change · noted, not filed"
]
}
ACCEPT → PR #25956 comment 6409329004 · domain:server#2 · 2026-10-26T05:59Z · landing through the relay (standing landing word, seat thread 2026-10-26 05:53Z); the card stays open for the metadataForms half
Release: domain:server seat 2 · os-elon-musk · session session_01TFnDdepdwyDJeM2kJ4GtMy · 2026-10-26T07:03Z · cause: the ETag half landed (Part of #25785), and the seat signs off · destination: pm:queue, unassigned, for the metadataForms half
merged: true, merge commit 69fa23d60, merged 2026-10-26T06:42Z through the merge queue
origin/main
69fa23d60 is an ancestor of origin/main
queue branch
the head branch is deleted; no queue head remains
Landed:GET /i18n/translations/:locale (both spellings) carries a weak content-hash ETag and Cache-Control: private, no-cache, and a matching If-None-Match gets a body-less 304. On app-crm zh-CN the dev measured 220,391 B → 304 with 0 B.
Remains: the card's second ask, keeping Studio's metadataForms (≈46.8 KB) out of the boot read. Its carrier is domain:spec, because the bundle shape is a published contract. The next seat should route or split it with triage.
State:pm:dispatched → pm:queue, assignee cleared, in this act. The card thread is closed.
Claim: PM loop round 1 · 2026-10-26T12:13Z
Session: session_01HbmCEPMBmMLU3VZCEzfec7 (seat 4; the card thread is session_01Vy85beHdawtEtqNscYBy7V, which writes no claim of its own)
Account: zhuangjianguo
Branch: claude/project-thread-nvoyre (the platform assigns the card thread's branch, and the thread can push only that branch. Written as measured, instead of claude/issue-25785-<slug>.)
Worktree: objectstack-issue-25785
Domain: domain:spec
Seat: domain:spec#4 (seat post #18917; 由 zhuangjianguo 账户的项目负责)
File surface: the translation-bundle composition for GET /i18n/translations/:locale (packages/spec/src/system/i18n-resolver.ts and the runtime door packages/runtime/src/domains/i18n.ts where the boot bundle is assembled), Studio's metadataForms readers (ui/packages/app-shell/src/views/metadata-admin/*, ui/packages/i18n/src/utils/spec-translations.ts), the packages/rest/src/rest-server.ts reader if it is affected, tests, and one changeset. Out of scope: scoping objects to the current app. If measurement puts the producer elsewhere, fix it there and say so. Stop on a breach and explain it in the report.
Container & model: M, mode:thread, model: TIER_DEFAULT — dispatch-gates --tier: no path-derived mandate, effort: xhigh (p1)
Clause-②: no
Metadata-protocol: none
Responsibility: the runtime/spec translation-bundle composition produces the cost | no platform path covers it: the boot read takes the whole bundle, metadataForms included | every console open on every tenant reaches it today (cloud#2914 measurement)
Thread-read: 6412175443
Premise: holds (unmeasured on main: metadataForms is still a bundle module at 0a694821 (i18n-resolver.ts:4246, conversions/registry.ts:8467); the thread re-measures the composition before changing it)
Ruling-ref: none from the maintainer; triage 6412175443 routed the whole card to domain:spec
Serial constraints cleared: #25956 (ETag) and #25983 (BCP-47 locale tags) landed on this route and the translation schema today; no in-flight claim names these files.
Resume-from: none
{
"issue": 25785,
"status": "done",
"branch": "claude/project-thread-nvoyre",
"head": "8b2ad27c24209acc9cddb61f4792b0b7e70a91e5",
"pr": "https://github.com/objectstack-ai/objectstack/pull/26159",
"session": "session_01Vy85beHdawtEtqNscYBy7V",
"premise_still_valid": true,
"summary": "GET /i18n/translations/:locale now serves every translation group except the ones the server resolves itself. The spec names them in SERVER_RESOLVED_TRANSLATION_GROUPS (today only metadataForms) and GetTranslationsResponseSchema.translations is the new closed ServedTranslationDataSchema, the platform face minus those groups. The runtime door serves a copy and never edits the i18n service's tree. How Studio loads metadataForms, the choice the dispatch left to the dev: it does not load it in the browser at all. The /meta and /meta/types handler (translateMetaTypesResponse in @objectstack/rest) already resolves metadataForms.TYPE in process from the same service and serves each authoring form translated, and the liveness ledger names that handler as the group's only reader. No new endpoint, route or key, so no needs_decision. Measured live on examples/app-crm zh-CN: 221,007 B raw / 68,580 gzip down to 145,863 / 45,107, the group (75,127 B) absent, a warm reopen still 304 with 0 B, and /meta/types serving the same 31 entries with identical translated labels before and after. The ETag half of the card landed earlier (not this PR) and was left untouched.",
"tests": "Under scripts/pm/os-verify-lock.sh, --maxWorkers=2. @objectstack/runtime full suite at 8b2ad27c: 'Test Files 455 passed (455)', 'Tests 7415 passed | 19 skipped (7434)', VERDICT command-exit 0. @objectstack/spec full suite: 'Tests 1 failed | 21929 passed | 1 todo', the one red being scripts/dropped-refinements.test.ts 'header totals match its body'; the totals were recounted in 8b2ad27c and that file then ran 27/27 (only that test reads them, git grep). Focused: runtime 4 files / 41 tests, spec 5 files / 434 tests, all passed. Type-check of spec, runtime and client: VERDICT command-exit 0. ui/apps/console/src/loadLanguage.test.tsx, which walks GetTranslationsResponseSchema.shape.translations through the workspace link and so reads this narrowing: 'Tests 7 passed (7)'. New pins: packages/runtime/src/domains/i18n-translations-served-groups.test.ts (10 tests: both spellings and the fallback exit omit the group and keep the rest byte-identical; the body parses the closed response schema with a control that the same body WITH the group is refused; the service's tree is not edited and a RestServer /api/v1/meta over the same service after a boot read still serves 仪表板 / 布局 / 列数; the ETag hashes the served body, If-None-Match gives 304, a metadataForms-only change keeps the validator and a messages change moves it) and packages/spec/src/system/served-translation-data.test.ts (served face == platform face minus the constant both ways with a positive control; the response schema serves that face; each constant group stays declared on both bundle faces; a document carrying it is refused with unrecognized_keys naming it). Ablation, one-off, mutated on disk then restored, both quoted in the PR body: (1) filter removed (blob 3154a44d to a28c8f4a) ⇒ 6 of 10 failed, restore blob == HEAD; (2) in-place delete of the group from the service's tree (blob 3154a44d to 5e38e852) ⇒ exactly the 2 Studio pins failed, /meta serving 'Dashboard' where '仪表板' was expected, the other 8 passing, restore blob == HEAD with git diff HEAD empty.",
"gates": "Local subset: all 114 derived commands, each exit code captured before any pipe into a ran.list, then reconciled — 'dispatch-gates --ran: 114 derived famil(ies) accounted for — 114 run, 0 NOT-MEASURED (a DERIVED zero — all 114 recorded an exit code and none of them is 3)'. Every one exited 0, among them check:generated, check:api-surface, check:authorable-surface, check:docs, check:liveness, check:strictness-ledger, check:spec-parsed-alias, check:exported-any, check:dual-build-cjs-loads, check:nul-bytes and check:type-check-debt under the verify lock ('26 raw tsc error(s) total, none above its recorded number'). The list derived at the final head 8b2ad27c is byte-identical to the list run (diffed). The sweep began at 12:55Z, before 8b2ad27c (13:02Z), so the 10 commands that finished before that commit plus check:query-options-erasure, which overlapped the 20-second window of ablation 1, were rerun at 8b2ad27c: all exit 0. Local-only families, read-only per os-dev.md: check:dev-prereqs exit 0 and check:skill-frame-freshness exit 0. CI's own repo-wide scans and the PR's check-runs are CI's; this report does not claim them — read them on PR #26159 at head 8b2ad27c.",
"dogfood_battery": "n/a — no `!` in the PR title and no (narrowing) arm",
"line_budget": "648 changed lines (+625 / -23) over 18 files, under dispatch-gates' 3000-line human-merge threshold. Hand-written source +93/-6 (translation.zod.ts +52, i18n.ts +33/-4, protocol.zod.ts +8/-2); tests +321/-3 (two new files 237 and 71, the alias pin +13/-3); docs and changeset +24/-3; generated or recounted artefacts +187/-11.",
"files_changed": [
".changeset/25785-served-translations-without-metadata-forms.md",
"content/docs/protocol/kernel/i18n-standard.mdx",
"content/docs/references/api/protocol.mdx (generated)",
"content/docs/references/index.mdx (generated)",
"content/docs/references/system/translation.mdx (generated)",
"docs/audits/2026-07-unknown-key-strictness-ledger.counts/system.md (generated)",
"packages/runtime/src/domains/i18n-translations-served-groups.test.ts (new)",
"packages/runtime/src/domains/i18n.ts",
"packages/spec/api-surface/system.json (generated)",
"packages/spec/authorable-surface/system.json (generated)",
"packages/spec/declaration-map/system.json (generated)",
"packages/spec/dropped-refinements.baseline.json",
"packages/spec/export-origins/system.json (generated)",
"packages/spec/json-schema.manifest/system.json (generated)",
"packages/spec/src/api/protocol.zod.ts",
"packages/spec/src/system/served-translation-data.test.ts (new)",
"packages/spec/src/system/translation.zod.ts",
"packages/spec/src/type-alias-convention.pin.test.ts"
],
"deviations": [
"Two files outside the claim's named file surface: packages/spec/src/system/translation.zod.ts and packages/spec/src/api/protocol.zod.ts. Contract-first — the served shape is a declaration, so it was declared in the spec rather than kept implicit in the runtime; the PR body names them. Non-test packages/spec/src moved, so a CONTRACT_REVIEW_TIER review is owed before landing.",
"The card's fix sketch says 'load it with Studio'. Studio needs no browser load: /meta/types already serves its forms translated and nothing in the browser read the group from the bundle. The acceptance item (Studio still renders its forms translated) is pinned by a test over a real RestServer.",
"The first full spec suite was spelled `pnpm --filter @objectstack/spec test -- --maxWorkers=2`; the `--` made vitest drop maxWorkers, so it ran at default workers. The whole suite still ran.",
"That run's one red was the dropped-refinements header totals, fixed in 8b2ad27c; the full spec suite was not rerun after that commit, only scripts/dropped-refinements.test.ts (27/27). That commit changes nothing else.",
"dispatch-gates warned STALE TREE (behind origin/main, stale scripts/sdui-manifest.record.json). No file in this diff is touched by main's newer commits and `git merge-tree` reports no conflict, so main was not merged in.",
"No labels sent with pr_create: the dispatch named none, and the diff publishes (changeset present), so skip-changeset does not apply. The platform's size/l landed on its own."
],
"mcp_calls": "8 — all reads, no write tool: issue_read get (#25785) x2, issue_read get_comments (#25785) x3, pull_request_read get x3 (#26159 twice, reading the stored body back, and #26011 once as a body-shape precedent).",
"api_writes": "3 — all through the fleet relay (POST /repos/objectstack-ai/objectstack/dispatches, 204, run read to conclusion): (1) pr_create, POST /repos/objectstack-ai/objectstack/pulls, read back '11390 byte(s) sent, 11390 stored — identical', assignee zhuangjianguo as the pull lists them; (2) pr_request_reviewers, POST /repos/objectstack-ai/objectstack/pulls/26159/requested_reviewers, zhuangjianguo; (3) this comment, POST /repos/objectstack-ai/objectstack/issues/25785/comments. git push is not a REST write.",
"open_questions": [],
"out_of_scope_findings": [
"class: b · reach: GET /i18n/translations/:locale still serves every object's translations, not the current app's — zh-CN `objects` is 111,504 B of the 145,863 B this PR leaves · evidence: the card's own optional item, which it calls a bigger contract change, plus the per-group byte reading in PR #26159 · dedupe words: i18n translations objects scope current app boot bundle · carrier: seat domain:spec#4 to file or drop · noted, not filed",
"class: a · reach: the locale-fallback exit serves `requestedLocale`, which GetTranslationsResponseSchema does not declare; the outer z.object is not strict, so it passes unnoticed · evidence: packages/runtime/src/domains/i18n.ts fallback exit versus GetTranslationsResponseSchema in packages/spec/src/api/protocol.zod.ts; pre-existing and unchanged by this PR · dedupe words: requestedLocale GetTranslationsResponseSchema undeclared fallback locale · carrier: seat domain:spec#4 to file or drop · noted, not filed",
"class: c · reach: two ui docblocks now describe the old composition — SPEC_TRANSLATION_GROUPS in ui/packages/i18n/src/utils/spec-translations.ts calls its list 'the keys of the translations shape' (metadataForms is no longer one, and the list is a superset detector, so no behaviour changes), and ui/packages/app-shell/src/views/metadata-admin/metadata-form-i18n.ts expects 'the environment's own translation bundle' to arrive one day as a higher-precedence source for Studio's form labels, which would now be /meta/types · evidence: both files read at 8b2ad27c; loadLanguage.test.tsx passes 7/7 against the narrowed face · dedupe words: SPEC_TRANSLATION_GROUPS metadata-form-i18n docblock served groups stale · carrier: seat domain:spec#4 to file or drop · noted, not filed"
]
}
Seat review of PR #26159 at 8b2ad27c amends claim 6415714537:
Clause-②: yes (narrowing)
Metadata-protocol: none
Why: GetTranslationsResponseSchema.translations moves from the platform face to the closed ServedTranslationDataSchema. A response body carrying metadataForms, which the published schema accepted, now fails it, and the exported TypeScript type loses the member; GET /i18n/translations/:locale stops serving a group it served. What an author writes is unchanged, so the kind is none and the level stays patch, with the BREAKING banner and one ADR-0087 disposition (AGENTS.md Post-Task Checklist step 3).
File surface, widened: packages/spec/src/system/translation.zod.ts and packages/spec/src/api/protocol.zod.ts (the dev's contract-first move, named in the PR body), plus requestedLocale declared on GetTranslationsResponseSchema — the runtime's fallback exit serves it undeclared, same schema, same defect class, mechanical — and the two ui docblocks this PR made false (ui/packages/i18n/src/utils/spec-translations.tsSPEC_TRANSLATION_GROUPS, ui/packages/app-shell/src/views/metadata-admin/metadata-form-i18n.ts).
Dropped, not filed: scoping objects to the current app (the card's optional item). After this PR the zh-CN bundle is 45,107 B gzip and a warm reopen is 304, 0 B; per-app scoping is a contract change with no measured user-visible cost left to pay for it.
A CONTRACT_REVIEW_TIER contract review is owed before landing.
{
"issue": 25785,
"status": "done",
"branch": "claude/project-thread-nvoyre",
"head": "4f5d2f0a417d404c7d44bc256585d25071d7c7e4",
"pr": "https://github.com/objectstack-ai/objectstack/pull/26159",
"session": "session_01Vy85beHdawtEtqNscYBy7V",
"premise_still_valid": true,
"summary": "Round 2, answering the seat's review of 8b2ad27c (claim amendment 6418168409). Four items, all landed: (1) the declarations are corrected to Clause-②: yes (narrowing) / Metadata-protocol: none, and the changeset carries the BREAKING banner, the remedy (read metadataForms from GET /meta/types) and exactly one ADR-0087 disposition, not-required (no-migration-prescription), which check-adr-0087-registration accepts by name; (2) requestedLocale is declared on GetTranslationsResponseSchema, optional, with pins on both sides — the door has served it on the locale-fallback exit since that fallback existed, undeclared; (3) the two ui docblocks this PR had made false are repaired; (4) finding 1 (scoping objects) is dropped by the seat, so nothing was built for it. The behaviour of round 1 is unchanged: the served document still leaves out SERVER_RESOLVED_TRANSLATION_GROUPS, the runtime still serves a copy, /meta/types still serves Studio's forms translated, and a warm reopen is still 304.",
"tests": "All at the final head 4f5d2f0a, under scripts/pm/os-verify-lock.sh, each exit code captured before any pipe. @objectstack/spec full suite (`exec vitest run --maxWorkers=2`): 'Test Files 803 passed (803)', 'Tests 23204 passed | 1 todo (23205)', VERDICT command-exit 0 — the ledger red of round 1 is gone and the count rose with main's 40 commits. runtime i18n suite (the six i18n test files of this door: served-groups, etag, anonymous-deny, the success-envelope conformance, fallback-locale, supported-locales): 'Test Files 6 passed (6)', 'Tests 103 passed (103)', VERDICT 0. Type-check of @objectstack/spec and @objectstack/runtime: VERDICT 0. ui (`cd ui && pnpm exec vitest run apps/console/src/loadLanguage.test.tsx packages/i18n/src/__tests__/spec-translations.test.ts`): 'Test Files 2 passed (2)', 'Tests 22 passed (22)' — the console loader walks GetTranslationsResponseSchema.shape.translations through the workspace link, so it reads this narrowing, and the i18n transform's own suite covers the docblock's package. New pins this round: the spec test fixes the response shape to locale / requestedLocale / translations, parses a real fallback body, keeps the field optional and refuses a non-string; the runtime test parses the fallback body against the schema and asserts the key is declared. Round 1's evidence stands at this head by the suites above: the two ablations (filter removed = 6 of 10 red; in-place delete = exactly the 2 Studio pins red, /meta serving 'Dashboard' for '仪表板'), both restored to HEAD with git diff HEAD empty, and the live app-crm measurement (zh-CN 221,007 B raw / 68,580 gzip to 145,863 / 45,107; en 213,880 / 58,666 to 138,502 / 37,576; the group absent; a warm reopen 304 with 0 B; /meta/types serving 31 entries with identical translated labels). Not re-measured live after the merge: the served composition is byte-identical in this round (requestedLocale was already served), so the readings above are the readings of this behaviour.",
"gates": "Local subset at the final head 4f5d2f0a: the derived list is now 125 commands (main's 40 commits add nine families, and the merge removed the STALE TREE warning). All 125 ran, each exit code captured before any pipe, every one exit 0, then reconciled: 'dispatch-gates --ran: 125 derived famil(ies) accounted for — 125 run, 0 NOT-MEASURED (a DERIVED zero — all 125 recorded an exit code and none of them is 3)'. Named receipts: check-adr-0087-registration --base origin/main exit 0 ('1 declared-breaking changeset(s), each carrying an ADR-0087 disposition … not-required (no-migration-prescription)'), check-sdui-manifest exit 0, check:generated, check:api-surface, check:authorable-surface, check:docs, check:liveness, check:strictness-ledger, check:spec-parsed-alias, check:exported-any, check:nul-bytes, the five docs families, and check:type-check-debt under the verify lock ('1 ledger entr(ies) re-measured in 246.8s, 26 raw tsc error(s) total, none above its recorded number'). Local-only families, read-only per os-dev.md: check:dev-prereqs exit 0, check:skill-frame-freshness exit 0 ('the frame itself is unchanged'). CI's repo-wide scans and the PR's check-runs are CI's; this report does not claim them — read them on PR #26159 at 4f5d2f0a.",
"dogfood_battery": "4f5d2f0a · closure built first (pnpm --filter '@objectstack/dogfood^...' build, VERDICT command-exit 0), then the battery as CI spells it: pnpm --filter @objectstack/dogfood test under the verify lock, no OS_TEST_SHARD and no path argument. VERDICT command-exit 0 · Test Files 296 passed | 3 skipped (299) · Tests 2523 passed | 18 skipped (2541) · no failure to name. Held the lock 26m47s.",
"line_budget": "716 changed lines (+685 / -31) over 22 files against the new merge base 601c7738, under dispatch-gates' 3000-line human-merge threshold; main's 40 merged commits are not this diff. Round 2 added +68 / -8 of that: protocol.zod.ts +10 (the declaration and its docblock), the two test files +12 and +4, the changeset +9/-3, the two ui docblocks +25/-7, one generated reference row, one authorable-surface key, and one re-recorded registry digest line.",
"files_changed": [
".changeset/25785-served-translations-without-metadata-forms.md",
"content/docs/protocol/kernel/i18n-standard.mdx",
"content/docs/references/api/protocol.mdx (generated)",
"content/docs/references/index.mdx (generated)",
"content/docs/references/system/translation.mdx (generated)",
"docs/audits/2026-07-unknown-key-strictness-ledger.counts/system.md (generated)",
"packages/runtime/src/domains/i18n-translations-served-groups.test.ts (new)",
"packages/runtime/src/domains/i18n.ts",
"packages/spec/api-surface/system.json (generated)",
"packages/spec/authorable-surface/api.json (generated)",
"packages/spec/authorable-surface/system.json (generated)",
"packages/spec/declaration-map/system.json (generated)",
"packages/spec/dropped-refinements.baseline.json",
"packages/spec/export-origins/system.json (generated)",
"packages/spec/json-schema.manifest/system.json (generated)",
"packages/spec/src/api/protocol.zod.ts",
"packages/spec/src/system/served-translation-data.test.ts (new)",
"packages/spec/src/system/translation.zod.ts",
"packages/spec/src/type-alias-convention.pin.test.ts",
"scripts/sdui-manifest.sources/i18n.json (re-recorded)",
"ui/packages/app-shell/src/views/metadata-admin/metadata-form-i18n.ts",
"ui/packages/i18n/src/utils/spec-translations.ts"
],
"deviations": [
"PR BODY AND TITLE ARE OWED, AND ARE THE SEAT'S WRITE: a dev writes a PR body once, at pr_create, and never PATCHes it (os-dev.md), so the body still carries `Clause-②: no` and the title still lacks `!`. The exact text to write is named below under `pr_text_for_the_seat`. The `Clause-②` declaration of record for the contract review is the changeset's, which reads `yes (narrowing)`.",
"`origin/main` was merged in (merge 81dc21e7, 40 commits), which the rules allow on a conflict: editing a ui registry source moves that package's digest, and main had just re-shaped those records one-per-package (#26120), so a re-record on the stale layout would have conflicted in the queue. No file in this diff overlaps main's range (comm over both name lists is empty), and the digest was re-recorded after the merge commit, never in a merging tree.",
"The remedy in the changeset is written as prose, not as a literal `FROM → TO` label block: that label is branch 1 of the migration-prescription detector, and with it the only claimable ADR-0087 category (`no-migration-prescription`) is refused while the other five are closed on facts. The mapping it would have carried is stated in words in the same changeset. This is the one place where the seat's wording and the gate disagree, and the gate's reading is the one that can be re-run.",
"Two files remain outside the claim's original file surface (packages/spec/src/system/translation.zod.ts, packages/spec/src/api/protocol.zod.ts); the amended claim widens the surface to include them, plus the requestedLocale declaration and the two ui docblocks, so this round is inside it.",
"The full ui app-shell suite was not run: the app-shell edit is a docblock inside a comment block, no behaviour, and that suite is about 71 minutes for 1722 files. Declared, not measured; CI runs it.",
"The first full spec suite of round 1 was spelled `pnpm --filter @objectstack/spec test -- --maxWorkers=2`; the `--` made vitest drop maxWorkers. Round 2's run spells it `exec vitest run --maxWorkers=2`."
],
"mcp_calls": "11 — all reads, no write tool: issue_read get (#25785) x2, issue_read get_comments (#25785) x5 (three in round 1, two reading the seat's amendment), pull_request_read get x4 (#26159 twice, #26011 once as a body-shape precedent, and one more read of #26159 before this report).",
"api_writes": "5 — all through the fleet relay (POST /repos/objectstack-ai/objectstack/dispatches, 204, each run read to its conclusion): round 1's pr_create (POST /pulls, read back 11390 of 11390 bytes identical, assignee zhuangjianguo), pr_request_reviewers (POST /pulls/26159/requested_reviewers), the first os-dev-report (POST /issues/25785/comments, comment 6418116291, 10544 of 10544 bytes identical); round 2's Round-2 comment on the PR (POST /issues/26159/comments) and this report (POST /issues/25785/comments). git push is not a REST write; three pushes landed 2f4dfc02, the main merge and 4f5d2f0a.",
"open_questions": [],
"out_of_scope_findings": [
"class: a · reach: closed by this round — `requestedLocale` is now declared on GetTranslationsResponseSchema, so the finding round 1 carried is fixed here rather than filed · evidence: packages/spec/src/api/protocol.zod.ts at this head, pinned in packages/spec/src/system/served-translation-data.test.ts and packages/runtime/src/domains/i18n-translations-served-groups.test.ts · carrier: none needed",
"class: c · reach: closed by this round — both ui docblocks are repaired here · evidence: ui/packages/i18n/src/utils/spec-translations.ts and ui/packages/app-shell/src/views/metadata-admin/metadata-form-i18n.ts at this head · carrier: none needed",
"class: b · reach: the seat dropped scoping `objects` to the current app (its reason: 45,107 B gzip and a 304 warm reopen leave no measured user-visible cost to pay for a contract change) · evidence: claim amendment 6418168409 · carrier: dropped by the seat, not filed"
],
"pr_text_for_the_seat": {
"title": "fix(i18n)!: the console translation bundle leaves out Studio's metadataForms (75 KB of 221 KB on app-crm)",
"body_line_to_replace": "Clause-②: no",
"body_line_to_write": "Clause-②: yes (narrowing)",
"body_section_to_append": "the `## Round 2` section of PR comment 6421330578 (https://github.com/objectstack-ai/objectstack/pull/26159#issuecomment-6421330578), paste-ready: it names the BREAKING disposition, the requestedLocale declaration, the two ui docblock repairs and the main merge with the re-recorded digest"
}
}
Amendment 6418168409 set Metadata-protocol: none. That is wrong. Check Changeset at 4f5d2f0a (check-run 121702102787) measures moved authorable-surface shards (packages/spec/authorable-surface/api.json, system.json), and the gate reads a moved shard as a metadata-protocol change. The lines now read:
{
"issue": 25785,
"status": "done",
"branch": "claude/project-thread-nvoyre",
"head": "2cd96962",
"pr": "https://github.com/objectstack-ai/objectstack/pull/26159",
"session": "session_01Vy85beHdawtEtqNscYBy7V",
"premise_still_valid": true,
"summary": "Round 3, answering the seat's patch note on 4f5d2f0a (claim amendment 6421832617). The changeset now declares `Clause-②: yes (narrowing)` and `Metadata-protocol: narrowed` and ships @objectstack/spec and @objectstack/runtime at `minor`; both are the packages the gate names. The ADR-0087 marker stays `not-required (no-migration-prescription)`, and the gate accepts it under the new kind. Its reason is restated for `narrowed`: the narrowed face is a response that no stored metadata holds, and the authorable-surface keys this diff moves are additions, none removed or renamed. The remedy stays prose. No product code moved this round. Check Changeset is green at 48088279 and again at the head. The PR went conflicting twice while this round ran, so origin/main was merged twice (merges f5753454 and dca2e00c). The second merge resolved one real conflict: main's #25808 and this diff each add one Iso pin, so the count is now 791. Check-run state at 2cd96962: every check-run is green except `Type Check · workspace` and its roll-up `TypeScript Type Check`. Those two are #26288, and this diff tips that margin (see open_questions).",
"tests": "At the head 2cd96962, under scripts/pm/os-verify-lock.sh, each exit code captured before any pipe; every VERDICT is command-exit 0. (1) @objectstack/spec full suite: 'Test Files 805 passed (805)', 'Tests 23257 passed | 1 todo (23258)'. That includes the Iso pin test at 791 and the dropped-refinements ledger at 246/843. (2) The six runtime i18n door files: 'Tests 103 passed (103)'. (3) spec and runtime type-check. (4) Console loader and i18n transform: 'Tests 22 passed (22)'. (5) The two ObjectSchema pins that were red on CI at 48088279, MetadataService.specKeyObjectPayload and MetadataService.retiredObjectEnabled: 'Test Files 2 passed (2)', 'Tests 25 passed (25)'. Check Changeset's local equivalent, offline with a pull_request payload, gives the same answers at 4c82d13f and at the head. `check-changeset-no-major --base origin/main --event` with a body declaring `narrowed` exits 0. With `none` it exits 1, refusing because authorable-surface api.json and system.json moved; that was the CI red. check-adr-0087-registration exits 0 (BREAKING+clause-②-narrowing+metadata-protocol-narrowed, not-required (no-migration-prescription)), and check-empty-changeset exits 0. CONTROL for the type-check red: this diff's three sources (translation.zod.ts, protocol.zod.ts, runtime i18n.ts) were reverted to main's, then spec and runtime were rebuilt. With that, plugin-hono-server `tsc --noEmit --extendedDiagnostics` passes at `--max-old-space-size=4096`, with 4,214,495K used and a 104.24 s check under GC pressure. At this diff's head the same command dies with 'JavaScript heap out of memory'. At 8192 MB the two trees read 4,752,303K (control) and 4,772,570K (head): +20 MB, +6,090 types, +25,110 instantiations. The sources were restored, `git diff HEAD` on them was empty, and spec and runtime were rebuilt.",
"gates": "At 2cd96962: the derived list is 123 commands. All 123 ran with each exit code captured before any pipe, every one exited 0, and they reconcile: 'dispatch-gates --ran: 123 derived famil(ies) accounted for — 123 run, 0 NOT-MEASURED (a DERIVED zero — all 123 recorded an exit code and none of them is 3)'. Named receipts: check-adr-0087-registration 0, check-sdui-manifest 0 (the i18n record was re-recorded after each merge commit, 106 components unchanged), check:generated 0 (the os-regen deferral of content/docs/references/index.mdx was discharged in bf688dc9, and check-regen-pending was cleared), and check:type-check-debt under the lock ('1 ledger entr(ies) re-measured in 180.9s … none above its recorded number'). The same sweep also ran at 48088279 (125/125) and at ecf4c1e7 (123/123), all green. CI at 2cd96962, from the PR's check-runs: 61 of 63 are success or skipped. That includes Check Changeset, all eight Test Core shards, all sixteen Test UI shards, Type Check · source gates / consumer gates / debt ledger, Lint · ESLint, the Lint gate jobs, Build Core, Build Docs, Spec property liveness and Dogfood Regression Gate. Two are red: `Type Check · workspace` (job 121847327765) and its roll-up `TypeScript Type Check`. The job's only failure is '@objectstack/plugin-hono-server#typecheck … exited (134)', with no TS error in the log. It was the same at 48088279 (job 121721067561).",
"dogfood_battery": "2cd96962 · closure built first (pnpm --filter '@objectstack/dogfood^...' build, VERDICT command-exit 0, 7m49s), then pnpm --filter @objectstack/dogfood test under the verify lock, with no OS_TEST_SHARD and no path · VERDICT command-exit 0 · Test Files 297 passed | 3 skipped (300) · Tests 2527 passed | 18 skipped (2545) · no failure to name. The lock was held for 22m58s. The same battery was green at 48088279 and at ecf4c1e7, with identical counts.",
"line_budget": "716 changed lines (+685 / -31) over 22 files against the merge base 3249e204, the same size as round 2. main's merged commits are not this diff.",
"deviations": [
"origin/main was merged three times this round, each time because the PR was conflicting or red from main. (1) 80441cdc: conflicting. The dropped-refinements header was recounted to 246/843. (2) f5753454: the two Test UI shards at 48088279 failed 'expected 48 to be 47' on ObjectSchema.shape. That came from main's 5e113b39 (#26005, which added `sharing`). main itself fixed it in a1477dec (#26231, 'Fixes #26218'), and this merge brought that fix in. (3) dca2e00c: conflicting again, in type-alias-convention.pin.test.ts and the i18n registry record. The pin count is now 790 → 791, with main's #25808 row first and this diff's row second. After every merge the i18n digest was re-recorded from a committed tree.",
"The full dogfood battery and the gate sweep each ran three times, once at each head this round pushed, because each merge moved the head. All three runs were green. The final head is 2cd96962. origin/main had moved to 61ba04f6 (4 commits) by the push, and `git merge-tree` reports a clean merge."
],
"mcp_calls": "23, all reads and no write tool. 11 came from rounds 1 and 2. This round: get_check_run x1 (121702102787); pull_request_read get x2 (#26159, of which one read mergeable_state 'dirty'); pull_request_read get_check_runs x2 (at 48088279 and at 2cd96962); get_job_logs x5 (121721067561, 121724040837, 121724040732, and 121847327765 twice); actions_list list_workflow_runs x1 (lint.yml on main, which was green at 4f7e0414); issue_read get x1 (#26288).",
"api_writes": "6, all through the fleet relay: the 5 of rounds 1 and 2, plus this report (POST /issues/25785/comments). git push is not a REST write. This round's three pushes landed 48088279, ecf4c1e7 and 2cd96962.",
"open_questions": [
{
"question": "The `Type Check · workspace` lane is red at 2cd96962 from #26288's plugin-hono-server heap OOM, and the measurement says this diff tips it: main's declarations pass at 4096 MB with 4.21 GB used, and this diff adds about 20 MB. A maintainer re-run is therefore unlikely to go green. How should the PR clear the lane?",
"options": [
"A: hold this PR until #26288's fix lands (skipLibCheck, or extending the base tsconfig, for plugin-hono-server; measured in #26288 at 872,405 KB peak). Then merge main and re-run.",
"B: fold #26288's one-line tsconfig fix into this PR, on the seat's amendment of the claim surface.",
"C: the maintainer re-runs the lane as the seat said, and the PR waits only if the re-run stays red."
],
"recommendation": "A, because the fix is tooling owned by another card and lane. Folding it in would put a CI tsconfig change into a spec contract PR. The margin is shared with main, so any spec PR that adds declarations will hit the same wall until #26288 lands."
}
],
"out_of_scope_findings": [
"class: a · reach: CI `Type Check · workspace` on any PR that moves packages/spec · evidence: the control measurement above (+20 MB tips a 4096 MB heap) · dedupe: already filed as #26288 by the seat; this report adds a second data point, not a card · carrier: #26288"
]
}
Landing head fec80c3 on PR #26159. This is origin/main merged in after #26356 fixed #26288; the diff is unchanged at +685/-31 over 22 files. CI: all 63 check-runs are success or skipped, including Type Check · workspace, TypeScript Type Check, Check Changeset, Test Core 8/8 and Test UI 16/16. Locally at this head, under the verify lock, every VERDICT is 0: the dogfood battery is 298 passed and 3 skipped of 301 files, @objectstack/spec has 806/806 files, the runtime i18n door 103/103, the console i18n 22/22 and the two ObjectSchema pins 25/25. plugin-hono-server type-check, check:generated, check-sdui-manifest and the three changeset gates all exit 0. mcp_calls 24, all reads. api_writes 7, this comment included. The PR stays a draft.
The new head is 392a610: origin/main 7c34e5d merged as 41d06a4, plus one regeneration commit. CI: all 63 check-runs are success or skipped, including Check Changeset, Type Check · workspace, TypeScript Type Check, Test Core 8/8 and Test UI 16/16. Conflict files and their resolutions:
packages/spec/dropped-refinements.baseline.json: only the header conflicted. Main's 247/866, plus this diff's unchanged system/ServedTranslationData entry (1 schema, 3 sites), gives 248/869, which is the count of the merged body. No entry changed.
Three generated files were deferred by os-regen rather than text-merged: packages/spec/authorable-surface/api.json, packages/spec/authorable-surface/system.json and content/docs/references/index.mdx. They are regenerated in 392a610, and the authorable-surface diff against main is exactly this diff's keys.
Reviewed logic is untouched: main changed none of protocol.zod.ts, translation.zod.ts or runtime i18n.ts, and this diff's hunks in them are byte-identical to fec80c3's. The one auto-merged file in scope, ui/packages/app-shell/.../metadata-form-i18n.ts, took main's edit on a different docblock line; this diff's bullet is unchanged. The diff is now 21 files, +684/-30.
Locally at 392a610, under the verify lock, every VERDICT is 0. The dogfood battery is 301 passed and 3 skipped of 304 files. The other suites:
@objectstack/spec: 811/811 files.
Runtime i18n door: 103/103.
Console i18n: 22/22.
The two ObjectSchema pins: 25/25.
check:generated, check-regen-pending and the three changeset gates all exit 0. mcp_calls 25, all reads. api_writes 8, this comment included. The PR stays a draft.
Activity
objectstack-fleet commentedon Oct 25, 2026
Triage: first grade —
bug·priority:p1·domain:server·area:i18n·pm:queue· triage seat ·session_01AavokzJ5DndAwitDXvKy4U· 2026-10-25T11:57Z⛔ Not a claim, ⛔ not a dispatch.
ETag/Cache-Controlon/i18n/translations/:locale. That is not a new contract, so it can go first. Splitting the bundle, if proposed, is a wire-shape change and goes to spec.Generated by Claude Code
objectstack-fleet commentedon Oct 26, 2026
Claim: PM loop round 1 · card thread · 2026-10-26T03:38Z
Session:
session_01HFAuCZPty5SsvseoPRgukQ(the card thread, mode:thread; the seat writes this claim for it: seat sessionsession_01TFnDdepdwyDJeM2kJ4GtMy)Account:
os-elon-musk(the seat's linked user asGET /useranswers it; the card's assignee)Branch:
claude/project-thread-icw4tr(platform-assigned to the card thread; a thread can push only its assigned branch, a measured platform exception toclaude/issue-<n>-<slug>)Worktree:
objectstack-issue-25785Domain:
domain:serverSeat:
domain:server#2(seat post #20966; 由 os-elon-musk 账户的项目负责)File surface: the
GET /i18n/translations/:localeserving path,packages/runtime/src/domains/i18n.ts(thetranslationsbranch, read onorigin/maincb0a2fcf) and, if the headers belong at the HTTP layer, the dispatcher's response path that carries them; their tests; one changeset. Scope = the triage comment's first step:ETag+Cache-Control: private, no-cache+304on a matchingIf-None-Match, asPart of #25785. ⛔ Not this claim: movingmetadataFormsout of the boot bundle (a wire-shape change, per triage 6397341079 it goes todomain:spec); report it as an out-of-scope finding with its carrier. The expected landing point is the file above; if measurement shows the producer elsewhere, fix it there and say so in the report and PR body. Stop on a breach and explain it.Container & model:
M,mode:thread,model: default tier (dispatch-gates --tier on this surface: "no path-derived mandate"),effort: xhigh(p1)Clause-②: no
Metadata-protocol: none
Basis for the Clause-② line: no accept set narrows or widens; an existing route answers the same body, plus a validator header and a conditional 304. Re-read against AGENTS.md on the measured diff; if the route's response is declared in a published schema and the diff touches it, stop and report (that is spec-lane work and owes a contract-tier review).
Responsibility: the runtime i18n domain (
packages/runtime/src/domains/i18n.ts) produces the cost | no platform path covers it: no ETag or Cache-Control is set anywhere on the route | every console open on every hosted tenant reaches it today (cloud#2914 measurement, per the card)Thread-read: 6397341079
Premise: holds (card measured on framework pin
888d6865;origin/maincb0a2fcfdomains/i18n.ts:137–:147 still answersgetTranslations(locale)with no caching header set in that branch; the thread re-measures)Writes: PR only through the relay
pr_create; comments, labels and bodies only through the relay write tools (post-stamped.mjs,label-write.mjs,fleet-write/dispatch.mjs). ⛔ No GitHub MCP write tool. Report both counts (writes,mcp_calls).Serial constraints cleared: none. #25783's card thread works on
/meta(packages/rest,packages/metadata-protocol), not on the i18n domain; no open PR namespackages/runtime/src/domains/i18n.ts.Resume-from: none
Generated by Claude Code
objectstack-fleet commentedon Oct 26, 2026
Claim amendment (file surface) ·
domain:server#2· seat sessionsession_01TFnDdepdwyDJeM2kJ4GtMy· 2026-10-26T04:26Z · amends claim 6407675488, same session, same branchclaude/project-thread-icw4tr.File surface adds one row in
scripts/check-route-envelope.mjs:DISPATCHER_DOMAINS['i18n.ts']goes fromhandBuilt: 0to2, with a REQUIREDnote. This is the gate's own kind 1 ("Enveloped, but the helper cannot express the response"), the classificationmeta.tstook forVary: Accept-Language.deps.successtakes no headers, so the 200 carryingETag/Cache-Controlis hand-built around the declared envelope. A304carries no body by HTTP rule, so it has no envelope to emit.The note names both. ⛔ No other row moves, and the gate's logic is unchanged. ⛔ No new
DomainHandlerDepsmember: growing the deps interface is a design decision outside this card. The PR body names this row as a declared surface addition. Every other line of the claim stands.Generated by Claude Code
objectstack-fleet commentedon Oct 26, 2026
os-dev-report
{
"issue": 25785,
"status": "done",
"branch": "claude/project-thread-icw4tr",
"pr": "#25956",
"session": "session_01HFAuCZPty5SsvseoPRgukQ",
"premise_still_valid": true,
"summary": "Part of #25785, per claim 6407675488. GET /i18n/translations/:locale (path and ?locale= spellings, direct and zh->zh-CN fallback exits) now answers 200 with ETag W/"base64url sha256 of the exact served envelope, computed every read" and Cache-Control: private, no-cache, and answers a matching If-None-Match (comma list, weak comparison, *) with a body-less 304 carrying both headers. The anonymous floor stays first (401, no headers). Only packages/runtime/src/domains/i18n.ts changes in source; no transport, spec or response-schema change. One declared surface addition per amendment 6408228005: scripts/check-route-envelope.mjs i18n.ts handBuilt 0->2 (kind 1). Measured on examples/app-crm: zh-CN 200 220,391 B -> 304 0 B; en 213,264 B -> 304 0 B; recomputed ETag equals the header. #25785 stays open for its metadataForms half (domain:spec).",
"tests": "New: runtime domains/i18n-translations-etag.test.ts 21 tests, runtime i18n-translations-etag.hono.integration.test.ts 4 tests (real socket, LiteKernel + HonoServerPlugin + createDispatcherPlugin: 304 has a 0-byte body), adapters/hono hono-not-modified-response.test.ts 3 tests (toResponse characterization pins). Ablation at a373155: i18n.ts replaced on disk by origin/main cb0a2fc blob -> 23 of 25 runtime tests red (2 green are the 400/401 controls); restored blob bb41d094 == HEAD, diff clean. Suites at 0b2e659: pnpm --filter @objectstack/runtime test under the verify lock VERDICT command-exit 0, 446 files, 7125 passed, 19 skipped; pnpm --filter @objectstack/hono test 13 files, 228 passed; typecheck both packages exit 0 (runtime re-run green at 7b2a1a2 after the check:test-typecheck fix). Real composition: pnpm dev:crm -- --fresh after full pnpm build (VERDICT 0), 25 cold reads one ETag, 25 conditional reads all 304.",
"gates": "Local: node scripts/pm/dispatch-gates.mjs --commands at 773c3f3 derives 87 families on 6 paths, all 87 exit 0 (codes captured before any pipe); --ran reconciliation 87 derived, 87 run, 0 NOT-MEASURED, 0 UNRUN, exit 0. check:route-envelope was red at 7b2a1a2 (i18n.ts handBuilt found 2, declared 0) until the amendment row; check-plugin-teardown-shape --self-test and check:dual-build-cjs-loads exited 3 until the fixture commit fetch and a full build, then 0. eslint --no-inline-config on the 5 code files exit 0. check-governed-merges --branch HEAD: NOT governed. CI on PR head 773c3f3: 46 check runs, 0 failed: Build Core success; Test Core 1/8..8/8 success and Test Core success; TypeScript Type Check success (workspace, source gates, consumer gates, debt ledger all success); Lint & Repo Gates success (ESLint, repo & tooling gates, docs & code guards, CI release & engine gates, PM dispatch-gates, three scoped lanes all success); Dogfood Regression Gate success; Check Changeset success; Governed Surface Queue Guard success; Part-of PR must not also close its card success; The card this PR closes must claim this branch success; No other open PR may claim the same issue success; No other open PR may claim the same single-writer path success; Check PR Size, Check Documentation Links, Flag docs affected by code changes, Auto Label success; UI, docs build, temporal, dogfood shards, opt-in smoke lanes skipped by the path filter. mergeable_state clean.",
"dogfood_battery": "n/a — no
!in the PR title and no (narrowing) arm","mcp_calls": "8 — all reads: issue_read x4, search_pull_requests x1, pull_request_read x3 (get_check_runs x2, get x1); no MCP write",
"api_writes": "3 relay actions in 2 strokes — POST /repos/objectstack-ai/objectstack/pulls (pr_create, assignee os-elon-musk, run 40274520812, read back identical 9764 B); POST /repos/objectstack-ai/objectstack/pulls/25956/requested_reviewers (pr_request_reviewers os-elon-musk, the requester); POST /repos//issues/25785/comments (this report). Plus git push of the branch (not REST).",
"open_questions": [],
"out_of_scope_findings": [
"carrier: domain:spec (#25785 stays open) — the card's second half, keeping metadataForms (46.8 KB raw on the measured tenant) out of the boot bundle and the optional scoping of objects to the current app; both change the GET /i18n/translations/:locale wire shape · noted, not filed",
"carrier: none — /i18n/locales and /i18n/labels/:object/:locale carry no validator; not measured on the open path and not asked by the card · noted in PR Acceptance notes, not filed",
"carrier: none — docs-drift bot comment 6408979046 lists content/docs/permissions/system-context.mdx row 52 via handleI18nRequest; re-read: it states the anonymous-deny seam, which still holds (401 first, pinned by tests), so no doc change · noted, not filed"
]
}
objectstack-fleet commentedon Oct 26, 2026
ACCEPT → PR #25956 comment 6409329004 ·
domain:server#2· 2026-10-26T05:59Z · landing through the relay (standing landing word, seat thread 2026-10-26 05:53Z); the card stays open for themetadataFormshalfGenerated by Claude Code
objectstack-fleet commentedon Oct 26, 2026
Release:
domain:serverseat 2 ·os-elon-musk· sessionsession_01TFnDdepdwyDJeM2kJ4GtMy· 2026-10-26T07:03Z · cause: the ETag half landed (Part of #25785), and the seat signs off · destination:pm:queue, unassigned, for themetadataFormshalfLanded: PR #25956 →
69fa23d60merged: true, merge commit69fa23d60, merged 2026-10-26T06:42Z through the merge queueorigin/main69fa23d60is an ancestor oforigin/mainGET /i18n/translations/:locale(both spellings) carries a weak content-hashETagandCache-Control: private, no-cache, and a matchingIf-None-Matchgets a body-less304. On app-crm zh-CN the dev measured 220,391 B →304with 0 B.metadataForms(≈46.8 KB) out of the boot read. Its carrier isdomain:spec, because the bundle shape is a published contract. The next seat should route or split it with triage.pm:dispatched→pm:queue, assignee cleared, in this act. The card thread is closed.Generated by Claude Code
7 remaining items
objectstack-fleet commentedon Oct 26, 2026
Claim: PM loop round 1 · 2026-10-26T12:13Z
Session:
session_01HbmCEPMBmMLU3VZCEzfec7(seat 4; the card thread issession_01Vy85beHdawtEtqNscYBy7V, which writes no claim of its own)Account:
zhuangjianguoBranch:
claude/project-thread-nvoyre(the platform assigns the card thread's branch, and the thread can push only that branch. Written as measured, instead ofclaude/issue-25785-<slug>.)Worktree:
objectstack-issue-25785Domain:
domain:specSeat:
domain:spec#4(seat post #18917; 由 zhuangjianguo 账户的项目负责)File surface: the translation-bundle composition for
GET /i18n/translations/:locale(packages/spec/src/system/i18n-resolver.tsand the runtime doorpackages/runtime/src/domains/i18n.tswhere the boot bundle is assembled), Studio'smetadataFormsreaders (ui/packages/app-shell/src/views/metadata-admin/*,ui/packages/i18n/src/utils/spec-translations.ts), thepackages/rest/src/rest-server.tsreader if it is affected, tests, and one changeset. Out of scope: scopingobjectsto the current app. If measurement puts the producer elsewhere, fix it there and say so. Stop on a breach and explain it in the report.Container & model:
M,mode:thread,model: TIER_DEFAULT — dispatch-gates --tier: no path-derived mandate,effort: xhigh (p1)Clause-②: no
Metadata-protocol: none
Responsibility: the runtime/spec translation-bundle composition produces the cost | no platform path covers it: the boot read takes the whole bundle,
metadataFormsincluded | every console open on every tenant reaches it today (cloud#2914 measurement)Thread-read: 6412175443
Premise: holds (unmeasured on
main:metadataFormsis still a bundle module at0a694821(i18n-resolver.ts:4246,conversions/registry.ts:8467); the thread re-measures the composition before changing it)Ruling-ref: none from the maintainer; triage 6412175443 routed the whole card to
domain:specSerial constraints cleared:
#25956 (ETag) and #25983 (BCP-47 locale tags) landed on this route and the translation schema today; no in-flight claim names these files.Resume-from: none
objectstack-fleet commentedon Oct 26, 2026
os-dev-report
{ "issue": 25785, "status": "done", "branch": "claude/project-thread-nvoyre", "head": "8b2ad27c24209acc9cddb61f4792b0b7e70a91e5", "pr": "https://github.com/objectstack-ai/objectstack/pull/26159", "session": "session_01Vy85beHdawtEtqNscYBy7V", "premise_still_valid": true, "summary": "GET /i18n/translations/:locale now serves every translation group except the ones the server resolves itself. The spec names them in SERVER_RESOLVED_TRANSLATION_GROUPS (today only metadataForms) and GetTranslationsResponseSchema.translations is the new closed ServedTranslationDataSchema, the platform face minus those groups. The runtime door serves a copy and never edits the i18n service's tree. How Studio loads metadataForms, the choice the dispatch left to the dev: it does not load it in the browser at all. The /meta and /meta/types handler (translateMetaTypesResponse in @objectstack/rest) already resolves metadataForms.TYPE in process from the same service and serves each authoring form translated, and the liveness ledger names that handler as the group's only reader. No new endpoint, route or key, so no needs_decision. Measured live on examples/app-crm zh-CN: 221,007 B raw / 68,580 gzip down to 145,863 / 45,107, the group (75,127 B) absent, a warm reopen still 304 with 0 B, and /meta/types serving the same 31 entries with identical translated labels before and after. The ETag half of the card landed earlier (not this PR) and was left untouched.", "tests": "Under scripts/pm/os-verify-lock.sh, --maxWorkers=2. @objectstack/runtime full suite at 8b2ad27c: 'Test Files 455 passed (455)', 'Tests 7415 passed | 19 skipped (7434)', VERDICT command-exit 0. @objectstack/spec full suite: 'Tests 1 failed | 21929 passed | 1 todo', the one red being scripts/dropped-refinements.test.ts 'header totals match its body'; the totals were recounted in 8b2ad27c and that file then ran 27/27 (only that test reads them, git grep). Focused: runtime 4 files / 41 tests, spec 5 files / 434 tests, all passed. Type-check of spec, runtime and client: VERDICT command-exit 0. ui/apps/console/src/loadLanguage.test.tsx, which walks GetTranslationsResponseSchema.shape.translations through the workspace link and so reads this narrowing: 'Tests 7 passed (7)'. New pins: packages/runtime/src/domains/i18n-translations-served-groups.test.ts (10 tests: both spellings and the fallback exit omit the group and keep the rest byte-identical; the body parses the closed response schema with a control that the same body WITH the group is refused; the service's tree is not edited and a RestServer /api/v1/meta over the same service after a boot read still serves 仪表板 / 布局 / 列数; the ETag hashes the served body, If-None-Match gives 304, a metadataForms-only change keeps the validator and a messages change moves it) and packages/spec/src/system/served-translation-data.test.ts (served face == platform face minus the constant both ways with a positive control; the response schema serves that face; each constant group stays declared on both bundle faces; a document carrying it is refused with unrecognized_keys naming it). Ablation, one-off, mutated on disk then restored, both quoted in the PR body: (1) filter removed (blob 3154a44d to a28c8f4a) ⇒ 6 of 10 failed, restore blob == HEAD; (2) in-place delete of the group from the service's tree (blob 3154a44d to 5e38e852) ⇒ exactly the 2 Studio pins failed, /meta serving 'Dashboard' where '仪表板' was expected, the other 8 passing, restore blob == HEAD with git diff HEAD empty.", "gates": "Local subset: all 114 derived commands, each exit code captured before any pipe into a ran.list, then reconciled — 'dispatch-gates --ran: 114 derived famil(ies) accounted for — 114 run, 0 NOT-MEASURED (a DERIVED zero — all 114 recorded an exit code and none of them is 3)'. Every one exited 0, among them check:generated, check:api-surface, check:authorable-surface, check:docs, check:liveness, check:strictness-ledger, check:spec-parsed-alias, check:exported-any, check:dual-build-cjs-loads, check:nul-bytes and check:type-check-debt under the verify lock ('26 raw tsc error(s) total, none above its recorded number'). The list derived at the final head 8b2ad27c is byte-identical to the list run (diffed). The sweep began at 12:55Z, before 8b2ad27c (13:02Z), so the 10 commands that finished before that commit plus check:query-options-erasure, which overlapped the 20-second window of ablation 1, were rerun at 8b2ad27c: all exit 0. Local-only families, read-only per os-dev.md: check:dev-prereqs exit 0 and check:skill-frame-freshness exit 0. CI's own repo-wide scans and the PR's check-runs are CI's; this report does not claim them — read them on PR #26159 at head 8b2ad27c.", "dogfood_battery": "n/a — no `!` in the PR title and no (narrowing) arm", "line_budget": "648 changed lines (+625 / -23) over 18 files, under dispatch-gates' 3000-line human-merge threshold. Hand-written source +93/-6 (translation.zod.ts +52, i18n.ts +33/-4, protocol.zod.ts +8/-2); tests +321/-3 (two new files 237 and 71, the alias pin +13/-3); docs and changeset +24/-3; generated or recounted artefacts +187/-11.", "files_changed": [ ".changeset/25785-served-translations-without-metadata-forms.md", "content/docs/protocol/kernel/i18n-standard.mdx", "content/docs/references/api/protocol.mdx (generated)", "content/docs/references/index.mdx (generated)", "content/docs/references/system/translation.mdx (generated)", "docs/audits/2026-07-unknown-key-strictness-ledger.counts/system.md (generated)", "packages/runtime/src/domains/i18n-translations-served-groups.test.ts (new)", "packages/runtime/src/domains/i18n.ts", "packages/spec/api-surface/system.json (generated)", "packages/spec/authorable-surface/system.json (generated)", "packages/spec/declaration-map/system.json (generated)", "packages/spec/dropped-refinements.baseline.json", "packages/spec/export-origins/system.json (generated)", "packages/spec/json-schema.manifest/system.json (generated)", "packages/spec/src/api/protocol.zod.ts", "packages/spec/src/system/served-translation-data.test.ts (new)", "packages/spec/src/system/translation.zod.ts", "packages/spec/src/type-alias-convention.pin.test.ts" ], "deviations": [ "Two files outside the claim's named file surface: packages/spec/src/system/translation.zod.ts and packages/spec/src/api/protocol.zod.ts. Contract-first — the served shape is a declaration, so it was declared in the spec rather than kept implicit in the runtime; the PR body names them. Non-test packages/spec/src moved, so a CONTRACT_REVIEW_TIER review is owed before landing.", "The card's fix sketch says 'load it with Studio'. Studio needs no browser load: /meta/types already serves its forms translated and nothing in the browser read the group from the bundle. The acceptance item (Studio still renders its forms translated) is pinned by a test over a real RestServer.", "The first full spec suite was spelled `pnpm --filter @objectstack/spec test -- --maxWorkers=2`; the `--` made vitest drop maxWorkers, so it ran at default workers. The whole suite still ran.", "That run's one red was the dropped-refinements header totals, fixed in 8b2ad27c; the full spec suite was not rerun after that commit, only scripts/dropped-refinements.test.ts (27/27). That commit changes nothing else.", "dispatch-gates warned STALE TREE (behind origin/main, stale scripts/sdui-manifest.record.json). No file in this diff is touched by main's newer commits and `git merge-tree` reports no conflict, so main was not merged in.", "No labels sent with pr_create: the dispatch named none, and the diff publishes (changeset present), so skip-changeset does not apply. The platform's size/l landed on its own." ], "mcp_calls": "8 — all reads, no write tool: issue_read get (#25785) x2, issue_read get_comments (#25785) x3, pull_request_read get x3 (#26159 twice, reading the stored body back, and #26011 once as a body-shape precedent).", "api_writes": "3 — all through the fleet relay (POST /repos/objectstack-ai/objectstack/dispatches, 204, run read to conclusion): (1) pr_create, POST /repos/objectstack-ai/objectstack/pulls, read back '11390 byte(s) sent, 11390 stored — identical', assignee zhuangjianguo as the pull lists them; (2) pr_request_reviewers, POST /repos/objectstack-ai/objectstack/pulls/26159/requested_reviewers, zhuangjianguo; (3) this comment, POST /repos/objectstack-ai/objectstack/issues/25785/comments. git push is not a REST write.", "open_questions": [], "out_of_scope_findings": [ "class: b · reach: GET /i18n/translations/:locale still serves every object's translations, not the current app's — zh-CN `objects` is 111,504 B of the 145,863 B this PR leaves · evidence: the card's own optional item, which it calls a bigger contract change, plus the per-group byte reading in PR #26159 · dedupe words: i18n translations objects scope current app boot bundle · carrier: seat domain:spec#4 to file or drop · noted, not filed", "class: a · reach: the locale-fallback exit serves `requestedLocale`, which GetTranslationsResponseSchema does not declare; the outer z.object is not strict, so it passes unnoticed · evidence: packages/runtime/src/domains/i18n.ts fallback exit versus GetTranslationsResponseSchema in packages/spec/src/api/protocol.zod.ts; pre-existing and unchanged by this PR · dedupe words: requestedLocale GetTranslationsResponseSchema undeclared fallback locale · carrier: seat domain:spec#4 to file or drop · noted, not filed", "class: c · reach: two ui docblocks now describe the old composition — SPEC_TRANSLATION_GROUPS in ui/packages/i18n/src/utils/spec-translations.ts calls its list 'the keys of the translations shape' (metadataForms is no longer one, and the list is a superset detector, so no behaviour changes), and ui/packages/app-shell/src/views/metadata-admin/metadata-form-i18n.ts expects 'the environment's own translation bundle' to arrive one day as a higher-precedence source for Studio's form labels, which would now be /meta/types · evidence: both files read at 8b2ad27c; loadLanguage.test.tsx passes 7/7 against the narrowed face · dedupe words: SPEC_TRANSLATION_GROUPS metadata-form-i18n docblock served groups stale · carrier: seat domain:spec#4 to file or drop · noted, not filed" ] }Read at 2026-10-26T14:10Z.
Generated by Claude Code
objectstack-fleet commentedon Oct 26, 2026
Claim amendment — PM loop round 1, seat
domain:spec#4, sessionsession_01HbmCEPMBmMLU3VZCEzfec7, 2026-10-26T14:12Z.Seat review of PR #26159 at
8b2ad27camends claim 6415714537:Clause-②: yes (narrowing)
Metadata-protocol: none
Why:
GetTranslationsResponseSchema.translationsmoves from the platform face to the closedServedTranslationDataSchema. A response body carryingmetadataForms, which the published schema accepted, now fails it, and the exported TypeScript type loses the member;GET /i18n/translations/:localestops serving a group it served. What an author writes is unchanged, so the kind isnoneand the level stayspatch, with the BREAKING banner and one ADR-0087 disposition (AGENTS.md Post-Task Checklist step 3).File surface, widened:
packages/spec/src/system/translation.zod.tsandpackages/spec/src/api/protocol.zod.ts(the dev's contract-first move, named in the PR body), plusrequestedLocaledeclared onGetTranslationsResponseSchema— the runtime's fallback exit serves it undeclared, same schema, same defect class, mechanical — and the two ui docblocks this PR made false (ui/packages/i18n/src/utils/spec-translations.tsSPEC_TRANSLATION_GROUPS,ui/packages/app-shell/src/views/metadata-admin/metadata-form-i18n.ts).Dropped, not filed: scoping
objectsto the current app (the card's optional item). After this PR the zh-CN bundle is 45,107 B gzip and a warm reopen is304, 0 B; per-app scoping is a contract change with no measured user-visible cost left to pay for it.A
CONTRACT_REVIEW_TIERcontract review is owed before landing.objectstack-fleet commentedon Oct 26, 2026
os-dev-report
{ "issue": 25785, "status": "done", "branch": "claude/project-thread-nvoyre", "head": "4f5d2f0a417d404c7d44bc256585d25071d7c7e4", "pr": "https://github.com/objectstack-ai/objectstack/pull/26159", "session": "session_01Vy85beHdawtEtqNscYBy7V", "premise_still_valid": true, "summary": "Round 2, answering the seat's review of 8b2ad27c (claim amendment 6418168409). Four items, all landed: (1) the declarations are corrected to Clause-②: yes (narrowing) / Metadata-protocol: none, and the changeset carries the BREAKING banner, the remedy (read metadataForms from GET /meta/types) and exactly one ADR-0087 disposition, not-required (no-migration-prescription), which check-adr-0087-registration accepts by name; (2) requestedLocale is declared on GetTranslationsResponseSchema, optional, with pins on both sides — the door has served it on the locale-fallback exit since that fallback existed, undeclared; (3) the two ui docblocks this PR had made false are repaired; (4) finding 1 (scoping objects) is dropped by the seat, so nothing was built for it. The behaviour of round 1 is unchanged: the served document still leaves out SERVER_RESOLVED_TRANSLATION_GROUPS, the runtime still serves a copy, /meta/types still serves Studio's forms translated, and a warm reopen is still 304.", "tests": "All at the final head 4f5d2f0a, under scripts/pm/os-verify-lock.sh, each exit code captured before any pipe. @objectstack/spec full suite (`exec vitest run --maxWorkers=2`): 'Test Files 803 passed (803)', 'Tests 23204 passed | 1 todo (23205)', VERDICT command-exit 0 — the ledger red of round 1 is gone and the count rose with main's 40 commits. runtime i18n suite (the six i18n test files of this door: served-groups, etag, anonymous-deny, the success-envelope conformance, fallback-locale, supported-locales): 'Test Files 6 passed (6)', 'Tests 103 passed (103)', VERDICT 0. Type-check of @objectstack/spec and @objectstack/runtime: VERDICT 0. ui (`cd ui && pnpm exec vitest run apps/console/src/loadLanguage.test.tsx packages/i18n/src/__tests__/spec-translations.test.ts`): 'Test Files 2 passed (2)', 'Tests 22 passed (22)' — the console loader walks GetTranslationsResponseSchema.shape.translations through the workspace link, so it reads this narrowing, and the i18n transform's own suite covers the docblock's package. New pins this round: the spec test fixes the response shape to locale / requestedLocale / translations, parses a real fallback body, keeps the field optional and refuses a non-string; the runtime test parses the fallback body against the schema and asserts the key is declared. Round 1's evidence stands at this head by the suites above: the two ablations (filter removed = 6 of 10 red; in-place delete = exactly the 2 Studio pins red, /meta serving 'Dashboard' for '仪表板'), both restored to HEAD with git diff HEAD empty, and the live app-crm measurement (zh-CN 221,007 B raw / 68,580 gzip to 145,863 / 45,107; en 213,880 / 58,666 to 138,502 / 37,576; the group absent; a warm reopen 304 with 0 B; /meta/types serving 31 entries with identical translated labels). Not re-measured live after the merge: the served composition is byte-identical in this round (requestedLocale was already served), so the readings above are the readings of this behaviour.", "gates": "Local subset at the final head 4f5d2f0a: the derived list is now 125 commands (main's 40 commits add nine families, and the merge removed the STALE TREE warning). All 125 ran, each exit code captured before any pipe, every one exit 0, then reconciled: 'dispatch-gates --ran: 125 derived famil(ies) accounted for — 125 run, 0 NOT-MEASURED (a DERIVED zero — all 125 recorded an exit code and none of them is 3)'. Named receipts: check-adr-0087-registration --base origin/main exit 0 ('1 declared-breaking changeset(s), each carrying an ADR-0087 disposition … not-required (no-migration-prescription)'), check-sdui-manifest exit 0, check:generated, check:api-surface, check:authorable-surface, check:docs, check:liveness, check:strictness-ledger, check:spec-parsed-alias, check:exported-any, check:nul-bytes, the five docs families, and check:type-check-debt under the verify lock ('1 ledger entr(ies) re-measured in 246.8s, 26 raw tsc error(s) total, none above its recorded number'). Local-only families, read-only per os-dev.md: check:dev-prereqs exit 0, check:skill-frame-freshness exit 0 ('the frame itself is unchanged'). CI's repo-wide scans and the PR's check-runs are CI's; this report does not claim them — read them on PR #26159 at 4f5d2f0a.", "dogfood_battery": "4f5d2f0a · closure built first (pnpm --filter '@objectstack/dogfood^...' build, VERDICT command-exit 0), then the battery as CI spells it: pnpm --filter @objectstack/dogfood test under the verify lock, no OS_TEST_SHARD and no path argument. VERDICT command-exit 0 · Test Files 296 passed | 3 skipped (299) · Tests 2523 passed | 18 skipped (2541) · no failure to name. Held the lock 26m47s.", "line_budget": "716 changed lines (+685 / -31) over 22 files against the new merge base 601c7738, under dispatch-gates' 3000-line human-merge threshold; main's 40 merged commits are not this diff. Round 2 added +68 / -8 of that: protocol.zod.ts +10 (the declaration and its docblock), the two test files +12 and +4, the changeset +9/-3, the two ui docblocks +25/-7, one generated reference row, one authorable-surface key, and one re-recorded registry digest line.", "files_changed": [ ".changeset/25785-served-translations-without-metadata-forms.md", "content/docs/protocol/kernel/i18n-standard.mdx", "content/docs/references/api/protocol.mdx (generated)", "content/docs/references/index.mdx (generated)", "content/docs/references/system/translation.mdx (generated)", "docs/audits/2026-07-unknown-key-strictness-ledger.counts/system.md (generated)", "packages/runtime/src/domains/i18n-translations-served-groups.test.ts (new)", "packages/runtime/src/domains/i18n.ts", "packages/spec/api-surface/system.json (generated)", "packages/spec/authorable-surface/api.json (generated)", "packages/spec/authorable-surface/system.json (generated)", "packages/spec/declaration-map/system.json (generated)", "packages/spec/dropped-refinements.baseline.json", "packages/spec/export-origins/system.json (generated)", "packages/spec/json-schema.manifest/system.json (generated)", "packages/spec/src/api/protocol.zod.ts", "packages/spec/src/system/served-translation-data.test.ts (new)", "packages/spec/src/system/translation.zod.ts", "packages/spec/src/type-alias-convention.pin.test.ts", "scripts/sdui-manifest.sources/i18n.json (re-recorded)", "ui/packages/app-shell/src/views/metadata-admin/metadata-form-i18n.ts", "ui/packages/i18n/src/utils/spec-translations.ts" ], "deviations": [ "PR BODY AND TITLE ARE OWED, AND ARE THE SEAT'S WRITE: a dev writes a PR body once, at pr_create, and never PATCHes it (os-dev.md), so the body still carries `Clause-②: no` and the title still lacks `!`. The exact text to write is named below under `pr_text_for_the_seat`. The `Clause-②` declaration of record for the contract review is the changeset's, which reads `yes (narrowing)`.", "`origin/main` was merged in (merge 81dc21e7, 40 commits), which the rules allow on a conflict: editing a ui registry source moves that package's digest, and main had just re-shaped those records one-per-package (#26120), so a re-record on the stale layout would have conflicted in the queue. No file in this diff overlaps main's range (comm over both name lists is empty), and the digest was re-recorded after the merge commit, never in a merging tree.", "The remedy in the changeset is written as prose, not as a literal `FROM → TO` label block: that label is branch 1 of the migration-prescription detector, and with it the only claimable ADR-0087 category (`no-migration-prescription`) is refused while the other five are closed on facts. The mapping it would have carried is stated in words in the same changeset. This is the one place where the seat's wording and the gate disagree, and the gate's reading is the one that can be re-run.", "Two files remain outside the claim's original file surface (packages/spec/src/system/translation.zod.ts, packages/spec/src/api/protocol.zod.ts); the amended claim widens the surface to include them, plus the requestedLocale declaration and the two ui docblocks, so this round is inside it.", "The full ui app-shell suite was not run: the app-shell edit is a docblock inside a comment block, no behaviour, and that suite is about 71 minutes for 1722 files. Declared, not measured; CI runs it.", "The first full spec suite of round 1 was spelled `pnpm --filter @objectstack/spec test -- --maxWorkers=2`; the `--` made vitest drop maxWorkers. Round 2's run spells it `exec vitest run --maxWorkers=2`." ], "mcp_calls": "11 — all reads, no write tool: issue_read get (#25785) x2, issue_read get_comments (#25785) x5 (three in round 1, two reading the seat's amendment), pull_request_read get x4 (#26159 twice, #26011 once as a body-shape precedent, and one more read of #26159 before this report).", "api_writes": "5 — all through the fleet relay (POST /repos/objectstack-ai/objectstack/dispatches, 204, each run read to its conclusion): round 1's pr_create (POST /pulls, read back 11390 of 11390 bytes identical, assignee zhuangjianguo), pr_request_reviewers (POST /pulls/26159/requested_reviewers), the first os-dev-report (POST /issues/25785/comments, comment 6418116291, 10544 of 10544 bytes identical); round 2's Round-2 comment on the PR (POST /issues/26159/comments) and this report (POST /issues/25785/comments). git push is not a REST write; three pushes landed 2f4dfc02, the main merge and 4f5d2f0a.", "open_questions": [], "out_of_scope_findings": [ "class: a · reach: closed by this round — `requestedLocale` is now declared on GetTranslationsResponseSchema, so the finding round 1 carried is fixed here rather than filed · evidence: packages/spec/src/api/protocol.zod.ts at this head, pinned in packages/spec/src/system/served-translation-data.test.ts and packages/runtime/src/domains/i18n-translations-served-groups.test.ts · carrier: none needed", "class: c · reach: closed by this round — both ui docblocks are repaired here · evidence: ui/packages/i18n/src/utils/spec-translations.ts and ui/packages/app-shell/src/views/metadata-admin/metadata-form-i18n.ts at this head · carrier: none needed", "class: b · reach: the seat dropped scoping `objects` to the current app (its reason: 45,107 B gzip and a 304 warm reopen leave no measured user-visible cost to pay for a contract change) · evidence: claim amendment 6418168409 · carrier: dropped by the seat, not filed" ], "pr_text_for_the_seat": { "title": "fix(i18n)!: the console translation bundle leaves out Studio's metadataForms (75 KB of 221 KB on app-crm)", "body_line_to_replace": "Clause-②: no", "body_line_to_write": "Clause-②: yes (narrowing)", "body_section_to_append": "the `## Round 2` section of PR comment 6421330578 (https://github.com/objectstack-ai/objectstack/pull/26159#issuecomment-6421330578), paste-ready: it names the BREAKING disposition, the requestedLocale declaration, the two ui docblock repairs and the main merge with the re-recorded digest" } }Read at 2026-10-26T16:28Z.
Generated by Claude Code
objectstack-fleet commentedon Oct 26, 2026
Claim amendment 2 — seat
domain:spec#4, sessionsession_01HbmCEPMBmMLU3VZCEzfec7, 2026-10-26T16:48Z.Amendment 6418168409 set
Metadata-protocol: none. That is wrong. Check Changeset at4f5d2f0a(check-run 121702102787) measures moved authorable-surface shards (packages/spec/authorable-surface/api.json,system.json), and the gate reads a moved shard as a metadata-protocol change. The lines now read:Clause-②: yes (narrowing)
Metadata-protocol: narrowed
The level rises to at least
minoron each package the gate names. The dev re-grades the changeset; the seat patches the PR body.objectstack-fleet commentedon Oct 26, 2026
os-dev-report
{ "issue": 25785, "status": "done", "branch": "claude/project-thread-nvoyre", "head": "2cd96962", "pr": "https://github.com/objectstack-ai/objectstack/pull/26159", "session": "session_01Vy85beHdawtEtqNscYBy7V", "premise_still_valid": true, "summary": "Round 3, answering the seat's patch note on 4f5d2f0a (claim amendment 6421832617). The changeset now declares `Clause-②: yes (narrowing)` and `Metadata-protocol: narrowed` and ships @objectstack/spec and @objectstack/runtime at `minor`; both are the packages the gate names. The ADR-0087 marker stays `not-required (no-migration-prescription)`, and the gate accepts it under the new kind. Its reason is restated for `narrowed`: the narrowed face is a response that no stored metadata holds, and the authorable-surface keys this diff moves are additions, none removed or renamed. The remedy stays prose. No product code moved this round. Check Changeset is green at 48088279 and again at the head. The PR went conflicting twice while this round ran, so origin/main was merged twice (merges f5753454 and dca2e00c). The second merge resolved one real conflict: main's #25808 and this diff each add one Iso pin, so the count is now 791. Check-run state at 2cd96962: every check-run is green except `Type Check · workspace` and its roll-up `TypeScript Type Check`. Those two are #26288, and this diff tips that margin (see open_questions).", "tests": "At the head 2cd96962, under scripts/pm/os-verify-lock.sh, each exit code captured before any pipe; every VERDICT is command-exit 0. (1) @objectstack/spec full suite: 'Test Files 805 passed (805)', 'Tests 23257 passed | 1 todo (23258)'. That includes the Iso pin test at 791 and the dropped-refinements ledger at 246/843. (2) The six runtime i18n door files: 'Tests 103 passed (103)'. (3) spec and runtime type-check. (4) Console loader and i18n transform: 'Tests 22 passed (22)'. (5) The two ObjectSchema pins that were red on CI at 48088279, MetadataService.specKeyObjectPayload and MetadataService.retiredObjectEnabled: 'Test Files 2 passed (2)', 'Tests 25 passed (25)'. Check Changeset's local equivalent, offline with a pull_request payload, gives the same answers at 4c82d13f and at the head. `check-changeset-no-major --base origin/main --event` with a body declaring `narrowed` exits 0. With `none` it exits 1, refusing because authorable-surface api.json and system.json moved; that was the CI red. check-adr-0087-registration exits 0 (BREAKING+clause-②-narrowing+metadata-protocol-narrowed, not-required (no-migration-prescription)), and check-empty-changeset exits 0. CONTROL for the type-check red: this diff's three sources (translation.zod.ts, protocol.zod.ts, runtime i18n.ts) were reverted to main's, then spec and runtime were rebuilt. With that, plugin-hono-server `tsc --noEmit --extendedDiagnostics` passes at `--max-old-space-size=4096`, with 4,214,495K used and a 104.24 s check under GC pressure. At this diff's head the same command dies with 'JavaScript heap out of memory'. At 8192 MB the two trees read 4,752,303K (control) and 4,772,570K (head): +20 MB, +6,090 types, +25,110 instantiations. The sources were restored, `git diff HEAD` on them was empty, and spec and runtime were rebuilt.", "gates": "At 2cd96962: the derived list is 123 commands. All 123 ran with each exit code captured before any pipe, every one exited 0, and they reconcile: 'dispatch-gates --ran: 123 derived famil(ies) accounted for — 123 run, 0 NOT-MEASURED (a DERIVED zero — all 123 recorded an exit code and none of them is 3)'. Named receipts: check-adr-0087-registration 0, check-sdui-manifest 0 (the i18n record was re-recorded after each merge commit, 106 components unchanged), check:generated 0 (the os-regen deferral of content/docs/references/index.mdx was discharged in bf688dc9, and check-regen-pending was cleared), and check:type-check-debt under the lock ('1 ledger entr(ies) re-measured in 180.9s … none above its recorded number'). The same sweep also ran at 48088279 (125/125) and at ecf4c1e7 (123/123), all green. CI at 2cd96962, from the PR's check-runs: 61 of 63 are success or skipped. That includes Check Changeset, all eight Test Core shards, all sixteen Test UI shards, Type Check · source gates / consumer gates / debt ledger, Lint · ESLint, the Lint gate jobs, Build Core, Build Docs, Spec property liveness and Dogfood Regression Gate. Two are red: `Type Check · workspace` (job 121847327765) and its roll-up `TypeScript Type Check`. The job's only failure is '@objectstack/plugin-hono-server#typecheck … exited (134)', with no TS error in the log. It was the same at 48088279 (job 121721067561).", "dogfood_battery": "2cd96962 · closure built first (pnpm --filter '@objectstack/dogfood^...' build, VERDICT command-exit 0, 7m49s), then pnpm --filter @objectstack/dogfood test under the verify lock, with no OS_TEST_SHARD and no path · VERDICT command-exit 0 · Test Files 297 passed | 3 skipped (300) · Tests 2527 passed | 18 skipped (2545) · no failure to name. The lock was held for 22m58s. The same battery was green at 48088279 and at ecf4c1e7, with identical counts.", "line_budget": "716 changed lines (+685 / -31) over 22 files against the merge base 3249e204, the same size as round 2. main's merged commits are not this diff.", "deviations": [ "origin/main was merged three times this round, each time because the PR was conflicting or red from main. (1) 80441cdc: conflicting. The dropped-refinements header was recounted to 246/843. (2) f5753454: the two Test UI shards at 48088279 failed 'expected 48 to be 47' on ObjectSchema.shape. That came from main's 5e113b39 (#26005, which added `sharing`). main itself fixed it in a1477dec (#26231, 'Fixes #26218'), and this merge brought that fix in. (3) dca2e00c: conflicting again, in type-alias-convention.pin.test.ts and the i18n registry record. The pin count is now 790 → 791, with main's #25808 row first and this diff's row second. After every merge the i18n digest was re-recorded from a committed tree.", "The full dogfood battery and the gate sweep each ran three times, once at each head this round pushed, because each merge moved the head. All three runs were green. The final head is 2cd96962. origin/main had moved to 61ba04f6 (4 commits) by the push, and `git merge-tree` reports a clean merge." ], "mcp_calls": "23, all reads and no write tool. 11 came from rounds 1 and 2. This round: get_check_run x1 (121702102787); pull_request_read get x2 (#26159, of which one read mergeable_state 'dirty'); pull_request_read get_check_runs x2 (at 48088279 and at 2cd96962); get_job_logs x5 (121721067561, 121724040837, 121724040732, and 121847327765 twice); actions_list list_workflow_runs x1 (lint.yml on main, which was green at 4f7e0414); issue_read get x1 (#26288).", "api_writes": "6, all through the fleet relay: the 5 of rounds 1 and 2, plus this report (POST /issues/25785/comments). git push is not a REST write. This round's three pushes landed 48088279, ecf4c1e7 and 2cd96962.", "open_questions": [ { "question": "The `Type Check · workspace` lane is red at 2cd96962 from #26288's plugin-hono-server heap OOM, and the measurement says this diff tips it: main's declarations pass at 4096 MB with 4.21 GB used, and this diff adds about 20 MB. A maintainer re-run is therefore unlikely to go green. How should the PR clear the lane?", "options": [ "A: hold this PR until #26288's fix lands (skipLibCheck, or extending the base tsconfig, for plugin-hono-server; measured in #26288 at 872,405 KB peak). Then merge main and re-run.", "B: fold #26288's one-line tsconfig fix into this PR, on the seat's amendment of the claim surface.", "C: the maintainer re-runs the lane as the seat said, and the PR waits only if the re-run stays red." ], "recommendation": "A, because the fix is tooling owned by another card and lane. Folding it in would put a CI tsconfig change into a spec contract PR. The margin is shared with main, so any spec PR that adds declarations will hit the same wall until #26288 lands." } ], "out_of_scope_findings": [ "class: a · reach: CI `Type Check · workspace` on any PR that moves packages/spec · evidence: the control measurement above (+20 MB tips a 4096 MB heap) · dedupe: already filed as #26288 by the seat; this report adds a second data point, not a card · carrier: #26288" ] }Read at 2026-10-26T22:35Z.
Generated by Claude Code
objectstack-fleet commentedon Oct 27, 2026
os-dev-report
Landing head fec80c3 on PR #26159. This is origin/main merged in after #26356 fixed #26288; the diff is unchanged at +685/-31 over 22 files. CI: all 63 check-runs are success or skipped, including
Type Check · workspace,TypeScript Type Check,Check Changeset, Test Core 8/8 and Test UI 16/16. Locally at this head, under the verify lock, every VERDICT is 0: the dogfood battery is 298 passed and 3 skipped of 301 files, @objectstack/spec has 806/806 files, the runtime i18n door 103/103, the console i18n 22/22 and the two ObjectSchema pins 25/25. plugin-hono-server type-check, check:generated, check-sdui-manifest and the three changeset gates all exit 0. mcp_calls 24, all reads. api_writes 7, this comment included. The PR stays a draft.Generated by Claude Code
objectstack-fleet commentedon Oct 27, 2026
os-dev-report
The new head is 392a610: origin/main 7c34e5d merged as 41d06a4, plus one regeneration commit. CI: all 63 check-runs are success or skipped, including
Check Changeset,Type Check · workspace,TypeScript Type Check, Test Core 8/8 and Test UI 16/16. Conflict files and their resolutions:packages/spec/dropped-refinements.baseline.json: only the header conflicted. Main's 247/866, plus this diff's unchangedsystem/ServedTranslationDataentry (1 schema, 3 sites), gives 248/869, which is the count of the merged body. No entry changed.packages/spec/src/type-alias-convention.pin.test.ts: main's Seed datasets cannot carry a file: aField.filecolumn needs asys_fileid only an upload can mint, so a declarative seed either drops the row, breaks the ADR-0104 attestation, or inserts a dangling token silently #25779 row (SeedFilePathSchema, 790 → 791) stays first. This diff's row is renumbered 791 → 792, and the count reads 792 in the header comment, theittitle andtoHaveLength.scripts/sdui-manifest.sources/i18n.jsonwas a modify/delete conflict. Main retired the per-package records (ci(sdui): retire the per-package SDUI manifest records; CI's regeneration holds freshness (#26137 PR B) #26367), so I took the deletion. The diff loses that one digest line.packages/spec/authorable-surface/api.json,packages/spec/authorable-surface/system.jsonandcontent/docs/references/index.mdx. They are regenerated in 392a610, and the authorable-surface diff against main is exactly this diff's keys.Reviewed logic is untouched: main changed none of
protocol.zod.ts,translation.zod.tsor runtimei18n.ts, and this diff's hunks in them are byte-identical to fec80c3's. The one auto-merged file in scope,ui/packages/app-shell/.../metadata-form-i18n.ts, took main's edit on a different docblock line; this diff's bullet is unchanged. The diff is now 21 files, +684/-30.Locally at 392a610, under the verify lock, every VERDICT is 0. The dogfood battery is 301 passed and 3 skipped of 304 files. The other suites:
check:generated, check-regen-pending and the three changeset gates all exit 0. mcp_calls 25, all reads. api_writes 8, this comment included. The PR stays a draft.
Generated by Claude Code
objectstack-fleet commentedon Oct 27, 2026
Landing — seat
domain:spec#4, sessionsession_01HbmCEPMBmMLU3VZCEzfec7, 2026-10-27T11:57Z.392a610aorigin/mainb49b752d fix(i18n)!: the console translation bundle leaves out Studio's metadataForms (75 KB of 221 KB on app-crm) (#26159)Fixesclosed the card ascompleted. In this stroke the seat removespm:dispatched.