Skip to content

chore(objectui): bump the console pin to 62597c588072 (carries the fail-closed quick_actions requiredPermissions fix) with 46 re-measured citations, the FormField.span describe re-point and the lockstep re-record - #19832

Merged
objectstack-fleet[bot] merged 16 commits into
mainfrom
claude/issue-19503-objectui-pin-bump
Sep 23, 2026

Conversation

@objectstack-fleet

@objectstack-fleet objectstack-fleet Bot commented Sep 23, 2026 •

Copy link
Copy Markdown
Contributor

Fixes #19503

Clause-②: no

Moves the console pin to objectui main 62597c588072. That tip carries objectui#10153, the fail-closed record:quick_actions.requiredPermissions fix. The PR also carries the bump's two required follow-ups, folded in under the PM ruling on #19503 (comment 5791879469, option A): the sdui-parser lockstep re-record, and a re-MEASURE of the packages/spec/src/** citations that check:objectui-pin-citations names. The citation edits touch comments and migration-rationale prose only; there are no schema or export changes. The one published sentence that moves is the FormField.span .describe() pin citation, authorised by the second ruling (comment 5793509969) and carried with .changeset/19503-pin-bump-describe-corrections.md (@objectstack/spec: patch) plus a regenerated content/docs/references/ui/view.mdx. Clause-②: no, because every authored document is accepted and refused exactly as before.

check:objectui-pin-citations exits 0 on the head: "47 asserting objectui pin citation(s) match .objectui-sha (62597c588) … 7 anchor content assertion(s) verified".

Ancestry reading (fix → new pin: AHEAD)

Measured in a FULL (non-shallow) clone of objectstack-ai/objectui. git rev-parse --is-shallow-repository returns false, so an exit 0 is self-proving:

