Repository navigation
chore(objectui): bump the console pin to 89cad75d5570 (carries objectui 0858267e, 8001068b, 3ae91930 and d0fba91aa) - #21380
Conversation
Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CuUktjSyZWTP2mU4ywPGA6
Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CuUktjSyZWTP2mU4ywPGA6
Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CuUktjSyZWTP2mU4ywPGA6
Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CuUktjSyZWTP2mU4ywPGA6
Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CuUktjSyZWTP2mU4ywPGA6
Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CuUktjSyZWTP2mU4ywPGA6
Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CuUktjSyZWTP2mU4ywPGA6
Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CuUktjSyZWTP2mU4ywPGA6
…on changeset Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CuUktjSyZWTP2mU4ywPGA6
…scribe Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CuUktjSyZWTP2mU4ywPGA6
Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CuUktjSyZWTP2mU4ywPGA6
📓 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 20df9b78ebbc56c5829942c373f79900c2bb7c44 && git checkout 20df9b78ebbc56c5829942c373f79900c2bb7c44
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin 11905a4f8be1c7b47f8b5bea600ce4e60829782a f2449fc18392d5171edec9902afa8122722210cf && git checkout -B drift-repro 11905a4f8be1c7b47f8b5bea600ce4e60829782a && git merge --no-ff f2449fc18392d5171edec9902afa8122722210cf
node scripts/docs-audit/affected-docs.mjs --json 11905a4f8be1c7b47f8b5bea600ce4e60829782a
|
…me honours — maxEntries and reflectionInterval are required once long-term memory is enabled, longTerm.store is retired, and the block is live (objectstack-ai#21413) Part of objectstack-ai#20274 Clause-②: yes (narrowing) ## What this does Ruling of record 5950198150 (director batch objectstack-ai#268 item 4, letter A′, maintainer 「同意」): **the `agent.memory` contract states exactly what the runtime honours.** One PR, as the ruling's execution parameters say: the refinement, the `store` retirement, the row flip, the describes. The claim amendment 5951618837 adds the two agent-form help texts, made after PR objectstack-ai#21398 landed on `main`. - **The contract check.** `checkAgentMemoryContract` in `packages/spec/src/ai/agent.zod.ts` is a refinement on `memory`, because `reflectionInterval` is `longTerm`'s sibling. It raises one `custom` issue at the key's own path in each of three cases, and each message names the key, its path and the remedy: - `longTerm.enabled: true` without `longTerm.maxEntries` is refused at `memory.longTerm.maxEntries`. - `longTerm.enabled: true` without `reflectionInterval` is refused at `memory.reflectionInterval`. This is the most natural declaration, `{ enabled: true, maxEntries: 5 }`, which cloud refused at turn time. - `reflectionInterval` while `longTerm` is absent or not enabled is refused at `memory.reflectionInterval`. - No default is declared for either number. The check runs only on a body the shape already accepted, so an unknown key, a wrong type or the `store` tombstone gets its own complaint and nothing on top of it. - **`longTerm.store` retires as a whole key,** by the `spec-property-retirement` playbook: - **Tombstone.** `retiredKey()` carries the prescription: "the memory store is platform infrastructure, not agent metadata … Delete the key", closing with the house `os migrate meta --from 17` sentence. `tsc` refuses the key as well. - **Aliases.** The `backend` / `storage` / `provider` aliases pointed at `store`. They moved to `guidance` and carry the same answer, because an alias may not target a tombstone (`alias-integrity.test.ts`). - **D2 conversion `agent-memory-long-term-store-removed`.** Step 18, `retiredFromLoadPath`, `retiredAfter` 17.6.0, order 56. It deletes the key from `agents[].memory.longTerm`, losslessly, with one notice per agent. It supplies neither number. The fixture covers `database`, the materialized `vector` default and `redis`, for 3 notices, plus two untouched controls. - **Registration.** `RETIRED_KEYS_BY_MAJOR[18]` gains the nested `ai/Agent:memory.longTerm.store`. The entry file is `18.ai__Agent__memory.longTerm.store.ts`, and the generated region was written by `gen:migration-registry`. - **D3 entry `agent-memory-store-retired-and-limits-required`.** Its `conversionIds` names the D2. It carries the judgement no conversion can make: the two numbers an enabled `longTerm` now requires. Its `STEP18_RATIONALE` fragment is at order 61. - **`acceptRetiredDefaultResidue` is deliberately not adopted** for the old `vector` default. The measured producer census is zero, and the ruling's ② names the prescription as the backstop for the unmeasured tenant population. The replayed D2 heals stored rows and built artifacts. The reasoning is in the retired-key entry file. - **Ledger.** `agent.memory` moves `experimental` → `live`, with `evidenceScope: cross-repo` and `verifiedAt` 2026-10-02. - The evidence is quoted from the `repo:cloud#1` seat's reading 5946891697 of cloud `ef5a4344`: the reader `agent-runtime.ts#compileAgentMemory` (via `AgentRuntime.resolveTurnGuardrails`), the enforcement in `ai-service.ts`, and the store `agent-memory.ts#AgentMemoryStore`. - The note attributes all of it to that reading. No seat in this session read cloud. - **The window, stated in the note.** At `ef5a4344` the reader still reads `store`: it honours `database` only and refuses `vector` and `redis`. Per the ruling, cloud drops `store` in that one reader once this release reaches its pin, and no earlier. - `state-counts/agent.md` was regenerated by `gen:liveness-counts`: live 22 → 23, experimental 2 → 1. - **Describes.** - `memory` drops `[EXPERIMENTAL — not enforced]`, in the `guardrails` / `structuredOutput` wording: enforced by the cloud AI runtime, and the open framework edition does not run agents. - `longTerm`, `enabled`, `maxEntries` and `reflectionInterval` each state what the runtime does with them: the newest N notes are recalled, a note is written every N delivered interactions, and notes beyond N are evicted. - The NOTE comment's "forward-looking" is replaced by what is enforced. - **The agent form.** - The `memory` row's help text no longer names short-term memory, which is refused. It now states what memory does and that both numbers are required once long-term memory is enabled. - The `planning` row's help text names only `maxIterations`. - `pnpm i18n:extract` regenerated the `en` leaves, run against a spec rebuilt from this tree. The `zh-CN`, `ja-JP` and `es-ES` leaves are authored, not copied. - **The published JSON Schema.** A value-conditioned requirement is not in the finite projection list: `dependent-required` is presence-only, and `refinement-projection.ts` says a value rule stays dropped. So the new site is annotated as dropped. `dropped-refinements.baseline.json` gains `memory` under `ai/Agent` and under the four installed-package schemas that embed agents, which is 5 sites (635 → 640). This is the corrected entry the build printed. - **Regenerated:** `content/docs/references/ai/agent.mdx`. - **Changeset:** `.changeset/20274-agent-memory-contract.md`. - The levels are `@objectstack/spec` minor and `@objectstack/platform-objects` patch (for the catalog leaves). - It carries the BREAKING header, the FROM → TO table and the one-line remedy: "declare `maxEntries` and `reflectionInterval` when `longTerm.enabled`; delete `store`". - It declares `Clause-②: yes (narrowing)` and the ADR-0087 marker `registered agent-memory-long-term-store-removed, agent-memory-store-retired-and-limits-required`. The four surface ratchets (`api-surface`, `authorable-surface`, `json-schema.manifest`, `api-surface-signatures`) are byte-identical, as expected for a NESTED key of an inline block: it has no `authorable-surface/` line of its own. `spec-changes.json` and the upgrade guide are unchanged, because step 18 is not yet projected; `PROTOCOL_MAJOR` is 17, the same state as the structured-output precedent. ## Verification (at `39412feb9e`, after merging `origin/main` at `ca0dfb658a`) - `@objectstack/spec` build + `check:generated`: "All 15 generated artifacts are up to date". - `@objectstack/spec` `vitest --project local`: 599 files, 17583 passed, 1 todo. - `@objectstack/spec` `vitest --project repo`: 43 of 49 files, 705 passed. The other 6 are NOT MEASURED; see below. - `@objectstack/spec` `typecheck` (`tsc --noEmit`, the scripts program and the test layer): OK. "52 file(s) / 246 error(s)" is exactly the pinned debt. `tsc --listFiles` over `tsconfig.test.json` lists both `src/ai/agent.test.ts` and `src/ai/agent-memory-store-retirement.test.ts`, and none of the 246 errors is in either file. So the `@ts-expect-error` on `store` is live. - Consumers: - `@objectstack/lint` reads `liveness/agent.json`: `test` 119 files, 5575 passed; `typecheck` OK. - `@objectstack/platform-objects` holds the catalogs: `test` 59 files, 949 passed; `typecheck` OK. - `node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --ran`: "117 derived famil(ies) accounted for — 117 run, 0 NOT-MEASURED (a DERIVED zero — all 117 recorded an exit code and none of them is 3)". Each exit code was written to disk before any pipe. The list includes: - `check:adr-0087-registration`: "1 declared-breaking changeset(s), each carrying an ADR-0087 disposition … [BREAKING+bang+clause-②-narrowing] registered agent-memory-long-term-store-removed, agent-memory-store-retired-and-limits-required"; - `check-changeset-no-major`: "This diff introduces no `major` bump"; - `check:empty-changeset`, `check:liveness`, `check:doc-authoring`, `check:nul-bytes`, `check:migration-registry`, `check:cross-package-test-inputs`, `check:i18n`, `check:i18n-stale-fill` and `check:type-check-debt`, which re-measured in 116.6 s. - On first runs, before the build closures existed, a few gates exited 3 (PREREQUISITE NOT MET). All were re-run green after building the lint, client and CLI closures. - One `check:dts-closure` red was a race with this worktree's own concurrent spec rebuild. It then named three unrelated packages (`organizations`, `plugin-approvals`, `verify`) whose `dist` had no `.d.ts`. They were rebuilt, and it is green. - `check:i18n-coverage` and `check:i18n-walk-parity` also ran green. - **ESLint, as a proven narrowing** (the repo-wide `pnpm lint` belongs to CI): - The run covered the 13 touched `.ts` files with `--no-inline-config --format json`: 13 files linted, 0 errors, 0 warnings. - All 13 are inside the config's population: `ESLint.isPathIgnored` is false for each. - The narrowing cannot have excluded anything. `eslint.config.mjs` enables no type-aware linting (no `parserOptions.project`; its own comment at `:328` says so), so this diff cannot move the verdict on any untouched file. - **Ablation** (committed tree `8965af164d`; `scripts/ablation-replace.mjs`; each mutation proven on disk by anchor count and blob hash, and each restore proven by blob equal to HEAD and an empty `git diff HEAD`). Both test files import `./agent.zod` relatively, so no `dist` rebuild is involved. - **The contract check.** The anchor `const enabled = memory.longTerm?.enabled === true;` was replaced by an early return: 6 failed, 67 passed. The six are the five refusal pins and the D2 lit control. The two acceptance pins stayed green. - A first attempt, whose replacement contained its own anchor, was a no-op. The tool refused it (anchor count 1 → 1), so no test ran. - **The tombstone.** `store: retiredKey(…)` was replaced by the old three-value enum: 5 failed, 68 passed. The five are the every-value refusal, the did-you-mean pin, the tsc/parse pin, the `defineStack` envelope pin and the artifact boot-door pin. - The direction is red in both runs, as expected. **NOT MEASURED** - Six `@objectstack/spec` repo-project files: `publish-smoke-boot-failure`, `publish-smoke-port-collision`, `dist-freshness`, `dist-freshness-adoption`, `build-schemas-check-mode` and `schema-tree-freshness`. Reason: they drive whole builds and exercise build tooling this diff does not touch; the precedent PR saw them cap-killed at the foreground ceiling. They are declared to CI. - `@objectstack/cli` integration tier. Reason: declared to CI; no CLI file is touched. ## Fixture and producer census - **Producers.** Measured at merge base `6d487d2094`, outside `packages/spec`, in `examples/**` and `packages/**`: - `longTerm`: 0 non-test files and 0 test files. `reflectionInterval`: 0 and 0. - The lit control `guardrails` hits 4 non-test files, the four metadata-form catalogs. - So no producer exists in this repo. - Cloud's built-in agents also have none, per the ruling record's own census. Tenant-authored agents are NOT MEASURED. - **objectui**, at the dispatch pin `31971ff1e28f` and at the current pin `89cad75d55` (after PR objectstack-ai#21380): - `longTerm`: 1 file, `packages/app-shell/src/views/metadata-admin/previews/AgentPreview.tsx`, a display-only preview that reads `memory.longTerm.store` through an `as any`. No build break follows. See Acceptance notes. - `reflectionInterval`: 0. The control `AgentSchema` hits 3 files. - **Fixtures that pinned the old acceptance, flipped:** - `packages/spec/src/ai/agent.test.ts` had two. "should accept agent with memory configuration" wrote `store: 'vector'` and expected it back; it now writes both numbers and asserts that no `store` materializes. "should accept all memory store backends" is replaced by acceptance of memory without enabled long-term memory. - `packages/lint/src/lint-liveness-properties.test.ts` had three cases using `agent.memory` as the live `experimental` ledger witness. They were repointed to `tool.outputSchema`: `memory` is no longer experimental, and `tool.outputSchema` is the remaining experimental row with no retirement queued. `agent.lifecycle` has one, the spec half tracked separately. - **New pins.** - `agent.test.ts` gains 8 contract cases. - The new `src/ai/agent-memory-store-retirement.test.ts`, registered in `vitest.repo-tests.json`, holds 14 cases: the tombstone at every door, the D2 conversion, the registration, and the tree-scoped absence walk. - The walk covers the five roots `@objectstack/spec#test:repo` already declares in `scripts/cross-package-test-inputs.mjs`. Its matcher judges a `longTerm` block that writes `store` / `backend` / `storage` / `provider`, has an anti-vacuity case, and excludes the conversions fixture, release notes and gitignored output. - **Other docs.** `content/docs/**` other than the regenerated reference page: 0 hits. ## Acceptance notes - **Published skill text that is now false (`skills/**`, Tier H, not edited here).** `skills/objectstack-ai/SKILL.md:311-313` says "`memory` is declared only — no runtime reads it". No `skills/**` text names `longTerm` or `store`. Carrier: the skills seat that took the `guardrails` half of the same sentence. - **objectui `AgentPreview.tsx:205-216`** renders `short.maxMessages` (retired by ADR-0013 D3) and `long.store` (retired here). Both now render nothing. It is display-only and read through `as any`, so the Console Pin Gate is unaffected. No carrier is named. - **The release number in the prescriptions.** They say "removed in @objectstack/spec 17.7.0", which assumes the next release is a minor (the label is 17.6.0, published). That is the same assumption the structured-output prescriptions make. - **`dropped-refinements.baseline.json` `measured.refinementSitesThatDidProject`** reads 369, while this tree's build prints 436. That counter was stale before this PR, and only `droppedRefinementSites` was moved (+5). No carrier is named. - **The liveness README's `agent` row** still says "autonomy tier experimental". After this flip, `lifecycle` is the only experimental agent row, and its retirement is queued. The precedent flips left the row as written, and so does this one. --- _Generated by [Claude Code](https://claude.ai/code/session_01YDt3PzwfrkuFzUBF89WPmM)_ --------- Co-authored-by: Claude <noreply@anthropic.com>
…ui f624f278, b0bf413c and ab187972) (objectstack-ai#21625) Fixes objectstack-ai#21616 Clause-②: no Moves the bundled Console's objectui pin from `89cad75d5570` (objectstack-ai#21380) to objectui `main` at 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: objectstack-ai#12438 (B1's re-run), objectstack-ai#21464 (the held object-grid `columns` member). objectstack-ai#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-ancestor` exits 0 against objectui `origin/main` for the old pin and for every commit named below; `ab1879721595` is `origin/main` at the claim-time read. ## The landings this bump carries | objectui landing | merge commit | who waits here | |---|---|---| | objectui#11553 — Studio reaches the organization's package-less flows at `/studio/~org/automations` (PR objectui#11565) | `f624f278d77e` | objectstack-ai#12438 B1's re-run | | objectui#11544 — a grouped grid's group headers read the object field's `options` only, never a column's (PR objectui#11563) | `b0bf413cac21` | objectstack-ai#21464's held object-grid `columns` member | | objectui#11562 — `record:details` edit mode edits a `textarea` field in a multi-line textarea, so a save keeps its line breaks (PR objectui#11567) | `ab1879721595` (the pin itself) | the console this repo ships | | objectui#11438 — objectui resolves `@objectstack/*` 17.6.0 and follows its mechanical contract moves (PR objectui#11531) | `6158e4c93f0b` | none; carried by the range | ## What changed here, and why - `.objectui-sha` and `.changeset/console-ab1879721595.md`, written by `scripts/bump-objectui.sh ab187972159583b595facdcae3c73b50f6f312e9 --no-commit` (auto level `minor`). The explicit sha is passed because the shared `../objectui` checkout sits on another branch. The script's `adr-0087: TODO` placeholder is answered `not-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 a `ComponentPropsMap` row (56 rows) or a `PageComponentType` member (31). - `packages/sdui-parser/objectui-lockstep.json`, re-recorded with `pnpm gen:sdui-lockstep` against 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 (blob `0131f27cf86d`), 25 codes and containment predicate `76c18fb95d1f`, all unchanged, so no port is owed. - `sdui.manifest.json` + `scripts/sdui-manifest.record.json`, from `node scripts/gen-sdui-manifest-node.mjs` over the tree `pnpm objectui:build` built at the pin. It has 107 components, none added or removed. Fourteen changed their published inputs: - `grid` drops `smColumns` / `mdColumns` / `lgColumns` / `xlColumns`, and its `columns` and `gap` become value sets. `stack` / `flex` `gap` and `container` `padding` become value sets too. - `page:header` drops the inert `breadcrumb`. - `object-grid` gains `description`, `emptyState` and `keyboardNavigation`. `object-pivot` gains `drillDown`, and `record:line_items` gains ten inputs. - Descriptions changed on `object-grid` / `object-kanban` `conditionalFormatting`, `action:button` / `action:icon` `successMessage`, and the `fields` input of the three form blocks (`object-form`, `embeddable-form`, `object-master-detail-form`). - The 49 asserting pin citations in `packages/spec/src` (`check:objectui-pin-citations` reds 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 every `89cad75d5` number: the selection block still hashes to `c88443302d40…`, and the corpus is 10071 files with `objectstack` 16044 and `@objectstack/spec` 6461 at the old pin, against 10267, 16377 and 6665 here. This regenerates `packages/spec/src/migrations/registry.ts` and `content/docs/references/ui/view.mdx`. It adds `.changeset/objectui-pin-citations-ab1879721595.md` (`@objectstack/spec` patch), because the `FormField.span` describe and six migration descriptions name the pin. - Records whose claim moved, not only their numbers: - The four `action:*` rows. objectui#11344 now forwards `outcomeMessages` to the runner. The `action:button` / `action:icon` rows record it as a key the renderer forwards and the row does not declare: it arrives on the `action:bar` member path, and objectui leaves the input unpublished until the row declares it. The `action:group` / `action:menu` rows record it riding each member's forward. - The `object-tree` paragraph now cites the regenerated manifest record. - Patch round, after the contract review: `object-grid` `keyboardNavigation`. The grid reads the key at this pin (objectui#11068, `154075ab1`: `ObjectGrid.tsx:5458` hands `schema.keyboardNavigation ?? inlineEditable` to `data-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 [objectstack-ai#20694] paragraph record the read and keep the `db11afd4967c` measurement as history. `content/docs/references/ui/component.mdx` is regenerated. - The same sweep found two more records of the same class: - `object-grid` `emptyState`'s record called the unresolved locale map "a renderer gap". objectui#11227 (`6158e4c93`) ends that gap: `ObjectGrid.tsx:6468-6469` resolves `title` / `message` against the display locale. - `ActionSchema.outcomeMessages` was `planned`, 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 is `live`, as it prescribed for this commit. This adds `packages/spec/liveness/action.json` and its count shard `liveness/state-counts/action.md` to the diff, and the `successMessage` row's note records the interpolation. - Every other anchor held on a byte-identical file or moved with its cited text byte-identical. That includes the three quoted-first-line anchors in `ui/view.zod.ts` that redded: `ObjectView.tsx` `2293` -> `2299`, `objectql.zod.ts` `2145` -> `2370` (still `.strict()`) and `1160` -> `1419` (still without `map`). No key, default, enum member or export moves. - No example, test or gate needed adapting for the breaking entries or for objectui#11438's behaviour changes. Measured on this branch: - The showcase JSX pages use `flex` gaps 1, 2, 3, 4, 6 and 8 and `grid` gap 5 with columns 3 and 4, all inside the new sets. - No example names a retired grid `*Columns` key or any retired node key (0 `git grep` hits). - No example dashboard widget uses the dataset-less inline-object form, which the spec refuses without `dataset` anyway. - All three example `percent` fields declare `max: 100`, so objectui#11475's storage-driven scaling reads them as whole percents. - No example uses `is_empty` / `$empty` on a value provider. ## Browser verification (`examples/app-showcase`, this branch) `pnpm dev -- --fresh --ui --no-watch -p 41737` ran at `87d7c51424`, before the merge, with its own ephemeral DB and the seeded admin. The four `main` commits merged afterwards touch no console asset. `check:console-sha` reports `objectui@ab1879721595`. The run was driven in headless Chromium (`/opt/pw-browsers/chromium`) with every API response captured. | carried fix | drive | result at `ab1879721595` | |---|---|---| | objectui#11553 | `POST /api/v1/automation/showcase_task_completed/clone` `{ name: 'pinprobe_flow_clone', label: 'Pinprobe flow clone' }`, then open `/_console/studio/~org/automations` | clone **200**. `GET /api/v1/meta/flow/pinprobe_flow_clone` **200**, `_packageId` null. 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" | | objectui#11544 | Tasks list → Group → Add group field → Status | five headers, keyed `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, matching `POST /api/v1/data/showcase_task/query` (`groupBy: ['status']`, 5 records). The retired column-`options` read cannot be authored (the strict `ListColumnSchema` refuses `options`), so there is no pre-fix leg to contrast | | objectui#11562 | `PATCH` a task's `notes` to `"Call back Monday.\n\nBudget approved, needs legal review.\n"`, open its record page, double-click Notes, append "Signed off.", Save | the editor is a `TEXTAREA` whose 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/home` launcher, 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 only `401 /auth/get-session` before sign-in, `404 /usage/storage` and one `404 ?state=draft` no-draft probe. Only the PIDs this run started were stopped. ## Gates and tests run locally, at `4fc15b7e67` (sync round), `5eadf35375` (patch round) and `b93b5fec00` `4fc15b7e67` is the head after merging `origin/main` `5b5e83f446` with `scripts/pm/os-regen-merge.sh`. The merge commit `501902fb09` had no conflict hunk. `component.zod.ts` and `migrations/registry.ts` auto-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 of `content/docs/references/ui/component.mdx`, dropping main's object-metric `aggregate` and `trend` rows (`3f1bc816a2`). `check:generated --fix` regenerated it in `4fc15b7e67`, and it now differs from main only by this PR's `keyboardNavigation` row. The PR's own contribution, its diff against `origin/main`, is the same 25 paths with the same added and removed lines as at `5eadf35375`. At `4fc15b7e67`, `dispatch-gates --commands` derived the same 128 commands from the same 25-path diff, and all 128 exited 0. `--ran` reports 128 derived, 128 run, 0 NOT-MEASURED. These also exited 0: - `check:objectui-pin-citations --verify-anchors` (54 asserting citations match `ab1879721`; 7 content assertions verified) - `check:authorable-surface`, `check:migration-registry` (`registry.ts` current: 360 semantic entries, with main's `ui-object-metric-aggregate-trend-typed`), `check:generated` (all 15 artifacts current), `check:docs` and `check:liveness` - `@objectstack/spec` test (609 files, 18057 passed, 1 todo) and typecheck - eslint on the 15 changed TS files (0 errors, 0 warnings) At `5eadf35375`, `dispatch-gates --commands` derived 128 commands from the 25-path diff (the 127 below plus `check:platform-checklist`), and all 128 exited 0. `--ran` reports 128 derived, 128 run, 0 NOT-MEASURED. These also exited 0: - `check:objectui-pin-citations --verify-anchors` (54 asserting citations match `ab1879721`; 7 content assertions verified) - `check:generated` and `check:docs` (`component.mdx` regenerated by `check:generated --fix`) - `check:liveness` (after `gen:liveness-counts`) - `@objectstack/spec` test (608 files, 18017 passed, 1 todo) and typecheck - `@objectstack/lint` `lint-liveness-properties.test.ts` (95 passed) - eslint on the 15 changed TS files (0 errors, 0 warnings) `b93b5fec00` is the head after merging `origin/main` `f97660cdd6` with `scripts/pm/os-regen-merge.sh`. The regenerated `registry.ts` is byte-identical to the merge's and keeps main's new `element-text-variant-heading-subheading-retired` entry. - `node scripts/pm/dispatch-gates.mjs --commands` derived 127 commands, the same set before and after the merge. All 127 exited 0 at this head, and the `--ran` reconciliation reports 127 derived, 127 run, 0 NOT-MEASURED, every exit recorded. On the pre-merge pass at `87d7c51424`, `check:skill-examples` and `check:dual-build-cjs-loads` first exited 3 (PREREQUISITE NOT MET: no `dist/`) and exited 0 after `pnpm build`. - Named by the dispatch, all exit 0: - `check-adr-0087-registration --base origin/main`, `check-changeset-no-major --base origin/main` - `check:console-sha`, `check:console-injection`, `check:sdui-lockstep`, `check-sdui-manifest` - `check:objectui-pin-citations --verify-anchors` (49 asserting citations match `ab1879721`; 7 content assertions verified) - `check:migration-registry`, `check:objectui-bump` - `@objectstack/spec check:generated` (after `check:generated --fix` regenerated `content/docs/references/ui/view.mdx`) - The console build passed its single-zod canary (one `{major:4,minor:6,patch:5}` literal) and its spec-injection check. - `pnpm build` exited 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-config` was 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-wide `pnpm lint` is left to CI. Environment: Node 22.22.0 sufficed. At this pin objectui locks `jsdom` 29.1.1 (`engines ^22.13.0`), so no newer Node was needed. ## Acceptance notes - objectui, measured in the browser run above, not touched here: switching the list's Group field leaves stale "(empty)" groups stuck on "Loading grid…". The server answers only the real groups. Title (10 groups), then Priority, showed 13 groups (9 phantom + 4); then Status 8 (3 + 5); then Priority 8 (4 + 4). `useServerGrouping.ts` and `useGroupedData.ts` are byte-identical at `89cad75d5570` and `ab1879721595`, so this hop does not reach them. Not measured in a browser at the old pin. - `object-kanban`'s `conditionalFormatting` is still `z.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 objectstack-ai#21464 makes for its object-block members. - The `action:button` / `action:icon` rows in `ui/component.zod.ts` still do not declare `outcomeMessages`, which objectui now forwards. Declaring it is a contract decision, recorded on the rows and not made here. - `conversions/registry.ts`' `PAGE_HEADER_COMPONENT_TYPES` docblock still calls `page-header` objectui's legacy alias. objectui retired that node key in this range (`ad1785c1d`). The conversion itself is unaffected. --- _Generated by [Claude Code](https://claude.ai/code/session_01HRYqpqGcWpJuJkDmbRF75w)_ --------- 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>
Clause-②: no
Moves the bundled Console's objectui pin from
31971ff1e28f(the pin 17.6.0 shipped) to current objectuimain,89cad75d55702cc4f267bead5bf267de575d5842, so the Console carries the four fixes 17.6.0's release verification found missing (#21330, objectstack-ai/hotcrm#1982, and the "Known console issues" list incontent/docs/releases/v17/17-6.mdx).Range
31971ff1e28f..89cad75d5570: 64 non-merge commits, 74 releasing changesets (16 declared breaking), 14 release-nothing, 6 commits without a changeset.git merge-base --is-ancestor <c> origin/mainexits 0 in an objectui clone for the old pin and for each fix commit below;89cad75d5570isorigin/main.Breaking entries:
990a2d616(objectui retires its baretree/viewnode-type keys and the bare field-widget fallbacks),063832222(@object-ui/plugin-designerTypeScript face),f9c8c4e45(two@object-ui/coreexports),063119f2b(an unevaluable gate is a fault),138ad4554/6aa029b63(authoredflex/object-gridtake thepropertiesbag),a1a44d621(pagerefusesmaxWidth/padding),e100589f3(appmobileNavModerefused),1a88ce22f(dashboard widgetchartConfig.*structure keys).The four fixes this bump carries
31971ff1e28ffield: '', refused422 measures.0.field0858267e(objectui#11402)externalblock, refused400since #211338001068b(objectui#11368)requiresback, so republishing an html page that gained a plugin component is refused422 page-requires-disagrees-with-source3ae91930(objectui#11357)d0fba91aaWhat changed here, and why
.objectui-shaand.changeset/console-89cad75d5570.md, written byscripts/bump-objectui.sh --no-commit(auto levelminor). The script'sadr-0087: TODOplaceholder is answerednot-required (no-migration-prescription), in the wording the previous two bumps used, naming all 16 upstream breaking entries: each is objectui's own surface, or (chartConfig.*) mirrors keysui/dashboard.zod.tsalready retired and tombstoned.packages/sdui-parser/objectui-lockstep.json, re-recorded withpnpm gen:sdui-lockstep: 214 grammar lines, 25 codes, containment predicate76c18fb95d1f, all unchanged; no port owed.sdui.manifest.json+scripts/sdui-manifest.record.json, fromnode scripts/gen-sdui-manifest-node.mjsover the treepnpm objectui:buildbuilt at the pin: 107 components, none added or removed;object-kanban,object-calendar,object-gantt,object-timeline,object-mapandobject-treechanged their published inputs (objectui#11168 slices 3–5, objectui#11293).packages/spec/src(check:objectui-pin-citationsturns red on any pin move), re-measured at the new pin: anchors mapped through each cited file's diff and re-read, block hashes and corpus counts re-taken with a method that first reproduced every31971ff1enumber. This regeneratespackages/spec/src/migrations/registry.tsandcontent/docs/references/ui/view.mdx, and adds.changeset/objectui-pin-citations-89cad75d5570.md(@objectstack/specpatch, since theFormField.spandescribe and six migration descriptions name the pin). Records whose claims moved, not only their numbers:object-map's declared-blockstyleprecedence (mapStylenow first, objectui#11168 slice 3; thegetMapConfigreturn quote is rewritten);object-tree'snavigationread andObjectTreeSchemamirror now carry the row's keys uncast, and objectui's record-source table drops the retired baretree/view:treekeys (objectui#10859 batch 8); twoobject-timelineanchors that were already one line off at31971ff1eare corrected. No key, default, enum member or export moves.type: 'tree'view and field are spec-level types, not the retired bare node keys. The browser run below covers both.Browser verification (
examples/app-showcase, this branch)pnpm dev -- --fresh --ui --no-watch -p 41733(own ephemeral DB, seeded admin),check:console-sha=objectui@89cad75d5570, driven in headless Chromium (/opt/pw-browsers) with every request captured. A writable packagecom.acme.pinprobewith one objectpinprobe_itemwas created throughPOST /api/v1/packagesand the metadata API for the authoring checks.89cad75d5570field: ''pin_ds→ Add measure → namerow_count, Aggregatecount, Field left blank → ⌘SPUT /meta/dataset/pin_ds?mode=draftcarries{"name":"row_count","aggregate":"count"}(nofieldkey) → 200; publish → 200; the served measure has nofieldexternalblock:memory:, Schema mode External, then Validate only, no credentialPOST /api/v1/datasourcescarries"external":{}→ 201 for bothexternalandvalidate-onlyrequiresecho<box>only (servedrequires: ["ui"]); metadata editor Source → add<object-kanban objectName="pinprobe_item" groupBy="status" />→ ⌘S → publishrequires→ 200; publish → 200; the server stampsrequires: ["ui","plugin-kanban"]/_console/apps/com.objectstack.account/component/approvals/inbox,localStorage['objectui-locale']='zh-CN', full reload<html lang="zh-CN">,i18n-locale-zh-*.jsfetched (before the switch: "Approvals Inbox")Smoke: sign-in lands on the
/_console/homelauncher; the showcase JSX home page (Capability Map,<flex>/<box>) renders; theshowcase_tasklist grid; a task record page; theshowcase_ops_dashboarddashboard with KPIs and charts; the Studio landing and the writable package's object surface. 0 page errors. Non-2xx responses were only401 /auth/get-sessionbefore sign-in,404 /usage/storage,501 /ai/usage(no AI provider) and404 ?state=draftno-draft probes. Only the PIDs this run started were stopped.Gates and tests run locally
check-adr-0087-registration --base origin/main,check:console-sha,check:console-injection,check:sdui-lockstep,check-sdui-manifest,check:objectui-pin-citations(49 matching;--verify-anchors: 7 anchor content assertions verified at89cad75d5),check:migration-registry,check:objectui-bump,@objectstack/spec check:generated(aftergen:docs) — all exit 0.pnpm buildexit 0. The console build passed its single-zod canary and spec-injection check.pnpm --filter @objectstack/spec test: 598 files, 17512 passed, 1 todo.pnpm --filter @objectstack/sdui-parser test: 218 passed.pnpm --filter @objectstack/spec typecheck: exit 0.Environment, not a product change: objectui's
jsdomneeds Node>= 22.22.2; the container has 22.22.0, so a Node 22.23.3 was prepended toPATHfor the console build and the dev boot.Generated by Claude Code