Description
domain:server#2 · os-project-manager · session_0186vfjHHMsRXC9EUT9hTFMo
Filing gate: ① a product defect, measured, found by the #28779 dev at the seat's request (os-dev-report 6563592889, PR #28800). Filed by domain:server seat 2. ⛔ Not a claim. Graded by this seat p2 under 「定级你可以自己决定」 (Leehom, 2026-11-01): a customer customization that saves and reads back but is never used, child of epic #28236's override line.
Reach: a customer who adds a locale to a vendor email template in the <base>.custom pair without overrides (admitted since PR #28777), e.g. fr-FR for showcase_task_done_email, which the base ships only in en-US.
What happens (measured on the showcase, main 8f294e04)
- The save and the publish answer 200; the by-name read returns the
fr-FRbody. GET /meta/email_template,?package=<base>and the execution list (getMetaItemsForExecution) do not carry it: the environment-wide list narrows at name grain to the one package that ships the name.- So
renderTemplate(…, locale: fr-FR)renders the base'sen-US. The customization is read but never sent. - The same list seam also decides what happens to a dependent package's added locale under a base template's name (metadata-protocol: measure what the base-named read serves when only a dependent package holds an email-template locale under the base's name (#28746 follow-up) #28779, evidence on docs(adr): ADR-0146 amendment — only the paired
<base>.customdeclares an override; a dependent package adds under its own names (ruled A, withdraws rider 3) #283906563574978): today the base address and the package-less read serve it, stamped with the dependent's id, while the lists and the send path drop it.
Wanted (seat's pick: option A of the #28779 report)
Member-grain coexistence, matching ADR-0146 D2 ("a dependent adds items under its own names") and the ruling A recorded on #28390:
- the base address (lists, by-name reads, the execution list) serves the base's members, the pair's declared overrides and the pair's own added members, so a pair-added locale is listed and sent;
- a dependent's added member is served only under
?package=<dependent>; the base-named and package-less by-name reads stop falling through to it.
⛔ Not option B (a dependent's member joining the base bundle: the silent-contribution shape #28390 reserves). Tests: a pair-added fr-FR is listed under the base and renderTemplate fr-FR renders it; a dependent's fr-FR is not served on the base address; the base's own en-US and a pair override of en-US unchanged. PR #28800's shape pin flips with this card.
Dedupe: searched email_template locale list soleShippingPackage member grain, custom addition never sent, getMetaItemsForExecution fr-FR; none.
Links back: #28779, #28746, PR #28777, PR #28800, #28390, epic #28236.
Generated by Claude Code
Activity
objectstack-fleet commentedon Nov 1, 2026
domain:server#2 · os-project-manager · session_0186vfjHHMsRXC9EUT9hTFMo
Claim: PM loop round 4 · card thread · 2026-11-01T20:45Z
Session:
session_0186vfjHHMsRXC9EUT9hTFMo(the seat); the card thread issession_01FEkQ5m2Ryfx2Wubuz716mwAccount:
os-project-manager(the seat's linked user; the card's assignee)Branch:
claude/project-thread-p5198q(the card thread's harness-pinned branch; it names no issue, so this claim is the identity record)Worktree: the card thread's own container checkout
Domain:
domain:serverSeat:
domain:server#2Ruling-ref: the maintainer, 2026-11-01T03:46Z: 「server 车道现在就是你负责,任务有一大堆啊,都可以派,包括 p3」, with 2026-10-26T10:29Z 「p1 p2 处理完了,就可以处理 p3」. With 2026-11-01T12:11Z 「定级你可以自己决定」; graded p2 by this seat at filing. Seat's pick: option A (member-grain coexistence); not B, not C; PR #28777's write gate unchanged.
File surface: the base-address list and by-name read paths and the execution list in
packages/metadata-protocol/src/andpackages/objectql/src/registry.ts(bundle types from the registry's key table only); PR #28800's shape pin flipped to the behaviour; dogfood and unit tests; changesetContainer & model:
M,mode:thread,model: opus(--tiernames no path mandate: PM's call, default),effort: highClause-②: yes (narrowing) expected — the pair-added locale starts being served (widening, stated in prose), a dependent's member stops being served on the base address; the dev measures and declares
Metadata-protocol: narrowed (expected; a dependent's added member stops being served on the base address; the dev measures and declares)
Responsibility: the dev serves pair-added bundle members on the base address and keeps a dependent's added member under its own package, red first, with ablation; the seat runs the contract review and lands
Thread-read: none
Premise: named by the #28779 measurement (report 6563592889, options A/B/C); option A picked by this seat
Serial constraints cleared: PR #28777 merged (
5bb7834a); PR #28800 (the shape pin this card flips) in auto-merge — rebase on it once merged; overlap re-read before pr_createResume-from: none — fresh from
origin/mainState: →
pm:dispatched, assigned toos-project-manager, recorded by this claim.Generated by Claude Code
objectstack-fleet commentedon Nov 1, 2026
domain:server#2 · os-project-manager · session_01FEkQ5m2Ryfx2Wubuz716mw
os-dev-report
{
"issue": 28802,
"status": "done",
"branch": "claude/project-thread-p5198q",
"pr": "#28828",
"session": "session_01FEkQ5m2Ryfx2Wubuz716mw",
"premise_still_valid": true,
"summary": "Option A (member-grain coexistence) on a base's address, bundle types only (ITEM_KEY_DISCRIMINATORS, email_template its one entry). metadata-protocol: the env-wide narrowing keeps the sole shipper's pair-added members (a member the base does not ship); the list scoped to the base keeps the pair's held stand-in at such a member; the by-name read serves the pair's own stored row at such a member and guards the registry's cross-package last tier so a dependent's member is no longer answered on the base's address (a no-member read falls back to the base's own canonical-first member). Pure helper baseAddressServesMember in protocol-environment-rows.ts. So a pair-added fr-FR is listed, executed and sent; a dependent's fr-FR is 404 on the base-named and package-less reads and served under the dependent. PR #28800's shape pin is flipped (cases renamed, second describe for the pair addition). Measured mechanism differs from the order in one place: with the pair's and a dependent's fr-FR both stored the registry holds one entry for that member (last hydration wins), so the pair's member is read from its stored row, not the registry.",
"tests": "Dogfood email-template-dependent-unshipped-locale-read.dogfood.test.ts: RED on main c064d3a 4 failed / 6 passed; GREEN at f085057 10/10 (os-verify-lock VERDICT command-exit 0). New objectql src/protocol-bundle-member-base-address.test.ts: RED 5/5 with the base's metadata-protocol src rebuilt; GREEN 5/5 at f085057. metadata-protocol typecheck+test: 296 files passed 4 skipped, 22068 tests passed. objectql typecheck+test: 520 files, 9988 tests passed. Ablations via ablation-replace.mjs (anchor 1->0, restore blob == HEAD verified) + metadata-protocol rebuild + ablation-dist-preflight --absent, both files per leg: A1 drop member-grain list change -> unit 3 red (pair-addition cases), dogfood 2 red (pair lists/send, pair beside dependent), dependent cases green; A2 drop by-name registry guard -> unit 2 red (dependent 404, no-member read), dogfood 2 red (dependent-on-base cases), pair cases green; A3 drop pair stored-row read -> unit 1 red, dogfood 1 red, both pair-beside-dependent only. First A1 attempt measured nothing (if(false) replacements failed the DTS build); re-run with type-neutral replacements.",
"gates": "Local at f085057: dispatch-gates --commands derived 66; 66 run; 65 exit 0 first time; check:dual-build-cjs-loads exit 3 (7 packages outside the dogfood closure unbuilt), built under the lock, re-run exit 0. dispatch-gates --ran on pm-orders/server/28802-gates-ran.txt: 66 derived, 66 run, 0 NOT-MEASURED (derived zero), exit 0. CI on 28828 at f085057 read 2026-11-01T22:13Z: skipped Schedule gate, 18.x upgrade harness (opt-in), Packed-tarball smoke (opt-in); in_progress Type Check (debt ledger, source gates, workspace), Lint (repo and tooling, PM dispatch-gates, ESLint, docs and code guards, scoped query-options erasure, scoped slot lookup, scoped tooling self-tests, CI release and engine), Flag docs, Governed Surface Queue Guard, filter, Spec property liveness, Check PR Size, PR-body guards, Check Changeset; queued Type Check consumer gates.",
"dogfood_battery": "f085057c · os-verify-lock: VERDICT command-exit 0 · held the lock 1718s · Test Files 380 passed | 3 skipped (383) · Tests 3118 passed | 28 skipped (3146) · no failures",
"mcp_calls": "7 — read tools only: issue_read x4 (get 28802, get_comments 28779, get_comments 28802, get 28778), pull_request_read x2 (get 28800, get_check_runs 28828), list_pull_requests x1 (overlap read). 0 write tools.",
"api_writes": "0 direct REST writes. Relay: pr_create via fleet-write (run 41355894672, PR 28828, 10729 bytes sent = stored, no labels, no assignees); this os-dev-report comment on #28802 via post-stamped. git push x1 (claude/project-thread-p5198q at f085057).",
"open_questions": [
{
"question": "Metadata-protocol kind: the claim expected narrowed; measured semantic (no key, value or write refused; the meaning of a written dependent or pair locale on the base's address changed). Accept semantic?",
"options": [
"A semantic as declared (minor either way)",
"B narrowed, if the seat reads a member no longer served as a requirement tightened"
],
"recommendation": "A, because AGENTS.md defines narrowed as a key removed, a value refused or a requirement tightened at authoring, and nothing an author writes is refused here."
}
],
"out_of_scope_findings": [
"class: none (dormant) · reach: none measured · previewDrafts by-name read of a pair-added member on the base's address falls through to the active pair row (preview arm asks served-row candidates only) · carrier: none · noted in PR Acceptance notes",
"Skills-docs follow-up owed: skills/objectstack-platform/SKILL.md, content/docs/concepts/metadata-lifecycle.mdx (a pair-added locale is listed and sent on the base's address; a dependent's same-named locale stays under the dependent) · carrier: seat 2 (may fold into #28778 / PR #28814)"
]
}
Generated by Claude Code
objectstack-fleet commentedon Nov 1, 2026
domain:server#2 · os-project-manager · session_0186vfjHHMsRXC9EUT9hTFMo
Landing record · #28802 · PR #28828
domain:serverseat 2 ·session_0186vfjHHMsRXC9EUT9hTFMo· 2026-11-01T23:18Z1920e480git merge-base --is-ancestor 1920e480 origin/maingit ls-remote origin refs/heads/gh-readonly-queue/*matching 28828git grep -c registryMemberServedAt origin/main -- packages/metadata-protocol/src/protocol.ts<base>.custompair is read by name but never listed or sent, so a send in that locale renders the base's (#28779 follow-up) #28802, Fixes metadata-protocol: measure what the base-named read serves when only a dependent package holds an email-template locale under the base's name (#28746 follow-up) #28779): an email template locale added in a<base>.custompair is now listed on the base's address, carried by the execution list and used by a send in that locale. A locale another package adds under the base template's name is served only under that package's own address; the base-named and package-less reads no longer answer it.?package=<pair>lists.@objectstack/metadata-protocolminor (Clause-②: yes (narrowing),Metadata-protocol: semantic).<base>.custompair adds, while the list, by-name and send serve it (#28802 follow-up, ADR-0146 D8) #28830 (the layered read, this seat), metadata-protocol: the per-package layer stamps another package's row under a base item name with the base's_packageId(export and form withdrawal layer name the wrong author) #28831 (per-package layer provenance, seat 1).Release: claim
6563657135(session_01FEkQ5m2Ryfx2Wubuz716mw, branchclaude/project-thread-p5198q) · landed. #28779's measurement record closes with it.pm:dispatchedremoved; assignee cleared; both cards closed on merge.Generated by Claude Code