Skip to content

Commit 43567a8

Browse files
ci(spec-shape-gate): drop the closed objectui#12325 retirement entry and point the header at the deleted objectui copy’s last commit (#23822)
Part of #23782 Clause-②: no ## What - **`scripts/ci/spec-shape-retirements.json`**: deletes the one entry, whose `downstream_card` is objectstack-ai/objectui#12325. That card closed `completed` on 2026-10-14, and the file's own `$comment` says an entry is deleted when its card closes. The entry's `packages/**` patterns (`TS2367` / `TS2678` with message `'"api"'`) would have read a later, unrelated break of the same shape as `known` instead of red. The registry is now `"retirements": []`. The `$comment` and the grammar are unchanged. - **`scripts/ci/spec-shape-gate.mjs`, header (comments only)**: says that objectui deleted its copy in objectstack-ai/objectui PR #12596 (card objectstack-ai/objectui#12352), so this gate is the only one. The "port of objectui's `scripts/spec-main-shape-gate.mjs`" sentence now points at objectui commit `7d0c174ba8383d08b8dd1d4f7d7845009f1bf2fd` for the measurements the header does not restate. The registry example's `downstream_card` is now `objectstack-ai/objectui#N`. - **Self-test fixture**: `FIXTURE_ENTRY.downstream_card` and the two checks that read it now use `objectstack-ai/objectui#999999` instead of the closed card's number. The malformed-card sample changes the same way. These are fixture literals; no reader, matcher or assertion changes. No change to the gate's logic, `MARKER_FILE`, or the "marker name is objectui's, on purpose" paragraph. ## Measurements - **The reader accepts an empty list.** `parseRegistry` requires `Array.isArray(doc.retirements)` and then checks each entry in a loop. Run on the edited live file, it returns 0 entries and does not throw. `pnpm check:spec-shape-gate` (the `--self-test`): `60/60 passed across 7 batteries`, exit 0. - **The pointer commit.** In a blobless clone of objectstack-ai/objectui, `git log -- scripts/spec-main-shape-gate.mjs` shows that the newest commit touching the file is merge `c6a42be392cf9ae820424a694c59fb2a7287d2ae` (PR #12596, which deletes it). Its first parent is `7d0c174ba8383d08b8dd1d4f7d7845009f1bf2fd`. `git cat-file -e` confirms that `scripts/spec-main-shape-gate.mjs` and `.github/workflows/spec-main-shape-gate.yml` both exist at that commit, and that `c6a42be392` is on objectui `main`. - `git grep -n 'objectui#12325' -- scripts/ci`: 0 hits (exit 1). ## Choice: a pointer, not moving the measurements here Weighed on the four axes: - **Real need:** nobody here reads or maintains the injection measurements. The mechanism is unchanged, and the measurements stay reachable at a fixed commit. - **Long-term soundness:** a pinned 40-hex commit cannot drift. A copied header would become a second text that ages. - **Hard for an AI to get wrong:** the pointer names the exact `git show` path. - **No scope spread at the startup stage:** copying the measurements adds text nobody here maintains. ## Gates `node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack` on this branch's diff derived 29 commands. All 29 exited 0 (each exit code captured before any pipe). Reconciliation with `--ran`: `29 derived famil(ies) accounted for — 29 run, 0 NOT-MEASURED (a DERIVED zero)`. ## Changeset None. The diff touches only `scripts/ci/**` at the repository root (root `package.json` is `private: true`), and no package's `package.json` names either file. Nothing published changes. ## Acceptance notes The workflow header paragraph (item 1 of the card) is in the companion Tier H PR, `claude/issue-23782-spec-shape-workflow-header`, which the maintainer lands. --- _Generated by [Claude Code](https://claude.ai/code/session_017rP7fP8F2BVtpC3SDZBAdu)_ Co-authored-by: Claude <noreply@anthropic.com>
1 parent 1ecb08a commit 43567a8

2 files changed

Lines changed: 17 additions & 46 deletions

File tree

