Skip to content

app-shell: the ObjectSchema corpus guards pin an exact top-level key count, so every additive spec change turns Test UI red on main; assert only the membership claims they guard #26238

Closed

Description

@objectstack-fleet

Filing gate ③: a coordinator-directed structural fix after the main-red of #26218. The maintainer asked whether one red blocking many PRs is the right shape and whether something faster exists. ⛔ Not a claim.

Two app-shell tests pin Object.keys(ObjectSchema.shape).size to an exact number:

  • ui/packages/app-shell/src/services/MetadataService.retiredObjectEnabled.test.ts:161
  • ui/packages/app-shell/src/services/MetadataService.specKeyObjectPayload.test.ts:175

Each file's own comment block records six re-points (42 → 48). Every one of them was caused by an unrelated spec adoption: editMode, imageField, attachedOnRead, defaultRowScope, membershipKeys, sharing. The count is not what the tests are about. It is described as "the corpus guard for the membership claims below", which are:

  • the tombstone keys enabled and _deleted are refused by name;
  • enable is the capabilities object;
  • no near-spelling of a retired key exists;
  • the object payload maps its keys.

The last re-point (#26005 adding sharing, fixed by #26218 / #26231) turned Test UI red on every ui PR's merge ref and in the merge queue, and ejected PRs that had nothing to do with it.

Business reason. An additive spec change, which is the most common kind, should not stop the ui lane. Today it does, until someone notices and re-points a number.

Expected.

  • Each guard asserts the claims it exists for, as explicit membership checks.
  • No exact count.
  • Where the comment says the count backs "no near-spelling of a retired key", that claim is asserted directly over the key set, for example as a no-key-within-edit-distance check against the retired names, rather than through a count.
  • The re-point comment history can be condensed to one line that points at this card.
  • No product change. Test-only. app-shell is outside the sdui registry closure.

Related.

Who acts. The domain:ui seat 2, after #26231 lands, because it edits the same two files.

Duplicate check. Searched the 40 newest issues for "corpus guard", "ObjectSchema key count" and "retiredObjectEnabled". Only #26218, #26222 and #26223 came up, all of them about the 48 re-point.

Activity

  1. objectstack-fleet commented on Oct 26, 2026

    @objectstack-fleet
    ContributorAuthor

    Scope widened · seat 2 · 2026-10-26T16:33Z

    The maintainer's word on the main-red (2026-10-26T16:32Z, project chat): 「根治」. This card goes to p1, and its scope becomes the whole ui/ tree, not just the two guards:

    • Sweep. Find every ui/** test that pins an exact count or a full shape of a spec-owned schema or enum. That covers Object.keys(<Spec>Schema.shape).size, .options.length of a spec enum, whole-object toEqual snapshots of a spec schema's key set, and literal key lists copied from @objectstack/spec. When such a test has to change because the spec gained something additive, a ui test goes red without any ui behaviour having changed.
    • Convert. Each one becomes membership assertions on what ui actually needs: the keys and values ui reads or must refuse, present or absent by name. Where a test's purpose is to catch a rename or retirement, assert that directly, for example a retired name absent, its successor present, and no near-spelling of a retired name. Don't use a count for that.
    • Keep. Exact pins on ui-owned shapes stay. Those are ui's own contract.
    • Report. List every file and assertion converted, every candidate kept with the reason, and the grep patterns used, with a control hit for each pattern.

    Test-only. No product change and no sdui record move unless a registry package's test imports change its digest; a gate run settles that. The PR goes after #26231, which edits two of these files, and merges main after #26231 lands.

  2. added
    priority:p1High: required for production / M2
    and removed on Oct 26, 2026
  3. objectstack-fleet commented on Oct 26, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 3 · 2026-10-26T16:34Z
    Session: session_01SMps7wq7rBTk53e8KTSEup
    Account: os-steve
    Branch: card thread (assigned by the platform)
    Worktree: card thread (its own container)
    Domain: domain:ui
    Seat: domain:ui#2
    File surface:

  4. objectstack-fleet commented on Oct 26, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 3 · 2026-10-26T16:41Z
    Session: session_01SMps7wq7rBTk53e8KTSEup
    Account: os-steve
    Branch: claude/project-thread-l7vqkg
    Worktree: card thread (its own container)
    Domain: domain:ui
    Seat: domain:ui#2
    File surface:

  5. objectstack-fleet commented on Oct 26, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report

    {
      "issue": 26238,
      "status": "done",
      "branch": "claude/project-thread-l7vqkg",
      "pr": 26272,
      "head": "cf00e778fb5cc85a679b62a70dddaeebfdcb63bd",
      "session": "session_01HRaa5qRyCQv9YZJCosen4d",
      "premise_still_valid": true,
      "summary": "Test-only. 38 ui/** test files that pinned exact counts or full key/value lists of spec-owned schemas, enums and constants now assert membership on what ui reads, writes or refuses. The two ObjectSchema corpus guards in app-shell trade the key count (re-pointed six times, 42 to 48) for a no-near-spelling-of-a-retired-key check. ui-owned shapes, derived ui-vs-spec parity guards, required-set pins and behavioural refusals are kept, each with a reason in the PR body. Sweep: 6 grep patterns P1-P6 over 1273 spec-reading ui test files at df8aac41f, each with a control hit (listed in the PR body).",
      "proof": "25 scratch spec members, full spec build: 24 files old red at the converted line and new green; 6 files old red and new red only at a kept derived-parity line (a real ui gap); 8 files not reached by the mutation set. Restore left 0 spec diff and 0 dist markers.",
      "tests": "Under os-verify-lock: 38 changed files at cf00e778, 38/38 files, 891/891 tests, VERDICT command-exit 0. Full suites of 12 touched packages at 402e830c (auth, core, data-objectstack, fields, plugin-dashboard, plugin-designer, plugin-detail, plugin-list, plugin-report, plugin-tree, sdui-parser, types): 1790 passed, 2 skipped files; 28011 passed, 65 skipped tests; VERDICT command-exit 0. Declared narrowing: app-shell and ui/apps/console ran their changed files only; their full suites are left to CI.",
      "gates": "dispatch-gates --commands at cf00e778: 24 derived, 24 run, each exit 0 (check:type-check-debt under the lock, VERDICT command-exit 0). --ran reconciliation: 0 NOT-MEASURED, 0 UNRUN.",
      "dogfood_battery": "n/a (test-only)",
      "mcp_calls": "0 GitHub MCP calls",
      "api_writes": "2 relay writes: pr_create #26272 (assignee os-steve, label skip-changeset, read back identical) and this comment",
      "open_questions": [
        "Derived ui-vs-spec parity guards (6 in the proof) still go red on an additive spec change, by design: red names a real ui gap (missing label, consumer or declaration). Recommendation: keep them; #26092 makes them visible on the spec PR itself."
      ],
      "out_of_scope_findings": [
        "Type-level literal-union pins: 51 Equal type assertions in 31 spec-reading ui test files at df8aac41f (e.g. plugin-chatbot/src/__tests__/spec-symbol-batch6.test.ts:251, PendingActionStatus). Spec-derived ones red Type Check UI on an additive spec change; converting needs a per-type ruling (exact equality vs extends). Suggest a separate card."
      ]
    }

    Generated by Claude Code

  6. objectstack-fleet commented on Oct 26, 2026

    @objectstack-fleet
    ContributorAuthor

    Landed · seat 2 · 2026-10-26T19:32Z

    probe reading
    PR #26272 MERGED 2026-10-26T19:30Z, merge commit b5d137af, head cf00e778 (+256/−217, 38 test files, ACCEPT on #26272)
    origin/main at b5d137af, contains it (git merge-base --is-ancestor exit 0); accept.size).toBe no longer appears under app-shell/src/services/
    queue branch gh-readonly-queue/main/pr-26272-*: none left (consumed)
    card closed (completed) by Fixes #26238 on #26272

    Status: ui tests no longer pin exact counts or full lists of spec-owned schemas. A spec adding a key or enum member leaves Test UI green unless ui really lacks a case (the kept derived-parity guards name the gap). The type-level twin is #26275 (seat 1); #26092 runs ui checks on spec PRs. pm:dispatched removed.

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

Metadata

Metadata

Assignees

Labels

area:devpathThe road — create, dev, verify, publish/install, connect an agent, iteratedomain:uienhancementNew feature or requestpriority:p1High: required for production / M2

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions