You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
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
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:
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.
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.
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.
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:
Owned:ui/** test files only (*.test.ts, *.test.tsx) that pin an exact count or a full shape of a spec-owned schema or enum. The sweep names them, starting with ui/packages/app-shell/src/services/MetadataService.retiredObjectEnabled.test.ts and MetadataService.specKeyObjectPayload.test.ts.
Changeset: root .changeset/ only if the gate asks for one on a test-only diff.
Out of bounds: ⛔ product sources, ⛔ packages/spec, ⛔ ui/packages/i18n/src/locales/*.ts, ⛔ ui/.github/** and the root .github/workflows/ci.yml.
Ruling section: the scope comment on this card (seat 2, citing the maintainer's 「根治」). Sweep, convert to membership assertions on what ui needs, keep ui-owned exact pins, and report each conversion and each kept candidate with its reason.
Seat's route:
Grep ui/** tests for Schema.shape with .size or .length, .options.length, Object.keys( of spec imports with toEqual or toHaveLength, and literal spec key lists. Pair every pattern with a control hit.
For each hit, say what ui behaviour it protects and replace the count or full shape with the named membership facts.
Retirement guards assert the retired names absent, successors present, and no near-spelling, directly.
Run every changed file red-first where possible: patch a scratch copy of the spec shape to add a key and show the old assertion going red while the new one stays green. Then run the full touched packages.
Owned:ui/** test files only (*.test.ts, *.test.tsx) that pin an exact count or a full shape of a spec-owned schema or enum. The sweep names them, starting with ui/packages/app-shell/src/services/MetadataService.retiredObjectEnabled.test.ts and MetadataService.specKeyObjectPayload.test.ts.
Changeset: root .changeset/ only if the gate asks for one on a test-only diff.
Out of bounds: ⛔ product sources, ⛔ packages/spec, ⛔ ui/packages/i18n/src/locales/*.ts, ⛔ ui/.github/** and the root .github/workflows/ci.yml.
Ruling section: the scope comment on this card (seat 2, citing the maintainer's 「根治」). Sweep, convert to membership assertions on what ui needs, keep ui-owned exact pins, and report each conversion and each kept candidate with its reason.
Seat's route:
Grep ui/** tests for Schema.shape with .size or .length, .options.length, Object.keys( of spec imports with toEqual or toHaveLength, and literal spec key lists. Pair every pattern with a control hit.
For each hit, say what ui behaviour it protects and replace the count or full shape with the named membership facts.
Retirement guards assert the retired names absent, successors present, and no near-spelling, directly.
Run every changed file red-first where possible: patch a scratch copy of the spec shape to add a key and show the old assertion going red while the new one stays green. Then run the full touched packages.
{
"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."
]
}
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.
Activity
objectstack-fleet commentedon Oct 26, 2026
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:ui/**test that pins an exact count or a full shape of a spec-owned schema or enum. That coversObject.keys(<Spec>Schema.shape).size,.options.lengthof a spec enum, whole-objecttoEqualsnapshots 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.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
mainafter #26231 lands.objectstack-fleet commentedon Oct 26, 2026
Claim: PM loop round 3 · 2026-10-26T16:34Z
Session:
session_01SMps7wq7rBTk53e8KTSEupAccount:
os-steveBranch:
card thread (assigned by the platform)Worktree:
card thread (its own container)Domain:
domain:uiSeat:
domain:ui#2File surface:
Owned:
ui/**test files only (*.test.ts,*.test.tsx) that pin an exact count or a full shape of a spec-owned schema or enum. The sweep names them, starting withui/packages/app-shell/src/services/MetadataService.retiredObjectEnabled.test.tsandMetadataService.specKeyObjectPayload.test.ts.Changeset: root
.changeset/only if the gate asks for one on a test-only diff.Out of bounds: ⛔ product sources, ⛔
packages/spec, ⛔ui/packages/i18n/src/locales/*.ts, ⛔ui/.github/**and the root.github/workflows/ci.yml.sdui records: the derived gates settle any record move. If a registry package's test change moves its digest, re-record per package (
gen-sdui-manifest-node, under the lock).Container & model:
M,mode:card-thread,model: default tier,effort: mediumClause-②: no
Metadata-protocol: none
Responsibility:
ui tests that go red when the spec adds a key, without any ui behaviour changing|@objectstack/spec's schema and enum declarations, which ui consumes and does not own|every ui PR's Test UI and the merge queueThread-read: none
Premise: holds 2026-10-26T16:30Z. On
origin/maindf8aac41f2, the two app-shell guards pinexpect(accept.size).toBe(47)(:161,:175). Their comment blocks record six re-points, each caused by an unrelated spec adoption. The latest one, feat(spec,plugin-security,lint): sharing.controlledByParent.ownerMayEdit — a detail row's owner updates it with read on the master #26005 addingsharing, turned Test UI red on every ui PR (app-shell: MetadataService.retiredObjectEnabled corpus guard expects 47 ObjectSchema keys, main now has 48 after #26005 added sharing, so Test UI is red for every ui PR #26218 / test(app-shell): re-point the ObjectSchema corpus guards to 48 after sharing was adopted #26231). The maintainer's word is 「根治」.Serial constraints cleared: test(app-shell): re-point the ObjectSchema corpus guards to 48 after sharing was adopted #26231 (app-shell: MetadataService.retiredObjectEnabled corpus guard expects 47 ObjectSchema keys, main now has 48 after #26005 added sharing, so Test UI is red for every ui PR #26218) holds the two app-shell guard files. This card develops now and merges
mainafter test(app-shell): re-point the ObjectSchema corpus guards to 48 after sharing was adopted #26231 lands; it does not enqueue before then.Writes: PR only via the relay op
pr_create; comments only via the relay write tools; ⛔ no GitHub MCP writes.Ruling section: the scope comment on this card (seat 2, citing the maintainer's 「根治」). Sweep, convert to membership assertions on what ui needs, keep ui-owned exact pins, and report each conversion and each kept candidate with its reason.
Seat's route:
ui/**tests forSchema.shapewith.sizeor.length,.options.length,Object.keys(of spec imports withtoEqualortoHaveLength, and literal spec key lists. Pair every pattern with a control hit.Fixes #26238.objectstack-fleet commentedon Oct 26, 2026
Claim: PM loop round 3 · 2026-10-26T16:41Z
Session:
session_01SMps7wq7rBTk53e8KTSEupAccount:
os-steveBranch:
claude/project-thread-l7vqkgWorktree:
card thread (its own container)Domain:
domain:uiSeat:
domain:ui#2File surface:
Owned:
ui/**test files only (*.test.ts,*.test.tsx) that pin an exact count or a full shape of a spec-owned schema or enum. The sweep names them, starting withui/packages/app-shell/src/services/MetadataService.retiredObjectEnabled.test.tsandMetadataService.specKeyObjectPayload.test.ts.Changeset: root
.changeset/only if the gate asks for one on a test-only diff.Out of bounds: ⛔ product sources, ⛔
packages/spec, ⛔ui/packages/i18n/src/locales/*.ts, ⛔ui/.github/**and the root.github/workflows/ci.yml.sdui records: the derived gates settle any record move. If a registry package's test change moves its digest, re-record per package (
gen-sdui-manifest-node, under the lock).Container & model:
M,mode:card-thread,model: default tier,effort: mediumClause-②: no
Metadata-protocol: none
Responsibility:
ui tests that go red when the spec adds a key, without any ui behaviour changing|@objectstack/spec's schema and enum declarations, which ui consumes and does not own|every ui PR's Test UI and the merge queueThread-read: none
Premise: holds 2026-10-26T16:30Z. On
origin/maindf8aac41f2, the two app-shell guards pinexpect(accept.size).toBe(47)(:161,:175). Their comment blocks record six re-points, each caused by an unrelated spec adoption. The latest one, feat(spec,plugin-security,lint): sharing.controlledByParent.ownerMayEdit — a detail row's owner updates it with read on the master #26005 addingsharing, turned Test UI red on every ui PR (app-shell: MetadataService.retiredObjectEnabled corpus guard expects 47 ObjectSchema keys, main now has 48 after #26005 added sharing, so Test UI is red for every ui PR #26218 / test(app-shell): re-point the ObjectSchema corpus guards to 48 after sharing was adopted #26231). The maintainer's word is 「根治」.Serial constraints cleared: test(app-shell): re-point the ObjectSchema corpus guards to 48 after sharing was adopted #26231 (app-shell: MetadataService.retiredObjectEnabled corpus guard expects 47 ObjectSchema keys, main now has 48 after #26005 added sharing, so Test UI is red for every ui PR #26218) holds the two app-shell guard files. This card develops now and merges
mainafter test(app-shell): re-point the ObjectSchema corpus guards to 48 after sharing was adopted #26231 lands; it does not enqueue before then.Writes: PR only via the relay op
pr_create; comments only via the relay write tools; ⛔ no GitHub MCP writes.Ruling section: the scope comment on this card (seat 2, citing the maintainer's 「根治」). Sweep, convert to membership assertions on what ui needs, keep ui-owned exact pins, and report each conversion and each kept candidate with its reason.
Seat's route:
ui/**tests forSchema.shapewith.sizeor.length,.options.length,Object.keys(of spec imports withtoEqualortoHaveLength, and literal spec key lists. Pair every pattern with a control hit.Fixes #26238.test(ui): turn spec-owned shape pins across ui into membership assert…
test(ui): the stored-type census counts what it iterated, not the mea…
objectstack-fleet commentedon Oct 26, 2026
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
objectstack-fleet commentedon Oct 26, 2026
Landed · seat 2 · 2026-10-26T19:32Z
b5d137af, headcf00e778(+256/−217, 38 test files, ACCEPT on #26272)origin/mainb5d137af, contains it (git merge-base --is-ancestorexit 0);accept.size).toBeno longer appears underapp-shell/src/services/gh-readonly-queue/main/pr-26272-*: none left (consumed)Fixes #26238on #26272Status: 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:dispatchedremoved.test(ui): relax the two export-format and options-bag restatements af…
Merge branch 'main' into claude/project-thread-q3olv3