‎scripts/ci/spec-shape-gate.mjs‎

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,18 @@
3030
* consecutive hourly runs here agree with objectui's. The MECHANISM of ruling C
3131
* on #19011 is kept unchanged: consumer compilation is the ONE shape gate for
3232
* the spec's public surface; what moved is where it runs and who owns a red.
33+
* objectui deleted its copy in objectstack-ai/objectui PR #12596 (card
34+
* objectstack-ai/objectui#12352), so this gate is the only one.
3335
*
34-
* This file is the objectstack port of objectui's `scripts/spec-main-shape-gate.mjs`
35-
* (its header carries the measurements behind the virtual-store injection, the
36-
* hardlink trap, the dependency re-pointing and the turbo-cache false green;
37-
* they are not restated here, and the mechanism is unchanged). Three things are
38-
* different, each because the direction reversed:
36+
* This file is the objectstack port of objectui's `scripts/spec-main-shape-gate.mjs`,
37+
* which that PR deleted. Its header carries the measurements behind the
38+
* virtual-store injection, the hardlink trap, the dependency re-pointing and
39+
* the turbo-cache false green; they are not restated here, and the mechanism is
40+
* unchanged. Read them at objectui commit `7d0c174ba8383d08b8dd1d4f7d7845009f1bf2fd`,
41+
* the first parent of that PR's merge commit `c6a42be392` and the last objectui
42+
* `main` commit that has the file (`git show <commit>:scripts/spec-main-shape-gate.mjs`
43+
* in an objectui clone). Three things are different, each because the
44+
* direction reversed:
3945
*
4046
* 1. THE SUBJECT IS THIS COMMIT. objectui built the spec from objectstack
4147
* `main` and compiled itself; here the spec is built and packed from the
@@ -73,7 +79,7 @@
7379
* "retired": "view-level data source provider 'api'",
7480
* "objectstack_pr": 23160,
7581
* "objectstack_commit": "1912af47ba6e3b250f7c717fea0d56e181029b9c",
76-
* "downstream_card": "objectstack-ai/objectui#12325",
82+
* "downstream_card": "objectstack-ai/objectui#N",
7783
* "registered_at": "2026-10-13",
7884
* "matches": [
7985
* { "file": "packages/react/src/hooks/useViewData.ts", "code": "TS2367", "message": "'\"api\"'" }
@@ -1307,7 +1313,7 @@ const FIXTURE_ENTRY = Object.freeze({
13071313
retired: "view-level data source provider 'api'",
13081314
objectstack_pr: 23160,
13091315
objectstack_commit: '1912af47ba6e3b250f7c717fea0d56e181029b9c',
1310-
downstream_card: 'objectstack-ai/objectui#12325',
1316+
downstream_card: 'objectstack-ai/objectui#999999',
13111317
registered_at: '2026-10-13',
13121318
matches: [
13131319
{ file: 'packages/react/src/hooks/useViewData.ts', code: 'TS2367', message: '\'"api"\'' },
@@ -1406,7 +1412,7 @@ async function selfTest() {
14061412
'a known-only summary says no new break and names the registration',
14071413
(() => {
14081414
const text = renderSummary({ ...base, status: 1, rows: [knownRow], known: [{ row: knownRow, entry: FIXTURE_ENTRY }] });
1409-
return text.includes('No new shape break') && text.includes('known (registered: objectstack-ai/objectui#12325') && !text.includes('NEW diagnostic');
1415+
return text.includes('No new shape break') && text.includes('known (registered: objectstack-ai/objectui#999999') && !text.includes('NEW diagnostic');
14101416
})(),
14111417
true,
14121418
);
@@ -1469,7 +1475,7 @@ async function selfTest() {
14691475
check('an empty matches array is refused', thrownMessage(() => parseRegistry(registryText([{ ...FIXTURE_ENTRY, matches: [] }]))).includes('registers nothing'), true);
14701476
check('an unknown entry key is refused', thrownMessage(() => parseRegistry(registryText([{ ...FIXTURE_ENTRY, ignore_all: true }]))).includes('unknown key "ignore_all"'), true);
14711477
check('a short commit, a bad card ref and a bad date are each named', (() => {
1472-
const msg = thrownMessage(() => parseRegistry(registryText([{ ...FIXTURE_ENTRY, objectstack_commit: '1912af47', downstream_card: 'objectui 12325', registered_at: 'yesterday' }])));
1478+
const msg = thrownMessage(() => parseRegistry(registryText([{ ...FIXTURE_ENTRY, objectstack_commit: '1912af47', downstream_card: 'objectui 999999', registered_at: 'yesterday' }])));
14731479
return msg.includes('objectstack_commit') && msg.includes('downstream_card') && msg.includes('registered_at') && msg.includes('3 problem(s)');
14741480
})(), true);
14751481
check('a pattern covers a row only when every declared field holds', [
@@ -1486,7 +1492,7 @@ async function selfTest() {
14861492
], [true, true, false, false]);
14871493
const newRow = { ...knownRow, file: 'packages/react/src/hooks/useViewData.ts', line: 200, code: 'TS2322', message: "Type 'string' is not assignable to type 'number'." };
14881494
const classified = classifyRows([knownRow, newRow], parseRegistry(registryText([FIXTURE_ENTRY])));
1489-
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]);
1495+
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]);
14901496
check('an entry that covers no row is reported as unmatched, and nothing is known', (() => {
14911497
const c = classifyRows([newRow], parseRegistry(registryText([FIXTURE_ENTRY])));
14921498
return [c.known.length, c.unknown.length, c.unmatchedEntries.length];
Lines changed: 1 addition & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,4 @@
11
{
22
"$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).",
3-
"retirements": [
4-
{
5-
"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",
6-
"objectstack_pr": 23160,
7-
"objectstack_commit": "1912af47ba6e3b250f7c717fea0d56e181029b9c",
8-
"downstream_card": "objectstack-ai/objectui#12325",
9-
"registered_at": "2026-10-13",
10-
"matches": [
11-
{
12-
"file": "packages/**",
13-
"code": "TS2367",
14-
"message": "'\"api\"'"
15-
},
16-
{
17-
"file": "packages/**",
18-
"code": "TS2678",
19-
"message": "'\"api\"'"
20-
},
21-
{
22-
"file": "packages/core/src/adapters/resolveDataSource.ts",
23-
"code": "TS2339",
24-
"message": "does not exist on type 'never'"
25-
},
26-
{
27-
"file": "packages/plugin-gantt/src/ObjectGantt.tsx",
28-
"code": "TS2339",
29-
"message": "does not exist on type 'never'"
30-
},
31-
{
32-
"file": "packages/types/src/__tests__/*.test.ts",
33-
"code": "TS2352",
34-
"message": "data: { read: Record<string, unknown>; }"
35-
}
36-
]
37-
}
38-
]
3+
"retirements": []
394
}

0 commit comments

Comments
 (0)