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
Metadata API: no batch by-names read, so the Console roster gate costs one /meta/object request per name #29236
Filing gate: ② out-of-scope finding, class a, from #29121 (PR #29229; report card comment 6574295250) · filed by domain:ui#1 · ⛔ Not a claim. No grade: triage sets it.
Business reason. After #29121, Console Home stops downloading the whole object registry. Instead it reads each object the app roster requires by name, one request per name: 8 requests on app-crm on every Home visit outside an app. A larger app means more round trips, and each one costs a full latency on a phone link. A single batch read would make it one request.
Measured (the #29121 dev, on the production Console with app-crm, at PR #29229 head d8b43ffa). The branch sends 28 requests in total, with no unscoped object or view list. 11 of them are by-name reads, 70 KB in all, and 8 of those are the roster gate's requiresObject union.
Wanted. The metadata list endpoint for a type (/meta/object, and generically /meta/:type) accepts a names filter, for example ?names=a,b,c, and answers only those items. The UI can then fold the roster gate's reads into one request. If this adds a query parameter to the published API, the change is a spec and API matter, so the reader decides the protocol declaration.
Reader. Server metadata API (domain:server); the Console adopts it as a follow-up in domain:ui.
Claim: PM loop round 8 · card thread · 2026-11-02T11:40Z
Session: session_01ADHkmQKwKFCp1m6Pb6Q8c1 (the seat); the card thread is named in a follow-up claim once it reports its branch
Account: os-steve (the seat's linked user; the card's assignee)
Branch: pending — the card thread's harness-pinned branch, written into a follow-up claim before the dev starts
Worktree: the card thread's own container checkout
Domain: domain:server
Seat: domain:server#5
Ruling-ref: no maintainer ruling on this card; triage grade p2 (6575623583: first check whether the existing list filter already serves a by-names read; a new query key is a protocol addition whose name goes to the maintainer before any code).
File surface: measurement of the /api/v1/meta/:type list door (packages/rest, packages/metadata-protocol); at most one test pinning an existing filter spelling. ⛔ No new query key or route, no packages/spec/**: a new key stops with needs_decision.
Container & model: S, mode:thread, model: the thread's default judgement tier, effort: medium (p2)
Clause-②: no
Metadata-protocol: none
Responsibility: the code is the metadata list door · the Console roster gate reads each required object by name, one request per name, because no batch by-names read is known · reached by every Console Home visit outside an app
Thread-read: 6575623583
Premise: holds as filed (PR #29046, merged, refuses bracketed ?id[]= on GET /meta/app; whether another spelling selects by names is what the dev measures on origin/main31826d3318)
Serial constraints cleared: measurement only; a pin-only PR touches no source.
Resume-from: none — fresh from origin/main
State: pm:queue → pm:dispatched, assigned to os-steve, recorded by this claim.
Claim: PM loop round 8 · card thread · branch named · 2026-11-02T11:45Z (supersedes 6576235563, which had the branch pending)
Session: session_01ADHkmQKwKFCp1m6Pb6Q8c1 (the seat); the card thread is session_01ADHkmNqzH9zZjokhM7K3u3
Account: os-steve (the seat's linked user; the card's assignee)
Branch: claude/project-thread-ddr31t (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:server
Seat: domain:server#5
Ruling-ref: no maintainer ruling on this card; triage grade p2 (6575623583: first check whether the existing list filter already serves a by-names read; a new query key is a protocol addition whose name goes to the maintainer before any code).
File surface: measurement of the /api/v1/meta/:type list door (packages/rest, packages/metadata-protocol); at most one test pinning an existing filter spelling. ⛔ No new query key or route, no packages/spec/**: a new key stops with needs_decision.
Container & model: S, mode:thread, model: the thread's default judgement tier, effort: medium (p2)
Clause-②: no
Metadata-protocol: none
Responsibility: the code is the metadata list door · the Console roster gate reads each required object by name, one request per name, because no batch by-names read is known · reached by every Console Home visit outside an app
Thread-read: 6576235563
Premise: holds as filed (PR #29046, merged, refuses bracketed ?id[]= on GET /meta/app; whether another spelling selects by names is what the dev measures on origin/main31826d3318)
Serial constraints cleared: measurement only; a pin-only PR touches no source.
Resume-from: none — fresh from origin/main
State: pm:queue → pm:dispatched, assigned to os-steve, recorded by this claim.
{
"issue": 29236,
"status": "needs_decision",
"branch": "claude/project-thread-ddr31t",
"pr": null,
"session": "session_01ADHkmNqzH9zZjokhM7K3u3",
"premise_still_valid": true,
"summary": "Measured on origin/main a19759ac (code) and a showcase boot of that tree: no existing spelling on the GET /meta/:type list door selects items by name for object or any type but app. The list door reads exactly five keys (META_QUERY_ARITY_DOORS.list: package, preview, object, include, id); id narrows only metaType app, to exactly one name; object narrows only view (by bound object, not by item name). Every other key is silently ignored (the route declares no closed set), so ?names= / ?name= / ?ids= / ?filter= / ?id[]= on /meta/object all answer the full 115-item, 746 KB list with 200; repeated ?id= is a 400 arity refusal on every type. The store read (getMetaItems -> readFlattenedMetaItems) loads the whole type list; GetMetaItemsRequestSchema has no names member. A batch by-names read therefore needs a new query key: stopping with needs_decision, no code, no PR.",
"tests": "Showcase boot (examples/app-showcase `objectstack dev --seed-admin --fresh -p 38917`, signed in as the seeded admin), each GET /api/v1/meta/...: object -> 200 746514B n=115; object?id=showcase_account -> same 746514B n=115; object?name=, ?names=showcase_account,showcase_contact, ?ids=, ?id[]=, ?filter= -> each 200 746514B n=115; object?id=a&id=b -> 400 VALIDATION_ERROR (id supplied 2 times); view -> 200 24009B n=36, view?names=x and view?id=x -> same n=36; app -> n=3; app?id=showcase_app -> 200 7368B n=1; app?id=a&id=b -> 400; app?id[]=showcase -> 400 bracketed-id refusal; app?names=showcase -> n=3 (ignored). By-name reads for comparison: object/showcase_account 10174B, object/showcase_contact 5875B. App bundle /meta/app/showcase_app/bundle 301937B. Build: turbo build --filter=@objectstack/example-showcase... under os-verify-lock, VERDICT command-exit 0 (132s). Server killed by its recorded PID, port confirmed free.",
"gates": "none: no diff, no PR (dispatch-gates not run: empty change set).",
"dogfood_battery": "n/a: no PR",
"mcp_calls": "2: mcp__github__issue_read get, mcp__github__issue_read get_comments (reads only)",
"api_writes": "1: this os-dev-report comment on #29236 via post-stamped.mjs",
"files_changed": [],
"line_budget": "n/a: no diff",
"deviations": [
"Booted the showcase through its own package dev script (cd examples/app-showcase; pnpm dev --fresh -p 38917) instead of root `pnpm dev`: root dev's check-dev-prereqs refuses until all 106 workspace packages (35 ui/ packages) have dist; the showcase closure itself was built by turbo first. Measurement only, no code ran from an unbuilt package."
],
"open_questions": [
{
"question": "Which spelling serves a batch by-names list read on GET /meta/:type (protocol addition, maintainer names it)?",
"options": [
"A ?names=a,b,c on every /meta/:type list: one comma-separated value (fits the existing arity rule that refuses a repeated key; machine names are snake_case so a comma never occurs in a name). Narrowing step in createMetaListAnswer after the per-caller gate and before the object mask, so masking and translation run only on the named items; empty value refused 400 like ?id=; unknown names simply absent (no 404). Pushed down to the store read as GetMetaItemsRequest.names so the protocol filters before decorating. Files: packages/spec/src/api/protocol.zod.ts (GetMetaItemsRequestSchema + gen:schema/gen:docs/api-surface artifacts), packages/rest/src/meta-item-read-gate.ts (META_QUERY_ARITY_DOORS.list, the chain step, the empty refusal), packages/rest/src/meta-collection-routes.ts (listRequest), packages/runtime/src/domains/meta.ts (dispatcher twin pass-through; meta-list-projection-parity.test.ts census), packages/metadata-protocol/src/protocol.ts (readFlattenedMetaItems filter), packages/client/src/index.ts (meta.getItems options). Size ~150-250 src lines + tests; minor changeset on spec/rest/metadata-protocol/client; Metadata-protocol: none (API, not authorable metadata) but Clause-2 wording to be set by the seat.",
"B Same key, chain-only: narrow in createMetaListAnswer (rest + runtime parity), no spec/store change. Smaller (~60 src lines + tests) and fixes the wire cost (746 KB -> only the named items), but the server still reads the full type list per request.",
"C Generalise the existing ?id= to every type and accept a comma list: reuses a known key but changes its meaning on app (today exactly one name) and collides with the bracketed-id refusal PR #29046 just shipped.",
"D Add no key: the Console keeps one by-name read per required object (8 on app-crm)."
],
"recommendation": "A, because it fixes both the round trips and the server-side full-list read, keeps one spelling for every type, fits the arity and empty-value rules the door already has, and leaves ?id='s just-shipped one-app meaning alone. If the maintainer wants the smallest step first, B now and the store push-down later is a clean split."
}
],
"security_findings": "none",
"out_of_scope_findings": [
"carrier: the names decision on this card · noted, not filed: GET /meta/:type declares no closed query-parameter set (AGENTS.md Route & surface ownership 5; existing routes convert per lane), so a misspelt filter (?names= today, or ?id= on any type but app) answers the full list with 200, indistinguishable from a real answer. Adding the new key is the natural moment to declare the list's closed set (refuseUnknownQueryParams with package, preview, object, include, id, the new key)."
]
}
The dev measured first and stopped with needs_decision (report 6576480506, at 2026-11-02T11:53Z). No existing spelling on GET /meta/:type selects list items by name, except ?id= on app, which takes exactly one name. A batch by-names read therefore needs a new public query key. Naming a public API key is the maintainer's call. The card thread is parked on claude/project-thread-ddr31t with no diff and no PR.
The question (maintainer):
A (seat recommends): add ?names=a,b,c on every /meta/:type list, as one comma-separated value. Narrow after the per-caller gate and push the filter down to the store read (GetMetaItemsRequest.names), so masking and translation run only on the named items. An empty value is refused with 400, and an unknown name is simply absent. This adds to the protocol: a spec, rest, metadata-protocol and client minor, about 150–250 source lines plus tests. The spec part goes to the spec lane first.
B: the same key, narrowed in the rest chain only, with no spec or store change (about 60 lines). It fixes the wire cost, but the server still reads the full list.
D: add no key. The Console keeps one request per name (8 on app-crm).
Why A: one spelling for every type. It fits the door's existing arity and empty-value rules, fixes both the round trips and the server's full-list read, and leaves ?id= alone. Adding the key is also the natural moment to declare the list door's closed set of query parameters (the dev's out-of-scope note).
State: pm:dispatched → needs-user-decision. The card thread stays parked until the ruling.
A — ?names=a,b,c on every /meta/:type list. One comma-separated value (the data routes' convention for fields, searchFields, orderby; it fits the door's arity rule that refuses a repeated key). The narrowing step runs after the per-caller gate and before the object mask, so masking and translation run only on the named items. An empty value is refused 400 like ?id=; an unknown name is simply absent (no 404). The filter is pushed down to the store read as GetMetaItemsRequest.names, so the protocol filters before decorating.
The same server PR declares the list door's closed set of query parameters (package, preview, object, include, id, names) with the refuseUnknownQueryParams pattern the sibling meta routes already use, so a misspelt filter answers 400 instead of the full list with 200. That is a narrowing; the seat states it on the changeset (Clause-②).
Release: session_01ADHkmQKwKFCp1m6Pb6Q8c1 · seat 5 signs off at the maintainer's wrap-up · to pm:blocked for the next domain:server seat
Resume-from: none (the card thread pushed no branch; it stopped at measurement)
Blocked-by: #29441
The dev's needs_decision (6576480506) was ruled: director ruling A (6580261740), which the seat executed in 6580443235. The spec half is #29441 (GetMetaItemsRequestSchema.names, spec lane, still open). This card is the server half and waits on that merge, so it goes to pm:blocked, not to the decision box: there is no open question.
Next: when #29441 merges, move this card to pm:queue. The next seat dispatches it under ruling A, serving ?names= on every /meta/:type list.
Spec half of ruling A (6580261740): PR #29722 for #29441, contract review PASS (6594380969 on 064d4e01, delta on bb07931c), landing now. Two things the server PR on this card inherits; the next domain:server seat's claim should name both.
Drop the marker in the serving change.GetMetaItemsRequestSchema.names ships with a describe that opens [PLANNED — not yet served] and ends "No list door reads it yet: until one does, a request carrying it is answered as if it were absent." A pin in packages/spec/src/api/protocol.test.ts asserts that prefix, so the PR that serves ?names= must, in the same change, remove the prefix and the trailing sentence, delete that one it(...), and run gen:docs (moves content/docs/references/api/protocol.mdx). That is one packages/spec edit outside the rest / runtime / metadata-protocol / client workload the ruling lists.
Blocker landed.#29441 closed: PR #29722 merged (6f094645), so GetMetaItemsRequestSchema.names is on main with the [PLANNED — not yet served] marker. This card's Blocked-by: #29441 (6591626191) is met; the pm:blocked → pm:queue flip and the pm:blocking sweep on #29441 are the triage sweep's. The serving PR carries the two items in 6594515725.
Activity
objectstack-fleet commentedon Nov 2, 2026
triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U
Path: none
Triage: p2 ·
pm:queue· 2026-11-02T11:07Z⛔ Not a claim.
?id[]=, see Metadata API: GET /api/v1/meta/app?id[]=NAME (bracketed array spelling) ignores the filter and answers the caller's full app list #28930 / PR fix(rest)!: GET /meta/app refuses a bracketed id key (?id[]=, ?id[0]=) instead of answering every app #29046) already serves this. Only if a new query key is needed does it become a protocol addition: then p1, and the new name goes to the maintainer before any code.Generated by Claude Code
objectstack-fleet commentedon Nov 2, 2026
domain:server#5 · os-steve · session_01ADHkmQKwKFCp1m6Pb6Q8c1
Claim: PM loop round 8 · card thread · 2026-11-02T11:40Z
Session:
session_01ADHkmQKwKFCp1m6Pb6Q8c1(the seat); the card thread is named in a follow-up claim once it reports its branchAccount:
os-steve(the seat's linked user; the card's assignee)Branch: pending — the card thread's harness-pinned branch, written into a follow-up claim before the dev starts
Worktree: the card thread's own container checkout
Domain:
domain:serverSeat:
domain:server#5Ruling-ref: no maintainer ruling on this card; triage grade p2 (6575623583: first check whether the existing list filter already serves a by-names read; a new query key is a protocol addition whose name goes to the maintainer before any code).
File surface: measurement of the
/api/v1/meta/:typelist door (packages/rest,packages/metadata-protocol); at most one test pinning an existing filter spelling. ⛔ No new query key or route, nopackages/spec/**: a new key stops with needs_decision.Container & model:
S,mode:thread, model: the thread's default judgement tier,effort: medium(p2)Clause-②: no
Metadata-protocol: none
Responsibility: the code is the metadata list door · the Console roster gate reads each required object by name, one request per name, because no batch by-names read is known · reached by every Console Home visit outside an app
Thread-read: 6575623583
Premise: holds as filed (PR #29046, merged, refuses bracketed
?id[]=onGET /meta/app; whether another spelling selects by names is what the dev measures onorigin/main31826d3318)Serial constraints cleared: measurement only; a pin-only PR touches no source.
Resume-from: none — fresh from
origin/mainState:
pm:queue→pm:dispatched, assigned toos-steve, recorded by this claim.objectstack-fleet commentedon Nov 2, 2026
domain:server#5 · os-steve · session_01ADHkmQKwKFCp1m6Pb6Q8c1
Claim: PM loop round 8 · card thread · branch named · 2026-11-02T11:45Z (supersedes 6576235563, which had the branch pending)
Session:
session_01ADHkmQKwKFCp1m6Pb6Q8c1(the seat); the card thread issession_01ADHkmNqzH9zZjokhM7K3u3Account:
os-steve(the seat's linked user; the card's assignee)Branch:
claude/project-thread-ddr31t(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#5Ruling-ref: no maintainer ruling on this card; triage grade p2 (6575623583: first check whether the existing list filter already serves a by-names read; a new query key is a protocol addition whose name goes to the maintainer before any code).
File surface: measurement of the
/api/v1/meta/:typelist door (packages/rest,packages/metadata-protocol); at most one test pinning an existing filter spelling. ⛔ No new query key or route, nopackages/spec/**: a new key stops with needs_decision.Container & model:
S,mode:thread, model: the thread's default judgement tier,effort: medium(p2)Clause-②: no
Metadata-protocol: none
Responsibility: the code is the metadata list door · the Console roster gate reads each required object by name, one request per name, because no batch by-names read is known · reached by every Console Home visit outside an app
Thread-read: 6576235563
Premise: holds as filed (PR #29046, merged, refuses bracketed
?id[]=onGET /meta/app; whether another spelling selects by names is what the dev measures onorigin/main31826d3318)Serial constraints cleared: measurement only; a pin-only PR touches no source.
Resume-from: none — fresh from
origin/mainState:
pm:queue→pm:dispatched, assigned toos-steve, recorded by this claim.objectstack-fleet commentedon Nov 2, 2026
domain:server#5 · os-steve · session_01ADHkmNqzH9zZjokhM7K3u3
os-dev-report
{ "issue": 29236, "status": "needs_decision", "branch": "claude/project-thread-ddr31t", "pr": null, "session": "session_01ADHkmNqzH9zZjokhM7K3u3", "premise_still_valid": true, "summary": "Measured on origin/main a19759ac (code) and a showcase boot of that tree: no existing spelling on the GET /meta/:type list door selects items by name for object or any type but app. The list door reads exactly five keys (META_QUERY_ARITY_DOORS.list: package, preview, object, include, id); id narrows only metaType app, to exactly one name; object narrows only view (by bound object, not by item name). Every other key is silently ignored (the route declares no closed set), so ?names= / ?name= / ?ids= / ?filter= / ?id[]= on /meta/object all answer the full 115-item, 746 KB list with 200; repeated ?id= is a 400 arity refusal on every type. The store read (getMetaItems -> readFlattenedMetaItems) loads the whole type list; GetMetaItemsRequestSchema has no names member. A batch by-names read therefore needs a new query key: stopping with needs_decision, no code, no PR.", "tests": "Showcase boot (examples/app-showcase `objectstack dev --seed-admin --fresh -p 38917`, signed in as the seeded admin), each GET /api/v1/meta/...: object -> 200 746514B n=115; object?id=showcase_account -> same 746514B n=115; object?name=, ?names=showcase_account,showcase_contact, ?ids=, ?id[]=, ?filter= -> each 200 746514B n=115; object?id=a&id=b -> 400 VALIDATION_ERROR (id supplied 2 times); view -> 200 24009B n=36, view?names=x and view?id=x -> same n=36; app -> n=3; app?id=showcase_app -> 200 7368B n=1; app?id=a&id=b -> 400; app?id[]=showcase -> 400 bracketed-id refusal; app?names=showcase -> n=3 (ignored). By-name reads for comparison: object/showcase_account 10174B, object/showcase_contact 5875B. App bundle /meta/app/showcase_app/bundle 301937B. Build: turbo build --filter=@objectstack/example-showcase... under os-verify-lock, VERDICT command-exit 0 (132s). Server killed by its recorded PID, port confirmed free.", "gates": "none: no diff, no PR (dispatch-gates not run: empty change set).", "dogfood_battery": "n/a: no PR", "mcp_calls": "2: mcp__github__issue_read get, mcp__github__issue_read get_comments (reads only)", "api_writes": "1: this os-dev-report comment on #29236 via post-stamped.mjs", "files_changed": [], "line_budget": "n/a: no diff", "deviations": [ "Booted the showcase through its own package dev script (cd examples/app-showcase; pnpm dev --fresh -p 38917) instead of root `pnpm dev`: root dev's check-dev-prereqs refuses until all 106 workspace packages (35 ui/ packages) have dist; the showcase closure itself was built by turbo first. Measurement only, no code ran from an unbuilt package." ], "open_questions": [ { "question": "Which spelling serves a batch by-names list read on GET /meta/:type (protocol addition, maintainer names it)?", "options": [ "A ?names=a,b,c on every /meta/:type list: one comma-separated value (fits the existing arity rule that refuses a repeated key; machine names are snake_case so a comma never occurs in a name). Narrowing step in createMetaListAnswer after the per-caller gate and before the object mask, so masking and translation run only on the named items; empty value refused 400 like ?id=; unknown names simply absent (no 404). Pushed down to the store read as GetMetaItemsRequest.names so the protocol filters before decorating. Files: packages/spec/src/api/protocol.zod.ts (GetMetaItemsRequestSchema + gen:schema/gen:docs/api-surface artifacts), packages/rest/src/meta-item-read-gate.ts (META_QUERY_ARITY_DOORS.list, the chain step, the empty refusal), packages/rest/src/meta-collection-routes.ts (listRequest), packages/runtime/src/domains/meta.ts (dispatcher twin pass-through; meta-list-projection-parity.test.ts census), packages/metadata-protocol/src/protocol.ts (readFlattenedMetaItems filter), packages/client/src/index.ts (meta.getItems options). Size ~150-250 src lines + tests; minor changeset on spec/rest/metadata-protocol/client; Metadata-protocol: none (API, not authorable metadata) but Clause-2 wording to be set by the seat.", "B Same key, chain-only: narrow in createMetaListAnswer (rest + runtime parity), no spec/store change. Smaller (~60 src lines + tests) and fixes the wire cost (746 KB -> only the named items), but the server still reads the full type list per request.", "C Generalise the existing ?id= to every type and accept a comma list: reuses a known key but changes its meaning on app (today exactly one name) and collides with the bracketed-id refusal PR #29046 just shipped.", "D Add no key: the Console keeps one by-name read per required object (8 on app-crm)." ], "recommendation": "A, because it fixes both the round trips and the server-side full-list read, keeps one spelling for every type, fits the arity and empty-value rules the door already has, and leaves ?id='s just-shipped one-app meaning alone. If the maintainer wants the smallest step first, B now and the store push-down later is a clean split." } ], "security_findings": "none", "out_of_scope_findings": [ "carrier: the names decision on this card · noted, not filed: GET /meta/:type declares no closed query-parameter set (AGENTS.md Route & surface ownership 5; existing routes convert per lane), so a misspelt filter (?names= today, or ?id= on any type but app) answers the full list with 200, indistinguishable from a real answer. Adding the new key is the natural moment to declare the list's closed set (refuseUnknownQueryParams with package, preview, object, include, id, the new key)." ] }Stamped 2026-11-02T11:53Z.
Generated by Claude Code
objectstack-fleet commentedon Nov 2, 2026
domain:server#5 · os-steve · session_01ADHkmQKwKFCp1m6Pb6Q8c1
Needs decision · #29236 · 2026-11-02T14:37Z
The dev measured first and stopped with
needs_decision(report 6576480506, at 2026-11-02T11:53Z). No existing spelling onGET /meta/:typeselects list items by name, except?id=onapp, which takes exactly one name. A batch by-names read therefore needs a new public query key. Naming a public API key is the maintainer's call. The card thread is parked onclaude/project-thread-ddr31twith no diff and no PR.The question (maintainer):
?names=a,b,con every/meta/:typelist, as one comma-separated value. Narrow after the per-caller gate and push the filter down to the store read (GetMetaItemsRequest.names), so masking and translation run only on the named items. An empty value is refused with 400, and an unknown name is simply absent. This adds to the protocol: a spec, rest, metadata-protocol and client minor, about 150–250 source lines plus tests. The spec part goes to the spec lane first.?id=to every type and accept a list. This changes?id='s meaning onappand collides with the bracketed-id refusal fix(rest)!: GET /meta/app refuses a bracketed id key (?id[]=, ?id[0]=) instead of answering every app #29046 just shipped.Why A: one spelling for every type. It fits the door's existing arity and empty-value rules, fixes both the round trips and the server's full-list read, and leaves
?id=alone. Adding the key is also the natural moment to declare the list door's closed set of query parameters (the dev's out-of-scope note).State:
pm:dispatched→needs-user-decision. The card thread stays parked until the ruling.zhuangjianguo commentedon Nov 2, 2026
Brief-claimed-by: session_01QsR2jV5sBSzCYNEDgpYLJw · batch #458 · 2026-11-02T14:50Z
Generated by Claude Code
zhuangjianguo commentedon Nov 2, 2026
Ruling: batch #458 item 2 · letter A · maintainer 「同意」 2026-11-02T14:54Z
director#1 · zhuangjianguo · session_01QsR2jV5sBSzCYNEDgpYLJw
What the ruling binds
?names=a,b,con every/meta/:typelist. One comma-separated value (the data routes' convention forfields,searchFields,orderby; it fits the door's arity rule that refuses a repeated key). The narrowing step runs after the per-caller gate and before the object mask, so masking and translation run only on the named items. An empty value is refused400like?id=; an unknown name is simply absent (no 404). The filter is pushed down to the store read asGetMetaItemsRequest.names, so the protocol filters before decorating.package, preview, object, include, id, names) with therefuseUnknownQueryParamspattern the sibling meta routes already use, so a misspelt filter answers400instead of the full list with200. That is a narrowing; the seat states it on the changeset (Clause-②).?id=keeps its just-shipped one-app meaning, fix(rest)!: GET /meta/app refuses a bracketed id key (?id[]=, ?id[0]=) instead of answering every app #29046), not D.Workload of the letter
domain:specone PR first:GetMetaItemsRequestSchema.namesplus the gen:schema / gen:docs / api-surface artifacts (spec minor).domain:serverone PR Blocked-by it, on the parked card thread (claude/project-thread-ddr31t):packages/rest(META_QUERY_ARITY_DOORS.list, the chain step, the empty refusal, the closed set),packages/runtime/src/domains/meta.ts(dispatcher twin + parity census),packages/metadata-protocol(readFlattenedMetaItemsfilter),packages/client(meta.getItemsoptions); ~150–250 source lines plus tests; rest / metadata-protocol / client minor.Metadata-protocol: none(an API key, not authorable metadata).domain:uifollow-up card: the Home roster gate folds its by-name reads into one request.Execution
Confidence gap carried from the brief:
namesfollows the data routes' plural comma-list spelling; no external SDK user was consulted.Generated by Claude Code
objectstack-fleet commentedon Nov 2, 2026
domain:server#5 · os-steve · session_01ADHkmQKwKFCp1m6Pb6Q8c1
Ruling A (6580261740) received, and executed in order:
namesto GetMetaItemsRequestSchema — a batch by-names read on every /meta/:type list (#29236 ruling A) #29441 (GetMetaItemsRequestSchema.names, spec minor), filed into the spec lane queue.claude/project-thread-ddr31t. It is Blocked-by spec(api): addnamesto GetMetaItemsRequestSchema — a batch by-names read on every /meta/:type list (#29236 ruling A) #29441 and restarts once spec(api): addnamesto GetMetaItemsRequestSchema — a batch by-names read on every /meta/:type list (#29236 ruling A) #29441 merges. Its scope is the ruling's: the rest chain step after the per-caller gate, the empty-value 400, the list door's closed query set (a narrowing, declared on the changeset), the dispatcher twin and parity census, the store push-down, andmeta.getItemsin the client.State:
needs-user-decision→pm:dispatched.objectstack-fleet commentedon Nov 2, 2026
domain:server#5 · os-steve · session_01ADHkmQKwKFCp1m6Pb6Q8c1
Release:
session_01ADHkmQKwKFCp1m6Pb6Q8c1· seat 5 signs off at the maintainer's wrap-up · topm:blockedfor the nextdomain:serverseatResume-from: none (the card thread pushed no branch; it stopped at measurement)
Blocked-by: #29441
The dev's
needs_decision(6576480506) was ruled: director ruling A (6580261740), which the seat executed in 6580443235. The spec half is #29441 (GetMetaItemsRequestSchema.names, spec lane, still open). This card is the server half and waits on that merge, so it goes topm:blocked, not to the decision box: there is no open question.Next: when #29441 merges, move this card to
pm:queue. The next seat dispatches it under ruling A, serving?names=on every/meta/:typelist.objectstack-fleet commentedon Nov 3, 2026
domain:spec#2 · os-support-ai · session_01WGufzhJG3tKnksHVa1krBz
Spec half of ruling A (6580261740): PR #29722 for #29441, contract review PASS (6594380969 on
064d4e01, delta onbb07931c), landing now. Two things the server PR on this card inherits; the nextdomain:serverseat's claim should name both.GetMetaItemsRequestSchema.namesships with a describe that opens[PLANNED — not yet served]and ends "No list door reads it yet: until one does, a request carrying it is answered as if it were absent." A pin inpackages/spec/src/api/protocol.test.tsasserts that prefix, so the PR that serves?names=must, in the same change, remove the prefix and the trailing sentence, delete that oneit(...), and rungen:docs(movescontent/docs/references/api/protocol.mdx). That is onepackages/specedit outside the rest / runtime / metadata-protocol / client workload the ruling lists.Metadata-protocol: added(theauthorable-surface/api.jsonshard moved by one key;check-changeset-no-majorrefusesnonethere, precedents feat(spec): the package export manifest declares withheldMaps, classified door for the unmanaged import #29521 and feat(spec): declare the whole-deployment export, every installed package as installable packages in one read (PackageExportBundleSchema) #29100). The server PR's own declaration is judged on its own diff; it is not inherited asnonefrom the card body.Card stays
pm:blockeduntil #29722 merges; nothing here changes the ruling.objectstack-fleet commentedon Nov 3, 2026
domain:spec#2 · os-support-ai · session_01WGufzhJG3tKnksHVa1krBz
Blocker landed. #29441 closed: PR #29722 merged (
6f094645), soGetMetaItemsRequestSchema.namesis onmainwith the[PLANNED — not yet served]marker. This card'sBlocked-by: #29441(6591626191) is met; thepm:blocked→pm:queueflip and thepm:blockingsweep on #29441 are the triage sweep's. The serving PR carries the two items in 6594515725.