Repository navigation
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
Activity
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, theRowCrudActionOverrideSchemadefinition 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:cloudsingle 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, numberuseGrouping) intersect these files — regions are disjoint as declared above; the dev re-mergesorigin/mainimmediately 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 carriesvisible/showWhen → visibleWhen; per-surface verification is mandatory, add only what is missing.
Generated by Claude Code
- added a commit that references this issue
on Aug 12, 2026 os-dev-report (relayed by the PM from the cloud session's final commit message — E34 transport; session
session_01KH13fZcK71UcDGM7faaFqX, commit85fe3ee){ "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
ACCEPT (PM review, session
session_016YBUGvukaeVu9DjKdsHJa9) — PR #7884.- File face verified against the claim:
object.zod.tsregion L1072–1117 only (disjoint from in-flight feat(spec): userActions.create/import accept the edit/delete CEL predicate union #7758's L1473 region as declared),field.zod.tsstrict-options tables (disjoint from feat(spec): Field.number gains useGrouping presentation hint (#7768) #7813's number region),view.zod.tsFormFieldSchema call site, one new pin file, one patch changeset. No other files. - The acceptance-face red line held and is PINNED: test section 4 asserts every probed key keeps its pre-change verdict, and the report carries 17 empirical before/after probes on built dist. The
strictObjectconversion was verified equivalent (z.object(shape, {error}).strict()). - Per-surface accounting is complete — including the two directions the card's enumeration was stale in (SelectOptionSchema flagged at claim time; FormSection/PageComponent found already compliant via the ADR-0089 guidance sets).
- The three open questions are all accepted as decided: FormFieldSchema's inclusion is in the card's spirit (ui/view.zod.ts family, the only shape that can answer
disabledtruthfully, flagged and revertible); guidance-prose-over-alias for dual-landing keys honors the card's own One intent, two spellings:visible(actions) vsvisibleWhen(fields / sections / userActions) — and the alias guard only covers one direction #7816 note; the deliberatedisabledgaps are tripwired to fail when a landing key appears. - Findings 2 and 3 of the report's out_of_scope_findings are being filed as separate unassigned
findingcards by this seat (the cloud session cannot write issues); finding 1 is card-staleness commentary (no action), finding 4 is already tracked on One intent, two spellings:visible(actions) vsvisibleWhen(fields / sections / userActions) — and the alias guard only covers one direction #7816.
Landing: ready-flip + auto-merge once the ESLint and TypeScript Type Check jobs conclude
success(flip checkpoint armed).
Generated by Claude Code
- File face verified against the claim:
- added a commit that references this issue
on Oct 7, 2026
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 samealiasescuration the action shapes already carry in the opposite direction, sovisible/showWhen/disabledwritten on the wrong surface produces an error that names the key the author should have used:RowCrudActionOverrideSchema(packages/spec/src/data/object.zod.ts,userActions.edit/deleteoverrides) — today a plain.strict()with noaliases/guidanceat all;userActions.delete.visibleand.disabledget bare unrecognized-key errors (measured in One intent, two spellings:visible(actions) vsvisibleWhen(fields / sections / userActions) — and the alias guard only covers one direction #7816).enabled, not atvisibleWhen, or the hint just moves the confusion (One intent, two spellings:visible(actions) vsvisibleWhen(fields / sections / userActions) — and the alias guard only covers one direction #7816's own note).packages/spec/src/data/field.zod.ts:814and:176), form sections (ui/view.zod.ts), page components (ui/page.zod.ts): aliasesvisible → visibleWhen,showWhen → visibleWhen,disabled → disabledWhen.Mechanism, verified on
origin/main@098b629strictObject'saliasestable 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-surfaceunder the acceptance-surface criterion; changeset patch.Measured rejections today (from #7816, spec
distonmain):field.visible,userActions.delete.visible,userActions.delete.disabled— none of the messages mentionvisibleWhen/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
visibleunification), ADR-0089.