Skip to content

chore(console): bump the objectui pin 190fbd01 → 9602dc82 so a stock console build resolves automation:packaged - #12955

Draft
os-elon wants to merge 2 commits into
mainfrom
claude/issue-12687-objectui-sha-bump
Draft

chore(console): bump the objectui pin 190fbd01 → 9602dc82 so a stock console build resolves automation:packaged#12955
os-elon wants to merge 2 commits into
mainfrom
claude/issue-12687-objectui-sha-bump

Conversation

@os-elon

@os-elon os-elon commented Aug 28, 2026

Copy link
Copy Markdown
Collaborator

Fixes #12687

Status: deliberately blocked, not stalled. check:objectui-pin-citations stays red on two
element:button records whose read point MOVED. By maintainer ruling (2026-08-28) that repair
is packages/spec authorable-surface contract prose, which is not this card's to rewrite — it
is tracked as #12968, and this PR waits on it. A loud, accurate red on a record that needs
a human decision is the outcome that gate was built to produce. Details in "Patch round 1".

Moves .objectui-sha from 190fbd01d061 to 9602dc820450 through the repo's dedicated
bump tooling (scripts/bump-objectui.sh), so a stock vendored-console build can resolve
the automation:packaged component ref.

If you are a tester walking ADR-0126 acceptance item A1

A1 — "admin login → Setup → Packaged automation page exists" — was failing for pin lag, not
for a UI defect.
The nav entry was already present and correct in the served metadata (PR
#12491 landed that), which is why the page's absence read like a rendering bug. It was not.
The console SPA this repo vendors was built from an objectui commit that predates the page
entirely, so the ref the metadata names had nothing to resolve to.

Measured, both directions, at the two pin endpoints:

objectui revision automation:packaged in the tree packages/app-shell/src/views/setup/
190fbd01d061 (old pin) 0 occurrences repo-wide (git grep -c exit 1; control term registerAppComponent hits 4× in the same file at the same revision, so the search itself works there) 0 files — the directory does not exist
9602dc820450 (new pin) 4 files, incl. services/builtinComponents.tsx 6 files, incl. PackagedAutomationPage.tsx

A bundle built from a tree that does not contain the string cannot register the ref. That is
the whole defect, and this pin move is the whole remedy. If you filed a UI bug against A1,
it is a duplicate of this pin lag.

The verification that actually answers the card

Not "the pin string changed and CI is green" — the card's point is that the served metadata is
already correct, so a metadata-side check proves nothing. The check is on the built bundle:

$ bash scripts/build-console.sh          # the stock build, unmodified
✓ Bundle canary 'import/jobs' present — framework client is in the bundle.
✓ Console bundle carries THIS tree's @objectstack/spec, and only it.
✓ @objectstack/console dist ready (49824 KB) from objectui@9602dc820450

$ grep -rho '.\{0,90\}automation:packaged.\{0,90\}' packages/console/dist/assets
…q_({ref:`automation:packaged`,label:`Packaged Automation`,source:`@object-ui/app-shell`,component:xv})…

One occurrence, in the app-shell component registry, bound to the minified
PackagedAutomationPage. Negative control (a ref that must not exist) correctly absent;
positive control present. This is the Console Pin Gate's own work, run locally ahead of CI —
and it passed.

Target choice — and a correction to the card

The card gives the target as >= 9602dc8 and attributes the page to "objectui#6382 / #6415".
Re-measured, that conflates two commits:

  • b362c1b474b8 (objectui#6382, 2026-08-25 19:32) is what actually introduces and
    registers
    automation:packaged — ADR-0126 §7.4, the Setup page itself. This is the true
    lowest SHA that resolves the ref.
  • 9602dc820450 (objectui#6415, 2026-08-25 22:43, 17 commits later) adds the packaged
    actions section beside the flows — ADR-0126 §8 item 2.

Pinned at 9602dc820450 rather than the lower b362c1b474b8 deliberately. The two are three
hours apart, so the lower pin buys no meaningful delta reduction, while b362c1b474b8 would
ship the page with its actions half missing — recreating the very "reads as a UI bug rather
than pin lag" trap this card exists to end, one acceptance item later. 9602dc820450 is also
the card's own stated bar.

Two more corrections, measured

  • Delta size. The card states "~700 objectui PRs". Measured over 190fbd01d061..9602dc820450:
    359 non-merge commits, 279 changesets added, of which 188 releasing, 91
    release-nothing, and 82 commits carrying no changeset. Still a large, risk-bearing range —
    just not 700. (objectui squash-merges, so commits ≈ PRs: --merges counts 0 in the range.)
  • File surface. packages/console/dist is gitignored (packages/console/.gitignore =
    dist/), and scripts/bump-objectui.sh writes exactly two files — .objectui-sha and the
    derived changeset. It touches no lockfile and no pnpm override; there are none to carry.
    So the diff is 2 files, and the large console delta is a build-time artifact CI produces
    and caches, never a committed one.

The ADR-0087 disposition

bump-objectui.sh emits the changeset with an adr-0087: TODO placeholder and states in its
own output that the bump cannot answer it and a human must, before pushing —
check-adr-0087-registration.mjs rejects the placeholder on purpose. That marker is the one
thing in this PR written by hand, and it is the tooling's own mandated step, not an edit to
generated content.

All 11 declared-breaking entries in the range are judged one at a time against their own
upstream changeset. Disposition: not-required (no-migration-prescription). The load-bearing
re-measurements at this HEAD:

  • packages/console/package.json publishes a frozen prebuilt SPA — files is
    ["dist","README.md","CHANGELOG.md"] and the sole exports entry is ./package.json. It
    forwards no @object-ui/* module entry point. This workspace declares no @object-ui/*
    dependency in any manifest at all.
  • The two directionorder sort retirements are objectui catching up to a refusal this
    repo already enforces: packages/spec/src/ui/view.zod.ts declares order as the sole
    accepted spelling and already refuses direction by name (aliases: { direction: 'order' }).
  • ui:icon's nameicon rename touches no ObjectStack authorable key: packages/spec
    declares no IconSchema, no type: 'icon' node, and the literal ui:icon appears nowhere
    under packages/.
  • The remaining eight are objectui-side TypeScript, React-prop or hook surfaces with 0 tracked
    files here. The two apparent in-repo hits are prose, never imports: every ActionParamDialog
    mention names the app-shell implementation that survives objectui#5685 (including the
    packages/spec/liveness/action.json evidence row), and the single useIsWorkspaceAdmin
    mention is a comment in packages/plugins/plugin-auth/src/auth-manager.ts.

The pin bump's second half — ADR-0082 D4

Per AGENTS.md the pin move is the declaration-parity ratchet's only trigger, so it was run:

$ pnpm sdui:manifest
✓ wrote 57 public blocks → packages/console/dist/sdui.manifest.json
## Baseline ratchet
✓ no new DECLARATION divergence vs accepted baseline (see the scope note above).

packages/spec/react-declaration-parity.baseline.json is byte-identical before and after
(sha256 79c1f51b…62f15 both times), and the manifest lands in the gitignored dist — so
neither is in this diff.

The container's Playwright browser did not match the revision the pinned objectui expects
(chromium_headless_shell-1194 installed, build 1234 wanted). That is the exact gap
docs/releases-maintenance.md → "If the dispatch container's Playwright browser doesn't match
the revision" records, and its documented scratchpad symlink remedy was applied verbatim —
nothing under /opt/pw-browsers was touched, and PLAYWRIGHT_BROWSERS_PATH was overridden for
that one invocation only. Chromium 141.0.7390.37, as the note predicts.

Gates run locally (round 0, head 02ddae3a5)

Derived from the actual diff with node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack
(8 families), plus the console pair the path derivation cannot reach — Console Pin Gate is a
dorny/paths-filter job keyed on .objectui-sha, not a pull_request: paths: filter, so no
path derivation names it; it was read out of ci.yml and run by hand instead.

gate verdict
check-adr-0087-registration ✓ 1 declared-breaking changeset(s), each carrying an ADR-0087 disposition.
check-changeset-no-major exit 0
check-empty-changeset exit 0
check:changeset-gate-self-tests ✓ 118 + 212 + 116 assertions
check:objectui-changeset ✓ objectui-range --self-test: all checks passed
check:pm-half-states ✓ check-half-states self-test: 1515 cases pass.
release-rehearsal-clone --self-test ✓ self-test passed
check:console-sha ✓ Console dist matches the objectui pin (objectui@9602dc820450).
check:console-injection ✓ the dist carries this tree's copy, and not the published one.
check:nul-bytes OK (scanned 7184 text file(s) … no raw ASCII control bytes)
scripts/pm/check-half-states.mjs exit 3 — NOT MEASURED, not a failure

check-half-states.mjs is a board sweep needing the GitHub API, and this seat's repo-scoped
REST answers 403, so it printed its own "no reading at all" text and exited 3. Its self-test
wiring (check:pm-half-states) is green. Recorded as unmeasured rather than as either colour.

pnpm lint was narrowed, and the narrowing is proven rather than asserted: eslint's own
configuration resolution answers "File ignored because no matching configuration was
supplied"
for both changed files (--format json, 2 files submitted, 0 linted, 0 findings).
The diff adds no TypeScript and edits no eslint config, so no untouched file's verdict can move
under any configuration.

Generated by Claude Code


Patch round 1 — check:objectui-pin-citations (head 39b05bf82)

The first push was red, and it was ours. Type Check · source gates failed on
pnpm --filter @objectstack/spec check:objectui-pin-citations: 8 spec sources carried
read-point records asserting .objectui-sha = 190fbd01d, which this PR moves off. This
is a real consequence of the pin move that the local gate sweep did not name (see the
"gates" note at the end).

TypeScript Type Check was NOT a second red. Read, not assumed — the aggregator's own
OS_NEEDS (job 98827675406) shows one lane failing and three green, and its only error line
is type-check lane 'typecheck-source-gates' concluded 'failure' -- expected 'success'. It is
a pure rollup over four lanes with if: always(), exactly as lint.yml documents it.

Method — re-measured, never sha-replaced

The gate refuses a mechanical fix by design (no gen:, NO_GENERATOR in the check:generated
ledger): rewriting the sha alone would make each record claim the new pin while its anchors
still described the old tree. So every anchor was re-derived from the file at 9602dc820450.

Byte-identity was used as a first cut, never as proof — and that distinction paid out, once,
in the section below.

objectui file across 190fbd01d9602dc820450
containers.tsx byte-identical
useBulkExecutor.ts byte-identical
lazy-icon.tsx, ObjectMetricWidget.tsx, MetricWidget.tsx, MetricCard.tsx byte-identical
ObjectGrid.tsx changed (3762 → 3955 lines)
plugin-dashboard/src/index.tsx changed (351 → 394 lines)
button.tsx changed (objectui#5993)

⭐ A measured instance of the #10274 class — the case for the gate's "do not replace the sha" rule

useBulkExecutor.ts:284-288 was wrong from the day it was written, and the file is
byte-identical across the pin move. Both halves matter:

  • the span stopped one line short of label = 'bulk delete', truncating the second of the two
    else if branches it exists to name (def.operation === 'update' / === 'delete', the claim
    that the data-plane bulk primitive is reachable only by an update/delete bulk def);
  • because the file did not change, every shortcut available would have waved it through: a
    sha-only rewrite would have preserved the truncation behind a fresh-looking sha, and so would
    trusting byte-identity as proof that an unchanged file's anchors are still correct.

It was caught only by re-reading all four cited spans at the new pin instead of inferring them
from identity. That is the gate header's #10274 warning reproduced live, in the exact
configuration it predicts — now a measured instance rather than a cited one. Widened to
284-289.

Per-anchor result — 6 of 8 records repaired

record anchor old → new verdict
api-methods-batch-conformance.test.ts:64 ObjectGrid.tsx 2492-25072586-2601 block byte-identical, shifted by insertions above it
useBulkExecutor.ts 284-288284-289 ⚠️ wrong since written — see the section above
component.test.ts:281 + component.zod.ts:1649 containers.tsx accordion 851-857, :898unchanged re-read at the new pin; the flex items-center gap-1.5 wrapper span and the [{ label, icon?, collapsed?, children }] input both verified verbatim
component.test.ts:366 + component.zod.ts:642 containers.tsx tabs 662-668, :721unchanged re-read; mr-1.5 h-3.5 w-3.5 shrink-0 opacity-70 + aria-hidden inside TabsTrigger, left of the label span, verified verbatim
component.zod.ts:2393 plugin-dashboard/src/index.tsx 161204 file changed and now holds two identical Icon (Lucide name) inputs (:132 metric-card, :204 object-metric); the record's own "on the registered object-metric block" is what disambiguated it
ObjectMetricWidget.tsx :142/:474, MetricWidget.tsx :312-321/:373-382, lazy-icon.tsx:66-80, MetricCard.tsx:83 unchanged all re-read and verified

⛔ 2 records NOT repaired — ruled, tracked as #12968

component.zod.ts:1827 and component.test.ts:2440 (the element:button icon records) still
assert 190fbd01d, so this gate stays red on exactly them. Maintainer ruling, 2026-08-28
(option A):
the repair is packages/spec authorable-surface contract prose and belongs to a
spec-side card, not to a console pin bump and not to a domain:devx seat. It is filed with every
measurement below already recorded, so nothing needs re-deriving there.

objectui#5993 moved the read point. button.tsx no longer carries its own icon normaliser;
it now calls the shared resolveIcon from ../action/resolve-icon — because the duplicated
algorithm silently missed a lucide alias every action:* site received. Measured at the new pin:

  • resolution :44-47:36, and now hops into a different file (resolve-icon.ts:14-24, :30-35)
  • render :69 / :71:57 / :59
  • registration :82-98:70-87
  • button.tsx:14-27, cited as the file-local normaliser, is now imports and the forwardRef opening

The key is still LIVE and the record's verdict still holds. What cannot be fixed by moving
line numbers is the shipped .describe() string, which tells authors the renderer resolves the
icon "using its own PascalCase normaliser and rename map". At 9602dc820450 that clause is
false. Everything else survives — resolveIcon returns null on an unknown name (?? null),
so "an unknown name here renders nothing rather than a fallback glyph" and the LazyIcon
contrast both still hold; only the ownership claim broke.

Gates, re-derived on the repaired diff

The family grew 8 → 33 once packages/spec/src/** entered the diff. All 33 run green on
head 39b05bf82 except the two records above, plus these, added by hand because the derivation
still does not name them:

  • check:objectui-pin-citationsstill not derived, even now that the diff edits the very
    files it scans. It is deliberately unfiltered (lint.yml: "a paths filter on
    packages/spec/** would go dormant on exactly the PR that moves .objectui-sha"
    ), and being
    unfiltered is what makes it invisible to path derivation — a gate built to fire when no path
    predicts it cannot, even in principle, be named by a path predicate. Filed as [finding] an .objectui-sha diff derives NO pin-critical gate — the gates a pin bump most needs are the ones structurally excluded from path derivation, and one of them shipped a red on PR #12955 #12956.
  • check:nul-bytesOK (scanned 7184 text file(s) … no raw ASCII control bytes)
  • @objectstack/spec typecheck → green, including the test layer, so the edited test files compile
  • vitest on both edited test files → 234 passed
  • check-dev-prereqs and check:doc-formula-expressions first reported PREREQUISITE NOT MET
    in this fresh worktree — the NOT-MEASURED class, not a red. A full pnpm build
    (71 tasks, all successful) turned both into real readings: ✓ 67 package build artifacts present and doc-formula exit 0.

The console evidence from round 0 stands unchanged — the pin did not move in this round, and
this round's diff is comment text in packages/spec/src. check:console-sha is not quoted
as a fresh green here: this worktree has no packages/console/dist, where that gate
deliberately prints ℹ No console dist — skipping and exits 0, which is a vacuous pass rather
than a measurement.

All edits in this round are comment text only — verified mechanically: every added line in
the diff is a comment line.

…mation page)

feat(app-shell): packaged actions on/off beside the packaged flows (ADR-0126 §8 item 2) (#6415)

objectui@9602dc820450dda956843c6cfe5b329bcf88c757

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CPrUz21stTFhJRUirdc4yw
Re-derived every cited anchor at the new pin rather than rewriting the sha,
per check-objectui-pin-citations' own instruction.

- ObjectGrid.tsx 2492-2507 -> 2586-2601 (block byte-identical, shifted)
- plugin-dashboard/src/index.tsx 161 -> 204 (object-metric block)
- useBulkExecutor.ts 284-288 -> 284-289 (span was truncated since written)
- containers.tsx tabs 662-668 / :721 and accordion 851-857 / :898 unmoved,
  re-read at the new pin rather than inferred from byte-identity
- MetricWidget / ObjectMetricWidget / MetricCard / lazy-icon anchors unmoved

The two element:button records are deliberately NOT touched: that read point
MOVED (objectui#5993) and its shipped .describe() text is now false. Reported
rather than re-pointed.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CPrUz21stTFhJRUirdc4yw
@github-actions

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 1 package(s): @objectstack/spec, touching 3 documentable anchor(s).

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

  • content/docs/releases/v15.mdx (via PageTabsProps (symbol))

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
  • the SDK route bridge reached 47 of 219 client-bound route-ledger rows — the other 172 have no registrar path: tail to select them, so pages documenting THEIR client methods cannot appear above, on this or any run. Of those 172: 14 are remediable by widening that discovery convention (an in-repo file declares the path; the convention did not scan it); 56 are structural — on a ledger where NOT ONE row is declared in-repo, so no discovery change reaches them at any price; 102 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.

Coarse fallback — 126 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 f4e741bd194f72c880a99d7af2e6a4faae09d63apackageMentionDocs.

Which tree this was computed on

This run read content/docs from ef2a0313fd587d66e6552e4ea40349a24f9a7a6a — the merge of head 39b05bf821af235c8046064c9cd4e08764cecec8 into base f4e741bd194f72c880a99d7af2e6a4faae09d63a, 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 ef2a0313fd587d66e6552e4ea40349a24f9a7a6a && git checkout ef2a0313fd587d66e6552e4ea40349a24f9a7a6a
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin f4e741bd194f72c880a99d7af2e6a4faae09d63a 39b05bf821af235c8046064c9cd4e08764cecec8 && git checkout -B drift-repro f4e741bd194f72c880a99d7af2e6a4faae09d63a && git merge --no-ff 39b05bf821af235c8046064c9cd4e08764cecec8

node scripts/docs-audit/affected-docs.mjs --json f4e741bd194f72c880a99d7af2e6a4faae09d63a

⚠️ 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 f4e741bd194f72c880a99d7af2e6a4faae09d63a → pass the list as
args.docs, on the commit named under Which tree this was computed on.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

2 participants