Skip to content

chore(objectui): bump the console pin to 2e818d0b51ec (carries objectui#11466, #11574, #11578, #11581 and #11583) - #21710

Merged
objectstack-fleet[bot] merged 7 commits into
mainfrom
claude/issue-21696-objectui-pin-bump
Oct 4, 2026
Merged

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

Conversation

@objectstack-fleet

Copy link
Copy Markdown
Contributor

Fixes #21696
Clause-②: no

This moves the bundled Console's objectui pin from ab1879721595 (#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 #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 / #11578 / #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 / #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, #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 #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 #21625's smoke.

#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 fix(sdui-parser): an html page literal of the wrong type is a compile error, not a warning #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:
  • Writes: no PR assignee or label was written. This dispatch's write budget names neither.

Generated by Claude Code

claude added 7 commits October 4, 2026 07:53
Written by scripts/bump-objectui.sh 2e818d0b51ecdf8fdd9fcbf4b916bcd7fe9a9cf6 --no-commit.

Claude-Session: https://claude.ai/code/session_01VDtqoecgES7ScQYGbFVDRv
Co-authored-by: Claude <noreply@anthropic.com>
…tations at 2e818d0b5

Claude-Session: https://claude.ai/code/session_01VDtqoecgES7ScQYGbFVDRv
Co-authored-by: Claude <noreply@anthropic.com>
Every asserting citation moves to the new pin with its anchors re-mapped
through the ab1879721..2e818d0b5 diff; the object-metric icon input and
registration move by 12 in plugin-dashboard/src/index.tsx, every other
cited file is byte-identical or changed away from the cited lines.

Claude-Session: https://claude.ai/code/session_01VDtqoecgES7ScQYGbFVDRv
Co-authored-by: Claude <noreply@anthropic.com>
…step at 2e818d0b51ec; spec citation changeset

Claude-Session: https://claude.ai/code/session_01VDtqoecgES7ScQYGbFVDRv
Co-authored-by: Claude <noreply@anthropic.com>
…console changeset

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

github-actions Bot commented Oct 4, 2026

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

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

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

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

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

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

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

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

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

Which tree this was computed on

This run read content/docs from e9af031ca5f1edcc7f4e1a9c04b3f105731824a9 — the merge of head a0a35cb30f9451294889f99df9d931b9d4d66d3b into base 7e0066af7a8e05709dc60096c69bc85e299d0331, which is what actions/checkout gives a pull_request run. Not the PR head.

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

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

node scripts/docs-audit/affected-docs.mjs --json 7e0066af7a8e05709dc60096c69bc85e299d0331

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

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

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

Contract review

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

① Changesets — TRUE

  • Breaking-commit list, measured myself on a full, non-shallow, non-partial clone of objectui: git log --format='%h %s' ab187972..2e818d0b5 | grep -E '^[0-9a-f]+ [a-z]+(\([^)]*\))?!:' yields exactly one commit, 83e3f8377 (objectui#11466). git rev-list --count --no-merges gives 22, as the PR says. Of the 18 .changeset/*.md files ADDED in the range, exactly two carry a breaking annotation, both added by 83e3f8377: 11466-envelope-object-metric-retired.md and 11466-node-slot-union.md. The 14 other changeset files 83e3f8377 touched are +2-line edits to files that already existed at ab187972 (already dispositioned on chore(objectui): bump the console pin to ab1879721595 (carries objectui f624f278, b0bf413c and ab187972) #21625), so they are correctly outside this bump's count.
  • .changeset/console-2e818d0b51ec.md (@objectstack/console: minor) carries exactly one <!-- adr-0087: not-required (no-migration-prescription) ... --> marker that names both entries of 83e3f8377 and gives a reason for each. Every declared-breaking commit in the range is dispositioned.
  • Claim (1) true: DeclaredNode is a @object-ui/types export (SchemaRenderer.tsx diff at the pin: schema: DeclaredNode | string | null | undefined); no packages/spec schema references it.
  • Claim (2) true: packages/spec/src/ui/dashboard.zod.ts:1078-1081 declares DashboardWidgetSchema as strictObject({... guidanceSets: WIDGET_GUIDANCE_SETS }), and WIDGET_GUIDANCE_SETS (:184-190, set QUARANTINED_WIDGET_KEYS) names 'component' with the prescription "objectui-internal renderer capabilities, not part of the author-facing dashboard spec". A widget component key is refused by name, so the retired envelope form is not ObjectStack-authorable.
  • .changeset/objectui-pin-citations-2e818d0b51ec.md (@objectstack/spec: patch, Clause-②: no): correct level. The only shipped text that moves is the FormField.span describe string and six migration-entry description strings (pin sha + corpus counts); no key, default, enum member or export moves (verified in ②), so patch is right and matches chore(objectui): bump the console pin to ab1879721595 (carries objectui f624f278, b0bf413c and ab187972) #21625's @objectstack/spec patch.
  • Precedent form: both files are the same shape as chore(objectui): bump the console pin to ab1879721595 (carries objectui f624f278, b0bf413c and ab187972) #21625's console-ab1879721595.md / objectui-pin-citations-ab1879721595.md (script-derived entry list, "declared nowhere" section, single adr-0087 HTML-comment marker with the same opening paragraph, objectui range: trailer; spec patch with Clause-②: no). Like chore(objectui): bump the console pin to ab1879721595 (carries objectui f624f278, b0bf413c and ab187972) #21625's, the console changeset carries no Clause-② line of its own; check-adr-0087-registration.mjs:639 reads the arm from the PR body (readClause2Line(parsed.body)), and the PR body carries Clause-②: no.

② Review faces — TRUE, all citation/comment/describe-text only

  • packages/spec/src/ui/component.zod.ts (+125/-39), action.zod.ts, dataset.zod.ts, view.zod.ts, kernel/functional-completeness.ts, six migrations/entries/semantic/18.*.ts and the regenerated migrations/registry.ts: every hunk is inside a /** ... */ or // comment, or inside a .describe(...) / description: string literal. No Zod builder, key, default, enum member, export or import changes (read the full diff).
  • KEY CHECK — corpus counts are genuine, not a sparse-checkout artifact. On a full clone (git rev-parse --is-shallow-repository = false, no partialclonefilter): git ls-tree -r --name-only <sha> | wc -l = 10267 at ab187972 and 7579 at 2e818d0b5. The drop is .changeset/: 2728 tracked files at ab187972, 8 at 2e818d0b5 (objectui release b493919c7 consumed them). Lit-control spot-checks with git grep -o -F <term> <sha> | wc -l reproduce every recorded number at both pins: objectstack 16377 → 17227, @objectstack/spec 6665 → 7134, timeout 1348 → 1351, useState 2476 → 2477, TTL 180 → 182, tenant 1238 → 1317, Span 491 → 505, SpanSchema 56 → 57. Hit counts rise while file count falls because the release folded the changesets into the package CHANGELOGs. PASS.
  • Anchor spot-checks at 2e818d0b5 (all hold): packages/plugin-dashboard/src/index.tsx:256 = 'object-metric', and :281 = { name: 'icon', type: 'string' }, (were :244 / :269 at ab187972, byte-identical text; file +14/-1); packages/types/src/objectql.ts:4720 = limit?: number; at both pins; content/docs/plugins/plugin-kanban.mdx still carries the limit rows (:174, :189); plugin-grid/src/ObjectGrid.tsx:5458 = keyboardNavigation: schema.keyboardNavigation ?? inlineEditable, and the file is byte-identical across the hop; core/src/actions/ActionRunner.ts:1497 = composeSuccessMessage(...), byte-identical; SchemaRenderer.tsx changes only its type import, docblock and schema prop type, as the record says. functional-completeness.ts cites ObjectCalendar.tsx / ObjectGantt.tsx / ObjectTimeline.tsx / ObjectMap.tsx / ListView.tsx as byte-identical; consistent with the measured 4-file change set of the hop.
  • content/docs/references/ui/view.mdx: the two changed rows are the FormField.span row in the two generated tables that share FormFieldBaseSchema, and the cell text equals the new view.zod.ts:3319 describe string verbatim (ab1879721595 → 2e818d0b51ec, nothing else). Two mdx occurrences from one describe is the generator's shape, not a hand edit; the dev report says check:generated --fix wrote it and check:generated reports all 15 artifacts current.

③ Scope — TRUE, no ride-along, no release act

  • 21 files: .objectui-sha, two changesets, scripts/sdui-manifest.record.json, packages/sdui-parser/objectui-lockstep.json, view.mdx, and 15 packages/spec/src files that are citation-only (three of them tests, comment-only as well). Nothing outside what the bump's gates require. sdui.manifest.json is not in the diff (sha256 0ead67c1... and 107 components unchanged in the record), consistent with no component input moving.
  • Lockstep / manifest consistency: packages/sdui-parser/src at objectui is byte-identical across ab187972..2e818d0b5 (git diff --quiet), so the lockstep record moving only rev, revDate (2026-10-04T07:05:00+00:00 = the commit date of 2e818d0b5) and recordedAgainstPin, with blob/codes/predicate untouched, is correct. The manifest record's objectuiWorkspaceVersion 17.6.0 → 17.7.0 matches objectui package.json at the pin. objectui validate.ts:418 / :465 still grade type-mismatch / member-type-mismatch by arms.includes('enum'), so the finding(sdui-parser): the html tier's type-mismatch stays a warning for a string literal handed to an object-typed input — os build passes and the tile draws no number #21671 reading in the PR body is accurate.
  • Pin target: 2e818d0b5 is objectui#11598, 973fc20f3 is its ancestor (card's floor satisfied). No objectui write, no tag, publish, Release or Version Packages action anywhere in the PR; version PR chore: version packages #21352 untouched.
  • Head check-runs at review time: 14 completed/success (incl. Check Changeset, Governed Surface Queue Guard, Spec property liveness, Build Docs, Type Check · source gates), 1 skipped (opt-in tarball smoke), 17 still in_progress (Test Core 1-6, Build Core, Console Pin Gate, Lint & Repo Gates, Type Check · consumer/debt/workspace, Dogfood 1-3 + CLI, Temporal Conformance); 0 failures. Landing still waits on those going green.

Implemented-by: claude/issue-21696-objectui-pin-bump
Reviewed-by: session_01VDtqoecgES7ScQYGbFVDRv

VERDICT: PASS


Generated by Claude Code

@objectstack-fleet
objectstack-fleet Bot marked this pull request as ready for review October 4, 2026 09:09
@objectstack-fleet
objectstack-fleet Bot enabled auto-merge October 4, 2026 09:09
@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

Console Pin Gate is red on this head (a0a35cb30f, job 111402467290), and the cause is not this PR's. Seat domain:devx#1, read at 2026-10-04T09:22Z.


Generated by Claude Code

@objectstack-fleet
objectstack-fleet Bot added this pull request to the merge queue Oct 4, 2026
@github-actions

github-actions Bot commented Oct 4, 2026

Copy link
Copy Markdown
Contributor

⛔ merge queue 构建失败 — 先分诊,再决定要不要重排

队列构建 37192871034 红了。队列跑的是全量套件(PR 侧 CI 只跑 affected 子集),
所以失败的测试可能在本 PR 没碰过的包里 —— 那不是重排能修的。每次盲目重排都会让排在后面的所有 PR 重建一轮。

失败的 job(日志抽取,best effort):

  • Console Pin Gate — 失败步骤: Build the Console SPA at the pinned objectui SHA

    ✗ Built console still carries the PUBLISHED @objectstack/spec.
    

↳ 失败原因 是判读的关键:超时(Test timed out in … / Hook timed out in …)多半是负载/时序,不是本 PR 的回归;
断言(AssertionError: …)才指向真实的行为改变。两者的 FAIL 行长得一模一样,只有这一行能区分。

⚠️ 断言这一侧有一类例外,判据是断言在测什么,不是它是不是 AssertionError。 断言的对象是产品行为(一个值、一个形状、一次拒收)⇒ 照上面读:真实的行为改变,去查,⛔ 不要重排掉;
断言的对象是这次实验自身的有效性前提(跑完的耗时、负载下的先后、任何只在时间预算内才成立的条件)⇒ 它跟超时是同一类,同样对负载敏感,重排一次是合法的判别手段。
识别是机械的:断言的消息或它比较的值本身点名了一段时长、一个时间戳、一个耗时计数。实测过的一对 —— AssertionError: SecurityPlugin.init() ran: expected false to be true 测的是产品行为(真回归);
AssertionError: this run took over a second, so second-precision stamps could have differed too: expected 1006 to be less than 1000 测的是实验前提:它守护的那条不变式当时是绿的,同一个 head 原样重排一次即成功。
穿着 AssertionError 外衣的时间测量,仍然是时间测量。(⛔ 这只改「怎么读一次红」,不改「哪些测试可以重排」——后者由别处管。)

跨 PR 相同签名(24h,按失败测试文件聚合):

  • ⚠️ 本次没有可用的聚合签名(日志里没有能解析出测试文件名的 FAIL 行)—— 这不是「没有同签名的其他 PR」,是这一轮没测到。跨 PR 聚合本次不可用,请手工比对其他 PR 的同类评论。
  • ⚠️ 24h 评论账本没读完(超过 5 页仍未读到窗口尽头),所以上面的「不同 PR 数」是下界,不是全量。

历史信号:

  • 本 PR 过去 24h 无队列失败记录(首次)。
  • 过去 24h 队列共有 9 个失败构建(不含本次)。

分诊清单:

  1. 失败测试在本 PR 改动的包里 → 真回归,修 PR。
  2. 失败测试与本 PR 无关 → 看上面的「跨 PR 相同签名」;已有汇总 issue ⇒ flaky/环境问题实锤,去那张 issue 上谈,修好前重排只会再烧一轮全队列。
  3. 两者都不是 → 可能与同组 PR 语义冲突;等前面的 PR 落地或失败出队后再重排一次即可,不要连续重排。

Generated by Claude Code · merge-queue-triage workflow (#4859)

akarma-synetal pushed a commit to akarma-synetal/framework that referenced this pull request Oct 7, 2026
…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>
akarma-synetal pushed a commit to akarma-synetal/framework that referenced this pull request Oct 7, 2026
…ui#11636, objectstack-ai#11637, objectstack-ai#11635, objectstack-ai#11624 and objectstack-ai#11640) (objectstack-ai#21827)

Fixes objectstack-ai#21807
Clause-②: no

This moves the bundled Console's objectui pin from `9dfaca654311`
(objectstack-ai#21772, PR objectstack-ai#21800) to `0abd4f9f8769fc4c19ad2f96707684876f74c09f`, which
was objectui `main` at write time and is past `39a3e91fad`. The Console
now carries objectui#11636, the fix for objectui#11092: the screen-flow
runner names the flow by its served label, translated. That merge is
what objectstack-ai#20318 waits on. The range also carries objectui#11637
(objectui#11170), objectui#11635 (objectui#11095), objectui#11624
(objectui#11396) and objectui#11640 (objectui#11628).

⛔ This is not a release act. Version PR objectstack-ai#21352 is untouched, and no tag,
publish or Release was made.

## Range

- objectui `git ls-remote origin refs/heads/main` read
`0abd4f9f8769fc4c19ad2f96707684876f74c09f` at 2026-10-05T04:53:29Z, just
before the bump.
- Re-read at 05:37:53Z, it reads `59917c4b2` (objectui#11639, a served
view's toolbar change written inside `config`), one commit past the pin.
This PR does not carry it.
- The objectui clone is full (`--is-shallow-repository`: false). `git
merge-base --is-ancestor` exits 0 against `0abd4f9f8` for `39a3e91fa`,
`c4c506b9e`, `22ddcd5c5` and `1c2e2c46c`.
- `9dfaca654311..0abd4f9f8769` has 5 commits and 0 merges.
- objectui declared 5 changesets over the range: 3 release and 2 release
nothing. Every commit carries a changeset. None declares `major`, and
none carries the breaking annotation. The highest declared level is
`minor`, so the console changeset is `minor`. These counts come from the
bump's own digest and were re-read from the changeset blobs.
- **No commit subject in the range carries `!`.** `git log --format='%h
%s' 9dfaca654..0abd4f9f8 | grep -E '^[0-9a-f]+ [a-z]+(\([^)]*\))?!:'`
matches nothing (exit 1).

| objectui commit | landing | changeset | note |
|---|---|---|---|
| `1c2e2c46c` | objectui#11624 (objectui#11396):
`MasterDetailDetailConfig` is derived from the spec's `details` entry by
reference, member for member the same | release-nothing | moves the
manifest (below) |
| `22ddcd5c5` | objectui#11635 (objectui#11095): a dataset-bound KPI
tile's re-read on the data-invalidation bus gets a pin; tests and a doc
comment only | release-nothing | |
| `39a3e91fa` | objectui#11636 (objectui#11092): the flow runner names
the flow by `flows.FLOW.label`, then the served `flowLabel`, then the
API name | minor (`Clause-②: yes (widening)`) | smoke below; unlocks
objectstack-ai#20318 |
| `c4c506b9e` | objectui#11637 (objectui#11170): one declaration of
per-type NODE SLOTS; `objectui check`, core `validateSchema`, the SDUI
parser's `validateTree` and the `kind:'html'` compile walk them | minor
(`Clause-②: yes (narrowing)`) | answered below |
| `0abd4f9f8` | objectui#11640 (objectui#11628): the External Datasource
panel unwraps the `{ success, data }` envelope | patch | smoke below |

## Declared-breaking entries and the ADR-0087 disposition

**There are none to dispose of.** No commit subject carries `!`, no
changeset declares `major` or the breaking annotation, and the bump
wrote no `adr-0087: TODO` placeholder. `check-adr-0087-registration
--base origin/main` reports "this PR adds no declared-breaking
changeset". `check-changeset-no-major --base origin/main` reports "This
diff introduces no `major` bump".

One entry narrows by its own declaration, so here is how this repo
answers it. **objectui#11170 (`c4c506b9e`, `Clause-②: yes
(narrowing)`)** widens the reach of four objectui validators: each now
judges nodes held in a renderer's declared slots, not only in
`children`. It adds, removes or renames no ObjectStack-authorable key,
and no Zod schema or stored `sys_metadata` shape moves. Its sdui-parser
half only takes effect when a manifest is built with `slotsFor`. This
repo's `scripts/gen-sdui-manifest-node.mjs` calls
`manifestFromConfigs(configs)` without that option, and the regenerated
`sdui.manifest.json` carries 0 `slots` keys. So the save gate's walk
does not move with this bump. The lockstep reading is in Acceptance
notes.

## What changed here (22 files, +255 / -93)

- **`.objectui-sha` and `.changeset/console-0abd4f9f8769.md`.**
`scripts/bump-objectui.sh 0abd4f9f8769fc4c19ad2f96707684876f74c09f
--no-commit` wrote both, with `OBJECTUI_ROOT` set to a read-only
objectui clone in the scratchpad. The range walked completely and the
level was auto-set to `minor`.
- The digest rendered objectui#11170's bullet as its first line, the
bare `**Clause-②: yes (narrowing)**`. That bullet is rewritten to say
what landed.
- A closing paragraph states the range has no declared-breaking entry
and names the release-nothing pair.
- **`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. It still has 107
components, and the sha256 moves from `6f921896ffac…` to
`f95d406a584e…`.
- One input moved: `object-master-detail-form`'s `details` gains `of:
"object"` and a description of the spec's closed entry (objectui#11396).
`"of": "object"` occurrences go from 12 to 13.
- The record moves its pin and `modulesRoot`. objectui's workspace
version stays 17.7.0, confirmed against the pin by `check-sdui-manifest
--require-objectui`.
- **`packages/sdui-parser/objectui-lockstep.json`.** `gen:sdui-lockstep`
re-recorded it from the clone at the pin. It records 214 grammar lines
(blob `0131f27cf86d`), 25 diagnostic codes and containment predicate
`76c18fb95d1f`, all unchanged, so no port is owed by that gate.
- **The 54 asserting pin citations in `packages/spec/src`, re-measured,
not restamped.**
- **Method.** The range changes 50 paths. Each asserting record's cited
objectui paths were resolved against the tree at `9dfaca654`. Ambiguous
bare names were disambiguated by the record's own directory. Each
`index.tsx` and `types.ts` cited is a `plugin-kanban`,
`plugin-dashboard`, `plugin-map`, `plugin-gantt`, `plugin-grid`,
`plugin-tree` or `plugin-timeline` file. None is
`plugin-form/src/index.tsx` or `sdui-parser/src/types.ts`, the two
same-named files the range touches.
- **Result.** No asserting record cites a changed path. So every cited
file is byte-identical across the hop, and every anchor held unmoved.
- **Records.** Each of the 41 hand-written records gains a dated
2026-10-05 hop sentence and keeps its earlier history.
- **Counts.** Three records carry a count, and each was re-taken by its
own method; all three read the same at `2e818d0b5`, `9dfaca654` and
`0abd4f9f8`:
- the `keyboardNavigation` hit lines: 15, against 3 for the
`schema.editable` control;
- `ObjectKanban.tsx`'s `quickAdd` / `onQuickAdd`: 2 each, against 11 for
`onCardClick`;
- the `ElementDataSourceGate` occurrences in the five `src/index.tsx`
shells: 0, 3, 3, 3 and 4.
- **Corpus counts.** The six migration entries' counts were re-taken
with `git grep -o -F`. That method first reproduced every `9dfaca654`
number: 7632 files, `objectstack` 17313, `@objectstack/spec` 7186,
`timeout` 1360, `useState` 2477, `TTL` 182, `tenant` 1318,
`RuntimeConfig` 293, `resourceLimits` 2, `window` 4193, `period` 238,
`interval` 195, `metrics` 401 and `Span` 508.
- The new readings are 7650 files, `objectstack` 17390,
`@objectstack/spec` 7209 and `useState` 2478. `window` reads 4194. Every
other control is unchanged.
- All 98 checked tokens (the export lists of
`plugin-lifecycle-advanced.zod.ts`, `tracing.zod.ts` and
`metrics.zod.ts`, plus every named key) read the same at both pins:
every zero is still zero, and `Span` / `SpanSchema` read 508 / 57.
- `packages/spec/src/migrations/registry.ts` was regenerated with
`gen:migration-registry`.
- **`.changeset/objectui-pin-citations-0abd4f9f8769.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 (the local Console Pin Gate equivalent)

`turbo run build --filter=@objectstack/client...
--filter=@objectstack/spec...` and then `pnpm objectui:build` ran as one
command under the verify lock. That is a clean build: mode 3
shallow-cloned objectui at the pin into `.cache/objectui-0abd4f9f8769`.
Exit 0, 10m51s on the shared 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"**: the spec-injection check passes.
- "@objectstack/console dist ready (64232 KB) from
objectui@0abd4f9f8769".

`check:console-sha` and `check:console-injection` (self-test 67
assertions, then the dist check) exit 0 against that dist.

## Browser smoke: `examples/app-showcase` with the Console built at
`0abd4f9f8769`

The server ran `pnpm dev -- --fresh --ui --no-watch -p 41907` with
`OS_PORT=41907`, on its own ephemeral DB with the seeded admin. Headless
Chromium (`/opt/pw-browsers/chromium`) drove it, signing in through the
console's login form. Page errors, console errors and every 4xx/5xx
response were captured. Only the PIDs this run started were stopped.

**Flow label (objectui#11636 / objectui#11092).** The launch was Tasks
list, select a row, then the toolbar's "Reassign…"
(`showcase_bulk_reassign`, which targets the screen flow
`showcase_reassign_wizard`, label "Reassign Task").

| leg | trigger answer | runner header line | dialog title (accessible
name) | API name shown | completion toast |
|---|---|---|---|---|---|
| `en` | 200, `status: paused`, `flowLabel: "Reassign Task"` | `Reassign
Task` | `New Assignee` (the screen's own title) | no | `Flow "Reassign
Task" completed` |
| `zh-CN`, with a bundle entry `flows.showcase_reassign_wizard.label` |
200, `flowLabel: "Reassign Task"` | `重新分配任务` | `New Assignee` | no |
`流程「重新分配任务」已完成` |

- The resume answered 200 with `flowLabel` on both legs.
- **The showcase bundle declares no `flows` translations** (`git grep`
finds none), so the `zh-CN` leg needed one to exist. It was made by a
temporary local edit, as objectstack-ai#21800's smoke did for `imageField`:
- `node scripts/ablation-replace.mjs --hold` added `flows: {
showcase_reassign_wizard: { label: '重新分配任务' } }` to the `zh-CN` block of
`examples/app-showcase/src/system/translations/index.ts`.
  - The server booted with `--compile`.
- The file was restored at once with `--restore`. The tool reports the
blob back to HEAD's `f0517049b565` and `git diff HEAD` empty, and `git
status --porcelain` is empty.
- `GET /api/v1/i18n/translations/zh-CN` served the entry, and the
session's `html[lang]` read `zh-CN`.
- The showcase `dist/` was rebuilt afterwards (`turbo run build
--filter=@objectstack/example-showcase --force`), and the held string
has 0 hits in `dist/objectstack.json`. Nothing of the edit is in this
diff.
- **Verdict:** at this pin the runner header and the completion toast
name the flow by the active language's `flows.FLOW.label`, then the
served label, and never by the API name. The launcher button still reads
the ACTION's label ("Reassign…"), which is the action's own string and
not the flow's.

**The range's other landings.**

| landing | surface | observed |
|---|---|---|
| objectui#11640 (objectui#11628) | Setup →
`metadata/datasource/showcase_external` | The External Datasource panel
lists the remote tables `customers` (7 columns) and `orders` (7), each
with Import. "Refresh catalog" (`POST …/external/refresh-catalog` 200)
shows `snapshot 10/5/2026, 5:25:23 AM`. "Run validation" (`POST
…/external/validate` 200) renders "All 2 objects match the remote
schema." with `showcase_ext_customer` and `showcase_ext_order`, and no
render error. |
| objectui#11624 (objectui#11396) | `page/showcase_project_workspace`
(`object-master-detail-form`, `details: [{ title: 'Tasks', childObject:
'showcase_task', addLabel: 'Add task' }]`) | The master form draws its 6
fields. The Tasks section draws, and "Add task" opens the child's inline
form with 14 more fields (Title*, Assignee, Priority, …). 0 page errors.
|
| objectui#11637 (objectui#11170) | the three `kind:'html'` pages:
`showcase_start_here`, `showcase_capability_map`,
`showcase_command_center_jsx` | All three render (1563 / 2426 / 882
characters of text), with no compile or validation text and 0 page
errors. |
| objectui#11635 (objectui#11095) | `dashboard/showcase_ops_dashboard`,
`showcase_revenue_pulse`, `showcase_chart_gallery` | The ops tiles read
Active Projects 2, At-Risk (Red) 1, Awaiting Review 2 and Total Budget
1,090,000, matching objectstack-ai#21710's REST cross-check. All three dashboards have
0 page errors. This landing changes no executable code (its changeset:
tests and one doc comment). An out-of-band REST `PATCH` of a task to
`in_review` did not re-read the open tile: it stayed 2 with 0 dataset
queries in 6s, and read 3 after a reload. That mutation never travels
the console's own invalidation bus, so this is no reading of
objectui#11095's pin. **NOT MEASURED** there. |

**Console messages across the run:** 0 page errors. The failed loads are
the pre-login `401 GET /api/v1/auth/get-session`, one `404` per page
load that the response listener did not attribute (`/favicon.ico`
answers 404 on this server, as objectstack-ai#21800 recorded), and `404 GET
/api/v1/meta/datasource/showcase_external?state=draft`, the panel's
draft probe for a datasource that has no draft.

## Gates and tests (head `e40526e564`)

- `node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack
--commands` derived 127 commands from the 22-path diff, and all 127 were
run at `e40526e564` and exited 0. `--ran` reports "127 derived, 127 run,
0 NOT-MEASURED, 0 UNRUN", with every exit code recorded. The full
workspace build (`turbo run build --filter=!@objectstack/docs`) ran
first, so no dist-reading gate met a missing prerequisite.
- Also exit 0:
- `check:objectui-pin-citations --verify-anchors` with `OBJECTUI_ROOT`
at the pin: "54 asserting objectui pin citation(s) match .objectui-sha
(0abd4f9f8)", and "7 anchor content assertion(s) verified against
objectui at 0abd4f9f8".
- `check:objectui-bump` (20 assertions across 5 cases),
`check:sdui-lockstep`, `check-sdui-manifest --require-objectui`,
`check:console-sha`, `check:console-injection`.
- `check-adr-0087-registration --base origin/main` and
`check-changeset-no-major --base origin/main`.
- `@objectstack/spec check:generated`: all 15 artifacts current after
the `--fix`.
- `pnpm --filter @objectstack/spec exec vitest run`: 668 files, 19261
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` (119 files, 5627 passed);
- `@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).
  - The CLI integration tier is declared 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 (`:328`), so this diff cannot
move a verdict on an untouched file.
  - Repo-wide `pnpm lint` is left to CI.

## Acceptance notes

- **Lockstep, a reading and not a gate result.** objectui#11170 gives
objectui's `validateTree` a slot walk: `slotElements` plus the
`comp?.slots` loop in `packages/sdui-parser/src/validate.ts`. This
repo's port has none (`git grep -n slots packages/sdui-parser/src`: 0).
- The walk only fires for a manifest built with `slotsFor`, and this
repo's committed manifest carries no `slots`. So the save gate and
objectui's runtime parser still agree on that manifest.
- objectui's `kind:'html'` compile (`getJsxManifest`) is now built with
`slotsFor`. A slot-held node that fails validation could fail the
renderer's compile while this repo's save gate accepts it.
- `check:sdui-lockstep` compares the grammar region, the codes and the
containment predicate, so it cannot see a walk-depth change. That class
is outside its reach by its own header ("CANNOT see … WHEN a code fires"
beyond the predicate).
- Not measured through a public door here, so it is noted rather than
filed. Carrier: none.
- `main` moved three commits past this branch's base (objectstack-ai#21810, objectstack-ai#21808,
objectstack-ai#21809). `git merge-tree --write-tree HEAD origin/main` is clean. Two of
them touch files this diff touches:
`api-methods-batch-conformance.test.ts` (test titles) and
`component.test.ts` (objectstack-ai#21808 re-points a non-asserting anchor). The
merged tree still carries 1 and 6 citations at the new pin and 0 at the
old one. No merge was made; the merge queue rebuilds on the current
`main`.
- objectui `main` reached `59917c4b2` (objectui#11639) after the pin was
read. It is not in this range.
- Writes: one draft PR through the relay and the report comment on
objectstack-ai#21807. No label, PR assignee, ready flag or auto-merge was written;
this dispatch's write budget names none of them.

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

---------

Co-authored-by: Claude <noreply@anthropic.com>
akarma-synetal pushed a commit to akarma-synetal/framework that referenced this pull request Oct 7, 2026
…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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

1 participant