Skip to content

docs(skills): auth-permissions stops teaching dataSource as the data expression root (objectui#9379) - #9669

Merged
os-zhuang merged 2 commits into
mainfrom
claude/issue-9379-auth-permissions-data-root
Sep 17, 2026
Merged

os-zhuang merged 2 commits into
mainfrom
claude/issue-9379-auth-permissions-data-root

Conversation

@os-try-charles

Copy link
Copy Markdown
Collaborator

Fixes #9379

Governed surface — this PR stays a DRAFT. scripts/check-governed-queue-guard.mjs --test skills/objectui/guides/auth-permissions.md exits 3 and prints: "One governed path governs the WHOLE pull request … Park it as a DRAFT and leave the merge to the maintainer", naming GOVERNED_APPROVERS: os-zhuang, hotlong. No ready-flip, no queue, no auto-merge from this seat.

What is repaired

The 2026-09-13 maintainer ruling on objectui#9308 (option B) stopped SchemaRenderer publishing the injected DataSource adapter as the expression root data. skills/objectui/guides/auth-permissions.md still taught both halves of the retired wiring. The document is what was wrong — the runtime is right — so the guide is moved onto the channel that does publish roots, PredicateScopeProvider, in the same shape PR #9369 used for content/docs/guide/schema-rendering.md and packages/react/README.md.

  • permission flags are published as an ambient scope and read by the names they were published under;
  • the scope table gains a record row (ADR-0089 D3 makes record the runtime-layer row root) and now states that data is a root only when the host publishes one;
  • the trap paragraph is re-derived rather than re-worded (see below).

The premise, checked rather than relayed

packages/react/src/SchemaRenderer.tsx carries the decision in its own words: "data is NOT here, and the absence is the decision (objectui#9308, maintainer ruling 2026-09-13 option B)". Nothing in this PR asks for dataSource to become a real root — that would widen a published surface. Prose only; no package source is touched.

Re-measured on the built evaluator, not remembered

packages/core/dist (built from this branch's base, cf601fff6), over the guide's own gate ${!canDeleteContacts} and its data.-rooted predecessor:

expression scope evaluateCondition evaluateExpression
${!data.canDeleteContacts} {} — no root at all true the source text ${!data.canDeleteContacts}
${!data.canDeleteContacts} { data: {} } — adapter-shaped true true
${!data.canDeleteContacts} { data: { canDeleteContacts: true } } false false
${!canDeleteContacts} { canDeleteContacts: true } — published as a root false false
${!canDeleteContacts} {} true the source text ${!canDeleteContacts}

Two consequences the old paragraph could not state: a bare name does resolve when the host publishes it as a root (so the old "reachable only under the data. root" sentence is now false in its own right), and the predicate layer fails soft to true while the interpolation layer prints the characters you typed. Both are in the new text.

One bounded repair in the same paragraph

The flag example derived its booleans from permissions.check(...), which answers a { allowed, … } object. An object is truthy, so ${!canDeleteContacts} was permanently false and the gate showed the button to every user — the mirror image of the trap the page warns about. The example now publishes permissions.can(...), which answers a boolean, and the guide says why. Without this the repaired example would be untrue on its own terms.

The class, re-derived (⛔ triage's "fourth" is not relayed)

Instrument, run on this branch's base cf601fff6: every tracked skills/**/*.md, content/docs/**/*.md, packages/*/README.md and README.md; every line naming dataSource, judged against a ±4-line window for a teaching token (${data, a data. root, bind, useDataScope, scope) and for a correction token (PredicateScopeProvider, "not an expression root", objectui#9308, "the ADAPTER"). Raw hits were then adjudicated by hand, because the raw signal does not distinguish the class from the unrelated PageComponentSchema.dataSource element-data-source key.

Members of the class (5):

file state
skills/objectui/guides/data-integration.md held by open PR #9378
skills/objectui/guides/schema-expressions.md held by open PR #9378
skills/objectui/rules/protocol.md held by open PR #9378
skills/objectui/guides/auth-permissions.md this PR
skills/objectui/guides/testing.md objectui#9380, held serial — ⛔ not touched

⭐ A sixth candidate, reported and not folded in: skills/objectui/guides/page-builder.md — its integration sequence says "Provide dataSource and contextual data through renderer provider" and every schema example on the page then reads ${data.metrics.activeUsers} / ${data.userRole}. It names no other channel, so a reader wires the retired one. On a governed surface every extra file widens what a human has to approve, so it is left for its own card.

Control, same instrument, same run: content/docs/guide/architecture.md and content/docs/guide/expressions.md were surfaced by the identical dataSource-plus-teaching-window query and both teach the correct root ("SchemaRendererProvider's dataSource is not an expression root"), so the instrument discriminates and the count above is a reading rather than an empty query. Adjudicated not in the class, also by the same run: content/docs/guide/{ci-cd-pipeline,data-source,user-state-persistence}.md, content/docs/rfcs/0001-clipboard-paste.md, packages/{plugin-detail,plugin-list,react}/README.md — every one of those names the adapter's own methods or the per-element dataSource spec key, neither of which is this class.

Gates — each verdict is the gate's own line

gate verdict
node scripts/check-skill-examples.mjs exit 0 — "Every marked skill example holds up against the built types." Marked: 15 ts fence(s) (floor 13), 70 json fence(s) (floor 70); Semantic phase: 15 of 15 ts fence(s) judged, 0 failed. The one tsx fence this PR adds is inside that 15.
node scripts/check-skills-paths.mjs exit 0 — 89/90 stated path(s) resolve across 20 guide file(s); 1 baselined
node scripts/check-skill-eval-tokens.mjs exit 0 — "Every must_contain token is taught by its own skill bundle."
node scripts/check-changeset-presence.mjs exit 0 — "No source or published contract of a released package changed in this range, so no changeset is owed." ⇒ nothing is owed; no label is involved in that verdict.
node scripts/check-new-cross-file-line-citations.mjs exit 0 — 0 new citation(s), enforcement report-only
pnpm check:control-bytes exit 0 — scanned 7788 tracked text file(s); plus a direct grep -naP '[\x00-\x08\x0b\x0c\x0e-\x1f\x7f]' over the changed file, exit 1 (no match)
pnpm exec vitest run packages/components/src/__tests__/skill-guide-provider-envelope.test.tsx scripts/__tests__/check-skill-eval-tokens.test.ts scripts/__tests__/check-skill-examples.test.ts scripts/__tests__/check-skills-paths.test.ts exit 0 — Test Files 4 passed (4), Tests 201 passed (201)

The four test files are the ones node scripts/markdown-test-inputs.mjs --list names as readers of skills/objectui/** and .claude/skills/**. ESLint is not owed by this diff: eslint.config.js declares no markdown surface, and pnpm lint is CI's repo-wide run either way. Build: turbo run build --concurrency=2 $(node scripts/check-skill-examples.mjs --build-filter)29 successful, 29 total — so the fences above were judged against built dist/*.d.ts.

Governed-surface size readings

reading before after net
skills/objectui/guides/auth-permissions.md 367 lines 403 lines +36
whole published catalogue (skills/**/*.md) 4604 lines 4640 lines +36

One file, one section. The added lines are the measured verdict table, the record row, and one tsx fence that the examples gate now type-checks; a second scope fence was drafted and dropped as duplicate teaching.

Acceptance notes

  • noted, not filed: skills/objectui/guides/auth-permissions.md's provider-composition example still nests only SchemaRendererProvider, with no PredicateScopeProvider beside it. It is not false — the adapter belongs there — but a reader copying it gets no scope. Carrier: whoever takes the page-builder.md card above, which needs the same nesting shown once.

维护者速读(草稿)

改了什么 —— 只改一份已发布技能指南 skills/objectui/guides/auth-permissions.md 的「表达式可见性」与「表达式作用域」两节。把权限标志的发布通道从已退休的 SchemaRendererProvider dataSource 改成 PredicateScopeProvider,作用域表补上 record 行,并按实测重写那段陷阱说明。⛔ 不动任何运行时代码。

为什么改 —— 2026-09-13 您对 objectui#9308 的裁决(选项 B)已经让渲染器不再把注入的适配器发布为表达式根 data;这份指南两半都还在教。它按人读文档的速度持续制造错写法,并且它 推荐 的那个写法今天同样失败,失败方式还和它自己警告的那个不同。

风险与代价(含回滚) —— 纯文档,风险面是「教得对不对」,不是运行时。三道技能门禁(examples / paths / eval-tokens)各自的判定行都在上表,均为 exit 0;changeset 门禁自己判定无需 changeset。回滚 = revert 这一个 commit,无迁移、无发版影响。⚠️ 顺带修掉同段里一处独立错误:示例用 check(...)(返回对象,恒真)当布尔标志,改成 can(...);不改它,新示例自己就是假的。

席位意见 ——

你要做的 —— 这是受管面:PR 保持 draft,合并权在您。需要 os-zhuang / hotlong 其一的 APPROVED review,或由您直接人工合并(人工合并本身即评审记录)。另外请裁决上面那个第六个候选文件 page-builder.md 是否单开一卡 —— 本 PR 刻意没有把它折进来。


Generated by Claude Code

…ta` expression root (objectui#9379)

The 2026-09-13 maintainer ruling on objectui#9308 (option B) stopped
`SchemaRenderer` publishing the injected `DataSource` adapter as the
expression root `data`. This guide still taught both halves: flags
derived "in the dataSource object", a scope table sourcing `data` from
"the `dataSource` passed to `SchemaRendererProvider`", and a trap
paragraph whose recommended spelling is the one that now fails.

The document is what is wrong here, not the runtime: the guide is moved
onto the channel that does publish roots, `PredicateScopeProvider`, in
the same shape PR #9369 used for `content/docs/guide/schema-rendering.md`
and `packages/react/README.md`.

- permission flags are published as an ambient scope and read by the
  names they were published under;
- the scope table gains a `record` row (ADR-0089 D3 makes `record` the
  runtime-layer row root) and states that `data` is a root only when the
  host publishes one;
- the trap paragraph is re-measured on the built evaluator: a name
  nothing published makes a predicate fail soft to `true` (the button is
  hidden for every user), while a text key hands back its own source
  characters.

One bounded repair inside the same paragraph: the flag example derived
its booleans from `check(...)`, which answers a `{ allowed, … }` object.
An object is truthy, so `${!flag}` was permanently `false` and the gate
showed the button to everyone. The example now publishes `can(...)`,
which answers a boolean.

Co-authored-by: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015h79niBMyoB1xcaQje3uiz
…`dist` path (objectui#9379)

`Skill Guide Path Check` went red on the first push of this branch while
`node scripts/check-skills-paths.mjs` was green locally, and the gap is
the gate's own premise: its workflow needs "no install and no build — a
checkout plus one `node` call", and it resolves every `packages/…` code
span with `existsSync`. The new measurement paragraph cited
`packages/core/dist`, which exists only in a tree someone has built — so
the local run resolved it and the CI checkout could not.

The citation now names the package instead of the build output. The
gate's own count moves 89 -> 88 stated paths, which is the one token this
commit removes.

Co-authored-by: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015h79niBMyoB1xcaQje3uiz
@os-zhuang
os-zhuang marked this pull request as ready for review September 17, 2026 11:12
@os-zhuang
os-zhuang added this pull request to the merge queue Sep 17, 2026
Merged via the queue into main with commit 61b7553 Sep 17, 2026
34 checks passed
@os-zhuang
os-zhuang deleted the claude/issue-9379-auth-permissions-data-root branch September 17, 2026 11:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

finding(skills): auth-permissions.md still teaches dataSource as the data expression root — a fourth file the objectui#9370 census missed

3 participants