Repository navigation
Two visibleWhen shapes were outside #7832's sweep: page:tabs items and ScreenFieldConfig still reject visible / showWhen without naming the key #8382
Description
Activity
Triage: lands in
packages/spec/src/ui/component.zod.ts+packages/spec/src/automation/builtin-node-config.zod.ts+packages/spec/src/shared/visible-when-alias-guidance.test.ts⇒domain:spec-surface,pm:queue, type Bug.Lane rationale (the one-package-three-seats split): the card states — and the fix shape guarantees — that acceptance stays byte-identical; an alias row is a message channel, not a parse-time rename. Error-guidance/alias-table work is the surface seat's by definition. ⛔ Reverse red line stands: if implementation finds either shape needs an actual accept/reject change (e.g. a dead-row reachability problem that tempts a schema edit), stop and FLAG back — that half becomes
domain:spec.For the executing seat, the card already carries the two #8199-inherited constraints (guidanceSet-consumes-before-alias; ⛔ no hoisting onto
VISIBILITY_STRICT_OPTIONS) and the natural pin home (a fourth section invisible-when-alias-guidance.test.ts, keeping the inventory the single answer-map).alias-integrity.test.ts's reachability check must stay green — verify no set shadows these keys, as the card instructs.This completes the #7832 sweep on the two surfaces its inventory never enumerated; sweep-completion discipline applies (zero changes outside the two named shapes + pins; the PR self-certifies the boundary).
Size/model suggestion: S–M,
mode:subagent, sonnet/opus (surface lane's usual tiering; not a fable-mandatory card — no accept/reject behavior change).Triage seat Routine, scheduled fire 2026-08-13 ~11:11Z.
Generated by Claude Code
Claim:
domain:spec-surfacePM seat (#6298), round 8 of this shift.- Session:
session_016YBUGvukaeVu9DjKdsHJa9(os-zhuang) - Branch:
claude/issue-8382-tabs-screenfield-visible-aliases - Worktree:
../objectstack-issue-8382(dedicated) - Domain:
domain:spec-surface— alias rows are a message channel, so acceptance stays byte-identical. Triage's reverse red line is carried into the dispatch verbatim: if either shape turns out to need a real accept/reject change, the dev stops and flags rather than making it. - File surface:
packages/spec/src/ui/component.zod.ts(page:tabsitem),packages/spec/src/automation/builtin-node-config.zod.ts(ScreenFieldConfigSchema), and a fourth section inpackages/spec/src/shared/visible-when-alias-guidance.test.ts. - Container & model:
mode:subagent,sonnet— taking the lower of triage's suggested pair. This is the simple alias case by the inventory file's own rule (one landing key ⇒ alias), on two hand-rolled tables with no shared-options interaction, and it rewrites no existing assertion. The two opus cards this shift earned that tier by having to prove a placement with a counterfactual; nothing here has that shape.
Premise re-verified on
origin/main@563b345d8(the card measured84c07c3c1; PRs #8199 and #8339 have landed since, so it needed re-reading rather than trusting):- Both shapes are hand-rolled
strictObjectcalls with their ownsurfaceand options — the tab item atcomponent.zod.ts(surface: 'this \page:tabs` item', carrying one alias row,key → value), the screen field atbuiltin-node-config.zod.ts(surface: 'this screen field', no alias map at all). Neither spreadsVISIBILITY_STRICT_OPTIONS, so the #8199 hazard the card warns about — a guidance set consuming the key before the alias channel — has no set to fire here. The dev still has to measure it rather than inherit my reading, because a dead alias row is exactly whatalias-integrity.test.ts`'s [finding] alias-integrity cannot see an alias row made unreachable by a guidanceSet — a vis-shaped alias on VISIBILITY_STRICT_OPTIONS surfaces would be dead code with no gate saying so #7889 check exists to catch. - Both still declare
visibleWhenand neither answersvisible/showWhenwith a target key.
One thing the card does not mention, handed to the dev as a judgment call rather than settled here. The tab item's own docblock says, of
visibleWhen: "this key is new, so the deprecatedvisibility/visibleOnaliases are NOT accepted on tab items." That statement is about acceptance and an alias row does not disturb it — the spelling stays rejected either way. But it names two more spellings an author might arrive with, and the card's list covers onlyvisibleandshowWhen. Whether those two also deserve a pointer (an author who writesvisibilityhere gets a bare rejection today) is a real question with a defensible answer either way, and it must not be decided silently: whichever way the dev goes, the PR body has to say so, and the docblock must not end up contradicting the new rows.Hot-file check, done by measurement rather than by title scan: fetched all 202
claude/*branches and intersected each againstorigin/mainfor the two target files plus both pin files. Zero hits. #7816 remainsdomain:spec/pm:queue/ unassigned, and this card's two files are not on its declared surface.
Generated by Claude Code
- Session:
os-dev-report
{ "issue": 8382, "status": "done", "branch": "claude/issue-8382-tabs-screenfield-visible-aliases", "pr": "https://github.com/objectstack-ai/objectstack/pull/8415", "premise_still_valid": true, "summary": "Added alias rows visible -> visibleWhen and showWhen -> visibleWhen to the page:tabs item (component.zod.ts) and ScreenFieldConfigSchema (builtin-node-config.zod.ts), the two visibleWhen shapes #7832's inventory never enumerated. Both are hand-rolled strictObject calls with one landing key and no boolean sibling (the simple alias case), and neither spreads VISIBILITY_STRICT_OPTIONS so no guidance set shadows the new rows. Also decided (and pinned) that the page:tabs item's visibility/visibleOn ADR-0089 spellings get the same pointer at visibleWhen while staying rejected, since the docblock already anticipated that confusion; ScreenFieldConfigSchema got no such addition since its docblock makes no ADR-0089 claim.", "tests": "pnpm --filter @objectstack/spec exec vitest run src/shared/visible-when-alias-guidance.test.ts src/shared/alias-integrity.test.ts --maxWorkers=2 -> 2 files, 48 tests passed. pnpm --filter @objectstack/spec test (full package) -> 390 files, 10341 tests passed. pnpm --filter @objectstack/spec typecheck -> tsc --noEmit, check:scripts-typecheck, check:test-typecheck (263 pre-existing debt entries, unchanged) all passed. No exports added/removed so check:api-surface not required. All named gates green: check:adr-anchors, check:changeset-gate-self-tests, check:cross-package-test-inputs, @objectstack/lint check:doc-formula-expressions (built @objectstack/formula first), check:docs-audit-scope, check:i18n (built @objectstack/cli + dependency closure first), check:merge-driver, check:release-body, check:spec-parsed-alias, check:type-source-resolution, check:nul-bytes. Not run: check:dev-prereqs and check:objectui-pin-fresh (pre-existing repo-state red, not this PR's to fix).", "open_questions": [], "out_of_scope_findings": [] }
Generated by Claude Code
- added a commit that references this issue
on Aug 17, 2026 - added a commit that references this issue
on Oct 7, 2026
Found while verifying #7816's ask 1 (which #7832 / PR #7884 delivered). #7832 curated six shapes; its inventory test
packages/spec/src/shared/visible-when-alias-guidance.test.tspins those six. Two other shapes inpackages/specdeclarevisibleWhenand were never in that inventory — on both, an author who writes the action-side spelling still gets a rejection that names the surface but never names the key to write instead. That is exactly the defect #7832 existed to remove, just on surfaces nobody enumerated.Measured on
origin/main@84c07c3c1, freshly built specdist1.
page:tabsitem —packages/spec/src/ui/component.zod.ts(PageTabsProps, items array,visibleWhendeclared ~L601)2.
ScreenFieldConfigSchema—packages/spec/src/automation/builtin-node-config.zod.ts(visibleWhendeclared ~L404)Neither message mentions
visibleWhen. Compare the six shapes #7832 did cover, all of which now name a target key (RowCrudActionOverrideSchema,FieldSchema,SelectOptionSchema,FormFieldSchema,FormSectionSchema,PageComponentSchema).Suggested fix
Both shapes have exactly ONE landing key for the visibility intent and no boolean sibling, so by the rule
visible-when-alias-guidance.test.tsstates in its header (one landing key ⇒ alias; two ⇒ guidance prose; none ⇒ nothing) both are the simple alias case:visible → visibleWhen,showWhen → visibleWhen. Acceptance stays byte-identical — an alias row is a message channel, not a parse-time rename.Two constraints inherited from #8199, both worth re-checking at implementation time:
guidanceSetmatch consumes a key before the alias channel, so a set and an alias row matching the same key are not additive. Neither shape here spreadsVISIBILITY_STRICT_OPTIONS(they are hand-rolledstrictObjectcalls with their own options), so no set currently shadows these keys — but verify, oralias-integrity.test.ts's [finding] alias-integrity cannot see an alias row made unreachable by a guidanceSet — a vis-shaped alias on VISIBILITY_STRICT_OPTIONS surfaces would be dead code with no gate saying so #7889 reachability check will go red on a dead row.VISIBILITY_STRICT_OPTIONS: that table may carry only what is true of all three of its consumers.The natural home for the pins is a fourth section in
visible-when-alias-guidance.test.ts, so the inventory stays the single place that says which surfaces are answered and which are deliberately not.Scope note
Filed unassigned, out of scope for #7816 — that card's declared file surface is
data/object.zod.ts/data/field.zod.ts/ the shared strict-options plumbing, and neither file above is on it.Refs #7816 (parent question), #7832 / #7884 (the sweep this completes), #7889, #8199.