From 1b10608543dee505d153623809508e3c51948ce7 Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 16 Oct 2026 05:10:54 +0000 Subject: [PATCH] ci(spec-shape-gate): drop the retirement entry whose objectui card closed, point the header at the deleted objectui copy's last commit objectstack-ai/objectui#12325 closed on 2026-10-14, but its entry was still in scripts/ci/spec-shape-retirements.json. Its packages/** patterns would have read a later, unrelated break of the same shape as `known` instead of red. The registry is now `"retirements": []`. The reader accepts an empty list: the self-test passes 60/60 and the live file parses with 0 entries. objectui deleted its spec-main-shape-gate copy in objectstack-ai/objectui PR #12596. The header now says so, and it points at objectui commit 7d0c174ba8383d08b8dd1d4f7d7845009f1bf2fd (the first parent of merge c6a42be392, the last objectui main commit that has the script) for the measurements it does not restate. The header's registry example and the self-test fixture now use placeholder card numbers. No logic changes. Co-Authored-By: Claude Claude-Session: https://claude.ai/code/session_017rP7fP8F2BVtpC3SDZBAdu --- scripts/ci/spec-shape-gate.mjs | 26 +++++++++++------- scripts/ci/spec-shape-retirements.json | 37 +------------------------- 2 files changed, 17 insertions(+), 46 deletions(-) diff --git a/scripts/ci/spec-shape-gate.mjs b/scripts/ci/spec-shape-gate.mjs index c0284ba1714..152248ee73b 100644 --- a/scripts/ci/spec-shape-gate.mjs +++ b/scripts/ci/spec-shape-gate.mjs @@ -30,12 +30,18 @@ * consecutive hourly runs here agree with objectui's. The MECHANISM of ruling C * on #19011 is kept unchanged: consumer compilation is the ONE shape gate for * the spec's public surface; what moved is where it runs and who owns a red. + * objectui deleted its copy in objectstack-ai/objectui PR #12596 (card + * objectstack-ai/objectui#12352), so this gate is the only one. * - * This file is the objectstack port of objectui's `scripts/spec-main-shape-gate.mjs` - * (its header carries the measurements behind the virtual-store injection, the - * hardlink trap, the dependency re-pointing and the turbo-cache false green; - * they are not restated here, and the mechanism is unchanged). Three things are - * different, each because the direction reversed: + * This file is the objectstack port of objectui's `scripts/spec-main-shape-gate.mjs`, + * which that PR deleted. Its header carries the measurements behind the + * virtual-store injection, the hardlink trap, the dependency re-pointing and + * the turbo-cache false green; they are not restated here, and the mechanism is + * unchanged. Read them at objectui commit `7d0c174ba8383d08b8dd1d4f7d7845009f1bf2fd`, + * the first parent of that PR's merge commit `c6a42be392` and the last objectui + * `main` commit that has the file (`git show :scripts/spec-main-shape-gate.mjs` + * in an objectui clone). Three things are different, each because the + * direction reversed: * * 1. THE SUBJECT IS THIS COMMIT. objectui built the spec from objectstack * `main` and compiled itself; here the spec is built and packed from the @@ -73,7 +79,7 @@ * "retired": "view-level data source provider 'api'", * "objectstack_pr": 23160, * "objectstack_commit": "1912af47ba6e3b250f7c717fea0d56e181029b9c", - * "downstream_card": "objectstack-ai/objectui#12325", + * "downstream_card": "objectstack-ai/objectui#N", * "registered_at": "2026-10-13", * "matches": [ * { "file": "packages/react/src/hooks/useViewData.ts", "code": "TS2367", "message": "'\"api\"'" } @@ -1307,7 +1313,7 @@ const FIXTURE_ENTRY = Object.freeze({ retired: "view-level data source provider 'api'", objectstack_pr: 23160, objectstack_commit: '1912af47ba6e3b250f7c717fea0d56e181029b9c', - downstream_card: 'objectstack-ai/objectui#12325', + downstream_card: 'objectstack-ai/objectui#999999', registered_at: '2026-10-13', matches: [ { file: 'packages/react/src/hooks/useViewData.ts', code: 'TS2367', message: '\'"api"\'' }, @@ -1406,7 +1412,7 @@ async function selfTest() { 'a known-only summary says no new break and names the registration', (() => { const text = renderSummary({ ...base, status: 1, rows: [knownRow], known: [{ row: knownRow, entry: FIXTURE_ENTRY }] }); - return text.includes('No new shape break') && text.includes('known (registered: objectstack-ai/objectui#12325') && !text.includes('NEW diagnostic'); + return text.includes('No new shape break') && text.includes('known (registered: objectstack-ai/objectui#999999') && !text.includes('NEW diagnostic'); })(), true, ); @@ -1469,7 +1475,7 @@ async function selfTest() { check('an empty matches array is refused', thrownMessage(() => parseRegistry(registryText([{ ...FIXTURE_ENTRY, matches: [] }]))).includes('registers nothing'), true); check('an unknown entry key is refused', thrownMessage(() => parseRegistry(registryText([{ ...FIXTURE_ENTRY, ignore_all: true }]))).includes('unknown key "ignore_all"'), true); check('a short commit, a bad card ref and a bad date are each named', (() => { - const msg = thrownMessage(() => parseRegistry(registryText([{ ...FIXTURE_ENTRY, objectstack_commit: '1912af47', downstream_card: 'objectui 12325', registered_at: 'yesterday' }]))); + const msg = thrownMessage(() => parseRegistry(registryText([{ ...FIXTURE_ENTRY, objectstack_commit: '1912af47', downstream_card: 'objectui 999999', registered_at: 'yesterday' }]))); return msg.includes('objectstack_commit') && msg.includes('downstream_card') && msg.includes('registered_at') && msg.includes('3 problem(s)'); })(), true); check('a pattern covers a row only when every declared field holds', [ @@ -1486,7 +1492,7 @@ async function selfTest() { ], [true, true, false, false]); const newRow = { ...knownRow, file: 'packages/react/src/hooks/useViewData.ts', line: 200, code: 'TS2322', message: "Type 'string' is not assignable to type 'number'." }; const classified = classifyRows([knownRow, newRow], parseRegistry(registryText([FIXTURE_ENTRY]))); - check('classifyRows splits a registered row from a new one in the same file', [classified.known.length, classified.unknown.length, classified.known[0]?.entry.downstream_card, classified.unmatchedEntries.length], [1, 1, 'objectstack-ai/objectui#12325', 0]); + check('classifyRows splits a registered row from a new one in the same file', [classified.known.length, classified.unknown.length, classified.known[0]?.entry.downstream_card, classified.unmatchedEntries.length], [1, 1, 'objectstack-ai/objectui#999999', 0]); check('an entry that covers no row is reported as unmatched, and nothing is known', (() => { const c = classifyRows([newRow], parseRegistry(registryText([FIXTURE_ENTRY]))); return [c.known.length, c.unknown.length, c.unmatchedEntries.length]; diff --git a/scripts/ci/spec-shape-retirements.json b/scripts/ci/spec-shape-retirements.json index f45f6d5338d..db7d1484cd9 100644 --- a/scripts/ci/spec-shape-retirements.json +++ b/scripts/ci/spec-shape-retirements.json @@ -1,39 +1,4 @@ { "$comment": "Intentional spec retirements the Spec Shape Gate reads as `known` instead of red. One entry per retirement, written by the accepting seat when the downstream (objectui) card is filed, deleted when that card closes. Every entry carries exactly: retired, objectstack_pr, objectstack_commit (40-hex merge commit), downstream_card (owner/repo#N), registered_at (YYYY-MM-DD), matches (non-empty; each pattern names a repo-relative objectui `file` -- `*` within a segment, `**` across -- plus at least one of `code` (TS) or `message` (substring)). A file alone is refused. The reader, its grammar and its refusals: scripts/ci/spec-shape-gate.mjs (THE REGISTRY).", - "retirements": [ - { - "retired": "view-level data source provider 'api' (ViewDataSchema arm; ruling C on #23082, executed by PR #23160) -- the downstream still compares against the '\"api\"' literal, reads the arm's read/write keys, and casts test fixtures to its { data: { read } } shape", - "objectstack_pr": 23160, - "objectstack_commit": "1912af47ba6e3b250f7c717fea0d56e181029b9c", - "downstream_card": "objectstack-ai/objectui#12325", - "registered_at": "2026-10-13", - "matches": [ - { - "file": "packages/**", - "code": "TS2367", - "message": "'\"api\"'" - }, - { - "file": "packages/**", - "code": "TS2678", - "message": "'\"api\"'" - }, - { - "file": "packages/core/src/adapters/resolveDataSource.ts", - "code": "TS2339", - "message": "does not exist on type 'never'" - }, - { - "file": "packages/plugin-gantt/src/ObjectGantt.tsx", - "code": "TS2339", - "message": "does not exist on type 'never'" - }, - { - "file": "packages/types/src/__tests__/*.test.ts", - "code": "TS2352", - "message": "data: { read: Record; }" - } - ] - } - ] + "retirements": [] }