Repository navigation
fix(types): walk set / map / prefault / promise in the strict authoring face, and report what the walker still has no arm for - #10139
Conversation
… authoring face, and report what the walker still has no arm for The walker's `default:` arm treated every def kind it had no arm for as a leaf, so the four schema-bearing wrappers fell through it in silence: the object inside stayed open and nothing reached `onOpaqueShape`. That is the MINOR remainder the director's review left on objectui#8345 — "the reporter's contract is every unclosed shape is reported". - `set` (element under `valueType`) and `map` (BOTH `keyType` and `valueType`) get arms of their own; `prefault` and `promise` join the `innerType` group. - The `default:` arm now reports a def that still carries a schema under its own def type instead of handing it back; on zod 4.4.3 that is only `success`, which can never refuse, so it is reported rather than walked. - Pins: an invented key inside each of the four wrappers is refused and named (promise via async parse, as zod requires); an opaque node inside each is still reported with its trail; the four kinds are counted at 0 on the forced published face, so the synthetic controls are the coverage; `success` is reported and a row of leaves is not. `refusedKeys` learns zod's `invalid_key` / `invalid_element` wrapping for Map entries with object keys. Nothing on the published face moves: none of the four kinds occurs on `AnyComponentSchema`, so both published twins accept and refuse exactly what they did, and the tolerant face is untouched. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QVJUngS9FKfuyQ9NFR2Nbn
✅ Console Performance Budget
The eager closure is every chunk the entry reaches through static imports — what the browser fetches and parses before the app renders. The entry chunk on its own is a small fraction of it. 📦 Bundle Size Report
Size Limits
|
…e kind the strict walker now names
The matrix pin (objectui#9692) requires every node kind either walker NAMES to
be built by MATRIX, so the null sweep visits it; the strict authoring face now
names `promise`, and MATRIX built `map`, `set` and `prefault` but never
`promise` because no walker had named it before. One row, per the pin's own
message ("add one entry per kind rather than narrowing this assertion").
Declared surface amendment for objectui#8345 (option A, card comment
5749989361): this file, this one row, nothing else in it.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QVJUngS9FKfuyQ9NFR2Nbn
|
changeset-claim-re-read
|
✅ Console Performance Budget
The eager closure is every chunk the entry reaches through static imports — what the browser fetches and parses before the app renders. The entry chunk on its own is a small fraction of it. 📦 Bundle Size Report
Size Limits
|
✅ Console Performance Budget
The eager closure is every chunk the entry reaches through static imports — what the browser fetches and parses before the app renders. The entry chunk on its own is a small fraction of it. 📦 Bundle Size Report
Size Limits
|
|
| Step | Outcome |
|---|---|
| Build packages | success |
| Check console performance budget | failure |
Which half objected:
| Eager-closure half | Verdict |
|---|---|
| Aggregate closure ceiling | ✅ pass |
| Per-chunk ceilings | ✅ pass |
| Ceiling sensitivity (headroom) | |
| Ceiling freshness (checkout vs. base branch) | ✅ pass |
⚠️ A broken gauge half is a verdict about the ceiling, not about the bundle: that line has drifted out of range of the regression it exists to catch, or the report behind it cannot be trusted. It does not say anything grew. TheCheck console performance budgetstep log carries the ceiling and the number it was compared against.
Reason: The entry chunk measured 146.9 KB, but the eager-closure half of this gate returned no trustworthy VERDICT: the report could not be read, a ceiling has drifted out of range of the regression it must catch, or (objectui#6245) a ceiling was replaced on the base branch after this checkout was made. The step log says which. This is not a passing budget — and it is not a size regression either.
See the workflow run for details.
📦 Bundle Size Report
| Package | Size | Gzipped |
|---|---|---|
| app-shell (consoleActionDispatch.js) | 0.20KB | 0.19KB |
| app-shell (index.js) | 16.68KB | 6.20KB |
| app-shell (runtime-config.js) | 20.68KB | 7.36KB |
| app-shell (types.js) | 0.01KB | 0.04KB |
| app-shell (urlParams.js) | 10.06KB | 3.86KB |
| auth (ActiveOrganizationStorage.js) | 25.05KB | 9.16KB |
| auth (AuthContext.js) | 0.31KB | 0.24KB |
| auth (AuthGuard.js) | 2.07KB | 1.00KB |
| auth (AuthProvider.js) | 40.18KB | 10.59KB |
| auth (AuthShell.js) | 3.49KB | 1.40KB |
| auth (ForgotPasswordForm.js) | 12.21KB | 3.45KB |
| auth (LoginForm.js) | 18.15KB | 5.39KB |
| auth (PreviewBanner.js) | 0.90KB | 0.50KB |
| auth (RegisterForm.js) | 6.65KB | 2.22KB |
| auth (SocialSignInButtons.js) | 9.61KB | 3.89KB |
| auth (UserMenu.js) | 3.41KB | 1.23KB |
| auth (auth-gate-events.js) | 1.29KB | 0.66KB |
| auth (authStyles.js) | 5.04KB | 1.72KB |
| auth (createAuthClient.js) | 40.21KB | 10.80KB |
| auth (createAuthenticatedFetch.js) | 8.46KB | 3.43KB |
| auth (index.js) | 3.19KB | 1.44KB |
| auth (invitation-status.js) | 1.22KB | 0.70KB |
| auth (org-roles.js) | 6.66KB | 2.78KB |
| auth (phone-identifier.js) | 1.11KB | 0.66KB |
| auth (types.js) | 0.59KB | 0.35KB |
| auth (useAuth.js) | 5.30KB | 1.02KB |
| auth (useWorkspaceAdminStatus.js) | 11.08KB | 4.58KB |
| collaboration (CommentThread.js) | 26.08KB | 7.56KB |
| collaboration (LiveCursors.js) | 3.17KB | 1.27KB |
| collaboration (PresenceAvatars.js) | 6.49KB | 2.64KB |
| collaboration (PresenceProvider.js) | 2.79KB | 1.13KB |
| collaboration (index.js) | 1.68KB | 0.73KB |
| collaboration (useCollaborationTranslation.js) | 6.05KB | 2.52KB |
| collaboration (useCommentSearch.js) | 1.98KB | 0.88KB |
| collaboration (useConflictResolution.js) | 7.75KB | 1.86KB |
| collaboration (useMentionNotifications.js) | 1.81KB | 0.68KB |
| collaboration (usePresence.js) | 6.33KB | 1.84KB |
| collaboration (useRealtimeSubscription.js) | 7.91KB | 2.01KB |
| components (index.js) | 545.92KB | 130.72KB |
| core (index.js) | 8.94KB | 3.59KB |
| create-plugin (index.js) | 27.94KB | 9.51KB |
| data-objectstack (index.js) | 221.99KB | 61.72KB |
| fields (index.js) | 251.81KB | 63.47KB |
| i18n (LocalizationContext.js) | 1.76KB | 0.96KB |
| i18n (builtinAggregateLabels.js) | 0.86KB | 0.49KB |
| i18n (currency.js) | 1.22KB | 0.64KB |
| i18n (fallbackInterpolation.js) | 6.25KB | 2.77KB |
| i18n (i18n.js) | 8.87KB | 3.64KB |
| i18n (index.js) | 5.22KB | 2.26KB |
| i18n (pickLocalized.js) | 9.86KB | 3.95KB |
| i18n (provider.js) | 32.15KB | 10.49KB |
| i18n (useDisplayLocale.js) | 2.85KB | 1.45KB |
| i18n (useObjectLabel.js) | 34.34KB | 9.17KB |
| i18n (useSafeTranslation.js) | 5.60KB | 2.33KB |
| layout (index.js) | 38.90KB | 10.97KB |
| mobile (MobileProvider.js) | 0.92KB | 0.49KB |
| mobile (ResponsiveContainer.js) | 0.94KB | 0.38KB |
| mobile (breakpoints.js) | 1.51KB | 0.70KB |
| mobile (createOfflineDataSource.js) | 5.61KB | 1.75KB |
| mobile (index.js) | 1.99KB | 0.87KB |
| mobile (offlineQueue.js) | 3.91KB | 1.35KB |
| mobile (pwa.js) | 0.97KB | 0.49KB |
| mobile (serviceWorker.js) | 1.48KB | 0.62KB |
| mobile (serviceWorkerSource.js) | 3.41KB | 1.48KB |
| mobile (useBreakpoint.js) | 1.54KB | 0.65KB |
| mobile (useGesture.js) | 6.96KB | 1.98KB |
| mobile (useOfflineSync.js) | 1.99KB | 0.72KB |
| mobile (usePullToRefresh.js) | 2.53KB | 0.85KB |
| mobile (useResponsive.js) | 0.72KB | 0.42KB |
| mobile (useSpecGesture.js) | 5.52KB | 2.10KB |
| mobile (useTouchTarget.js) | 1.01KB | 0.54KB |
| permissions (MePermissionsProvider.js) | 13.52KB | 4.88KB |
| permissions (PermissionContext.js) | 0.31KB | 0.25KB |
| permissions (PermissionGuard.js) | 0.89KB | 0.45KB |
| permissions (PermissionProvider.js) | 6.24KB | 2.16KB |
| permissions (discardProofCache.js) | 1.04KB | 0.55KB |
| permissions (evaluator.js) | 8.39KB | 3.10KB |
| permissions (index.js) | 0.93KB | 0.41KB |
| permissions (store.js) | 0.91KB | 0.42KB |
| permissions (useFieldPermissions.js) | 1.28KB | 0.53KB |
| permissions (usePermissions.js) | 4.83KB | 2.27KB |
| plugin-ai (index.js) | 14.81KB | 3.63KB |
| plugin-calendar (index.js) | 51.08KB | 14.50KB |
| plugin-charts (index.js) | 71.73KB | 20.08KB |
| plugin-chatbot (index.js) | 198.20KB | 47.14KB |
| plugin-dashboard (index.js) | 132.96KB | 35.17KB |
| plugin-designer (index.js) | 215.94KB | 44.33KB |
| plugin-detail (index.js) | 255.17KB | 66.48KB |
| plugin-editor (index.js) | 2.23KB | 1.05KB |
| plugin-form (index.js) | 139.56KB | 35.40KB |
| plugin-gantt (index.js) | 167.99KB | 41.37KB |
| plugin-grid (index.js) | 213.40KB | 58.19KB |
| plugin-kanban (index.js) | 48.71KB | 15.17KB |
| plugin-list (index.js) | 113.53KB | 27.99KB |
| plugin-map (index.js) | 21.48KB | 6.99KB |
| plugin-markdown (index.js) | 13.88KB | 4.80KB |
| plugin-report (index.js) | 43.49KB | 11.97KB |
| plugin-timeline (index.js) | 30.68KB | 8.95KB |
| plugin-tree (index.js) | 10.58KB | 3.72KB |
| plugin-view (index.js) | 85.18KB | 21.05KB |
| providers (DataSourceProvider.js) | 0.75KB | 0.39KB |
| providers (MetadataProvider.js) | 1.37KB | 0.59KB |
| providers (ThemeProvider.js) | 1.90KB | 0.85KB |
| providers (UploadProvider.js) | 11.66KB | 3.50KB |
| providers (index.js) | 0.45KB | 0.23KB |
| providers (types.js) | 0.01KB | 0.04KB |
| react-runtime (index.js) | 5.62KB | 2.34KB |
| react (LazyPluginLoader.js) | 4.47KB | 1.63KB |
| react (SchemaRenderer.js) | 109.04KB | 36.08KB |
| react (data-invalidation.js) | 5.05KB | 2.08KB |
| react (index.js) | 4.63KB | 2.18KB |
| react (schema-input.js) | 4.25KB | 2.04KB |
| react (spec-input.js) | 0.20KB | 0.18KB |
| sdui-parser (body-dialect.js) | 4.38KB | 1.98KB |
| sdui-parser (codegen.js) | 6.58KB | 2.74KB |
| sdui-parser (dashboard-widget-options.js) | 3.08KB | 1.30KB |
| sdui-parser (index.js) | 5.74KB | 2.54KB |
| sdui-parser (input-type.js) | 2.84KB | 1.40KB |
| sdui-parser (kanban-quick-add.js) | 3.89KB | 1.87KB |
| sdui-parser (parse.js) | 25.28KB | 7.80KB |
| sdui-parser (provenance.js) | 3.66KB | 1.82KB |
| sdui-parser (types.js) | 0.28KB | 0.23KB |
| sdui-parser (validate.js) | 15.71KB | 5.30KB |
| types (ai.js) | 4.11KB | 2.06KB |
| types (api-types.js) | 0.20KB | 0.18KB |
| types (app.js) | 2.87KB | 1.00KB |
| types (base.js) | 0.20KB | 0.18KB |
| types (blocks.js) | 0.20KB | 0.18KB |
| types (complex.js) | 2.93KB | 1.49KB |
| types (crud.js) | 0.20KB | 0.18KB |
| types (dashboard-filter-alias.js) | 6.23KB | 2.74KB |
| types (data-display.js) | 3.75KB | 1.85KB |
| types (data-protocol.js) | 0.20KB | 0.19KB |
| types (data.js) | 0.20KB | 0.18KB |
| types (designer.js) | 1.85KB | 0.85KB |
| types (disclosure.js) | 0.20KB | 0.18KB |
| types (error-code.js) | 1.54KB | 0.88KB |
| types (expression.js) | 0.20KB | 0.18KB |
| types (feedback.js) | 0.20KB | 0.18KB |
| types (field-types.js) | 0.20KB | 0.18KB |
| types (form.js) | 0.20KB | 0.18KB |
| types (http-inflight.js) | 8.87KB | 3.73KB |
| types (http-retry.js) | 4.32KB | 2.02KB |
| types (icon-key-migration.js) | 4.26KB | 1.63KB |
| types (index.js) | 4.74KB | 2.25KB |
| types (layout.js) | 0.20KB | 0.18KB |
| types (managed-by.js) | 0.19KB | 0.18KB |
| types (mobile.js) | 5.00KB | 2.39KB |
| types (navigation.js) | 0.20KB | 0.18KB |
| types (objectql.js) | 0.20KB | 0.18KB |
| types (overlay.js) | 0.20KB | 0.18KB |
| types (permissions.js) | 0.20KB | 0.18KB |
| types (plugin-scope.js) | 0.20KB | 0.18KB |
| types (record-components.js) | 0.20KB | 0.19KB |
| types (record-semantics.js) | 1.28KB | 0.67KB |
| types (registry.js) | 0.20KB | 0.18KB |
| types (reports.js) | 0.20KB | 0.18KB |
| types (select-option.js) | 0.20KB | 0.19KB |
| types (spec-report.js) | 5.05KB | 1.93KB |
| types (spec-ui-namespace.js) | 0.20KB | 0.19KB |
| types (strict-authoring-face.js) | 17.15KB | 6.32KB |
| types (system-fields.js) | 3.33KB | 1.54KB |
| types (theme.js) | 6.28KB | 2.87KB |
| types (ui-action.js) | 8.11KB | 3.32KB |
| types (views.js) | 0.20KB | 0.18KB |
| types (widget.js) | 0.20KB | 0.18KB |
Size Limits
- ✅ Core packages should be < 50KB gzipped
- ✅ Component packages should be < 100KB gzipped
⚠️ Plugin packages should be < 150KB gzipped
|
Fixes #8345
Clause-②: no
Session:
https://claude.ai/code/session_01QVJUngS9FKfuyQ9NFR2Nbn· branchclaude/issue-8345-strict-authoring-face· headfd8099b821d88d46d2777d898a443a1f4dc48b62· baseorigin/main0c2eb5eee029ecbc0c7d818d4bf49d3a370acea5What this PR is, and what it is not
dacb4021, "feat(types): derive and export the strict authoring twin of the node face").StrictAnyComponentSchema,StrictSchemaNodeSchemaandderiveStrictAuthoringSchemahave been published from@object-ui/types/zodsince then; the card body now carries a DATED READING block saying so. This PR lands only the remainder the director's review left on the card (comment5592118283, item 3, MINOR, "does hold the card"):「The walker's
default:arm swallowsset/map/prefault/promisesilently: inner object 0/1 closed, twin accepts an invented key, 0onOpaqueShapereports. … the reporter's contract is "every unclosed shape is reported". Either walk those arms or report them viaonOpaqueShape, and extend the three-kind control pin to cover the report path.」⛔ Not in this PR, as ruled: placement option B (module stays at
packages/types/src/strict-authoring-face.ts), any consumer wiring, any document repair, the.passthrough()onBaseSchemaCore(untouched — 4 hits on the base file, same after).The change (3 files, +212 / −10)
packages/types/src/strict-authoring-face.ts—set(element undervalueType) andmap(BOTHkeyTypeandvalueType) get arms;prefaultandpromisejoin theinnerTypegroup. Thedefault:arm now reports a def that still carries a schema under its own def type instead of handing it back as a leaf (carriesSchemaover the def members the arms read). On zod 4.4.3 the only kind that still routes there carrying a schema issuccess, which parses its inner schema into a boolean and can never refuse — reported, not walked, because walking it would move an OUTPUT value while closing nothing.packages/types/src/__tests__/strict-authoring-face-8345.test.ts(the EXISTING pin file, 25 → 32 tests) — inside "what strict could not close is enumerated, not claimed": an invented key inside each of the four wrappers is refused and NAMED (promiseviasafeParseAsync, since zod throws on a synchronous parse of a promise); a distinct opaque node inside each wrapper is reported WITH its trail (#/shape/inSet/valueType,…/inMapKey/keyType,…/inMapValue/valueType,…/inPrefault/innerType,…/inPromise/innerType); the four kinds are counted at 0 each on the FORCED tolerant face (so the synthetic controls are the coverage, not the corpus; non-vacuity: the same census sees 250-plus objects);successis reported at#/shape/flagand a row of five leaves is not.refusedKeyslearns zod'sinvalid_key/invalid_elementwrapping for Map entries whose key is not a property key (zod corehandleMapResult), andcensusgains a per-kind count..changeset/8345-strict-authoring-face-wrapper-kinds.md—@object-ui/typespatch.Clause ② — declared
nofrom this diff, with the instrumentsThe card's claim line reads
Clause-②: yesfor the card's ORIGINAL scope (a new published face). This PR's diff publishes no symbol and moves no key; measured on the builtdistat base0c2eb5eand headfd8099b8, zod 4.4.3:@object-ui/types/zod(Object.keysof the built barrel)export const zzClause2ProbeSymbolappended to the deep module (blob3b0dcb6→e3bfade, dist marker 1) — the deep module's export list grows from 3 to 4 and names it; barrel stays 211 because it re-exports by name; after restore + rebuild the marker reads 0 and the list is 3 againdist/strict-authoring-face.jsshapekey reachable, lazies forced)zzClause2ProbeKeyunioned onto the face reads 4493 on both faces — the instrument reports an injected keyset/map/prefault/promise/successnodes on the published faceobjectat 300-plus andunionabove 0StrictAnyComponentSchemaswapped into the measurement scriptAnyComponentSchemaswapped in reads 42 / 571 (first report on the card)Direction of the accept set: on the published face, nothing — none of the four kinds occurs, so both published twins accept and refuse exactly what they did (the corpus row above is the corpus-scale statement, base = head in every cell: 571 documents, 164 refused, 37 red today, 2182 nodes, 169 refused per node). For a caller deriving its OWN schema through
deriveStrictAuthoringSchema, the change is a narrowing only: an undeclared key inside a set, map, prefault or promise is now refused where it used to be silently dropped, and asuccesswrapper is now reported where it was silent; nothing is newly accepted anywhere. ⇒no. Comments were not counted as symbols: the instruments read the built modules, not the source.Re-taken figures (from the card's dated block, ⛔ not re-derived here)
Card body figures are dated readings that moved at every commit they were taken on (176/553 at
5505aec1, 196/557 atfa7d66c4, 174/556 at8e9b563). On today'sorigin/main0c2eb5e: 164 / 571 documents refused whole-tree strict (catalog 119 / docs 43 / authored 2), 37 / 571 red today, 169 / 2182 nodes (126 strict-only, 43 already red), registry 154 component types (card body said 107), 103 seen, 75 strict-clean, collisions 0, arms without a literaltype0.Gates — hand-derived from objectui's
package.jsonscripts and.github/workflows/(dispatch-gates.mjsrefuses for objectui); every exit code captured to a file before any pipePackage (
@object-ui/types), under the verify lock: buildpnpm --workspace-concurrency=2 --filter '@object-ui/types...' buildexit 0 ("130 emitted files verified");pnpm --filter @object-ui/types type-checkexit 0 — all three programs, and the test program's--listFileslists the pin file (1) and the source (1) while the emitting program lists the pin file 0 times (so the type-level pins are read by exactly one program, and it ran); package eslint--format jsonexit 0 over 281 files per eslint's own config (files: **/*.{ts,tsx}plus the js family), 0 errors, 298 pre-existing warnings, 0 on the two changed files — the rootpnpm lintworkflow fires on.changeset/**and runsturbo run lint, i.e. this same per-packageeslint .; the config is not type-aware (tseslint.configs.recommended, noprojectService/parserOptions.project), so this diff moves no other package's verdict; pin file from the repo rootpnpm exec vitest run --maxWorkers=2 packages/types/src/__tests__/strict-authoring-face-8345.test.tsexit 0, Test Files 1 passed (1) / Tests 32 passed (32) (selected count asserted: 1 file, 32 tests); whole packagepnpm exec vitest run --maxWorkers=2 packages/types/exit 1 — 209 passed / 1 failed files, 4862 passed / 1 failed tests, the one red named below.Root
check:*families (unlocked, per CI): control-bytes 0 · new-line-citations 0 · changeset-presence 0 · changeset-claims 0 (report-only) · changeset-no-major 0 · changeset-overwrite 0 · pending-changeset-literals 0 · shell-escape-residue 0 · governed-queue-guard self-test 0, and--teston the three changed paths reads NOT GOVERNED (the plain run exits 1 for want ofGITHUB_EVENT_PATH— a prerequisite, not a verdict) · self-import 0 · published-tsconfig-exclude 0 · side-effects-array 0 · esm-specifiers 0 · phantom-deps 0 · test-path-roots 0 · vi-mock-override-shape 0 · vi-mock-specifiers 0 · vi-mock-inherit 0 · action-ref-convention 0 · comment-mask-corpus 0 · unreferenced-sources 0 · doc-fences 0 · doc-types 0 · prompt-keys 0 · doc-example-ids 0 · doc-example-readers 0 · docs-route-closure 0 · spec-symbols 0 · handler-key-reads 0 · metadata-write-doors 0 · element-data-source-declaration 0 · published-dist 0 · readme-exports 0. Control-byte self-scan of the three files: no match. Cross-file line-citation shapes in the diff: none.NOT MEASURED, declared to CI:
check:doc-snippetsandcheck:doc-examples(exit 2 = "I could not run", a prerequisite the gate names itself, ⛔ not a verdict);check:eager-closure(exit 2, wantsapps/console/dist/eager-closure.json, which needs the console build);check:node-esm-load(cron / push-only lane); the whole-repopnpm test,pnpm type-checkandpnpm lintruns beyondpackages/types(narrowed as stated above — public types and exports are byte-identical, so no downstream consumer is owed a run).packages/types/src/__tests__/walkable-def-null-mint-9491.test.ts› "the matrix is as wide as the walkers, which is the rule it states (objectui#9692)" › "every node kind either walker NAMES is built by the matrix":expected [ 'promise' ] to deeply equal []. That pin reads both walkers'caselabels and requires itsMATRIXto build every kind named;MATRIXalready buildsset,mapandprefault, and never listedpromisebecause no walker named it before this PR (zod 4.4.3 does not deprecatez.promise). The pin's own message prescribes the remedy — "add one entry per kind rather than narrowing this assertion" — i.e. one rowpromise: z.promise(leaf),inMATRIX. That file is not on this PR's declared surface (the walker plus the existing 8345 pin file), so it is not edited here and the red is reported rather than hidden; no open pull request holds that file (all 9 open PRs' file lists read). ⇒ owed by a surface grant, one line.Reverse verification (one-off, restored to HEAD blobs; ⛔ nothing left in the tree)
caselabels and thedefault:report removed; blob3b0dcb6→86907b9, on-disk proofcase 'set'0,case 'promise'0,carriesSchema(def)0, marker 1): pin file exit 1, 6 failed / 26 passed — exactly the four wrapper pins, the report-through pin and thesuccesspin; the census-absent pin and every pre-existing pin stay green. Restored bygit checkout HEAD -- PATHunder an EXIT/INT/TERM trap; restored blob equals HEAD (3b0dcb6),git status --porcelainempty.Acceptance notes
z.promisecannot be parsed synchronously on zod 4.4.3 (Encountered Promise during synchronous parse); the pin states it. 承接者:无.successis REPORTED rather than walked, by design (it can never refuse); if a future consumer wants the inner object closed for its output value, that is a separate decision. 承接者:the first consumer that surfaces the limit list.needs:contract-reviewis on the card; the PR-side half is the seat's to hang, per the dispatch.维护者速读(草稿)
改了什么: 严格作者面的派生 walker 原本把
set/map/prefault/promise四种包装节点当叶子放过——里面的对象没被封闭、也不上报。现在四种都会走进去封闭;walker 没有分支的、但仍带 schema 的节点(zod 4.4.3 上只剩success)会按自己的类型上报,不再静默。钉子从 25 条加到 32 条,changeset 为@object-ui/typespatch。为什么改: 这是 #8345 卡上评审留下的唯一欠项(director 评论 5592118283 第 3 条):上报器的契约是「每个没封闭的形状都要上报」,四种包装违反了它。卡的主体(严格面本身)已在 PR #8642 于 2026-09-08 合入。
风险与代价(含回滚): 已发布面上四种节点一个都没有(强制展开后逐类计数为 0),语料 164/571 前后完全一致,导出符号与键集合零变化并各有点亮对照;唯一可观察变化是对自行调用⚠️ 一条相邻钉子变红:
deriveStrictAuthoringSchema的调用方——只收紧、不放宽。回滚 = revert 这一个 commit。walkable-def-null-mint-9491.test.ts要求 walker 点名的每种节点都进它的矩阵,promise缺一行;补法是该矩阵加一行promise: z.promise(leaf),不在本 PR 申报的文件面内,故未动、如实上报。席位意见: (留空,席位定稿)
你要做的: 决定那一行矩阵补在哪个 PR(本 PR 扩面、或席位代补);其余按常规评审与合并队列走,不需要维护者动手。
Generated by Claude Code