Skip to content

fix(spec): view-reference build lint — collision warns, form-target errors (#2554)#2586

Merged
os-zhuang merged 3 commits into
mainfrom
fix/view-namespace-kind-aware
Jul 4, 2026
Merged

fix(spec): view-reference build lint — collision warns, form-target errors (#2554)#2586
os-zhuang merged 3 commits into
mainfrom
fix/view-namespace-kind-aware

Conversation

@os-zhuang

Copy link
Copy Markdown
Contributor

Closes #2554. Supersedes #2556.

Problem

list and form views share one <object>.<key> namespace during container expansion, and the default list implicitly claims <object>.default. On a key collision the loser is silently renamed to <key>_2, so any reference to the requested name (a form action target, a nav viewName) resolves to the other view — the root cause of a type:'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

  • specexpandViewContainer gains a behaviour-preserving companion expandViewContainerWithDiagnostics that reports every <object>.<key> collision, captured at the exact points the shared used set forces a rename (zero-drift with the runtime expansion). expandViewContainer delegates to it; runtime behaviour is unchanged.

  • cli — new lint-view-refs wired into os 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:

    rule severity why
    view-ref-form-target-kind — a type:'form' target resolves to a LIST view ERROR (fails build) the concrete expandViewContainer silently renames colliding form view keys (formViews.default → default_2) — form action targets break #2554 breakage; high-confidence
    view-key-collision WARNING fragile, not broken — only bites if the requested name is referenced
    view-ref-form-target-missing WARNING possibly a view the lint didn't collect — avoid a false-positive failure

    Shifts objectui's runtime viewKind guard left to compile time: the author (often an AI generating templates) sees the error on os compile, not the end user on click.

  • examples/app-showcase — fix 3 real collisions the lint surfaced (formViews.defaultedit), 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, and get('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

  • Unit: cli 466/466, metadata 257/257 (incl. collision capture + expandViewContainer delegation invariance).
  • E2E: showcase os compile green; full turbo build 71/71.
  • Revert-proof: target → LIST view → build red (EEXIT 1); collision-only → build green + warning.
  • Downstream dogfood: ran the lint against 11 real compiled stacks (hotcrm + 10 templates, 88 view containers) → 0 false positives, 0 blocked, 0 skipped (full object-name coverage). These apps carry no 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

🤖 Generated with Claude Code

os-zhuang and others added 2 commits July 4, 2026 11:05
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>
@vercel

vercel Bot commented Jul 4, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
spec Ready Ready Preview, Comment Jul 4, 2026 3:54pm

Request Review

…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>
@github-actions github-actions Bot added documentation Improvements or additions to documentation tests protocol:ui tooling size/l and removed documentation Improvements or additions to documentation tests protocol:ui tooling labels Jul 4, 2026
@github-actions

github-actions Bot commented Jul 4, 2026

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 3 package(s): @objectstack/cli, @objectstack/metadata, @objectstack/spec.

94 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:

  • content/docs/ai/agents.mdx (via @objectstack/spec)
  • content/docs/ai/skills-reference.mdx (via packages/cli, @objectstack/spec)
  • content/docs/ai/skills.mdx (via @objectstack/spec)
  • content/docs/api/client-sdk.mdx (via @objectstack/cli, @objectstack/spec)
  • content/docs/api/environment-routing.mdx (via @objectstack/cli, @objectstack/spec)
  • content/docs/api/error-catalog.mdx (via @objectstack/spec)
  • content/docs/api/error-handling-client.mdx (via @objectstack/spec)
  • content/docs/api/error-handling-server.mdx (via @objectstack/spec)
  • content/docs/api/index.mdx (via @objectstack/spec)
  • content/docs/automation/approvals.mdx (via packages/spec)
  • content/docs/automation/flows.mdx (via @objectstack/spec)
  • content/docs/automation/hook-bodies.mdx (via packages/cli, packages/spec)
  • content/docs/automation/hooks.mdx (via @objectstack/spec)
  • content/docs/automation/webhooks.mdx (via @objectstack/spec)
  • content/docs/automation/workflows.mdx (via @objectstack/spec)
  • content/docs/concepts/architecture.mdx (via @objectstack/spec)
  • content/docs/concepts/design-principles.mdx (via packages/spec)
  • content/docs/concepts/index.mdx (via @objectstack/spec)
  • content/docs/concepts/metadata-driven.mdx (via @objectstack/spec)
  • content/docs/concepts/metadata-lifecycle.mdx (via @objectstack/metadata, packages/spec)
  • content/docs/concepts/north-star.mdx (via packages/spec)
  • content/docs/data-modeling/analytics.mdx (via @objectstack/spec)
  • content/docs/data-modeling/drivers.mdx (via @objectstack/spec)
  • content/docs/data-modeling/external-datasources.mdx (via @objectstack/spec)
  • content/docs/data-modeling/field-types.mdx (via @objectstack/spec)
  • content/docs/data-modeling/fields.mdx (via @objectstack/spec)
  • content/docs/data-modeling/formulas.mdx (via @objectstack/spec)
  • content/docs/data-modeling/objects.mdx (via @objectstack/spec)
  • content/docs/data-modeling/queries.mdx (via @objectstack/spec)
  • content/docs/data-modeling/schema-design.mdx (via @objectstack/spec)
  • content/docs/data-modeling/seed-data.mdx (via @objectstack/spec)
  • content/docs/data-modeling/validation-rules.mdx (via @objectstack/spec)
  • content/docs/data-modeling/validation.mdx (via @objectstack/spec)
  • content/docs/deployment/cloud-artifact-api.mdx (via packages/cli, packages/spec)
  • content/docs/deployment/troubleshooting.mdx (via @objectstack/spec)
  • content/docs/getting-started/cli.mdx (via @objectstack/cli, @objectstack/spec)
  • content/docs/getting-started/common-patterns.mdx (via @objectstack/spec)
  • content/docs/getting-started/examples.mdx (via @objectstack/spec)
  • content/docs/getting-started/quick-reference.mdx (via @objectstack/spec)
  • content/docs/getting-started/quick-start.mdx (via @objectstack/cli, @objectstack/spec)
  • content/docs/getting-started/validating-metadata.mdx (via @objectstack/spec)
  • content/docs/kernel/cluster.mdx (via packages/metadata, @objectstack/spec)
  • content/docs/kernel/contracts/auth-service.mdx (via packages/spec)
  • content/docs/kernel/contracts/cache-service.mdx (via packages/spec)
  • content/docs/kernel/contracts/data-engine.mdx (via @objectstack/spec)
  • content/docs/kernel/contracts/index.mdx (via @objectstack/spec)
  • content/docs/kernel/contracts/metadata-service.mdx (via packages/spec)
  • content/docs/kernel/contracts/storage-service.mdx (via packages/spec)
  • content/docs/kernel/runtime-services/data-service.mdx (via packages/cli)
  • content/docs/kernel/runtime-services/email-service.mdx (via packages/spec)
  • content/docs/kernel/runtime-services/index.mdx (via packages/cli, packages/spec)
  • content/docs/kernel/runtime-services/queue-service.mdx (via packages/spec)
  • content/docs/kernel/runtime-services/sharing-service.mdx (via packages/spec)
  • content/docs/kernel/runtime-services/storage-service.mdx (via packages/spec)
  • content/docs/kernel/services-checklist.mdx (via @objectstack/spec)
  • content/docs/permissions/authentication.mdx (via @objectstack/cli)
  • content/docs/permissions/authorization.mdx (via packages/spec)
  • content/docs/permissions/permission-sets.mdx (via @objectstack/spec)
  • content/docs/permissions/permissions-matrix.mdx (via @objectstack/spec)
  • content/docs/permissions/profiles.mdx (via @objectstack/spec)
  • content/docs/permissions/roles.mdx (via @objectstack/spec)
  • content/docs/permissions/sharing-rules.mdx (via @objectstack/spec)
  • content/docs/plugins/adding-a-metadata-type.mdx (via @objectstack/spec)
  • content/docs/plugins/development.mdx (via @objectstack/spec)
  • content/docs/plugins/index.mdx (via @objectstack/spec)
  • content/docs/plugins/packages.mdx (via @objectstack/cli, @objectstack/metadata, @objectstack/spec)
  • content/docs/protocol/backward-compatibility.mdx (via @objectstack/spec)
  • content/docs/protocol/diagram.mdx (via packages/spec)
  • content/docs/protocol/knowledge.mdx (via @objectstack/spec)
  • content/docs/protocol/objectos/config-resolution.mdx (via @objectstack/spec)
  • content/docs/protocol/objectos/i18n-standard.mdx (via @objectstack/spec)
  • content/docs/protocol/objectos/lifecycle.mdx (via @objectstack/spec)
  • content/docs/protocol/objectos/metadata-service.mdx (via @objectstack/metadata)
  • content/docs/protocol/objectos/plugin-spec.mdx (via @objectstack/cli, @objectstack/spec)
  • content/docs/protocol/objectos/realtime-protocol.mdx (via @objectstack/cli)
  • content/docs/protocol/objectos/runtime-capabilities.mdx (via @objectstack/spec)
  • content/docs/protocol/objectql/index.mdx (via packages/spec)
  • content/docs/protocol/objectql/query-syntax.mdx (via @objectstack/spec)
  • content/docs/protocol/objectql/schema.mdx (via @objectstack/spec)
  • content/docs/protocol/objectql/security.mdx (via packages/spec)
  • content/docs/protocol/objectql/state-machine.mdx (via @objectstack/spec)
  • content/docs/protocol/objectui/actions.mdx (via @objectstack/spec)
  • content/docs/protocol/objectui/concept.mdx (via @objectstack/spec)
  • content/docs/protocol/objectui/index.mdx (via @objectstack/spec)
  • content/docs/protocol/objectui/layout-dsl.mdx (via packages/spec)
  • content/docs/protocol/objectui/record-alert.mdx (via @objectstack/spec)
  • content/docs/protocol/objectui/widget-contract.mdx (via @objectstack/spec)
  • content/docs/releases/implementation-status.mdx (via @objectstack/cli, @objectstack/spec)
  • content/docs/releases/index.mdx (via @objectstack/spec)
  • content/docs/releases/v9.mdx (via @objectstack/spec)
  • content/docs/ui/create-vs-edit-form.mdx (via @objectstack/spec)
  • content/docs/ui/dashboards.mdx (via @objectstack/spec)
  • content/docs/ui/forms.mdx (via @objectstack/spec)
  • content/docs/ui/setup-app.mdx (via @objectstack/spec)

Advisory only. To re-verify, run the docs-accuracy-audit workflow scoped to these files:
node scripts/docs-audit/affected-docs.mjs origin/main → pass the list as args.docs.

@os-zhuang
os-zhuang merged commit 069c205 into main Jul 4, 2026
17 checks passed
@os-zhuang
os-zhuang deleted the fix/view-namespace-kind-aware branch July 4, 2026 16:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

expandViewContainer silently renames colliding form view keys (formViews.default → default_2) — form action targets break

1 participant