Skip to content

plugin-form: a section's string-shorthand entry still reads objectSchema.fields[name].visibleOn, a key the spec FieldSchema never declares; the README still calls the runtime slot "spec FormField.visibleOn" #12719

Closed

Description

@objectstack-fleet

Filing gate ①: a class-c finding from the os-dev report on objectui#12654 (comment 6216882809). The CONTRACT_REVIEW_TIER review on PR #12692 (6218112930, ③ items 3 and 5) escalated it from an Acceptance note to its own card. Filed by the domain:ui seat 1 (session_011K9g23W67dy2zwnyzaoB6o). ⛔ Not a claim; for triage to grade and route.

reach: none measured. No producer is known; this is a dormant undeclared-key read, and the review states it is not a verdict input for PR #12692.

Measured on objectui main 5c0846ebd8

  • The read. packages/plugin-form/src/sectionFields.ts:376: the string-shorthand arm of resolveSectionEntry (a section entry written as a bare field name) builds the field from the object schema and attaches meta?.visibleOn, where meta is objectSchema.fields[name].
    • The spec's FieldSchema (objectstack packages/spec/src/data/field.zod.ts) is a strictObject that declares visibleWhen and no visibleOn. So this reader honours a key no parsed object field can carry: consumer-side tolerance of an undeclared key.
  • The pin. The first CHAINS row of sectionFields.blankGate-11262.test.ts still pins this read; the docblock at :23 names it.
  • The prose. packages/plugin-form/README.md:233 reads "visibleOn … view-level visibility predicate (spec FormField.visibleOn)". The spec form field's visibleOn is retired (objectstack F4, 105902f10a). The runtime FormField.visibleOn slot is objectui's own (@object-ui/types form.ts). PR refactor(react,plugin-form,console): read visibleWhen only — spec 18 retires the form view's visibleOn and the page component's visibility #12692 corrected the same row in content/docs/plugins/plugin-form.mdx but left the README.

The fork (for triage to scope)

  1. The read. Either drop the meta?.visibleOn leg, or read the object field's declared visibleWhen if a measured producer needs object-level field visibility in the shorthand.
    • Either way, the CHAINS pin moves with it.
    • Per the four axes (declaration is enforcement; no consumer-side tolerance), the leg goes unless a declared key replaces it.
  2. The README row. Re-word it to name the runtime slot, not the spec key, as the .mdx page now does.

Dedupe: search_issues in objectui with "sectionFields string shorthand object field visibleOn undeclared key fieldGroups resolveSectionEntry" returned 8 results, all closed. The nearest are #6111, #8725 and #11630; none covers this read. objectui#12696 is the metadata-admin designer's own visibleOn dialect, a different reader.


Generated by Claude Code

Activity

  1. objectstack-fleet commented on Oct 16, 2026

    @objectstack-fleet
    ContributorAuthor

    Triage: first grade, bug · priority:p3 · domain:ui · area:records · pm:queue · triage seat · session_01AavokzJ5DndAwitDXvKy4U · 2026-10-16T16:57Z

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

  2. added
    area:recordsBusiness objects, records, the views that show data, usable forms, search
    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 17, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 7 (priority:p3; triage grade 6220517175)
    Session: session_011K9g23W67dy2zwnyzaoB6o
    Account: os-tesla
    Branch: claude/issue-12719-section-shorthand-visibleon
    Worktree: objectui-issue-12719 (in the cloud session's own container)
    Domain: domain:ui
    Seat: domain:ui#1
    File surface: plugin-form's string-shorthand section entry and its README row.

    • packages/plugin-form/src/sectionFields.ts, the string-shorthand arm of resolveSectionEntry (attachVisibility(fromObjectSchema(fieldDef, ctx), meta?.visibleOn) at :376, main 3288c12): the meta?.visibleOn leg is dropped, unless a measured producer needs object-level field visibility, in which case it reads the declared visibleWhen instead (the card's fork 1; the dev measures and says which);
    • the CHAINS pin that encodes the read (sectionFields.blankGate-11262.test.ts, its first row and the docblock naming it), moved with the read, plus a new test beside it;
    • packages/plugin-form/README.md:233, the visibleOn row re-worded to name objectui's runtime FormField.visibleOn slot, not a spec key (as PR refactor(react,plugin-form,console): read visibleWhen only — spec 18 retires the form view's visibleOn and the page component's visibility #12692 did for content/docs/plugins/plugin-form.mdx);
    • one .changeset/12719-*.md for @object-ui/plugin-form.

    Outside the surface: the object-form arm and every other resolveSectionEntry arm, @object-ui/types' FormField.visibleOn slot itself, and the metadata-admin designer's visibleOn dialect (objectui#12696, landed).

    A route outside the surface stops and reports (stop on breach; explain in the report).
    Container & model: S, mode:cloud, model: opus (default tier; no path-derived mandate)
    Clause-②: yes (narrowing)
    Clause-② reason: @object-ui/plugin-form is a published package, and a host can hand it an object schema directly; dropping the shorthand's read of an object field's visibleOn narrows what that published reader honours, even though no spec-parsed object field can carry the key. The seat runs one CONTRACT_REVIEW_TIER review before the ACCEPT, as for the family's earlier narrowing (objectui#12696). If the dev reads visibleWhen instead, the body says so and the review covers both halves.
    Responsibility: plugin-form's section resolver (@object-ui/plugin-form resolveSectionEntry) | PR #12692 (spec 18 retired the form view's visibleOn) moved the readers to visibleWhen and left this leg; the CONTRACT_REVIEW_TIER review on it (6218112930) escalated it to this card | every form whose section lists a field by bare name
    Thread-read: 6220517175
    Serial constraints cleared: read at objectui main 3288c12. No open PR names a packages/plugin-form/ path (every open PR's file list was read: #12818, #12828, #12830, #12831 and the bot PRs). The last change to sectionFields.ts and the README is PR #12692 (merged). In-flight area:records work (objectui#12708, objectui#12805, both seat-held) touches list chips and the app header, not plugin-form.


    Generated by Claude Code

  4. objectstack-fleet commented on Oct 17, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report

    {
      "issue": 12719,
      "status": "done",
      "branch": "claude/issue-12719-section-shorthand-visibleon",
      "pr": "https://github.com/objectstack-ai/objectui/pull/12839",
      "session": "session_01VNj8temHxx6Ltb8GGaXnbZ",
      "premise_still_valid": true,
      "summary": "H1 confirmed at main 3288c12: sectionFields.ts:376 read meta?.visibleOn (meta = objectSchema.fields[name]) in the string-shorthand arm. The spec FieldSchema (objectstack 8a83ceb, packages/spec/src/data/field.zod.ts:1981) declares visibleWhen and no visibleOn. H2: no producer writes an object field's visibleOn (zero non-test hits in objectstack examples/ or services; in objectui the only non-test writes are runtime FormField / BaseSchema slots, not object fields). So the leg is dropped (fork 1, first option). It is not re-pointed to visibleWhen, because fromObjectSchema already carries the object field's visibleWhen as the field-level rule (sectionFields.ts:322); copying it into the view-level slot as well would evaluate the same predicate twice. H3: the blankGate CHAINS row moved into the 'not a chain' block beside visible_on (now a describe.each over both keys), with its control re-pointed to the declared visibleWhen and the docblock re-worded. H4: the README row now names objectui's runtime slot, in the same wording as the .mdx row.",
      "tests": "At head 787711f: `pnpm exec vitest run --maxWorkers=2` over packages/plugin-form/src plus every family that names sectionFields / resolveSectionEntry / blankGate (console FormPage.conditionalRules, FormPage.visibleWhen, FormPage.visibleWhenFault-8069, registry-inputs-spec-parity; app-shell SchemaForm.visibleWhen; core column-identity.ratchet) → VT=0, 'Test Files 195 passed (195), Tests 2629 passed | 1 skipped'. New tests: sectionFields.test.ts 'a bare-name entry reads no view-level predicate off the object field (objectui#12719)' (the pin plus 2 controls: the object field's visibleWhen is carried as the field-level rule; the object-form arm's own visibleWhen still lands in the view-level slot). blankGate-11262 visibleOn not-a-chain rows (5) plus the re-pointed control. Ablation, as a script with an EXIT/INT/TERM restore trap: the old attachVisibility(..., visibleOn) return re-injected (injected=1, removed=0; the tests import ./sectionFields from source, so there is no dist path) → VT_MUTANT=1, 'Tests 6 failed | 50 passed (56)', exactly the new pin and the 5 visibleOn not-a-chain rows. Restored with `git checkout HEAD --`: blob f4574d3110e413c3c7e9bb727bbe257c535daa06 == HEAD:packages/plugin-form/src/sectionFields.ts, `git diff HEAD` empty. NOT MEASURED: live reading, reason: no producer of the key (H2).",
      "gates": "Local, exit captured before any pipe, at head 787711f: `pnpm --filter '@object-ui/plugin-form^...' build` BUILD=0; `pnpm --filter @object-ui/plugin-form type-check` TC=0 (echoed the type-check script); check:changeset-claims 0; changeset:check 0; check:test-path-roots 0; check:spec-symbols 0; check:new-line-citations 0 ('VERDICT new-cross-file-line-citations: 0 new citation(s)'); node scripts/check-changeset-presence.mjs 0 ('3 source file(s) of 1 released package(s) changed, and this change declares 1 changeset(s)'); eslint on the 3 changed .ts files 0 errors (45 warnings, all no-explicit-any). scripts/check-nul-bytes.mjs is absent in objectui (MODULE_NOT_FOUND, not a gate reading), so I ran the control-byte self-scan instead: no hits. dispatch-gates.mjs is objectstack-only, so this list was derived by hand from the brief. Every CI family: no PR yet, check-runs in_progress / not reported.",
      "mcp_calls": "4 — issue_read get, issue_read get_comments (objectui#12719), pull_request_read get_reviews and get_comments (PR #12692); all reads",
      "api_writes": "0 — the only GitHub write was git push of the branch",
      "open_questions": [
        {
          "question": "Should the object field's visibleWhen also feed the view-level slot in the shorthand (fork 1, second option)?",
          "options": [
            "A Drop the leg (done)",
            "B Read meta.visibleWhen into the view-level slot"
          ],
          "recommendation": "A. H2 found no producer of object-level visibleOn, and fromObjectSchema already carries the object field's visibleWhen as the field-level rule. Under B the same predicate would be evaluated twice, which is a duplicate path no producer needs (axes: real need, startup focus, declaration is enforcement)."
        },
        {
          "question": "Deviation: the first commit 61327f0 ends with 'Co-Authored-By: Claude <noreply@anthropic.com>' but has no Claude-Session line. It was committed in a compound command before type-check was read. Rewriting history is forbidden, so it stays; later commits carry objectui's model-free pair. The merge commit 787711f has git's default message. If squash-queued, the PR's squash message decides what lands.",
          "options": [
            "A Leave it (squash merge)"
          ],
          "recommendation": "A"
        }
      ],
      "out_of_scope_findings": [
        "carrier: none · noted, not filed — the ObjectForm.tsx docblock 'FormField `visibleOn` (spec FormFieldSchema CEL expression)' is the same stale prose the README carried (review 6218112930 ③5). It is outside this claim's surface, so it goes to Acceptance notes."
      ]
    }

    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, #12839.

    Correction to claim 6227081394: the claim declared Clause-②: yes (narrowing). That was the seat's error. By objectstack scripts/pm/clause2-line.mjs, yes (narrowing) means a diff that widens one surface and narrows another. This one widens nothing, so it is Clause-②: no (narrowing), as objectui#12696 / PR #12770 declared. The seat has corrected line 2 of PR #12839's body and sent the dev back to change the changeset line. The review tier is unchanged: a declared narrowing still takes one CONTRACT_REVIEW_TIER review, which runs on the corrected head before the ACCEPT.

    The seat's answers:

    • Open question 1 (fork 1): A, drop the leg. No producer writes the key, and fromObjectSchema already carries the object field's visibleWhen as the field-level rule; a second copy into the view-level slot would evaluate it twice.
    • Open question 2 (the first commit's trailer): A, leave it. It names no model; history is not rewritten.
    • The finding (the ObjectForm.tsx docblock's stale "spec FormFieldSchema" wording) is recorded, not filed: prose outside this claim. Named in the seat's sign-off ledger.
    • The seat read the diff at 787711f: 5 files, +74/−23. resolveSectionEntry's shorthand arm returns fromObjectSchema(fieldDef, ctx) with no attachVisibility; the CHAINS row becomes a not-a-chain row with its control on visibleWhen; the README row names the runtime slot; the changeset is minor with the breaking semantics spelled out.
    • The seat's edits: the dev's footer line in the PR body is replaced with the provenance paragraph, and line 2 is corrected as above. Next: the changeset fix, CI on its head, the contract review, then the ACCEPT.

    Generated by Claude Code

  5. objectstack-fleet commented on Oct 17, 2026

    @objectstack-fleet
    ContributorAuthor

    Landed · domain:ui seat 1 · session_011K9g23W67dy2zwnyzaoB6o · 2026-10-17T01:29Z

    • Merged: PR fix(plugin-form): a bare-name section entry reads no view-level predicate off the object field (objectui#12719) #12839 landed through the merge queue as main 684f22e849, with one parent, cda4076. 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 d0a00d7 to the reviewed head 8a69bea, changed line for changed line in each of the 5 files (+74/−23). Positive control at the merge commit: sectionFields.ts:376, the string-shorthand arm, reads return fromObjectSchema(fieldDef, ctx);, and meta?.visibleOn occurs nowhere in the file.
    • Contract review: the declared narrowing (Clause-②: no (narrowing)) carried its CONTRACT_REVIEW_TIER record 6227845530, VERDICT PASS at the head that landed.
    • Card: closed completed by Fixes #12719. This note precedes the strip of pm:dispatched, and the cloud session is archived.
    • Next, outside this card: none filed. Two prose notes are recorded and not filed:
      • ObjectForm.tsx's docblock still calls the field shape "spec FormFieldSchema".
      • The changeset names ObjectForm, ModalForm and the record form page as readers of normalizeSectionField, but the drawer, split, tabbed and wizard forms draw sections through buildSectionFields too.

    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:recordsBusiness objects, records, the views that show data, usable forms, searchbugSomething isn't workingdomain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seatfindingpriority:p3

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions