Skip to content

chore(objectui): bump the console pin to db11afd4967c (carries objectui#11119, the objectui#11105 fix) - #20706

Merged
objectstack-fleet[bot] merged 6 commits into
mainfrom
claude/issue-20638-bump-objectui-pin
Sep 30, 2026
Merged

objectstack-fleet[bot] merged 6 commits into
mainfrom
claude/issue-20638-bump-objectui-pin

Conversation

@objectstack-fleet

@objectstack-fleet objectstack-fleet Bot commented Sep 29, 2026 •

Copy link
Copy Markdown
Contributor

Fixes #20638

Clause-②: no

Bumps the console pin: .objectui-sha dd3f7e1be356 -> db11afd4967c (objectui origin/main HEAD at bump time, on main). The pin ships @object-ui/console 17.6.0 (apps/console/package.json at the pin and @object-ui/core workspace version both 17.6.0; npm view @object-ui/console@17.6.0 version answers 17.6.0).

Containment (objectui merge-base --is-ancestor C db11afd4967c, full clone, not shallow)

commit subject result
a5841be351 flow designer shows a connector action's description (objectui#11028) exit 0, contained
99878d8e3a validateTree no longer calls a declared bind unknown (objectui#11008) exit 0, contained
49f76725aa matrix report with columns draws its declared chart (objectui#10964) exit 0, contained
ae582b70a number field useGrouping (objectui#11026) exit 0, contained
5b2ea17570 Studio previews show authored descriptions and labels (objectui#11027) exit 0, contained
3100bef65c server-grouped grid selects field names (objectui#11105, PR #11119) exit 0, contained
control dd3f7e1be3 (old pin) exit 0

The target is objectui origin/main HEAD (git branch -r --contains lists origin/main).

What changed

  • .objectui-sha, sdui.manifest.json, scripts/sdui-manifest.record.json (via scripts/gen-sdui-manifest-node.mjs, no arguments: the --objectui-version route is retired per that script), and .changeset/console-db11afd4967c.md (written by scripts/bump-objectui.sh, minor).
  • pnpm objectui:build at the new pin built the console dist (64404 KB) with no API break against framework code.

Follow-up (pushed on this branch, two commits, written 2026-09-29T20:01Z)

Requested by the PM seat after the first report: the two gates that sat outside the first file surface.

  • packages/sdui-parser/objectui-lockstep.json re-recorded with pnpm gen:sdui-lockstep against db11afd4967c; pnpm check:sdui-lockstep now exits 0.
  • The 49 spec sources that asserted the old pin were re-measured, not re-labelled: each anchor mapped through the dd3f7e1be356..db11afd4967c diff and re-read, hashes and counts re-taken with the method each record names, and only then the pin and the moved numbers updated. Files: component.zod.ts, component.test.ts, view.zod.ts, dataset.zod.ts, functional-completeness.ts, api-methods-batch-conformance.test.ts, six migrations/entries/semantic/18.* files and the regenerated migrations/registry.ts. pnpm --filter @objectstack/spec run check:objectui-pin-citations exits 0 (49 asserting citations match, 7 anchor content assertions verified).
  • content/docs/references/ui/view.mdx regenerated with gen:docs: the FormField.span describe names the pin, so its sha moved. This is the only non-comment text change; no schema or behaviour moved.
  • One claim was falsified, not just moved: objectui#5157 closed ObjectMapConfigSchema with .strict(), so the ListMapConfigSchema record in view.zod.ts no longer holds when it says the renderer's schema is a plain z.object that parses an undeclared key clean. The three anchors were re-pointed and the two false sentences were qualified in the comment. That prose wants a human read.
  • These edits ship inside published text, so .changeset/objectui-pin-citations-db11afd4967c.md carries an @objectstack/spec patch (commit d8bac3877d).

Resolved since the first report

Boot at the new pin

  • scripts/build-console.sh at db11afd4967c, with this tree's client and spec injected and the canary present. assert-console-spec-injection passes: 105 of 145 injected-only descriptions present, all 160 published-only absent. chunk-membership reads client in vendor-objectstack.
  • examples/app-showcase booted with objectstack dev --ui --fresh --no-seed-admin; bootstrap-status read hasOwner: false.
  • Headless Chromium opened /_console/setup and submitted the owner form. bootstrap-status flipped to hasOwner: true, and the session is the new owner (platform_admin, org_owner). The wizard landed on /_console/home, with Showcase and Setup listed.
  • Signed in again through /_console/login: Showcase opens its Capability Map html page, and Setup opens System Overview. 0 page errors, 0 TypeError, 0 5xx. The only 404 is GET /api/v1/usage/storage, as at the old pin.

Governed surface

None of the 20 changed paths is a row of GOVERNED_SURFACES in scripts/pm/check-governed-merges.mjs (rows: docs/adr/, .claude/, skills/, AGENTS.md, CLAUDE.md, docs/NORTH-STAR.md). No release act performed.

Gates at head ef6276c0e9: 125 derived, 125 run, 0 NOT-MEASURED, 0 unrun; all 125 exit 0. packages/spec tests: 16991 passed (576 files). sdui-parser: 199 passed. Spec and sdui-parser typecheck clean.


🤖 Generated with Claude Code

https://claude.ai/code/session_01VDtqoecgES7ScQYGbFVDRv

@github-actions github-actions Bot added size/m documentation Improvements or additions to documentation tooling labels Sep 29, 2026
@github-actions

github-actions Bot commented Sep 29, 2026 •

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 2 package(s): @objectstack/sdui-parser, @objectstack/spec, touching 12 documentable anchor(s). ⚠️ 2 changed file(s) yielded no anchor (packages/sdui-parser/objectui-lockstep.json, packages/spec/src/kernel/functional-completeness.ts), so the pages documenting them are NOT COVERED by this run — this is not a clean bill of health for those files.

2 hand-written doc(s) NAME something this change touched and may need an implementation-accuracy re-verification:

  • content/docs/data-modeling/analytics.mdx (via DatasetMeasureSchema (symbol, a top-level const))
  • content/docs/protocol/objectui/layout-dsl.mdx (via ComponentPropsMap (symbol, a top-level const object))

⛔ 5 release-owned page(s) also name something this change touched. These are read-only:

  • content/docs/releases/v15.mdx (via PageTabsProps (symbol, a top-level const object))
  • content/docs/releases/v17/17-1.mdx (via ComponentPropsMap (symbol, a top-level const object))
  • content/docs/releases/v17/17-3.mdx (via ComponentPropsMap (symbol, a top-level const object))
  • content/docs/releases/v17/17-4.mdx (via ComponentPropsMap (symbol, a top-level const object))
  • content/docs/releases/v17/17-5.mdx (via ComponentPropsMap (symbol, a top-level const object))

content/docs/releases/ is RELEASE-OWNED (AGENTS.md "Documentation Guardrails"): release
notes are written centrally at release time, and a code PR that edits them is the exact PR
that guardrail exists to stop. They are still audited — read-only. If one of them is actually
wrong, file an issue or open a dedicated docs-only PR; do not edit it here.

What this run could not see
  • 2 changed file(s) yielded no anchor (packages/sdui-parser/objectui-lockstep.json, packages/spec/src/kernel/functional-completeness.ts) — pages documenting those are invisible to this run
  • 2 name(s) were too generic to anchor anything (single lowercase words)
  • the SDK route bridge reached 54 of 206 client-bound route-ledger rows — the other 152 have no registrar path: tail to select them, so pages documenting THEIR client methods cannot appear above, on this or any run. Of those 152: 0 are remediable by widening that discovery convention (an in-repo file declares the path; the convention did not scan it); 55 are structural — on a ledger where NOT ONE row is declared in-repo, so no discovery change reaches them at any price; 97 are undecided (no in-repo declaration, on a ledger that has other in-repo registrars — absence and an unreadable spelling are not distinguishable here). The rows themselves: node scripts/docs-audit/affected-docs.mjs --bridge-coverage
  • a page that states a rule by its inputs shares no identifier with the emitter that implements the rule, so an emitter-only diff cannot list it — not on this run and not on any run. Measured on fix(driver-sql): emit varchar(maxLength) for a text field a declared index keys on #11430: content/docs/protocol/objectql/types.mdx documents the text-family column mapping by the ObjectQL type names it maps FROM (text / textarea / html) while the diff changed createColumn; it went unlisted, and it was the page that diff falsified, in four places. No shared token exists to detect this on, so a rule your change carries has to be re-read by hand in the pages that restate it.
  • a key NAME is not a key, so the hand re-read the line above prescribes can land on the wrong schema. The same spelling is authorable on one governed type and a [REMOVED] tombstone on another for each of active, aria, joins, objects, template, tools and version (censused on [finding] tools is a key on BOTH AgentSchema (tombstoned, dead) and SkillSchema (live, cloud-attested), so a name-based search attributes skill examples to the agent key — it produced a false stop-the-line alarm on PR #19059 #19093 over the liveness ledger's governed types, top-level keys); nothing in a search result distinguishes the two, so a grep hit on a LIVE example reads as evidence about the DEAD key. Measured on fix(spec): the agent.tools liveness row says dead — it claimed live on a key the schema tombstoned #19059: content/docs/ai/agents.mdx was reported as contradicting the agent.tools tombstone over its tools: example at :161, which is inside the defineSkill({ block opened at :155 — the page was already correct. Settle ownership by PARSING the value against both schemas, never by the name: that literal PASSES SkillSchema, and as an AgentSchema it FAILS at tools with the tombstone prescription. ⛔ These names are not the whole class — a key retired through a .strict() guidance map leaves no tombstone in the walked shape and none of them here (tool.category, live as AIToolDefinition.category).

Coarse fallback — 138 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): node scripts/docs-audit/affected-docs.mjs --json 7053333e1e2194cea2e21d8b2e1c9b6f081fcfa6 → packageMentionDocs.

Which tree this was computed on

This run read content/docs from fa9e366c44a895f3660c22c0d34202e3ec23fc53 — the merge of head ef6276c0e9cc91a3fdcc9acc5acea9e897b0fb7f into base 7053333e1e2194cea2e21d8b2e1c9b6f081fcfa6, which is what actions/checkout gives a pull_request run. Not the PR head.

A worktree cut from an older main holds a different content/docs, so re-deriving there can legitimately return a different list — that is a different tree, not a wrong row. To answer on the same tree:

# while this PR is open — GitHub drops the merge commit once it closes
git fetch origin fa9e366c44a895f3660c22c0d34202e3ec23fc53 && git checkout fa9e366c44a895f3660c22c0d34202e3ec23fc53
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin 7053333e1e2194cea2e21d8b2e1c9b6f081fcfa6 ef6276c0e9cc91a3fdcc9acc5acea9e897b0fb7f && git checkout -B drift-repro 7053333e1e2194cea2e21d8b2e1c9b6f081fcfa6 && git merge --no-ff ef6276c0e9cc91a3fdcc9acc5acea9e897b0fb7f

node scripts/docs-audit/affected-docs.mjs --json 7053333e1e2194cea2e21d8b2e1c9b6f081fcfa6

⚠️ That checkout carried uncommitted changes, so the commit above does not fully identify what was read.

Advisory only, and a precision-first one (#9192): a page is listed because it names a
symbol, wire route or SDK method this diff touched — not because it mentions a changed
package. Each row says which anchor put it there, so a wrong row is reportable rather than
merely annoying. To re-verify, run the docs-accuracy-audit workflow scoped to these files:
node scripts/docs-audit/affected-docs.mjs 7053333e1e2194cea2e21d8b2e1c9b6f081fcfa6 → pass the list as
args.docs, on the commit named under Which tree this was computed on.

Every record asserting the pin was re-read at the new pin: anchors mapped through the
pin-to-pin diff, hashes and counts re-taken with the method each record names, and the
ListMapConfigSchema record corrected where objectui#5157 closed ObjectMapConfigSchema.
Comments, citation strings and one describe sentence only.
This was referenced Sep 29, 2026
… bump

Replaces the bump script's placeholder in .changeset/console-db11afd4967c.md
with `not-required (no-migration-prescription)`, the maintainer's
disposition, takeover claim 5903537467, worded after the last pin bump's
(3cf6449). The reason block states what this diff moves: the pin, the
console changeset, the sdui manifest and record, the lockstep record, and
the pin citations in packages/spec/src, which change describe text and
migration-entry description text with no key added, removed or renamed.
The six declared-breaking entries are objectui's own package surfaces.

Claude-Session: https://claude.ai/code/session_014EJ1ED8X4MMrT18BhVx4tx
Co-authored-by: Claude <noreply@anthropic.com>
@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

Contract review

Served-tier: CONTRACT_REVIEW_TIER
Head-sha: ef6276c0e9cc91a3fdcc9acc5acea9e897b0fb7f
Local-runs: none

Read: card #20638 (body and all 7 comments, including the triage target rule 5895893448, claim 5896593369, report 5896951506, takeover claim 5903537467 and report 5904014004), PR #20706 (body, its one comment, 6 commits, 20-path file list, the net diff against merge base 7053333e1e), #20436 / 3cf6449389 as the precedent, the 35 check-runs on this head (read once), and objectui at both pins through REST compare, the trees API and raw files. Nothing was built, run or re-run; the anchor hashes below are sha1 over the fetched raw bytes.

① Derived judgments

Containment (REST compare, not the dev's table). C...db11afd4967c for each target reads status: ahead, behind_by: 0: a5841be351 (ahead 23), 99878d8e3a (48), 49f76725aa (47), ae582b70a (21), 5b2ea17570 (17), 3100bef65c (6). Control: dd3f7e1be356...db11afd4967c reads ahead 113 / behind 0 (113 commits, the range the changeset digests). db11afd4967c...main reads ahead 23 / behind 0, so the pin is an ancestor of objectui main. The commit is fix(plugin-grid,types): six of the eight keys ObjectGridSchema declares take effect or are retired (objectui#11068) (#11130), committed 2026-09-29T18:01:28Z; apps/console/package.json at the pin is @object-ui/console 17.6.0. Right.

@objectstack/spec — accept set: no change; public surface: text only. Right. Every changed line of the 13 .ts files under packages/spec/src, read off git diff -U0 against the merge base, is one of three shapes: a comment line (358: api-methods-batch-conformance.test.ts 16, functional-completeness.ts 36, component.test.ts 50, component.zod.ts 212, dataset.zod.ts 10, view.zod.ts 34), a + '…' string-continuation line inside the reason field of the six 18.*-unit-in-key.ts entries (43) and their projection in registry.ts (43, every hunk between lines 12436 and 16850, inside the os-generated semantic:18 region that spans 5971 to 18576 — the generated region only, as the entries carry), or the FormField.span .describe() line in view.zod.ts (1 removed, 1 added; the key, z.enum(['auto', 'full']) and .default('auto') are byte-identical, only dd3f7e1be356 → db11afd4967c inside the sentence). No key, default, enum member, export, regex or code token moves; check:api-surface (Lint and Repo Gates) is green on the head. The published text that moves is that describe (the JSON-schema description, and its projection in the regenerated content/docs/references/ui/view.mdx, 2 rows) and the six entries' reason text (compiled into the registry). The ADR-0087 reason block calls the six strings "description text"; the field is reason — a naming looseness, not a false claim.

@objectstack/sdui-parser — no accept-set or public-surface change. Right. The only file is objectui-lockstep.json: rev, revDate and recordedAgainstPin move (3 lines); no source under src/ changes, and the file is outside the package's published files (dist, README.md, CHANGELOG.md), so no changeset is owed, as in #20436. check:sdui-lockstep (Lint and Repo Gates) is green. The revDate spelling changed from …Z to …+00:00: the generator writes git %cI, and both name the commit's committer instant above — benign.

@objectstack/console — the bundle moves 113 objectui commits; ObjectStack-authorable contract unchanged. Right. .objectui-sha moves; sdui.manifest.json is regenerated from the built tree (still 107 components; the diff is descriptions and type: string → [string, object] widenings on the per-locale-map label inputs of objectui#10993 / #11039 / #11061 and kin) and scripts/sdui-manifest.record.json moves with it (objectuiSha, modulesRoot .cache/objectui-db11afd4967c/apps/console, objectuiWorkspaceVersion 17.6.0, new sha256). The narrowings objectui declares in the range (ObjectMapConfigSchema.strict(), the content-channel refusals, the bare pivot drillDown retirement, the globalFilters[].options lift) are objectui's own validator and type surfaces, carried as the changeset's entry list; nothing in packages/spec moves with them, exactly the #20436 shape.

The re-measured numbers, re-taken at the pin (nine, beyond the three asked):

  • tracked files: the recursive trees API at db11afd4967c lists 9546 blobs (not truncated) and 9283 at dd3f7e1be356 — the two file totals every entry states.
  • packages/types/src/zod/objectql.zod.ts:2037 reads export const ObjectMapConfigSchema = z.object({, closed at :2046 by }).strict();; LIST_VIEW_LOCAL_OVERRIDES opens at :944 with no 'map' member; ObjectMapSchema.map binds the schema at :2149. So the three re-pointed anchors (1835 → 2037, 809 → 944, and ObjectView.tsx:2043 → 2280, which reads case 'map':) hold.
  • The falsified claim, re-read (the human read the first dev asked for): plugin-map/src/ObjectMap.tsx at the pin: getMapConfig at :388, const result = ObjectMapConfigSchema.safeParse(config); at :409, then if (!result.success) console.warn('[ObjectMap] Invalid map configuration:', result.error.format()) and return { ...config, style: … }; hasCoordinateBinding at :487, the refusal arm at :1285. The qualified sentences — the parse now FAILS on an undeclared key, getMapConfig warns it by name (the formatted error carries the unrecognized_keys issue), the read is still warn-only, the spread of the authored block is still returned, and the flatten whitelist (ListView.tsx:85 FLAT_MAP_CONFIG_SPELLING, :146 resolveListMapConfig) still drops the key in silence — are true at the pin. "objectui validate refuses the node with an unrecognized_keys issue at map" follows from the strict schema being the one ObjectMapSchema.map binds, and is what objectui's own 5157-object-map-config-strict.md declares. The spec changeset's summary of it is accurate.
  • containers.tsx 946-952 and 1171-1177 are the two item.icon && LazyIcon name={item.icon} icon blocks (the tabs and accordion triggers); :1005 and :1220 are the items inputs documented [{ label, value?, icon?, count?, visibleWhen?, children }] and [{ label, icon?, collapsed?, children }].
  • plugin-dashboard/src/index.tsx:252 reads { name: 'icon', type: 'string' }; packages/types/src/objectql.ts:4302 reads limit?: number;.
  • ObjectGrid.tsx:4637-4664 hashes (blob header plus bytes) to c88443302d40c2db739ddb235470bafa29056e2e, and hooks/useBulkExecutor.ts:298-303 to 01083348330f10a201cdf1078b4c21c236402b6a — both as api-methods-batch-conformance.test.ts now states.
  • FormField.span: plugin-form/src/autoLayout.ts:58-69 is WIDE_FIELD_TYPES (textarea, markdown, html, grid, richtext in both spellings), resolveColSpan at :154 returns the grid width on span === 'full'; spanLadderFor is packages/components/src/renderers/form/form.tsx:204-231 with its call at :2848 and emits one clamped class per multi-column tier. The describe's claim holds at the pin. (The record calls the file form.tsx without its package; it is the components renderer, not a plugin-form file — the same spelling chore(objectui): bump the console pin to dd3f7e1be356 (carries the injected-client boot fix) with the showcase div→box and trash-icon follow-through #20436 used, and the gate resolves anchors by suffix.)
  • Not re-taken: the lit-control grep totals (14704 objectstack, 5545 @objectstack/spec, timeout 1197, useState 2449, TTL 181, tenant 1200, and the rest), which need a whole-tree grep. The dark counts they calibrate are 0 at every pin, the file totals they sit beside are verified, and the method line is unchanged.

Migration registry. Only the generated region moves, and it moves by exactly the six entries' text (43 lines each side, identical hunks); check:migration-registry (Lint and Repo Gates) is green on the head.

② Semver level

@objectstack/console minor — right, and the entry list derives faithfully. Between the pins objectui's .changeset/ gained 99 files and lost none (trees diff; 70 stock files were edited in place and are rightly not entries). 89 carry a package frontmatter and 10 carry an empty one (release-nothing: 10088-json-fences-parse, the two 10803-dead-citation-sweep-*, 10895-…relatedlist-client-sort-gate, 10903-today-reference-day-rule, 10905-types-stale-docblocks, 10987-retire-list-view-tabs-fixture, 11024-spec-gate-canonical-operator-fixtures, 11040-comment-mask-tracked-files, 8071-master-detail-other-half-slice-18) — the changeset's "89 releasing of 99". The declared levels are patch 107 and minor 36 package-lines, no major, so the highest is minor. The digest's positional breaking rule (hasBreakingAnnotation: an emphasis run or block opening with the word) flags exactly six: 9256-input-content-channels, 9256-public-blocks-content-channels, 9256-remeasure-content-channels (each @object-ui/types), 10946-expression-wire-slots-by-reference (@object-ui/types), 10932-pivot-drilldown-retired (@object-ui/types and @object-ui/plugin-dashboard), retire-options-shorthand-lift-4356 (@object-ui/core) — the six entries the file marks BREAKING (7e8b3c033, f6fb83f0c, 2049b03df, d570eaa59, cc4e47638, a51fa0cca). The file carries 89 releasing rows and 20 _(no changeset)_ rows against the compare's 113 commits; four of the 20 spot-checked through the commits API (51401e63c, 80c2d5e61, a93ba8792, af2221d45) carry no .changeset/ path. The list, counts and level are what scripts/bump-objectui.sh writes through objectui-changeset-digest.mjs, in #20436's shape.

ADR-0087 disposition not-required (no-migration-prescription) — the maintainer's ruling (5903537467), recorded in b4cd814ec2 (+20/-1, the placeholder line only, as the takeover claim's surface allowed); the gate accepts it (Check Changeset, green). Every sentence of the reason block judged against THIS diff:

  • "moves .objectui-sha and the artefacts that travel with it (…)" — true; the parenthetical omits the spec changeset and the regenerated view.mdx, which the second paragraph and the PR name; not false.
  • "adds, removes or renames no ObjectStack-authorable key: no Zod schema, no spec declaration and no stored sys_metadata shape moves … no FROM/TO prescription of its own" — true (①); the block carries no prescription, so the category's one mechanical refusal does not bite.
  • "the re-measure changes text only: source comments, one .describe() sentence (FormField.span) and the description text of six semantic migration entries, with the generated migrations/registry.ts and reference page that project them … no key, default, enum member or export" — true (①), with the reason-field naming noted above.
  • "the 6 declared-breaking entries listed above are objectui's OWN package surfaces (@object-ui/types, @object-ui/core and @object-ui/plugin-dashboard), each already carrying its upstream record" — true: the six declare exactly those three packages (types five times, core once, plugin-dashboard once alongside types), each in its own upstream changeset.
  • "where one of them mirrors an ObjectStack-authorable key, the ledger entry belongs to the packages/spec PR that lands the mirror, never to the pin bump, whose diff contains no such key" — true of this diff: none of the six mirrors a key this diff changes, because this diff changes no key. (The closest kin, objectui#4356's globalFilters[].options, moves objectui onto the spec's existing { value, label } form; the spec side does not move here.)
  • "a claim about THIS diff, not a per-entry re-measurement of the 6" — true and correctly scoped.
    The ruling is not re-opened; its written reasons hold.

@objectstack/spec patch — right. The describe and the six reason strings ship in dist (the JSON-schema description; the compiled registry, which objectstack migrate meta and the upgrade guide read) and in the reference page, so skip-changeset would be wrong, and no accept set moves, so minor would be wrong. The body states the one falsified record accurately (above). #20436 took the same level for the same describe.

Clause-②: no — right, on the PR body and in both changesets. No accept set on an ObjectStack-authorable surface widens or narrows; objectui's own narrowings ride in the console bundle as upstream declarations, the reading #20436 gave its 41.

③ Boundary flags

  • First dev's flag, "that prose wants a human read" (the ListMapConfigSchema record in view.zod.ts): read against ObjectMap.tsx, objectql.zod.ts and ListView.tsx at the pin; every qualified sentence is true there (①). Answered.
  • First report's open questions. Q1 (the disposition) is answered by the maintainer's ruling and recorded as ruled. Q2 (widening to the lockstep and the 49 citations) was done on the same branch (690bf369c3, db448bfbe0, d8bac3877d); the PR body says the PM seat requested it after the first report, and the card carries no dispatch record of that widening between 5896951506 and the takeover claim. The takeover claim 5903537467 names the PR's 20 paths as the surface, so the surface is covered from that record on, and the head's file list is those 20 paths. Noted; nothing to do.
  • Deviation, OBJECTUI_ROOT at a private depth-1 source: accepted; the build script asserts the pinned HEAD, and the CI Console Pin Gate builds the pin independently — success on this head.
  • Deviation, origin/main moved after the merge: ordinary concurrency, not a flag. c9c182ed14 adds the time-default-zone-refused rationale at registry.ts:5811 and entry at :16899; this PR's hunks are reason-string lines at 12436–16850. No line overlaps, and both are projections of independent entry files, so a regenerated registry on the merged tree equals the text merge; check:migration-registry on the pre-landing merge arbitrates. f284ab26dd and eead9dcf40 touch none of the 20 paths. GitHub reads the PR mergeable_state: clean against current main.
  • The merge ef6276c0e9 itself lost nothing. Against its branch parent b4cd814ec2 it changes exactly the 393 paths main changed between 31ed067639 and 7053333e1e; against its main parent 7053333e1e it changes exactly the branch's 20; registry.ts, the one overlap, carries the branch's hunks and main's hunks each byte-identical to their own side. The os-regen-merge "nothing to regenerate" reading is consistent with that.
  • Boot vs the card's Acceptance: meets the bar. scripts/build-console.sh at db11afd4967c with this tree's spec injected (the injection assertion passing), a zero-user database (hasOwner:false before the drive), /setup registration completing (hasOwner:true, the owner session platform_admin / org_owner), the launcher and the first Showcase (the html Capability Map page, the one that died at the old pin's predecessor) and Setup pages, 0 page errors, 0 TypeError, 0 5xx — the same entry chore(objectui): bump the console pin to dd3f7e1be356 (carries the injected-client boot fix) with the showcase div→box and trash-icon follow-through #20436 drove, with the same pre-existing 404 on /api/v1/usage/storage. chore(objectui): bump the console pin to dd3f7e1be356 (carries the injected-client boot fix) with the showcase div→box and trash-icon follow-through #20436 went on to invitations, member gates, CRUD and a 95-surface sweep; the card asks for the boot driven past first-run registration, and that is what is recorded.
  • Out of scope, /_console/ lands on /login on a zero-owner deployment: pre-existing at both pins by the dev's read of LoginPage.tsx and App.tsx, objectui-side, and whether the login page's sign-up link bootstraps an owner was not measured, so no defect is established here. "Noted, not filed" stands; the owning seat may file a probe card if it wants that question answered. Not this diff's.
  • Out of scope, the 10 [expand] runAs refusals at owner sign-up: server-side, deliberate, independent of the pin. Not this diff's.
  • PR body is stale relative to the head: "Still open" still names the ADR-0087 placeholder, "Follow-up" says the spec changeset was not added, "Governed surface" counts 19 paths, and the gates line names db448bfbe0. The takeover report carries the five pr_body_lines edits; applying them is the owning seat's step before enqueue, since the body becomes the landing commit's message. Not a contract defect.
  • Gate coverage on this head: all 35 check-runs concluded — 34 success, 1 skipped by design (Packed-tarball smoke (opt-in)); none red, none unconcluded. Console Pin Gate: success. The families this diff derives are answered by: Console Pin Gate (the console built at the pin), Lint and Repo Gates (check-sdui-manifest, check:console-sha, check:sdui-lockstep, check:objectui-pin-citations, check:migration-registry, check:generated --reconcile-only, check:api-surface), Check Changeset (the ADR-0087 registration gate, on the merge base), Test Core 1–6, the four Type Check lanes, Spec property liveness, and the Governed Surface Queue Guard. Two assertions live outside CI and rest on the dev's recorded local reads: the pin-citation gate's 7 anchor-content assertions (verified with OBJECTUI_ROOT at the pin) and check-sdui-manifest --require-objectui (107 components, 17.6.0) — both accepted on the record, and the anchors I re-took above corroborate the first.
  • Governed surface: none of the 20 paths is a row of GOVERNED_SURFACES (docs/adr/, .claude/, skills/, AGENTS.md, CLAUDE.md, docs/NORTH-STAR.md); the queue guard agrees. No release act is performed. Landing is the owning seat's, through the queue, after the body edits.

Implemented-by: claude/issue-20638-bump-objectui-pin
Reviewed-by: session_014EJ1ED8X4MMrT18BhVx4tx

VERDICT: PASS


Generated by Claude Code

@objectstack-fleet
objectstack-fleet Bot marked this pull request as ready for review September 30, 2026 04:44
@objectstack-fleet
objectstack-fleet Bot added this pull request to the merge queue Sep 30, 2026
Merged via the queue into main with commit a3d7588 Sep 30, 2026
44 checks passed
@objectstack-fleet
objectstack-fleet Bot deleted the claude/issue-20638-bump-objectui-pin branch September 30, 2026 05:20
akarma-synetal pushed a commit to akarma-synetal/framework that referenced this pull request Oct 7, 2026
…undle in view (objectstack-ai#20646) (objectstack-ai#20743)

Fixes objectstack-ai#20646

Clause-②: no

`Console Pin Gate` is red on `main` since `fbec216e2d` (PR objectstack-ai#20695, the
`@objectstack/spec/migrations` entry split). Its build step exits 2:
"Neither spec appears in the built console — no @objectstack/spec
content matched." The injection works. The check was reading text the
console never bundles. This PR makes the build-time probe derivation
choose with the bundle in view. The fresh leg stops reading entries the
console never imports, and the stale leg becomes strictly stronger.

## Root cause, measured

`scripts/console-spec-probes.mjs` builds each spec's blob from every JS
file the package's `exports` map resolves to. The assertion then took
the alphabetically first unique `.describe()` text on each side. A
console bundles only the entries it imports, so either probe could come
from an entry the bundle can never carry.

The readings below compare the published `@objectstack/spec` 17.4.0 that
objectui locks at pin `dd3f7e1be356` with the framework spec.

| leg | framework | fresh witness (carried by) | in bundle | stale
detector (carried by) | in bundle | old check |
| --- | --- | --- | --- | --- | --- | --- |
| dark | `f927864ea0` (main before the split) | "A public export added
or removed by one release." (`.`) | yes | "Accepted developer agreement
version" (`./cloud`) | no | exit 0 |
| lit | `fbec216e2d` (`origin/main`) | the same text, now
(`./migrations`) | no | the same (`./cloud`) | no | exit 2 |

- The witness moved with the split from the root to `./migrations`,
which the console never imports. Meanwhile 102 of the 142 injected-only
descriptions ARE in that bundle; the first sorts from `./ui`.
- The stale leg was already blind. Its detector sits in the published
`./cloud` entry, which objectui's shipped source never imports: 116
`/ui`, 62 `/data`, 17 `/kernel` and so on, and no `/cloud`. A console
built WITHOUT the injection carries 56 of the 160 published-only
descriptions, and not that one.
- The spec side is not the cause. The console never imported the change
manifest, and the injected spec is in the bundle. `packages/spec` is
untouched here.

## The fix (`scripts/console-spec-probes.mjs`, `chooseProbes`)

- **Fresh witness:** the first injected-only description the bundle DOES
carry. With none carried, "neither spec appears" is still exit 2.
- **Stale leg:** judged over EVERY published-only description. It fails
when ANY of them is in the bundle, and reports the first one found with
the count. A bundle the old single pick flagged is still flagged, so
this is strictly stronger.
- **Stamp:** keeps its shape and version. With nothing published in the
bundle, the stamped detector is the same one `pickProbe` chose, so
`check:console-injection`'s cache-hit replay is unchanged.
- **Assertion script:** `scripts/assert-console-spec-injection.mjs`
calls `chooseProbes` and prints the counts. The exit ladder is
unchanged: 0 verified, 1 published spec bundled, 2 unverified.
- **Self-test:** `scripts/check-console-injection.mjs` gains battery 13
(roster floor 10 to 11). It runs the real assertion script on fixtures
whose first unique candidate is not in the bundle:
  - a working injection verifies, and its stamp replays green;
- a published-only description the old pick skipped fails the build and
writes no stamp;
  - neither side present stays exit 2.

I checked that the battery can fail: reverting `chooseProbes` to
first-pick semantics made it red with 5 failures, and restoring the fix
turned it green again.

## Proof

All legs ran against real `vite build`s of the console, with the old and
the new assertion on the same bundle.

| console build | objectui pin | new check | old check |
| --- | --- | --- | --- |
| injected spec from `fbec216e2d` | `dd3f7e1be356` | exit 0 (witness
from `./ui`; 102/142 present; 0/160 published) | exit 2 |
| NOT injected (published spec) | `dd3f7e1be356` | exit 1 (56/160
published-only descriptions present) | exit 2 |
| a bundle with no spec text | — | exit 2 ("Neither spec appears") | — |
| injected spec from `f927864ea0` (dark) | `dd3f7e1be356` | exit 0
(111/142 present) | exit 0 |
| injected spec from `fbec216e2d` | `db11afd49670` (PR objectstack-ai#20706's pin) |
exit 0 (102/142; 0/160) | exit 2 |
| NOT injected (published spec) | `db11afd49670` | exit 1 (56/160) |
exit 2 |

On this branch's head, the Console Pin Gate's steps run locally all
pass: `bash scripts/build-console.sh` with the injected spec exits 0;
the dist presence assert passes; `pnpm check:console-sha` exits 0; and
`pnpm check:console-injection --require-stamp` exits 0 and replays the
new stamp.

## Verification record

- `dispatch-gates --commands` for the 3 changed paths derives 31
families. `--ran` reconciles them as 30 run, all exit 0, and 1 NOT
MEASURED: `check:pm-dispatch-gates`, whose self-test alone outruns the
590-second foreground cap here. It does not read these files' behaviour.
- `node scripts/check-console-injection.mjs --self-test` passes: 44
assertions, battery floor met.
- Lint, narrowed and proven: `eslint --no-inline-config` on the 3
changed files reports 0 errors and 0 warnings. The config enables no
type-aware linting, so untouched files' verdicts cannot move.
- No changeset: the diff touches only root `scripts/`, which ship in no
published package (`@objectstack/spec-monorepo` is private).

## Acceptance notes

- **The cache-hit replay's stale leg is still a single stamped
detector.** At this pin that detector is `./cloud` text no console
bundles, so on a dist-cache HIT the replay cannot catch a published
spec. The build-time leg now can. Fixing the replay needs a
multi-detector stamp (a `stampVersion` bump that invalidates every
cached dist under the unchanged cache key), which is outside this claim.
Carrier: the `domain:spec` seat. Noted, not filed.
- **CI on this head:** `Console Pin Gate` (job 109696257740) concluded
success. The dist cache missed, so step 11 built the console and ran the
changed assertion (105 of 145 injected-only descriptions present, all
160 published-only absent), and steps 12 to 14 passed on that fresh
dist.

---
_Generated by [Claude
Code](https://claude.ai/code/session_014EJ1ED8X4MMrT18BhVx4tx)_

Co-authored-by: Claude <noreply@anthropic.com>
akarma-synetal pushed a commit to akarma-synetal/framework that referenced this pull request Oct 7, 2026
…s to the commits that decided them (stage 10) (objectstack-ai#20750)

Part of objectstack-ai#20234

Clause-②: no

Stage 10 of the dead-citation sweep: the migration registry's
hand-written entries. Every tracker number in
`packages/spec/src/migrations/entries/**` that no longer exists on the
board now cites the commit that decided it, in ruling C+D form C (ruling
`5749154545` on objectstack-ai#19123). Where the number alone carried the meaning, the
line now says what was decided. That is 131 sites over 21 numbers. All
of them are comments; the entries' string literals carry no dead number.
`migrations/registry.ts` moves only by `gen:migration-registry`. No
entry id, literal, order, `conversionIds` or code token moves, and no
live citation is removed.

## Boundary

- **In:** all of `entries/**`. The gate's census reads 117 sites there,
under the claim's ~120 slicing threshold, so there is no slice. My raw
walk finds 14 more comment sites that the census does not count (see
*Census* below), which gives 131 in total. They are the same dead card
on the line after a counted site, plus one README line, so they are
rewritten with it.
- **Regenerated only:** `migrations/registry.ts`, 128 lines.
`spec-changes.json` and `docs/protocol-upgrade-guide.md` do not move,
because entry comments are never projected into them. Both `check:`
scripts pass with no regeneration.
- **Out, per the claim:** `registry.ts`'s hand-written parts. They still
hold 13 dead sites, listed under Acceptance notes. The six
`18.*-unit-in-key.ts` entries that PR objectstack-ai#20706 edits carry no dead site,
and I did not touch them. I did not touch `conversions/` or other lanes'
sites.

## The anchors (one per number, reused from earlier stages where they
anchored the same number)

| number | sites | anchor | what the rewritten line says it decided |
|---|---|---|---|
| objectstack-ai#13135 | 26 (13 are `re-charter objectstack-ai#13135`) | commit 9e0ba21 | retires
the paper metadata-customization protocol; re-charter of objectstack-ai#12057, which
stays |
| objectstack-ai#8495 | 23 | commit 4bfe1a5 (PR objectstack-ai#8666 kept) | the precedent: the
first 17.x-line narrowing registered under protocol 18 (its own second
commit says so) |
| objectstack-ai#8715 | 16 | commit 2c86fe3 | the ApiKeySchema retirement; its
message names the "route 3" kit (no carrier key, no tombstone, no D2) |
| objectstack-ai#14691 | 11 | commit b3a63d3 | retires the ten inert
`RestServerConfig` keys |
| objectstack-ai#10724 | 11 | commit be21955 | retires the nine dead `contributes`
members |
| objectstack-ai#14369 | 10 | commit a3d5724 | the liveness census that recorded the
15 `dead` rows |
| objectstack-ai#10485 | 6 | commit 35ad101 | retires the `themes` carrier and
`ThemeSchema` |
| objectstack-ai#11846 | 5 | commit 0c2334f | retires preview mode; its own text
carries the ruling record (objectstack-ai#12428 kept) |
| objectstack-ai#14676 | 5 | commit 13c48c2 | retires `connector.errorMapping` |
| objectstack-ai#11332 | 3 | commit dce5cd4 | retires the manifest's three dead
containers |
| objectstack-ai#6361 | 2 | commit 90bbf25 | retires the notification-list `cursor`
on both halves |
| objectstack-ai#10627 | 2 | commit be21955 | that commit records the controlled
monorepo census |
| objectstack-ai#14365 | 2 | commit f60ab90 | the open `z.partialRecord` proposal
that commit's changeset recorded; the retirement leaves no record to
reshape |
| objectstack-ai#14526 | 2 | commit db16b94 | the landing of the client envelope
convergence (anchor block, and the README's measured case) |
| objectstack-ai#6363 | 1 | commit 17d0954 | "ruled jointly with the `unreadCount`
fix" |
| objectstack-ai#6239 | 1 | commit f549a0d | the ViewProtocol retirement sweep |
| objectstack-ai#10726 | 1 | commit bc56e18 | retires `contributes.routes` (Option
B) |
| objectstack-ai#10812 | 1 | commit be21955 | "the cloud census", whose 2026-08-24
reading @5b5925a that commit's message records |
| objectstack-ai#9041 | 1 | commit d491625 | the url-branch refinement (objectstack-ai#9147, live,
stays) |
| objectstack-ai#14996 | 1 | commit db16b94 | the ADR-0087 registration, which
landed in the same squash (its body: "Registration requested on objectstack-ai#14996")
|
| objectstack-ai#14312 | 1 | commit e944fdb | the `oauth.*` binding, which left
`applications.delete` out as a behaviour change (PR objectstack-ai#15445 kept) |

Two lines change without a number, so the sentence still reads:
`patterns`' follow-on line and the `oauth` anchor block's continuation
line. In total 133 lines are removed and 133 added in 86 files, and
every file is balanced.

## Verification record (final head `1ee5841c09`; base `fbec216e2d`)

**Census** (the gate's own `check-issue-citations.mjs --census --json`,
board enumerated, 186 pages):

| subtree | base (00:21Z, frontier objectstack-ai#20740) | head (01:18Z, frontier
objectstack-ai#20743) |
|---|---|---|
| `entries/retired-keys` | 73 | 0 |
| `entries/retired-defs` | 40 | 0 |
| `entries/semantic` | 4 | 0 |
| `registry.ts`, generated regions | 114 | 0 |
| `registry.ts`, hand-written parts | 2 | 2 |
| `chain.ts`, `types.ts`, `index.ts`, `spec-changes.ts`, tests | 0 | 0 |
| **`migrations/`** | **233** | **2** |
| `packages/spec/src` | 235 | 4 |

- **Site-set difference:** 254 sites are only at base. 231 are this
diff's (117 plus 114 copies). The other 23 are `plugin-audit`'s, from
`main`'s objectstack-ai#20737. 0 sites are only at head.
- **Kind** (every census site is a comment): a TypeScript 6.0.3 walker
classes all 131 entry sites as comments. It also finds 13 dead string
sites, all in `registry.ts`'s hand-written rationale (see Acceptance
notes).
- **Probe:** REST `issues/N` without following redirects, over all 302
distinct in-repo numbers of 100 or more in `migrations/`. 277 answer 200
and 25 answer 404. Controls were read at start, every 50 and end: lit
objectstack-ai#20234 200 (8/8), dead objectstack-ai#8710 404 (8/8).
- **Blind spots:** the census does not count 14 of the 131 entry sites.
- 13 are `re-charter objectstack-ai#13135`, because `NON_CITATION_HEADS` reads
`re-charter #N` as an ordinal.
- 1 is in `entries/README.md`, which is outside the gate's
`packages/**/src/**/*.ts` surface.
- **Numbers:** no tracker number is added. The only numbers on added
lines are the live ones kept from the same lines: objectstack-ai#8666, objectstack-ai#12057, objectstack-ai#8586,
objectstack-ai#12428, objectstack-ai#9147 and objectstack-ai#15445. The diff-scoped gate judges them: "every
citation this change adds resolves".

**Residue** (scratch walker over the TypeScript parser, per file, base
vs head, 86 `.ts` files):
- The file with every comment range cut out, everything else byte for
byte, is IDENTICAL.
- The leaf-token stream is IDENTICAL: 38,417 tokens, aggregate
`67c1f6db944e93ed`.
- **Controls** mutate the head text in memory only, 259 of 259 as
expected:
  - Expected identical: a comment insertion in every file.
- Expected to differ: a string-literal edit, a template-literal edit, a
regex-literal edit (where the file has one) and an appended declaration.

**Regeneration** (`gen:migration-registry`):
- `check:migration-registry` exits 1 before and 0 after.
- The registry diff is 128 lines out and 128 in. As (old, new) pairs
they equal the entry diff's pairs, re-indented by four spaces.
- 0 changed lines fall outside the generated regions.
- 5 entry pairs are deliberately not carried: the README line, and the
semantic "Anchors" header lines, which sit above a blank line and so are
not in the carried comment run.
- `check:spec-changes` and `check:upgrade-guide` exit 0 with no
regeneration.

**Build and tests** (under `os-verify-lock`):
- Build: `turbo run build` over `./packages/*` and `./packages/*/*`, 71
of 71, at `845e90fea4` and again at `1ee5841c09`.
- `check:generated`: all 15 artifacts up to date, at both heads.
- spec `local` project: 576 files, 16,991 passed and 1 todo, at both
heads.
- spec `repo` project: 41 of its 45 files, 666 passed, at both heads.
- spec `typecheck`: exit 0; 53 files / 251 errors / 138 pinned
signatures held.

**Gates:** `dispatch-gates --commands` derives 82 gates, and the
derivation is identical before and after the second merge. At
`1ee5841c09` all 82 exit 0. `--ran` reconciles: 82 derived, 82 run, 0
NOT-MEASURED, a derived zero.

**Lint** (a proven narrowing):
- `eslint --no-inline-config --format json` over the 86 touched `.ts`
files: 86 files, 0 errors, 0 warnings.
- `isPathIgnored` is false for all 86.
- `eslint.config.mjs:327-328` states that type-aware linting is never
enabled, so a comment edit cannot move an untouched file's verdict.

**Changeset:** `patch`.
- In the built `dist`, the new wording (for example "the precedent of
commit 4bfe1a5, PR objectstack-ai#8666") appears in `dist/migrations/index.js` and
`.mjs`, and the old wording appears in 0 files.
- Control: an unchanged phrase appears in the same 2 files.
- So the published `@objectstack/spec/migrations` entry carries these
comments.

**Merges:** `origin/main` was merged twice through
`scripts/pm/os-regen-merge.sh`. Neither merge left a regeneration to
commit.
- Since then, `main` has advanced to `97005aed04`, and none of those
commits touches `packages/spec`.
- Driver-free `merge-tree` probes (from a bare `--shared` scratch clone
with no `merge.*` config) exit 0 against that `main` and against PR
objectstack-ai#20706's head `d8bac3877d`.

## Acceptance notes

- **The next stage for this card: 13 dead sites left in `registry.ts`'s
hand-written parts.** They are outside this claim, which says
`registry.ts` is regenerated only.
  - **Comments (form C), 2:**
- `:5940` objectstack-ai#8495, the step-18 doc comment on the persistence placeholder
refusal.
    - `:22819` objectstack-ai#6239, the `RETIRED_DEFS_BY_MAJOR[17]` doc comment.
  - **Author-shown rationale strings (form D), 11:**
- Step 17's `:344` objectstack-ai#6345. It projects into
`docs/protocol-upgrade-guide.md:68`, so that stage regenerates the
guide.
- Step 18's fragments: `:5121` objectstack-ai#14676, `:5455` objectstack-ai#12868, `:5526` objectstack-ai#10329,
`:5544` objectstack-ai#8495, `:5555` objectstack-ai#13135, `:5742` objectstack-ai#10724, `:5745` objectstack-ai#10627, `:5752`
objectstack-ai#10726, `:5799` objectstack-ai#10485, `:5816` objectstack-ai#10926. These are not projected into
either artifact yet.
- **Census blind spots, measured here and not filed** (a coverage
boundary, not one of the three filing classes; new gates default to no):
- `NON_CITATION_HEADS` skips `re-charter #N` even where N is a tracker
card.
  - `.md` files under `packages/**/src` are outside the surface.
- **NOT MEASURED locally, left to CI:**
- `scripts/build-schemas-check-mode.test.ts` hit the foreground cap
alone (exit 124 after 560 s, no output). It parses `registry.ts`'s
source; the residue check above shows that source's code and string
tokens are unchanged.
- The other three heavy `repo`-project files (`def-key-collisions`,
`publish-smoke-boot-failure`, `publish-smoke-port-collision`) were not
run, as in stages 8 and 9.
- **Hypothesis 6's baseline half is falsified by construction.**
`scripts/doc-authoring-prose-id.baseline.json` has no `packages/spec`
row, because its leg excludes `packages/spec`. `check:doc-authoring`
reads strings only, so a comment-only diff cannot move it. It read 808
sites across 229 files at `845e90fea4` and 794 across 227 at
`1ee5841c09`. The difference is `main`'s own re-anchor commits; this
diff touches no row.

---
_Generated by [Claude
Code](https://claude.ai/code/session_014EJ1ED8X4MMrT18BhVx4tx)_

---------

Co-authored-by: Claude <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

2 participants