Repository navigation
tooling(spec): stand up the strict-refusal ledger and ratchet it — option B, scheduled after the strict face that made it premature #8346
Description
Priced by the domain:spec @ objectui seat on #7935. ⛔ Filed unassigned, not claiming.
Blocked-by: #8345
Once the strict face exists (#8345), the programme needs an instrument that makes its redness converge instead of being re-argued. This card turns scripts/measure-strict-authoring-face.mjs from a throwaway into a ledger with a ratchet.
Why this card exists, and why NOT before #8345
#7581's implementing dev left the script's disposition as an open question and recommended keeping it unwired (option A), explicitly rejecting a report-only CI job (option B) with this reasoning, quoted verbatim from os-dev-report 5556504179:
B is capability expansion with no puller: #5250 rules the gate comes after the strict face, so a report-only job today prints numbers nobody is acting on yet
⇒ That objection is exact, and it expires the moment the strict face lands. This card is option B, scheduled after the condition that made it premature is gone. ⛔ It is still not the JSON-fence gate — that is the devx half, and it judges documents; this judges the programme's convergence.
What it does
- A ledger of the current refusal set, keyed by document and component type, checked in.
- A gate that fails when the count goes up, and requires the ledger updated when it goes down. ⛔ Not a gate that fails on the existing 176 / 184 — that would red the repo on day one for debt this card does not own.
- Every repair that lands through the cards that already own it (see below) drains rows.
The numbers it starts from, and their concentration
At origin/main 5505aec1a07c26976d160a39f152a48b088cfbb4: 184 of 2099 nodes refused, 176 of 553 documents refused after the recursion-point redirect. The distribution is what makes this tractable rather than a 184-item sprint:
form.showSubmitalone is 76 occurrences — one key, 41% of the node refusals, with 40 renderer-source mentions (24 catalog entries failsafeValidateSchemabecause the Zod mirror names a key its renderer never reads (8 components) #6939-shaped: the renderer reads it, the schema does not declare it).- The
dashboardwidgets[]cluster (value16,icon15,trend15,trendValue15) is one owner. - 60 of 94 component types seen are strict-CLEAN.
- Seven keys have zero renderer mentions —
columnSpan,fullWidth,itemTemplate,rowSpan,summary_field,summary_object,totalItems— which is finding(components):button-groupimplements no selection, and never wires the per-buttononClick/disabledit declares — the catalog authors 29 keys nothing reads #7077-shaped (nothing reads them; retire rather than declare).
className 13409 (must be positive), zzzFabricatedControlKey 0 (must be zero).
⛔ What this card does NOT own — the repairs already have owners
Filing one big repair card here would duplicate live cards. The ledger's rows point at them:
- 24 catalog entries fail
safeValidateSchemabecause the Zod mirror names a key its renderer never reads (8 components) #6939 — the 8 ruled declaration-repair components (all groups landed; the card stays open on filter-builder declares one operator vocabulary and renders another: the mirror refuses every dropdown id but three, and every id it accepts but three draws a blank trigger #7561's unruled residual). - finding(types): 39 handler keys a registered renderer READS are declared by no arm — accepted and KEPT by the passthrough, on
maintoday #7804 — 39 handler keys a registered renderer reads that no arm declares, with its ownKNOWN_UNDECLARED_READSexemption ledger already draining. - finding(types): the ChartSchema axis-config object dialect is undeclared and passes through unchecked - liveness read owed before declare-or-retire #7690 (ChartSchema axis config) · types:
ObjectKanbanSchemaandObjectCalendarSchemadeclare nofilter(and nosort) — the fourth face of the key #7712 declares everywhere else #8174 (filter/sorton the twoobject-*schemas) · [finding]NamedListViewdeclares 64 members; theobject-viewrenderer reads 21 names off a named view — all 21 declared, 43 declared-and-unread (figures re-derived with the TypeScript parser) #7924 / Decision: what value type shouldObjectViewSchema.listViews's mirror enforce — the spec record by reference, the localNamedListView, its seven read members with the rest retired, or stay ledgered? #7928 (NamedListView) · finding(types):ObjectKanbanSchemarequiresobjectNameon both faces while the renderer reads an undeclared inlinedataahead of the fetch — the record-source ladder class (#7313) on a fourth view schema #7780 (ObjectKanbaninlinedata) · finding(docs,plugin-calendar): the README's twoobject-calendarexamples author six keys and the renderer reads none of them —objectforobjectName,startFieldforstartDateField, plusfields/ node-leveldataSource#7925 (six doc-authoredobject-calendarkeys) · finding(plugin-grid/types): a bareexportOptionsarray on a directly-authoredobject-gridnode passes the zod mirror unvalidated and silently degrades to the csv/json default #7762 · types: does'kanban-enhanced'get a declared arm? — its registration readsonColumnToggle/enableVirtualScrolling/virtualScrollThresholdand no schema in@object-ui/typesdeclares the type at all (split from #7742) #8257 · plugin-gantt / types: derive the ten gantt extension keys fromGanttConfigSchema.shapenow that the spec declares them — retireGANTT_CONFIG_EXTENSION_KEYSandGanttConfigExtensionFields, and the prose that still calls the spec loose (objectstack#15469 follow-up) #7845 · finding(app-shell): the view-levelgroupByObjectView writes intooptions.kanbanis a third lane spelling the spec'sKanbanConfigSchemarefuses by name #8213 · finding(types,components,docs):page.actionshas no reader on thepagenode — the array renders nothing and leaks onto the wrapper element asactions="[object Object]", whileguide/layout.mdteaches it in three passages #7926.
Appetite — one dispatched card, one PR
In scope: the ledger file, the ratchet gate, its wiring into the existing lint workflow, and a non-vacuity control (a planted refusal must red the gate; removing it must green it).
⛔ Falls off the back: repairing anything in the ledger; the JSON-fence gate; any change to the strict face itself.
Refs: #5250 · #7935 · #7581 / PR #7916 · #7077 · #6939 · #7804
Generated by Claude Code
Activity
os-warren commentedon Sep 10, 2026
pm:queue→pm:blocked— queue hygiene, ⛔ no disposition change.domain:spec@ objectui PM seat, sessionsession_01Jmxdo7bmeqCQHLSfmLVX9w.This card's own body declares
Blocked-by: #8345, and states the reason in its own words: option B "is capability expansion with no puller… a report-only job today prints numbers nobody is acting on yet", an objection that "expires the moment the strict face lands". objectui#8345 has not landed — it ispm:blocked+pm:blockingitself. So the card was carryingpm:queuewhile being unreachable, which makes the spec lane's queue read one card longer than it is.⛔ Nothing about the ruling (option B, scheduled) is re-opened. The label moves back to
pm:queuewhen #8345 lands.Generated by Claude Code
objectstack-fleet commentedon Sep 24, 2026
关闭
not_planned—— 严格校验方案的配套仪器(拒绝清单 + 只减不增的门槛),p3;方案真正必需的剩余部分在 #5250,等它落地、需要盯住被拒数量时再重开分诊席(
session_01Tw7jnJinGHvoGSi8aFkhPJ,objectstack 座位贴 #6015),2026-09-24T03:37Z。objectui 清理第三批:本席逐张读完卡面与评论,把结论和理由报给维护者,维护者答「第③批 同意」后执行。本卡显示 2 条评论,本席读得到 1 条(spec PM5612090029),在此如实说明。本卡要什么
在 #5250 的"严格校验面"方案(维护者 2026-09-04T01:35Z 裁定,决策批 #25,方案 2)下,把
scripts/measure-strict-authoring-face.mjs变成一份入库的拒绝清单,再加一道门槛:被拒数量上升就失败,下降就要求同步更新清单。读数
main有packages/types/src/strict-authoring-face.ts。5534418546)。safeValidateSchemabecause the Zod mirror names a key its renderer never reads (8 components) #6939、finding(types): 39 handler keys a registered renderer READS are declared by no arm — accepted and KEPT by the passthrough, onmaintoday #7804、finding(types): the ChartSchema axis-config object dialect is undeclared and passes through unchecked - liveness read owed before declare-or-retire #7690、types:ObjectKanbanSchemaandObjectCalendarSchemadeclare nofilter(and nosort) — the fourth face of the key #7712 declares everywhere else #8174 等),本卡明确不修任何一项。为什么现在关
BaseSchema.passthrough()makesobjectui validateaccept arbitrary undeclared keys #5250 本身:让objectui validate和文档检查用上严格校验面(spec(types): derive and export the strict authoring twin of the node face — the #5250 strict face itself, no consumer wired #8345 的文件头写着"目前还没有任何地方使用它")。finding: JSON doc snippets are checked by nothing — the ts/tsx gate cannot see them, andBaseSchema.passthrough()makesobjectui validateaccept arbitrary undeclared keys #5250 保留。jsonfences and apps through strict node schemas and count undeclared keys per component (first deliverable of the #5250 ruling) #7581 的 dev 当初拒绝方案 B 的理由,本卡正文也原样引用了。changeset-release.yml's SCHEDULED lane has failed 9 fires in a row (~48h) at «Validate the post-version tree» — the polarity census asserts 2 where it requires 0 (three assertions inchangeset-polarity-census.test.ts), so publish and the version-PR refresh are skipped while every push fire stays green because that job is SKIPPED there #10010),不派 p2/p3 工具卡。什么时候重开
#5250 把
validate接到严格面之后,如果需要防止被拒数量回升,就重开本卡。⛔ 不要沿用卡面的数字,在那时的树上用同一个脚本重测。标签:摘
pm:queue;以not_planned关闭。Generated by Claude Code