Commit 96fb785
committed
feat(lint): move the views[] visibility-predicate family to the runtime publish gate (#7220)
The four rules that judge a `views[]` conditional-visibility predicate ran on
the three CLI commands only. A `view` written through the runtime publish door
— Studio's designer, REST `/meta`, MCP — was judged by NONE of them, and that
door is the only one most tenants have and the one AI authors use. A predicate
that cannot parse saved clean and then failed OPEN in the console: the element
renders unconditionally, pixel-identical to one carrying no predicate (#5149).
Both registry entries move to `surfaces: CLI_AND_RUNTIME` with
`runtimeTypes: ['view']`, in ONE edit, on the maintainer's 2026-08-10 ruling
and sequenced after #4717's `advisories` channel landed (PR #7435). Six rule
ids cross together: `visibility-predicate-syntax`,
`visibility-predicate-over-budget`, `visibility-bare-identifier`,
`visibility-root-mislayered`, `predicate-path-unresolved` and
`predicate-path-unrooted`.
They move together on purpose. #7214's implementer wired the path rule alone,
measured the result and reverted it: a `view` refused for an unresolvable
predicate PATH while a predicate that does not parse at all walks through the
same door is less predictable than refusing neither. A half-wired wall is worse
than an unwired one, so the family property is now PINNED in
`authoring-rule-wiring.test.ts` — every id on this surface is gated at the
runtime door, or none is — rather than trusted to a prose `surfaceReason` that
goes stale silently. `RUNTIME_VISIBILITY_FAMILY_IS_CLI_ONLY`, the constant that
recorded the CLI-only state as a decision, is deleted with its last user.
Three things were measured rather than assumed:
- The gate needed no dispatch-side change. `runtimeGatedTypes()` is derived
from this registry, `TYPE_TO_STACK_KEY` already mapped `view -> views`, and
`runtime-authoring-gate.ts` passes the written type straight through — its
two `'flow'` literals belong to the gate-local #6285 rule, not to a type
allowlist. Declaring is sufficient; `runtimeGatedTypes()` now returns
`['flow', 'view']`.
- Neither rule needs a stack-wide snapshot. Both read `stack.views` and
`stack.pages` and no other collection — never `objects` — so the previous
`RUNTIME_NEEDS_FULL_SNAPSHOT` reason on `validateVisibilityPredicates` was
describing nothing about this rule. It was the reason a rule got when nobody
measured, which is the #4409/#4463 defect one layer in.
- The door and `os build` agree. `runtime-gate.test.ts` drives the real
dispatch path over an eight-input corpus and asserts the finding sets are
IDENTICAL — id, severity and path — so the move changes WHERE the rules run,
never WHAT they say. Set equality, not "both non-empty": a half-wired wall is
precisely the state where both sides are non-empty and disagree.
`visibility-root-mislayered` is `warning` on every surface, so it does not 422
— it reaches the author through the `advisories` channel on the 2xx save
response. That channel is why this move was allowed to happen at all: moving
the rules before findings could travel back would have run them and discarded
the verdicts, the exact shape #4463 exists to close.
Behaviour change on a public door (a `view` publish carrying one of these
defects is now refused), so it ships a changeset rather than skip-changeset.
Drafts are still never gated and `OS_ALLOW_UNLINTED_METADATA_WRITES=1` remains
the migration hatch.
Fixes #7220
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QpSiahE9sb96neoWajbiQz1 parent 8e17759 commit 96fb785
5 files changed
Lines changed: 348 additions & 35 deletions
Lines changed: 45 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
448 | 448 | | |
449 | 449 | | |
450 | 450 | | |
| 451 | + | |
| 452 | + | |
| 453 | + | |
| 454 | + | |
| 455 | + | |
| 456 | + | |
| 457 | + | |
| 458 | + | |
| 459 | + | |
| 460 | + | |
| 461 | + | |
| 462 | + | |
| 463 | + | |
| 464 | + | |
| 465 | + | |
| 466 | + | |
| 467 | + | |
| 468 | + | |
| 469 | + | |
| 470 | + | |
| 471 | + | |
| 472 | + | |
| 473 | + | |
| 474 | + | |
| 475 | + | |
| 476 | + | |
| 477 | + | |
| 478 | + | |
| 479 | + | |
| 480 | + | |
| 481 | + | |
| 482 | + | |
| 483 | + | |
| 484 | + | |
| 485 | + | |
| 486 | + | |
| 487 | + | |
| 488 | + | |
| 489 | + | |
| 490 | + | |
| 491 | + | |
| 492 | + | |
| 493 | + | |
| 494 | + | |
| 495 | + | |
| 496 | + | |
| 497 | + | |
| 498 | + | |
| 499 | + | |
451 | 500 | | |
452 | 501 | | |
453 | 502 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
351 | 351 | | |
352 | 352 | | |
353 | 353 | | |
354 | | - | |
355 | | - | |
356 | | - | |
357 | | - | |
358 | | - | |
359 | | - | |
360 | | - | |
361 | | - | |
362 | | - | |
363 | | - | |
364 | | - | |
365 | | - | |
366 | | - | |
367 | | - | |
368 | | - | |
369 | | - | |
370 | | - | |
371 | | - | |
372 | | - | |
373 | | - | |
374 | | - | |
375 | | - | |
376 | | - | |
377 | | - | |
378 | | - | |
379 | | - | |
380 | 354 | | |
381 | 355 | | |
382 | 356 | | |
| |||
841 | 815 | | |
842 | 816 | | |
843 | 817 | | |
| 818 | + | |
| 819 | + | |
| 820 | + | |
| 821 | + | |
| 822 | + | |
| 823 | + | |
| 824 | + | |
| 825 | + | |
| 826 | + | |
| 827 | + | |
| 828 | + | |
| 829 | + | |
| 830 | + | |
| 831 | + | |
| 832 | + | |
| 833 | + | |
| 834 | + | |
| 835 | + | |
| 836 | + | |
| 837 | + | |
| 838 | + | |
| 839 | + | |
| 840 | + | |
| 841 | + | |
| 842 | + | |
| 843 | + | |
| 844 | + | |
| 845 | + | |
| 846 | + | |
| 847 | + | |
| 848 | + | |
844 | 849 | | |
845 | 850 | | |
846 | 851 | | |
847 | 852 | | |
848 | 853 | | |
849 | 854 | | |
850 | | - | |
851 | | - | |
| 855 | + | |
| 856 | + | |
852 | 857 | | |
853 | 858 | | |
854 | 859 | | |
| |||
871 | 876 | | |
872 | 877 | | |
873 | 878 | | |
874 | | - | |
875 | | - | |
| 879 | + | |
| 880 | + | |
| 881 | + | |
| 882 | + | |
| 883 | + | |
876 | 884 | | |
877 | 885 | | |
878 | 886 | | |
| |||
0 commit comments