From 1c3a721ac1000a7045e8a7808b59c8154f43d99a Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 18 Sep 2026 03:11:02 +0000 Subject: [PATCH] fix(scripts): the manifest generator defaults its @object-ui version from the PIN, not the record MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `gen-sdui-manifest-node.mjs` re-read `objectuiSha` from the live `.objectui-sha` while `objectuiPackagesVersion` fell back to the value already in `scripts/sdui-manifest.record.json`. The two record fields were therefore read at two different moments: a regeneration after a pin bump wrote the NEW pin under the OLD version string, producing a record whose two objectui fields describe two different commits — the exact record `check-sdui-manifest.mjs` check 4 rejects. The person that reds is the one who followed the documented bump procedure, so the producer is where it is fixed. The default now comes from the same oracle the gate judges with: the version `packages/core/package.json` declares at the pinned commit, read through `check-sdui-manifest.mjs`'s exported `readPinnedDeclaredVersion` — the same function, imported, not a second copy. Producer and gate consulting two separate oracles is where this drift came from. `--objectui-version` still wins when passed. When the oracle cannot answer (no objectui checkout, or one that does not carry the pin) the script now REFUSES and names both remedies, rather than falling back to a version string nobody read: an absent reading is never converted into an answer. Claude-Session: https://claude.ai/code/session_01JbZnqu8bt6YqfJsr9vaFb3 Co-authored-by: Claude --- scripts/gen-sdui-manifest-node.mjs | 63 ++++++++++++++++++++++++------ 1 file changed, 50 insertions(+), 13 deletions(-) diff --git a/scripts/gen-sdui-manifest-node.mjs b/scripts/gen-sdui-manifest-node.mjs index ad8f285e5a7..c9713d25f3b 100644 --- a/scripts/gen-sdui-manifest-node.mjs +++ b/scripts/gen-sdui-manifest-node.mjs @@ -5,7 +5,7 @@ * gen-sdui-manifest-node — regenerate the repo-root `sdui.manifest.json` from * objectui's PUBLISHED registry packages, without a browser. * - * node scripts/gen-sdui-manifest-node.mjs # temp npm install (network) + * node scripts/gen-sdui-manifest-node.mjs # temp npm install (network); version from the PIN * node scripts/gen-sdui-manifest-node.mjs --modules-root DIR # use a preinstalled node_modules parent * node scripts/gen-sdui-manifest-node.mjs --objectui-version V # override the version to install * @@ -48,15 +48,33 @@ * tombstone there; this header is what both of them now send readers to for * the readings. * - * ## Versioning contract + * ## Versioning contract — ONE oracle, shared with the gate * * The manifest must describe the registry the SHIPPED console runs — i.e. the * `@object-ui/*` version that `.objectui-sha` ships. This script installs that - * version from npm; the version is read from `scripts/sdui-manifest.record.json` - * unless `--objectui-version` overrides it. After a pin bump, pass the version - * the new pin carries (its `packages/core/package.json` in the objectui - * checkout the bump already required) — `check-sdui-manifest.mjs` goes red on - * a moved pin until this script has been re-run and the record re-written. + * version from npm. Which version that is has exactly one source: + * `--objectui-version` when it is passed, otherwise what + * `packages/core/package.json` DECLARES at the pinned commit — read through + * `check-sdui-manifest.mjs`'s exported `readPinnedDeclaredVersion`, the SAME + * function its check 4 judges the written record with, imported rather than + * re-typed. + * + * ⛔ The version is NOT defaulted from `scripts/sdui-manifest.record.json`. + * That default is what this file was fixed for: `objectuiSha` below is re-read + * from the LIVE pin while `objectuiPackagesVersion` fell back to the value + * already in the record, so the two fields were read at two different moments. + * A regeneration after a pin bump therefore wrote the NEW pin under the OLD + * version string — a record whose two objectui fields describe two different + * commits, which check 4 reds. The person it reds is the one who followed the + * documented bump procedure, so the producer is where it is fixed. Two readers + * consulting two oracles is precisely where that drift came from; there is now + * one oracle and both read it. + * + * When the oracle cannot answer — no objectui checkout, or one that does not + * carry the pinned commit — this script REFUSES. An unread version is never + * converted into a version string (Route & surface ownership §3: prefer failing + * to falling back). Point `OBJECTUI_ROOT` at a checkout that carries the pin, + * or pass `--objectui-version` explicitly. * * ## Preconditions (all loud) * @@ -71,6 +89,8 @@ import { tmpdir } from 'node:os'; import { dirname, join } from 'node:path'; import { pathToFileURL, fileURLToPath } from 'node:url'; +import { readPinnedDeclaredVersion } from './check-sdui-manifest.mjs'; + const ROOT = join(dirname(fileURLToPath(import.meta.url)), '..'); const RECORD_PATH = join(ROOT, 'scripts', 'sdui-manifest.record.json'); const OUT_PATH = join(ROOT, 'sdui.manifest.json'); @@ -126,12 +146,26 @@ if (existsSync(RECORD_PATH)) { } } -const version = arg('--objectui-version') ?? record.objectuiPackagesVersion; +// The version this run installs AND records. `--objectui-version` wins; the +// default is what the PIN declares, through check 4's own oracle — never the +// version already sitting in the record (see the versioning contract above). +const explicitVersion = arg('--objectui-version'); +let version = explicitVersion; +let versionSource = '--objectui-version, as passed'; if (!version) { - fail( - 'no --objectui-version and no version in scripts/sdui-manifest.record.json.\n' + - " Pass the @object-ui/* version the pin ships (the objectui checkout's packages/core/package.json).", - ); + const leg = readPinnedDeclaredVersion(pin, { root: ROOT }); + if (leg.status !== 'resolved') { + fail( + `no --objectui-version, and the pinned commit's declared version could not be read: ${leg.reason}\n` + + ' ⛔ This script does NOT fall back to the version in scripts/sdui-manifest.record.json: after a pin\n' + + ' bump that re-records the NEW pin under the OLD version string, and check-sdui-manifest.mjs check 4\n' + + ' reds exactly that record. Either:\n' + + ` - point OBJECTUI_ROOT at an objectui checkout carrying ${pin.slice(0, 12)}…, or\n` + + ' - pass --objectui-version {the @object-ui version that pin ships} explicitly.', + ); + } + version = leg.version; + versionSource = `packages/core/package.json at objectui ${pin.slice(0, 12)}… (read from ${leg.where})`; } let modulesRoot = arg('--modules-root'); @@ -205,4 +239,7 @@ const nextRecord = { }; writeFileSync(RECORD_PATH, JSON.stringify(nextRecord, null, 2) + '\n'); console.error(`✓ wrote sdui.manifest.json (${count} components, ${Buffer.byteLength(json)} bytes, sha256 ${sha256.slice(0, 12)}…)`); -console.error(`✓ re-recorded scripts/sdui-manifest.record.json at pin ${pin.slice(0, 12)} / @object-ui ${version}`); +console.error( + `✓ re-recorded scripts/sdui-manifest.record.json at pin ${pin.slice(0, 12)} / @object-ui ${version}\n` + + ` (version from ${versionSource})`, +);