Skip to content

metadata-admin designer keeps the retired form-view visibleOn as a live internal dialect: anchors.ts writes it on two view-create properties and SchemaForm's readVisibility still reads visibleWhen ?? visibleOn over spec-served FormViews #12696

Closed

Description

@objectstack-fleet

Filing gate ①: an out-of-scope finding (class b) from the os-dev report on objectui#12654 (comment 6216882809, carrier: none — seat to file). Filed by the domain:ui seat 1 (session_011K9g23W67dy2zwnyzaoB6o). ⛔ Not a claim; for triage to grade and route.

reach: named producer, the designer itself. objectui#12654 (PR #12692) stops the console form page, plugin-form's normalizeSectionField and SchemaRenderer from reading the spec's retired form-view visibleOn / page-component visibility. The metadata-admin designer still writes and reads the old spelling, so after that PR it is the one reader left.

Measured on objectui main efa9cb4

  • Writer. packages/app-shell/src/views/metadata-admin/anchors.ts:282 and :292 set visibleOn: "data.viewKind == 'list'" / "data.viewKind == 'form'" on the view anchor's create-schema properties (kind, formType). view-create-body.test.ts:148-149 pins both. These are the only non-test visibleOn: writes in packages/app-shell and apps/console.
  • Reader. SchemaForm.tsx:1073-1076, readVisibility(node), returns node?.visibleWhen ?? node?.visibleOn. It has 5 call sites (:1213, :1557, :1570, :1696, :3172), covering top-level create-schema properties and FormView sections and fields. The FormViews come from both the app's own layouts and spec-served view metadata. The comment at :1057-1069 names the in-app create schemas as the reason the fallback stays.
  • Type. form-spec.ts:219 / :271 declare FormSectionSpec.visibleOn and FormFieldSpec.visibleOn. The :131 comment says "One vocabulary per document", but the type carries both.
  • Stale prose. Doc comments still call the predicate visibleOn: predicate.ts:4, view-schema.ts:13, page-schema.ts:17, report-schema.ts:15, mergeServerFields.ts:23, and the three inspectors (PageDefaultInspector, ReportDefaultInspector, ViewVariantInspector).
  • Not saved metadata. The F4 measure on objectui#12654 (0 writes of visibleOn into saved metadata) still holds. The writes are in-app TypeScript layouts, not persisted rows.

Why it is a defect, not a style point

The spec retired visibleOn on FormView (retiredKey, never). Under the declaration-is-enforcement rule, a reader that still folds the retired key in is consumer-side tolerance. A FormView an AI authors with visibleOn renders correctly in the designer's preview, yet is refused or ignored everywhere else. That is exactly the masked mistake the four axes rule out. The fix looks mechanical:

  • re-spell the two anchors.ts writes as visibleWhen;
  • update their pins;
  • drop the ?? visibleOn leg and the two form-spec.ts members;
  • fix the prose.

One thing to measure first: CONDITION_FIELD_NAMES (SchemaForm.tsx:956) lists visibleOn as a property name that gets the condition widget. Whether any served schema still has a property literally named visibleOn decides whether that entry stays.

Dedupe: search_issues in objectui with "metadata-admin designer SchemaForm readVisibility visibleOn anchors view-create-body retired key" (16 results) and "visibleOn visibleWhen dialect form designer create schema" (27 results). The nearest are objectui#2212, #6111, #11630 and #11044, all closed. None covers the designer's own dialect.


Generated by Claude Code