command exit reading
git merge-base --is-ancestor 28b065800c7d1b6069c06aa906d0716377b5e281 62597c588072636e9c30ea35b3d89b1e46fd765d 0 the fix is IN the new pin
git rev-list --count 28b065800c7d..62597c588 33 the new pin is 33 commits ahead of the fix
git merge-base --is-ancestor 87af769e9a3e 28b065800c7d 0 the old pin was 4 behind the fix (the card's REST compare: behind_by 4)

The bump's own changeset lists the fix: fix(plugin-detail): record:quick_actions.requiredPermissions is an ADR-0066 capability set, read fail-closed ... (objectui 28b065800).

What moved, and how each artefact was produced

artefact producer
.objectui-sha + .changeset/console-62597c588072.md bash scripts/bump-objectui.sh --no-commit 62597c588072… exit 0 (27 releasing changesets, 0 breaking, @objectstack/console: minor)
scripts/sdui-manifest.record.json node scripts/gen-sdui-manifest-node.mjs --objectui-version 17.6.0 exit 0. sdui.manifest.json came out BYTE-IDENTICAL (sha256 49211fee7792, 57 components), because packages/core ships 17.6.0 at both pins; only the record moves
packages/sdui-parser/objectui-lockstep.json pnpm gen:sdui-lockstep with OBJECTUI_ROOT at a checkout of 62597c588, exit 0. Diff: 3+/3-, only rev, revDate and recordedAgainstPin. Grammar blob 0131f27cf86d unchanged, 214 lines, all 26 diagnostic codes agree. check:sdui-lockstep exit 0: "byte-identical to objectui@62597c588072". No parser port is owed
packages/spec/src/migrations/registry.ts pnpm --filter @objectstack/spec gen:migration-registry, from the six edited entries
the console bash scripts/build-console.sh exit 0: "Console dist ready (60524 KB) from objectui@62597c588072", bundle canary present. check:console-sha exit 0

Citation re-measure: method

  • Read-point records. For every cited objectui file I ran git diff --quiet 87af769e9a3e 62597c588 -- FILE.
    • Unchanged file: the anchor holds by identity. The prose names that, keeps the earlier hop's history, and says where the last content re-read happened.
    • Changed file: each anchor was mapped through the git diff -U0 hunks and its text compared at both pins. It was then re-read in the new tree.
  • Corpus counts. These are the six migration entries plus registry.ts. I re-counted with git grep -o -F TOKEN SHA | wc -l. The method was calibrated first: at 87af769e9a3e it reproduces every recorded count exactly (8228 files, useState 2383, timeout 1075, objectstack 12966, @objectstack/spec 4997, window 3464, interval 170, tenant 976, …).
    • Every dark token still counts 0 at 62597c588: the def exports and key names each entry names, 95 tokens in all.
    • The Span / SpanSchema collisions are unchanged at 486 / 53.
    • Only the corpus size (8303) and the lit controls move.

Re-read sites (all 46 the gate named)

site(s) objectui file(s) reading at 62597c588
6 migration entries + their 6 registry.ts copies whole corpus re-counted: dark tokens still 0. The kernel-health-check… entry keeps its 87af769e9 lit-control clause verbatim (now dated) and adds the new counts after it. check:future-spec-major holds a measurement exemption to that exact sentence, and the new figure "@objectstack/spec 5043" would read as a version
component.test.ts accordion/tabs icon; component.zod.ts PageTabs / PageAccordion icon containers.tsx (changed, 4c6f549ef) re-read: 853-859, 912, 1069-1075 and 1116 did NOT move, text byte-identical
component.test.ts button icon; component.zod.ts element:button icon resolve-icon.ts, button.tsx, lazy-icon.tsx byte-identical, so no anchor moved
component.zod.ts metric icon plugin-dashboard index.tsx, ObjectMetricWidget.tsx, MetricWidget.tsx byte-identical
component.test.ts / component.zod.ts kanban limit ×3, quickAdd ×2, navigation plugin-kanban (all), objectql.ts, ElementDataSourceGate, ListView.tsx, ObjectView.tsx, plugin-kanban.mdx byte-identical. ⚠️ The quickAdd block's lit control said 6 onCardClick; the identical file counts 11 at both pins (the test-side twin already says 11). It was miscounted, not moved, and is corrected; the verdict rests on the 0
component.zod.ts calendar navigation ObjectCalendar.tsx (changed, afb228418) re-read: 921-935, 936 and 938-939 unmoved; 1293→1317, 1218→1237 and 1228-1241→1250-1263, text byte-identical
component.zod.ts object-map header, filter, sort; component.test.ts / component.zod.ts map/gantt/tree rows; functional-completeness.ts map row ObjectMap.tsx (changed, 2252653d0: only warnOnTopLevelStyleUrl's docblock and dev-warning text) every anchor from :289 on MOVED 16-19 lines with its text byte-identical (e.g. 814→833, 895→914, 377→396, 382→401, 1058→1077); no read point or key set changed
component.zod.ts gantt / tree ×3 / timeline ×2 headers; functional-completeness.ts gantt, timeline rows plugin-gantt, plugin-tree, plugin-timeline, record-source.ts, ListView.tsx byte-identical. The tree's ElementDataSourceGate count was re-taken: tree 0, map/gantt/grid/calendar 3 each (plugin-grid/src/index.tsx changed and still reads 3)
api-methods-batch-conformance.test.ts sys_api_key ObjectGrid.tsx (changed, 804831c2a + 62597c588) ⚠️ the selection block's CONTENT moved: objectui#10218 rewrote the selection arm to "presence enables; an explicit off wins". The span is now 4024-4051 (hash c88443302d40, was 6133933199… over the last three hops). Re-read, the record's claim holds: with neither selection nor selectable authored, multi-select is enabled only by hasBulkActions, and none of the four views declares selection
dataset.zod.ts measure format date-display.ts (changed, 516583b54), dataset-format.ts formatDate now parses via toDisplayDate (date-only values keep their calendar day); the cited style handling is unchanged; 198-233→271-306, 152→225
view.zod.ts view-face limit reach (#19228) 9 files both instruments re-run: the probe returns 0, and the control returns the same 13 lines across 6 files, line for line. All 9 cited files are byte-identical
view.zod.ts:1975/:1978 ObjectMap anchors (content-asserted) ObjectMap.tsx re-READ against 2252653d0: it rewrote the docblock and dev warning ABOVE getMapConfig (the remedy now names the declared map: { style }, carried out as mapStyle). getMapConfig is byte-identical, so 385→404 and 390→409; the quoted getMapConfig comment is intact (:361→:380)
view.zod.ts FormField.span docblock autoLayout.ts (changed, e026e15f9), form.tsx resolveColSpan 153→154 (an import added above it). form.tsx is byte-identical, so spanLadderFor still emits the ladder

pnpm exec tsx scripts/check-objectui-pin-citations.ts --verify-anchors reads: all 7 content-asserted anchors pass at 62597c588.

The two sites first reported, then resolved under the second ruling (comment 5793509969, option A)

  1. packages/spec/src/kernel/functional-completeness.ts, the calendar row: its claim had become FALSE, so it is RESTATED. The row said the "Calendar configuration required" literal "is the text RENDERED at the pin: objectui#10101 landed AFTER the pin". git merge-base --is-ancestor afb228418 62597c588 → 0 (and → 1 against 87af769e9a3e).
    • At the new pin the screen's copy goes through tt('calendar.configRequired', …) (ObjectCalendar.tsx:1207-1208). Its default and the en pack read the same English sentence; zh, de and the other packs render their own words.
    • The if (!calendarConfig) refusal arm is unchanged (the ObjectCalendar.tsx diff on this hop is copy-only).
    • The row now says what renders, names the arm rather than the English sentence as the thing to match, and cites .objectui-sha = 62597c588. Comment only.
  2. packages/spec/src/ui/view.zod.ts FormField.span .describe(): its claim still holds, so the citation is RE-POINTED. The describe now names .objectui-sha = 62597c588.

Gates

node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands on head 3fd40bedd derives 124 families. The docs families are added by view.mdx. Per-family exit codes are in the os-dev-report comment on #19503. Summary:

  • check:objectui-pin-citations exit 0; pnpm --filter @objectstack/spec check:generated exit 0 (all 15 artefacts)
  • run as CI runs it and green: check:react-declaration-parity (MANIFEST=$PWD/sdui.manifest.json … --baseline react-declaration-parity.baseline.json --strict, "no new DECLARATION divergence"); the derived spelling omits the manifest input
  • check:skill-examples read exit 3 (PREREQUISITE NOT MET: @objectstack/client-react unbuilt) in the sweep; after pnpm --filter '@objectstack/client-react...' build it reads exit 0 (259 prose examples type-check). dispatch-gates --ran: 124 derived, 122 run, 2 NOT-MEASURED, 0 UNRUN
  • NOT MEASURED, left to CI: check:dual-build-cjs-loads and check:type-check-debt (both exit 3, PREREQUISITE NOT MET: they need a full workspace pnpm build; this diff changes only comments and migration-rationale strings in spec)
  • tests: @objectstack/spec vitest on component.test.ts, api-methods-batch-conformance.test.ts, src/migrations, functional-completeness and src/ui/view*: 22 files, 1562/1562 pass

Changed lines: 560 (+364 / -196, 19 files), under the 5000 threshold. origin/main was merged in twice (d3ff597a before the PR was opened; 16329059b for this round, with view.mdx regenerated from the merged tree as the pre-push os-regen check requires).

Acceptance notes

维护者速读(草稿)

  • 改了什么:把控制台钉住的 objectui 版本推进到 62597c588(包含权限修复 objectui#10153:record:quick_actions.requiredPermissions 改为失败即拒绝);同时按 PM 裁决 A,重录 sdui-parser 的对齐记录(只动了出处字段),并在新版本上逐条重新核对 spec 里引用 objectui 代码行号的注释。
  • 为什么改:当前发布的控制台仍按旧逻辑“失败即放行”,这是 [Decision] requiredPermissions 在 record 块上到底是对象动作还是 ADR-0066 能力?—— 已发布的 record:quick_actions 那一半今天是 fail-open #19186 的解锁前提;钉住版本一动,引用旧版本的注释门禁必然变红,所以这些注释必须随版本重新测量,不能只替换哈希。
  • 风险与代价(含回滚):不改任何 schema 或导出,已写的元数据接受/拒绝结果完全不变;唯一对外文字变化是 FormField.span 的 describe 把所引版本改为新钉住版本(说法本身仍成立,附 spec patch changeset)。控制台行为只随 objectui 这 37 个提交变化(27 条带发布说明)。日历那一行说法在新版本上已不成立(提示文案改为按语言翻译),已按第二次裁决改写。回滚:还原本 PR 即可。
  • 席位意见:
  • 你要做的:本 PR 需要在最终 head 上做一次同档合约审查,记录后才能排队;PR 保持草稿。

Dev session: session_01852ixPjE785Lt8MUeYGDEb (PM seat domain:devx#1, session_01VDtqoecgES7ScQYGbFVDRv).

🤖 Generated with Claude Code

https://claude.ai/code/session_01852ixPjE785Lt8MUeYGDEb


Generated by Claude Code

…ui 28b065800c7d)

Produced by scripts/bump-objectui.sh --no-commit 62597c588072.

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01852ixPjE785Lt8MUeYGDEb
node scripts/gen-sdui-manifest-node.mjs --objectui-version 17.6.0; the
manifest is byte-identical (sha256 49211fee7792), only the provenance
record moves.

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01852ixPjE785Lt8MUeYGDEb
pnpm gen:sdui-lockstep with OBJECTUI_ROOT at 62597c588; provenance
fields only (grammar blob 0131f27cf86d and all 26 codes unchanged).

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01852ixPjE785Lt8MUeYGDEb
…2597c588072

Each dark token (the def exports and key names each entry names) was
re-counted with git grep -o -F at the new pin: still 0 everywhere, the
Span / SpanSchema collisions unchanged at 486 / 53. The method was
calibrated first: at 87af769e9a3e it reproduces every recorded count
(8228 files, useState 2383, timeout 1075, objectstack 12966, ...). Only
the corpus size and the lit controls move. registry.ts is regenerated
by gen:migration-registry.

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01852ixPjE785Lt8MUeYGDEb
…nd map pin citations at 62597c588

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01852ixPjE785Lt8MUeYGDEb
…ations at 62597c588

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01852ixPjE785Lt8MUeYGDEb
…w pin citations at 62597c588

Re-points the two view.zod.ts ObjectMap anchors (385 -> 404, 390 -> 409)
after re-reading getMapConfig at the new pin: objectui 2252653d0 rewrote
the docblock and dev warning above it, the read itself is byte-identical.

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01852ixPjE785Lt8MUeYGDEb
check:future-spec-major reads "@objectstack/spec NNNN" as a version and
holds its measurement exemption to the witness sentence; the 87af769e9
clause stays verbatim (and dated) and the 62597c588 re-count follows it.

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

github-actions Bot commented Sep 23, 2026 •

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 2 package(s): @objectstack/sdui-parser, @objectstack/spec, touching 13 documentable anchor(s). ⚠️ 1 changed file(s) yielded no anchor (packages/sdui-parser/objectui-lockstep.json), 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))

⛔ 4 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/ 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
  • 1 changed file(s) yielded no anchor (packages/sdui-parser/objectui-lockstep.json) — 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 60 of 215 client-bound route-ledger rows — the other 155 have no registrar path: tail to select them, so pages documenting THEIR client methods cannot appear above, on this or any run. Of those 155: 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; 100 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 — 137 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 8cbc3c0084a3c3c8ef5e59763ab3be96aa1a6f07 → packageMentionDocs.

Which tree this was computed on

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

node scripts/docs-audit/affected-docs.mjs --json 8cbc3c0084a3c3c8ef5e59763ab3be96aa1a6f07

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

@objectstack-fleet objectstack-fleet Bot changed the title chore(objectui): bump the console pin to 62597c588072 (carries the fail-closed quick_actions requiredPermissions fix) with 44 re-measured citations and the lockstep re-record chore(objectui): bump the console pin to 62597c588072 (carries the fail-closed quick_actions requiredPermissions fix) with 46 re-measured citations, the FormField.span describe re-point and the lockstep re-record Sep 23, 2026
@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

Contract review

Served-tier: CONTRACT_REVIEW_TIER
Head-sha: 3fd40bedd80463437f8435048bdc1c73da14d428

① Derived judgments

  • Executable-surface check — PASS. Every touched non-test spec file was comment-stripped (block + line comments, strings preserved) at origin/main and at the head, and the results diffed:
    • packages/spec/src/ui/component.zod.ts (+128/−79): stripped diff EMPTY — every hunk is JSDoc/comment prose (PageTabs, PageAccordion, element:button, metric, kanban, calendar, object-map header, map filter/sort, gantt, tree, timeline, ComponentPropsMap).
    • packages/spec/src/ui/dataset.zod.ts: stripped diff EMPTY.
    • packages/spec/src/kernel/functional-completeness.ts: stripped diff EMPTY (calendar, gantt, timeline, map rows — comment only).
    • packages/spec/src/ui/view.zod.ts: against the PR's merge-base afc3b649 the stripped diff is exactly ONE line — the FormField.span .describe() at head :3264, whose only token change is 87af769e9 → 62597c588. (Against the origin/main tip, extra columns/hiddenFields/fieldOrder describe lines are main drift from 9dcdb775, landed after the merge-base; merge-tree is clean and mergeable_state is clean.) No schema, default, enum, export or other .describe() moved.
    • Migration entries: all six hunks sit inside the reason: string; no id, key, version or transform changed.
    • packages/spec/src/migrations/registry.ts: mechanical regeneration — its changed lines are byte-identical to the entries' changed lines modulo indent; nothing else moved against the merge-base.
  • Test files — no assertion weakened. component.test.ts and api-methods-batch-conformance.test.ts: comment-stripped diff EMPTY for both; the edits are // citation prose only.
  • Citation spot-checks at objectui 62597c588072 (full clone; 30+ anchors read, all as claimed), including: the two view.zod.ts ObjectMap anchors (ObjectMap.tsx:404 ObjectMapConfigSchema.safeParse(config), :409 the style fallback — byte-identical to :385/:390 at 87af); the calendar row (ObjectCalendar.tsx:1200 if (!calendarConfig) → :1206-1208 tt('calendar.configRequired', …); en.ts:711 carries the English sentence, zh.ts:598 / de.ts:579 their own; afb228418 is an ancestor of the new pin and not of the old); the calendar navigation read points; FormField.span (autoLayout.ts:154 resolveColSpan, WIDE_FIELD_TYPES identical at both pins, form.tsx byte-identical); the grid selection block hashes in api-methods-batch-conformance.test.ts; dataset.zod.ts measure format; the byte-identity roster; corpus counts re-taken at both pins (dark tokens 0 at both; onCardClick = 11 at both — the "6" correction is right).
  • packages/sdui-parser/objectui-lockstep.json: only rev, revDate and recordedAgainstPin changed; revDate equals the new pin's commit date. Grammar untouched.
  • The pin: 28b065800c7d (the fail-closed fix) is an ancestor of 62597c588072 (exit 0, non-shallow clone); 87af769e9a3e is an ancestor of the fix; 33 commits fix → pin. .objectui-sha and scripts/sdui-manifest.record.json carry the full sha.
  • No stale asserting citation: zero matches of the gate's asserting pattern for the old pin remain in packages/spec/src; the one leftover 87af769e9a in a .pin.test.ts is the historical spelling.
  • Clause-②: no is right: no accept-set change, no exported name moved, no public surface widened.

② Semver level

  • .changeset/console-62597c588072.md → @objectstack/console: minor: correct and truthful (30 objectui changesets in range, 0 major; lists the fail-closed fix).
  • .changeset/19503-pin-bump-describe-corrections.md → @objectstack/spec: patch: correct — one describe sentence re-points a pin citation. No major anywhere.

③ Boundary flags

  • No governed surface and no release-owned tree in the 19-file list.
  • content/docs/references/ui/view.mdx: exactly the two span rows, generator output only.
  • origin/main has moved since the merge-base; merge-tree is clean; a later re-merge will need gen:docs from the merged tree, which the pre-push os-regen hook enforces.
  • Check-runs on 3fd40bedd: 42 total, 39 success, 3 skipped, 0 failures.

Implemented-by: session_01852ixPjE785Lt8MUeYGDEb
Reviewed-by: session_01VDtqoecgES7ScQYGbFVDRv

VERDICT: PASS

Isolated at-tier reviewer, adopted by the domain:devx#1 seat.


Generated by Claude Code

gen:schema + gen:docs on the merge 557f561. The os-regen driver kept this
branch's side of view.mdx and dropped main's fieldOrder / hiddenFields
describe rows; the regenerated file equals origin/main's plus this
branch's two FormField.span rows.

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01852ixPjE785Lt8MUeYGDEb
@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

Regen-provenance: 5794397942 · 3fd40bedd80463437f8435048bdc1c73da14d428 → 2a768071114e39151f9231823700d17c39f3b7f3 · git diff --name-only 3fd40bedd..2a7680711, minus paths whose blob equals origin/main → content/docs/references/ui/view.mdx (regenerated), packages/spec/src/migrations/registry.ts, packages/spec/src/ui/view.zod.ts (main's delta, verbatim)

The hop was produced by bash scripts/pm/os-regen-merge.sh (merge commit 557f561aa, parents 3fd40bedd + origin/main 8cbc3c008). The regeneration commit 2a7680711 changes one file, content/docs/references/ui/view.mdx, via gen:schema + gen:docs. The os-regen driver had kept this branch's side and dropped main's fieldOrder / hiddenFields describe rows; the regenerated file equals origin/main's except for this PR's two FormField.span rows.

Of the 52 paths in git diff --name-only 3fd40bedd..2a7680711, 49 are byte-identical to origin/main. The other two, registry.ts and view.zod.ts, were text-merged by git without conflict. For each, the hop's +/- lines are identical to main's own delta (git diff afc3b649 origin/main compared with git diff 3fd40bedd 2a7680711, matching sha1). No other change is in the push.

Step 4 on 2a7680711 (spec build VERDICT exit 0, then gen:docs and gen:migration-registry, which produced no further diff) — each exit 0:

  • check:generated
  • check:objectui-pin-citations
  • check:docs
  • check:api-surface
  • check:authorable-surface
  • check:sdui-lockstep
  • check-sdui-manifest
  • check:future-spec-major
  • check:objectui-changeset

Main's sibling migration entries are present at the same counts in registry.ts.

Dev session session_01852ixPjE785Lt8MUeYGDEb.


Generated by Claude Code

@objectstack-fleet
objectstack-fleet Bot marked this pull request as ready for review September 23, 2026 12:40
@objectstack-fleet
objectstack-fleet Bot added this pull request to the merge queue Sep 23, 2026
Merged via the queue into main with commit 48c91e9 Sep 23, 2026
37 checks passed
@objectstack-fleet
objectstack-fleet Bot deleted the claude/issue-19503-objectui-pin-bump branch September 23, 2026 13:07
This was referenced Sep 23, 2026
akarma-synetal pushed a commit to akarma-synetal/framework that referenced this pull request Sep 28, 2026
…ui#10221 and the objectui#9910 re-cut) with re-measured pin citations and the lockstep re-record (objectstack-ai#20036)

Fixes objectstack-ai#20029

Clause-②: no

Moves the console pin to objectui `main` `f8a9d0fb0596` (the tip at
2026-09-24T20:41Z). That pin carries objectui#10221 (`0651e7ab4`, a
currency amount's decimals come from its currency, never from `scale`),
which ruling 乙 on objectstack-ai#19910 item 2 requires before PR objectstack-ai#19909 lands. It also
carries the objectui#9910 re-cut (`5ea623ea`, containment is the
declared `children` slot), which objectstack-ai#19969 waits on. The PR folds in the
objectstack-ai#19503 / PR objectstack-ai#19832 precedent's two steps: the sdui-parser lockstep
re-record, and a re-MEASURE of the `packages/spec/src/**` citations that
`check:objectui-pin-citations` names. Every spec edit is to comment or
migration-rationale prose only, plus ONE `.describe()` citation re-point
(the `FormField.span` pin, under PM ruling `5822830122`, option A). No
schema, key, default or export changes. Clause-②: no, because every
authored document is accepted and refused exactly as before.

✅ **All 47 pin citations are now green.** The one `.describe()` this PR
first stopped on (`view.zod.ts:3392`, `FormField.span`) was re-pointed
under PM ruling `5822830122` (option A) on objectstack-ai#20029. See "The describe,
resolved" below.

## Ancestry reading (fix → new pin: AHEAD)

- **REST `compare`: NOT MEASURED.** This session's proxy refuses GitHub
API reads on `objectstack-ai/objectui`. `GET
/repos/objectstack-ai/objectui/compare/0651e7ab4...f8a9d0fb0` answered
"GitHub access to this repository is not enabled for this session".
- **In its place, measured by git** in a FULL clone of
`objectstack-ai/objectui`, where `git rev-parse --is-shallow-repository`
returns `false`. An exit 0 is self-proving, and an exit 1 there is not a
shallow-window artefact.

| command | exit | reading |
|---|---|---|
| `git merge-base --is-ancestor 0651e7ab4 f8a9d0fb0596` | 0 |
objectui#10221 is IN the new pin |
| `git rev-list --count 0651e7ab4..f8a9d0fb0596` | 14 | the new pin is
14 commits AHEAD of the fix (REST would read `ahead`) |
| `git merge-base --is-ancestor 5ea623ea f8a9d0fb0596` | 0 | the
objectui#9910 re-cut is IN the new pin |
| `git merge-base --is-ancestor 5ea623ea 0651e7ab4` | 0 | it is an
ancestor of the fix, too |
| `git merge-base --is-ancestor 62597c588072 0651e7ab4` | 0 | the old
pin is behind the fix (control leg) |
| `git merge-base --is-ancestor 5ea623ea 62597c588072` | 1 | the re-cut
was NOT in the old pin (full clone, so the exit 1 stands) |
| `git rev-list --count 62597c588072..f8a9d0fb0596` | 92 | this hop's
size |

The bump's own changeset lists both: `(objectui 0651e7ab4)` and
`(objectui 5ea623eab)`.

## What moved, and how each artefact was produced

| artefact | producer |
|---|---|
| `.objectui-sha` + `.changeset/console-f8a9d0fb0596.md` | `bash
scripts/bump-objectui.sh --no-commit f8a9d0fb0596…` exit 0. It reads 86
releasing changesets and 9 breaking (all 9 annotated, none declared
major); `@objectstack/console: minor`. The generator's `adr-0087: TODO`
is answered `not-required (no-migration-prescription)`, in the wording
of the last bump that carried breaking entries. |
| the console | `OBJECTUI_ROOT=../objectui bash
scripts/build-console.sh`, through the verify lock, VERDICT command-exit
0 (691 s). The `import/jobs` bundle canary is present. `pnpm
check:console-sha` exit 0: "Console dist matches the objectui pin
(objectui@f8a9d0fb0596)". |
| `sdui.manifest.json` + `scripts/sdui-manifest.record.json` | `node
scripts/gen-sdui-manifest-node.mjs` exit 0. It wrote 59 components,
sha256 `12dd4f8fbf45`. The diff is +39: the `children` slot input
objectui#9910 declared on `alert`, `badge`, `box`, `button`, `card`,
`container`, `flex`, `grid` and `stack`. `node
scripts/check-sdui-manifest.mjs` exit 0. |
| `packages/sdui-parser/objectui-lockstep.json` |
`OBJECTUI_ROOT=../objectui pnpm gen:sdui-lockstep` exit 0. The diff is
3+/3-, only `rev`, `revDate` and `recordedAgainstPin`. Grammar blob
`0131f27cf86d` is unchanged (214 lines), and all 26 diagnostic codes
agree. `pnpm check:sdui-lockstep` exit 0: "byte-identical to
objectui@f8a9d0fb0596". No parser port is owed by the lockstep gate. |
| `packages/spec/src/migrations/registry.ts` | `pnpm --filter
@objectstack/spec gen:migration-registry`, from the six edited entries |

## The objectstack-ai#19969 save/render window (measured, not fixed here)

In the NEW `sdui.manifest.json`, **5 of 59 components** disagree between
`isContainer` (what `packages/sdui-parser/src/validate.ts` still tests)
and "declares a `{ name: 'children', type: 'slot' }` input" (what the
pinned renderer now decides containment by):

| component | `isContainer` | `children` slot | direction |
|---|---|---|---|
| `badge` | false | true | the save gate warns `not-a-container` on
children the renderer renders |
| `alert` | false | true | same |
| `button` | false | true | same. objectui states it on purpose: "⛔ Not
`isContainer`: objectui#6804 ruled that flag means LAYOUT containment"
(`button.tsx:97-104`) |
| `page:tabs` | true | false | the save gate accepts top-level children
that the slot rule does not declare (the children live in
`items[].children`) |
| `page:accordion` | true | false | same |

Non-zero, so objectstack-ai#19969 can be sequenced right behind this PR. The predicate
is ⛔ not ported here.

## Citation re-measure: method

- **Read points.** For each cited objectui file, `git diff --quiet
62597c588072 f8a9d0fb0596 -- FILE`.
- An unchanged file holds its anchors by identity. The prose says so and
keeps the earlier hops' history.
- For a changed file, each cited span was taken at the old pin and
searched for byte-for-byte at the new pin. A moved span is re-pointed. A
span not found was re-READ in the new tree, and its content change is
stated where it is cited.
- **Corpus counts** (six migration entries + `registry.ts`). `git grep
-o -F TOKEN SHA | wc -l`. The method was calibrated first: at
`62597c588` it reproduces every recorded count exactly (8303 files,
`objectstack` 13125, `@objectstack/spec` 5043, `timeout` 1086,
`RuntimeConfig` 240, `resourceLimits` 2, `useState` 2389, `window` 3526,
`period` 170, `interval` 179, `metrics` 324, `TTL` 156, `tenant` 987,
`Span` 486, `SpanSchema` 53).
- At `f8a9d0fb0`, all 100 dark tokens still count 0: every export of the
four cited zod files plus each key name.
- Only the corpus size (8512) and the lit controls move. The two new
`Span` hits are `colSpan` and the word "Spanish".
- `check:future-spec-major`'s measurement exemption to the sentence
"controls objectstack 12966 and @objectstack/spec 4997 on the same
corpus" is kept verbatim. The new figures follow it as "13347 and 5123 …
at this pin", and the gate is exit 0.

## Every `packages/spec/src/**` edit, with its before → after anchor

| site | objectui file(s) | reading at `f8a9d0fb0` |
|---|---|---|
| `api-methods-batch-conformance.test.ts` `sys_api_key` |
`ObjectGrid.tsx` (changed +18/-5: objectui#10083 `rowActionsDeclared`,
objectui#9909 currency locale), `useBulkExecutor.ts` (identical) |
selection block `4024-4051` → `4032-4059`, still hash `c88443302d40`.
`298-303` is identical (hash `01083348330f`) |
| `functional-completeness.ts` calendar / gantt / timeline / map rows |
`ListView.tsx` (changed: objectui#10275 `$select`; objectui#10037 /
objectui#10250 self-query filter and search on gantt / tree / chart),
`ObjectGantt.tsx` (changed: `$search`), `ObjectCalendar.tsx` /
`ObjectTimeline.tsx` / `ObjectMap.tsx` (identical) | no calendar /
gantt-date / timeline / map arm touched; prose restated |
| 6 migration entries + their 6 `registry.ts` copies | whole corpus |
dark tokens 0 at 8512 files; lit controls re-counted (see method) |
| `component.zod.ts` / `component.test.ts` tabs + accordion `icon` |
`containers.tsx` (changed, `ba0b61a60`: an import line + `page:header`)
| `853-859`, `912`, `1069-1075`, `1116` did NOT move, text
byte-identical |
| `component.zod.ts` / `component.test.ts` button `icon` | `button.tsx`
(changed, `5ea623eab`), `resolve-icon.ts` / `lazy-icon.tsx` (identical)
| ⚠️ registration inputs CONTENT grew: `85-97` → `85-105` (+ `children`
slot input), `defaultProps` `98-102` → `106-110`; still no `icon` input.
`:43` / `:72` / `:74` unmoved |
| `component.zod.ts` metric `icon` | `ObjectMetricWidget.tsx` (changed,
`0651e7ab4`), `index.tsx` / `MetricWidget.tsx` (identical) | destructure
`174` → `181`, forward `483` → `528`, text byte-identical |
| `component.zod.ts` / `component.test.ts` kanban `limit` ×3, `quickAdd`
×2, `navigation` | `ObjectKanban.tsx` (changed, objectui#10068
`$orderby`), plugin-kanban `index.tsx` (changed), `objectql.ts`,
`ElementDataSourceGate.tsx`, `ListView.tsx`, plugin-view
`ObjectView.tsx` (all changed); `types.ts`, `element-data-source.ts`,
`KanbanImpl.tsx`, `plugin-kanban.mdx` (identical) | ⚠️ query CONTENT
gained `$orderby` (`674-679` → `680-690`), mapping gained `sort: true`
(`447-450` → `507-511`); moved byte-identical: `:84`→`:85`,
`:553`→`:554`, `:559`→`:565`, `:676`→`:687`, `:1210`→`:1225`,
`:1218-1219`→`:1233-1234`, `:1468`→`:1483`, `:1484-1497`→`:1499-1512`,
`:1563`→`:1578`, `:1587`→`:1602`, `index.tsx:313`→`:363-364`,
`objectql.ts:3735`→`:3832`, Gate `316-331`→`373-388`,
`192-194`→`200-202`, ListView `2979`→`3067`, `2952`→`3040`, ObjectView
`1638`→`1666`, `1579`→`1607`. `onQuickAdd` / `quickAdd` still 0,
`onCardClick` still 11 |
| `component.zod.ts` calendar `navigation` | `ObjectCalendar.tsx`
(identical) | anchors hold by identity |
| `component.zod.ts` `object-map` header, `filter`, `sort` |
`ObjectMap.tsx`, plugin-map `index.tsx`, `record-source.ts` (identical)
| anchors hold by identity |
| `component.zod.ts` `object-gantt` header | `ObjectGantt.tsx` (changed
+29/-2, objectui#10250) | `:501-503`, `:613` unmoved; the rest moved 21
/ 29 lines byte-identical (e.g. `844`→`865`, `1615`→`1644`,
`2181`→`2210`, `2144`→`2173`). ⚠️ new undeclared reads `search` /
`searchableFields` (`:776-779`, `:880-885`) are recorded, host-generated
by `ListView`'s toolbar |
| `component.zod.ts` flat `TreeConfig` guidance + `object-tree` header +
registry-shell count | `ObjectTree.tsx` (changed +69/-3: objectui#9549,
objectui#9136), `ListView.tsx` (changed); `index.tsx`,
`record-source.ts` (identical) | ⚠️ two CONTENT changes, restated: the
`filter.tree` stash read is DELETED (`getTreeConfig` `235-248` →
`246-259`, `tree` `:236` → `:247`), and `filter` gains a second read on
the inline `value` provider (`:837`); `ObjectTreeSchema` now declares
`filter` (objectui#9549). Moved byte-identical: `582`→`593`,
`871/922/985`→`937/988/1051`, `813-814`→`879-880`, `742`→`753`,
`908`→`974`, `891`→`957`, `775`→`786`, `741-753`→`752-764`, `751`→`762`,
`750`→`761`, `197-218`→`198-219`, ListView `3261-3275`→`3366-3385`,
`3270`→`3380`. `ElementDataSourceGate` count re-taken: tree 0, map /
gantt / grid / calendar 3 each |
| `component.zod.ts` `object-timeline` header + `data` read |
`renderer.tsx` (changed, `0b6b295a1`), `ObjectTimeline.tsx` /
`index.tsx` (identical) | `1215`→`1240`, `1505`→`1531`,
`1442-1457`→`1468-1483`, text byte-identical |
| `component.zod.ts` `ComponentPropsMap` comments (map/gantt/tree;
timeline) | as above | restated to match the headers |
| `dataset.zod.ts` measure `format` | `dataset-format.ts`,
`date-display.ts` (both changed, objectui#10026) | `formatDate`
`271-306` → `355-390` and `225` → `309` byte-identical;
`formatMeasureDate` `229-264` → `229-263` (comment-only change), call
`370` → `369`, datetime arm `260-262` → `259-261`; the style handling is
unchanged |
| `view.zod.ts` view-face `limit` reach (objectstack-ai#19228) | 9 files | instrument
1: probe 0; control 14 lines / 7 files (was 13 / 6; the new one is
`RelatedList.selectFls-10186.test.tsx:314`, executable ⇒ 9 executable,
was 8). Instrument 2: the same four flattening spreads and the same
exclusions. Every anchor re-pointed byte-identical (e.g.
`ListView.tsx:3084`→`3172`, `4702`→`4815`, `ObjectView.tsx:1725`→`1753`,
`2319`→`2347`). Both verdicts stand |
| `view.zod.ts` `ListMapConfigSchema` content-asserted anchors |
plugin-view `ObjectView.tsx`, `objectql.zod.ts` (changed) | `case
'map':` `1764` → `1792` (17-line block identical),
`ObjectMapConfigSchema` `1574` → `1589` (47-line declaration identical),
`LIST_VIEW_LOCAL_OVERRIDES` `734` → `741` (list identical, still no
`map`). `--verify-anchors` passes all content assertions |
| `view.zod.ts` `FormField.span` DOCBLOCK | `form.tsx` (changed,
`5ea623eab`: registration inputs only), `autoLayout.ts` (identical) |
`spanLadderFor` `:204-231` is byte-identical, so it still emits the
ladder |

## The describe, resolved (PM ruling `5822830122`, option A)

The ruling widened the file surface by exactly three items, all landed
in one new commit (`90f9a30`):

| file | what |
|---|---|
| `packages/spec/src/ui/view.zod.ts` | the `FormField.span`
`.describe()` citation, `.objectui-sha` = `62597c588` → `.objectui-sha`
= `f8a9d0fb0596`; nothing else in the sentence changes. The claim was
re-read true at the new pin: `plugin-form`'s `autoLayout.ts` is
byte-identical, and `form.tsx`'s `spanLadderFor` `:204-231` is
byte-identical |
| `content/docs/references/ui/view.mdx` | regenerated by `pnpm --filter
@objectstack/spec gen:schema && pnpm --filter @objectstack/spec
gen:docs` (VERDICT command-exit 0): the two `span` rows only (+2/-2).
**No other generated file moved** |
| `.changeset/20029-pin-bump-describe-correction.md` |
`'@objectstack/spec': patch`, stating the describe correction, in the
shape of `17429-` / `19503-pin-bump-describe-corrections.md` |

## Gates

`node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack
--commands` on head `90f9a30` derives 124 families (the `view.mdx` edit
adds the docs families). `--ran` reads: "124 derived famil(ies)
accounted for — 121 run, 3 NOT-MEASURED".
- **All run families exit 0**, among them: `pnpm --filter
@objectstack/spec run check:objectui-pin-citations` ("47 … match
.objectui-sha"), `pnpm check:sdui-lockstep`, `pnpm check:console-sha`,
`node scripts/check-sdui-manifest.mjs`, `pnpm --filter @objectstack/spec
run check:generated`, `check:docs`, `check:objectui-changeset`,
`check:future-spec-major` and `check:migration-registry`.
- Five docs families first read exit 3 (unbuilt `@objectstack/lint` /
`formula` / `client-react`). After `turbo run build` of those closures
they read exit 0: `check:doc-formula-expressions`,
`check:doc-security-posture`, `check:skill-examples`,
`check:docs-transcript-drift`, `check:lean-entry-closure`.
- **NOT MEASURED, exit 3 (PREREQUISITE NOT MET), left to CI:**
`check-plugin-teardown-shape --self-test` (shallow clone);
`check:dual-build-cjs-loads` and `check:type-check-debt` (both need a
full workspace build). This diff changes no code in any package those
read.
- **Tests:** `@objectstack/spec` vitest on `component.test.ts`,
`api-methods-batch-conformance.test.ts`, `src/migrations`,
`functional-completeness`, `src/ui/view*` and `src/ui/dataset*`: 26
files, 1666 / 1666 pass (head `530fc4d`); re-run on `src/ui/view*` at
head `90f9a30`: 19 files, 1085 / 1085 pass.

Changed lines: **884** (+600 / -284, 20 files), under the 5000
threshold.

## Acceptance notes

- **Stale metric test anchors, out of the gate's population.**
`component.test.ts`'s metric `icon` test body still cites
`index.tsx:204`, `ObjectMetricWidget.tsx:142` / `:474` and
`MetricWidget.tsx:312-321`. It carries no pin citation, so it is outside
the gate's population. Those anchors were already stale before this hop:
the docblock beside them reads `:237`, `:181` / `:528` and `:351-360`.
Left as they are, because the gate does not name them.
- **`object-kanban` reads `sort` now** (objectui#10068, via
`ElementDataSourceGate` from the binding's `dataSource.sort`). The node
schema declares no `sort`. The key reaches the board from the binding,
not from the authored node, so this is not an authoring gap. Recorded,
not acted on.
- **The branch name is `claude/issue-20029-objectui-pin-bump`**, as the
claim names. The console changeset is the script's own
`console-f8a9d0fb0596.md` (the precedent's spelling), not a hand-named
`20029-*.md`.

## 维护者速读(草稿)

- **改了什么**:把控制台钉住的 objectui 版本从 `62597c588` 推进到 `f8a9d0fb0`(objectui
main 当时的最新提交),其中包含货币小数位修复 objectui#10221(`0651e7ab4`)和容器判定改用 `children`
插槽的 objectui#9910(`5ea623ea`)。同时按先例重新生成 SDUI 清单、重录 sdui-parser
对齐记录,并在新版本上逐条重新核对 spec 里引用 objectui 代码行号的注释(47 处中 46 处已改)。
- **为什么改**:裁决乙要求 objectui#10221 先进入发布的控制台,PR objectstack-ai#19909 才能落地;同一次推进也是 objectstack-ai#19969
在等的前提。
- **风险与代价(含回滚)**:spec 只改注释和迁移说明文字,外加按 PM 裁决 `5822830122`(选项 A)把
`FormField.span` describe 里引用的钉住版本改为新版本(附 spec patch changeset,重新生成
`view.mdx`);不改任何 schema、键、默认值或导出,已写的元数据接受/拒绝结果完全不变。控制台行为随 objectui 这 92
个提交变化(其中 9 条标注 breaking,都是 objectui 自身的类型面)。清单里有 5 个组件的 `isContainer` 与
`children` 插槽不一致(badge、alert、button、page:tabs、page:accordion),这是 objectstack-ai#19969
要补的保存/渲染窗口。回滚:还原本 PR 即可。
- **席位意见**:
- **你要做的**:describe 已按裁决 A 处理,门禁全部跑绿(3 项需完整构建的留给 CI)。落地前还需要一次同档合约审查。

Dev session: `session_01BMUTTbeXStLRWxU9zEWDJq` (PM seat
`domain:devx#1`, `session_01VDtqoecgES7ScQYGbFVDRv`).

🤖 Generated with [Claude Code](https://claude.com/claude-code)

https://claude.ai/code/session_01BMUTTbeXStLRWxU9zEWDJq

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

---------

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