Skip to content

feat(spec): the position form picks permissionSets from the permission-set registry (ref-multi:permission), with the console pin moved to 4997995022f8 - #22794

Merged
objectstack-fleet[bot] merged 5 commits into
mainfrom
claude/issue-22682-position-permission-sets-picker
Oct 11, 2026
Merged

objectstack-fleet[bot] merged 5 commits into
mainfrom
claude/issue-22682-position-permission-sets-picker

Conversation

@objectstack-fleet

@objectstack-fleet objectstack-fleet Bot commented Oct 11, 2026 •

Copy link
Copy Markdown
Contributor

Fixes #22682
Clause-②: no

Item 3 of #22682, the card's last packages/spec item (items 1 and 2 landed with PR #22710 as b32ee3eaf3). ADR-0131 D4, verbatim: "References to declared items are by machine name, resolved registry-first." The position form is the one authoring surface for the position to permission-set binding, and its permissionSets row (added by PR #22723 as type: 'tags', a free-text tag box) now names the permission-set registry picker, so the designer offers the declared set names instead of free text.

This PR now also moves the bundled Console's objectui pin to 4997995022f8, objectui#12136's merge (objectui#12126), which registers the ref-multi:permission widget. That is landing order B from seat 1's ACCEPT 6106524871 on #22682: the objectui widget first, then the pin, then this row. Triage's unlock 6108789665 put the pin bump into this PR.

  • Round 1 (accepted): claim 6105901038 (seat domain:spec#1), base e84aeb36ce, accepted at 8996b566b5 by ACCEPT 6106524871. The three files of that round are unchanged here.
  • Landing round: claim 6109075588 (seat domain:spec#3, session session_01KNKBCRDJCu5tGy3TEbvtrF), branch claude/issue-22682-position-permission-sets-picker continued from 8996b566b5. It merges main (aa734f0924 onto efcbac73cc, then 483fddb3fc onto 1eff3224d7, both through scripts/pm/os-regen-merge.sh), and adds one pin-bump commit, aaa50c66ec.

What changes

  • The row (packages/spec/src/identity/position.form.ts): { field: 'permissionSets', type: 'tags', colSpan: 2, helpText: … } becomes { field: 'permissionSets', widget: 'ref-multi:permission', colSpan: 2, helpText: … }, with a comment saying why. The helpText is unchanged. No other row, section or form changes.
  • One pin (packages/spec/src/identity/position.test.ts, a new describe at the end, 4 tests). It reads the position form through METADATA_FORM_REGISTRY, the registry /meta/types serves, which holds the output of defineForm's parse, so a parse that dropped widget would also turn it red. It asserts:
    • a lit and a dark control for the row probe;
    • exactly one permissionSets row, whose widget is ref-multi:permission;
    • the registry type the key names is permission, and getMetadataTypeSchema('permission') is PermissionSetSchema;
    • permissionSets refuses a bare string with invalid_type at permissionSets, so the list-valued key sits on a list-valued field.
  • Changeset: @objectstack/spec patch, Clause-②: no.
  • ⛔ No schema, parse, export or accept-set change. PositionSchema is untouched (permissionSets stays z.array(SnakeCaseIdentifierSchema).optional()), the approver bindings are untouched, and FormField.widget stays z.string().optional(): the spec has no form widget-key vocabulary, so no published vocabulary is added. No objectui file.
  • The pin hop (commit aaa50c66ec, 20 files, +312 / -83): .objectui-sha from 0df67f237c5a to 4997995022f8, with its regeneration. The next section has the details.

The console pin: 0df67f237c5a to 4997995022f8

This moves the bundled Console's objectui pin from 0df67f237c5a (PR #22812) to 4997995022f8e65946f6362b7434685539cc72b7, objectui#12136's merge (objectui#12126): metadata-admin registers ref-multi:permission, so the position form's permissionSets row renders a multi-picker of the declared permission sets instead of the raw-JSON fallback.

This is not a release act. The Version Packages PR is untouched, and this diff edits neither packages/console/CHANGELOG.md nor packages/console/package.json. The console's release input is the new .changeset/console-4997995022f8.md.

Range

  • REST compare on objectstack-ai/objectui, 0df67f237c5a...4997995022f8 (read 2026-10-11T12:55:58Z): status: ahead, ahead_by: 7, behind_by: 0, 80 files, merge base 0df67f237c5a.
  • In a scratch repository that borrows the objectui object store, git merge-base --is-ancestor 4997995022 origin/main exits 0 (objectui main read at 1d1cfe0c119e, 2026-10-11T12:39:18Z). 0df67f237c5a..4997995022f8 has 7 commits and 0 merges. Its 80 paths are 17 added, 62 modified, 1 renamed and 0 deleted.
  • Why this commit and not a later one: it is the nearest objectui main commit that carries the widget, as the dispatch ruled. objectui main has two more commits (9b75509, 1d1cfe0). I measured no reason to take them, so this bump does not chase them.

What each commit brings, and which regenerated change it causes

objectui commit what it is what it changes here
69bca0a (objectui#12081 item 3) a paged grid's footer reads the whole matched set, or says it reads the page ObjectGrid.tsx (+75 / -41) and the en / zh / de packs: hop sentences in the four ObjectGrid.tsx records and the calendar record; corpus counts
802f0bc (objectui#5250 slice C, the strict authoring face) repairs the keys the strict authoring face refuses in objectui's examples examples JSON and packages/types/examples/dashboard.ts only. No record cites them. Its one regenerated effect is a corpus control: timeout 1705 to 1704 in two migration entries
1071393 (objectui#12098) marketplace install answers say what the runtime served app-shell marketplace and the locale packs: the calendar record's pack sentence; corpus counts
7525045 (objectui#12082 leg A) more write affordances read the affordance-to-grant map ObjectGrid.tsx (+14 / -3: a bulk update def needs the edit verdict) and ObjectGantt.tsx (+27 / -4): hop sentences in five gantt records and the grid records
c9fc10b (objectui#12121) a boolean with a CEL default is left to the server on create form.tsx (+37 / -25): the form-layout record's call-site anchor moves :3246 to :3258
66eb560 (objectui#12131 phase 1, the strict authoring face) docs stop teaching keys the strict authoring face refuses README, docs pages and one renamed example. No record cites them, and no corpus count moves
4997995 (objectui#12126) the ref-multi:permission widget widgets.tsx, ResourceEditPage.tsx and metadata-admin i18n.ts. No record cites them; corpus counts

Neither of the two strict-authoring-face commits touches a registered component, so neither moves the SDUI manifest.

What the regeneration changed (20 files)

file written by gate that required it
.objectui-sha scripts/bump-objectui.sh 4997995022f8… --no-commit Console Pin Gate builds what it names
.changeset/console-4997995022f8.md the same run (the digest): 5 releasing changesets of 5, 2 commits without a changeset, highest level minor check:objectui-changeset, Check Changeset
scripts/sdui-manifest.record.json node scripts/gen-sdui-manifest-node.mjs over .cache/objectui-4997995022f8 check-sdui-manifest.mjs
packages/sdui-parser/objectui-lockstep.json node scripts/check-sdui-lockstep.mjs --update, OBJECTUI_ROOT at the built tree check:sdui-lockstep
55 asserting citations: 49 in 14 committed files under packages/spec/src, and 6 in the generated registry.ts re-measured by hand (below) check:objectui-pin-citations (and --verify-anchors)
.changeset/objectui-pin-citations-4997995022f8.md hand-written, @objectstack/spec patch, Clause-②: no Check Changeset (the shipped describes name the pin)
content/docs/references/ui/view.mdx pnpm --filter @objectstack/spec gen:docs, the one artifact check:generated named stale check:docs
  • sdui.manifest.json is byte-identical (cmp against the tracked file: equal). It keeps 107 components and sha256 9d87162a3ef6…. Only its record moves: objectuiSha and modulesRoot.
  • The lockstep records 214 grammar lines (blob 0131f27cf86d), 25 diagnostic codes and containment predicate 76c18fb95d1f. All are unchanged; objectui's packages/sdui-parser is untouched by the range, so no port is owed. Only rev, revDate and recordedAgainstPin move.
  • packages/spec/src/migrations/registry.ts is gitignored and regenerated (gen:migration-registry), not committed.
  • The bump script and the console build read objectui through a scratch repository with no refs of the shared checkout's own, borrowing its object store as an alternate. So nothing was written into the shared objectui checkout.

How the citations were re-measured

  • Method. Each asserting record's cited objectui files were resolved at 0df67f237c5a and intersected with the range's 80 changed paths. A record whose cited files are all byte-identical (git diff --quiet) gains that sentence and no re-pointing: 29 records. The other 20 were re-read one by one.
  • Changed cited files: ObjectGrid.tsx, ObjectGantt.tsx and form.tsx, plus the en / zh / de packs, whose calendar.configRequired lines hash the same at both pins. Every cited line in them moved or held byte-identical, measured by exact-text search of each old range in the new file:
    • ObjectGrid.tsx: the selection block 4897-4924 to 4981-5008, still hashing to c88443302d40; :1786 to :1787; :1850 to :1851; :5097-5116 to :5165-5184; :5132 to :5200; :5570 to :5615; :6587-6588 to :6632-6633; :6604-6605 to :6649-6650.
    • ObjectGantt.tsx: +2 above the new grant block and +23 below it, for example getGanttConfig :610 to :612 and the refusal arm :2307 to :2330. The gantt record's 25 read-point anchors are re-cited at this pin.
    • form.tsx: spanLadderFor held at :274-301; its call site moved :3246 to :3258.
  • Readings beside a cited read, each said in its hop sentence:
    • ObjectGrid.tsx (objectui#12082): a bulk update def is now withheld unless the edit verdict allows it. That narrows the declared defs and adds no implicit one, so the sys_api_key reading in api-methods-batch-conformance.test.ts holds.
    • ObjectGantt.tsx (objectui#12082): the in-chart write handlers are withheld without the grant. The renderer's schema.* read set is the same 49 names at both pins, so no declared key set moves.
  • Counts re-taken by each record's own method.
    • keyboardNavigation: 15 hit lines against 3 for schema.editable, at both pins.
    • ObjectKanban.tsx's quickAdd / onQuickAdd / onCardClick: 2 / 2 / 11. No 'kanban-ui' literal in objectui's non-test sources at either pin.
    • The ElementDataSourceGate occurrences in the five src/index.tsx shells: 0, 3, 3, 4 and 3, all five shells byte-identical.
  • Corpus counts. The six migration entries' counts were re-taken with git grep -o -F. That method first reproduced every 0df67f237c5a number: 8424 files, objectstack 18248, @objectstack/spec 7582, useState 2645, timeout 1705, RuntimeConfig 347, resourceLimits 2, window 4596, period 251, interval 233, metrics 456, Span 517, SpanSchema 57, TTL 184 and tenant 1357.
    • At the new pin they read: 8441 files, objectstack 18271, @objectstack/spec 7587, useState 2648, timeout 1704, RuntimeConfig 352, resourceLimits 2 (the same two packages/app-shell hits), window 4604, period 251, interval 238, metrics 456, Span 517, SpanSchema 57, TTL 184 and tenant 1362.
    • The zero tokens: 98 were checked (the exports of plugin-lifecycle-advanced.zod.ts, tracing.zod.ts and metrics.zod.ts, plus every named key). 96 read 0 at both pins; Span / SpanSchema read 517 / 57 at both.

Clause-②: the pin hop moves no published contract, measured

  • .zod.ts accept sets, defaults and exports: none moves. Each of the 14 changed .ts files under packages/spec/src was scanned with the TypeScript scanner at aa734f0924 and at the head, comments skipped and every string, template and regular-expression literal replaced by one placeholder token. The token sequences are identical in 12 of the 14. The other two, 18.system-metrics-jsdoc-durations-unit-in-key.ts and 18.system-tracing-otel-exporter-durations-unit-in-key.ts, each gain one + joining one new string fragment (the older count) into a reason string. No identifier, key, value or export moves. The one shipped describe that changes is FormField.span's, and only its sha moves.
  • Baselines: check:api-surface ("public API surface + factory signatures unchanged") and check:authorable-surface are green, and check:generated reads "All 14 generated artifacts are up to date".
  • The html tier: the SDUI manifest the save gate and os validate compile against is byte-identical, so no page source changes verdict.
  • So the hop's line is Clause-②: no, the same as this PR's line 2 and as both new changesets. No line in this body moves.

The widget renders at the new pin

  • packages/app-shell/src/views/metadata-admin/widgets.tsx:3242 is export const WIDGETS = {, and :3246 is 'ref-multi:permission': RefMultiPermissionWidget,. WIDGET_LABELLING declares it 'group' at :3358. The key is absent from widgets.tsx at 0df67f237c5a.
  • ResourceEditPage.tsx:1001-1004 loads the permission catalog (client.list('permission')) only when the form on screen declares the widget, which the position form now does.

The key: ref-multi:permission, measured

objectui readings are git show in a read-only clone, at objectui origin/main 206505c and at this repo's pin .objectui-sha 20c6d351ad74; both read the same at every line cited.

question reading
Does a multi-value ref: spelling exist anywhere? No. Census of quoted ref: widget literals: this repo has ref:object, ref:dataset and ref:component only; objectui has the same three. All three are single-valued.
How does the vocabulary spell a multi-value picker? As its own key: field-ref / field-multi, select / multiselect, and action-multi. No key in either repo serves both arities.
Can objectui's single ref: widgets take an array? No. RefObjectWidget, RefComponentWidget and RefDatasetWidget (widgets.tsx:464, :607, :684) each read String(value) and write one string. The registry also declares ONE labelling per key (WIDGET_LABELLING, widgets.tsx:3142): the single ref: pickers are 'control', while field-multi, action-multi and multiselect are 'group'.
Which registry type names permission sets? permission, on both sides. Spec: MetadataTypeSchema (kernel/metadata-plugin.zod.ts:166), the DEFAULT_METADATA_TYPE_REGISTRY row labelled Permission Set (:1117), and getMetadataTypeSchema('permission') returns PermissionSetSchema. objectui: registerMetadataResource({ type: 'permission', … }) (PermissionMatrixEditor.tsx:28), and anchors.ts:374.
Does type: 'tags' override an explicit widget? No. inferWidget returns an explicit fieldSpec.widget first (SchemaForm.tsx:447). tags maps to string-tags only when no widget is declared (:467). So the row drops type, matching every other ref: and -multi row in the spec forms, none of which declares a type.

So the key is a distinct list key in the ref: family. The prefix carries the arity, and the token after the colon is the exact registry type, so the same split reads ref:object and ref-multi:permission.

Alternatives considered:

  • ref:permission on the array field, with the arity read from the schema. It is one key per type, but no widget in the vocabulary is arity-polymorphic, a single ref: widget writes a string into a list, and one key would have to carry one labelling for two shapes.
  • permission-multi, mirroring field-multi. It drops the ref: namespace the claim names.
  • ref:permission-multi. The token after the colon would no longer be a registry type.

What objectui rendered for this key before the pin moved, and the landing order

Round 1's reading, measured by code path at objectui 206505c and at the then pin 20c6d351ad74:

  • The position editor is the generic ResourceEditPage. Its form is entry?.form from /meta/types (ResourceEditPage.tsx:456, :457, :2943). Position registers only a preview (previews/index.ts:87), not an edit page. So the key reaches every console as soon as the server runs this spec.
  • WIDGETS (widgets.tsx:3033) had no ref-multi:permission entry. resolveFieldFace therefore sent an unregistered, non-passthrough hint to the raw-json face (SchemaForm.tsx:870), rendered at :2223: a JSON textarea under the note widget ref-multi:permission — falling back to JSON until a custom renderer is registered. (i18n.ts:2166).
  • No objectui test pins "every widget key a spec form names is registered", so the change turned no objectui gate red; it would have degraded to the announced fallback.
  • Precedent: objectui#11601 records the same shape for ref:dataset, and the joined-block row in spec(ui): reportForm's "Joined blocks" row offers a block's dataset as free text with no required, so Studio saves the block #21702 now refuses #21714 declared ref:dataset only after the pin carried the renderer.

Seat 1 set landing order B in ACCEPT 6106524871: the objectui companion first, then the pin, then this row. The companion was filed as objectui#12126 and landed as objectui#12136 (4997995022). This PR now carries the pin as well, so the row and the widget that renders it ship in one console build. The section above has the reading at the new pin.

Tests and gates

This round's readings are at head 483fddb3fc (git rev-parse --short HEAD) unless a line says otherwise. Every build and test went through scripts/pm/os-verify-lock.sh, and each result below is quoted from its VERDICT line or from the gate's own verdict line. Exit codes were captured before any pipe.

  • @objectstack/spec:
    • pnpm --filter @objectstack/spec build: VERDICT command-exit 0. Its declaration stamp (9278c1ed04e9…) still matches at 483fddb3fc; the second merge brought no packages/spec path.
    • pnpm --filter @objectstack/spec exec vitest run --project local --maxWorkers=2: Test Files 648 passed (648), Tests 19346 passed | 1 todo (19347), VERDICT command-exit 0. It read the same at aaa50c66ec, before the second merge.
    • pnpm --filter @objectstack/spec typecheck (tsc --noEmit, the scripts program and the test layer): VERDICT command-exit 0. The test-layer line reads 52 file(s) / 246 error(s) / 135 pinned signature(s) held.
    • pnpm --filter @objectstack/spec check:generated: "All 14 generated artifacts are up to date". The one stale artifact before gen:docs was content/docs/references/** (check:docs), from the FormField.span describe.
  • @objectstack/sdui-parser (its lockstep record moved): pnpm --filter @objectstack/sdui-parser test: Test Files 14 passed (14), Tests 225 passed (225); its typecheck exits 0.
  • The bump's own gates:
    • check-sdui-manifest.mjs: "present, intact (sha256 9d87162a3ef6…, 107 components) and recorded at the live objectui pin 4997995022f8…" (exit 0).
    • check:sdui-lockstep: "OK — this copy is byte-identical to objectui@4997995022f8 (2026-10-11T10:56:33+00:00) over 214 grammar line(s) [blob 0131f27cf86d], agrees on all 25 diagnostic code(s) and on the not-a-container predicate [blob 76c18fb95d1f]" (exit 0).
    • check:objectui-pin-citations: "55 asserting objectui pin citation(s) match .objectui-sha (499799502), 145 historical citation(s) recorded and not checked, across 1983 spec source(s)." With --verify-anchors (OBJECTUI_ROOT at the scratch repository): "13 anchor content assertion(s) verified against objectui at 499799502" (exit 0).
  • Console Pin Gate, local equivalent. CI's job runs turbo run build --filter=@objectstack/client..., bash scripts/build-console.sh, the dist assertion, check:console-sha and check:console-injection --require-stamp. Run here, at the pin commit's tree:
    • turbo run build --filter=@objectstack/client... --filter=@objectstack/sdui-parser --concurrency=2: Tasks: 34 successful, 34 total, VERDICT command-exit 0.
    • bash scripts/build-console.sh: VERDICT command-exit 0 (lock held 8m18s). Its log reads "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" and "@objectstack/console dist ready (64384 KB) from objectui@4997995022f8".
    • The dist holds a non-empty index.html, assets/ and a .objectui-sha stamp reading 4997995022f8e65946f6362b7434685539cc72b7.
    • check:console-sha: "Console dist matches the objectui pin (objectui@4997995022f8)" (exit 0). check:console-injection --require-stamp: "the dist carries this tree's copy, and not the published one" (exit 0). Both also ran green at 483fddb3fc inside the derived union.
    • The CI job itself is not measured here; it is CI's run, and the pin change moves its dist-cache key, so it rebuilds.
  • Derived gates. node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack, run with no paths at 483fddb3fc, derives 126 commands from 23 changed paths against merge base 1eff3224d. All 126 ran.
    • The --ran reconciliation reads "126 derived famil(ies) accounted for — 126 run, 0 NOT-MEASURED (a DERIVED zero — all 126 recorded an exit code and none of them is 3)".
    • Three first refused with exit 3, PREREQUISITE NOT MET, which is not a reading: check:skill-examples, check:i18n and check:dual-build-cjs-loads. All three exit 0 after building their closures: pnpm --filter @objectstack/client-react build, then the CLI closure check:i18n names (Tasks: 59 successful, restored from the turbo cache). check:i18n reads "9 package(s) — all bundles in sync". check:dual-build-cjs-loads reads "107 published require entry point(s) across 66 package(s) load".
    • The derivation at aaa50c66ec warned that the tree was behind origin/main on six gate files. That is why main was merged a second time; the derivation at 483fddb3fc is current and names the same 126 commands.
  • Artifact rosters. The 46 commands the no-path run lists under "Artifact rosters" were run too. 43 exit 0. The three PR-context guards (check-closing-target-claim.mjs, check-partof-closing-keyword.mjs, check-single-claim-paths.mjs) ran with PR_NUMBER=22794, this body as PR_BODY, the branch as PR_HEAD_REF and a read token, as their workflows wire them: all three exit 0.
  • Lint, narrowed and proven. ESLint (--no-inline-config) over the 16 changed TS files gives 0 errors and 0 warnings, 16 files by the --format json count. The population is the eslint.config.mjs block that lints every ts file (line 971). The config never enables type-aware linting (line 328), so this diff cannot move the verdict on any file it does not touch. The repo-wide pnpm lint is CI's run.
  • NOT MEASURED, declared for CI: the seven path-scheduled CI jobs the derivation names (Test Core, Temporal Conformance, Dogfood Regression Gate, Dogfood Verify CLI, Build Core, Build Docs, Console Pin Gate), the four workspace type-check lanes with no local invocation, and the six families that take a value from the workflow.

Round 1, at 8996b566b5 (unchanged files, so still the record for them): position.test.ts 23 tests (19 + 4 new). An ablation through scripts/ablation-replace.mjs reverted the row to type: 'tags' and turned exactly the widget pin and the registry-type pin red (Tests 2 failed | 21 passed (23)); the restore was proven blob-equal to HEAD and re-ran 23 of 23.

Size: 23 files, +372 / -84 (456 changed lines) against 1eff3224d, under the 3,000-line threshold.

Acceptance notes

  • The pin hop moves no published contract (measured above), so it adds no Clause-② line of its own. Both new changesets say Clause-②: no. The console changeset is minor because objectui declared minor for three of its five entries.
  • objectui main is two commits past the pin (9b75509, objectui#5250 slice B; 1d1cfe0, objectui#12106). Neither is needed here.
  • Cloud's own .objectui-sha is untouched; this PR moves only this repository's pin.
  • Writes this round: git push (no force) of three commits; one body and title update and one assignee swap on this PR (zhuangjianguo replaces os-project-manager, mirroring the card), both through scripts/pm/; no label; no MCP write.

Landing round written by domain:spec seat 3, session session_01KNKBCRDJCu5tGy3TEbvtrF; round 1 by seat 1, session session_01S3aAf11JjbW1mSGL1EhfFj.

…n-set registry (ref-multi:permission)

ADR-0131 D4 resolves a reference to a declared item by machine name,
registry-first. The position form's permissionSets row was a free-text
tags box; it now declares widget 'ref-multi:permission', the list form of
the ref:<type> pickers, naming the permission-set registry (metadata type
permission). The row drops type 'tags': an explicit widget outranks type
inference. A pin in position.test.ts reads the served form registry.

Claude-Session: https://claude.ai/code/session_01S3aAf11JjbW1mSGL1EhfFj
Co-authored-by: Claude <noreply@anthropic.com>
@github-actions github-actions Bot added size/s documentation Improvements or additions to documentation tests tooling labels Oct 11, 2026
@github-actions

github-actions Bot commented Oct 11, 2026 •

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 2 package(s): @objectstack/sdui-parser, @objectstack/spec, touching 15 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.

10 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/data-modeling/objects.mdx (via permissionSets (literal, a string literal in sections))
  • content/docs/permissions/authorization.mdx (via permissionSets (literal, a string literal in sections))
  • content/docs/permissions/capabilities.mdx (via permissionSets (literal, a string literal in sections))
  • content/docs/permissions/delegated-administration.mdx (via permissionSets (literal, a string literal in sections))
  • content/docs/permissions/explain.mdx (via permissionSets (literal, a string literal in sections))
  • content/docs/permissions/permission-sets.mdx (via permissionSets (literal, a string literal in sections))
  • content/docs/permissions/positions.mdx (via permissionSets (literal, a string literal in sections))
  • content/docs/permissions/profiles.mdx (via permissionSets (literal, a string literal in sections))
  • content/docs/protocol/objectui/layout-dsl.mdx (via ComponentPropsMap (symbol, a top-level const object))

⛔ 7 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-0.mdx (via permissionSets (literal, a string literal in sections))
  • 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/v17/17-7.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 — 140 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 1eff3224d7e7d28474152f12e01819fa0ab1fb3a → packageMentionDocs.

Which tree this was computed on

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

node scripts/docs-audit/affected-docs.mjs --json 1eff3224d7e7d28474152f12e01819fa0ab1fb3a

⚠️ 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 1eff3224d7e7d28474152f12e01819fa0ab1fb3a → 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

Held in draft on purpose · domain:spec seat 1 (#6017) · session session_01S3aAf11JjbW1mSGL1EhfFj · 2026-10-11T07:09Z

…ui#12136)

Moves the bundled Console's objectui pin from 0df67f237c5a to
4997995022f8e65946f6362b7434685539cc72b7, objectui#12136's merge
(objectui#12126): metadata-admin registers the ref-multi:permission
widget, so the position form's permissionSets row renders a picker of
declared permission sets. It is the nearest objectui main commit that
carries the widget, 7 commits past the old pin (0 merges, 80 paths).

The bump follows the repo's procedure: scripts/bump-objectui.sh writes
the pin and the console changeset; pnpm objectui:build and
node scripts/gen-sdui-manifest-node.mjs re-record the SDUI manifest;
check-sdui-lockstep --update re-records the lockstep; the asserting
objectui pin citations in packages/spec/src are re-measured at the new
pin; gen:docs regenerates the one describe whose sha moved.

sdui.manifest.json is byte-identical (sha256 9d87162a3ef6, 107
components); only its record names the new pin. No key, default, enum
member or export moves: check:generated, check:api-surface and
check:authorable-surface are green on this tree.

Claude-Session: https://claude.ai/code/session_01KNKBCRDJCu5tGy3TEbvtrF
Co-authored-by: Claude <noreply@anthropic.com>
@objectstack-fleet objectstack-fleet Bot changed the title feat(spec): the position form picks permissionSets from the permission-set registry (ref-multi:permission) feat(spec): the position form picks permissionSets from the permission-set registry (ref-multi:permission), with the console pin moved to 4997995022f8 Oct 11, 2026
@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

Landing pre-checks at 483fddb3fc, by the owning seat: all green, queued

domain:spec seat 3 (#18883) · zhuangjianguo · session session_01KNKBCRDJCu5tGy3TEbvtrF · 2026-10-11T14:01Z · holder of claim 6109075588 on #22682.

pr_ready and automerge_enable follow.


Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

3 participants