fix(spec): view-reference build lint — collision warns, form-target errors (#2554)#2586
Merged
Conversation
fix(plugin-grid): schema-aware multi-value semantics for bulk-edit params (#2206) objectui@3e4268041bc2523bc3f40a4d54646672ce3394c5
…rrors (#2554) List and form views share one `<object>.<key>` namespace during container expansion, and the default `list` implicitly claims `<object>.default`. A colliding form key was silently renamed to `<key>_2`, so any reference to the requested name (a form action `target`, a nav `viewName`) resolved to the OTHER view — the root cause of a form action opening a list view as a blank form. - spec: `expandViewContainer` gains a behaviour-preserving companion `expandViewContainerWithDiagnostics` reporting every name collision (zero-drift with the runtime expansion). Runtime behaviour unchanged. - cli: new `lint-view-refs` wired into `os compile`, with a broken/fragile severity split tuned NOT to break existing apps on upgrade — form target -> LIST view = ERROR (the concrete #2554 breakage); key collision = WARNING; target -> missing view = WARNING (avoids false positives). Shifts objectui's runtime viewKind guard left to build time. - examples/app-showcase: fix 3 real collisions (formViews.default -> edit), point the Log Time form action at the form view. - tests + api-surface snapshot synced. Verified: cli 466, metadata 257, full turbo build 71/71; revert-proof (bad target -> red, collision-only -> green+warning); 11 downstream apps (hotcrm + templates, 88 view containers) -> 0 false positives, 0 blocked. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
…nostics) #2556 (view-key collision boot warnings) landed on main while this branch was open. Reconciled by keeping BOTH: the merged `expandViewContainerWithDiagnostics` now pushes `collisions[]` (consumed by the new build-time `lint-view-refs`) AND stamps per-item `_diagnostics` (consumed by the boot loaders) at the same detection points. view-expand keeps both test suites (17 pass); showcase view/ action conflicts merged; .objectui-sha takes main's pin; api-surface unchanged; full turbo build 71/71. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Contributor
📓 Docs Drift CheckThis PR changes 3 package(s): 94 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #2554. Supersedes #2556.
Problem
listandformviews share one<object>.<key>namespace during container expansion, and the defaultlistimplicitly claims<object>.default. On a key collision the loser is silently renamed to<key>_2, so any reference to the requested name (a form actiontarget, a navviewName) resolves to the other view — the root cause of atype:'form'action opening a LIST view as a blank form (a submit can even silently no-op). objectui #2209 (landed the same day as #2556) turned the runtime symptom into a loud error; this PR shifts that guard left to build time.Fix
spec —
expandViewContainergains a behaviour-preserving companionexpandViewContainerWithDiagnosticsthat reports every<object>.<key>collision, captured at the exact points the sharedusedset forces a rename (zero-drift with the runtime expansion).expandViewContainerdelegates to it; runtime behaviour is unchanged.cli — new
lint-view-refswired intoos compile, mirroring the existing broken/fragile two-level authoring lints (flow-patterns, autonumber, liveness). Severity split tuned so an upgrade does NOT break existing apps that merely have a colliding key:view-ref-form-target-kind— atype:'form'target resolves to a LIST viewview-key-collisionview-ref-form-target-missingShifts objectui's runtime
viewKindguard left to compile time: the author (often an AI generating templates) sees the error onos compile, not the end user on click.examples/app-showcase — fix 3 real collisions the lint surfaced (
formViews.default→edit), and point the Log Time form action at the form view.Why not make list/form share a name at the storage level (the "pure" fix)?
That would need ~6
view-type special-cases across two registries'register/get/unregister, andget('view', name)is a hot path (GET /meta/:type/:name, hit on every form open). High-risk surgery to solve a problem objectui #2209 already de-fanged. This lint reaches the same north-star (author sees the error at build, not the user at click) with zero registry churn and zero data-migration risk.Verification
expandViewContainerdelegation invariance).os compilegreen; fullturbo build71/71.EEXIT 1); collision-only → build green + warning.type:'form'actions, so the target-kind gate's "catches real bugs" property is proven by the showcase revert-proof; the downstream run proves "never misfires".Blast radius
expandViewContainerbehaviour is unchanged; registry/addressing untouched; the lint only runs atos compile. Deployed apps are unaffected.🤖 Generated with Claude Code