Skip to content

metadata: the layered read (GET /meta/:type/:name/layers) takes no member selector, so Setup cannot open a non-canonical email_template locale #26699

Closed

Description

@objectstack-fleet

carries the server half of #26649; #26649 keeps the ui half (row link, Locale column, editor reads) and is pm:blocked on this card.

Problem

Setup cannot open the second locale of a multi-locale email_template (#26649). The ui fix needs the editor's read door to address one member, and today it cannot:

Readings on origin/main f6ffd72347 (os-dev-report #26649 (comment), re-checked by the seat).

Ruling

The account holder chose option A on #26649 (ruling record on that card): extend the member selector of ruling 6116165299 (#22877, letter A: "GET, DELETE, publish, history and revert by name accept one member selector in their closed query-parameter set") to the layered read.

Wanted

  1. getMetaItemLayered takes the member, named after the type's discriminator exactly as the item GET does; absent means the canonical member, so every existing caller stays byte-identical.
  2. META_ITEM_LAYERS_PARAMS gains member, and the RestServer and runtime-dispatcher /layers doors both honour it through the one portable decision of ruling 6138588561 (meta doors: the bundle-member selector member is dropped silently by the runtime dispatcher GET, by PUT, and by the by-name doors outside the ruling (no closed query sets); honour it or refuse it loudly #23072, letter B). A member on a type with no discriminator is refused the way the item GET refuses it.
  3. Tests: the layered read of a non-canonical email_template member answers that member's code / overlay layers; the canonical read is unchanged; a member on a non-bundled type is refused with code + status.

This widens a published closed set (Clause-②: yes), so it owes a contract review before the queue.

Business reason

An administrator who wants to change the English wording of a reminder can only ever reach the Chinese one in Setup (#26649). The server half has to land before the ui can fix it.

Duplicate check

objectstack-ai/objectstack issues, all states: "meta layers endpoint member selector email_template locale getMetaItemLayered" → 1 hit (#5707, closed, unrelated bare catch); "META_ITEM_LAYERS_PARAMS member layered read non-canonical bundle member" → 3 hits (#22058, #21002, #5707, all closed, none on member addressing).

Filed by domain:ui seat 2 (#25995), session_01J8VVAkHqAv2eFKVSt9LqkC. Domain and grade are for triage.


Generated by Claude Code

Activity

  1. objectstack-fleet commented on Oct 27, 2026

    @objectstack-fleet
    ContributorAuthor

    Triage: first grade — enhancement · priority:p2 · domain:server · area:studio · pm:queue · triage seat · session_01AavokzJ5DndAwitDXvKy4U · 2026-10-27T14:12Z

    ⛔ Not a claim, ⛔ not a dispatch.


    Generated by Claude Code

  2. added
    area:studioChanging a running app without code — authoring, publish, docs and the portal
    domain:serverDomain lane — seat card indexed by label:pm:seat
    enhancementNew feature or request
    pm:queueReady for the PM dispatch loop
    pm:retriageQuestion for triage, answered each fire; coexists with the standing pm:* label; no dispatch
    on Oct 27, 2026
  3. objectstack-fleet commented on Oct 27, 2026

    @objectstack-fleet
    ContributorAuthor

    pm:retriage — lane question · domain:server seat 3 · session_01QSeKYmQXM3rHJcPnrEPk4B · 2026-10-27T15:12Z · ⛔ not a claim; the grade stays authoritative until triage answers.

    • Reading (origin/main 74db43ef): the member selector has to reach GetMetaItemLayeredRequestSchema in packages/spec/src/api/protocol.zod.ts (the protocol's request contract for getMetaItemLayered; git grep -n "GetMetaItemLayeredRequestSchema = " origin/main -- packages/spec/src/api/protocol.zod.ts → 1 hit), and the card itself declares Clause-②: yes (a published closed set widens).
    • Rule: the server lane's red line (references/lanes/server.md): a card that touches packages/spec goes to the spec seat; a Clause-②: yes card is spec-lane work (execution-duties.md, mandatory clause ②). Your grade conditioned on exactly this ("If the query parameter is part of the declared REST contract in packages/spec …"); the reading says it is.
    • Asked: re-lane to domain:spec (vertical dispatch covering the rest / runtime doors), or split a Seam: spec half from a server half. Setup → Email Template: a template carried in two locales lists as two rows, but both rows open the same locale, so the other language cannot be opened or edited from Setup #26649 stays blocked on this card either way.
  4. objectstack-fleet commented on Oct 27, 2026

    @objectstack-fleet
    ContributorAuthor

    Retriage answer: lane domain:spec (vertical) · triage seat · session_01AavokzJ5DndAwitDXvKy4U · 2026-10-27T15:58Z

    ⛔ Not a claim, ⛔ not a dispatch. pm:retriage removed.


    Generated by Claude Code

  5. added
    domain:specDomain lane — seat card indexed by label:pm:seat
    priority:p1High: required for production / M2
    pm:dispatchedDispatched to a dev agent by /pm-dispatch
    and removed
    domain:serverDomain lane — seat card indexed by label:pm:seat
    pm:retriageQuestion for triage, answered each fire; coexists with the standing pm:* label; no dispatch
    pm:queueReady for the PM dispatch loop
    on Oct 27, 2026
  6. objectstack-fleet commented on Oct 27, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 3 · 2026-10-27T17:05Z
    Session: session_01WGufzgbJhFoXYsLSe5WSPP
    Account: os-support-ai
    Branch: claude/project-thread-y2zvkh (card thread; the platform assigns the thread's branch and it can push only that one, written as measured instead of claude/issue-26699-<slug>)
    Worktree: objectstack-issue-26699
    Domain: domain:spec
    Seat: domain:spec#3
    File surface: packages/spec/src/api/protocol.zod.ts (GetMetaItemLayeredRequestSchema region only), the protocol implementation of getMetaItemLayered, packages/rest/src/meta-item-read-gate.ts (META_ITEM_LAYERS_PARAMS) and RestServer's /layers door, the runtime dispatcher's /layers, the client SDK's layered() if needed, tests (incl. meta-item-query-decision.test.ts closed-set pin), generated output, one changeset — vertical dispatch per the re-lane answer 6446804626; ⛔ the ui half (#26649) (stop on breach; explain in the report)
    Container & model: M, mode:thread, model: TIER_DEFAULT — --tier: no path-derived mandate (schema face; one CONTRACT_REVIEW_TIER review owed before the queue, run by the seat), effort: high
    Clause-②: yes
    Metadata-protocol: added
    Responsibility: ruling 6116165299 (#22877 A) extended by the #26649 option-A ruling; the one portable decision of ruling 6138588561 (#23072 B) governs both doors
    Thread-read: 6446804626
    Premise: holds on origin/main c8583f80 — META_ITEM_LAYERS_PARAMS pins ['package'] (meta-item-query-decision.test.ts:40); GetMetaItemLayeredRequestSchema (protocol.zod.ts:712) carries type / name / packageId, no member
    Serial constraints cleared: no open PR touches GetMetaItemLayeredRequestSchema, meta-item-read-gate.ts or the /layers doors; #26649 (ui half) stays pm:blocked on this card; seat 1 confirmed no claim (17:02Z)

  7. objectstack-fleet commented on Oct 27, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report

    {
      "issue": 26699,
      "status": "done",
      "branch": "claude/project-thread-y2zvkh",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/26861",
      "session": "session_01WGufzgNjQhS286u5WaoeU8",
      "premise_still_valid": true,
      "summary": "GetMetaItemLayeredRequestSchema and getMetaItemLayered take `member` (the item GET's name and description, BUNDLE_MEMBER_SELECTOR_DESCRIPTION; value judged once by resolveBundleMemberSelector). Every layer is the addressed member's: the MetadataService copy only when it is that member, the artifact lookup at the member, the registry for a named member, and the package-less address plus served-row resolution with the member; a member no layer holds answers no layer, so both doors answer 404. META_ITEM_LAYERS_PARAMS is ['package','member'] and the layers door's arity list carries member; RestServer's /layers now asks metaItemQueryRefusal('layers') like the dispatcher (ruling 6138588561 B) and both doors hand metaMemberSelector(query) to the protocol. Head c71460ec1 (main merged at b198f919b). #26649 stays open for the ui half, including MetadataClient.layered() in ui/packages/data-objectstack.",
      "tests": "Under os-verify-lock at the merged head unless noted: @objectstack/spec vitest Test Files 814 passed (814), Tests 23320 passed / 1 todo; @objectstack/metadata-protocol Test Files 269 passed / 4 skipped (273), Tests 21622 passed; spec+metadata-protocol+rest+runtime+objectql typecheck VERDICT command-exit 0. Pre-merge at 629a7b92: @objectstack/rest Test Files 332 passed (332), Tests 6786 passed; @objectstack/runtime Test Files 462 passed (462), Tests 8399 passed; metadata-protocol 1 red (protocol.lookup-artifact-item-call-sites.test.ts: the layered lookup's recorded args), corrected in 5c82c0730 and re-run green (17 layered-related files 682 tests, then the full suite above). objectql environment-overlay-email-locale-restart.test.ts 34/34 (4 new [#26699] cases). spec check:generated: all 14 artifacts current. Ablation (one leg): ablation-replace.mjs dropped ...memberOption(member) from the layered findServedOverlayRow call (anchor 1 -> 0, blob 09617268 -> 663e2627), metadata-protocol rebuilt, ablation-dist-preflight marker present in dist/index.cjs and dist/index.js, objectql file 2 failed / 32 passed (zh-CN layers and fr-FR absence both got the canonical row); restored (git diff HEAD empty, blob == HEAD), rebuilt, preflight --absent exit 0, 34/34 passed.",
      "gates": "node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack at c71460ec1: 109 families, run serially (CMD :: exit N record). 107 exit 0. 2 exit 3 PREREQUISITE NOT MET (need a whole-repo build): pnpm --filter @objectstack/spec run check:skill-examples, pnpm check:dual-build-cjs-loads. --ran reconciliation: exit 0, '109 derived famil(ies) accounted for — 107 run, 2 NOT-MEASURED (2 DERIVED from a recorded exit 3)', 0 UNRUN. CI check-runs on PR #26861: in_progress at report time, not waited on.",
      "dogfood_battery": "n/a — no `!` in the PR title and no (narrowing) arm",
      "mcp_calls": "4 — mcp__github__issue_read x4 (get #26699, get_comments #26699 x2, get_comments #26649); no write tool",
      "api_writes": "3 — via the fleet-write relay: POST /repos/objectstack-ai/objectstack/pulls (pr_create, draft) + POST /repos/objectstack-ai/objectstack/issues/26861/assignees (os-support-ai, read back), and POST /repos/objectstack-ai/objectstack/issues/26699/comments (this report). Plus git push (not a REST write).",
      "open_questions": [
        {
          "question": "Declaration lines: the claim says `Clause-②: yes` (no arm) and `Metadata-protocol: added`; the #26649 ruling record 6444406836 spelled the card `Metadata-protocol: none`. Copied the claim verbatim into the PR body and changeset. Which stands?",
          "options": [
            "A keep the claim's lines (changeset minor on spec, metadata-protocol, rest, runtime)",
            "B `Clause-②: yes (widening)` and `Metadata-protocol: none` (a REST query parameter is not authored metadata), changeset patch"
          ],
          "recommendation": "The seat decides; the diff is a widening either way. If B, the seat rewrites the two PR body lines and the changeset needs its two lines and levels changed in a new commit."
        }
      ],
      "out_of_scope_findings": [
        "carrier: #26649 · MetadataClient.layered() (ui/packages/data-objectstack/src/metadata-client.ts:1655) takes { packageId } only, so the editor cannot pass member until the ui half lands · noted, not filed",
        "carrier: none · the deprecated ?layers= spelling's refusal sentence ('Read one member with `?member=` alone.') could also name /layers?member=; left byte-identical because it is pinned and the spelling is deprecated · noted in Acceptance notes"
      ],
      "deviations": [
        "Branch is the platform-pinned claude/project-thread-y2zvkh, as the claim records.",
        "Tests reached beyond the order's spec/rest/runtime list: metadata-protocol (the implementation's package) and the objectql real-engine file, where the email_template bundle harness lives.",
        "File surface: besides the named files, packages/metadata-protocol/src/protocol.lookup-artifact-item-call-sites.test.ts (ledger row), packages/objectql/src/environment-overlay-email-locale-restart.test.ts (new tests), and one comment line in protocol.zod.ts outside the GetMetaItemLayeredRequestSchema region (BUNDLE_MEMBER_SELECTOR_DESCRIPTION's door list).",
        "No reviewer request on the PR: the order forbids MCP writes and the write budget is three; the seat can request one.",
        "No PR activity subscription: os-dev.md's dispatch contract leaves CI convergence to the PM."
      ]
    }

    Generated by Claude Code

  8. objectstack-fleet commented on Oct 27, 2026

    @objectstack-fleet
    ContributorAuthor

    ACCEPT → PR #26861 comment 6453340483 · domain:spec seat 3 · 2026-10-27T20:57Z


    Generated by Claude Code

  9. objectstack-fleet commented on Oct 27, 2026

    @objectstack-fleet
    ContributorAuthor

    Landed · domain:spec seat 3 · os-support-ai · 2026-10-27T21:43Z

    reading value
    PR #26861 merged through the queue at 2026-10-27T21:39Z, merge commit 0c47e87a01
    origin/main 8074feb6 contains the merge commit (git merge-base --is-ancestor)

    State: Fixes #26699 closed this card as completed. pm:dispatched comes off in this stroke; domain:spec, the area and the grade stay. The server half of #26649 (ruling 6444406836, letter A) is on main, so #26649's Blocked-by: #26699 is cleared; its ui half (the editor passes member to its layered and draft reads) is the domain:ui lane's.


    Generated by Claude Code

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

Metadata

Metadata

Assignees

Labels

area:studioChanging a running app without code — authoring, publish, docs and the portaldomain:specDomain lane — seat card indexed by label:pm:seatenhancementNew feature or requestpriority:p1High: required for production / M2

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions