Repository navigation
chore(objectui): bump the console pin to ab1879721595 (carries objectui f624f278, b0bf413c and ab187972) - #21625
Conversation
…bjectui.sh --no-commit output) Claude-Session: https://claude.ai/code/session_01HRYqpqGcWpJuJkDmbRF75w Co-authored-by: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HRYqpqGcWpJuJkDmbRF75w Co-authored-by: Claude <noreply@anthropic.com>
…kstep at ab1879721595; re-measure more pin citations (wip) Claude-Session: https://claude.ai/code/session_01HRYqpqGcWpJuJkDmbRF75w Co-authored-by: Claude <noreply@anthropic.com>
…9721 (wip) Claude-Session: https://claude.ai/code/session_01HRYqpqGcWpJuJkDmbRF75w Co-authored-by: Claude <noreply@anthropic.com>
…(wip) Claude-Session: https://claude.ai/code/session_01HRYqpqGcWpJuJkDmbRF75w Co-authored-by: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HRYqpqGcWpJuJkDmbRF75w Co-authored-by: Claude <noreply@anthropic.com>
…d.span describe (wip) Claude-Session: https://claude.ai/code/session_01HRYqpqGcWpJuJkDmbRF75w Co-authored-by: Claude <noreply@anthropic.com>
📓 Docs Drift CheckThis PR changes 2 package(s): 2 hand-written doc(s) NAME something this change touched and may need an implementation-accuracy re-verification:
⛔ 5 release-owned page(s) also name something this change touched. These are read-only:
What this run could not see
Coarse fallback — 139 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): Which tree this was computed onThis run read A worktree cut from an older # while this PR is open — GitHub drops the merge commit once it closes
git fetch origin a46cc222b2bb8a65baf6756259de4d63bdb3df2d && git checkout a46cc222b2bb8a65baf6756259de4d63bdb3df2d
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin 5b5e83f446bde0bf6e13db304b9f07f115635704 4fc15b7e67f4d4f25e3886058e3eb507b2947bbc && git checkout -B drift-repro 5b5e83f446bde0bf6e13db304b9f07f115635704 && git merge --no-ff 4fc15b7e67f4d4f25e3886058e3eb507b2947bbc
node scripts/docs-audit/affected-docs.mjs --json 5b5e83f446bde0bf6e13db304b9f07f115635704
|
Contract reviewServed-tier: ① Derived judgmentsInputs: card #21616 (body, claim 5971910197, os-dev-report 5972904218), PR #21625 (body, the 20-file list, net diff
② Semver level
Clause-②: no — right. No ObjectStack published accept set widens and no public surface is added. The spec moves text only. ③ Boundary flags
Deviations:
Not flagged by the dev, raised here: the Implemented-by: VERDICT: FAIL Generated by Claude Code |
…te records and the outcomeMessages liveness row at objectui ab1879721 The console reader for each landed inside 89cad75d5570..ab1879721595 (objectui#11068, objectui#11227, objectui#11344), so the records that said no renderer reads them are rewritten to the measured read at the pin, and the keyboardNavigation describe drops its not-enforced marker. Claude-Session: https://claude.ai/code/session_01HRYqpqGcWpJuJkDmbRF75w Co-authored-by: Claude <noreply@anthropic.com>
…boardNavigation describe Claude-Session: https://claude.ai/code/session_01HRYqpqGcWpJuJkDmbRF75w Co-authored-by: Claude <noreply@anthropic.com>
Contract reviewServed-tier: ① Derived judgmentsInputs.
② Semver level
Clause-②: no — right.
③ Boundary flags
Deviations in the patch-round report:
No blocking item remains. Implemented-by: VERDICT: PASS Generated by Claude Code |
The os-regen driver kept this branch's side of the generated page in the merge with origin/main 5b5e83f, which dropped main's object-metric aggregate and trend rows (3f1bc81). gen:docs on the merged tree puts them back. The page now differs from origin/main only by this branch's keyboardNavigation row. Claude-Session: https://claude.ai/code/session_01HRYqpqGcWpJuJkDmbRF75w Co-authored-by: Claude <noreply@anthropic.com>
Contract reviewServed-tier: ① Derived judgmentsInputs.
This round is a sync, not new work: right.
Spec accept set: right. It does not move.
Re-measured records, each checked against objectui at
Console surface through
ADR-0087 disposition on
Lockstep and manifest records: right.
Not flagged by the dev; non-blocking.
② Semver level
Clause-②: no — right.
③ Boundary flags
Deviations:
The
No blocking item remains. Implemented-by: VERDICT: PASS Generated by Claude Code |
✅ ACCEPT — PR #21625 (#21616), head
|
…/spec/src to the commits that decided them (objectstack-ai#21642) Part of objectstack-ai#20234 Clause-②: no The next stage of the dead-citation sweep under ruling C+D (record `5749154545` on objectstack-ai#19123): the six comment sites the census pointer `5923089344` names, claimed in `5973700515`. Each cited a tracker number that answers 404. Each now cites, in form C, the commit on `main` that decided the rule, and in every case that is the anchor an earlier stage of this card already landed for the same number in a sibling site. Comment text only: no string literal, `.describe()` text, schema, type, export or test changes. ## The rule applied Form C, as triage's first grade (`5856637615`) states it and stages 1 to 11 applied it: "the ADR or ruling record, else the commit sha, with a PR number allowed only beside it as a link", and "Each rewritten line says what the cited object decided … Where nothing answers, keep the sentence's reason in words and drop the citation." Stage 10's ACCEPT (`5902947213`) adds: "Where the number alone carried the meaning, the decision is also said in words." Live numbers stay (stage 9's ACCEPT `5899135835`: "its claims forbid removing a lit citation"). A slash group keeps its live numbers and takes the commit beside them, as stage 5 did for `objectstack-ai#9881/objectstack-ai#9972` in `component.test.ts` (now `the objectstack-ai#9881 / commit 60e0f90 records`). ## What changes (line numbers at base `5b5e83f446`) | site | dead number | now reads | the same anchor already on `main` | |:--|:--|:--|:--| | `data/datasource.zod.ts:701` | `objectstack-ai#9040` in `objectstack-ai#8082/objectstack-ai#8336/objectstack-ai#9040` | `objectstack-ai#8082/objectstack-ai#8336, or the refusal of a credential in mongo's options passthrough (commit 2420641)` | `data/datasource-credential-redaction.ts`, `data/driver/common.zod.ts` (stage 3) | | `data/filter.zod.ts:1067` | `@see` URL of `objectstack-ai#17590` | `@see commit e04a0af (the membership reading, landed with the SQL family)` | `data/filter.zod.ts:979` (stage 3) | | `data/value-roundtrip-conformance.ts:100` | `@see` URL of `objectstack-ai#12380` | `@see commit 4045b95 (the measured boundary set)` | the same file's family table and `v_json` paragraph (stage 3) | | `ui/component.zod.ts:675` | `objectstack-ai#6276` in `objectstack-ai#5611/objectstack-ai#5775/objectstack-ai#6276` | `objectstack-ai#5611 / objectstack-ai#5775 / commit 78f0be8` | `ui/component.zod.ts:71`, `:207`, `:682` (stage 5) | | `ui/component.zod.ts:751` | `objectstack-ai#6276` in `objectstack-ai#5611/objectstack-ai#5775/objectstack-ai#6276` | `objectstack-ai#5611 / objectstack-ai#5775 / commit 78f0be8` | as above | | `ui/component.zod.ts:4555` | `objectstack-ai#9972` in `objectstack-ai#9881/objectstack-ai#9972` | `objectstack-ai#9881 / commit 60e0f90` | `ui/component.zod.ts:2609`, `ui/component.test.ts:407` (stage 5) | The datasource line is the one site whose sentence did not say what the dead number decided, so it now says it in words, from the code: the mongo `options` passthrough refusal is part of the config gate (`credentialFreeMongoOptions` on `MongoConfigSchema.options`). That comment reflows from two lines to three. Every other edit is one line for one line, and each of those sentences already stated its decision in words. ## Evidence **The six are dead, measured with the gate's own instrument.** `node scripts/check-issue-citations.mjs --census --json` (read-only, board enumerated, 195 pages) at base `5b5e83f446` lists exactly these six plus the two literal-read sites stage 6 kept on purpose (`data/api-derivation.ts:163` `[objectstack-ai#6259]`, `identity/identity.zod.ts:230` `objectstack-ai#8715`). Lines match the claim. No seventh dead number in `packages/spec/src`. REST `issues/N`, redirects not followed: `objectstack-ai#9040`, `objectstack-ai#17590`, `objectstack-ai#12380`, `objectstack-ai#6276`, `objectstack-ai#9972` answer 404; the lit controls `objectstack-ai#8082`, `objectstack-ai#8336`, `objectstack-ai#5611`, `objectstack-ai#5775`, `objectstack-ai#9881`, `objectstack-ai#5286`, `objectstack-ai#12624` answer 200. **After, at head `dbacec5f91`:** the same census reads `allocated-but-absent` 119 → 113 repo-wide and 8 → 2 in `packages/spec/src`. Gone: exactly the six. New: none. **Each anchor is on `main` and names its number.** REST `compare/SHA...5b5e83f` answers `ahead`, `behind_by: 0` for all five shas (controls: `5b5e83f446~1` answers `ahead`, `behind_by: 0`; the off-main branch commit `25fb56f1b7` answers `diverged`, `behind_by: 3`). The local `merge-base --is-ancestor` exits 1 for all five on this shallow checkout, which is the shallow false negative, so the REST reading is the one cited. Each commit's own text names the number it replaces: `24206416a` (subject: refuse a credential in the mongo options passthrough at publish, `objectstack-ai#9040`); `e04a0aff2` (its body names `objectstack-ai#17590` as the card it delivers, and its diff wrote the very `@see` line rewritten here); `4045b954d` ("Part of objectstack-ai#12380", with the live 17-value measurement across three dialects); `78f0be872` (subject names `objectstack-ai#6276`); `60e0f900a` (subject names `objectstack-ai#9972`). **Comment-only, proved two ways.** - A parser-driven token comparison (TypeScript parser, leaf tokens off the syntax tree, JSDoc nodes skipped): base and head token streams are identical in all four files (2,231 / 6,169 / 1,098 / 16,019 tokens), with 0 parse diagnostics on either side. Controls, 7 of 7 behave: an identifier edit, a `.describe()` string edit, a template-literal edit and a regex-literal edit each report DIFFERS; a line-comment edit, a JSDoc edit and an `@see`-line edit each report IDENTICAL. - Every added or removed line in the source diff is a comment line: 15 of 15 (+8 / −7). **Generated artifacts.** After a spec build, `check:generated` reports 15 of 15 up to date. No reference page renders any of the six comments (`content/docs/references/` holds neither the old nor the new text). Nothing was regenerated. **Changeset: `@objectstack/spec` patch.** Measured after the build: `datasource.zod.ts`, `filter.zod.ts` and `component.zod.ts` ship verbatim through the package's `files` entry `src/**/*.zod.ts`; in `dist`, the three `component.zod.ts` comments are in 14 `.js` / `.mjs` bundles and the `value-roundtrip-conformance.ts` `@see` is in `dist/data/index.d.ts` and `.d.mts`. The datasource and filter comments reach no `dist` file. Positive control: the `maxVisible` `.describe()` text is in 14 `dist` files. So the change publishes text, and `skip-changeset` does not apply. **Tests and gates, at head `dbacec5f91`.** - `pnpm --filter @objectstack/spec build`: exit 0. Spec `local` vitest: 609 files, 18,057 passed, 1 todo. `pnpm --filter @objectstack/spec typecheck`: exit 0. - `node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack` derived 79 families; `--ran` reconciles 78 run, all exit 0, and 1 NOT MEASURED, 0 unrun. - NOT MEASURED: `check:dual-build-cjs-loads`, reason: it refuses (exit 3) until every publishable package is built, and a full monorepo build was not run locally. Narrowed and declared: the diff is comment-only in `packages/spec`, and of the gate's 106 `require` entries (its own `--list`), spec's 19 all load at head. CI runs the full gate. - Two gates first refused for unbuilt prerequisites (`@objectstack/lint` `check:doc-formula-expressions`, `check:lean-entry-closure`). After building `formula`, `lint` and `objectql` (14 of 14 turbo tasks), both exit 0. **Overlap.** Open PR objectstack-ai#21632 and PR objectstack-ai#21625 touch `ui/component.zod.ts` in other regions. Neither had landed at `origin/main` `36e4647520`, re-fetched before this PR opened, so no merge was taken. A `merge-tree` of this head onto that tip exits 0, and none of the five changed paths is routed to the regeneration merge driver, so the local answer is GitHub's. ## Acceptance notes - `docs/audits/2026-07-unknown-key-strictness-ledger.md:676` still names the `objectstack-ai#5611/objectstack-ai#5775/objectstack-ai#6276` rule. It is outside this stage's file surface and outside the census surface. Carrier: none. - For `objectstack-ai#17590` the commit rung was taken, although `e04a0aff2`'s message names a director-seat ruling record. That matches stage 3's anchor for the same number at `filter.zod.ts:979`, reviewed PASS. - Not governed: no path under `docs/adr/`, `.claude/`, `skills/`, `AGENTS.md` or `CLAUDE.md`. 29 changed lines. --- _Generated by [Claude Code](https://claude.ai/code/session_01T9u38rswFp5Rw8DswRUReJ)_ --------- Co-authored-by: Claude <noreply@anthropic.com>
…eld — the console derives the line-position field from the child object (objectstack-ai#21589) (objectstack-ai#21632) Fixes objectstack-ai#21589 Clause-②: no (narrowing) ## What this does Retires `sortField` from the `object-master-detail-form` detail entry (`ComponentPropsMap['object-master-detail-form'].details[]`). The console reads no authored value for it. At the `.objectui-sha` pin `89cad75d5570` (and unchanged at the current pin `ab1879721595`: `MasterDetailForm.tsx` and `deriveMasterDetail.ts` are byte-identical between the two), `MasterDetailDetailConfig` has no `sortField` member (`plugin-form/src/MasterDetailForm.tsx:83`). The field the line grid stamps with each line's position is the one `deriveDetail` derives from the child object (`deriveMasterDetail.ts:540`), and it reaches the grid as `sort_field` (`:874`). The spec still declared the key, so an authored `sortField` went through `os validate` clean and was then dropped. This executes the direction triage confirmed (`5969870827`), the one recorded on objectstack-ai#21220's landing (`5937457620`) and mirrored on objectstack-ai/objectui#11396 ③: a `retiredKey()` tombstone, one ADR-0087 D2 conversion and one D3 entry, with no staged window because the writer census is zero. There is no objectui edit here: the objectui#11396 mirror follows once a published `@objectstack/spec` carries this. ## The retirement kit - **Tombstone** on the strict detail entry (`packages/spec/src/ui/component.zod.ts`). The refusal is the prescription, and the key's input type is the retired-key mark, so `tsc` refuses it too. The prescription opens with the fully qualified key: `object-master-detail-form` property `details[].sortField`. It ends with the house `os migrate meta --from 17` sentence. - **One declaration of the derived sort-field names.** `INLINE_GRID_SORT_FIELDS` (the same six names in the same order as the renderer's `SORT_FIELD_NAMES`) moves out of `data/inline-grid-columns.ts` into `data/inline-grid-sort-fields.ts`, a module reached only by relative import, like `ui/action-target-aliases.ts`. Exported from `inline-grid-columns.ts`, it would have reached the published API through the `data` barrel. `inline-grid-columns.ts` imports it, and the tombstone's prescription and `record:line_items`' answer print the list from it (`INLINE_GRID_SORT_FIELD_LIST`). `check:api-surface` is unchanged, as expected. - **D2 conversion `object-master-detail-form-detail-sort-field-removed`** (step 18, `retiredFromLoadPath`, `retiredAfter: '17.6.0'`, order 60). It is a lossless delete of `sortField` from each `properties.details[]` entry of an `object-master-detail-form`, scoped by component type and by position. Its fixture covers region, nested-card and slotted positions, an open-namespace control with the same shape, and an entry that is not an object. - **`RETIRED_KEYS_BY_MAJOR[18]`** registers the nested key `ui/ObjectMasterDetailFormProps:details.sortField` (an array member, spelled without its `[]`). It has no `authorable-surface/` line, so checks (b2) and (b3) resolve it against the emitted schema, and `check:authorable-surface` is green on it. - **D3 entry `object-master-detail-form-detail-sort-field-retired`**, plus a `STEP18_RATIONALE` fragment at order 70. - **Texts that became false, changed in this PR:** - the entry docblock: "exactly the twelve keys" becomes eleven plus the tombstone, re-read at the pin, and "the three it adds … and `sortField`" now says the line-position field is derived; - `record:line_items`' guidance for `sortField`, which used to say the key "belongs to an `object-master-detail-form` detail entry" and now says no block takes it; - the generated reference page row (`content/docs/references/ui/component.mdx`); - the carriers test's every-key control (`FULL_DETAIL_ENTRY`, now 11 keys); - two landed step-18 D3 entries. `ui-object-master-detail-form-details-closed` listed `sortField?` among the keys to write, and `ui-record-line-items-props-closed` sent `sortField` to the detail entry. Both entries shipped in 17.6.0's `registry.ts`. Step 18 is still open, so the 17 → 18 upgrade guide will be generated from these texts. Reviewer, please confirm that this correction belongs in this PR. - **Changeset** `@objectstack/spec` `minor`, with a BREAKING banner, the FROM → TO table and the ADR-0087 `registered` disposition. ## Premise checks (measured on origin/main 9a4182a, objectui at the pin 89cad75d5570) - Locations: the key was at `component.zod.ts:5566`, the docblock at `:5539` and the `record:line_items` guidance at `:2201`–`:2202`, as the claim said. - Renderer: `MasterDetailForm.tsx:83` says "⛔ No `sortField` member". The only `sortField` on that path is the derived one (`:372`, `:874`, `:1066`, `:1081`; `deriveMasterDetail.ts:55` and `:540`). A fully configured entry (FK plus every column typed) loads no child schema (`:977`–`:979`), so it stamps no line position. The prescription says this. - Writer census, `git grep -n -w sortField` over `examples apps packages skills content/docs`, excluding `packages/spec/**` and CHANGELOGs: 1 hit, the generated reference page. Same instrument, control `addLabel`: 6 hits, including the showcase project workspace's detail entry. At the objectui pin, the only detail entries that write the key are probes asserting that nothing reads it (`masterDetailDetailsMembers-8071.test.tsx` rows 2c and `:295`/`:304`). No objectui source assigns it through a spec type. - Landing site: `packages/spec` is the producer of the declared key. No other package was involved. ## Evidence All on the final head `f765e8caaf` unless noted. The branch merged `origin/main` three times: at `e367002e11` (which carries the sibling element:text landing `36ad3210d4`), at `5b5e83f446` (which carries objectstack-ai#21622's landing `3f1bc816a2`), and at `15fe567c9c` (which carries objectstack-ai#21625's pin bump `1cbe165bfc` and objectstack-ai#21642's `15fe567c9c`). Readings marked `69f42d393d` predate the second merge. - `@objectstack/spec` local project at `f765e8caaf`: 609 files and 18059 tests passed (1 todo), with no skip. - `@objectstack/spec` repo project at `f765e8caaf`: the three merge-shape and retirement files (`step18-rationale-merge`, `conversions-major18-merge` and `master-detail-detail-sort-field-retirement`) passed 41 tests. The wider repo-project run is a `69f42d393d` reading: 52 of 53 files passed. NOT MEASURED: `scripts/build-schemas-check-mode.test.ts`, which alone exceeds the 590 s foreground cap. `check:authorable-surface`, the gate whose mode it tests, is green at `f765e8caaf`. - `pnpm --filter @objectstack/spec typecheck`: exit 0, including `check:test-typecheck`. The new pin's `@ts-expect-error` is compiled there, so an unused directive would be red. - Consumer packages that author an `object-master-detail-form` `details[]` entry: - `@objectstack/lint` at `f765e8caaf`: `validate-component-props.test.ts` passed 51 tests (including the new advisory pin). At `69f42d393d`, all 119 files and 5621 tests passed, and its typecheck passed; - `@objectstack/example-showcase` at `69f42d393d`: its typecheck passed, and 32 files and 399 tests passed. - `pnpm --filter @objectstack/spec check:generated`: all 15 artifacts are up to date. - Gates: `node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack` derived 114 commands at `f765e8caaf` (the same set as at `a1b0552acd`), and all 114 exited 0 on the first attempt after a full build. `--ran` reconciled them as 114 derived, 114 run, 0 NOT-MEASURED, 0 UNRUN. At `a1b0552acd`, the round report that first quoted the same reading had stale provenance; the seat's note `5974199078` on the card corrects it. - ESLint, as a proven narrowing rather than the repo-wide `pnpm lint`: - Population: `eslint.config.mjs` lints `**/*.{ts,tsx,mts,cts,js,jsx,mjs,cjs}` minus `NEVER_LINTED`. - `--no-inline-config --format json` over the 12 changed lintable files at the final head `f765e8caaf` reported 12 files, 0 errors and 0 warnings (no ignored-file warnings, so all 12 are in the population). An earlier run, before the two D3 entry text edits, read 10 files with the same result. - Invariance: the config never enables type-aware linting (no `parserOptions.project` and no `projectService`), and the diff touches neither the config nor its baselines, so no verdict on an untouched file can move. - Ablations: one-shot runs through `scripts/ablation-replace.mjs`, wrapped in a trap. Each restore is proven by blob == HEAD and an empty `git diff HEAD`. - The tombstone reverted to `z.string().optional()`: 5 of the pin's tombstone rows went red (refusal, list, props-lint row, tombstone-not-strict-arm, tsc channel), and 15 stayed green. - `sortField: 'position'` planted on the showcase workspace's detail entry: the tree-scoped absence walk went red, naming `examples/app-showcase/src/ui/pages/project-workspace.page.ts authors sortField: 'position'`. ## New pins - `packages/spec/src/ui/master-detail-detail-sort-field-retirement.test.ts`, in the repo project because it walks the tree. It covers: - the tombstone: issue `code` `invalid_type`, path `details.0.sortField`, the prescription, and the derived names drawn from the one declaration; - that the props-lint row is the same schema; - the tombstone against the strict-arm control; - the walked shape keeping the key; - the tsc channel; - that the page parse never refuses; - `record:line_items`' answer; - the D2 strip: stored row, built artifact in every position, by-reference control, type and position scoping, idempotence, retired from the load path; - the ledger row and the D3 entry; - a tree-scoped absence walk over the radius `@objectstack/spec` already declares. `check:cross-package-test-inputs` is green, and the test is listed in `vitest.repo-tests.json`. - `packages/lint/src/validate-component-props.test.ts`: a detail-entry `sortField` is a `component-props-invalid` warning at `properties.details.1.sortField`, carrying the prescription. ## Acceptance notes - The D3 entry's `replacement` spells out the six derived names literally. The generator copies entry values into `registry.ts` and keeps no imports, so it cannot read the declaration. The pin asserts that every member of `INLINE_GRID_SORT_FIELDS` appears in it. - Deployed metadata is NOT MEASURED. Stored pages are converted by the D2 strip when they are read, and the props lint reports live sources. - Merge order with this seat's siblings: the element:text variant retirement (`36ad3210d4`) landed first at conversion order 59 and rationale order 68. objectstack-ai#21622 (`3f1bc816a2`) landed next with rationale order 69. This PR takes 60 and 70. All three merges went through `scripts/pm/os-regen-merge.sh`. Each time, the os-regen driver kept this branch's copy of `component.mdx` and dropped main's rows: the variant row, then objectstack-ai#21622's `object-metric` rows, then objectstack-ai#21625's `object-grid` `keyboardNavigation` row. Each time, the page was regenerated from the merged source in its own commit (the last is `f765e8caaf`). Measured by comparing change lines, the head's delta against `main` is this PR's own delta at `a1b0552acd`, file by file; and the head's delta against `a1b0552acd` is `main`'s own delta. objectstack-ai#21625 did not touch the detail entry or its docblock. - CI at `f765e8caaf`: complete and green, 33 success and 2 skipped (`Console Pin Gate` and the opt-in packed-tarball smoke, by their own filters). `Lint & Repo Gates`, red at `a1b0552acd` only because GitHub's issues API answered HTTP 503 in `check-issue-citations`, is success on this head. --------- Co-authored-by: Claude <noreply@anthropic.com>
…ui#11466, objectstack-ai#11574, objectstack-ai#11578, objectstack-ai#11581 and objectstack-ai#11583) (objectstack-ai#21710) Fixes objectstack-ai#21696 Clause-②: no This moves the bundled Console's objectui pin from `ab1879721595` (objectstack-ai#21625) to objectui `main` as of the write time, `2e818d0b51ecdf8fdd9fcbf4b916bcd7fe9a9cf6`, which is past `973fc20f3`. The Console now carries objectui#11574 (the phantom "(empty)" groups fix), objectui#11578, objectui#11581, objectui#11576, objectui#11583 and objectui#11466 (V1 declared node slot). It also carries objectui's own 17.7.0 package release. ⛔ This is not a release act. Version PR objectstack-ai#21352 is untouched, and no tag, publish or Release was made. Whether 17.7.0 ships with this pin is the maintainer's call. ## Range `ab1879721595..2e818d0b51ec` has 22 non-merge commits. `git merge-base --is-ancestor` exits 0 against objectui `origin/main` for `973fc20f3`, and `2e818d0b51ec` was objectui `main` when it was read (`git ls-remote` just before this PR). From the changesets objectui declared over the range: - 17 releasing changesets, 1 release-nothing, and 6 commits that carry no changeset. - 12 of the 18 changesets were already consumed by objectui's release `b493919c7`. Each was read from the commit that added it. - 2 breaking entries, both annotated by the author and both from one commit. The range was listed by measurement, not copied from the card. Exactly one commit subject in the range carries `!`: `git log --format='%h %s' ab187972..2e818d0b5 | grep -E '^[0-9a-f]+ [a-z]+(\([^)]*\))?!:'` gives `83e3f8377 feat(types,react,core,plugin-dashboard)!: … (objectui#11466)`. | objectui landing | commit | note | |---|---|---| | objectui#11466: node slot and `SchemaRenderer`'s `schema` take `DeclaredNode`; the dashboard producers name declared nodes; an envelope's object-metric retires | `83e3f8377` | **declared breaking**, both breaking entries | | objectui#11574: a grouping-field switch paints only the server's groups | `2f54dca53` | smoke below | | objectui#11581 / objectstack-ai#11578 / objectstack-ai#11576: Create View doors share one builder; a refused save is said; chart views bind an ADR-0021 dataset | `b65aa5e65`, `f1c937966`, `d0097af2e` | | | objectui#11583: a refused metadata write on the view, report and draft surfaces is said | `e8c0b9614` | past the card's `973fc20f3` | | objectui#11598: dashboard slot-entry and chart-producer reads compile without `BaseSchema`'s index signature | `2e818d0b5` (the pin itself) | | | objectui#11572 / objectstack-ai#10380: interface and object page relay stored view config | `09036173c`, `068564691` | | | objectui#11588: grid summary footer reads currency/precision from the object field only | `d768c3178` | | | objectui#11216: `object-kanban` declares `grouping` as the spec's `GroupingConfig` | `a7557a7d4` | | | objectui#11573, objectstack-ai#11564: `AnyComponentSchema` / flex child typing | `bdc9049ed`, `b10c68e58` | | | objectui release 17.7.0 | `b493919c7` | removes 2726 consumed `.changeset/*.md` files | ## ADR-0087 disposition of the declared-breaking entries Both entries are `not-required (no-migration-prescription)`. The disposition is in `.changeset/console-2e818d0b51ec.md`, which replaces the script's `adr-0087: TODO` placeholder. | objectui PR | commit | entry | disposition | |---|---|---|---| | objectui#11466 (PR objectui#11512) | `83e3f8377` | A node slot and `SchemaRenderer`'s `schema` prop take `DeclaredNode` | not-required (no-migration-prescription). This is objectui's own TypeScript face (`@object-ui/types` / `@object-ui/react`). No ObjectStack schema declares or references it. | | objectui#11466 (PR objectui#11512) | `83e3f8377` | An `object-metric` node in a dashboard widget's legacy `component` envelope draws the retired-format prompt | not-required (no-migration-prescription). An ObjectStack author cannot write that envelope: `ui/dashboard.zod.ts` refuses a widget's `component` key by name as objectui-internal, and no example authors one. The showcase's `object-metric` page tiles still draw their numbers (smoke below). | `check-adr-0087-registration --base origin/main` gives "1 declared-breaking changeset(s), each carrying an ADR-0087 disposition". `check-changeset-no-major --base origin/main` gives "This diff introduces no `major` bump". ## What changed here - **`.objectui-sha` and `.changeset/console-2e818d0b51ec.md`** were written by `scripts/bump-objectui.sh 2e818d0b51ecdf8fdd9fcbf4b916bcd7fe9a9cf6 --no-commit` with `OBJECTUI_ROOT` set to a read-only clone of objectui. The level was auto-set to `minor`. No `../objectui` sibling exists in this container. - **`scripts/sdui-manifest.record.json`** was re-recorded by `node scripts/gen-sdui-manifest-node.mjs` over the tree that `pnpm objectui:build` built at the pin. **`sdui.manifest.json` is byte-identical**: 107 components, sha256 `0ead67c1111d…` at both pins, so no component input moved. The record moves its pin, its `modulesRoot` and objectui's workspace version (17.6.0 to 17.7.0). - **`packages/sdui-parser/objectui-lockstep.json`** was re-recorded with `pnpm gen:sdui-lockstep` against `OBJECTUI_ROOT=.cache/objectui-2e818d0b51ec`. It records 214 grammar lines (blob `0131f27cf86d`), 25 codes and containment predicate `76c18fb95d1f`. All are unchanged, so no port is owed. objectui's `packages/sdui-parser/src` is byte-identical across the range; only its CHANGELOG and package.json moved. - **The 54 asserting pin citations in `packages/spec/src`** were re-measured at the new pin, not restamped: - Every anchor in each asserting record was resolved against objectui's tree at the old pin and mapped through `git diff -U0 ab187972 2e818d0b5`. - Four cited files changed: - `plugin-dashboard/src/index.tsx` (+13/-1, objectui#11466). Lines were added above the `object-metric` registration, so its start moves `244` to `256` and the icon input moves `269` to `281`. Both lines are byte-identical, still `{ name: 'icon', type: 'string' }`. - `packages/types/src/objectql.ts`. objectui#11216's `grouping` member landed below the cited `limit` member, so `:4720` did not move. - `content/docs/plugins/plugin-kanban.mdx`. A `grouping` row landed below the `limit` row, and the page still teaches `limit: 250`. - `packages/react/src/SchemaRenderer.tsx` (+21/-20, objectui#11466). Only the type import, the `SchemaRendererProps` docblock and the `schema` type changed. The `properties.*` hoist, its strip list and the `createElement` spread did not, so `object-timeline`'s prop channel still carries `data`. - Every other cited file is byte-identical across the hop. - Each record gains a dated 2026-10-04 hop sentence and keeps its `ab1879721` history. - **The six migration entries' corpus counts** were re-taken with `git grep -o -F`. That method first reproduced every `ab1879721` number: 10267 files, `objectstack` 16377, `@objectstack/spec` 6665, `timeout` 1348, `useState` 2476, `TTL` 180, `tenant` 1238, `Span` 491. - The new numbers are 7579 files, 17227, 7134, 1351, 2477, 182, 1317 and 505. The file count drops because objectui's 17.7.0 release removed 2726 consumed changesets. - Every zero is still zero: 98 tokens were checked, the export lists of the three cited spec files plus every named key. The only non-zero tokens are the expected `Span` / `SpanSchema`. The 14 new `Span` hits are `Spanish` prose. - `packages/spec/src/migrations/registry.ts` was regenerated with `gen:migration-registry`. - **`.changeset/objectui-pin-citations-2e818d0b51ec.md`** is a `@objectstack/spec` patch, because the `FormField.span` describe and six migration descriptions name the pin. `content/docs/references/ui/view.mdx` was regenerated by `check:generated --fix`. - **`main` was merged** (`7e0066af7a`) with `scripts/pm/os-regen-merge.sh` in merge commit `a0a35cb30f`, with no conflict hunk. Afterwards: - `check:generated` reports all 15 artifacts current. - main's three new semantic entries (`ui-object-form-fields-names-typed`, `ui-object-gantt-markers-typed`, `ui-object-timeline-mapping-typed`) are present in the regenerated registry. - The pin-citation gate still counts 54 asserting citations. main added historical ones only (108 to 118). No example, test or gate needed adapting, and no code changed outside generated records, citations and changesets. ## Browser smoke: `examples/app-showcase` with the Console built at `2e818d0b51ec` The Console was built by `pnpm objectui:build`. The build log reports: "Console dist matches the objectui pin (objectui@2e818d0b51ec)", "Single-zod canary: exactly one zod version literal {major:4,minor:6,patch:5}" and "Console bundle carries THIS tree's @objectstack/spec, and only it". The server ran `pnpm dev -- --fresh --ui --no-watch -p 41853` (with `OS_PORT=41853`) on its own ephemeral DB with the seeded admin. Headless Chromium (`/opt/pw-browsers/chromium`) drove it, with console messages, page errors and every non-2xx response captured. Only the PIDs this run started were stopped. **Dashboards.** objectui#11466 touches the dashboard producers. There are no page errors and no "retired" prompt on any of the four dashboards. | dashboard | metric tiles (value read in the DOM) | charts drawn | console errors | |---|---|---|---| | Delivery Operations `showcase_ops_dashboard` | Active Projects 2, At-Risk (Red) 1, Awaiting Review 2, Total Budget 1,090,000 | 4 | 404 `/api/v1/usage/storage`, 404 `/favicon.ico` | | Revenue Pulse `showcase_revenue_pulse` | Invoices 7, Invoiced Subtotal 1,920, Accounts Signed 3, Accounts (all time) 14, Paid Rate 42.9% | 4 | 404 `/api/v1/usage/storage` | | Chart Gallery `showcase_chart_gallery` | Total Tasks 10, Avg Progress 47.0, Total Spent 616,000 | 13 | 404 `/api/v1/usage/storage` | | System Overview `system_overview` (setup) | Total Users 3, Active Sessions 3, Login Events 3, Config Changes 0 | 2 | 404 `/api/v1/usage/storage` | The Delivery Operations tiles match the REST data on the same server: - `showcase_project?status=active` returns 2 rows, `?health=red` returns 1, and the budget sum is 1,090,000. - `showcase_task?status=in_review` returns 2 rows. - `showcase_task` has 10 rows, matching the Chart Gallery's Total Tasks. - `showcase_account` has 14 rows, matching Revenue Pulse's all-time count. The `object-metric` page tiles that this repo authors also draw: - My Work shows Open Tasks 8, In Review 2 and At-Risk Projects 1. - Command Center (大屏) shows 2 / 8 / 2 / 1 / 14 / 1.1M. Neither page has a page error. **Grouping-field switch (objectui#11574).** The drive was Tasks list, then Group, then Add group field (it selects Title). The select then switched to Priority, Status and Priority. The painted groups are counted from the DOM, and the server answers are each `POST /api/v1/data/showcase_task/query` with `groupBy`, all 200: | step | painted groups | server rows | "(empty)" groups | stuck "Loading grid…" | |---|---|---|---|---| | Title | 10 (one per task) | 10 | 0 | 0 | | Priority | 4: High 3, Low 1, Medium 4, Urgent 2 | 4 | 0 | 0 | | Status | 5: Backlog 2, Done 2, In Progress 2, In Review 2, To Do 2 | 5 | 0 | 0 | | Priority | 4: High 3, Low 1, Medium 4, Urgent 2 | 4 | 0 | 0 | The same sequence painted 13, 8 and 8 groups (9, 3 and 4 phantom) at `ab1879721595`, as objectstack-ai#21625's acceptance notes recorded. **No phantom "(empty)" groups appear at this pin.** **Console errors across the run.** The only ones are the browser's "Failed to load resource: 404" lines for `/api/v1/usage/storage` and `/favicon.ico`, and the run has 0 page errors. The `usage/storage` 404 was already recorded in objectstack-ai#21625's smoke. ## objectstack-ai#21671 lockstep reading - objectui's `packages/sdui-parser/src/validate.ts` at `2e818d0b5` is byte-identical to `ab1879721595`. - `checkType` (`:450-466`) still grades `type-mismatch` with `severity: arms.includes('enum') ? 'error' : 'warning'`. `checkMemberTypes` (`:407-419`) grades `member-type-mismatch` the same way. - This repo grades both `error` since PR objectstack-ai#21678 (`packages/sdui-parser/src/validate.ts:446`, `:506`). **The gap still stands at this pin.** - This repo's "Known lead" note (`packages/sdui-parser/src/validate.ts:336-340`) names objectui's copy "at the `.objectui-sha` pin" without a sha, so it is still true and needs no update. The bump route regenerates nothing there, and `validate.ts` is not edited. - `check:sdui-lockstep` does not compare severity, so this is a reading, not a gate result. ## Gates and tests (head `a0a35cb30f`) - `node scripts/pm/dispatch-gates.mjs --commands` derived 127 commands from the 21-path diff. That is the same set before and after the merge. - At `378d424915` (pre-merge) and again at `a0a35cb30f`, all 127 exited 0. `--ran` reports "127 derived, 127 run, 0 NOT-MEASURED, 0 UNRUN", with every exit code recorded. - Also exit 0: - `check:objectui-pin-citations --verify-anchors` with objectui at the pin: 54 asserting citations match `2e818d0b5`, and 7 content assertions are verified. - `check:objectui-bump` (20 assertions across 5 cases), `check:sdui-lockstep`, `check-sdui-manifest`, `check:console-sha`, `check:console-injection`, `check:migration-registry`. - `@objectstack/spec check:generated`: all 15 artifacts current after the merge. - `pnpm --filter @objectstack/spec test`: 612 files, 18185 passed, 1 todo. - `pnpm --filter @objectstack/spec typecheck`: exit 0. - `pnpm --filter @objectstack/sdui-parser test`: 225 passed. - `eslint --no-inline-config` on the 15 changed TS files: 0 errors and 0 warnings. The lint population is `**/*.{ts,…}` (`eslint.config.mjs:971`). The config enables no type-aware linting (`:328`), so this diff cannot move a judgment on an untouched file. Repo-wide `pnpm lint` is left to CI. ## Acceptance notes - `ui/component.zod.ts`'s `object-grid` `columns` record (the⚠️ paragraph on `plugin-grid/src/useColumnSummary.ts:558-568`) says, about `ab1879721595`, that the footer summary reads `currency` / `defaultCurrency` / `precision` / `scale` off an authored column. objectui#11588 (`d768c3178`, inside this pin) retires that read. The record is in the historical spelling and stays true of the pin it names, so it is left as is. - Two anchors in records that cite no sha are outside the pin-citation gate's population and were not re-measured: - `ObjectView.tsx:882`, in `ui/view.zod.ts`'s [objectstack-ai#5074] block and two view tests. - `plugin-dashboard/src/index.tsx:204`, in the `ObjectMetricPropsSchema icon liveness` test. - Both already read an unrelated line at `ab1879721595`, and they shift to `:936` and `:214` here. - Writes: no PR assignee or label was written. This dispatch's write budget names neither. --- _Generated by [Claude Code](https://claude.ai/code/session_01VDtqoecgES7ScQYGbFVDRv)_ --------- Co-authored-by: Claude <noreply@anthropic.com>
…ui#11611, objectstack-ai#11614 and objectstack-ai#11619) (objectstack-ai#21800) Fixes objectstack-ai#21772 Clause-②: no This moves the bundled Console's objectui pin from `2e818d0b51ec` (objectstack-ai#21710) to objectui `main` as of the write time, `9dfaca654311cddd81714153c4f82c241d7cdc54`, which is past `c096f03`. The Console now carries objectui#11611 (the `ref:dataset` spec-form widget), objectui#11614 (the grid widget's camelCase keys) and objectui#11619 (the record chrome's picture). Those are the three merges objectstack-ai#21714, objectstack-ai#21768 and objectstack-ai#21765 wait on. ⛔ This is not a release act. Version PR objectstack-ai#21352 is untouched, and no tag, publish or Release was made. The card's "release first" hold is lifted by the maintainer's order recorded in the claim: 「浏览器测试已经在运行,还有很多问题在处理,服务端开发不应该被阻塞」. ## Range - objectui `git ls-remote origin refs/heads/main` read `9dfaca654311cddd81714153c4f82c241d7cdc54` at 2026-10-05T00:51:29Z, just before the bump, and the same sha again before this PR was opened. - `git merge-base --is-ancestor` exits 0 against `9dfaca654311` for all three carried merges: `b508ac50d9` (objectui#11611), `2abec3a96c` (objectui#11614) and `c096f03279` (objectui#11619). The objectui clone is shallow, but exit 0 proves itself there. - `2e818d0b51ec..9dfaca654311` has 17 commits and 0 merges. - objectui declared 24 changesets over the range, and all 24 release. There are 0 release-nothing changesets and 0 commits without a changeset. None declares `major`. Four carry the author's breaking annotation, and the highest declared level is `minor`, so the console changeset is `minor`. These counts come from `scripts/objectui-range.mjs --from 2e818d0b51ec --to 9dfaca654311 --json` and from the bump's own digest. They were measured, not copied from the card. - Four commit subjects carry `!`. `git log --format='%h %s' 2e818d0b5..9dfaca654 | grep -E '^[0-9a-f]+ [a-z]+(\([^)]*\))?!:'` gives `9db9ff3f9`, `8b14aecbd`, `2abec3a96` and `b403bb36f`. | objectui commit | landing | changesets | declared disposition | |---|---|---|---| | `9dfaca654` | objectui#11615: the default `simple` form draws a self-describing inline section entry; `ObjectFormSection.fields` gains the form view's `{ field }` arm | 1, minor, **BREAKING** (for TypeScript readers) | releasing; declared breaking, answered below | | `15f67025b` | objectui#11345: the inline grid's default columns derive through the spec rule `deriveInlineGridColumns` | 1, patch | releasing | | `4c127cdef` | objectui#11613: `record:related_list` stops requiring `columns` | 1, minor | releasing; moves the manifest | | `c096f0327` | objectui#11383 (PR objectui#11619): the record chrome draws the record's picture from the object's `imageField` | 1, minor | releasing; smoke below; unlocks objectstack-ai#21765 | | `6e9090c26` | objectui#11336: an object document's served listViews count as served views | 1, patch | releasing | | `9db9ff3f9` `!` | objectui#11266: a form view's `subforms[].columns` entry is the spec's `InlineGridColumnSchema`, by reference | 1, minor, **BREAKING** | releasing; declared breaking, answered below | | `7c9a6b194` | objectui#11340: the docs portal renders the book resolver's answer | 1, patch | releasing | | `8b14aecbd` `!` | objectui#11608: `PartialSchema` is retired from `@object-ui/types` | 1, minor, **BREAKING** | releasing; declared breaking, answered below | | `2abec3a96` `!` | objectui#11610 (PR objectui#11614): the grid widget's eight field-level keys are camelCase; the snake_case spellings are refused by name | 1, minor, **BREAKING** | releasing; declared breaking, answered below; unlocks objectstack-ai#21768 | | `b403bb36f` `!` | objectui#8347: `BaseSchema` loses its index signature | 1, minor (`Clause-②: yes (narrowing)`, no BREAKING word) | releasing; declared breaking by its `!`, answered below | | `fd060f076` | objectui#11605: bound registrations stop requiring `objectName`, and a node with neither shows a no-object hint | 8, minor | releasing; moves the manifest | | `b508ac50d` | objectui#11601 (PR objectui#11611): the `ref:dataset` spec-form widget, fed by the report inspector's dataset catalog | 1, minor | releasing; unlocks objectstack-ai#21714 | | `d2e859936` | objectui#11002: the console asks `GET /usage/storage` only when the runtime serves `features.storageUsage` | 1, minor | releasing; smoke below | | `b92329c89` | objectui#11591: the Organization flows page copy | 1, patch | releasing | | `902ebab63` | objectui#11569: `record:line_items` stops requiring `childObject` | 1, minor | releasing; moves the manifest | | `278d2444e` | objectui#11546: a node click on a read-only flow canvas opens the inspector read-only | 1, patch | releasing | | `b61c116b2` | objectui#11577: `record:details` read mode keeps a textarea's line breaks | 1, patch | releasing | ## Declared-breaking changes, and how this repo answers each The ADR-0087 disposition is `not-required (no-migration-prescription)`. It replaces the bump's `adr-0087: TODO` placeholder in `.changeset/console-9dfaca654311.md`, and it covers all five entries below. `check-adr-0087-registration --base origin/main` gives "1 declared-breaking changeset(s), each carrying an ADR-0087 disposition". `check-changeset-no-major --base origin/main` gives "This diff introduces no `major` bump". 1. **objectui#11610 / PR objectui#11614 (`2abec3a96`): the grid widget's eight keys.** `min_rows`, `max_rows`, `allow_add`, `allow_delete`, `allow_reorder`, `total_field`, `add_label` and `sort_field` become `minRows` … `sortField`. objectui has no dual read: its zod faces refuse a snake_case key by name, and its `GridField` draws an inline alert instead of the grid. - **This repo, today.** `@objectstack/spec`'s runtime form field (`buildObjectFormRuntimeField`, `packages/spec/src/ui/component.zod.ts`) already refuses the eight snake_case keys by name, with guidance that names objectui#11610. The camelCase keys are not declared there yet. - **The interim, stated plainly.** Between this PR and objectstack-ai#21768, an ObjectStack-authored `grid` form field can spell the keys neither way. Measured on this head's built spec: `object-form` with `customFields: [{ name: 'items', type: 'grid', min_rows: 1 }]` is refused with `unrecognized_keys` at `customFields.0` and the grid-key guidance. The same field with `minRows: 1` is refused with `unrecognized_keys` at `customFields.0`, as an undeclared key. So a `grid` field takes its `columns` and the widget's own defaults. The refusal's prescription says these keys "come in once the widget reads a camelCase spelling". At this pin the widget does, and objectstack-ai#21768 declares the keys and retargets that prescription. - **Nothing here carries the retired spelling.** `git grep` over `examples/` and `packages/` finds no authored snake_case grid key. The only hits are the spec's own refusal list and its pin test, migration prose, and one historical note about objectui's internal master-detail adapter. 2. **objectui#11615 (`9dfaca654`): the `simple` form's inline section entries.** For TypeScript readers of `ObjectFormSection.fields`, the type gains the spec's `FormFieldInput` arm. No code in this repo imports `@object-ui/types`; the only `@object-ui/*` import is `scripts/gen-sdui-manifest-node.mjs` reading `@object-ui/core` from the built tree. The behaviour change is that the default `simple` form now draws an inline `{ name, … }` entry, as the other five form types already did. The showcase's `object-form` nodes are `wizard`, `drawer` and `modal` forms whose sections list field names, so none of them draws differently. 3. **objectui#11266 (`9db9ff3f9`): `subforms[].columns`.** objectui's validator now judges a column by `@objectstack/spec`'s own `InlineGridColumnSchema`. This repo has enforced that closed shape since objectstack-ai#20927. objectui's verdict now matches `os validate`, and the ObjectStack accept set does not move. 4. **objectui#11608 (`8b14aecbd`): `PartialSchema`.** It leaves `@object-ui/types`. Nothing in this repo names it (`git grep PartialSchema`: 0). 5. **objectui#8347 (`b403bb36f`): `BaseSchema` loses its index signature.** This narrows the TypeScript face of objectui's node types, and nothing here compiles against them. objectui's zod faces keep their accept sets for every key except `visibleWhen`. That key widens to the `{ dialect, source }` envelope this repo's own parse writes. ## The three cards this unblocks - **objectstack-ai#21714**: objectui#11601's `ref:dataset` widget (PR objectui#11611, `b508ac50d`) is now in the pinned build, so `report.form.ts`'s joined-block `dataset` row can declare `widget: 'ref:dataset'`. - **objectstack-ai#21768**: objectui#11610's camelCase keys (PR objectui#11614, `2abec3a96`) are now what the pinned widget reads, so the spec's runtime form field can declare them. - **objectstack-ai#21765**: objectui#11383's record picture (PR objectui#11619, `c096f0327`) is now in the pinned build, so `object.imageField`'s liveness row can move to `live`. The smoke below observes that read in the browser. The reader is `packages/components/src/renderers/layout/containers.tsx`, in the `page:header` record chrome. ## What changed here - **`.objectui-sha` and `.changeset/console-9dfaca654311.md`.** `scripts/bump-objectui.sh 9dfaca654311cddd81714153c4f82c241d7cdc54 --no-commit` wrote both, with `OBJECTUI_ROOT` set to the container's objectui clone after `git fetch origin main`. The range walked completely without a deepen, and the level was auto-set to `minor`. - **`sdui.manifest.json` and `scripts/sdui-manifest.record.json`.** `node scripts/gen-sdui-manifest-node.mjs` regenerated them over the tree that `pnpm objectui:build` built at the pin. There are 107 components at both pins, and the sha256 moves from `0ead67c1111d…` to `6f921896ffac…`. **This time the manifest moves**: - Eleven inputs lose `required: true` and gain a description. Nine are `objectName`, on `object-grid`, `list-view`, `object-form`, `embeddable-form`, `object-master-detail-form`, `object-kanban`, `object-metric`, `object-chart` and `object-pivot` (objectui#11605). The other two are `record:related_list` `columns` (objectui#11613) and `record:line_items` `childObject` (objectui#11569). - `object-master-detail-form`'s `fields` description is rewritten for objectui#11615's inline entries. - Where the spec has a `ComponentPropsMap` row, these inputs are already optional there. Measured on the built spec: `object-grid`, `object-form`, `object-kanban`, `object-metric` and `object-master-detail-form` `objectName`, `record:related_list` `columns` and `record:line_items` `childObject`. So the manifest now agrees with the spec rows. The JSX page compile reads the manifest, and it stops refusing a node whose `dataSource` binding names the object. - The record moves its pin and `modulesRoot`. objectui's workspace version stays 17.7.0. - **`packages/sdui-parser/objectui-lockstep.json`.** `pnpm gen:sdui-lockstep` re-recorded it against `OBJECTUI_ROOT=.cache/objectui-9dfaca654311`. It records 214 grammar lines (blob `0131f27cf86d`), 25 codes and containment predicate `76c18fb95d1f`. All are unchanged, and objectui's `packages/sdui-parser` has no diff over the range, so no port is owed. - **The 54 asserting pin citations in `packages/spec/src`.** They were re-measured at the new pin, not restamped: - Each asserting record's anchors were resolved in objectui at `2e818d0b5`, mapped through `git diff -U0 2e818d0b5 9dfaca654`, and re-read at the new pin. Each record gains a dated 2026-10-05 hop sentence and keeps its earlier history. - In every cited file that changed, the cited lines moved with their text byte-identical: - objectui#8347 re-worded docblocks in `ObjectGrid.tsx`, `ObjectTree.tsx`, `ObjectGantt.tsx`, `ObjectCalendar.tsx`, `SchemaRenderer.tsx`, `plugin-view/src/ObjectView.tsx`, `plugin-map/src/index.tsx` and `plugin-gantt/src/index.tsx`. - In `ObjectKanban.tsx`, objectui#8347 added a private `GateBoundKanbanSchema` read type, so its fetch, navigation reads and spread moved +30. - objectui#11605 touched `plugin-kanban/src/index.tsx`, `plugin-dashboard/src/index.tsx` and `ElementDataSourceGate.tsx`. The `object-metric` icon input moved `281` → `299` and is still `{ name: 'icon', type: 'string' }`. - objectui#11619 moved the `page:tabs` and `page:accordion` icon anchors in `containers.tsx` by +3. - objectui#11615, objectui#11266 and objectui#8347 moved `ObjectKanbanSchema.limit`, `ObjectMapConfigSchema` and `LIST_VIEW_LOCAL_OVERRIDES` in `objectql.ts` and `objectql.zod.ts`. - objectui#11605 added `view.noObject` to the `en`, `zh` and `de` locale packs. Their cited `calendar.configRequired` strings did not change or move. - One cited line changed content. `ObjectKanban.tsx:10`, the type import, gained `SortConfig` beside the `ObjectKanbanSchema` the record cites. - Two counts were re-taken by their records' own methods, and both read the same: the `keyboardNavigation` hit lines (15, against the `schema.editable` control's 3) and the `ElementDataSourceGate` occurrences in five `src/index.tsx` shells (0, 3, 3, 3 and 4). - The three quoted anchors in `ui/view.zod.ts`'s map record redded at this pin, and each was re-read and re-pointed: `case 'map':` moved `2299` → `2300`, `ObjectMapConfigSchema` `2370` → `2388`, and `LIST_VIEW_LOCAL_OVERRIDES` `1419` → `1437`. - **The six migration entries' corpus counts** were re-taken with `git grep -o -F`. That method first reproduced every `2e818d0b5` number: 7579 files, `objectstack` 17227, `@objectstack/spec` 7134, `timeout` 1351, `useState` 2477, `TTL` 182, `tenant` 1317 and `Span` 505. - The new numbers are 7632 files, 17313, 7186, 1360, 2477, 182, 1318 and 508. The other controls read `RuntimeConfig` 276 → 293, `resourceLimits` 2 → 2, `window` 4175 → 4193, `period` 238, `interval` 195 and `metrics` 374 → 401. - Every zero is still zero: 98 tokens were checked, the export lists of the three cited spec files plus every named key. The only non-zero tokens are the expected `Span` (508) and `SpanSchema` (57). The three new `Span` hits are `colSpan` in objectui's `object-form-section-field-entry-11615.test.ts`. Both `resourceLimits` hits are still prose in `packages/app-shell`. - `packages/spec/src/migrations/registry.ts` was regenerated with `gen:migration-registry`. - **`.changeset/objectui-pin-citations-9dfaca654311.md`** is a `@objectstack/spec` patch, because the `FormField.span` describe and six migration descriptions name the pin. `content/docs/references/ui/view.mdx` was regenerated by `check:generated --fix`. No example, test or gate needed adapting, and no code changed outside generated records, citations and changesets. ## Console build and canaries `build-console.sh` ran locally under the verify lock, after `turbo run build --filter=@objectstack/client...`, the same two steps the `Console Pin Gate` job runs. Exit 0, 9m02s on a shared four-core box. The build log reports: - "Bundle canary 'import/jobs' present". - "Single-zod canary: exactly one zod version literal {major:4,minor:6,patch:5}". - "Console bundle carries THIS tree's @objectstack/spec, and only it". - "@objectstack/console dist ready (64192 KB) from objectui@9dfaca654311". `check:console-sha` and `check:console-injection` exit 0 against that dist. ## Browser smoke: `examples/app-showcase` with the Console built at `9dfaca654311` The server ran `pnpm dev -- --fresh --ui --no-watch --compile -p 41877` with `OS_PORT=41877`, on its own ephemeral DB with the seeded admin. Headless Chromium (`/opt/pw-browsers/chromium`) drove it, signing in through the console's own login form, with console messages, page errors and every 4xx/5xx response captured. Only the PIDs this run started were stopped. **No showcase object declares `imageField`, so the record picture needs one to exist.** `git grep imageField examples` gives 0 hits. To exercise objectui#11619's read, the smoke made a temporary local edit: - It added `imageField: 'f_image'` to `showcase_field_zoo`, through `node scripts/ablation-replace.mjs --hold`. - It compiled and booted the server. - It restored the file at once with `--restore`. The tool reports the blob back to HEAD's `4130858b8f8b` and `git diff HEAD` empty, and `git status --porcelain` is empty. - After the run, the showcase `dist/` was restored from turbo's cache for the clean source: sha256 `cc1034dd9d23…`, as before the smoke. The stray runtime bundle of the edited compile was deleted. Nothing of the edit is in this diff. A real `sys_file` was uploaded through `/api/v1/storage/upload/presigned` → `PUT` → `/upload/complete` (a 64×64 red PNG) and written to "Specimen — Full"'s `f_image`. | record page | `[data-record-picture]` | image | |---|---|---| | Field Zoo "Specimen — Full" (`f_image` set) | 1, beside the title in the record header, `rounded-md` (an `image` field, not `avatar`) | `src="/api/v1/storage/files/b1f4e384-…"`, `alt=""`, loaded, `naturalWidth` 64 | | Field Zoo "Specimen — Minimal" (`f_image` empty) | 0 | none, as objectui#11619 specifies for an empty value | **Verdict:** at this pin the record header draws the record's picture from the object's `imageField`, drawing the stored file through `/api/v1/storage/files/:id`, and draws nothing when the value is empty. `showcase_task`'s record page is the custom `task-detail` page, which has no `page:header`, so it draws no record chrome to put a picture in. That page was smoked too: it renders its path bar, highlights and sections with 0 page errors. **Console messages across the run:** 0 page errors. The only failed loads are a 401 on `GET /api/v1/auth/get-session` (the pre-login probe) and a 404 for `/favicon.ico`. There is no `/api/v1/usage/storage` 404. objectstack-ai#21625's and objectstack-ai#21710's smokes both recorded one, and objectui#11002 (`d2e859936`) stopped the request on a runtime that does not serve it. ## Gates and tests (head `4b9519ea23`) - `node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands` derived 127 commands from the 22-path diff, and all were run at `4b9519ea23`. `--ran` reports "127 derived, 127 run, 0 NOT-MEASURED, 0 UNRUN", with every exit code recorded. - Two exited 3 (`PREREQUISITE NOT MET`) on the first pass: `check:skill-examples` (no `client-react` dist) and `check:dual-build-cjs-loads` (no dist for 34 packages). - Both exited 0 after `turbo run build --filter=!@objectstack/docs` (71 of 72 tasks were cache hits), and those are the codes recorded. - Also exit 0: - `check:objectui-pin-citations --verify-anchors` with objectui at the pin: 54 asserting citations match `9dfaca654`, and 7 anchor content assertions are verified. - `check:objectui-bump` (20 assertions across 5 cases), `check:sdui-lockstep`, `check-sdui-manifest`, `check:console-sha`, `check:console-injection`, `check:migration-registry`. - `@objectstack/spec check:generated`: all 15 artifacts current after the `--fix`. - `pnpm --filter @objectstack/spec exec vitest run` (both projects, `local` and `repo`): 668 files, 19259 passed, 1 todo. `pnpm --filter @objectstack/spec typecheck`: exit 0. - `@objectstack/sdui-parser` test (14 files, 225 passed) and typecheck: exit 0. - These suites read the regenerated manifest: - `@objectstack/lint` test: 119 files, 5627 passed. It declares `sdui.manifest.json` as a test input. - `@objectstack/metadata-protocol` `src/protocol.runtime-authoring-gate.test.ts`: 70 passed. - `@objectstack/cli` unit tier `src/utils/sdui-manifest.test.ts` and `test/validate-build-gate-parity.test.ts`: 2 files, 79 passed. - `test/jsx-gate-manifest-notice.e2e.test.ts` belongs to neither CLI tier; it runs nightly, so it is NOT MEASURED here and is left to CI. - `eslint --no-inline-config --format json` on the 15 changed TS files: 15 files, 0 errors and 0 warnings. The lint population is `**/*.{ts,tsx,mts,cts,js,jsx,mjs,cjs}` (`eslint.config.mjs:971`). The config enables no type-aware linting (`:327-328`), so this diff cannot move a verdict on an untouched file. Repo-wide `pnpm lint` is left to CI. ## Acceptance notes - `main` moved two commits past this branch's base (objectstack-ai#21783, objectstack-ai#21780). Neither touches a path this diff touches, so no merge was made. The merge queue rebuilds on the current `main`. - Anchors in records that cite no asserting sha are outside the pin-citation gate's population and were not re-measured. Several point into files that changed here: `containers.tsx` anchors in `ui/component.zod.ts` docblocks with no sha, and `component.test.ts`'s `plugin-dashboard/src/index.tsx:204` (the `ObjectMetricPropsSchema icon liveness` test, already reading an unrelated line at `ab1879721595`, as objectstack-ai#21710 noted). - After this pin, the spec's snake_case grid-key prescription ("these come in once the widget reads a camelCase spelling") describes a condition that now holds. objectstack-ai#21768 retargets it when it declares the camelCase keys. It is left as is here, because the pin bump changes no accept set. - Writes: one draft PR through the relay and the report comment. No label, no PR assignee, no ready flag and no auto-merge were written, because this dispatch's write budget names none of them. --- _Generated by [Claude Code](https://claude.ai/code/session_016tKoy8NJa35Yih1FdzrVmn)_ --------- Co-authored-by: Claude <noreply@anthropic.com>
…objectstack-ai#21994) Fixes objectstack-ai#21989 Clause-②: no ## What this is This PR adds the curated release page for 17.7.0, `content/docs/releases/v17/17-7.mdx` (1,402 lines). It was written after the publish: npm `latest` moved on 2026-10-06, and `@objectstack/spec@17.7.0` went out at 12:22:14Z. It also wires the page in: - `content/docs/releases/v17/meta.json`: `17-7` comes ahead of `17-6`. - `content/docs/releases/v17/index.mdx`: the status blockquote, the minors warning, the per-release list and the checklist links now name 17.7.0 as current. This is the same shape objectstack-ai#21362 used for 17.6.0. - `scripts/docs-audit/handwritten-docs.json`: the page joins the docs-accuracy audit scope. - `content/docs/releases/v17/17-6.mdx`: one dated correction (2026-10-06) on the anonymous-endpoints known issue. objectstack-ai#21158 was closed as not planned on 2026-10-04. The page follows the 17.6 page's structure: 1. Highlights. 2. What's new: the counts, and the runtime changes that happen silently. 3. Breaking changes and migration, triaged by door and subject. It includes a coverage table that names the section carrying the migration for every ADR-0087 entry added since 17.6.0 (8 conversions, 41 D3 entries). 4. New capabilities. 5. Notable fixes. Security fixes are described only as classes and doors. 6. New in Console: each objectui declared-breaking change, with this repo's answer. 7. The code that shipped but is not listed. 8. The upgrade checklist. Every line is marked *Not exercised.* ## Sources and counts - The version commit `4e4e881427` (objectstack-ai#21352) consumed 323 changesets. 322 are new. One, `748b240` (objectstack-ai#21270), shipped in 17.6.0 and is listed again; the page explains this in its own section. - 69 CHANGELOGs carry a 17.7.0 section, and 48 of them have entries. Their 444 entries (194 minor, 250 patch) de-duplicate to the 323 changesets. - Two commits landed on `main` after the Version Packages PR's last refresh and before it merged: - `8a399b2b15` (objectstack-ai#21977, for objectstack-ai#21923) - `04e776b39a` (objectstack-ai#21976, for objectstack-ai#21968) Both are ancestors of the version commit (exit 0 for each), so the 17.7.0 packages carry their code. But the version commit did not consume their changesets, so no 17.7.0 CHANGELOG line names them. The release-integrity audit named both in a warning. - objectui: the pin moved five times and ends at `0abd4f9f8769`: - `89cad75d5570` (objectstack-ai#21380) - `ab1879721595` (objectstack-ai#21625) - `2e818d0b51ec` (objectstack-ai#21710) - `9dfaca654311` (objectstack-ai#21800) - `0abd4f9f8769` (objectstack-ai#21827) Across 173 commits, 254 changesets were added and 229 of them release something. 65 are declared breaking, plus one commit marked `!`. The Console table answers each. - `PROTOCOL_VERSION` is still 17.0.0. ## Premise corrections - The dispatch named two pin moves ending at `9dfaca654311`. The tree has five, ending at `0abd4f9f8769` (`8832655`, objectstack-ai#21827). The page covers all five. - One new D3 id contains a word that `check:role-word` refuses on docs pages, and release pages are not in its baseline. The coverage table therefore names that entry by its subject and points at `os migrate meta --from 17`. ## Fact-check A second pass checked every cited SHA, PR number, key name and behavioural claim against the commits, changesets and registry entries. It corrected **31 claims** (commit `e4a6280b46`). Two more corrections came earlier, while drafting: - objectstack-ai#21361 is closed; it is not tracking the issue. - There are seventeen `ui-object-*` members, not eighteen. Mechanical checks on the final page: - All 276 cited SHAs resolve, in objectstack or in an objectui clone carrying the final pin's history. - Each of the 216 distinct sha–PR pairs matches its commit subject. - Every printable new D3 id (40) and all 8 conversions appear on the page. - The MDX for 17-7, 17-6 and index compiles with @mdx-js/mdx 3.1.1 and remark-gfm 4.0.1. After the fact-check, `main` gained `1abfc58` (objectstack-ai#21985), which lands the read half of objectstack-ai#21922. It is not an ancestor of the version commit: the test returned exit 1, and the control commit `753e7a1` returned exit 0. So in 17.7.0, the metadata door's reads still serve a stored row under a code-defined datasource name. Commit `8347e0d172` says so in the datasource migration bullet. ## Independent fact-check and fix round An independent, read-only fact-check of head `8347e0d172` returned **FAIL** with 13 findings (record: objectstack-ai#21989 comment 6018402030): 2 wrong facts (a flow's `get_record` node still reads the stored-metadata tables, in projected form), 1 security line that named the filter shapes and depth threshold evading 17.6.0's refusal, 1 breaking change missing from the Breaking section (`0fc8087`, objectstack-ai#21626), 1 link whose label did not match its target, 4 overstatements, 1 missing security fix (`49524f6`, objectstack-ai#21420), 1 missing rollback caveat on `os secret rewrap --apply`, and 2 minor wording issues. All 13 were re-verified against their sources and applied in `a53c972fa7`; none was refuted. A scan for any other line naming a bypass shape of a fixed issue reduced two more lines to their class (`0728cbf`, `fb69825`). ## Measured on `a53c972fa7` - Derived gates: `node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands` derives 57 commands; all 57 exited 0 (`--ran`: "57 run, 0 NOT-MEASURED (a DERIVED zero)"). The verdicts include: - check-doc-anchors: 458 links resolve. - check-issue-citations: 305 resolve as a PR, 9 resolve, 15 are cross-repo; every citation this change adds resolves. - `check:role-word`, `check:release-notes` and `check:release-page-status`: OK. - check-release-section-coverage: OK, both plain and with `--strict` (10 minors). - The docs-audit scope check and `check:nul-bytes`: OK. - Docs production build: `TURBO_FORCE=true pnpm turbo run build --filter=@objectstack/docs`, run under the verify lock, reports `Tasks: 2 successful, 2 total` and `Cached: 0 cached`. The built `releases/v17/17-7.html` carries the corrected text and none of the removed text. - Mechanical checks: 231 distinct sha–PR pairs, 0 unresolved, 0 subject mismatches; the MDX of 17-7, 17-6 and index compiles. - Not measured locally: the repo-wide lint and the CI-only families. CI owns them. ## Not in this PR - No changeset. The PR touches only docs and a docs-audit list, nothing a package ships (`skip-changeset`). - Nobody has walked the 17.6.0 → 17.7.0 upgrade. The checklist says so on each line. --- _Generated by [Claude Code](https://claude.ai/code/session_016tKoy8NJa35Yih1FdzrVmn)_ --------- Co-authored-by: Claude <noreply@anthropic.com>
Fixes #21616
Clause-②: no
Moves the bundled Console's objectui pin from
89cad75d5570(#21380) to objectuimainat claim time,ab187972159583b595facdcae3c73b50f6f312e9, so the Console carries objectui#11553, objectui#11544 and objectui#11562, and objectui's own move onto@objectstack/*17.6.0. Unblocked by this, once it lands: #12438 (B1's re-run), #21464 (the held object-gridcolumnsmember). #21596's run reads whatever console this pin builds.Range
89cad75d5570..ab1879721595: 65 non-merge commits, 119 changesets added (one no longer present at the tip, read from the commit that added it), 111 releasing (43 declared breaking, all by the author's annotation), 8 release-nothing, 1 commit without a changeset (6903eafbc, a docs example).git merge-base --is-ancestorexits 0 against objectuiorigin/mainfor the old pin and for every commit named below;ab1879721595isorigin/mainat the claim-time read.The landings this bump carries
/studio/~org/automations(PR objectui#11565)f624f278d77eoptionsonly, never a column's (PR objectui#11563)b0bf413cac21columnsmemberrecord:detailsedit mode edits atextareafield in a multi-line textarea, so a save keeps its line breaks (PR objectui#11567)ab1879721595(the pin itself)@objectstack/*17.6.0 and follows its mechanical contract moves (PR objectui#11531)6158e4c93f0bWhat changed here, and why
.objectui-shaand.changeset/console-ab1879721595.md, written byscripts/bump-objectui.sh ab187972159583b595facdcae3c73b50f6f312e9 --no-commit(auto levelminor). The explicit sha is passed because the shared../objectuicheckout sits on another branch. The script'sadr-0087: TODOplaceholder is answerednot-required (no-migration-prescription), in the wording the previous bumps used, naming all 43 declared-breaking entries (26 commits). Each is objectui's own surface: its validators, layout nodes, node-type keys, CLI, designer and drill-report types. Where an entry narrows toward an ObjectStack shape, ObjectStack already declares that shape: the{ condition, style }rule, a dataset-bound dashboard widget,deleteBehavior,percentScaleOf. Measured: none of the 22 retired or narrowed node keys probed is aComponentPropsMaprow (56 rows) or aPageComponentTypemember (31).packages/sdui-parser/objectui-lockstep.json, re-recorded withpnpm gen:sdui-lockstepagainst the build worktree at the pin (OBJECTUI_ROOT=.cache/objectui-ab1879721595; the generator correctly refused the off-pin shared checkout). It reads 214 grammar lines (blob0131f27cf86d), 25 codes and containment predicate76c18fb95d1f, all unchanged, so no port is owed.sdui.manifest.json+scripts/sdui-manifest.record.json, fromnode scripts/gen-sdui-manifest-node.mjsover the treepnpm objectui:buildbuilt at the pin. It has 107 components, none added or removed. Fourteen changed their published inputs:griddropssmColumns/mdColumns/lgColumns/xlColumns, and itscolumnsandgapbecome value sets.stack/flexgapandcontainerpaddingbecome value sets too.page:headerdrops the inertbreadcrumb.object-gridgainsdescription,emptyStateandkeyboardNavigation.object-pivotgainsdrillDown, andrecord:line_itemsgains ten inputs.object-grid/object-kanbanconditionalFormatting,action:button/action:iconsuccessMessage, and thefieldsinput of the three form blocks (object-form,embeddable-form,object-master-detail-form).packages/spec/src(check:objectui-pin-citationsreds on any pin move) were re-measured at the new pin, not restamped. Each anchor was mapped through its cited file's diff and re-read. Block hashes and corpus counts were re-taken with a method that first reproduced every89cad75d5number: the selection block still hashes toc88443302d40…, and the corpus is 10071 files withobjectstack16044 and@objectstack/spec6461 at the old pin, against 10267, 16377 and 6665 here. This regeneratespackages/spec/src/migrations/registry.tsandcontent/docs/references/ui/view.mdx. It adds.changeset/objectui-pin-citations-ab1879721595.md(@objectstack/specpatch), because theFormField.spandescribe and six migration descriptions name the pin.action:*rows. objectui#11344 now forwardsoutcomeMessagesto the runner. Theaction:button/action:iconrows record it as a key the renderer forwards and the row does not declare: it arrives on theaction:barmember path, and objectui leaves the input unpublished until the row declares it. Theaction:group/action:menurows record it riding each member's forward.object-treeparagraph now cites the regenerated manifest record.object-gridkeyboardNavigation. The grid reads the key at this pin (objectui#11068,154075ab1:ObjectGrid.tsx:5458handsschema.keyboardNavigation ?? inlineEditabletodata-table.tsx, which makes the cells one roving Tab stop). So the describe drops[EXPERIMENTAL — not enforced]and its "no renderer reads it" sentence, and states the measured behaviour. The member docblock and the block docblock's [finding(spec):ComponentPropsMap['object-grid'](ObjectGridPropsSchema) declares neitherdescriptionnoremptyState, which objectui'sObjectGridreads once objectui#11130 lands #20694] paragraph record the read and keep thedb11afd4967cmeasurement as history.content/docs/references/ui/component.mdxis regenerated.object-gridemptyState's record called the unresolved locale map "a renderer gap". objectui#11227 (6158e4c93) ends that gap:ObjectGrid.tsx:6468-6469resolvestitle/messageagainst the display locale.ActionSchema.outcomeMessageswasplanned, with an author warning that the console does not show outcome copy yet. The console reader is objectui#11344 (c476be0e0,ActionRunner.composeSuccessMessage), so the row islive, as it prescribed for this commit. This addspackages/spec/liveness/action.jsonand its count shardliveness/state-counts/action.mdto the diff, and thesuccessMessagerow's note records the interpolation.ui/view.zod.tsthat redded:ObjectView.tsx2293->2299,objectql.zod.ts2145->2370(still.strict()) and1160->1419(still withoutmap). No key, default, enum member or export moves.flexgaps 1, 2, 3, 4, 6 and 8 andgridgap 5 with columns 3 and 4, all inside the new sets.*Columnskey or any retired node key (0git grephits).datasetanyway.percentfields declaremax: 100, so objectui#11475's storage-driven scaling reads them as whole percents.is_empty/$emptyon a value provider.Browser verification (
examples/app-showcase, this branch)pnpm dev -- --fresh --ui --no-watch -p 41737ran at87d7c51424, before the merge, with its own ephemeral DB and the seeded admin. The fourmaincommits merged afterwards touch no console asset.check:console-shareportsobjectui@ab1879721595. The run was driven in headless Chromium (/opt/pw-browsers/chromium) with every API response captured.ab1879721595POST /api/v1/automation/showcase_task_completed/clone{ name: 'pinprobe_flow_clone', label: 'Pinprobe flow clone' }, then open/_console/studio/~org/automationsGET /api/v1/meta/flow/pinprobe_flow_clone200,_packageIdnull. The page header reads "Organization flows · Automations". The rail lists "Pinprobe flow clone" and the canvas opens it (?surface=flow:pinprobe_flow_clone, status draft). Studio's home lists "NOT IN A PACKAGE · Organization flows" beside "No writable packages yet"backlog/done/in_progress/in_review/todo, labelled from the object field's options: Backlog, Done, In Progress, In Review, To Do. Each counts 2, matchingPOST /api/v1/data/showcase_task/query(groupBy: ['status'], 5 records). The retired column-optionsread cannot be authored (the strictListColumnSchemarefusesoptions), so there is no pre-fix leg to contrastPATCHa task'snotesto"Call back Monday.\n\nBudget approved, needs legal review.\n", open its record page, double-click Notes, append "Signed off.", SaveTEXTAREAwhose value carries both line breaks. The stored value after the save is"Call back Monday.\n\nBudget approved, needs legal review.\nSigned off."Smoke: the
/_console/homelauncher, Capability Map, Command Center (大屏), the JSX Command Center (grid columns={4} gap={5}), the Delivery Operations dashboard (KPI tiles and charts drawn), Chart Gallery, Component Gallery and Task Board. 0 page errors. Non-2xx responses were only401 /auth/get-sessionbefore sign-in,404 /usage/storageand one404 ?state=draftno-draft probe. Only the PIDs this run started were stopped.Gates and tests run locally, at
4fc15b7e67(sync round),5eadf35375(patch round) andb93b5fec004fc15b7e67is the head after mergingorigin/main5b5e83f446withscripts/pm/os-regen-merge.sh. The merge commit501902fb09had no conflict hunk.component.zod.tsandmigrations/registry.tsauto-merged, and both sides' added and removed lines are intact, compared line for line against each side's own diff. The os-regen driver kept this branch's side ofcontent/docs/references/ui/component.mdx, dropping main's object-metricaggregateandtrendrows (3f1bc816a2).check:generated --fixregenerated it in4fc15b7e67, and it now differs from main only by this PR'skeyboardNavigationrow. The PR's own contribution, its diff againstorigin/main, is the same 25 paths with the same added and removed lines as at5eadf35375.At
4fc15b7e67,dispatch-gates --commandsderived the same 128 commands from the same 25-path diff, and all 128 exited 0.--ranreports 128 derived, 128 run, 0 NOT-MEASURED. These also exited 0:check:objectui-pin-citations --verify-anchors(54 asserting citations matchab1879721; 7 content assertions verified)check:authorable-surface,check:migration-registry(registry.tscurrent: 360 semantic entries, with main'sui-object-metric-aggregate-trend-typed),check:generated(all 15 artifacts current),check:docsandcheck:liveness@objectstack/spectest (609 files, 18057 passed, 1 todo) and typecheckAt
5eadf35375,dispatch-gates --commandsderived 128 commands from the 25-path diff (the 127 below pluscheck:platform-checklist), and all 128 exited 0.--ranreports 128 derived, 128 run, 0 NOT-MEASURED. These also exited 0:check:objectui-pin-citations --verify-anchors(54 asserting citations matchab1879721; 7 content assertions verified)check:generatedandcheck:docs(component.mdxregenerated bycheck:generated --fix)check:liveness(aftergen:liveness-counts)@objectstack/spectest (608 files, 18017 passed, 1 todo) and typecheck@objectstack/lintlint-liveness-properties.test.ts(95 passed)b93b5fec00is the head after mergingorigin/mainf97660cdd6withscripts/pm/os-regen-merge.sh. The regeneratedregistry.tsis byte-identical to the merge's and keeps main's newelement-text-variant-heading-subheading-retiredentry.node scripts/pm/dispatch-gates.mjs --commandsderived 127 commands, the same set before and after the merge. All 127 exited 0 at this head, and the--ranreconciliation reports 127 derived, 127 run, 0 NOT-MEASURED, every exit recorded. On the pre-merge pass at87d7c51424,check:skill-examplesandcheck:dual-build-cjs-loadsfirst exited 3 (PREREQUISITE NOT MET: nodist/) and exited 0 afterpnpm build.check-adr-0087-registration --base origin/main,check-changeset-no-major --base origin/maincheck:console-sha,check:console-injection,check:sdui-lockstep,check-sdui-manifestcheck:objectui-pin-citations --verify-anchors(49 asserting citations matchab1879721; 7 content assertions verified)check:migration-registry,check:objectui-bump@objectstack/spec check:generated(aftercheck:generated --fixregeneratedcontent/docs/references/ui/view.mdx){major:4,minor:6,patch:5}literal) and its spec-injection check.pnpm buildexited 0.pnpm --filter @objectstack/spec test: 608 files, 18017 passed, 1 todo.pnpm --filter @objectstack/sdui-parser test: 218 passed.pnpm --filter @objectstack/spec typecheck: exit 0.eslint --no-inline-configwas run on the 13 changed TS files: 0 errors, 0 warnings. The population is**/*.{ts,…}(eslint.config.mjs:971), and the config enables no type-aware linting (:327-328), so the diff cannot move a judgment on an untouched file. Repo-widepnpm lintis left to CI.Environment: Node 22.22.0 sufficed. At this pin objectui locks
jsdom29.1.1 (engines ^22.13.0), so no newer Node was needed.Acceptance notes
useServerGrouping.tsanduseGroupedData.tsare byte-identical at89cad75d5570andab1879721595, so this hop does not reach them. Not measured in a browser at the old pin.object-kanban'sconditionalFormattingis stillz.unknown()in this spec, while objectui#11522 now declares only the{ condition, style }rule on that block. This is the same typing-by-reference move spec(ui): theComponentPropsMaprows still type renderer-read members asz.unknown()—navigationon object-map / object-gantt / object-tree andconditionalFormattingon object-kanban accept42— the family close-out after #21445 #21464 makes for its object-block members.action:button/action:iconrows inui/component.zod.tsstill do not declareoutcomeMessages, which objectui now forwards. Declaring it is a contract decision, recorded on the rows and not made here.conversions/registry.ts'PAGE_HEADER_COMPONENT_TYPESdocblock still callspage-headerobjectui's legacy alias. objectui retired that node key in this range (ad1785c1d). The conversion itself is unaffected.Generated by Claude Code