Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 16 additions & 10 deletions scripts/ci/spec-shape-gate.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -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 <commit>: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
Expand Down Expand Up @@ -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\"'" }
Expand Down Expand Up @@ -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"\'' },
Expand Down Expand Up @@ -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,
);
Expand Down Expand Up @@ -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', [
Expand All @@ -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];
Expand Down
37 changes: 1 addition & 36 deletions scripts/ci/spec-shape-retirements.json
Original file line number Diff line number Diff line change
@@ -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<digits>) 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<string, unknown>; }"
}
]
}
]
"retirements": []
}
Loading