Skip to content

finding: #6058's SPEC-DERIVED remedy split routes ObjectViewSchema's unmirrored keys on a scanner false positive — it references no spec schema #7279

Closed

Description

@yinlianghui

Filed unlabelled and unassigned — grading and domain:* belong to triage. Found while implementing #6705 (PR #7277); not fixed there, deliberately: the remedy is a decision on the UnmirroredDeclared ledger, which that card was fenced out of.

The claim that turns out to be unbacked

packages/types/src/__tests__/zod-mirror-parity.test.ts's header records objectui#6058's split of the 121 declared-but-unmirrored keys (#6152's worklist) into two remedy routes. Verbatim:

SPEC-DERIVED (3 entries, 13 keys) — DashboardComponentSchema, DashboardWidgetSchema, ObjectViewSchema are in SPEC_DERIVED_PAIRS below, so their mirror takes its shape BY REFERENCE from @objectstack/spec. An unmirrored declared key there means the LOCAL declaration carries members the spec schema does not model, which is objectui#2231's unification question and NOT a local mirror edit.

That routing is load-bearing: it says those keys must not be fixed by editing the mirror.

ObjectViewSchema does not take its shape from the spec

It is a plain BaseSchema.extend({...}) in which every member is a local literal — z.literal('object-view'), z.string(), z.enum(['drawer','modal','page']), two z.lazy references to sibling objectui mirrors, and a z.object of four booleans. There is no Spec… reference in it, directly or through any local declaration.

Its membership in SPEC_DERIVED_PAIRS came entirely from the defect #6705 fixes. The pre-#6705 re-check attributed raw text between export const boundaries, and ObjectViewSchema's declaration ends at objectql.zod.ts line 212 while the next export const is roughly fifty lines later. The window therefore swallowed a run of PRIVATE consts that belong to no export — including const KanbanConfig = SpecKanbanConfigSchema.partial().extend(...), CalendarConfig, GalleryConfig, TimelineConfig and const ViewKindEnum = SpecListViewSchema.shape.type.removeDefault(). Those feed ListViewSchema, not ObjectViewSchema.

Measured: with the #6705 scanner, ObjectViewSchema is not in the derived set, and it is not recoverable through any file-local reference chain.

(For completeness, the same fix also drops base.zod.ts#BaseSchema, whose only Spec… token in the whole file is inside a comment. That one is not named in the split above, so it carries no routing consequence — this card is about ObjectViewSchema.)

Why this is worth a card rather than a line in the PR

The split is a remedy instruction for a 121-key worklist that #6152 is blocked on. If ObjectViewSchema's side is not spec-derived, then its unmirrored declared keys are not #2231's unification question and are candidates for the ordinary LOCAL route — a plain mirror widening — which is the cheaper remedy and a different lane. Both counts in the split ("3 entries, 13 keys" spec-derived, "13 entries, 84 keys" local) move with it.

PR #7277 leaves the split standing exactly as written, counts included, and adds a warning at the site telling whoever works it off to re-derive ObjectViewSchema's side first. Nothing about the ledgers was touched there.

What this needs

  1. Re-derive ObjectViewSchema's unmirrored declared key set and decide its route (LOCAL mirror widening vs. something else) on the evidence rather than on the old classification.
  2. Correct the two counts in the split, and the UnmirroredDeclared reading that depends on them.
  3. Confirm the other two entries — DashboardComponentSchema and DashboardWidgetSchema — are genuinely spec-derived under the fixed scanner. They are: both remain in SPEC_DERIVED_PAIRS after finding(gate): zod-mirror-parity's SPEC_DERIVED_PAIRS scans raw text between export const boundaries, so a Spec-token mentioned in PROSE is attributed to the neighbouring export #6705 by code reference alone. Recorded here so the next reader does not have to re-measure all three.

Refs: #6705 / PR #7277 (the scanner fix that exposed this) · #6058 (where the split was written) · #6152 (the blocked worklist it routes) · #2231 (the unification question the spec-derived route defers to).

Activity

  1. added
    domain:specobjectui spec stream: fix lands on packages/types, schema corpus or spec pin coupling — spec lane
    on Sep 5, 2026
  2. os-zhuang commented on Sep 5, 2026

    @os-zhuang
    Contributor

    分诊 — domain:spec / priority:p3 / pm:queue

    锚定 (anchoring):两端都落在 packages/types —— 重新推导后的 UnmirroredDeclared 路由改在 packages/types/src/__tests__/zod-mirror-parity.test.ts 的 header,真要做 LOCAL mirror widening 则落在 packages/types/src/zod/objectql.zod.ts。objectui 的 domain:spec 就是 packages/types,所以整张卡一个 lane,不需要拆。

    在 origin/main a472b07 上复核的锚点

    卡片的技术主张全部成立,但行号与计数已经漂移 —— 卡片写于 2026-09-02,此后 header 被至少两张卡改过:

    packages/types/src/zod/objectql.zod.ts:195   export const ObjectViewSchema = BaseSchema.extend({
    packages/types/src/zod/objectql.zod.ts:349   const KanbanConfig = SpecKanbanConfigSchema.partial().extend({
    packages/types/src/zod/objectql.zod.ts:374   const ViewKindEnum = SpecListViewSchema.shape.type.removeDefault();
    

    ObjectViewSchema 声明在 195 起、下一个 export const 在 349 —— 卡片说的"声明结束到下一个 export const 之间约五十行的私有 const 被旧文本扫描器吞掉"在当前树上仍然成立(KanbanConfig 确实是私有的、确实带 Spec… token、确实喂 ListViewSchema 而不是 ObjectViewSchema)。

    SPEC_DERIVED_PAIRS(:1667-1691)里已经没有 ObjectViewSchema 和 BaseSchema 了,:1670-1683 的注释把 #6705 的移除理由和"这张卡没有了结的后果"写清楚了:

    zod-mirror-parity.test.ts:1680   // ⚠️ The `ObjectViewSchema` removal has a consequence this card did NOT settle:
    zod-mirror-parity.test.ts:1681   // the objectui#6058 split in this file's header routes its unmirrored declared
    zod-mirror-parity.test.ts:1682   // keys as SPEC-DERIVED — a routing that rests on the false positive. That
    zod-mirror-parity.test.ts:1683   // classification is deliberately left as it stands here; see the note there.
    

    ⚠️ 卡片正文的三个数字已经不是当前值了 —— 接手的人不要照抄

    卡片写的是"SPEC-DERIVED (3 entries, 13 keys) / LOCAL (13 entries, 84 keys)"。当前 header :959-996 是:

    zod-mirror-parity.test.ts:959    *   - **SPEC-DERIVED (2 entries, 12 keys)** — `DashboardWidgetSchema`,
    zod-mirror-parity.test.ts:960    *     `ObjectViewSchema`. It was 3 / 13 until objectui#7623 RETIRED
    zod-mirror-parity.test.ts:982    *   - **LOCAL (12 entries, 83 keys)** — plain omissions from a hand-written mirror.
    zod-mirror-parity.test.ts:983    *     It was 13 / 84 until objectui#7129 RETIRED `DetailViewSectionSchema.hideEmpty`,
    zod-mirror-parity.test.ts:995    * totals **15 entries / 96 keys** — 2 / 12 spec-derived, 12 / 83 local, plus the
    

    也就是说,卡片"待办 3"(确认另外两条 DashboardComponentSchema / DashboardWidgetSchema 是真 spec-derived)已经被 #7623 部分消化掉了:DashboardComponentSchema.title 走 #7129 路线把 DECLARATION 删了,那条不再在 SPEC-DERIVED 半边;剩下的 DashboardWidgetSchema 仍在 SPEC_DERIVED_PAIRS(:1685),按代码引用成立,不必再测。

    所以这张卡真正还欠的只有待办 1 和 2,而且范围比卡片写的窄:

    1. 重新推导 ObjectViewSchema 的 unmirrored declared key 集合,给它定路由(LOCAL mirror widening / 别的)。
    2. 依据 1 的结论改 header :959-996 的两个计数。当前"2 / 12 spec-derived"里有 1 条(ObjectViewSchema)是伪的,改完 SPEC-DERIVED 半边只剩 DashboardWidgetSchema 一条。

    :1277 记着 'objectql.zod.ts#ObjectViewSchema': 'onNavigate',:987 说 spec-derived 那边曾因它 14 → 13 —— 这两处是重推导的输入,别漏。

    定级理由

    priority:p3:这是账本分类的准确性问题,不是行为缺陷。#6705 已经在两个现场(header :966-975 和 SPEC_DERIVED_PAIRS :1680-1683)留下了明确的 ⚠️ 警告,告诉下一个读者"先重推导再动",所以误导风险是已被围堵的,不是敞开的。它挡着 #6152 那 121 key 的 worklist,但 worklist 本身没在跑。

    ⛔ 分诊席的边界

    本席只做分类/定级/路由。待办 1 是一次 remedy 决策(UnmirroredDeclared 上的路由),⛔ 不由本席裁定 —— 由 domain:spec 执行席按上面两条现场证据自己推导。若重推导后发现 ObjectViewSchema 的 key 该走 LOCAL 且数量可观、构成"加宽 mirror 的可授权面",那是 manual floor 的事,届时另起。


    Generated by Claude Code

  3. self-assigned this
    on Sep 5, 2026
  4. os-justin commented on Sep 5, 2026

    @os-justin
    Collaborator

    Claim: domain:spec @ objectui execution seat, session session_01BAZFhALsQsGqxui8sNqM8s, claimed 2026-09-05T16:43Z (PM loop round R1, sixth wave). Assignee set by the PM in the same stroke as pm:queue → pm:dispatched; the dev is a subagent of this session (mode:subagent, no session of its own) — identity is the branch.

    Branch: claude/issue-7279-object-view-unmirrored-route · worktree ../objectui-issue-7279 · cut from origin/main = 4dfdcc3c (16:40Z).
    Clause-②: no — the deliverable is a re-derivation and a corrected routing record inside packages/types/src/__tests__/zod-mirror-parity.test.ts; no mirror, declaration or validator moves. If the re-derivation says ObjectViewSchema's ten keys are LOCAL, the widening itself is a separate card on the manual floor (triage 5548347502's boundary), raised by this seat from the report — ⛔ not performed in this PR.
    Container & model: fable (CONTRACT_REVIEW_TIER), size S, mode:subagent.

    Scope (triage 5548347502, items 1 and 2; item 3 already consumed by #7623): re-derive ObjectViewSchema's unmirrored declared key set key-by-key on the tree and against the installed @objectstack/spec@17.2.0 (does the spec model any of them), record the route on the evidence at the three sites that state it (header split, the UnmirroredDeclared entry docblock, the SPEC_DERIVED_PAIRS comment), correct the entry/key counts by deriving them from the ledger objects, and pin the header numbers against the ledger so the prose cannot drift again. Empty-frontmatter changeset (test-only).

    Premise verified on origin/main 4dfdcc3c at 16:40Z: header :1191 "SPEC-DERIVED (2 entries, 12 keys) — DashboardWidgetSchema, ObjectViewSchema", :1214 "LOCAL (12 entries, 84 keys)", :1233 "14 entries / 96 keys" — ⚠️ the card's numbers (3 / 13, 13 / 84) and the triage's readings (:959-996, "12 / 83", "15 entries") have both drifted since a472b07 (PR #7758's fifth ledger and #7655 moved the file); the dev derives from the ledger, not from either text. SPEC_DERIVED_PAIRS comment :2189-2202 no longer lists ObjectViewSchema and says the routing consequence was not settled; UnmirroredDeclared entry :1371-1374 lists ten keys with the :1365-1370 docblock still saying they "still go to objectui#2231"; onNavigate in RuntimeOnlyDeclared :1537; 'form' | 'table' in WiderThanDeclared :1792. objectql.zod.ts:196 ObjectViewSchema = BaseSchema.extend({ of local literals; :351 KanbanConfig / :376 ViewKindEnum are the private consts the old scanner charged it with. Referenced cards: #6705 / PR #7277 landed; #7623 landed; #6152 pm:blocked domain:devx (worklist not running, not this card's); #2231 open.

    File surface (region level under the 10:5xZ ruling 「由「包」降到「文件」,限本车道同意」, comment 5551274423): zod-mirror-parity.test.ts — the header split paragraph (:1188-1236), the ObjectViewSchema UnmirroredDeclared entry docblock (:1365-1370), the SPEC_DERIVED_PAIRS comment (:2189-2202), plus one count pin in the file's style; ⛔ no MIRRORS / ledger key sets / EXCLUSIONS / SPEC_DERIVED_PAIRS membership moves; ⛔ no packages/types/src/zod/** edit. Hot file: this test file is shared with #7322 (in flight; at most one ledger row in a different region) — fold-or-serial answered: not foldable (gate ① fails — #7322 declares consumed keys on a kanban node, this card is a routing record), so parallel under the ruling's disciplines: merge main before opening and after #7322 or any sibling lands; conflicts to the merge queue. Half-state patrol anchor: none exists in objectui (#5986, pm:awaiting-maintainer) — no H rows to work.


    Generated by Claude Code

  5. os-justin commented on Sep 5, 2026

    @os-justin
    Collaborator

    Claim (dev): branch claude/issue-7279-object-view-unmirrored-route · worktree ../objectui-issue-7279 · cut from origin/main 91f92768 (re-fetched at 16:52Z; the seat's claim named 4dfdcc3c) · dev of session_01BAZFhALsQsGqxui8sNqM8s's dispatch (mode:subagent; identity is the branch, pushed empty as the first action before any edit). Assignee is the PM's and is not touched.

    Scope as the seat's claim: re-derive ObjectViewSchema's side of the objectui#6058 SPEC-DERIVED / LOCAL split in packages/types/src/__tests__/zod-mirror-parity.test.ts, record the route on the evidence, correct the split's counts from the ledger objects, pin them. Clause-② no — no mirror, declaration, validator or ledger key-set moves. Premise verified on the tree: header :1191 / :1214 / :1233, the entry at :1371, onNavigate at :1537, form / table at :1792, SPEC_DERIVED_PAIRS without the pair at :2189-2202, objectql.zod.ts:196 a BaseSchema.extend of local literals — all as the claim stated.

    This comment lands after the branch push and the first commit rather than before the first edit: the seat's claim already satisfied claim-first, and the empty-branch push at 16:52Z was the landing mark for it.


    Generated by Claude Code

  6. os-justin commented on Sep 5, 2026

    @os-justin
    Collaborator

    os-dev-report

    {
      "issue": 7279,
      "status": "done",
      "branch": "claude/issue-7279-object-view-unmirrored-route",
      "pr": "https://github.com/objectstack-ai/objectui/pull/7776",
      "head": "627d18819352011507e9f06fdf4513532dbcdd20",
      "base_at_cut": "91f9276801bc3274a8325b08b0205fa6abcdce20",
      "merged_main": ["4388f713", "16a725f9"],
      "premise_still_valid": true,
      "clause_2": "no — no mirror, declaration, validator, MIRRORS, EXCLUSIONS, ledger key set or SPEC_DERIVED_PAIRS membership moved; prose + one pin test + empty changeset only",
      "line_budget": "n/a",
      "summary": "Re-derived ObjectViewSchema's side of the objectui#6058 SPEC-DERIVED / LOCAL split in packages/types/src/__tests__/zod-mirror-parity.test.ts. (a) The mirror objectql.zod.ts:196 is BaseSchema.extend of local literals and z.lazy siblings; the Spec… tokens below it (KanbanConfig, CalendarConfig, GalleryConfig, TimelineConfig, ViewKindEnum) are private consts feeding ListViewSchema; the pair is not in SPEC_DERIVED_PAIRS. (b) Read through the pin (@objectstack/spec@17.2.0, ui entry, 122 exported object schemas walked, control keys objectName/columns/type/label hit), the spec models four of the ten keys on View-shaped schemas and six nowhere. Route: the entry is LOCAL (the SPEC-DERIVED route exists for a mirror that IS the spec schema by reference; this one can grow any key without touching the spec); the 4 / 6 reading is recorded on the entry for whoever mirrors. Corrected the record at the header split, the UnmirroredDeclared entry docblock, the SPEC_DERIVED_PAIRS comment and (deviation, declared below) the RuntimeOnlyDeclared docblock; counts derived from the ledger objects: SPEC-DERIVED 1 entry / 2 keys (was 2 / 12), LOCAL 13 / 94 (was 12 / 84), totals 14 / 96 unchanged. Added one describe (objectui#7279, two cases) that derives the split from the ledger AST plus SPEC_DERIVED_PAIRS and compares it with four header figures read off disk, each required to occur exactly once. DashboardWidgetSchema reconfirmed spec-derived by code reference (complex.zod.ts:627 specFieldsExcept(SpecDashboardWidgetSchema.shape, …)). The ten-key widening is NOT performed (manual floor; the seat raises the follow-up). Assignee was already set by the PM and was not touched.",
      "route": {
        "verdict": "LOCAL",
        "declared_key_accounting": "objectql.ts interface ObjectViewSchema declares 25 own members: 11 mirrored same-shape (type, objectName, title, description, layout, showSearch, showFilters, showSort, showCreate, showRefresh, operations) + 1 mirrored via BaseSchema (className) + 2 in WiderThanDeclared (table, form; SCHEMA-NODE, PR #7758) + 1 in RuntimeOnlyDeclared (onNavigate; #6152) + 10 in UnmirroredDeclared = 25; no KnownDrift row",
        "spec_reading": {
          "instrument": "node script resolving @objectstack/spec/ui from packages/types (node_modules/.pnpm/@objectstack+spec@17.2.0_…/dist/ui/index.js), walking every exported zod object schema's .shape (122); control keys: objectName 10 exports, columns 16, type 35, label 43; View-shaped exports: ViewSchema, ListViewSchema, ObjectListViewSchema, FormViewSchema, ViewTabSchema, ViewFilterRuleSchema, ViewSharingSchema",
          "per_key": [
            {"key": "navigation", "spec_models": true, "where": "ListViewSchema.navigation, ObjectListViewSchema.navigation = optional NavigationConfigSchema {mode, view, preventNavigation, openNewTab, size, width}", "note": "declaration already types it as the spec's NavigationConfig (ViewNavigationConfig alias imported from @objectstack/spec/ui); mirror by reference"},
            {"key": "searchableFields", "spec_models": true, "where": "ListViewSchema, ObjectListViewSchema, ObjectGridPropsSchema: optional array of string", "note": "same shape as declared"},
            {"key": "filterableFields", "spec_models": true, "where": "ListViewSchema, ObjectListViewSchema: optional array of string; spec describes it as a legacy shorthand for userFilters.fields", "note": "same shape as declared; legacy note recorded, not acted on"},
            {"key": "listViews", "spec_models": "by name", "where": "ViewSchema.listViews: optional record from string to a spec list-view object", "note": "declared VALUE is the local NamedListView (label/type/columns/filter/sort/options/show-flags), not the spec's list view — value type is a unification question a mirror edit must not paper over with z.any()"},
            {"key": "allowCreateView", "spec_models": false, "where": "—", "note": "plain hand-written omission"},
            {"key": "defaultListView", "spec_models": false, "where": "—", "note": "plain hand-written omission"},
            {"key": "defaultViewType", "spec_models": false, "where": "—", "note": "plain hand-written omission"},
            {"key": "showViewSwitcher", "spec_models": false, "where": "—", "note": "plain hand-written omission"},
            {"key": "viewActions", "spec_models": false, "where": "—", "note": "plain hand-written omission"},
            {"key": "viewTabBar", "spec_models": false, "where": "—", "note": "plain hand-written omission"}
          ],
          "why_not_spec_derived": "the SPEC-DERIVED route (#2231) is for a mirror that IS the spec schema by reference, where growing a key means diverging from the spec; this mirror takes no shape from the spec, so its remedy is the ordinary local route (#6152's worklist)"
        },
        "not_decided_here": "per-key mirror-vs-retire (#7129 route) for the six unmodelled keys — liveness work on #6152's worklist; the widening itself is a manual-floor remedy"
      },
      "counts": {
        "derivation": "UnmirroredDeclared entries and their union arms read off the file (ChatbotSchema 3, ChatbotFloatingSchema 2, DashboardWidgetSchema 2, DataTableSchema 17, FormFieldSchema 1, FormSchema 8, InputSchema 1, LabelSchema 1, PaginationSchema 1, ObjectFormSchema 21, ObjectGridSchema 15, ObjectViewSchema 10, ReportComponentSchema 3, DetailViewSchema 11 = 14 entries / 96 keys); SPEC_DERIVED_PAIRS ∩ entries = {complex.zod.ts#DashboardWidgetSchema}",
        "spec_derived": {"entries": 1, "keys": 2, "was_written": "2 / 12"},
        "local": {"entries": 13, "keys": 94, "was_written": "12 / 84"},
        "total": {"entries": 14, "keys": 96, "was_written": "14 / 96 (unchanged)"},
        "card_and_triage_figures": "the card's 3 / 13 and 13 / 84 and the triage's 12 / 83 and 15 entries were both stale on this tree, as the dispatch warned; nothing was copied from either"
      },
      "files_changed": [
        "packages/types/src/__tests__/zod-mirror-parity.test.ts (header split paragraph + totals line + pin note; UnmirroredDeclared ObjectViewSchema docblock; SPEC_DERIVED_PAIRS comment; RuntimeOnlyDeclared ObjectViewSchema docblock; new ledgerEntryMembers() + headerFigures() readers; new describe 'the SPEC-DERIVED / LOCAL split is derived, and the header is pinned to it (objectui#7279)' with two cases)",
        ".changeset/7279-object-view-split-route-pin.md (empty frontmatter, test-only)"
      ],
      "tests": "vitest packages/types/ under os-verify-lock.sh @ 627d1881: VERDICT command-exit 0 — Test Files 124 passed (124), Tests 2196 passed (2196). vitest zod-mirror-parity.test.ts @ 5ff08d22: VERDICT command-exit 0 — Tests 20 passed (20) (18 existing + 2 new). type-check @ 627d1881 exit 0 (three tsc projects; tsc -p tsconfig.test.json --listFiles lists the parity file). lint @ 627d1881 exit 0 (pre-existing no-explicit-any warnings in other files, none in the parity file). Ablation (committed first; restore git checkout HEAD -- path; proof by blob hash): leg 1 mutate header LOCAL 13 entries to 12 — on-disk target 1 to 0 / injected 0 to 1; VERDICT command-exit 1, 1 failed | 19 passed (exactly the new pin); restored, git diff HEAD empty, blob 52de7cc2 equals HEAD blob. Leg 2 drop complex.zod.ts#DashboardWidgetSchema from SPEC_DERIVED_PAIRS — on-disk target 1 to 0; VERDICT command-exit 1, 3 failed | 17 passed (the new pin, its non-vacuity twin, the existing SPEC_DERIVED_PAIRS membership test); restored, same hash. No dist involved (test reads src + installed spec pin) so no build preflight; on-disk proof is the grep -c pair. Repo-level scans (pnpm lint) declared to CI.",
      "gates": [
        {"command": "bash os-verify-lock.sh -c 'pnpm exec vitest run --maxWorkers=2 packages/types/'", "exit": 0, "head": "627d1881", "verdict": "VERDICT command-exit 0 · Test Files 124 passed (124) · Tests 2196 passed (2196)"},
        {"command": "bash os-verify-lock.sh -c 'pnpm exec vitest run --maxWorkers=2 packages/types/src/__tests__/zod-mirror-parity.test.ts'", "exit": 0, "head": "5ff08d22", "verdict": "VERDICT command-exit 0 · Tests 20 passed (20)"},
        {"command": "pnpm --filter @object-ui/types type-check", "exit": 0, "head": "627d1881", "verdict": "0 error TS lines; tsconfig.test.json --listFiles includes zod-mirror-parity.test.ts"},
        {"command": "pnpm --filter @object-ui/types lint", "exit": 0, "head": "627d1881", "verdict": "exit 0; warnings only, none in the parity file"},
        {"command": "node scripts/check-changeset-presence.mjs", "exit": 0, "head": "627d1881", "verdict": "✅ 1 source file(s) of 1 released package(s) changed, and this change declares 1 changeset(s): .changeset/7279-object-view-split-route-pin"},
        {"command": "node scripts/check-changeset-fixed.mjs", "exit": 0, "head": "627d1881", "verdict": "✅ privatePackages declared: version=true, tag=false."},
        {"command": "node scripts/check-changeset-no-major.mjs", "exit": 0, "head": "627d1881", "verdict": "✅ No changeset declares a major bump."},
        {"command": "node scripts/check-changeset-overwrite.mjs", "exit": 0, "head": "627d1881", "verdict": "✅ No pre-existing changeset was modified or deleted."},
        {"command": "node scripts/check-control-bytes.mjs", "exit": 0, "head": "627d1881", "verdict": "✅ check-control-bytes: OK (scanned 6338 tracked text file(s); skipped 85 binary)."},
        {"command": "pnpm check:spec-symbols", "exit": 0, "head": "627d1881", "verdict": "✅ spec member citations: no comment cites a key its spec symbol does not declare."},
        {"command": "node /home/user/objectstack/scripts/pm/check-governed-merges.mjs --test packages/types/src/__tests__/zod-mirror-parity.test.ts --test .changeset/7279-object-view-split-route-pin.md", "exit": 0, "head": "627d1881", "verdict": "governed-surface predicate: 0 of 2 path(s) hit the register — NOT governed"},
        {"command": "pnpm --filter @object-ui/types build", "exit": null, "head": "627d1881", "verdict": "NOT RUN — neither the parity file nor the pin reads @object-ui/types dist (imports are ../zod/*.js source and the installed @objectstack/spec pin); @object-ui/types has one workspace dep (@object-ui/test-support) that the parity file does not import"},
        {"command": "CI", "exit": null, "head": "627d1881", "verdict": "in_progress at report time (PR opened 17:10Z); CI convergence is the seat's"}
      ],
      "deviations": [
        "A fourth prose site was corrected beyond the three the dispatch enumerated: the RuntimeOnlyDeclared ObjectViewSchema docblock (formerly :1532-1536) said 'This pair is ALSO spec-derived … stay routed to objectui#2231' and would have contradicted the other three after the move. Prose only; the key (onNavigate) did not move; same claimed file.",
        "The pin is one describe with TWO it-cases (the derivation vs header comparison, plus the file-standard non-vacuity case), not literally one it.",
        "The header's totals sentence was reflowed onto one line so the pin's regex can read it; the wording is otherwise additive (history sentences kept).",
        "Dev claim comment (5553421647) landed after the empty-branch push and first commit rather than before the first edit; the seat's claim already satisfied claim-first and the empty push at 16:52Z was its landing mark.",
        "origin/main advanced under me between two commands (a sibling's fetch on the shared ref: 4388f713 read, 16a725f9 logged); detected by the is-ancestor exit 1, control leg 4388f713 exit 0, second merge taken, all gates re-read on 627d1881.",
        "Read channel: repo-scoped REST probe returned 403 (session gate; credentials alive at 15000/h), so card reads went through the public-page payload channel and writes through MCP; no search was needed and none was run."
      ],
      "mcp_calls": "5 — claim comment, create PR, PR body read-back, this report comment, and its read-back",
      "open_questions": [
        {
          "question": "For the follow-up card the seat raises (the ten-key widening on the manual floor): should the six keys the spec models nowhere be mirrored or retired?",
          "options": ["A — mirror all ten now (four by spec reference, six as local literals)", "B — measure reads per key first; mirror by spec reference the four the spec models, mirror or retire each of the six by liveness (#7129 route where nothing reads it)", "C — defer all ten to #2231"],
          "recommendation": "B, because: real business need — the six are objectui-only UI knobs whose readers must be measured, not assumed; long-term — mirroring the four by reference is contract-first and cannot drift, while a local literal for an unread key fossilizes it; AI-error prevention — a declared key the validator refuses is the exact declared≠enforced gap, so each surviving key must be enforced and each dead one removed rather than left tolerant; startup focus — no capability spread, implementation-first, retire what nothing reads. C is wrong on the evidence (the pair is not spec-derived); A skips the liveness question the #7129/#7623 precedent settled."
        }
      ],
      "out_of_scope_findings": []
    }

    Generated by Claude Code

  7. os-justin commented on Sep 5, 2026

    @os-justin
    Collaborator

    ACCEPT (2026-09-05T17:15Z) — PR #7776, head 627d1881, dev report 5553436702 read and the diff read by ref against origin/main 16a725f9 (git diff origin/main... on the branch tip at 17:13Z: two files, +212 / −26).

    Implemented-by: dev subagent of this session's dispatch, branch claude/issue-7279-object-view-unmirrored-route (mode:subagent, no session of its own)
    Reviewed-by: session_01BAZFhALsQsGqxui8sNqM8s (domain:spec @ objectui seat; Clause-② no — a test-file routing record, so the default judgment applies, no tier review)

    • Re-derivation accepted. (a) Declared-key accounting closes: 25 own members = 11 mirrored same-shape + 1 via BaseSchema + 2 in WiderThanDeclared + 1 in RuntimeOnlyDeclared + 10 in UnmirroredDeclared; no KnownDrift row. (b) The spec read THROUGH THE PIN (@objectstack/spec@17.2.0, ui entry, 122 exported object schemas walked, control keys hit) finds four of the ten keys modelled on View-shaped schemas (navigation, searchableFields, filterableFields, listViews by name with the NamedListView value-type caveat) and six nowhere. Route: LOCAL — the SPEC-DERIVED route is for a mirror that IS the spec schema by reference; this mirror (objectql.zod.ts:196, BaseSchema.extend of local literals and z.lazy siblings, not in SPEC_DERIVED_PAIRS) takes no shape from the spec. The seat agrees with the reading and the route.
    • Counts derived, not restated: SPEC-DERIVED 1 entry / 2 keys (header said 2 / 12), LOCAL 13 / 94 (header said 12 / 84), totals 14 / 96 unchanged — derived from the UnmirroredDeclared union arms and SPEC_DERIVED_PAIRS membership, entry by entry in the PR body. The card's and the triage's figures were both stale on this tree, as the claim warned; neither was copied.
    • Record corrected at four sites — the header split (history sentences kept, extended), the UnmirroredDeclared entry docblock (with the 4 / 6 per-key reading for whoever mirrors), the SPEC_DERIVED_PAIRS comment, and the RuntimeOnlyDeclared ObjectViewSchema docblock (a fourth site outside the enumerated three; it said "this pair is ALSO spec-derived" and would have contradicted the others — prose only, the key did not move; deviation accepted). DashboardWidgetSchema reconfirmed spec-derived by code reference.
    • Pin: ledgerEntryMembers() reads each UnmirroredDeclared entry's union of string literals off the file's own AST (a non-literal arm is a hard error, not a skipped row); headerFigures() reads each header figure off disk and requires the spelling to occur exactly once (a stale copy beside a corrected one is red); the describe derives the split and compares four figures, plus a non-vacuity twin. Ablation: leg 1 (one header figure mutated) → 1 failed / 19 passed, exactly the pin; leg 2 (DashboardWidgetSchema dropped from SPEC_DERIVED_PAIRS) → 3 failed / 17 passed including the existing membership test; restore proven by blob hash. Red-first, adequate. The totals sentence reflowed onto one line so the regex can read it — accepted.
    • Gates: packages/types/ 124 files / 2196 tests green on 627d1881 (two origin/main merges absorbed — 4388f713, 16a725f9; the second taken after the dev detected the shared ref advancing under it, by an is-ancestor exit code with a control); three tsc projects green; lint green; four changeset gates green (empty-frontmatter changeset, test-only); control bytes; spec-symbols; governed predicate NOT governed. Build declared not run with the reason (nothing on the path reads dist) — accepted.
    • Scope held: packages/types/src/zod/** untouched; no MIRRORS / EXCLUSIONS / ledger key set / SPEC_DERIVED_PAIRS membership moved. The ten-key widening is NOT performed, as dispatched.
    • Open question (the follow-up's shape — mirror or retire the six unmodelled keys): the dev recommends B (mirror the four by spec reference; measure reads per key for the six and mirror-or-retire each by liveness). That is a remedy on the manual floor per triage 5548347502; this seat files it as a decision card with the four-facet block and the same recommendation, ⛔ not answered here.

    Landing: every check run on 627d1881 must be completed: success (farm started 17:10Z; Type Check, four shards, Lint, Doc Snippet Type Check, Bundle Analysis, Skill Example Check in progress at 17:12Z) — flip re-check armed; then ready + auto-merge SQUASH + queue probe + landing note here. Head moves ⇒ re-read before any flip.


    Generated by Claude Code

  8. os-justin commented on Sep 5, 2026

    @os-justin
    Collaborator

    Landing — PR #7776 (2026-09-05T17:27Z). Pre-landing three: ① flipped ready at 17:26Z after the ACCEPT above (comment 5553451329; Clause-② no, so no contract-review carrier was ever attached); every check run on 627d1881 was completed: success or skipped at 17:25Z (32 runs), head unchanged since the ACCEPT, mergeable_state: clean; ② auto-merge enabled, method SQUASH (the API echoes an empty method string — known platform reading); ③ queue probe running against refs/heads/gh-readonly-queue/main/* (the queue was empty at 17:24Z after PR #7774 landed; origin/main = 669d71bf). This PR carries Fixes #7279: the card closes on its squash; pm:dispatched is stripped once MERGED is read twice (PR merged: true + origin/main containing the squash). The follow-up decision card for the ten-key remedy is #7779 (needs-user-decision).


    Generated by Claude Code

  9. os-justin commented on Sep 5, 2026

    @os-justin
    Collaborator

    MERGED (2026-09-05T17:40Z) — PR #7776 landed through the merge queue as squash 1b69ca58 on main. Three readings: PR merged: true (merged_at 17:40:14Z); this card's closed_by_pull_requests reference to PR #7776 reads MERGED and the card closed at 17:40:16Z; git log origin/main at 17:40:33Z shows 1b69ca58 test(types): re-derive ObjectViewSchema's side of the #6058 split as LOCAL and pin the header counts (#7776) at the tip. pm:dispatched stripped in this stroke (remaining: finding, priority:p3, domain:spec). The split now reads SPEC-DERIVED 1 / 2, LOCAL 13 / 94, pinned to the ledger; the ten-key remedy is decision card #7779 (needs-user-decision). Session session_01BAZFhALsQsGqxui8sNqM8s.


    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

domain:specobjectui spec stream: fix lands on packages/types, schema corpus or spec pin coupling — spec lanefindingpriority:p3

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions