Skip to content

spec-surface: alias guidance for visible/showWhen/disabled on the visibleWhen shapes — the reverse direction of the action shapes' existing table (#7816 ask 1) #7832

Description

@os-zhuang

Provenance: split out of #7816 (its "ask 1") by the triage seat — the standalone, no-behaviour-change half. #7816 itself keeps the canonical-spelling decision (its "ask 2"); this card does not depend on that ruling.

Scope

Give the visibleWhen-family strict shapes the same aliases curation the action shapes already carry in the opposite direction, so visible / showWhen / disabled written on the wrong surface produces an error that names the key the author should have used:

Mechanism, verified on origin/main @ 098b629

strictObject's aliases table is error-message curation only — "semantic near-misses edit distance cannot reach" (packages/spec/src/shared/strict-object.ts), and its own doc example is exactly this key pair in the other direction (aliases: { visibleWhen: 'visible' }). Nothing that parses today changes; acceptance is byte-identical before/after ⇒ domain:spec-surface under the acceptance-surface criterion; changeset patch.

Measured rejections today (from #7816, spec dist on main): field.visible, userActions.delete.visible, userActions.delete.disabled — none of the messages mention visibleWhen / disabledWhen / enabled.

Out of scope

Choosing ONE canonical spelling (widening any schema, the boolean arm, ADR-0087 retirement of either form, ADR-0089's reach over action shapes) — that is #7816's decision. If that ruling later converges the vocabulary, these alias rows remain the right rows: they then carry the migration hint.

Refs #7816 (parent question), #5970 (action-side visible unification), ADR-0089.

Activity

  1. self-assigned this
    on Aug 12, 2026
  2. os-zhuang commented on Aug 12, 2026

    @os-zhuang
    ContributorAuthor

    Claim: PM loop round 1 (spec-surface seat, shift of 2026-08-12)
    Session: session_016YBUGvukaeVu9DjKdsHJa9
    Branch: claude/issue-7832-visiblewhen-aliases
    Worktree: objectstack-issue-7832 (cloud session's own clone)
    Domain: domain:spec-surface
    File surface: packages/spec/src/data/object.zod.ts (region ~L1060–1090, the RowCrudActionOverrideSchema definition ONLY), packages/spec/src/data/field.zod.ts (strict-options alias tables; NOT the number-presentation region), packages/spec/src/ui/view.zod.ts + packages/spec/src/ui/page.zod.ts (visibleWhen-family alias rows), plus pin tests for the curated messages.
    Container & model: M (multi-surface + a judgment call on the boolean-case alias target), mode:cloud single container, model: opus — triage gave no Size/model suggestion line; M-not-mechanical ⇒ cloud/opus per the 2026-08-10 tiering ruling.
    Serial constraints cleared: in-flight PR #7758 (object.zod.ts ~L1473, userActions.create/import predicate union) and PR #7813 (field.zod.ts, number useGrouping) intersect these files — regions are disjoint as declared above; the dev re-merges origin/main immediately before opening the PR and again if either sibling lands during convergence. No other open PR touches these faces (sweep read 2026-08-12T01:10Z). Premise note for the dev: the card's enumeration is partially stale — SelectOptionSchema (field.zod.ts:149) ALREADY carries visible/showWhen → visibleWhen; per-surface verification is mandatory, add only what is missing.


    Generated by Claude Code

  3. os-zhuang commented on Aug 12, 2026

    @os-zhuang
    ContributorAuthor

    os-dev-report (relayed by the PM from the cloud session's final commit message — E34 transport; session session_01KH13fZcK71UcDGM7faaFqX, commit 85fe3ee)

    {
      "issue": 7832,
      "status": "done",
      "branch": "claude/issue-7832-visiblewhen-aliases",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/7884",
      "premise_still_valid": true,
      "summary": "Premise held, but only PARTLY as the card described it — three of the five enumerated surfaces needed nothing, and the `disabled` ask was impossible on four of five. CHANGED: (1) RowCrudActionOverrideSchema — the real gap; converted to strictObject (verified acceptance-equivalent: strictObject IS z.object(shape,{error}).strict()); alias showWhen→visibleWhen; guidance prose for visible/disabled naming BOTH landing keys (honoring #7816's note: the boolean reading belongs on `enabled`). (2) FieldSchema — showWhen→visibleWhen rename; `visible` answered in prose naming `hidden` (INVERTED polarity) and `visibleWhen`; existing disabled→readonly left alone (a field has readonlyWhen). (3) FormFieldSchema (view.zod.ts) — disabled→readonly on its own call site, NOT the shared VISIBILITY_STRICT_OPTIONS (two sibling consumers would make it false). ALREADY COMPLIANT: SelectOptionSchema (as the claim comment warned); FormSection + PageComponent + FormField answer visible/showWhen via the ADR-0089 guidanceSets — an alias there would be dead code (VISIBILITY_KEY_PATTERN consumes the key before the rename channel). OUT OF SCOPE with reason: `disabled` on select option / form section / page component — no shape declares any disabled-ish key; pinned as deliberate gaps that FAIL if a landing key ever appears. Also drafted and dropped: hideWhen→visibleWhen (inverse predicate — the rename would flip meaning).",
      "tests": "New pin file packages/spec/src/shared/visible-when-alias-guidance.test.ts (19 pins: curated messages, already-compliant surfaces, deliberate gaps, acceptance-invariance). Spec full suite PASS 380 files / 10002 tests; post-rebase affected suites PASS 24 files / 808 tests; typecheck clean; spec build PASS; check:spec-parsed-alias PASS (1512/826/686 OK); check:adr-anchors PASS (22537 citations); check:nul-bytes PASS; acceptance equivalence VERIFIED EMPIRICALLY (17 surface×key pairs probed on built dist before/after — every verdict unchanged). CI in_progress at draft-PR time; PM owns convergence.",
      "open_questions": [
        "FormFieldSchema was not in the card's enumeration but is in ui/view.zod.ts and is the only view/page shape that can answer `disabled` truthfully — included and flagged, trivially revertible.",
        "Three surfaces reject `disabled` loudly but with no pointer (no landing key); a wrong-layer prescription was considered and NOT written — recorded as an out_of_scope_finding.",
        "Three rows landed as guidance prose instead of aliases; rule: one landing key ⇒ alias, two ⇒ prose naming both, none ⇒ nothing. Stated in PR body + test docblock for review override."
      ],
      "out_of_scope_findings": [
        "Card enumeration stale in two directions: form sections and page components were ALSO already compliant (ADR-0089 guidanceSets, #6619).",
        "`disabled` has no vocabulary at all on FormSectionSchema / PageComponentSchema — deliberate boundary or gap is a domain:spec question.",
        "VISIBILITY_KEY_PATTERN silently makes any vis-shaped alias dead on VISIBILITY_STRICT_OPTIONS surfaces; alias-integrity checks the target is declared, not that the row is reachable — a gate gap (spec-tooling face).",
        "#7816 ask 2 (canonical spelling) remains open; if it converges the vocabularies these rows become the migration hint."
      ]
    }

    Generated by Claude Code

  4. os-zhuang commented on Aug 12, 2026

    @os-zhuang
    ContributorAuthor

    ACCEPT (PM review, session session_016YBUGvukaeVu9DjKdsHJa9) — PR #7884.

    Landing: ready-flip + auto-merge once the ESLint and TypeScript Type Check jobs conclude success (flip checkpoint armed).


    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

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions