Skip to content
This repository was archived by the owner on Nov 4, 2026. It is now read-only.
This repository was archived by the owner on Nov 4, 2026. It is now read-only.

Measure the strict authoring face before building it: run catalog fixtures, docs json fences and apps through strict node schemas and count undeclared keys per component (first deliverable of the #5250 ruling) #7581

Closed

Description

@os-warren

Filed by the director seat from the #5250 ruling (maintainer, 2026-09-04, decision batch #25: option 2 — a strict authoring face as a programme, measurement first). This card is the measurement. ⛔ It builds nothing that ships: no schema in packages/types changes, no gate is wired, .passthrough() on the rendering face is not touched.

Deliverable: a number per component, not a fix

Derive, in a throwaway (a script under scripts/ or a one-off test that is not left in the tree unless the seat decides it is worth keeping as the future gate's skeleton), a strict variant of every node schema in @object-ui/types/zod — the same declared members, unknown keys refused — and run three corpora through it:

  1. every fixture under examples/schema-catalog/src/schemas/**/*.json;
  2. every ```json fence under content/docs/** that parses as a node document (a fence that is a deliberate fragment is counted separately as "fragment", ⛔ not silently skipped — the fragment-marking question finding: no gate reads a doc snippet's schema KEYS against the spec — #4823's deferred "second dimension", closed unbuilt #5138 already costed is part of what this measurement prices);
  3. the authored documents under apps/** and packages/*/examples/**.

Report, in the PR or on this card:

A component with zero undeclared keys is a result too — the programme needs to know how much of the tree is already strict-clean.

Why a measurement card exists at all

The ruling on #5250 is a multi-week programme touching every node schema and AGENTS.md #0.1. Its appetite cannot be set without knowing how red strict goes on today's corpus, and which side of each red is wrong (schema under-declares, or corpus authors garbage). This card produces that reading; the programme cards (strict face on the spec side, validate + fence gate on the devx side) are priced from it on #5250 afterwards.

Constraints

Unlocks: #5250 (Blocked-by: this card). Refs: #5250 (the ruling and the facet blocks) · #5138 / PR #5161 · #5174 · #5229 · #6939 · #7077 · ADR-0049.

Activity

  1. added theissue type on Sep 4, 2026
  2. added
    domain:devxobjectui devx stream: fix lands on .github/, scripts/ or release pipeline — devx lane cross-repo
    on Sep 4, 2026
  3. claude commented on Sep 6, 2026

    @claude
    Contributor

    Claim: PM loop round R44
    Session: session_013uAaxiwgYDybsTNV9xwa1M
    Branch: claude/issue-7581-strict-authoring-face-measurement
    Worktree: objectui-issue-7581
    Domain: domain:devx
    File surface: a throwaway measurement script under scripts/ (or scripts/__tests__/) + the report on this card / in the PR body; ⛔ nothing under packages/types/src/**, no gate wiring, no .passthrough() change (stop on breach; explain in the report)
    Container & model: M, measurement (judgment in corpus classification; nothing ships), mode:subagent, model: opus — objectstack's node scripts/pm/dispatch-gates.mjs --tier REFUSES --repo objectstack-ai/objectui (measured this round: gate families are a property of the tree it runs in), so the tier is the PM's per-card judgment under the script's declared policy floor sonnet · default opus · ceiling fable; no path-derived mandate applies to this surface.
    Clause-②: no
    Serial constraints cleared: none on files — the deliverable is a throwaway under scripts/ (new file) plus a report; ⚠️ #6939 (domain:spec, in flight, declaration repairs in the Zod mirror) moves the very numbers this card measures — the run pins its main SHA so it can be re-derived after #6939 lands; #5250 is pm:blocked on this card (fan-out 1)


    Generated by Claude Code

  4. claude commented on Sep 6, 2026

    @claude
    Contributor

    Claim: os-dev subagent (dispatched by domain:devx @ objectui PM seat, round R44)
    Session: session_013uAaxiwgYDybsTNV9xwa1M
    Branch: claude/issue-7581-strict-authoring-face-measurement
    Worktree: /home/user/objectui-issue-7581
    Base SHA: fa7d66c4505d0fcc866fbecec1901c4990a80c3a

    Inherits the PM claim 5556352168 (assignee already set; I do not write the assignee field). File surface as claimed: a throwaway measurement script under scripts/ plus the report; nothing under packages/types/src/**, no gate wiring, no .passthrough() change.


    Generated by Claude Code

  5. claude commented on Sep 6, 2026

    @claude
    Contributor

    os-dev-report

    {
      "issue": 7581,
      "status": "done",
      "branch": "claude/issue-7581-strict-authoring-face-measurement",
      "pr": "https://github.com/objectstack-ai/objectui/pull/7916",
      "premise_still_valid": true,
      "summary": "Added scripts/measure-strict-authoring-face.mjs, a reproducible throwaway that derives strict twins of every node schema in @object-ui/types/zod in memory and runs the three corpora through them; nothing ships, nothing was repaired, BaseSchemaCore.passthrough() is untouched. Headline at origin/main fa7d66c45 (corpus verified identical to that commit by the script's own pin): 2100 nodes, 196 strict-refused, 137 of them green today and red only under strict, 59 already red under the face as shipped; 58 of 94 component types seen are strict-clean; 13 registered types have no document anywhere. Two premise details on the card are wrong and are reported rather than worked around: (1) the TS index signature the card cites at base.ts 409/441 now sits at 467 (BaseSchema) and 499 (ComponentRendererProps) - located by content; 12 declaration sites repo-wide, 120 interfaces extend BaseSchema directly. (2) All 8 apps/**/*.json files are tooling config (package.json, three tsconfig*.json, manifest.json, vercel.json) and hold ZERO authored node documents, so corpus 3 yields only 2 node documents even after widening it mechanically to .ts modules carrying a type literal; the apps' real authored surface is JSX preview harnesses and spec records, not node documents. Two structural findings the programme needs before pricing: the node recursion point SchemaNodeSchema resolves to BaseSchemaCore, so a naive whole-document .strict() refuses 304/557 documents by unrecognising every child's own props - the recursion point must be redirected to AnyComponentSchema first; and the registry must come from the arms of AnyComponentSchema, not from module exports, because FilterFieldSchema's type enum otherwise captures the text and select node types (that bug inflated an early draft from 0 to 704 refusals on `text` alone). #6939 was NOT merged in; this reading is fa7d66c45's.",
      "tests": "No unit tests added - the deliverable is a measurement script, and it is verified by its own controls plus the repo gates. GATES (redirect-then-capture, each quoted from the gate's own verdict line): `pnpm check:control-bytes` exit 0 -> 'check-control-bytes: OK (scanned 6398 tracked text file(s); skipped 85 binary).'; `pnpm check:shell-escape-residue` exit 0 -> 'check-shell-escape-residue: OK (5/5 root(s) resolved ...; 0 occurrence(s) outside a fence (counted, not judged)).'; `pnpm type-check:scripts` exit 0, no diagnostics; `pnpm lint:root` exit 0 -> '33 problems (0 errors, 33 warnings)', 0 of them on the new file (grep -c measure-strict = 0, all 33 pre-existing); `node scripts/check-governed-queue-guard.mjs --test scripts/measure-strict-authoring-face.mjs .changeset/7581-...md` -> 'NOT GOVERNED - 2 path(s) checked against 5 governed surface(s); none matched.'. Build first: `pnpm --filter @object-ui/types build` exit 0 -> 'dist completeness: 1 package(s) complete (124 emitted files verified)' (run under bash /home/user/objectstack/scripts/pm/os-verify-lock.sh, VERDICT command-exit 0, held 7s, waited 0s). Note: `pnpm --filter '@object-ui/types^...' build` exits 1 with ERR_PNPM_RECURSIVE_RUN_NO_SCRIPT - the closure has no buildable workspace dependency; the package itself was built directly. REPRODUCIBILITY (the card requires it): two consecutive runs of both output formats diff byte-identical - markdown 455 lines, --json 63k, `diff` silent both ways. ABLATION of the corpus pin, on the committed tree, with an EXIT/INT/TERM trap and absolute paths: appended one line to content/docs/blocks/authentication.mdx; on-disk landing proven by blob hash 6aa5e59b -> 1d59f6a9 (both non-empty, different) and `grep -c` = 1 on the injected text; the run then printed \"corpus identical to that main commit: **NO - the numbers below are not main's**\" where the clean run prints **yes**. Restore leg: `git checkout HEAD -- content/docs` returned the blob to 6aa5e59b byte-identically and `git diff HEAD -- content/docs` is empty; the re-run prints **yes** again. Direction predicted before the run. PROBE CONTROLS inside the script itself: the renderer-mention probe runs `className` (must be > 0) and `zzzFabricatedControlKey` (must be 0) every run and prints both - it reads 13409 / 0, 'probe is live'. That control earned its keep: the first spelling of the pathspec (`packages/*/src` without `:(glob)`) matched nothing and the second was a TDZ throw swallowed by the catch; both returned 0 for every key, which reads exactly like 'nothing reads any of these'. Both are fixed and both traps are written into the script's comments. A third control: `git grep -n '[key: string]: any'` for a fabricated signature name returns 0 matches.",
      "mcp_calls": "1 - a single targeted mcp__github__search_issues for the dedupe of the two filed findings (REST /search/* is 403 through the proxy, re-measured this round at 02:51Z; it returned 15 non-empty results, so no control query was owed). Every other GitHub read and write went over repo-scoped REST curl: 6 issue/comment reads, 1 claim comment, 1 PR create, 1 PR body read-back, 2 issue creates, plus the report comment.",
      "open_questions": [
        {
          "question": "Should scripts/measure-strict-authoring-face.mjs stay in the tree as the skeleton of the future fence/validate gate, or be deleted once #5250's pricing has read the numbers? #7581 leaves this to the seat and the PR currently keeps it (the card also requires the script be kept so the numbers can be re-derived after #6939 lands).",
          "options": [
            "A - keep it as a plain script, unwired to any gate (the state of this PR). Costs one more file under scripts/ that pnpm lint:root and check-control-bytes already cover; buys the ability to re-run the measurement after #6939 and after each declaration repair, which is exactly what the programme needs to know it is converging.",
            "B - keep it AND wire it as a report-only CI job that prints the numbers without failing. Buys a trend line for free; costs a job slot and a thing to keep honest, and #5250 explicitly rules that the fence gate is built ON TOP OF the strict face, not before it.",
            "C - delete it after the pricing round, keeping only the numbers in this card and the PR body. Cheapest tree; but every future re-measurement is rebuilt from scratch, and the five decisions this one had to get right (registry source, schema-guided traversal, node boundary, clone-not-rebuild, unfailable key probe) are exactly the kind that get re-litigated wrongly."
          ],
          "recommendation": "A, for now, and explicitly not B. On the anti-AI-error axis, keeping the script is what makes 'declared = enforced' re-checkable rather than re-argued, and the four traps it documents in its own comments (the FilterFieldSchema registry capture, the field-def/node collision, the recursion point, the dead grep probe) are the ones a re-implementation would hit again. On the startup-focus axis, 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, and #7581 forbids leaving a gate wired. C is the honest fallback if the seat judges a scripts/ file with no gate behind it to be dead weight - but the card's own reproducibility clause argues against it while #6939 is still in flight."
        },
        {
          "question": "The whole-document reading (304/557 refused) is dominated by the node recursion point, not by component under-declaration. Does the domain:spec seat want the strict face's first card to be 'redirect SchemaNodeSchema to AnyComponentSchema' rather than a per-component declaration sweep?",
          "options": [
            "A - redirect the recursion point first, then measure again; the per-component numbers here (196/2100) are what remains after that.",
            "B - do the per-component declaration repairs first (the #6939 shape), leaving the recursion point as is; strict then still cannot be switched on at document level."
          ],
          "recommendation": "A. B leaves 304/557 documents red for a reason that has nothing to do with the components, so no per-component repair budget can ever close it; the measurement's job was to tell the programme which red is which, and this is the biggest single answer it produced. Flagged rather than decided: sequencing the programme cards is #5250's, not mine."
        }
      ],
      "out_of_scope_findings": [
        "filed as #7917: `BreadcrumbSchema` and `ObjectTreeSchema` are declared node schemas (arms of AnyComponentSchema) that @object-ui/types/zod never exports, so 2 of 107 component types cannot be validated on their own - unlabelled, unassigned, deduped against #7502/#7324 which are the same class on packages/fields and packages/plugin-form",
        "filed as #7918 (label `finding`): ten z.lazy exports in the zod node face rebuild their schema on every getter call, so the recursion point cannot be compared by identity and the sub-schema is reconstructed per parse - unassigned",
        "listed in the PR body, NOT filed (objectui#7581 explicitly permits 'file it ... or list it in the report'): the full undeclared-key worklist - `showSubmit`x76 on FormSchema with 40 renderer mentions (#6939-shaped), the dashboard `widgets[].value/icon/trend/trendValue` cluster, and the seven zero-mention #7077-shaped candidates (`columnSpan`, `fullWidth`, `itemTemplate`, `rowSpan`, `summary_field`, `summary_object`, `totalItems`)",
        "listed in the PR body, NOT filed: 59 nodes and 50 whole documents are already refused by the face AS SHIPPED - a superset of #6939's 8 components, which is open and in flight; folding them into a new card would duplicate it"
      ]
    }

    The measurement — condensed (full tables in PR #7916)

    Pinned to origin/main fa7d66c4505d0fcc866fbecec1901c4990a80c3a; the script verifies the corpus is byte-identical to that commit before reporting. zod 4.4.3, face read from packages/types/dist/zod/index.zod.js. #6939 was not merged in.

    Per corpus

    corpus items node documents fragments not an object no type unresolved type nodes nodes strict-refused nodes red today strict-ONLY
    catalog 431 412 0 0 0 19 1899 136 23 113
    docs 204 143 25 0 20 16 193 58 35 23
    authored 19 2 2 0 6 9 8 2 1 1

    Corpus sizes agree with the PM's enumeration on all four counts (431 catalog .json, 204 ```json fence openings, 8 apps/**/*.json, 6 files under packages/*/examples/**) — but all 8 apps JSON files are tooling config and hold zero authored node documents, which is why corpus 3 yields only 2.

    Headline

    metric value
    node documents measured 557
    nodes measured (documents flattened at declared node slots) 2100
    nodes refused by the strict twin 196
    …of which strict is the ONLY reason (green today) 137
    nodes already red under the face as shipped 59
    component types seen in the corpora 94
    component types strict-CLEAN (zero refusals) 58
    registered component types with no document anywhere 13
    whole-document strict parse, no node boundary 304 / 557 refused
    whole-document parse under the face as shipped 50 / 557 refused

    ⚠️ The 304/557 is not a per-component number. Child slots are z.union([SchemaNodeSchema, z.array(SchemaNodeSchema)]) and SchemaNodeSchema resolves to BaseSchemaCore — the ~21 base keys and nothing type-specific — so strict-ifying the recursion point unrecognises every child node's own declared props. The per-component tables therefore judge each node against its own schema and treat the recursion point as a boundary. The recursion point has to be redirected to AnyComponentSchema before strict can be switched on at document level at all; that is this measurement's largest structural result.

    Per component type — the 36 with at least one refusal

    type nodes strict-refused strict-only red today top-level undeclared nested undeclared
    flex 243 5 0 5 — —
    stack 154 1 0 1 items×1 —
    button 134 11 8 3 action×5, events×1, fullWidth×1, text×1 —
    card 111 7 7 0 change×3, value×3, dataSource×2, content×1, +1 —
    form 92 83 79 4 showSubmit×76, submitButton×3, title×1 fields.[].multiple×6, fields.[].rows×5, fields.[].columns×3, fields.[].formula×3, +21
    icon 73 1 0 1 — —
    label 45 1 1 0 required×1 —
    badge 42 3 0 3 text×2 —
    input 38 1 1 0 validations×1 —
    statistic 33 1 0 1 — —
    grid 26 1 0 1 actions×1, pagination×1, rows×1, title×1 —
    object-grid 19 4 1 3 dataSource×2, operations×1, resizableColumns×1, singleClickEdit×1, +1 pagination.enabled×1, selection.enabled×1, selection.mode×1
    dashboard 15 13 10 3 — widgets.[].value×16, widgets.[].icon×15, widgets.[].trend×15, widgets.[].trendValue×15, +6
    page 14 7 1 6 actions×3, breadcrumbs×1 regions.[].body×1
    select 11 3 0 3 field×1, optionsFrom×1 —
    data-table 8 1 0 1 dataSource×1 columns.[].key×1, columns.[].title×1
    empty 7 5 5 0 action×4, message×2 —
    resizable 7 7 0 7 — —
    carousel 5 5 0 5 — —
    combobox 5 2 2 0 searchPlaceholder×2, emptyText×1 —
    filter-builder 5 3 0 3 — —
    input-otp 5 2 2 0 separator×2 —
    object-form 5 4 3 1 formType×3, sections×3, dataSource×1, defaultTab×1, +1 —
    timeline 5 3 3 0 — items.[].description×8, items.[].time×8, items.[].title×8, items.[].variant×8, +2
    alert-dialog 4 4 4 0 actions×4 —
    object-view 4 4 4 0 defaultViewType×2, listViews×2, searchableFields×2, defaultListView×1, +3 form.drawerSide×1, form.formType×1
    alert 3 1 0 1 message×1 —
    list 3 2 1 1 itemTemplate×1 items.[].type×3
    list-view 2 2 0 2 dataSource×2 —
    navigation-menu 2 2 2 0 — items.[].items×2
    pagination 2 2 2 0 currentPage×2, pageSize×1, totalItems×1 —
    app 1 1 1 0 pages×1 —
    collapsible 1 1 0 1 — —
    detail 1 1 0 1 — —
    object-kanban 1 1 0 1 dataSource×1 —
    popover 1 1 0 1 — —

    Strict-CLEAN — 58 component types, zero refusals (a result too, per the card)

    text, box, container, separator, toggle, avatar, div, checkbox, radio-group, date-picker, file-upload, header-bar, scroll-area, sonner, spinner, switch, toast, kanban, tree-view, aspect-ratio, button-group, kbd, progress, table, bar-chart, breadcrumb, chart, code-editor, textarea, calendar-view, chatbot, markdown, object-gantt, object-map, sheet, skeleton, tabs, toaster, toggle-group, command, dropdown-menu, image, loading, view-switcher, accordion, action, context-menu, detail-view, dialog, drawer, filter-ui, hover-card, html, menubar, sidebar, slider, sort-ui, tooltip

    Top undeclared keys, top level (what BaseSchemaCore.passthrough() admits today)

    key occurrences renderer-source mentions
    showSubmit 76 40
    action 9 2724
    dataSource 9 1465
    actions 8 989
    change 3 790
    formType 3 76
    message 3 2046
    sections 3 413
    submitButton 3 45
    text 3 7680
    value 3 8785
    currentPage 2 40
    defaultViewType 2 13
    listViews 2 92
    searchPlaceholder 2 93

    Mention-probe controls: className = 13409 (must be > 0), zzzFabricatedControlKey = 0 (must be 0) ⇒ probe live. Mentions are a coarse triage hint, not a verdict: a common word (value, title, data) hits unrelated code and a computed accessor hits zero. The actionable end is the zero-mention rows — columnSpan, fullWidth, itemTemplate, rowSpan, summary_field, summary_object, totalItems — which are the #7077-shaped candidates, against showSubmit (76 occurrences, 40 mentions), the largest #6939-shaped one.

    Top undeclared keys, nested inside declared members

    path occurrences
    widgets.[].value 16
    widgets.[].icon 15
    widgets.[].trend 15
    widgets.[].trendValue 15
    widgets.[].options.data 11
    widgets.[].options.xField 11
    widgets.[].options.yField 11
    items.[].description 8
    items.[].time 8
    items.[].title 8
    items.[].variant 8
    fields.[].multiple 6
    fields.[].rows 5
    items.[].icon 4
    widgets.[].options.value 4

    Walker limits and other reported non-results (⛔ nothing silently skipped)

    • Shapes strict could not close: only opaque custom / function / transform validators — there is no shape inside them to close. Every reachable object, union, discriminated union, array, tuple, record, intersection, optional, nullable, default, pipe and z.lazy was strict-ified. Registry collisions: 0. Arms without a literal type: 0.
    • type values resolving in NO node schema (refused by AnyComponentSchema today): 44 at document roots across 28 distinct spellings (ui:calendar×5, sidebar-provider×4, action:button×3, page:tabs, donut-chart, pie-chart, radar-chart, spec-report, unknown-component, …) and 9 at declared child-node slots (footer, h1, header, line-chart).
    • Registered component types with zero documents in any corpus (13): calendar, chatbot-enhanced, chatbot-floating, crud-dialog, object-calendar, object-chart, object-data-table, object-gallery, object-tree, report, report-builder, report-viewer, span.
    • Authored modules that could not be imported (recorded, not skipped): apps/console/src/pages/developer/hooks/useApiDiscovery.ts — needs a built @object-ui/app-shell. One module prints on import (packages/types/examples/zod-validation-example.ts); console is muted for the run so stdout stays exactly the report, and the fact is reported.
    • The TypeScript face: [key: string]: any is declared at 12 sites in packages/types/src, and 120 interfaces extends BaseSchema directly. The card cites base.ts lines 409 / 441; located by content they are now 467 (BaseSchema) and 499 (ComponentRendererProps) — the second is the renderer props type, not an authoring type.

    Generated by Claude Code

  6. claude commented on Sep 6, 2026

    @claude
    Contributor

    ACCEPT — PR #7916 (head 0044a6021): the measurement is delivered, nothing ships, nothing was repaired. Open question 1 answered here: A, keep the script unwired.

    domain:devx @ objectui execution seat, PM session session_013uAaxiwgYDybsTNV9xwa1M, R44, 2026-09-06T03:04Z. Report 5556504179 reviewed against GitHub and the tree, ⛔ not against its narrative.

    item reading (mine)
    PR shape draft ✅ · base main ✅ · first line Fixes #7581 ✅ (this card's deliverable is the measurement; it closes on merge) · no other closing keyword adjacent to any card number ✅ · one platform footer ✅
    Path surface (get_files) exactly 2: scripts/measure-strict-authoring-face.mjs (+1001), .changeset/7581-strict-authoring-face-measurement.md (+9, empty frontmatter). Zero packages/ changes, zero governed paths — the card's ⛔ (no schema, no gate wiring, no .passthrough() change) holds by the file list, not by assertion
    Deliverable shape per-component table (documents / strict-refused / undeclared keys, top-level vs nested) and per-corpus totals with the docs fragment and non-document buckets are in the PR body and in the report comment on this card, as the card asked ("in the PR or on this card" — both)
    Reproducibility the script pins and verifies the corpus against the main commit it ran on; two consecutive runs of both output formats diff byte-identical; the pin's ablation (one appended line → corpus identical … NO) proved on disk by differing blob hash and restored to the HEAD blob with empty git diff HEAD
    Controls the renderer-mention probe carries a must-fire (className 13409) and a must-not (zzzFabricatedControlKey 0) every run — ⭐ and that control caught two dead-probe spellings during development that would otherwise have read "nothing reads any of these"
    Gates type-check:scripts 0 diagnostics · lint:root 33 warnings all pre-existing (0 on the new file) · check:control-bytes OK · check:shell-escape-residue OK · governed-queue-guard NOT GOVERNED — quoted from verdict lines
    CI on head at 2026-09-06T03:04Z 23 success · 5 in progress · 3 skipped · 0 failing
    Out-of-scope #7917 (two node schemas never exported from the zod face — bare, for triage) · #7918 (z.lazy rebuild per getter — finding); the undeclared-key worklist and the 59 already-red nodes are listed in the PR body rather than filed, which the card explicitly permits and which avoids a twin of in-flight #6939

    Headline the programme will price from (at origin/main fa7d66c45, #6939 NOT merged in)

    2100 nodes · 196 strict-refused, of which 137 are green today and red only under strict, 59 already red under the face as shipped · 58 of 94 seen component types strict-clean · 13 registered types with no document anywhere. ⭐ And the structural result that outranks the per-component numbers: the node recursion point SchemaNodeSchema resolves to BaseSchemaCore, so a naive whole-document .strict() refuses 304 / 557 documents by unrecognising every child's own props — the recursion point must be redirected to AnyComponentSchema before any per-component repair budget can close a whole-document reading.

    The two open questions

    1. Keep or delete the script — A, keep, unwired. This is a validation-strategy call inside the seat's discretion. The card's own reproducibility clause requires re-derivation after 24 catalog entries fail safeValidateSchema because the Zod mirror names a key its renderer never reads (8 components) #6939 lands; the five traps the script documents in its comments (registry captured from module exports, the field-def/node collision, the recursion point, clone-vs-rebuild, the dead grep probe) are exactly what a rewrite would hit again. ⛔ Not B: finding: JSON doc snippets are checked by nothing — the ts/tsx gate cannot see them, and BaseSchema.passthrough() makes objectui validate accept arbitrary undeclared keys #5250 rules the fence gate is built on top of the strict face, and a report-only job today prints numbers nobody acts on yet.
    2. Redirect the recursion point first vs. per-component repairs first — that is the sequencing of finding: JSON doc snippets are checked by nothing — the ts/tsx gate cannot see them, and BaseSchema.passthrough() makes objectui validate accept arbitrary undeclared keys #5250's programme, which the ruling reserves to the domain:spec and domain:devx seats proposing on finding: JSON doc snippets are checked by nothing — the ts/tsx gate cannot see them, and BaseSchema.passthrough() makes objectui validate accept arbitrary undeclared keys #5250. Relayed there in this stroke with the dev's recommendation (A) as input, ⛔ not decided here.

    Two card-premise corrections from the dev, adopted

    • base.ts index signature lines are 467 (BaseSchema) and 499 (ComponentRendererProps) today, not 409/441; located by content.
    • apps/**/*.json holds zero authored node documents (all eight are tooling config); corpus 3 is JSX harnesses and spec records, so its node-document yield is 2 even after mechanical widening. The card's corpus-3 definition should be read as "the apps' authored documents" ≈ empty, not as a measurement gap.

    Landing plan

    Path surface clean ⇒ flipped ready at 2026-09-06T03:04Z; auto-merge armed only when every check is green; enqueue confirmed by the added_to_merge_queue event. On MERGED: this card closes via Fixes; #5250 (Blocked-by: #7581) is discharged by the unlock scan — the stroke that closes this card also posts the pointer on #5250 and returns it to the pricing step its ruling names.


    Generated by Claude Code

  7. claude commented on Sep 6, 2026

    @claude
    Contributor

    LANDED — PR #7916 merged 2026-09-06T03:35:09Z (queued 03:19:56Z). Verified on origin/main b8e3f8379 by CONTENT, ⛔ not by the merge event.

    domain:devx @ objectui execution seat, PM session session_013uAaxiwgYDybsTNV9xwa1M, R44, 2026-09-06T03:36Z.

    reading expected got
    scripts/measure-strict-authoring-face.mjs present on main 1 1
    its header marker MEASUREMENT THROWAWAY > 0 ✅
    the must-fire probe key zzzFabricatedControlKey in the script > 0 ✅
    control — a nonsense phrase 0 0

    The card closes via Fixes on merge; pm:dispatched stripped and assignee cleared in this stroke where GitHub left them. #5250 (Blocked-by: #7581) is now discharged — pointer posted there. Open question 1 was answered A (script kept, unwired); question 2 (recursion point first vs per-component repairs) is the domain:spec seat's to propose on #5250.


    Generated by Claude Code

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    domain:devxobjectui devx stream: fix lands on .github/, scripts/ or release pipeline — devx lane cross-repopriority:p2tooling

    Type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions