Repository navigation
docs(skills): the schema-expressions guide says a faulted or stored-blank field rule refuses the submit (objectui#11256) - #11419
Conversation
…eld rule refuses the submit (objectui#11256) The field-level conditional rules passage of `skills/objectui/guides/schema-expressions.md` still taught that a broken predicate "never blocks submit". Since objectui#8069 (ADR-0137 D2) a faulted or stored-blank field rule refuses the submit, naming the field and the rule, while render stays fail-open (D3). The paragraph beginning "Renderer-side, and only here" now says so, keeps "never a security boundary on the client", and adds that a blank triad key is refused at authoring and a blank gate stays "no gate" with a diagnostic. Docs only; an empty-frontmatter changeset declares no release. Claude-Session: https://claude.ai/code/session_01FNKm1SmPpuJASnbjxWGtsJ Co-authored-by: Claude <noreply@anthropic.com>
…hema-expressions-field-rule-submit-refusal
|
changeset-claim-re-read
|
Contract reviewServed-tier: Face: governed rule text ( ① Derived judgments
② Semver levelDocs-only in a governed surface; no package ③ Boundary flags
Implemented-by: VERDICT: PASS |
维护者速读(终稿)席位(skills 席 1, 改了什么。 只改 为什么改。 PR objectui#11233(2026-09-30 合并)落地了 ADR-0137 D2:提交被拒并点名字段与规则。这份发布给作者(含 AI)的技能仍教相反的行为,照它写元数据的 agent 不会预期提交被拒。 风险与代价(含回滚)。 纯文档改动,无代码、无发布包源码变动。风险只在措辞是否精确:席位逐句对照 ADR-0137 D1–D4 原文;新增的「客户端判 席位意见。 建议批准。席内达档契约复核 PASS(见本 PR 评论)。同文件另一处(「Which components read 你要做的(一个动作)。 在本 PR 上留一条 APPROVED review( |
Fixes #11256
Clause-②: no
Docs only, on the governed
skills/**surface (Tier H: this PR stays a draft until an authorized APPROVED review; the seat lands it). One paragraph ofskills/objectui/guides/schema-expressions.mdchanges — the one beginning "Renderer-side, and only here" in the section "Field-level conditional rules" — plus one empty-frontmatter changeset. No other passage is edited: the sibling card objectui#11414's region ("Which components readbind") is untouched, andorigin/main(549aaa83) was merged into the branch before this PR opened, without conflict. Dispatched work (claim on the card, sessionhttps://claude.ai/code/session_01FNKm1SmPpuJASnbjxWGtsJ); draft is the delivered state.What the passage said, and what it says now
Before, on
mainat0858267e: "Evaluation is fail-open -- a broken predicate never hides content, never blocks submit and never locks a field -- sovisibleWhenis never a security boundary on the client."Now, restated from ADR-0137 (objectstack
docs/adr/0137-predicate-fault-semantics-are-contract.md, Accepted), as PR objectui#11233 landed it for objectui#8069:visibleWhen; a faultedrequiredWhen/readonlyWhenis the server's refusal, shown beside the input.visibleWhenis still never a security boundary on the client; the server is the authority.The paragraph's first three lines (reactive re-evaluation via
resolveFieldRuleState; the staticrequired: true/readonly: truefloor) are unchanged, and nothing was re-wrapped.Mechanism assumptions, measured on the tree rather than taken from the card
origin/mainwas byte-identical to the card's quotation (read at0858267ebefore editing).af9e9572, 2026-09-30) lands the D2 refusal on three submit paths —form.tsx(handleSubmit, before react-hook-form validation), the consoleFormPage(findSubmitRefusals) andWizardForm(gateFinalSubmit) — each readingfaults.visibleWhenoffresolveFieldRuleState. The refusal text is theform.visibleWhenFaultedkey inpackages/i18n/src/locales/en.ts: "Can't submit: the visibleWhen rule of {{fields}} could not be evaluated. The rule must be fixed before this form can be submitted." Pins:visibleWhen-fault-refuses-submit-8069.test.tsx,FormPage.visibleWhenFault-8069.test.tsx,wizardVisibleWhenFault-8069.test.tsx. The client refuses onlyvisibleWhen; a faultedrequiredWhen/readonlyWhenis let through to the server, whose D2 envelope (VALIDATION_FAILED,code: 'rule_violation',constraint.reason: 'unevaluable',constraint.rulenaming the slot) lands beside the field — the end-to-end server pin in the same components test file. That is why the new text says "the client judgesvisibleWhen, the server the other two" rather than "the client refuses every field rule".packages/types/src/__tests__/base-schema-predicate-envelope-7530.test.ts, describeFormFieldSchema.%s refuses a blank predicate (objectui#8069, ADR-0137 D1), which asserts the spec's ownEVALUATED_EXPRESSION_SOURCE_REQUIREDmessage at the key. "A blank gate stays no gate, with a diagnostic": pinned bypackages/core/src/evaluator/__tests__/fieldRuleFaults-8069.test.ts, describeADR-0137 D4 — silencer 2: hasDeclaredPredicate folding a blank gate(the[blank]report), implemented byreportBlankGateinpackages/core/src/evaluator/declaredPredicate.ts. Both verified on the tree; nothing is written as unverified.visibleWhenfails open. Do not generalise from one to another." (under "CEL predicates over a row record") describes the render-side direction (D3) and is still true; it is not edited (see Acceptance notes).Line readings (lines; objectui has no token ratchet)
skills/objectui/guides/schema-expressions.md: 635 before → 638 after, net +3 (the budget's ceiling). The paragraph goes from 6 to 9 lines; no line exceeds 80 columns. The three lines buy the D2 / D1 / D4 content; none was bought by re-wrapping.skills/objectui/**/*.md(16 files): 4808 → 4811.skills/*/SKILL.mdsummed (one file,skills/objectui/SKILL.md): 142 → 142.wc -lovergit ls-tree -r --name-onlyenumerations oforigin/main(549aaa83) and this head (d4de5a59).Gates — exit codes captured before any pipe; verdict lines quoted; run at the merged head
d4de5a59unless notednode scripts/check-skills-paths.mjs→ EXIT 0: "check-skills-paths: OK (89/90 stated path(s) resolve across 20 guide file(s); 1 baselined)."node scripts/check-skill-eval-tokens.mjs --self-test→ EXIT 0 (29 cases);node scripts/check-skill-eval-tokens.mjs→ EXIT 0: "Every must_contain token is taught by its own skill bundle."node scripts/check-skill-examples.mjs --build-filter→ the 12--filter=…words the gate derives;pnpm exec turbo run build FILTERS --concurrency=2behindscripts/pm/os-verify-lock.sh(slotissue-11256; "VERDICT command-exit 0 · held the lock 86s · waited 138s"); turbo reported FULL TURBO — 29 of 29 tasks replayed from cache (the sibling worktree's identical-input build), withdist/present in this worktree; then--self-test→ EXIT 0 (60 cases) and the gate → EXIT 0: "Semantic phase: 18 of 18 ts fence(s) judged, 0 failed. JSON phase: 70 fence(s) parsed, 0 failed." Run atcbf60c87; the merge that followed changed nothing underskills/orpackages/(git diff --name-only cbf60c87 d4de5a59 -- skills packagesis empty), so the gate's inputs are byte-identical at the head.scripts/markdown-test-inputs.mjslists as reading this guide):pnpm exec vitest run packages/types/src/__tests__/list-bind-only-11405.test.ts packages/components/src/__tests__/skill-guide-data-table-binding.test.tsx→ "Test Files 2 passed (2) · Tests 28 passed (28)" (same locked run, atcbf60c87).node scripts/check-control-bytes.mjs→ EXIT 0 (9936 tracked text files); agrep -naPcontrol-byte scan of the two changed files finds none.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." The empty-frontmatter changeset is the explicit declaration anyway; noskip-changesetlabel (objectui has no reader for it).node scripts/check-changeset-no-major.mjs→ EXIT 0;check-changeset-claims.mjs→ EXIT 0;check-changeset-overwrite.mjs→ EXIT 0: "No pre-existing changeset was modified or deleted."CITATION_GATE_BASE=origin/main node scripts/check-new-cross-file-line-citations.mjs→ "VERDICT new-cross-file-line-citations: 0 new citation(s), enforcement report-only, exit 0".node scripts/check-governed-queue-guard.mjs --test PATHS→ EXIT 3 GOVERNED (skills-catalog), the expected verdict: draft until an authorized APPROVED review.lint.ymlandci.yml: the diff is.mdplus.changeset/**only, so their "Decide whether this change needs a full run" step readsshould_run=falseand both report without running the expensive steps. NOT MEASURED locally, by design:pnpm lint(repo-wide, CI's run; no lint input is in this diff).Deviations
pnpm installin the fresh worktree was refused under the repo'sengine-strict=true:jsdom@30.0.1declares node^22.22.2 || ^24.15.0 || 26 and aboveand the container's/opt/node22is v22.22.0. Everything above ran on Node v22.22.2 downloaded from nodejs.org into this session's scratchpad (SHA256 verified againstSHASUMS256.txt) and prepended to PATH for this worktree's commands only; the shared toolchain is untouched. CI'ssetup-node22.xresolves to a current 22 release, so CI is unaffected.Acceptance notes (observations, not filed)
visibleWhenfails open. Do not generalise from one to another." is render-side (D3) and remains true. With the submit refusal now stated two paragraphs above it, a hurried reader could take "fails open" as the whole story; the bullet's own topic is failure DIRECTION at render across surfaces, so it is left as is, as the card asks. carrier: none — noted, not filed.git grep -n 'never blocks submit' origin/mainreturns nothing: objectui#11233 had already correctedcontent/docs/guide/metadata-diagnostics.mdandcontent/docs/plugins/plugin-form.mdx, and this passage was the last shipped sentence teaching the old behaviour.维护者速读(草稿)
改了什么:只改了已发布技能
skills/objectui/guides/schema-expressions.md中「字段级条件规则」一节以「Renderer-side, and only here」开头的那一段,外加一个空 frontmatter 的 changeset。旧文说「坏掉的谓词永不阻止提交」;新文按 ADR-0137 重述:渲染期照常画出字段(不隐藏、不锁定),提交期求值失败或存储为空白的字段规则拒绝这次提交并点名字段与规则(visibleWhen由客户端判,requiredWhen/readonlyWhen由服务端判),空白三元键在编写期被拒,空白 gate 视为无 gate 并出一次诊断;「不是客户端安全边界、服务端仍是权威」保留。净增 3 行。为什么改:PR objectui#11233(objectui#8069)已于 2026-09-30 把提交期拒绝落到三条提交路径,这份技能文档却还在教相反的行为;AI 按这份指南写元数据,会不预期提交被拒。
风险与代价(含回滚):纯文档,不发版(changeset 为空 frontmatter);风险只在措辞是否准确,每一句都对应树上的实现与 pin 测试(见上文)。回滚 = revert 本 PR。
席位意见:(留空)
你要做的:确认措辞后留下 APPROVED review;落地由席位执行。
Generated by Claude Code