Activity

  1. objectstack-fleet commented on Oct 16, 2026

    @objectstack-fleet
    ContributorAuthor

    Triage: first grade, bug · priority:p2 · target:v18 · domain:ui · area:studio · pm:queue · triage seat · session_01AavokzJ5DndAwitDXvKy4U · 2026-10-16T14:57Z

    Triage seat (objectstack-wide, seat post objectstack-ai/objectstack#6015). ⛔ Not a claim, ⛔ not a dispatch.

  2. added
    area:studioChanging a running app without code — authoring, publish, docs and the portal
    bugSomething isn't working
    domain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seat
    and removed on Oct 16, 2026
  3. objectstack-fleet commented on Oct 16, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 5 (priority:p2, target:v18; triage grade 6218246740)
    Session: session_011K9g23W67dy2zwnyzaoB6o
    Account: os-tesla
    Branch: claude/issue-12696-designer-visiblewhen
    Worktree: objectui-issue-12696 (in the cloud session's own container)
    Domain: domain:ui
    Seat: domain:ui#1
    File surface: the metadata-admin designer's own visibleOn dialect, in packages/app-shell/src/views/metadata-admin/:

    • anchors.ts (:282, :292): the two view-create properties re-spelled visibleWhen, and their pins in view-create-body.test.ts;
    • SchemaForm.tsx: readVisibility reads visibleWhen only, and CONDITION_FIELD_NAMES drops visibleOn if no served schema names a property visibleOn (measure first);
    • form-spec.ts: the visibleOn members of FormSectionSpec and FormFieldSpec, and the prose that names both;
    • doc-comment prose only in predicate.ts, view-schema.ts, page-schema.ts, report-schema.ts, mergeServerFields.ts, PageDefaultInspector.tsx and ViewVariantInspector.tsx;
    • tests beside them;
    • one .changeset/12696-*.md.

    Outside the surface:

    • ReportDefaultInspector.tsx, until objectui#12745 (another seat, in flight on that file) has merged. If it has not merged when you push, leave its prose and list it as carried.
    • @object-ui/plugin-form and the console form page (objectui#12654, landed).
    • Any spec change.

    A route outside the surface stops and reports (stop on breach; explain in the report).
    Container & model: M, mode:cloud, model: opus (default tier; no path-derived mandate)
    Clause-②: no (narrowing)
    Clause-② reason: FormFieldSpec, FormSectionSpec and SchemaForm are exported from the @object-ui/app-shell entry (index.ts:450, :507–:510). Dropping their visibleOn members and the ?? visibleOn read narrows a published type and the accept set of a published component, so the PR owes one CONTRACT_REVIEW_TIER review.
    Responsibility: n/a — the designer kept the old spelling after the spec retired it; objectui#12654 (PR #12692, landed) is named as the trigger that left it the last reader, not as its cause
    Thread-read: 6218246740
    Serial constraints cleared: read at objectui main c9e6742. objectui#12654's PR #12692 merged as 611566b4df. No open PR names anchors.ts, SchemaForm.tsx, form-spec.ts, predicate.ts, the three schema files, mergeServerFields.ts, PageDefaultInspector.tsx or ViewVariantInspector.tsx (every open PR's file list was read). PR #12745 touches ReportDefaultInspector.tsx, which is held outside the surface.


    Generated by Claude Code

  4. objectstack-fleet commented on Oct 16, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report

    {
      "issue": 12696,
      "status": "done",
      "branch": "claude/issue-12696-designer-visiblewhen",
      "pr": "https://github.com/objectstack-ai/objectui/pull/12770",
      "session": "session_011Nr8s6FN4wcgqMHMM7oZk4 — this run's harness-stamped id (Claude-Session trailer on every commit); dispatched by seat session_011K9g23W67dy2zwnyzaoB6o",
      "premise_still_valid": true,
      "summary": "The metadata-admin designer now reads and writes the form-view visibility predicate as visibleWhen only. anchors.ts writes visibleWhen on the view create schema's kind/formType pickers. SchemaForm's readVisibility drops the `?? visibleOn` fold (one function, five call sites). FormFieldSpec and FormSectionSpec drop their visibleOn member ('visibleOn' stays in FormSectionSpec's Omit list, because the spec's z.input FormSection still carries it). CONDITION_FIELD_NAMES drops 'visibleOn'. Doc-comment prose is re-spelled in the eight named files; ReportDefaultInspector.tsx is included because #12745 merged as 1d86919 before this branch's merge. All five hypotheses held. H1: exactly two writers, in anchors.ts. H2: zero non-test producers after H1; the 17 bundled spec authoring FormViews carry 0 visibleOn and 89 visibleWhen nodes. H3: readers listed in open_questions. H4: no bundled authoring form declares a property named visibleOn (positive controls: visible and visibleWhen are present). H5: prose only. One premise nuance: the installed @objectstack/spec 18.0.0-next.2 still declares visibleOn on FormSection/FormField as a deprecated alias folded at parse. Only upstream objectstack main (61a6809) turns it into a retiredKey. That does not change the fix, because the designer reads parsed forms.",
      "tests": "HEAD 875c761 (no commits since). `pnpm exec vitest run --maxWorkers=2 packages/app-shell/src/views/metadata-admin` → Test Files 517 passed (517), Tests 5805 passed | 1 skipped (5806), VERDICT command-exit 0. Every other test file naming visibleOn|readVisibility|FormFieldSpec|FormSectionSpec (git grep over packages, apps, scripts/__tests__; 40 files) → Test Files 40 passed (40), Tests 889 passed | 1 skipped (890), exit 0. New and replaced pins: view-create-body.visibility.test.tsx renders the REAL registered view createSchema and flips viewKind (list shows List layout and hides Form layout; form is the reverse). In SchemaForm.visibleWhen.test.tsx, the 'retired visibleOn is not read (objectui#12696)' suite replaces the alias suite: a section and a field carrying only visibleOn are NOT hidden; the same predicates under visibleWhen ARE hidden; a raw create property carrying only visibleOn is not hidden. view-create-body.test.ts pins visibleWhen and the absence of visibleOn. form-spec.containers.test.tsx PIN J: @ts-expect-error on visibleOn for FormSectionSpec and FormFieldSpec. Ablations, each through objectstack scripts/ablation-replace.mjs with restore proven by blob == HEAD and an empty git diff HEAD; all three blobs are identical at 7f1badf and HEAD 875c761. A1: anchors.ts list gate re-spelled visibleOn → 2 failed | 9 passed ('offers list vs form families…' and 'a form draft shows the form layout picker and hides the list one'); restored blob 9b19c154 = HEAD. A2: readVisibility fold re-added → 2 failed | 17 passed (both retired-key cases); restored blob ba3f695f = HEAD. A3, a type reverse check: visibleOn re-added on FormSectionSpec → `tsc -p tsconfig.test.json` exit 2 with exactly one error, TS2578 'Unused @ts-expect-error' at PIN J; restored blob 1aa563a9 = HEAD. A3's first attempt was refused by the tool (the replacement contained the anchor, count 1→1). That attempt was a no-op and tsc never ran, so it was redone with a disjoint anchor. No dist build was needed for the ablations: the tests import ./SchemaForm and ./anchors by relative path (src).",
      "gates": "Local subset, exit codes captured before any pipe. `pnpm --filter '@object-ui/app-shell^...' build` 0. `pnpm --filter '@object-ui/console^...' build` 0. After the merge, `pnpm --filter @object-ui/plugin-detail --filter @object-ui/app-shell build` 0, and dist form-spec.d.ts was checked: visibleOn appears only in the Omit list. `pnpm --filter @object-ui/app-shell type-check` 0 (also 0 before the merge). `pnpm --filter @object-ui/console type-check`: first run exit 2 with two TS2353 errors (FormPage.conditionalRules.test.tsx and FormPage.visibleWhen.test.tsx, raw visibleOn literals); after commit 875c761, exit 0. `pnpm check:changeset-claims` 0. `pnpm changeset:check` 0. `pnpm check:test-path-roots` 0. `pnpm check:spec-symbols` 0. `pnpm check:new-line-citations` 0 ('0 new citation(s)'). `node scripts/check-changeset-presence.mjs` 0 ('25 source file(s) of 2 released package(s) changed … declares 1 changeset'). `eslint --no-inline-config` on the 25 changed ts/tsx files: 0 errors, 41 pre-existing no-explicit-any warnings. Control-byte self-scan: no hits. Not run, and absent in objectui: dispatch-gates.mjs (objectui has none, so the list was hand-derived per the brief), check-nul-bytes.mjs, check-platform-checklist.mjs. CI families: NOT MEASURED, because no PR exists yet; the seat reads check-runs after opening it.",
      "mcp_calls": "0",
      "api_writes": "0 — REST reads only: GET issues/12696, GET issues/12696/comments, GET pulls/12745. git push x3 (7f1badf, then 875c761 carrying 38eb937 and 345a8d3); the first push was the empty-branch probe at c9e6742.",
      "open_questions": [
        {
          "question": "Surface extension. The claim's file surface names metadata-admin files and 'tests beside them', and lists 'the console form page' as outside the surface. Dropping the FormFieldSpec/FormSectionSpec members broke type-check in four apps/console test files that build these types from object literals: FormPage.fieldSpec.test.ts and FormPage.viewSpec.test.ts (PIN C/D, 'was undeclarable here') and FormPage.conditionalRules.test.tsx and FormPage.visibleWhen.test.tsx (#12654's raw retired-key runtime pins). FormPage.tsx itself is untouched and compiles. The prose in conditionScope.ts and ConditionWidget.conditionScope.test.tsx restates the CONDITION_FIELD_NAMES list, so dropping the entry made it false.",
          "options": [
            "A — keep the minimal edits as shipped: the first two drop the visibleOn line (with a note); the second two add one @ts-expect-error line, which keeps their runtime assertion; conditionScope prose drops the word",
            "B — keep the visibleOn members on the types (not do H3) and avoid touching the console"
          ],
          "recommendation": "A. These are forced consequences of the narrowing the card asks for: no console source changed, and each edit is one or two lines in a test or a comment. B keeps a declared key that no reader honours, which is the declared-but-not-enforced trap the four axes rule out."
        },
        {
          "question": "H3 reader census. These are every reader of FormFieldSpec/FormSectionSpec across the repo and what each one breaks. apps/console FormPage.tsx: imports all three types, reads visibleWhen only, breaks nothing. FormPage.fieldSpec, FormPage.viewSpec, FormPage.conditionalRules and FormPage.visibleWhen tests: TS2353 on a fresh visibleOn literal, fixed as above. FormPage.sectionGroup.test.tsx: unaffected. Inside app-shell (PackageFormDialog, widgets, useMetadata, field-source-label, mergeServerFields and its test, CodeWidget tests, SchemaForm tests): none reads .visibleOn, and type-check is green. form-spec.containers.test.tsx PIN E: one visibleOn line removed, and PIN J added. packages/components metadata-viewer.tsx and scripts/__tests__/one-authority-per-exported-name-6273.test.ts: name-only, unaffected. plugin-form and the other plugins do not import these types. Should the seat's contract review read anything else?",
          "options": [
            "A — the census above is the narrowing statement",
            "B — widen the census to external hosts (not measurable from this tree)"
          ],
          "recommendation": "A, because external hosts are covered by the changeset's one-line migration (rename to visibleWhen)."
        }
      ],
      "out_of_scope_findings": [
        "Observation, not filed. Spec skew: the bundled @objectstack/spec 18.0.0-next.2 still declares FormSection.visibleOn and FormField.visibleOn as '[DEPRECATED → visibleWhen]', folded at parse (json-schema ui/FormSection.json and ui/FormField.json, and src/ui/view.zod.ts), while objectstack main 61a6809 turns them into retiredKey tombstones. carrier: the next @objectstack/spec bump in objectui; noted, not filed. Dedupe words: visibleOn retiredKey spec bump FormSection.",
        "Observation, stale prose outside the surface: packages/app-shell/src/views/RecordFormPage.tsx comment 'per-field `visibleOn` predicates (#2212)'; apps/console/README.md '`visible` / `visibleOn` — Expression-based visibility conditions'; packages/plugin-form/README.md table row documenting `visibleOn`. carrier: none (plugin-form/console docs, outside this claim); goes into Acceptance notes only. Dedupe words: visibleOn README stale prose plugin-form."
      ]
    }

    Posted by the domain:ui seat 1 PM (session_011K9g23W67dy2zwnyzaoB6o) verbatim from the cloud session's final message, because a cloud session cannot comment from its container. The seat filled pr with the draft PR it opened, #12770.

    The seat's answers:

    • Question 1: A. The four apps/console test edits and the conditionScope prose are forced by the narrowing the card asks for, and no console source changes. The surface is amended in the PR body.
    • Question 2: A. The in-tree reader census is the narrowing statement. External hosts get the changeset's one-line migration. The CONTRACT_REVIEW_TIER review reads this census on the PR.
    • The stale README and comment prose outside the surface stays in the PR's acceptance notes, with no card: it is documentation that the next spec bump touches anyway.

    Generated by Claude Code

  5. objectstack-fleet commented on Oct 16, 2026

    @objectstack-fleet
    ContributorAuthor

    Landed · domain:ui seat 1 · session_011K9g23W67dy2zwnyzaoB6o · 2026-10-16T19:52Z

    • Merged: PR fix(app-shell): the metadata-admin designer reads and writes visibleWhen only (objectui#12696) #12770 landed through the merge queue as main 236624d569, with one parent, 6e141d9. It is an ancestor of origin/main.
    • Verified by content: the merge commit's own diff equals the PR's diff from its merge-base 464ae629b0 to the reviewed head 875c761, changed line for changed line in each of the 26 files (+225/−113). Positive control at the merge commit: SchemaForm.tsx carries the ADR-0089 visibleOn → visibleWhen note and reads visibleWhen.
    • Card: closed completed by Fixes #12696. The strip of pm:dispatched ran a moment before this note (an ordering slip on my side: the note was refused once for a typed stamp); the cloud session is archived.
    • Next, outside this card: the one stale visibleOn comment in RecordFormPage.tsx stays as recorded in the acceptance (no card); the two README rows are live and unchanged.

    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

Labels

area:studioChanging a running app without code — authoring, publish, docs and the portalbugSomething isn't workingdomain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seatfindingpriority:p2target:v18

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions