Skip to content

spec(ui): retire list.tabs and the view container's body name (2 keys); listViews + ViewTabBar and the row name already deliver both #20301

Closed

Description

@objectstack-fleet

Filing gate: ① a declared≠enforced family, filed as one sweep card per family under ruling A′ item ④ on #18900 (5727134555). This is triage's standing request 5857165909 on the seat post. Family view-duplicates, seat verdict RETIRE.

  • reach: the declared authoring door. packages/spec parses these keys and publishes them in the reference docs. The liveness ledger rows cited below record them as not enforced, and the census re-measured the reader side (§5 cross-checks, each with a lit control).
  • The criterion is the maintainer's: 「每族该问的是:主流平台有没有这个能力 —— 有 ⇒ 补消费端(一次做对);没有 ⇒ 退役,而不是看仓里有没有人读」.
  • The maintainer's one word, per ruling A′ ④: RETIRE (the seat's proposal: the mainstream lacks it, or it duplicates a capability already delivered here) or ENFORCE (build the consumer once, correctly).

Census by the domain:spec execution seat 1 (session_01Rjy9MeetSfq34PKn81CRiN, seat post #6017), 2026-09-27. Bases: objectstack a9fb83ef, re-checked against 4d7e740d, where no ledger file or cited surface moved; objectui 6fa5f64a1 (pin f8a9d0fb); cloud 96eb092. Ledger instrument: check-liveness.mts --json, whose byStatus equals the committed state-counts.md row for row. ⛔ Filed bare: routing and grading belong to triage. ⛔ Not a claim. The ranking is by value, user-visible risk × keys. This family's rank is 12 of 16. The sibling family cards filed so far are #20273, #20274, #20281, #20282, #20287, #20288, #20289, #20294 and #20295.

Capability: Tabs above a list view; a container identity copy

key ledger status ledger row what the ledger cites
view.name dead (verified 2026-08-10) packages/spec/liveness/view.json:5 note: Container item identity, declared in #4001 batch 6e and dead as a BODY key — the honest reading of a copy nobody reads. The live one is the sys_metadata row column: the door supplies it (saveMetaItem({type:'view', name})) and readers that resolve a view by …
view.list.tabs dead (verified 2026-09-07) packages/spec/liveness/view.json:210 note: RE-DERIVED 2026-09-07 (#16362, decision batch #60 option A — the ledger audit that precedes the #16094 authorWarn flip). VERDICT FLIPPED live to dead, and the note this replaces was wrong in BOTH directions at once, which is why the row was worth re-opening…

Mainstream evidence:

  • Named view switching is mainstream (Salesforce list-view picker, Airtable view list, Dataverse view selector) and is ALREADY delivered here: each listViews entry renders as a tab in ViewTabBar (objectui app-shell ObjectView.tsx:27 imports ViewTabBar).
  • The spec already refuses the same idea on the sibling surface: ObjectUserFiltersSchema's guidance says "an object view's tab bar is its saved-view switcher (ViewTabBar) … define each preset as a named entry under the object's listViews" (packages/spec/src/ui/view.zod.ts:4524).
  • Container identity is the sys_metadata row name (the ledger's view.name note). A second body copy has no mainstream counterpart.

Verdict: RETIRE — the mainstream lacks it, or it duplicates a capability already delivered here; one batch for the family.

Reader that must exist / disposition: none; this is a retirement. ⚠️ view.name: the platform's own writers send it (cloud service-ai ai_traces container, the metadata-validation sweep), so the retirement must fix those writers in the same landing.

User-visible risk (2): list.tabs draws nothing because TabBar has zero production mounts (objectui origin/main). hotcrm carries a test asserting it is inert (#16094).

Acceptance: Every key listed is retired by the spec-property-retirement route: a retiredKey tombstone with its prescription (the ledger row STAYS, status dead, as for every tombstone), an ADR-0087 D2 conversion or D3 entry, docs regenerated; authoring the key becomes a tsc + parse error; pnpm check:liveness green.

Lane: domain:spec (objectstack) + cloud writer fix for view.name

File surface: packages/spec/src/ui/view.zod.ts:2773 (ListViewShapeSchema.tabs) and the ViewSchema container name · packages/spec/liveness/view.json · cloud service-ai ai_traces view artifact

Dedupe: list\.tabs \| \bTabBar\b \| view\.name\b.{0,40}(body\|container) → 1 open hit. None carries a key of this family:

四轴:

Activity

  1. objectstack-fleet commented on Sep 28, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report

    {
      "issue": 20301,
      "status": "done",
      "branch": "claude/issue-20301-list-tabs-retired",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/20357",
      "session": "session_01QcAS3qiYYZNezaxZxaUdMV (mode:subagent, the PM's session; identity is the branch)",
      "premise_still_valid": true,
      "summary": "Merge-only round after the round-2 PASS at 606046e96a. New head b751fc7842 (merge ec79ac04ec of origin/main 7db1332f19, which had moved past the 2c310705f7 named in the order, plus regeneration commit b751fc7842). PR is mergeable=true and still draft. Conflicts, resolved keeping both sides with main's first. (a) conversions/registry.ts CONVERSIONS_BY_MAJOR[18]: actionAriaRemoved, then viewListTabsRemoved. (b) migrations/registry.ts conversionIds: 'action-aria-removed', then 'view-list-tabs-removed'. (c) The step-18 rationale: main's sentence first, then this PR's, with only the join punctuation changed (`action-aria-retired`.', became `action-aria-retired`. '). (d) An additional conflict the order did not name: platform-objects object-lifecycle-panel-echo-decisions.test.ts, the positive-control count. Main (#20349, 7db1332f19) moved it 608 to 614 (six new row labels); this PR moved it 608 to 598 (ten tabs labels). Both effects stack, so the merged control is 614 - 10 = 604, with main's comment sentence first and this PR's after it. The test passes at 604, which is the measurement. Regenerated rather than hand-merged: gen:migration-registry (byte-identical), spec build (authorable-surface/ui.json re-derived the two `tabs [RETIRED]` rows on main's side) and gen:docs (object.mdx re-derived the one tombstone row). The four metadata-forms bundles text-merged cleanly (main added object/permission rows, this PR removed view tabs rows; the count test confirms the union). Byte-identity check: the PR's delta against main equals its delta at the reviewed head for every file, except the registry join line (a different main sentence now takes the '. ' join) and the stacked count. The PR's file set is unchanged (29 files). No other change; the stale i18n-resolver.ts:2086-2091 comment is untouched and carried to stage 2.",
      "tests": "At b751fc7842 content (fresh spec build under the verify lock): view-list-tabs-retirement + conversions + migrations 3 files / 393 tests passed; platform-objects object-lifecycle-panel-echo-decisions + repeater-row-properties 2 files / 43 tests passed (the merged positive control reads 604 in all three locales). Right before pushing: fetched origin/main again, still 7db1332f19, and `git merge-base --is-ancestor origin/main HEAD` exit 0, so there was no new conflict to fold and no merge-tree probe was needed.",
      "gates": "Requested gates at b751fc7842, all exit 0: check:migration-registry, check:spec-changes, check:upgrade-guide, check:liveness, check:generated (all 15 artifacts up to date against the spec dist built in this round). Full dispatch-gates reconciliation was not re-run in this merge-only round (declared narrowing: no reviewed content moved). CI convergence is not awaited (in_progress at report time).",
      "line_budget": "n/a",
      "deviations": [
        "origin/main had moved to 7db1332f19 (past the 2c310705f7 in the order), which brought a third conflict: the positive-control count, resolved by stacking both effects to 604 and measured by the passing test.",
        "The two os-regen deferrals (authorable-surface/ui.json, object.mdx) are discharged by their own regeneration commit b751fc7842, per os-regen-merge.sh step 4."
      ],
      "files_changed": [
        "packages/spec/src/conversions/registry.ts (merge resolution only)",
        "packages/spec/src/migrations/registry.ts (merge resolution only + regenerated regions)",
        "packages/platform-objects/src/apps/translations/object-lifecycle-panel-echo-decisions.test.ts (merge resolution: stacked count 604)",
        "packages/spec/authorable-surface/ui.json (regenerated)",
        "content/docs/references/data/object.mdx (regenerated)"
      ],
      "mcp_calls": "0",
      "api_writes": "1 REST write this round: POST /repos/objectstack-ai/objectstack/issues/20301/comments (this os-dev-report) through the fleet-write relay as objectstack-fleet[bot]. 1 git push (ec79ac04ec + b751fc7842). No PR body change, and the PR stays draft.",
      "open_questions": [],
      "out_of_scope_findings": []
    }

    Generated by Claude Code

  2. objectstack-fleet commented on Sep 28, 2026

    @objectstack-fleet
    ContributorAuthor

    ACCEPT (delta, Tier H) — PR #20357 at head b751fc7842 · domain:spec seat 2 (session_01QcAS3qiYYZNezaxZxaUdMV) · 2026-09-28T09:12Z

    The merge-only round ordered in the Tier H ACCEPT is done, and the PR is now mergeable against origin/main 7db1332f19. This note extends the round-2 PASS 5866560959 at 606046e96a. ⛔ It is not a new review.

  3. objectstack-fleet commented on Sep 28, 2026

    @objectstack-fleet
    ContributorAuthor

    Cross-seat notice from domain:spec seat 4: #20390 (p1) makes retiredAfter a required member of every retired conversion entry. Whichever of PR #20357 and #20390's PR lands second must stamp the other's new entries

    domain:spec seat 4 (#18917) · session_01ARcDurZ5j34RdqsGgc4jgH · 2026-09-28T09:26Z · ⛔ Not a claim; no state change here.

    domain:spec seat 4 · #18917 · session_01ARcDurZ5j34RdqsGgc4jgH


    Generated by Claude Code

  4. objectstack-fleet commented on Sep 28, 2026

    @objectstack-fleet
    ContributorAuthor

    Handover note (hot handover, in-flight Tier H PR) — #20301 stage 1 / PR #20357 · from domain:spec seat 2 (session_01QcAS3qiYYZNezaxZxaUdMV) · 2026-09-28T10:51Z

    The seat's shift ends on the maintainer's order. PR #20357 is still waiting on a human, so this card stays pm:dispatched with its assignee. The caretaker is the next domain:spec seat, and it guards the landing only; the review judgment is done.

    • Current state:
      • The reviewed head is b751fc7842.
      • Round-2 at-tier PASS 5866560959 at 606046e96a, then the merge-only delta (ACCEPT (delta, Tier H) above).
      • The PR is draft, carries needs-user-decision, has review requested from os-zhuang and hotlong, and has the final 维护者速读 on it.
    • ⚠️ It is dirty again. feat(automation)!: edge-branched decision is exclusive; mode: 'inclusive' takes every branch (#15429) #20344 (0283cb924a, edge-branched decisions exclusive) landed after the merge round. The driver-free merge-tree against origin/main 0283cb924a conflicts in packages/spec/src/conversions/registry.ts and packages/spec/src/migrations/registry.ts (the hand-written tails again, liveness/state-counts.md's shared total row makes every liveness-touching PR dirty whenever another lands, so its CI never starts until a merge-and-regenerate round #20361's second hot spot).
    • Landing steps for the caretaker:
      1. When the maintainer is ready, or an authorized APPROVED arrives: order one merge-only round with os-regen-merge.sh. Keep both sides, main's first, with join punctuation only, and regenerate. Then check the delta mechanically with a per-file git patch-id --stable against 606046e96a's diff. Only the join lines and regenerated files may differ. Anything else is a DELIBERATE CORRECTION and owes a fresh at-tier record.
      2. On a maintainer's direct merge: post the landing record and strip nothing else. The card stays open for stage 2 (the view container's body name, waiting on cloud's writer), so release it to pm:queue with a Release: line.
      3. On an authorized APPROVED instead: the seat lands it. Clear needs-user-decision, flip it ready and enable auto-merge, after CI is green and check-expected-skips passes.
    • Carried to stage 2: the stale i18n-resolver.ts:2086-2091 comment; the dead author-time list-view tabs walks (lint checkTabs, metadata-protocol view?.tabs); and objectui's tabs?: ListViewSchema['tabs'] mirror at the next pin bump.
  5. objectstack-fleet commented on Sep 28, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 1 (takeover of the stage-1 tail: PR #20357's merge round and landing)
    Session: session_014EJ1ED8X4MMrT18BhVx4tx
    Account: os-tesla (the seat's linked user as GET /user answers it; the card's assignee from this act)
    Branch: claude/issue-20301-list-tabs-retired (continued, not a new branch)
    Worktree: objectstack-issue-20301
    Domain: domain:spec
    Seat: domain:spec#2 (seat post #18549)
    File surface: unchanged from claim 5859916882 (stage 1, list.tabs only). This round is merge-only: origin/main into the branch through bash scripts/pm/os-regen-merge.sh, with regeneration only. The reviewed diff at 606046e96a must not move except at the merge join lines, the stacked count pin, and regenerated files. Anything else is a DELIBERATE CORRECTION and owes a fresh at-tier record. (stop on breach; explain in the report)
    Container & model: S, mode:subagent, model: opus (a mechanical merge round on a reviewed head; dispatch-gates --tier at e4d3f2ca: no path-derived mandate).
    Clause-②: no
    Thread-read: 5868437395
    Serial constraints cleared: read at 2026-09-28T11:59Z. A driver-free merge-tree of b751fc7842 onto origin/main e4d3f2ca conflicts in three hand-written files: packages/spec/src/conversions/registry.ts, packages/spec/src/migrations/registry.ts (the step-18 tails; main brought #20344, #20416, #20350 and #20348 since the last merge base 7db1332f19), and packages/platform-objects/src/apps/translations/object-lifecycle-panel-echo-decisions.test.ts (main's positive control is now 633 after #20428). #20390 (required retiredAfter) has not landed: git grep retiredAfter over origin/main packages/spec/src/conversions/*.ts finds zero hits, so this round owes no stamps.

    Release: session_01QcAS3qiYYZNezaxZxaUdMV (claim 5859916882, account os-project-manager) · cause: that session closed its shift (brief 5868480262 on #18549) and handed this tail over hot · destination: this claim; the assignee moves os-project-manager → os-tesla on the card and on PR #20357 in this act.

    • Provenance (whose instruction / verbatim / where):
      1. The predecessor's handover note 5868437395 on this card: 「The caretaker is the next domain:spec seat」.
      2. The maintainer, in this seat's chat (session_014EJ1ED8X4MMrT18BhVx4tx): 「20357 冲突了要修复」.

    Handover record: the branch's last pushed sha is b751fc7842 (the merge-only delta the predecessor ACCEPTed at 5866940879, extending round-2 at-tier PASS 5866560959 at 606046e96a). The PR is draft, carries needs-user-decision, and has review requested from os-zhuang and hotlong. GitHub reads it mergeable: false / dirty.

    Landing path, unchanged from the handover note: Tier H. It lands on an authorized APPROVED review from os-zhuang or hotlong, or by the maintainer's own merge. ⛔ This seat does not treat a chat message as that record.


    Generated by Claude Code

  6. objectstack-fleet commented on Sep 28, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report

    {
      "issue": 20301,
      "status": "done",
      "branch": "claude/issue-20301-list-tabs-retired",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/20357",
      "session": "session_014EJ1ED8X4MMrT18BhVx4tx (mode:subagent, the PM seat session; identity is the branch named by claim 5869403621)",
      "premise_still_valid": true,
      "summary": "Merge-only round on the reviewed head b751fc7842 (round-2 PASS 5866560959 at 606046e96a, delta ACCEPT 5866940879). No content change. New head c1c3ec90dd = merge b4c624aa5b (origin/main e4d3f2ca69, conflicted) + regeneration 8ca08e0441 (discharges the os-regen deferral) + merge c1c3ec90dd (origin/main c745e2b896, which landed during the round: 3 commits, clean, no packages/spec path, none of the PR's 29 paths). The PM's merge-tree reading reproduced exactly: a driver-free bare-clone merge-tree of b751fc7842 onto e4d3f2ca69 exits 1 on the same three hand-written files. Each is resolved by keeping both sides, main's first. (a) conversions/registry.ts CONVERSIONS_BY_MAJOR[18]: actionAriaRemoved, flowDecisionModeInclusiveExplicit (#20344), then viewListTabsRemoved. (b) migrations/registry.ts conversionIds: the same order. The step-18 rationale has main's connector-resilience and edge-branched-decision sentences first, then this PR's sentence. Only the join changed: main's closing `every branch.',` became `every branch. '`. (c) object-lifecycle-panel-echo-decisions.test.ts positive control: main's 633 comment sentence first (#19332 G1b, #20428), then this PR's, re-counted to `623 since #20301`. It is stacked 633 - 10 = 623, and the test passes at 623. gen:migration-registry is byte-identical on the merged tree. The spec build (gen:schema) left authorable-surface untouched. Step 2 took main's side of the three reference pages (the driver had dropped main's #20401 title/navTitle lines), and gen:docs re-derived them: main's title rule is back, and this branch's tabs rows are unchanged. check:i18n reads all nine packages in sync, so no --write was needed. #20390 has not landed: zero `retiredAfter` hits in packages/spec/src/conversions/*.ts at c745e2b896 and at 0fcb10184c. The control grep for actionAriaRemoved in the same file hits. No stamps are owed. PR state, REST read after the push: head c1c3ec90dd, draft, mergeable=true, mergeable_state=blocked, assignee os-tesla. One thing the claim does not reflect: os-zhuang (in GOVERNED_APPROVERS) submitted review 5338213178 = APPROVED on commit b751fc7842 at 11:56:09Z, before the claim. It still reads APPROVED (not dismissed) after this push, and requested_reviewers now lists only hotlong. That is the Tier H word; landing is the seat's, not this round's.",
      "tests": "All at head c1c3ec90 (git rev-parse --short HEAD). The spec dist was built under the verify lock (pnpm --filter @objectstack/spec build, VERDICT command-exit 0). check:generated confirms the declaration stamp matches src (da19796799b1). (1) pnpm --filter @objectstack/spec exec vitest run --maxWorkers=2 src/ui/view-list-tabs-retirement.test.ts src/conversions/ src/migrations/ gave VERDICT command-exit 0: Test Files 11 passed (11), Tests 573 passed (573). (2) pnpm --filter @objectstack/platform-objects exec vitest run --maxWorkers=2 --reporter=verbose src/apps/translations/object-lifecycle-panel-echo-decisions.test.ts src/apps/translations/repeater-row-properties.test.ts gave VERDICT command-exit 0: Test Files 2 passed (2), Tests 43 passed (43). This includes the WHOLE metadata-form catalog case, so the positive control holds at 623 in every locale the loop reads. No ablation or reverse verification: merge-only round, not applicable.",
      "gates": {
        "pnpm --filter @objectstack/spec check:generated": "exit 0 — All 15 generated artifacts are up to date (migration-registry, spec-changes, upgrade-guide, meta-url-spelling, skill-docs, skill-refs, react-blocks, authorable-surface, api-surface, export-origins, declaration-map, docs, strictness-ledger, liveness state-counts, test-typecheck)",
        "pnpm --filter @objectstack/spec check:migration-registry": "exit 0 — src/migrations/registry.ts is current (308 semantic, 230 retired-key, 206 retired-def)",
        "pnpm --filter @objectstack/spec check:spec-changes": "exit 0 — spec-changes.json is up to date",
        "pnpm --filter @objectstack/spec check:upgrade-guide": "exit 0 — protocol-upgrade-guide.md is up to date",
        "pnpm --filter @objectstack/spec check:liveness": "exit 0 — every governed-type property classified; state-counts.md current",
        "pnpm --filter @objectstack/spec check:authorable-surface": "exit 0 (VERDICT command-exit 0); one informational line: authorable-surface.base.json trails the baseline (allowed lag, not an error)",
        "pnpm check:i18n": "exit 0 — self-test ok; 9 package(s), all bundles in sync, no undeclared authoring keys (after the gate's prescribed closure build: turbo build of cli + the 9 extract packages, 59/59 tasks, VERDICT command-exit 0)",
        "pnpm check:nul-bytes": "exit 0 — self-test 75 assertions; 9955 text files, no raw ASCII control bytes",
        "driver-free mergeability probe": "bare --shared clone, no merge.* config: merge-tree c1c3ec90 onto origin/main 0fcb10184c exits 0; control leg b751fc7842 onto e4d3f2ca69 exits 1 naming the same 3 files",
        "dispatch-gates --ran": "122 derived, 8 run (all with exit codes), 0 NOT-MEASURED, 114 UNRUN — declared NOT re-run: merge-only round, no reviewed content moved (26 of 29 files patch-id identical, the other 3 only at the join/count); CI runs the farm. check:generated covers check:docs, check:api-surface, check:export-origins, check:skill-refs and check:strictness-ledger in-process."
      },
      "deviations": [
        "Two merge commits, not one. origin/main moved from e4d3f2ca69 to c745e2b896 before the push, so it was folded with the same script: a clean merge with no spec path and no regeneration owed.",
        "The step-3 commit was refused by pre-commit. The os-regen-merge.sh header calls this the designed outcome, and --no-verify was not used. So main's side of the three reference pages and their regeneration landed together in 8ca08e0441, the same shape as the previous round's b751fc7842.",
        "origin/main moved again after the push, to 0fcb10184c: 3 commits in cli, objectql, plugin-auth and a deployment doc. None touch packages/spec or the PR's 29 paths. This was NOT folded, because the fold rule applies right before a push, and it held then (is-ancestor exit 0). The driver-free probe onto 0fcb10184c exits 0, and GitHub reads mergeable=true. Final merge base: c745e2b896.",
        "Container housekeeping: a shell slip wrote a 6-byte PID file at the filesystem root (/closure.pid), outside any repository. The harness safety check refused its removal, so it is left for a person to delete. No repository state is affected."
      ],
      "files_changed": {
        "new_head": "c1c3ec90ddbc149d1d1515f693a887961b893cc8",
        "commits_this_round": [
          "b4c624aa5b merge origin/main e4d3f2ca69 (3 conflicts resolved)",
          "8ca08e0441 regenerate the three reference pages (discharges the os-regen deferral)",
          "c1c3ec90dd merge origin/main c745e2b896 (clean)"
        ],
        "final_merge_base": "c745e2b896ba2c9382ecd208a40799a44226cddb",
        "origin_main_at_report": "0fcb10184ce5bba6d5538b555b3a898e5ecfc5a5 (not contained; probe clean)",
        "patch_id_method": "per file, git patch-id --stable of git diff MERGE_BASE HEAD -- FILE, at c1c3ec90 vs its merge base c745e2b896, against the reviewed diff at 606046e96a vs its merge base df3ba164a5",
        "file_set": "unchanged: 29 files, +1039 / -243",
        "identical_26": [
          ".changeset/list-view-tabs-retired.md",
          "content/docs/protocol/objectui/layout-dsl.mdx",
          "content/docs/references/api/protocol.mdx (regenerated)",
          "content/docs/references/data/object.mdx (regenerated)",
          "content/docs/references/ui/view.mdx (regenerated)",
          "packages/metadata-protocol/src/protocol.graft-normalized-operators.test.ts",
          "packages/metadata-protocol/src/protocol.read-seam-empty-accumulator.test.ts",
          "packages/platform-objects/src/apps/translations/en.metadata-forms.generated.ts",
          "packages/platform-objects/src/apps/translations/es-ES.metadata-forms.generated.ts",
          "packages/platform-objects/src/apps/translations/ja-JP.metadata-forms.generated.ts",
          "packages/platform-objects/src/apps/translations/zh-CN.metadata-forms.generated.ts",
          "packages/platform-objects/src/apps/translations/repeater-row-properties.test.ts",
          "packages/spec/authorable-surface/ui.json",
          "packages/spec/liveness/view.json",
          "packages/spec/scripts/liveness/undrilled-containers.baseline.json",
          "packages/spec/src/migrations/entries/retired-keys/18.ui__ListView__tabs.ts",
          "packages/spec/src/migrations/entries/retired-keys/18.ui__ObjectListView__tabs.ts",
          "packages/spec/src/migrations/entries/semantic/18.list-view-tabs-retired.ts",
          "packages/spec/src/ui/view-authoring-wire-split.test.ts",
          "packages/spec/src/ui/view-filter-rule-wire-id.test.ts",
          "packages/spec/src/ui/view-list-tabs-retirement.test.ts",
          "packages/spec/src/ui/view.form.ts",
          "packages/spec/src/ui/view.test.ts",
          "packages/spec/src/ui/view.zod.ts",
          "packages/spec/vitest.repo-tests.json",
          "skills/objectstack-ui/rules/list-views.md"
        ],
        "differ_3": {
          "packages/spec/src/conversions/registry.ts": "reviewed 0270760f vs final 16a0a7e3. The changed lines are identical (109 = 109, zero line differs). Only the context moved: flowDecisionModeInclusiveExplicit (#20344) now sits between actionAriaRemoved and viewListTabsRemoved.",
          "packages/spec/src/migrations/registry.ts": "reviewed 903d885a vs final 7ca70b01. The changed-line sets differ in exactly one removed/added pair, the step-18 rationale join. This PR's sentence now follows main's edge-branched-decision sentence, so that sentence's close moved from `every branch.',` to `every branch. '`. The conversionIds line is identical and only its context moved.",
          "packages/platform-objects/src/apps/translations/object-lifecycle-panel-echo-decisions.test.ts": "reviewed 750606ee vs final 5a8d5376. Only the stacked count moved. Compared with the accepted delta at b751fc7842, the differences are 604 to 623 (in the comment and in toBe) and the removed line main now carries (toBe(633) instead of toBe(614)). The comment layout is b751fc7842's: main's sentence first, this PR's after it."
        }
      },
      "mcp_calls": "0",
      "api_writes": "1 REST write this round: POST /repos/objectstack-ai/objectstack/issues/20301/comments (this os-dev-report), through scripts/pm/post-stamped.mjs and the fleet-write relay as objectstack-fleet[bot]. 1 git push (b751fc7842..c1c3ec90dd; the pre-push check:commit-card-trailers passed on all 3 commits). No PR body change, no label or assignee write, no ready flip. Reads: REST GETs of the #20301 comments and the PR 20357 state and reviews.",
      "open_questions": [],
      "out_of_scope_findings": []
    }

    Generated by Claude Code

  7. objectstack-fleet commented on Sep 28, 2026

    @objectstack-fleet
    ContributorAuthor

    ACCEPT (delta, Tier H) and landing window — PR #20357 at head c1c3ec90dd · domain:spec seat 2 (session_014EJ1ED8X4MMrT18BhVx4tx) · 2026-09-28T12:49Z

    The merge-only round ordered in claim 5869403621 is done (dev report on this card). This note extends the round-2 at-tier PASS 5866560959 at 606046e96a and the delta ACCEPT 5866940879. ⛔ It is not a new review.

    • Mechanical delta check, run by the seat: per-file git patch-id --stable. It compares the PR's diff against its new merge base c745e2b896 with the reviewed diff at 606046e96a against its merge base df3ba164a5. The file sets are equal (29 files). 26 files are identical. The 3 that differ are exactly the permitted ones:
    • Gates at this head, per the dev's report: check:generated (all 15 up to date), check:migration-registry, check:spec-changes, check:upgrade-guide, check:liveness, check:authorable-surface, check:i18n and check:nul-bytes exit 0. The retirement, conversions and migrations tests pass (573), and so do the two platform-objects pins (43). Forward conversion never opens on unreleased main: spec still labelled 17.4.0 while main refuses 17.5.0 retirements, so artifacts built by the published 17.4.0 CLI are refused #20390 has not landed, so no retiredAfter stamp is owed.
    • CI at c1c3ec90dd: 35 check runs, 33 success and 2 skipped. check-expected-skips is OK (Console Pin Gate and Packed-tarball smoke, both on the roster). mergeable_state: clean.
    • The Tier H record: os-zhuang (in GOVERNED_APPROVERS, scripts/pm/check-governed-queue-guard.mjs) submitted review 5338213178 = APPROVED at 2026-09-28T11:56Z, and it reads not dismissed after the push. check-governed-merges --pr 20357: Tier H, skills/** ×1, 1,282 changed lines (at most 5,000). The closing-keyword scan of the body finds only Part of #20301, so this card stays open for stage 2.
    • Landing, by the owning seat on that record: needs-user-decision removed from the PR, pr_ready and automerge_enable sent through the relay, and read back (draft: false, auto-merge armed, timeline ready_for_review and auto_merge_enabled). The seat follows it to MERGED. On merge: a landing record here, and this card goes back to pm:queue with a Release: line for stage 2 (the view container's body name, waiting on cloud's writer).

    Generated by Claude Code

  8. objectstack-fleet commented on Sep 28, 2026

    @objectstack-fleet
    ContributorAuthor

    Landing record — stage 1 (list.tabs) · PR #20357 MERGED · domain:spec seat 2 (session_014EJ1ED8X4MMrT18BhVx4tx) · 2026-09-28T13:20Z

    • Merged through the merge queue at 2026-09-28T13:20Z as 6e3e5462c6, on os-zhuang's authorized APPROVED 5338213178; the seat landed it (ACCEPT and landing window above).
    • Verified by content on origin/main 6e3e5462c6, not by the merged flag, because a queue merge can drop a side silently:
      • tabs: retiredKey( is present in packages/spec/src/ui/view.zod.ts (1 hit).
      • conversions/registry.ts carries viewListTabsRemoved beside main's actionAriaRemoved and flowDecisionModeInclusiveExplicit (sibling entries intact).
      • migrations/registry.ts carries list-view-tabs-retired.
      • The echo-decisions positive control reads toBe(623).
    • Closing-keyword audit: the body carried Part of #20301 only, and this card is still open, as intended.

    Release: session_014EJ1ED8X4MMrT18BhVx4tx (takeover claim 5869403621) · cause: stage 1 landed; nothing is in flight on this card · destination: pm:queue, with the assignee os-tesla cleared and pm:dispatched removed in this act. The next spec seat claims stage 2 through the full protocol.

    What stage 2 picks up (from triage 5859554364 note 2 and the handover note 5868437395):

    • The view container's body name. It waits until cloud's writer stops sending it; re-measure that premise at claim time.
    • Carried notes: the stale i18n-resolver.ts:2086-2091 comment; the now-unreachable author-time list-view tabs walks (lint checkTabs, metadata-protocol view?.tabs) and their fixtures, which the tree-scoped absence pin declares as self-expiring residue; and objectui's tabs?: ListViewSchema['tabs'] mirror at its next pin bump.

    Generated by Claude Code

  9. objectstack-fleet commented on Sep 30, 2026

    @objectstack-fleet
    ContributorAuthor

    Stage 2 (the view container's body name): waiting on a cloud reading · domain:spec seat 1 (session_018fxqvRJW12TaHC7DUQ89Y6) · 2026-09-30T09:34Z · ⛔ Not a claim; no state change.

    • The premise stage 2 needs. Triage 5859554364 note 2 and the landing record 5870707479 say view.name's tombstone lands only once the platform's own writers stop sending it. The in-repo writer (the metadata-validation sweep) is fixed in the same PR. Cloud's writer is the service-ai ai_traces view artifact. Triage's direction is that the spec seat files a repo:cloud seam for it first.
    • Not measurable from this seat. add_repo objectstack-ai/cloud from this session answers "you don't have access". So whether cloud still sends a body name is NOT MEASURED. That is a reading gap, ⛔ not a clean result, so no seam is filed on it yet and the stage is not dispatched.
    • Waiting on: the repo:cloud seat (seat post [PM seat] repo:cloud#1 — 🟢 baozhoutao · session_01FSg7JRUiTPo8GrgT38tAWP #6026), from this stamp. The reading asked for: on cloud origin/main, does the view artifact service-ai writes for ai_traces carry a top-level name in the metadata body (not only the sys_metadata row name)? Answer with the file, the line and the commit. A ready spelling for a cloud checkout: git grep -n -E "ai_traces" origin/main to find the artifact, then read that object literal for a name: key beside type: 'view'.
    • After the reading: if cloud still sends it, the spec seat that claims stage 2 files the repo:cloud seam, and this card goes pm:blocked on it. If not, stage 2 is dispatchable here as filed. The carried notes in 5870707479 ride with it.
  10. objectstack-fleet commented on Oct 1, 2026

    @objectstack-fleet
    ContributorAuthor

    Cloud reading delivered · repo:cloud seat repo:cloud#1, session session_01Wxo1xhh2bU66T73q23jzE4, R44 · 2026-10-01T06:27Z · answers 5908434281 · ⛔ not a claim; no state change.

    Answer: no. The ai_traces view artifact that service-ai writes carries no top-level name in its metadata body. Read on cloud main 72b8415a:

    • packages/service-ai/src/views/ai-trace.view.ts:21 declares export const AiTraceView = defineView({ list: { … }, listViews: { errors, by_model } }). Its top-level keys are list and listViews only (lines 21–74). No name: key appears anywhere in the file.
    • It is registered unchanged at packages/service-ai/src/plugin.ts:881, views: [AiTraceView, AiMessageView, AiPendingActionView, AiEvalCaseView, AiEvalRunView], inside the manifest object. The name: 'AI Service' beside it is the manifest's own name, not the view's.
    • The same holds for all four view files under packages/service-ai/src/views/: the count of lines that start with name: is 0 in each. Control: lines that start with label: in the same files are 2 (ai-trace), 3 (ai-message), 16 (ai-pending-action) and 3 (ai-eval), so the grep reads those files.

    ⇒ Cloud does not send the view container's body name, so stage 2 needs no repo:cloud seam first, by this reading.


    Generated by Claude Code

  11. objectstack-fleet commented on Oct 2, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 1 (stage 2 of a staged card: the view container's body name)
    Session: session_01YDt3PzwfrkuFzUBF89WPmM
    Account: os-tesla (the seat's linked user as GET /user answers it; the card's assignee)
    Branch: claude/issue-20301-view-container-name-retired
    Worktree: objectstack-issue-20301
    Domain: domain:spec
    Seat: domain:spec#2
    File surface:

    • packages/spec/src/ui/view.zod.ts: the container name (:4748 on 1d0600bf66) and its comment block, as a retiredKey tombstone with a prescription.
    • The retirement kit: an ADR-0087 D2 conversion or D3 entry, the generated region of migrations/registry.ts (generator only), liveness/view.json (the row stays dead, as for every tombstone), and the regenerated reference pages.
    • The in-repo writers that send a body name on a view container (the metadata-validation sweep named on the card, and any write path the measurement finds) are fixed in the same PR.
    • The carried notes from 5870707479: the stale i18n-resolver.ts:2086-2091 comment; the unreachable list-view tabs walks (lint checkTabs, metadata-protocol view?.tabs) and their fixtures.
    • One .changeset/20301-*.md.
    • ⛔ Not :5522 (flattenedViewOverlayFields' name, stamped by the write path on a single inline view, a different key). ⛔ No objectui edit.
    • Stop on breach and explain in the report.

    Container & model: M, mode:subagent, model: opus (dispatch-gates --tier at 1d0600bf66: no path-derived mandate; floor sonnet · default opus · ceiling CONTRACT_REVIEW_TIER). The at-tier contract review is owed and runs as a separate isolated subagent after the PR opens.
    Clause-②: yes (narrowing)
    Thread-read: 5925985857
    Serial constraints cleared:

    Premise, re-measured at claim time (as the landing record 5870707479 orders):

    Seat terms: p3, under the maintainer's 「p3 的卡也可以派了」 (5952442849).

    This PR is Fixes #20301, closing stage 2, the card's last.


    Generated by Claude Code

  12. objectstack-fleet commented on Oct 2, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report

    {
      "issue": 20301,
      "status": "needs_decision",
      "branch": "claude/issue-20301-view-container-name-retired",
      "pr": null,
      "session": "session_01YDt3PzwfrkuFzUBF89WPmM (mode:subagent, the PM's session; identity is the branch named by claim 5952493523, which is the newest Claim: on the card and names this branch)",
      "premise_still_valid": false,
      "summary": "STOPPED at the A2 stop condition, before any tombstone. Nothing was written to the tree. The metadata door itself writes a view container's body `name`. `saveMetaItem` runs `normalizeViewMetadata` (packages/metadata-protocol/src/protocol.ts:1220, stamp at :1227, call at :17256) before the schema gate, and it stamps the save name onto every view body that has none, containers included. A container saved with no name is stored as `{ list, name: 'crm_lead' }`, the by-name read serves that `name` back, and a GET then PUT round trip sends it and is accepted today. The door's own overlay identity paths also READ the body copy. `hydrateOverlayIntoRegistry` (:15990) does not register, or expand, a body that has no `name`. `mergePackageAwareOverlay` (:1835) skips an overlay row with no body `name` and keys its slot by `body.name`. The ObjectQL boot loop (engine.ts:7010) mints `name` onto every stack container it registers. With the tombstone in place, every container save through the door would 422 on the name the door itself stamped. The precondition that the landing record set (`the platform's own writers stop sending a body name`) does not hold, and the card's premise (a `dead` body copy that nobody reads) is false at 1d0600bf66. Two smaller corrections: the metadata-validation sweep does not author a body `name` (the door stamps it), and a 2026-09-03 maintainer ruling refused exactly this spec-level forbid (direction 3). The PM returns to the card; options and the four axes are in open_questions.",
      "tests": "All runs are at worktree HEAD 1d0600bf66 (== BASE, no commits). (1) Build closure: `OS_SKIP_DTS=1 bash scripts/pm/os-verify-lock.sh -c \"pnpm --workspace-concurrency=2 --filter '@objectstack/metadata-protocol^...' build\"` -> `VERDICT command-exit 0 · held the lock 63s`. (2) The pin on main that records the door's stamp: `pnpm --filter @objectstack/metadata-protocol exec vitest run --maxWorkers=2 src/view-container-runtime-expansion.test.ts` -> `Test Files 1 passed (1) / Tests 16 passed (16)`, `VERDICT command-exit 0`. Its case at :252 asserts that the stored row of a nameless container equals `{ ...leadContainer, name: 'crm_lead' }`, with the comment `plus the name the write door has always stamped`. (3) Probe A2(a)/(b): a temporary file, src/zz-probe-20301.test.ts, built on that file's stub engine, run, then deleted. Output: `PROBE stored body keys: list,name name= crm_lead` / `PROBE served body keys: _diagnostics,list,name name= crm_lead` / `PROBE registry container key present: true registered name= crm_lead` / `PROBE GET->PUT round-trip success: true sent body has name: true` / `PROBE hydrateOverlayIntoRegistry(nameless) = false ; with name = true`; `Tests 1 passed`, `VERDICT command-exit 0`. (4) Probe: a body name that differs from the row name, at the runtime door. Temporary file src/zz-probe2-20301.test.ts, deleted after the run. Output: `PROBE2 save error: none` / `PROBE2 rows: crm_lead -> body.name=lead_views` / `PROBE2 registry keys: lead_views,crm_lead.default` / `PROBE2 list names: crm_lead.default`; `VERDICT command-exit 0`. After each deletion `git status --porcelain` printed nothing. (5) Census A2(e) with the TypeScript AST. It finds object literals with a top-level list/form/listViews/formViews and no viewKind/type key, passed to defineView(...), in a `views: [...]` array, or in a View-typed declaration. examples/** + packages/platform-objects (260 files): `containers 10, withName 0`. packages/** production sources (2853 files): `containers 27, withName 0, withObject 24` (control: the key detector reads keys). packages/** including tests (7359 files): `containers 227, withName 90` (lit control: the name detector fires; all 90 are test fixtures). (6) `node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands` -> exit 2, `this branch changes nothing against 'origin/main' (merge base 1d0600bf6) — nothing to derive`. No ablation and no reverse verification: no implementation exists to verify.",
      "mcp_calls": "0",
      "api_writes": "1 — POST issues/20301/comments (this os-dev-report), through scripts/pm/post-stamped.mjs over the fleet-write relay. Reads were REST GET only (the card and its comments, PR #15319, comment 5520462984 -> 404).",
      "gates": [
        "dispatch-gates --commands: exit 2, `this branch changes nothing against 'origin/main' (merge base 1d0600bf6) — nothing to derive`",
        "Zone gates (spec build/check:generated/check:liveness/test/typecheck, consumer suites, check:adr-0087-registration, changeset gates, check:doc-authoring, check:nul-bytes): NOT RUN, reason: stopped at A2 before any edit, so there is no diff to gate",
        "verify-lock runs: build closure VERDICT command-exit 0; view-container-runtime-expansion.test.ts VERDICT command-exit 0 (16/16); probe 1 VERDICT command-exit 0; probe 2 VERDICT command-exit 0"
      ],
      "line_budget": "n/a — no diff; no skills/** or governed file touched",
      "files_changed": "none committed. Two temporary probe files were created and deleted in the worktree (packages/metadata-protocol/src/zz-probe-20301.test.ts, zz-probe2-20301.test.ts); the tree reads clean.",
      "semver": "none — no changeset written, because the stop came before the kit. The A5 level (minor + BREAKING + ADR-0087 marker) was not exercised, and no changeset gate judged anything.",
      "deviations": [
        "The empty branch was pushed per os-dev rule 1 (the write probe) before the A2 stop. origin/claude/issue-20301-view-container-name-retired exists at 1d0600bf66 with zero commits of its own, and no PR is open. The seat may delete it or reuse it.",
        "Zone 1 conflict, reported and not resolved: Zone 1 rules RETIRE for the container `name`. The merged PR #15319 records a maintainer ruling of 2026-09-03 (direction 2 adopted) that explicitly refused `direction 3 (forbid ViewSchema.name on object-scoped containers in spec)`. The PR body says so at its changeset paragraph (`forbidding ViewSchema.name in spec was direction 3, explicitly refused`), and the header of packages/objectql/src/view-container-divergent-name-registrars.test.ts says the same. A tombstone is a superset of direction 3. The ruling comment itself (5520462984, on #14666) answers 404 from this session, so its own text is NOT MEASURED; the PR body and the test header are the surviving records.",
        "Zone 2 A2(d) falsified: the metadata-validation sweep does not author a body `name`. Its view fixture (packages/objectql/src/metadata-validation-sweep.test.ts:164-178) is a nameless container, and `runOne` passes `name: fx.valid.name ?? 'sweep_view'` as the REQUEST name (:392). The door's `normalizeViewMetadata` then stamps it. There is no in-repo writer to `fix` short of the door.",
        "A4 carried notes NOT executed (under the stop, the budget is the report comment only). Locations re-measured at 1d0600bf66: the stale ListView-tabs comment is now packages/spec/src/system/i18n-resolver.ts:2355-2361 (it still says `ListViewSchema.tabs (multi-tab view interface)` is a live carrier); lint `checkTabs` is packages/lint/src/validate-list-view-field-refs.ts:786-799; metadata-protocol `view?.tabs` is packages/metadata-protocol/src/metadata-diagnostics.ts:231. These three do not depend on the container `name` and could ride a separate small PR if the seat wants them.",
        "History questions (when the sweep fixture lost its `name`, when the stamp was added) are NOT MEASURED. The checkout is shallow (`--is-shallow-repository` = true), and the stop does not need them."
      ],
      "a2_census": {
        "a_door_write": "WRITES. packages/metadata-protocol/src/protocol.ts `normalizeViewMetadata` (:1220; `return { ...it, ...(it.name ? undefined : { name: saveName }), ...patch }` at :1227) is called inside `ObjectStackProtocolImplementation.saveMetaItem` at :17256, ahead of the schema gate. For a view `projectStorableViewBody` keeps every key the body carried, so the stamped `name` is persisted. `SysMetadataRepository.put` (sys-metadata-repository.ts:638-640) writes the body verbatim and the row name to the `name` column. Measured: probe 1 stored keys `list,name`. Pinned on main: view-container-runtime-expansion.test.ts:252. The doors that call it do not inject a name: REST PUT /meta/:type/:name (rest-server.ts:7097-7125, request built field by field) and the dispatcher door (runtime/src/domains/meta.ts:1424).",
        "b_read_path": "SERVES AND ROUND-TRIPS IT. `getMetaItem` step 1 serves the stored overlay body, which carries the stamped `name`. Probe 1: served keys `_diagnostics,list,name`, and GET then PUT of that body returns success true while sending `name`. Step 3 (SchemaRegistry) serves the boot loop's copy, and packages/objectql/src/engine.ts `registerMetadataCollections` :7010 `toRegister = item.name === itemName ? item : { ...item, name: itemName }` mints `name` onto every stack container it registers. That half is a code read, and PR #15319's body states the same (`the boot loop's minting of a derived name onto a container that carries none`); it was not driven. The artifact/HMR loader (packages/metadata/src/plugin.ts:1167-1200 `_registerArtifactBodyCollections`) registers a container as authored, with no mint.",
        "door_readers_of_the_body_copy": "protocol.ts `hydrateOverlayIntoRegistry` :15990 (`!('name' in data)) return false` — no registry entry and no `hydrateExpandedViewItems`; probe 1 measured false without a name, true with one) · protocol.ts `mergePackageAwareOverlay` :1835 (overlay row skipped without a body `name`; slot keyed by `body.name`) · protocol.ts `expandRuntimeViewContainer` :16064 and packages/metadata/src/view-container.ts `deriveViewContainerObject` :81 (`name` is the last-resort object binding) · packages/objectql/src/view-container-name-refusal.ts `viewContainerNameRefusal` plus the artifact door's `assertMetadataRegisterContract` (both refuse a divergent container `name`). The ledger row packages/spec/liveness/view.json `name` (status dead, verifiedAt 2026-08-10, `a copy nobody reads`) is therefore falsified by measurement.",
        "c_objectui_at_pin_89cad75d55": "No objectui writer AUTHORS a container body `name`. Studio's view create path emits a ViewItem whose `name` is the qualified id (packages/app-shell/src/views/metadata-admin/anchors.ts:291 `createBuildBody`), a ViewItem key and not the container key. Studio's view list drops containers (packages/app-shell/src/services/builtinComponents.tsx:232 `listFilter: (item) => !isAggregatedViewContainer(item)`). The generic editor's edit mode PUTs the served body back (`{ ...current, ...partial }`, clientValidation.ts:635 comment), so a container opened by direct URL would round-trip the server-served `name`; that is the server's write echoed, not an objectui writer. The adapter `updateView` (packages/data-objectstack/src/index.ts:5864) unwraps `current.list` from a container and writes a flattened overlay, which carries no container `name`. Read from the local objectui clone at the pin commit (git show / git grep).",
        "d_metadata_validation_sweep": "Not a writer. packages/objectql/src/metadata-validation-sweep.test.ts:164-178: the view fixture has no body `name`; :392 passes `name: fx.valid.name ?? 'sweep_' + type` as the request name, and the door stamps it into the body (a_door_write).",
        "e_examples_and_platform_objects": "examples/** + packages/platform-objects: 10 containers, 0 author `name`. packages/** production sources: 27 containers, 0 `name` (24 carry `object`, the control). Authored container `name`s exist only in test fixtures (90 of 227 across packages/** tests: cli, lint and others). Cloud: reading 5925985857 (not re-measured) finds no `name` in service-ai's view artifacts."
      },
      "open_questions": [
        {
          "question": "The view container's body `name` is written by the platform's own metadata door (`normalizeViewMetadata` stamps it on every view save), served back by the by-name read, and read by the door's overlay identity paths (`hydrateOverlayIntoRegistry`, `mergePackageAwareOverlay`). The A2 stop fired, and a 2026-09-03 maintainer ruling refused forbidding `ViewSchema.name` in spec (direction 3). How should stage 2 of #20301 close?",
          "options": [
            "A — Keep the key and correct the record. Flip packages/spec/liveness/view.json `name` from dead to live, with the measured evidence: the writer `normalizeViewMetadata` protocol.ts:1227; the readers `hydrateOverlayIntoRegistry` :15990, `mergePackageAwareOverlay` :1835 and `deriveViewContainerObject`; the boot-loop mint engine.ts:7010. Rewrite its note, regenerate the README counts, and close stage 2 (and the card) as premise falsified, with stage 1 as the card's delivered half. Cost: one ledger row plus the README count, in a small spec PR. liveness/ is in @objectstack/spec `files[]`, so the changeset rule's published-surface test applies to that PR. No tombstone, no conversion, no door change. This is consistent with the 2026-09-03 ruling.",
            "B — Retire anyway by moving the door's view-container identity off the body. Stop the stamp for containers (normalizeViewMetadata). Key overlay rows by the sys_metadata row column instead of `body.name` in hydrateOverlayIntoRegistry, mergePackageAwareOverlay and the other `data.name` callers. This seam is shared by EVERY overlay type, so either it becomes generic, or it becomes a view-only identity path, which is a dialect. Stop the boot loop's mint (engine.ts:7010), or strip it at serve time. Add an ADR-0087 D2 conversion stripping `name` from every stored container row: every door-saved container carries one. That is lossless when it equals the row name; the divergent case has no lossless answer, so it needs a D3 semantic entry. Then the full tombstone kit. Cost: multi-package (metadata-protocol x3 seams on the generic overlay identity path, objectql boot loop, spec kit, conversion), well beyond what the card estimated, plus a maintainer word that supersedes the 2026-09-03 refusal of direction 3.",
            "C — A plus enforcement: keep the key, mark it live, and make the runtime door refuse a container body `name` that differs from the save (row) name. That is the same divergence the 2026-09-03 ruling already refuses at the two SOURCE registrars. Measured open at the runtime door by probe 2: the save is accepted, the row is `crm_lead` with body name `lead_views`, and the container is registered under `lead_views`. Cost: a small metadata-protocol change plus a pin, reusing `viewContainerNameRefusal`'s judgment and words (one judge) instead of a second rule."
          ],
          "recommendation": "A, with C's divergence routed separately as the class-b finding below rather than folded in. By the four axes: (实际业务需求) measured — no author writes it (0 of 10 example containers, 0 of 27 production containers), but the platform's own door writes it on every view save and two door readers key on it, so it is the stored identity copy, not an unused authoring capability, and the RETIRE premise `a copy nobody reads` is false; (项目长远合理性) every overlay type stores `name` in its body, equal to the row (objects, dashboards, pages), so taking it off views alone makes a view-only identity dialect, and B is a re-architecture of the generic overlay identity that deserves its own card if ever; (防 AI 写错) the trap the card names (an AI writes a container `name` that does nothing) does not exist as described, because the key is not inert. The real trap is divergence (body name differs from row name), measured accepted at the runtime door, and C or the finding closes it loudly. A tombstone would make the platform 422 its own stamped writes, the exact `rejected shapes the platform itself writes` failure the schema comment at view.zod.ts:4720-4728 already records; (创业阶段不扩散) A costs one ledger row, B expands far past the card's estimate, and the maintainer's 2026-09-03 ruling already refused the spec-forbid direction. Four-axis conflict to surface: Zone 1's RETIRE verdict and the 2026-09-03 refusal of direction 3 point opposite ways on this key; this report does not pick between them, and that is for the maintainer."
        }
      ],
      "out_of_scope_findings": [
        "class: b · Seam: spec:ViewSchema.name (packages/spec/src/ui/view.zod.ts:4748, `.describe('Item name — supplied by the metadata door; for an object-scoped container it is the object name.')`) → runtime:metadata-protocol saveMetaItem → hydrateOverlayIntoRegistry (protocol.ts:15990) / mergePackageAwareOverlay (protocol.ts:1835) · reach: the save door, measured at the protocol `saveMetaItem` seam that REST PUT /meta/view/:name and the dispatcher door call, with the stub engine of view-container-runtime-expansion.test.ts (not over HTTP): `saveMetaItem({ type: 'view', name: 'crm_lead', item: { name: 'lead_views', list: {...} } })` is accepted with no error, the row is `crm_lead`, the body name is `lead_views`, and the registry keys are `lead_views,crm_lead.default`. One document is filed under two keys. The two SOURCE registrars refuse this same document (objectql `viewContainerNameRefusal`, the artifact door `assertMetadataRegisterContract`, VALIDATION_ERROR/400) under the 2026-09-03 ruling; the third, runtime door does not. · dedupe words: `view container name divergent runtime door`, `saveMetaItem container body name row name mismatch`, `hydrateOverlayIntoRegistry body name key`, `viewContainerNameRefusal metadata door`",
        "carrier: the seat's stage-2 decision on this card · noted, not filed — the liveness ledger row packages/spec/liveness/view.json `name` (dead, verifiedAt 2026-08-10) is falsified by the measurements above (one door writer, two door readers). The correction rides option A or B, whichever the maintainer picks."
      ]
    }

    Generated by Claude Code

  13. objectstack-fleet commented on Oct 2, 2026

    @objectstack-fleet
    ContributorAuthor

    Stage 2: the stop condition fired. The premise is falsified, the retirement is withdrawn, and the stage is re-scoped to a ledger correction (claim amendment)

    domain:spec seat 2 (session_01YDt3PzwfrkuFzUBF89WPmM), holder of claim 5952493523 · 2026-10-02T13:06Z. From the os-dev report 5953000865, which stopped at A2 before any edit. Nothing was committed, and the branch is empty at 1d0600bf66.

    What was measured (file, symbol and probe lines are in 5953000865):

    • The door writes it. metadata-protocol normalizeViewMetadata (protocol.ts:1227, called by saveMetaItem at :17256, ahead of the schema gate) stamps the save name onto every view body that has none, containers included. This is pinned on main: view-container-runtime-expansion.test.ts:252, "plus the name the write door has always stamped".
    • The read path serves it, and a GET then PUT round-trips it. The objectql boot loop mints it onto every stack container (engine.ts:7010).
    • The door reads it. hydrateOverlayIntoRegistry (:15990) does not register a body without name. mergePackageAwareOverlay (:1835) keys its slot by body.name.
    • No author writes it: 0 of 10 example containers, 0 of 27 production containers. Cloud does not send it (5925985857). objectui writes none of its own.

    Why the tombstone is off, by rulings already on record:

    The stage-2 scope from this act (claim amendment; same branch claude/issue-20301-view-container-name-retired):

    1. Correct the ledger. packages/spec/liveness/view.json name: dead → live. Cite the writer and readers above (verifiedAt, measured in-repo). The note says the key is the door-stamped identity copy, and that a divergent body name is refused at the two source registrars under the 2026-09-03 ruling. Regenerate the counts through gen:liveness-counts.
    2. The carried notes from 5870707479, re-located by the dev:
      • the stale ListViewSchema.tabs comment, now packages/spec/src/system/i18n-resolver.ts:2355-2361;
      • lint checkTabs (packages/lint/src/validate-list-view-field-refs.ts:786-799);
      • metadata-protocol view?.tabs (packages/metadata-protocol/src/metadata-diagnostics.ts:231), each deleted if unreachable since stage 1, with their fixtures.
    3. The release: a patch changeset (the ledger ships in @objectstack/spec's files[]) plus each touched package. Clause-②: no. Fixes #20301: stage 1 delivered list.tabs, and this delivers the corrected record.

    ⛔ No tombstone, no conversion, no door change, no view.zod.ts key change.

    Not taken:

    • Taking the identity off the body (the report's option B): stop the stamp, re-key the generic overlay identity path by the row column, add a conversion for every stored container, then the kit. It supersedes a maintainer ruling and is a multi-package re-architecture nobody is pulling for. If ever wanted, it is a new card in the decision box, not this one.
    • The divergence the runtime door accepts (the report's option C) is a defect of its own, filed as a card in this act and named in the next comment.

    The at-tier contract review still follows the PR (packages/spec/src/** is touched by the comment edit).


    Generated by Claude Code

  14. objectstack-fleet commented on Oct 2, 2026

    @objectstack-fleet
    ContributorAuthor

    Correction to 5953063959 item 1: the name row stays dead; only its note is corrected

    domain:spec seat 2 (session_01YDt3PzwfrkuFzUBF89WPmM), holder of claim 5952493523 · 2026-10-02T13:08Z. A seat assumption, falsified within the hour, is corrected here on the same card.

    • What I wrote: flip liveness/view.json name from dead to live.
    • Why that is wrong:
      • The ledger's definition (packages/spec/liveness/README.md:180) reads: "live means authoring the property changes runtime behaviour". An AUTHORED container name restates the registry key or contradicts it.
      • The contradiction is refused at the two source registrars under the 2026-09-03 ruling, whose remedy is "drop name".
      • The runtime door's acceptance of a contradicting one is a defect. It is filed separately, as the next comment names.
      • What the door stamps and keys on is its own identity copy, not an authored value. PR fix(cli)!: os generate binds declared metadata (--object, --flow), never the item name, and every scaffold passes validate, build and lint #21369 (merged) read the same key from its readers and reached dead for the same reason. os validate's liveness-dead-property warning, "drop it", is correct advice for an author and for an AI.
    • Item 1, corrected:
      • name stays dead. Its note is rewritten to the measured facts: the metadata door stamps the save name into the body (normalizeViewMetadata) and its overlay paths key on that stamped copy (hydrateOverlayIntoRegistry, mergePackageAwareOverlay), which replaces the false "a copy nobody reads".
      • The note says why the key is not retired: the door's own writes, the 2026-09-03 refusal of direction 3, and triage's guard. It is kept on the "KEPT deliberately, exempt from enforce-or-remove" precedent the ledger already uses.
      • verifiedAt is updated. No status moves, so state-counts does not move.
    • Unchanged from 5953063959: items 2–3, the "not taken" list, Clause-②: no, a patch changeset, and Fixes #20301.

    Generated by Claude Code

  15. objectstack-fleet commented on Oct 2, 2026

    @objectstack-fleet
    ContributorAuthor

    Pointer from domain:spec seat 2 (session_01YDt3PzwfrkuFzUBF89WPmM) · 2026-10-02T13:09Z, named by 5953063959 and 5953104466. The runtime save door's acceptance of a container body name that contradicts the row name, which the two source registrars refuse under the 2026-09-03 ruling, is filed as #21412 (bare; routing and grading are triage's).


    Generated by Claude Code

  16. objectstack-fleet commented on Oct 2, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report

    {
      "issue": 20301,
      "status": "done",
      "branch": "claude/issue-20301-view-container-name-retired",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/21423",
      "session": "session_01YDt3PzwfrkuFzUBF89WPmM (mode:subagent, the PM's session; identity is the branch named by claim 5952493523, re-scoped by 5953063959 as corrected by 5953104466)",
      "premise_still_valid": true,
      "summary": "Built the reduced stage-2 scope on the same branch, fast-forwarded to origin/main 6d67ad5eca, and opened draft PR #21423 (`Fixes #20301`, `Clause-②: no`). (1) liveness/view.json `name` STAYS `dead`. Only its note is rewritten to the measured facts: the door stamps the save name into the body (normalizeViewMetadata); the overlay paths key on it (hydrateOverlayIntoRegistry, mergePackageAwareOverlay); a contradicting authored value is refused at the two source registrars under the 2026-09-03 ruling and accepted at the runtime door (#21412); and the three reasons it is kept. verifiedAt is now 2026-10-02 and evidenceScope stays cross-repo, with ViewPreview re-read at the pin 89cad75d55. gen:liveness-counts rewrote 0 shards. (2) The carried notes: the stale i18n-resolver comment is corrected; the unreachable list-view `tabs` reads in lint (`checkTabs(listView.tabs, ...)`) and in metadata-protocol `computeViewReferenceDiagnostics` (`view?.tabs`) are deleted with their fixtures, and each keeps its userFilters.tabs walk; the stage-1 absence pin's self-expiring RESIDUE drops the two fixture files. (3) Three patch changesets: spec, lint, metadata-protocol. No tombstone, conversion, door change or view.zod.ts edit.",
      "tests": "All at HEAD 7ee481ef2d (base 6d67ad5eca); every os-verify-lock line reads `VERDICT command-exit 0` unless stated. Build: `pnpm --workspace-concurrency=2 --filter '@objectstack/objectql^...' build` (with declarations, held 267s). Spec: `check:generated` -> `✓ All 15 generated artifacts are up to date`; `typecheck` exit 0 (`SPEC_GENERATED_EXIT=0 SPEC_TYPECHECK_EXIT=0`); `check:liveness` exit 0, `✓ packages/spec/liveness/state-counts/ is current`; `gen:liveness-counts` -> `0 shard(s) rewritten, 0 pruned`, totals `988 live · 3 experimental · 1 live-elsewhere · 109 dead · 10 planned = 1111` (no status moved); `test` -> `Test Files 600 passed (600) / Tests 17601 passed | 1 todo`, including view-list-tabs-retirement.test.ts with RESIDUE reduced to the CLI file. Lint: `test && typecheck` -> `Test Files 119 passed (119) / Tests 5574 passed (5574)`, `check:test-typecheck: OK`. metadata-protocol: `exec vitest run --maxWorkers=2 && typecheck` -> `Test Files 201 passed | 3 skipped (204) / Tests 2983 passed | 19 skipped (3002)`. objectql (test file only): `exec vitest run --maxWorkers=2 src/metadata-diagnostics.test.ts src/view-container-divergent-name-registrars.test.ts src/metadata-validation-sweep.test.ts && typecheck && build` -> `Test Files 3 passed / Tests 23 passed`, `check:test-typecheck: OK`. Derived gates: `dispatch-gates --commands` listed 91; each was run with its exit recorded before any pipe; `--ran` -> `✓ dispatch-gates --ran: 91 derived famil(ies) accounted for — 90 run, 1 NOT-MEASURED`. No ablation: this is a deletion of reads that are unreachable on parsed input, not a new guard.",
      "mcp_calls": "0",
      "api_writes": "4 across both rounds — POST issues/20301/comments (the A2-stop report 5953000865, via post-stamped over the relay); POST repos/objectstack-ai/objectstack/pulls (pr_create, draft forced, via with-fleet.sh --via dispatch, relay run 37019721873; read-back 7882 bytes sent, 7882 stored, identical); POST issues/21423/assignees os-tesla (label-write.mjs over the relay, run 37019851709; read-back MATCHES); POST issues/20301/comments (this report). git push is not counted. No label was added by me.",
      "gates": [
        "node scripts/check-adr-0087-registration.mjs --base origin/main :: exit 0 — `✓ check-adr-0087-registration: this PR adds no declared-breaking changeset (3 non-breaking changeset(s) seen).`",
        "node scripts/check-changeset-no-major.mjs --base origin/main :: exit 0 — `✓ This diff introduces no major bump.`",
        "node scripts/check-empty-changeset.mjs --base origin/main :: exit 0; pnpm check:changeset-gate-self-tests :: exit 0",
        "pnpm check:doc-authoring :: exit 0; pnpm check:nul-bytes :: exit 0; pnpm check:cross-package-test-inputs :: exit 0",
        "pnpm --filter @objectstack/spec run check:liveness / check:api-surface / check:authorable-surface / check:docs / check:variant-docs / check:empty-state / check:exported-any / check:dual-source-exports / check:skill-refs / check:strictness-ledger / check:objectui-pin-citations (+8 more spec check:*) :: all exit 0",
        "pnpm check:lean-entry-closure :: first exit 3 (PREREQUISITE NOT MET: objectql dist absent), re-run after building objectql :: exit 0 — `✓ check-lean-entry-closure: 2 published condition(s) measured from a real load ... Admitted set held exactly (15 packages)`",
        "NOT MEASURED: pnpm check:dual-build-cjs-loads :: exit 3, reason: PREREQUISITE NOT MET — it loads every package's built dist and this run built only the objectql closure (`Run pnpm build first. This is NOT a pass: nothing was measured.`)",
        "NOT MEASURED: node scripts/check-engine-split-ratio.mjs --days 90 :: exit 2, reason: the shallow clone's oldest visible commit (2026-09-18) sits inside the 90-day window (`cannot compute the ADR-0076 D7 trigger metric`). The --ran tally counts this line as run; it measured nothing.",
        "All other 82 derived commands :: exit 0 (record: ran.list reconciled by --ran)",
        "CI at the PR head: in_progress when this report was written (Test Core 1-6, Dogfood 1-3, Temporal Conformance running; Build Docs and Console Pin Gate skipped). Not waited on."
      ],
      "line_budget": "n/a — no skills/** or governed surface touched; diff is 11 files, +88 / -59.",
      "files_changed": [
        ".changeset/20301-spec-view-container-name-ledger-note.md (new, @objectstack/spec patch)",
        ".changeset/20301-lint-list-view-tabs-walk-deleted.md (new, @objectstack/lint patch)",
        ".changeset/20301-metadata-protocol-list-view-tabs-walk-deleted.md (new, @objectstack/metadata-protocol patch)",
        "packages/spec/liveness/view.json (name note + verifiedAt; list.tabs note's follow-up sentence)",
        "packages/spec/liveness/README.md (view cell's name sentence)",
        "packages/spec/src/system/i18n-resolver.ts (comment only)",
        "packages/spec/src/ui/view-list-tabs-retirement.test.ts (RESIDUE drops the two deleted fixtures)",
        "packages/lint/src/validate-list-view-field-refs.ts (list.tabs call deleted; header prose)",
        "packages/lint/src/validate-list-view-field-refs.test.ts (list.tabs fixtures and HARD_CODED_FILTER_WALKS row deleted)",
        "packages/metadata-protocol/src/metadata-diagnostics.ts (view?.tabs read deleted)",
        "packages/objectql/src/metadata-diagnostics.test.ts (list.tabs fixtures deleted; the deleted-read case now asserts the surviving userFilters.tabs read)"
      ],
      "semver": "patch x3 (@objectstack/spec, @objectstack/lint, @objectstack/metadata-protocol). Each changeset carries `Clause-②: no`, matching the PR body's second line. No ADR-0087 marker is owed, because there is no breaking changeset. Gate lines: `✓ check-adr-0087-registration: this PR adds no declared-breaking changeset (3 non-breaking changeset(s) seen).` and `✓ This diff introduces no major bump.` objectql gets no changeset: test-only change, and its files[] is dist/README/CHANGELOG.",
      "deviations": [
        "Scope reading: besides the name note, I corrected two neighbouring ledger sentences that carry the same false claims. The README `view` cell said `the platform's own writers send name (artifact-shipped containers, the metadata-validation sweep)`. The list.tabs row's note said the two walks `are left for their own follow-up`. The spec-property-retirement skill's correction rule requires the README row to follow a ledger correction. Both are prose; no status changed.",
        "lint header prose that listed `tabs[].filter` and `tabs[].view` as walked positions, and the lint test's comments that counted `three` hard-coded walks, were updated to match the deletion.",
        "The objectql case `flags tab filter rules pointing at unknown fields` was converted, not just deleted. It now asserts the same unknown field on the surviving `userFilters.tabs` read, which had no negative case in that file.",
        "Not merged with origin/main (declared narrowing). ceb4a939b4 is 7 commits ahead of base 6d67ad5eca, and `git diff --stat 6d67ad5eca ceb4a939b4` over the 11 paths is empty; CI's merge ref judges the combination.",
        "`default PR labels` was read through os-dev's label rule (named labels + skip-changeset by its criterion): no label was named and skip-changeset does not apply (three changesets), so my label-write carried only `--assign os-tesla`. The automation's path/size labels (documentation, size/m, tests, tooling, protocol:ui, protocol:system) were already on the PR at read-back; I wrote none of them.",
        "Commit trailers: the model-free pair (`Claude-Session` + `Co-authored-by: Claude`) per AGENTS.md and the pre-push hook, not the harness reminder's model-named `Co-Authored-By` line; neither commit names a card.",
        "The worktree was removed after the PR opened (node_modules deleted, `git worktree remove` without --force, exit 0)."
      ],
      "open_questions": [],
      "out_of_scope_findings": [
        "carrier: the next PR that touches the ViewSchema guidance block, else none · noted, not filed — packages/spec/src/ui/view.zod.ts, about lines 4720-4728 (the comment above `guidance:` in ViewSchema), still says `saveMetaItem sends the name, artifact-shipped containers do (service-ai/ai_traces), the validation sweep injects it`. Measured: only the door's stamp is real. It is the same misattribution this PR corrects in the ledger, left in place by this stage's no-view.zod.ts scope. Also in the PR's Acceptance notes.",
        "carrier: objectui's next pin bump · noted, not filed — objectui's `tabs?: ListViewSchema['tabs']` mirror (types objectql.ts) is objectui's, as carried from 5870707479; named in the PR's Acceptance notes."
      ]
    }

    Generated by Claude Code

  17. objectstack-fleet commented on Oct 2, 2026

    @objectstack-fleet
    ContributorAuthor

    ACCEPT — PR #21423 @ 7ee481ef (stage 2, as re-scoped)

    domain:spec seat 2 (session_01YDt3PzwfrkuFzUBF89WPmM), holder of claim 5952493523 · 2026-10-02T14:51Z

    • Shape (read on GitHub): a draft against main. The first line is Fixes #20301, and Clause-②: no sits at a line start. 11 files, +88 / −59, all inside the re-scope 5953063959 as corrected by 5953104466. The two neighbouring ledger sentences that carried the same false claim (the README.md view cell and the list.tabs note's follow-up sentence) are corrected with them, by the playbook's correction rule.
    • Contract review: at-tier PASS 5954879465 on this exact head.
    • CI on 7ee481ef: 32 success and 3 skipped by design (Build Docs path-filtered, Console Pin Gate with no .objectui-sha change, and the opt-in packed-tarball smoke).
    • Governed surface: check-governed-merges --pr 21423 reads NOT governed, 147 changed lines.
    • The re-scope, item by item:
      • liveness/view.json name stays dead. Only its note is rewritten to the measured facts: the door stamps the save name into the body, the overlay paths key on that stamped copy, and an authored value restates the key or contradicts it. The note gives why the key is kept. No status moved (gen:liveness-counts: 0 shards rewritten).
      • Stage 1's carried residue is gone:
        • the stale i18n-resolver.ts comment is corrected;
        • the unreachable list.tabs reads in lint and metadata-protocol are deleted with their fixtures, each keeping its userFilters.tabs walk;
        • the stage-1 absence pin's RESIDUE drops the two files.
      • Releases: three patch changesets (spec, lint, metadata-protocol).
      • ⛔ Not changed: no tombstone, conversion, door change or view.zod.ts key change.
    • Prose read sentence by sentence by this seat: the name note and the three changesets.

    Out-of-scope findings:

    Next: ready, auto-merge, the queue. On landing this card closes: stage 1 delivered list.tabs, and stage 2 delivers the corrected record.


    Generated by Claude Code

  18. objectstack-fleet commented on Oct 2, 2026

    @objectstack-fleet
    ContributorAuthor

    Landed: PR #21423 → bdd3654f29 (stage 2, the card's last)

    domain:spec seat 2 (session_01YDt3PzwfrkuFzUBF89WPmM), holder of claim 5952493523 · 2026-10-02T15:20Z


    Generated by Claude Code

  19. added 2 commits that reference this issue on Oct 7, 2026
    bdd3654
    db87a02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

area:recordsBusiness objects, records, the views that show data, usable forms, searchbugSomething isn't workingdomain:specpriority:p3

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions