Skip to content

fix(spec): a dataset dimension's nullLabel is live; move the objectui pin past its reader - #25437

Merged
objectstack-fleet[bot] merged 2 commits into
mainfrom
claude/project-thread-to6m3a
Oct 23, 2026
Merged

objectstack-fleet[bot] merged 2 commits into
mainfrom
claude/project-thread-to6m3a

Conversation

@objectstack-fleet

Copy link
Copy Markdown
Contributor

Requested by Tesla · project thread

Fixes #25330

Clause-②: no
Metadata-protocol: none

This PR is landing 3 of 3 for the label half of #25330, following ruling A (6358843349, approved by the maintainer). The earlier landings:

This PR moves the console pin past that reader, then flips the liveness row once the reader is at the pin. The seat approved the order as option (a): bump the pin and flip the row in one PR.

What changes

  • The objectui pin. .objectui-sha moves from 5fef032b1ada to 1d178e06ac5e by scripts/bump-objectui.sh. It brings five objectui commits in. Their six changesets are digested into .changeset/console-1d178e06ac5e.md as an @objectstack/console patch.
    • Then pnpm objectui:build ran, and node scripts/gen-sdui-manifest-node.mjs re-recorded scripts/sdui-manifest.record.json. The manifest itself is byte-identical: 107 components.
    • pnpm gen:sdui-lockstep re-recorded packages/sdui-parser/objectui-lockstep.json with the objectui checkout parked on the pin. objectui's parser region did not change.
  • Liveness. liveness/dataset.json moves dimensions[].nullLabel from planned to live. It was measured at the pin, following the shape of runAction (Flip the nav runAction liveness-ledger row to live — the objectui half landed, and it needs TWO evidence pointers, not one #10068) and print (spec liveness: the console pin hop to objectui 1f23d5b070fa makes page.print and translation.flows.successMessage / errorMessage read planned while the shipped console applies them (family card; the parentDataSource leg is #23585) #23710).
    • evidence (cross-repo, objectui @1d178e06ac5e): packages/plugin-dashboard/src/DatasetWidget.tsx#declaredNullCategoryLabel. It reads the category dimension's fields[].nullLabel, and the widget passes it as the chart's nullCategoryLabel, ahead of chart.nullCategory.
    • producer: packages/services/service-analytics/src/analytics-service.ts#enrichResultColumns. It resolves the dimension's nullLabel at the request locale and writes it onto the column descriptor, which is the second input the reader depends on.
    • authorWarn and authorHint go with the flip, so os lint stops telling an author that nothing draws the bucket. The state-counts/dataset.md shard is regenerated: 27 live / 1 planned becomes 28 live / 0 planned.
  • The dataset form. The Dimensions repeater offers a Null Label column (.meta({ title: 'Null Label' })).
    • The form ↔ Zod reconciliation ledger had excluded the key with the reason "planned, not yet rendered". The ledger's own rule says such a row "holds only while the verdict does … delete it and decide the offer then". So the row is deleted, and the key is offered beside label, which has the same I18nLabel type.
    • The new row label enters the metadata-form catalogs: en is copied from the source, and zh-CN 空值标签, ja-JP 空値ラベル and es-ES Etiqueta de nulos are authored. That way no locale echoes English, and the dataset panel's zero-echo pin holds.
    • The two catalog census pins count the new label: 677 → 678 translated leaves and 37 → 38 dataset-form leaves.
  • Changeset. An @objectstack/spec patch (.changeset/25330-null-label-live.md). Clause-②: no: the schema, accept set, served body and error codes are unchanged. Only the ledger verdict, its advisory and a form column for an already-accepted key move.

Pins and ablation

  • metadata-form-zod-reconciliation.test.ts now requires the form to offer dimensions.nullLabel, because no ledger row excuses it any more.
  • Ablation (scripts/ablation-replace.mjs, under the verify lock): I replaced the form's { field: 'nullLabel', label: 'Null Label' } with a comment (anchor ×1 → ×0). The ablated blob is exactly main's c0701a46. The reconciliation test goes 1 failed / 75 passed: "dataset.dimensions: accepted by the Zod but unauthorable in the form — offer it, or add a ledger entry: expected [ 'nullLabel' ] to deeply equal []". After restoring, the blob equals HEAD and git diff HEAD is empty.
  • check:liveness resolves the new producer symbol anchor in this repo and attributes the objectui evidence. nullLabel no longer opts into authorWarn.

Verification

All at head 78302ab05f, base f0fdd45bbc.

  • node scripts/pm/dispatch-gates.mjs --commands: 106 derived families, all 106 run with exit 0, reconciled with --ran (0 UNRUN, 0 NOT MEASURED). Three were red on the first pass and are fixed in the second commit:
    • check:liveness: the count shard was stale.
    • check:i18n: the new form label was missing from the platform-objects bundles.
    • check:sdui-lockstep: the record still named the old pin.
  • pnpm --filter @objectstack/platform-objects test: 93 files, 1341 tests passed. Its typecheck exits 0.
  • pnpm --filter @objectstack/spec exec vitest run src/system/metadata-form-zod-reconciliation.test.ts src/ui: 153 files, 5673 tests passed.
  • pnpm --filter @objectstack/spec check:generated: all 14 artifacts up to date.
  • node scripts/check-sdui-manifest.mjs: intact and recorded at the live pin 1d178e06ac5e. pnpm check:console-sha: exit 0.

Acceptance notes

  • Other renderers. objectui's DatasetReportRenderer and ObjectChart still draw the null bucket under chart.nullCategory only. The flat table draws a null dimension value as —. These are recorded in the row's note and are not carried here.
  • Pivot. The objectui reader applies a declared name on a two-dimension pivot only when both dimensions declare the same one, because buildChartSeries takes one null label for both arms. This is recorded in the row's evidence.

🤖 Generated with Claude Code

https://claude.ai/code/session_016qAuAwFXMw94v5vFqTVcw2

… pin past its reader

The console now draws a dataset chart's null bucket under the name its
dimension declares. objectstack#25402 carries the name on the answer's
column descriptor as `fields[].nullLabel`, and objectui#13354 reads it, so:

- `.objectui-sha` moves 5fef032b1ada -> 1d178e06ac5e (objectui#13354's
  merge), with the regenerated SDUI manifest record and the console
  changeset the bump writes.
- `liveness/dataset.json` re-grades `dimensions[].nullLabel` planned ->
  live, measured at that pin: evidence objectui
  DatasetWidget#declaredNullCategoryLabel, producer service-analytics
  enrichResultColumns. `authorWarn` goes with the flip.
- The dataset form's Dimensions repeater offers the Null Label column, and
  the reconciliation ledger's planned-only omit row for it is deleted, as
  that ledger prescribes once the verdict moves.

Claude-Session: https://claude.ai/code/session_016qAuAwFXMw94v5vFqTVcw2
Co-authored-by: Claude <noreply@anthropic.com>
- packages/sdui-parser/objectui-lockstep.json re-recorded at the new pin
  1d178e06ac5e (check:sdui-lockstep).
- liveness/state-counts/dataset.md regenerated: dataset is 28 live, 0
  planned.
- The dataset form's new Null Label row label enters the metadata-form
  catalogs (en from the source; zh-CN 空值标签, ja-JP 空値ラベル, es-ES
  Etiqueta de nulos), and the two catalog census pins count it: 677 -> 678
  translated leaves, 37 -> 38 dataset-form leaves.

Claude-Session: https://claude.ai/code/session_016qAuAwFXMw94v5vFqTVcw2
Co-authored-by: Claude <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 3 package(s): @objectstack/platform-objects, @objectstack/sdui-parser, @objectstack/spec, touching 2 documentable anchor(s). ⚠️ 3 changed file(s) yielded no anchor (packages/sdui-parser/objectui-lockstep.json, packages/spec/liveness/dataset.json, packages/spec/liveness/state-counts/dataset.md), so the pages documenting them are NOT COVERED by this run — this is not a clean bill of health for those files.

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

  • content/docs/api/data-api.mdx (via nullLabel (literal, a string literal in sections))
What this run could not see
  • 3 changed file(s) yielded no anchor (packages/sdui-parser/objectui-lockstep.json, packages/spec/liveness/dataset.json, packages/spec/liveness/state-counts/dataset.md) — pages documenting those are invisible to this run
  • 2 name(s) were too generic to anchor anything (single lowercase words)
  • 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 — 144 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 77392e901cce58316e803144971f2741ef049fc4 → packageMentionDocs.

Which tree this was computed on

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

node scripts/docs-audit/affected-docs.mjs --json 77392e901cce58316e803144971f2741ef049fc4

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

Copy link
Copy Markdown
Collaborator

Overlap note, no objection: #25430 (pin move for the 18.1.0 cut) also moves .objectui-sha.

Neither pin greens main's current Console Pin Gate red (#25438). plugin-view fails against the spec after #24947, and the same failure reproduces at 1d178e06ac5e's successor 4603b8c4ec99. The fix is objectui#13370. #25430 will move the pin to objectui main past objectui#13370.

If this PR lands first, #25430 merges it and moves on from 1d178e06ac5e. If #25430 lands first, this PR's pin hunk would move backwards, and should take #25430's pin instead.


Generated by Claude Code

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

席位核对

ACCEPT · domain:engine seat 1 · os-tesla · session_014Hse9cj2i4o5UAVrd21NKr · 2026-10-23T14:06Z · head 78302ab05 · #25330 (Fixes, landing 3 of 3, after objectstack#25402 and objectui#13354)


Generated by Claude Code

Copy link
Copy Markdown
Collaborator

Follow-up to the overlap note: the other .objectui-sha move is now #25455, to 6fb31dcc9954 (objectui main after objectui#13370, which greens the Console Pin Gate red in #25438). 1d178e06ac5e is inside that range. If #25455 lands first, this PR keeps 6fb31dcc9954 on rebase and drops its own pin move, changeset and record changes; the liveness flip still reads the reader at that pin.


Generated by Claude Code

Merged via the queue into main with commit 1000cc7 Oct 23, 2026
43 checks passed
@objectstack-fleet
objectstack-fleet Bot deleted the claude/project-thread-to6m3a branch October 23, 2026 14:44
marchtian pushed a commit that referenced this pull request Oct 23, 2026
…8e06ac5e → 6fb31dcc9954 (#25430)

#25437 landed first with its own pin move and console changeset over
5fef032b1ada..1d178e06ac5e. The conflicted .objectui-sha and both records
take main's side, then scripts/bump-objectui.sh re-runs to 6fb31dcc9954,
so this branch's console changeset now covers 1d178e06ac5e..6fb31dcc9954
only, and the SDUI manifest record and lockstep record are regenerated
from a fresh console build at the pin.

Claude-Session: https://claude.ai/code/session_01CBtjEGZifSHGenaRcRBKYb
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

Projects

None yet

3 participants