You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@causeway.apache.org by da...@apache.org on 2026/09/03 16:42:10 UTC
(causeway) 01/16: docs(openspec): plan generic Vue web component viewer
This is an automated email from the ASF dual-hosted git repository.
danhaywood pushed a commit to branch htmx
in repository https://gitbox.apache.org/repos/asf/causeway.git
commit ea372fc6ddba56cc7045688f64c4ccc119de5089
Author: Dan Haywood <da...@haywood-associates.co.uk>
AuthorDate: Thu Sep 3 07:38:45 2026 +0100
docs(openspec): plan generic Vue web component viewer
---
.../.openspec.yaml | 0
.../add-generic-vue-web-component-viewer/design.md | 174 +++++++++++
.../proposal.md | 39 +++
.../specs/generic-vue-web-component-viewer/spec.md | 347 +++++++++++++++++++++
.../add-generic-vue-web-component-viewer/tasks.md | 70 +++++
.../add-generic-vue-web-component-viewer/design.md | 99 ------
.../proposal.md | 36 ---
.../specs/generic-vue-web-component-viewer/spec.md | 92 ------
.../add-generic-vue-web-component-viewer/tasks.md | 29 --
9 files changed, 630 insertions(+), 256 deletions(-)
diff --git a/openspec/planned-changes/web-component-viewer/add-generic-vue-web-component-viewer/.openspec.yaml b/openspec/changes/add-generic-vue-web-component-viewer/.openspec.yaml
similarity index 100%
rename from openspec/planned-changes/web-component-viewer/add-generic-vue-web-component-viewer/.openspec.yaml
rename to openspec/changes/add-generic-vue-web-component-viewer/.openspec.yaml
diff --git a/openspec/changes/add-generic-vue-web-component-viewer/design.md b/openspec/changes/add-generic-vue-web-component-viewer/design.md
new file mode 100644
index 00000000000..1fb35e0329a
--- /dev/null
+++ b/openspec/changes/add-generic-vue-web-component-viewer/design.md
@@ -0,0 +1,174 @@
+## Context
+
+Vue provides component composition, application plugins, dynamic components, async components, and a mature router.
+Causeway's custom elements already own GraphQL execution, semantic context, object layout, menus, editors, validation, interaction dispatch, action-result rendering, and domain-state concurrency.
+Applications can declare those elements directly in Vue single-file component templates.
+The Vue viewer should therefore be an integration package for browser routing, route-value binding, semantic-event policy, and framework lifecycle rather than a Vue rewrite of the component library.
+
+The accepted HTMX viewer established two relevant ownership rules.
+The application owns the stable application shell, while each replaceable route page owns its semantic object context and interaction controller.
+The Vue design applies the same semantic split through framework-native source templates rather than through classpath HTML resources.
+
+## Goals / Non-Goals
+
+**Goals:**
+
+- Provide canonical deep-linkable object routes through an application-owned Vue Router instance.
+- Support exact-logical-type custom Vue pages and a generic `<cw-object>` fallback.
+- Keep the GraphQL provider, menu coordination, result outlet, and application chrome stable across route changes.
+- Bind endpoint and route identity into authored custom elements without imperatively creating them.
+- Bridge semantic navigation and result events into replaceable Vue policy.
+- Package a typed reusable Vue integration and a production-built Petclinic acceptance application.
+- Preserve deterministic lifecycle, accessibility, theming, and cross-viewer route meaning.
+
+**Non-Goals:**
+
+- Wrapping each Causeway custom element as a Vue component.
+- Reimplementing GraphQL operations, metadata interpretation, domain validation, object layout, menus, editors, or result rendering in Vue.
+- Making `<cw-object>` inspect Vue Router, Vue injection state, or the custom-page registry.
+- Introducing Pinia or another duplicate domain-state store.
+- Owning an application's complete router, HTML document, deployment topology, authentication UI, or static-resource server.
+- Supporting Nuxt, server-side rendering, streaming hydration, or server-only route data in the first version.
+- Adding inherited-logical-type page matching or runtime page-registry mutation in the first version.
+
+## Decisions
+
+### Deliver an optional typed Vue package
+
+The primary frontend artifact is an npm package under `viewers/webcomponents/vue` targeting Vue 3 and Vue Router 4.
+Vue and Vue Router are peer dependencies and are external to the library bundle, so installing or building the framework-neutral component modules does not acquire a Vue runtime.
+The package exports ECMAScript modules and TypeScript declarations and is built reproducibly with Vite library mode from a committed lockfile.
+Package verification includes unit tests, production build, declaration generation, package-content inspection, dependency licensing, and an install-from-packed-artifact smoke test.
+
+A lightweight Maven module integrates verification and release metadata with the web-components reactor without making Vue transitive to the foundation or HTMX artifacts.
+Any generated browser assets committed or packaged for a sample are reproducible from locked sources and retain the required third-party notices.
+
+### Integrate with an application-owned router
+
+The package does not create or hide a router instance.
+It exports namespaced Causeway route records and a plugin that an application installs beside its own Vue Router instance.
+The application remains free to add unrelated routes, guards, scroll behavior, and deployment-specific history configuration.
+
+The application supplies the history base to `createWebHistory`, mounts the returned Causeway records at the documented viewer path, and configures its server to return the Vue document for valid client routes.
+The package documents this direct-refresh contract but does not catch unrelated backend, GraphQL, or asset URLs.
+Hash history is not the default because it would change the cross-viewer bookmark grammar.
+
+### Use an independent canonical route codec
+
+Route creation and route acceptance use one Vue viewer codec for the canonical `<base-path>/object/<logical-type>/<identifier>` grammar.
+The codec applies the same canonical UTF-8 percent encoding, separator rejection, dot-segment rejection, control-character rejection, malformed-Unicode rejection, and encoded-segment bound as the existing viewer contract.
+It validates the raw URL path before binding decoded values because Vue Router parameters alone cannot prove that the original encoding was canonical.
+
+The Vue codec is tested against `viewers/webcomponents/canonical-route-fixtures.yaml` and against generated round trips.
+Navigation policy pushes codec-produced paths rather than relying on implicit router-parameter encoding.
+Invalid routes render a bounded invalid-route page and never reach a semantic object context.
+
+### Normalize an immutable exact-type page registry
+
+Plugin creation accepts a map from exact public logical type to either a Vue component or an async component loader.
+Registration keys are normalized once, and empty, malformed, or duplicate effective registrations fail during application startup.
+Arbitrary factories and inheritance fallback are excluded from the first contract because Vue components and async loaders already cover synchronous and code-split pages without introducing a second lifecycle model.
+
+The object route controller validates canonical identity and chooses the exact registration before mounting route content.
+If no registration exists, it selects the package's generic route page.
+Async loading is associated with the current route key, exposes an accessible loading and error presentation, and cannot mount a component after that route has been superseded.
+
+### Keep semantic route boundaries application-authored
+
+Every custom route-page component receives immutable `logicalTypeName`, `objectId`, and `routeKey` props.
+Its source template declares one marked route-level `<cw-object-context>`, binds the identity props to that element, and declares one `<cw-interaction-controller>` within the context.
+The generic route page follows the same contract and additionally declares `<cw-object editable>`.
+
+The package may render an ordinary non-semantic wrapper for lifecycle observation, but it does not create, move, select, or repair semantic provider elements.
+After each page mount, a bounded development validator confirms the route-context and interaction-controller cardinality, containment, and bound identity.
+An invalid page fails closed to a safe diagnostic rather than querying through an ancestor context or retaining stale route content.
+
+`RouterView` uses a canonical route key rather than component type alone.
+Changing logical type or identifier therefore disconnects the old object context and lets the established component disconnect contract release requirements, subscriptions, cancellation state, and obsolete responses.
+
+### Keep the stable shell application-owned
+
+The application's root `App.vue` owns the complete stable body composition inside the Vue mount point.
+It declares exactly one shell-level `<cw-graphql-client>`, binds the configured endpoint, and places `<cw-menubars>`, branding, authentication chrome when applicable, route loading, announcements, a default `<cw-action-results>` outlet, and the router-view region beneath that provider.
+The provider and menus remain mounted while keyed route pages change.
+
+The package exports composables and small route-view helpers, not a mandatory visual shell hierarchy.
+A reference shell and theme are supplied as copyable source in the Vue Petclinic application and documentation.
+A bounded shell validator diagnoses missing or duplicate protocol landmarks during development and tests, but never manufactures or relocates them.
+
+The HTML document remains application-owned and loads the framework-neutral Causeway registration module and selected toolkit assets before or alongside the bundled Vue entry point.
+Applications retain authority over CSP, base URL, locale, initial color scheme, global CSS, authentication metadata, and deployment-specific script delivery.
+
+### Treat custom elements as the data plane
+
+Both the package build and documented consuming Vite configuration classify `cw-` tags as native custom elements through Vue compiler options.
+String identity values may use ordinary bindings, while structured services and values use DOM-property bindings, including Vue's explicit `.prop` modifier where necessary.
+Native `CustomEvent` payloads remain authoritative and are not converted into Vue component-emits contracts.
+
+The plugin installs a scoped event bridge on the stable shell boundary and removes it when the Vue application unmounts.
+The bridge receives semantic navigation, interaction completion, and result events and invokes injected viewer policy.
+It does not alter GraphQL documents, validation outcomes, authoritative identity, interaction ordering, or component refresh behavior.
+
+### Define default navigation, home, and result policy
+
+Default object navigation and object results use the canonical codec and `router.push` to reach the corresponding object route.
+The policy accepts only complete advertised public identity and presents a bounded unsupported result when canonical navigation identity is unavailable.
+
+The home route uses the accepted application-entry semantics and permits an application-provided home component or handler.
+An object-valued default home outcome navigates canonically, while an unavailable home remains an accessible landing state.
+
+Scalar and collection results are assigned to the declared active-page result outlet when exactly one valid outlet exists, otherwise to the one shell-level default outlet.
+The existing `<cw-action-results>` and `<cw-standalone-collection>` components retain presentation authority.
+Void results refresh the current object context when it still exists and return home only when an authoritative refresh establishes that the target disappeared.
+Applications may replace navigation, home, and result handlers, and a documented claim protocol prevents both default and application policy from handling the same event.
+
+### Separate route failure from domain failure
+
+Malformed or non-canonical paths fail before object lookup.
+A valid route then relies on object-context observable states for schema loading, object loading, ready, partial error, and terminal error.
+Not-found and access-denied presentation does not reveal domain state or authorization rules, and the default unavailable presentation does not claim to distinguish outcomes that GraphQL intentionally makes indistinguishable.
+
+Route navigation sets the route region busy, announces completion or failure through the authored live region, and moves focus to the current page heading or route container according to documented policy.
+Superseded async imports and obsolete context responses cannot update the current route's focus, announcement, or status.
+
+### Reuse Petclinic rather than duplicate it
+
+A small shared Petclinic domain module is extracted from the existing HTMX sample so the HTMX and Vue host applications use the same entities, public logical types, fixtures, GraphQL behavior, and deterministic identities.
+The extraction changes Java packaging only where required and must not alter domain semantics, HTMX routes, resource-page lookup, seed cardinalities, or existing acceptance selectors.
+
+The new Vue Petclinic module owns its Spring Boot entry point, Vite application, `index.html`, `App.vue`, custom logical-type pages, generic fallback demonstration, and client-route forwarding.
+It uses production Vite output served by the application rather than a development server or runtime template compiler.
+At least one Petclinic logical type has a source-visible custom Vue page, and another uses the generic route fallback.
+
+### Keep first release client-rendered
+
+The supported lifecycle is a browser-created Vue application using Vue Router history.
+Nuxt, SSR, streaming hydration, and server-rendered custom-element upgrade require separate compatibility work and are explicitly unsupported rather than partially emulated.
+
+## Risks / Trade-offs
+
+- [Raw route encoding can be lost by router normalization] → Validate the raw path with the canonical codec before using decoded route parameters and test all shared invalid fixtures.
+- [Vue can resolve `cw-` tags as Vue components] → Configure `isCustomElement` in library and consuming builds and test compiled output.
+- [Vue can assign an attribute where a DOM property is required] → Document and test property bindings, including explicit `.prop` bindings for structured values.
+- [Route reuse can retain obsolete object state] → Key the rendered route component by canonical identity and verify disconnect and cancellation behavior.
+- [An authored page can omit or duplicate its semantic boundary] → Validate cardinality, containment, and bound identity and fail closed without repair.
+- [An async page can resolve after navigation] → Scope imports, diagnostics, focus, and announcements to the active route key.
+- [A duplicate Vue domain store can emerge] → Keep only router and viewer policy in Vue state and forbid mirroring GraphQL object, member, validation, or interaction state.
+- [Browser-history refresh can be mistaken for a frontend-only concern] → Specify and test the application server fallback independently of package route resolution.
+- [Sharing Petclinic can regress the HTMX sample] → Preserve logical types and fixture identities and run the existing HTMX Java and Playwright suites after extraction.
+- [Frontend tooling can leak into unrelated builds] → Keep Vue dependencies in the opt-in package and sample profiles and verify unaffected foundation and HTMX consumers.
+
+## Migration Plan
+
+The Vue viewer is additive and installed only by applications that select it.
+Applications create or reuse a Vue Router instance, add the exported route records, install the viewer plugin, author their stable shell, and configure server fallback for the chosen history base.
+They may begin with the generic route page and incrementally register exact logical-type custom pages.
+Rollback removes the plugin, route records, and Vue application assets without changing GraphQL or semantic component contracts.
+The Petclinic domain extraction is performed in one compatibility-preserving step before the Vue host application depends on it.
+
+## Deferred Work
+
+- Inherited or assignable logical-type page matching.
+- Runtime mutation of the page registry.
+- Nuxt, SSR, streaming hydration, and server route-data integration.
+- A framework-specific authentication package beyond application-owned shell chrome and existing GraphQL transport policy.
diff --git a/openspec/changes/add-generic-vue-web-component-viewer/proposal.md b/openspec/changes/add-generic-vue-web-component-viewer/proposal.md
new file mode 100644
index 00000000000..f057563a0b4
--- /dev/null
+++ b/openspec/changes/add-generic-vue-web-component-viewer/proposal.md
@@ -0,0 +1,39 @@
+## Why
+
+Vue applications need a complete generic Causeway viewer rather than examples that only place individual custom elements.
+The accepted component contracts now provide application entry points, semantic object contexts, object composition, menus, interactions, result outlets, collection previews, and toolkit-backed presentation.
+The remaining Vue-specific work is therefore deliberately thin: own browser routing and host lifecycle policy, bind route and endpoint values into application-authored semantic markup, and leave authoritative domain behavior in the framework-neutral components.
+
+## What Changes
+
+- Add an optional Vue 3 and Vue Router 4 package with TypeScript declarations, reproducible Vite library output, and no Vue dependency in the framework-neutral component artifact.
+- Export an application-owned-router integration consisting of route-record creation, a Vue plugin, route codecs, route-page components, composables, and replaceable navigation, home, and result policies.
+- Implement the canonical `<base-path>/object/<logical-type>/<identifier>` bookmark grammar and validate it against the shared cross-viewer route fixtures.
+- Resolve an exact logical-type Vue component or async component before falling back to a generic Vue route page containing `<cw-object>`.
+- Require application-authored Vue route pages to declare one `<cw-object-context>` and one route interaction controller, with Vue binding canonical identity rather than manufacturing semantic elements.
+- Require the application root component to own the stable shell, including one `<cw-graphql-client>`, `<cw-menubars>`, announcements, loading presentation, a result outlet, and the keyed router-view region.
+- Bridge authoritative custom-element navigation and interaction-result events into replaceable Vue policy without constructing GraphQL operations or mirroring domain state into a Vue store.
+- Configure and document native custom-element compilation, property binding, event handling, upgrade ordering, and deterministic cleanup.
+- Provide accessible route lifecycle, invalid-route, unavailable, partial-error, terminal-error, theme, and responsive behavior.
+- Add a production-built Vue Petclinic acceptance application that reuses the deterministic Petclinic domain without duplicating it and supports direct browser-history refresh through an application-owned server fallback.
+- Integrate package, browser, accessibility, Maven-reactor, licensing, and distribution verification while keeping npm installation and Vue runtime opt-in.
+
+## Capabilities
+
+### New Capabilities
+
+- `generic-vue-web-component-viewer`: Provides a router-led generic Vue Causeway viewer over the framework-neutral semantic web-component library.
+
+### Modified Capabilities
+
+None.
+
+## Impact
+
+- Adds Vue viewer package sources and generated distribution metadata under `viewers/webcomponents/vue`.
+- Adds a Vue Petclinic sample and the minimal shared Petclinic domain module needed by the HTMX and Vue host applications.
+- Updates the web-components reactor, test profiles, documentation, shared route fixtures, and release/licensing checks.
+- Relies on the accepted `graphql-web-component-context`, `domain-web-components`, rich GraphQL application-entry and interaction capabilities, and their declarative ownership contracts.
+- Preserves the existing GraphQL schema, public logical types, deterministic Petclinic identities, HTMX routes, and component semantics.
+- Does not require Vue, Vue Router, Vite, or a frontend build runtime for HTMX, vanilla HTML, or direct framework-neutral component consumers.
+- Does not add Nuxt, server-side rendering, streaming hydration, or a Vue-specific domain data store.
diff --git a/openspec/changes/add-generic-vue-web-component-viewer/specs/generic-vue-web-component-viewer/spec.md b/openspec/changes/add-generic-vue-web-component-viewer/specs/generic-vue-web-component-viewer/spec.md
new file mode 100644
index 00000000000..299abc8f28b
--- /dev/null
+++ b/openspec/changes/add-generic-vue-web-component-viewer/specs/generic-vue-web-component-viewer/spec.md
@@ -0,0 +1,347 @@
+## ADDED Requirements
+
+### Requirement: Optional packaged Vue viewer
+
+The project SHALL provide an explicitly installed Vue 3 viewer package that uses Vue Router 4 for host routing and semantic Causeway custom elements for domain behavior.
+Vue, Vue Router, and Vue build tooling MUST NOT become runtime or build dependencies of the framework-neutral component, HTMX viewer, or vanilla HTML artifacts.
+
+#### Scenario: Vue viewer is installed
+
+- **WHEN** a Vue application installs the package and its router integration
+- **THEN** the documented Causeway route records, route pages, composables, and policy hooks are available
+- **AND** authoritative domain state remains owned by semantic components
+
+#### Scenario: Vue viewer is absent
+
+- **WHEN** an application does not install the package
+- **THEN** Vue, Vue Router, and Vite are not required to consume the framework-neutral component library
+- **AND** existing HTMX and vanilla applications retain their established behavior
+
+#### Scenario: Package artifact is inspected
+
+- **WHEN** the Vue package is built and packed from its lockfile
+- **THEN** it contains ECMAScript library output, TypeScript declarations, documented peer dependencies, licenses, and only intended public files
+- **AND** a clean consumer can install and import the packed artifact
+
+### Requirement: Application-owned Vue Router integration
+
+The viewer SHALL export namespaced Causeway route records and installation helpers for an application-owned Vue Router instance.
+The viewer MUST NOT create a hidden router or prevent the application from defining unrelated routes, guards, history behavior, or scroll policy.
+
+#### Scenario: Causeway routes are added
+
+- **WHEN** an application adds the exported records to its router and installs the viewer plugin
+- **THEN** Causeway home, object, invalid-route, and fallback states coexist with application routes
+- **AND** viewer navigation uses that same router instance and history
+
+#### Scenario: Viewer is mounted beneath a base
+
+- **WHEN** the application configures a valid non-root browser-history base and route mount
+- **THEN** home, object, asset, refresh, and history URLs consistently honor that deployment
+- **AND** the viewer does not assume origin-root deployment
+
+#### Scenario: Direct history refresh reaches the application
+
+- **WHEN** a canonical Vue object bookmark is requested directly from the application server
+- **THEN** application-owned server fallback returns the Vue document for that client route
+- **AND** does not intercept GraphQL, static asset, authentication, or unrelated backend routes
+
+### Requirement: Canonical Vue bookmark routing
+
+The viewer SHALL map a public logical type and opaque identifier to the documented `<base-path>/object/<logical-type>/<identifier>` grammar.
+Route generation and raw-path acceptance MUST apply the same canonical UTF-8 percent encoding, separator rules, malformed-input rejection, and encoded-segment bound as the cross-viewer contract.
+
+#### Scenario: Canonical bookmark loads
+
+- **WHEN** a valid authorized bookmark is opened, refreshed, restored, or revisited through browser history
+- **THEN** Vue Router renders the page for the exact logical type and identifier
+- **AND** the browser location has the same route meaning as the HTMX viewer
+
+#### Scenario: Semantic navigation is requested
+
+- **WHEN** a component publishes complete authoritative object identity
+- **THEN** default Vue navigation pushes the codec-produced canonical path
+- **AND** does not reinterpret or truncate the identifier
+
+#### Scenario: Route encoding is invalid
+
+- **WHEN** a raw route contains malformed escapes, empty values, encoded separators, control characters, dot segments, malformed Unicode, overlong encoded segments, or non-canonical encoding
+- **THEN** the viewer presents a bounded invalid-route state before mounting an object context
+- **AND** does not disclose submitted route content, object state, authorization rules, or raw decoder exceptions
+
+#### Scenario: Shared route fixtures are exercised
+
+- **WHEN** the Vue route codec is verified
+- **THEN** every valid and invalid entry in `viewers/webcomponents/canonical-route-fixtures.yaml` has the same outcome as the established viewer contract
+- **AND** generated valid identities round-trip without loss
+
+### Requirement: Immutable exact-type Vue page registry
+
+The viewer SHALL normalize an application-supplied registry from exact public logical type to a Vue component or async component loader during plugin creation.
+Exact registration SHALL take precedence over the generic route page, and runtime registry mutation or inheritance fallback SHALL NOT be part of the initial contract.
+
+#### Scenario: Vue page is registered
+
+- **WHEN** a canonical route resolves a logical type with an exact synchronous registration
+- **THEN** the registered Vue component receives immutable canonical route props
+- **AND** the generic page is not mounted
+
+#### Scenario: Async Vue page is registered
+
+- **WHEN** the exact registration is an async component loader
+- **THEN** the viewer presents the current route's accessible loading state until that component resolves
+- **AND** loader rejection presents a bounded current-route error
+
+#### Scenario: No Vue page is registered
+
+- **WHEN** no exact registration exists
+- **THEN** the route renders the package's declarative generic page
+- **AND** that page contains `<cw-object editable>` within the route object context
+
+#### Scenario: Registry is defective
+
+- **WHEN** registration has an empty or malformed logical type, an unsupported value, or a duplicate effective key
+- **THEN** plugin installation fails with a bounded diagnostic
+- **AND** no arbitrary registration is selected
+
+### Requirement: Declarative Vue route context boundary
+
+Every custom and generic Vue object page SHALL declare exactly one marked route-level `<cw-object-context>` bound to the canonical logical type and identifier and exactly one `<cw-interaction-controller>` contained by that context.
+The viewer SHALL validate this authored boundary without creating, moving, selecting, or repairing semantic elements.
+
+#### Scenario: Valid custom page mounts
+
+- **WHEN** a registered page declares and binds the required context and interaction controller
+- **THEN** semantic descendants obtain the established GraphQL, object, and interaction services
+- **AND** Vue does not mirror object, member, validation, or interaction state
+
+#### Scenario: Declared context awaits Vue bindings
+
+- **WHEN** an authored context connects before Vue has supplied complete route props
+- **THEN** it issues no object query while identity is incomplete
+- **AND** becomes operational after complete canonical identity is bound
+
+#### Scenario: Route boundary is invalid
+
+- **WHEN** the mounted page omits or duplicates the marked context, misplaces the interaction controller, or binds identity different from the canonical route
+- **THEN** the route fails closed to a bounded diagnostic
+- **AND** does not query through an ancestor context, retain prior content, or manufacture a replacement
+
+#### Scenario: Generic component connects
+
+- **WHEN** `<cw-object>` renders the route object
+- **THEN** it uses effective or fallback grid behavior from the semantic component contract
+- **AND** does not inspect Vue Router, Vue injection state, or the page registry
+
+### Requirement: Stable application-authored Vue shell
+
+The application root Vue component SHALL declare one stable `<cw-graphql-client>` containing application chrome, `<cw-menubars>`, loading and announcement landmarks, one default result outlet, and the router-view region.
+The viewer SHALL expose endpoint and policy values for binding but SHALL NOT manufacture or prescribe the visual placement of those semantic elements.
+
+#### Scenario: Vue object route changes
+
+- **WHEN** the keyed router-view region changes canonical object identity
+- **THEN** the declared GraphQL client and menu coordination remain connected
+- **AND** the obsolete route context and interaction controller disconnect deterministically
+
+#### Scenario: Application chooses its shell layout
+
+- **WHEN** an application places menus, branding, results, route content, auxiliary regions, or footer differently from the reference shell
+- **THEN** routing, menu events, loading, results, announcements, focus, and context disposal retain their documented behavior
+- **AND** no vertical-menu or other visual hierarchy is imposed by the viewer package
+
+#### Scenario: Shell protocol is defective
+
+- **WHEN** the root composition omits or duplicates its provider, route region, default result outlet, loading landmark, or announcement landmark
+- **THEN** bounded development and test diagnostics identify the invalid contract
+- **AND** the viewer does not create, move, or silently select a landmark
+
+#### Scenario: Application document is authored
+
+- **WHEN** the Vue application loads
+- **THEN** its application-owned HTML document selects Causeway registration, toolkit assets, locale, CSP, base URL, theme, and Vue entry assets
+- **AND** the viewer package does not replace that document policy
+
+### Requirement: Native Vue custom-element integration
+
+The package and documented consuming build SHALL classify `cw-` tags as native custom elements and preserve their attributes, DOM properties, slots, `CustomEvent` payloads, upgrade behavior, and disconnect lifecycle.
+Structured values and services SHALL be assigned as DOM properties rather than serialized into unintended attributes.
+
+#### Scenario: Vue template is compiled
+
+- **WHEN** a package or application single-file component contains a `cw-` tag
+- **THEN** Vue compiles it as a native custom element rather than resolving a Vue component
+- **AND** authored descendants and slots remain available to the element's declarative capture lifecycle
+
+#### Scenario: Structured value is bound
+
+- **WHEN** Vue supplies a structured executor, result, or other property-only value to a custom element
+- **THEN** the value is assigned through the element's DOM property contract
+- **AND** is not stringified as an HTML attribute
+
+#### Scenario: Semantic event is published
+
+- **WHEN** a Causeway component emits navigation, interaction, or result semantics
+- **THEN** the scoped Vue bridge forwards the authoritative payload once to replaceable viewer policy
+- **AND** does not modify the originating GraphQL operation or semantic outcome
+
+#### Scenario: Vue application unmounts
+
+- **WHEN** the host application is unmounted
+- **THEN** the bridge removes its listeners and pending viewer lifecycle work
+- **AND** disconnected semantic elements perform their normal cleanup
+
+### Requirement: Vue navigation, home, and result policy
+
+The viewer SHALL provide replaceable policy for object navigation, application-entry home behavior, and scalar, object, collection, and void action results.
+Application handlers SHALL receive semantic payloads through a documented single-claim protocol without replacing component interaction behavior.
+
+#### Scenario: Object result uses default policy
+
+- **WHEN** an interaction returns complete navigable object identity and no application handler claims it
+- **THEN** default policy navigates to the canonical Vue object route
+- **AND** the component-provided identity remains authoritative
+
+#### Scenario: Object result lacks navigation identity
+
+- **WHEN** an object-shaped result lacks the required public logical type or opaque identifier
+- **THEN** default policy presents a bounded unsupported result
+- **AND** does not infer identity from title, type name, current route, or Vue state
+
+#### Scenario: Non-object result uses a page outlet
+
+- **WHEN** a scalar or collection result is unclaimed and the active page declares exactly one eligible result outlet
+- **THEN** default policy assigns the normalized result to that outlet
+- **AND** established semantic result components retain presentation authority
+
+#### Scenario: Non-object result uses the shell outlet
+
+- **WHEN** a scalar or collection result is unclaimed and the active page has no eligible result outlet
+- **THEN** default policy assigns it to the one declared shell outlet
+- **AND** duplicate or disconnected outlets fail closed rather than receiving an arbitrary result
+
+#### Scenario: Void result retains its target
+
+- **WHEN** a successful void action leaves the current route object available
+- **THEN** default policy refreshes the current object context without adding a history entry
+- **AND** preserves accessible result status
+
+#### Scenario: Void result removes its target
+
+- **WHEN** the authoritative post-action refresh establishes that the current route object no longer exists
+- **THEN** default policy replaces the route with configured home
+- **AND** does not leave a stale object page in history state
+
+#### Scenario: Application replaces policy
+
+- **WHEN** an application handler claims a navigation, home, or result event
+- **THEN** the handler receives the unchanged semantic payload
+- **AND** default policy does not also handle that event
+
+### Requirement: Accessible generation-scoped route lifecycle
+
+The viewer SHALL coordinate accessible loading, ready, invalid-route, unavailable, partial-error, unsupported, and terminal-error states for the current route generation.
+Focus, busy state, and announcements MUST belong only to the current canonical route.
+
+#### Scenario: Navigation begins
+
+- **WHEN** Vue Router starts a Causeway route transition or an async page begins loading
+- **THEN** the authored route region exposes a busy state and the authored live region announces bounded progress
+- **AND** the previous route cannot overwrite that generation's status
+
+#### Scenario: Navigation completes
+
+- **WHEN** the current page is mounted and reaches its presentable state
+- **THEN** focus moves to the current page heading or documented route container
+- **AND** the live region announces the current authoritative title without duplicating component-local announcements
+
+#### Scenario: Async page is superseded
+
+- **WHEN** navigation changes before an async registered page resolves or rejects
+- **THEN** the obsolete page, error, focus movement, and announcement are discarded
+- **AND** the current route remains authoritative
+
+#### Scenario: Domain data is partially available
+
+- **WHEN** the current object context reports a partial GraphQL error with usable sibling data
+- **THEN** the page preserves usable semantic content and exposes bounded partial-error status
+- **AND** does not replace the whole route with a terminal state
+
+#### Scenario: Object cannot be presented
+
+- **WHEN** a canonical object route yields unavailable or denied data
+- **THEN** the default presentation reveals neither domain state nor authorization rules
+- **AND** does not claim to distinguish outcomes that the authoritative transport leaves indistinguishable
+
+### Requirement: Vue theme and responsive shell contract
+
+The viewer SHALL provide a copyable reference theme and stable styling hooks while leaving application CSS and shell geometry authoritative.
+The reference application SHALL support wide and narrow layouts, light and dark color preferences, reduced motion, keyboard operation, and visible focus.
+
+#### Scenario: Application supplies its own theme
+
+- **WHEN** an application overrides documented custom properties or shell classes
+- **THEN** routing and semantic component behavior remain unchanged
+- **AND** component shadow-part and custom-property contracts remain available
+
+#### Scenario: Narrow or reduced-motion presentation applies
+
+- **WHEN** viewport width or motion preference changes
+- **THEN** shell content remains operable without obscuring the active route or result
+- **AND** transitions do not interfere with focus or announcements
+
+### Requirement: Executable Vue Petclinic acceptance application
+
+The project SHALL provide a production-built Vue Petclinic application that reuses the same deterministic Petclinic domain, public logical types, and fixture identities as the HTMX sample without copying domain implementation.
+The application SHALL demonstrate a source-visible custom Vue page, generic fallback, stable shell, menus, interactions, results, canonical routing, and server refresh fallback.
+
+#### Scenario: Custom Petclinic page loads
+
+- **WHEN** the configured Petclinic logical type is opened through a direct canonical bookmark
+- **THEN** its registered Vue single-file component binds the declared object context and renders semantic members
+- **AND** the source demonstrates application-owned layout and interaction-controller placement
+
+#### Scenario: Generic Petclinic page loads
+
+- **WHEN** another Petclinic logical type has no registration
+- **THEN** the generic Vue page renders `<cw-object>` for the same GraphQL identity
+- **AND** direct refresh and browser history retain that route
+
+#### Scenario: Existing HTMX Petclinic is rebuilt
+
+- **WHEN** the Petclinic domain is shared with the new Vue application
+- **THEN** existing HTMX routes, pages, shell, seed cardinalities, stable identities, and acceptance behavior remain unchanged
+- **AND** the shared module introduces no Vue dependency
+
+#### Scenario: Acceptance suite runs
+
+- **WHEN** the Vue browser profile executes
+- **THEN** it covers direct links, refresh, back and forward, exact custom-page precedence, generic fallback, menus, property and action interactions, object and collection results, partial errors, invalid routes, absent objects, responsive layout, keyboard focus, announcements, and both supported component toolkit policies
+- **AND** browser console errors, page errors, failed resource requests, and accessibility violations fail the suite
+
+### Requirement: Reactor and release integration
+
+The Vue package, shared sample domain, and Vue Petclinic application SHALL integrate with the web-components reactor and project release checks while retaining opt-in frontend dependency installation.
+Reproducible frontend regeneration SHALL be separated from unrelated runtime consumers and documented for maintainers.
+
+#### Scenario: Ordinary project build runs
+
+- **WHEN** the normal Maven reactor builds the web-components modules
+- **THEN** Java artifacts and committed or packaged Vue outputs are verified without making Vue runtime classes transitive to non-Vue modules
+- **AND** licensing and stale-generated-output checks remain enforceable
+
+#### Scenario: Vue verification profile runs
+
+- **WHEN** the documented Vue verification profile or frontend command is selected
+- **THEN** locked dependencies are installed, unit tests and type checks run, production artifacts are regenerated, package contents are verified, and browser acceptance can be selected
+- **AND** a generated-output difference fails verification
+
+### Requirement: Initial client-rendered scope
+
+The first generic Vue viewer SHALL document browser client rendering as its supported lifecycle and SHALL NOT imply verified Nuxt, SSR, or streaming-hydration compatibility.
+
+#### Scenario: SSR support is requested
+
+- **WHEN** an application requires Nuxt, SSR, streaming hydration, or server-only route data
+- **THEN** the viewer reports that capability as separate compatibility work
+- **AND** does not silently provide inconsistent custom-element hydration
diff --git a/openspec/changes/add-generic-vue-web-component-viewer/tasks.md b/openspec/changes/add-generic-vue-web-component-viewer/tasks.md
new file mode 100644
index 00000000000..3c8aa638272
--- /dev/null
+++ b/openspec/changes/add-generic-vue-web-component-viewer/tasks.md
@@ -0,0 +1,70 @@
+## 1. Package and Build Contract
+
+- [ ] 1.1 Add the optional `viewers/webcomponents/vue` Vue 3 and Vue Router 4 package with TypeScript sources, package metadata, a committed lockfile, Vite library mode, peer dependencies, ECMAScript exports, and declarations.
+- [ ] 1.2 Add the lightweight Maven/reactor integration and explicit frontend regeneration profile without making Vue dependencies transitive to foundation, HTMX, or vanilla consumers.
+- [ ] 1.3 Configure Vue single-file component compilation to recognize `cw-` tags as native custom elements in the library and documented consumer setup.
+- [ ] 1.4 Add package unit-test, type-check, production-build, stale-output, license, `npm pack`, package-content, and clean packed-consumer smoke checks.
+- [ ] 1.5 Document the public package exports and keep unimplemented Nuxt, SSR, runtime registry mutation, and inherited-type matching out of the initial API.
+
+## 2. Canonical Router Integration
+
+- [ ] 2.1 Implement the bounded canonical UTF-8 route encoder and raw-path decoder for `<base-path>/object/<logical-type>/<identifier>` without relying on already-decoded Vue Router parameters.
+- [ ] 2.2 Test valid, invalid, overlong, Unicode, non-canonical, and generated round-trip routes against `viewers/webcomponents/canonical-route-fixtures.yaml`.
+- [ ] 2.3 Export namespaced home, object, invalid-route, and fallback route records for an application-owned Vue Router instance.
+- [ ] 2.4 Implement plugin installation and injected viewer configuration without creating a hidden router or overriding unrelated application routes, guards, scroll behavior, or history policy.
+- [ ] 2.5 Implement codec-produced push and replace helpers that preserve configured base-path meaning and complete advertised identity.
+- [ ] 2.6 Document and integration-test application-owned browser-history server fallback without intercepting GraphQL, assets, authentication, or unrelated backend routes.
+
+## 3. Custom and Generic Route Pages
+
+- [ ] 3.1 Normalize an immutable exact-logical-type registry for Vue components and async component loaders and reject malformed, unsupported, or duplicate effective registrations at startup.
+- [ ] 3.2 Implement custom-page precedence and the generic route-page fallback containing authored `<cw-object-context>`, `<cw-object editable>`, and `<cw-interaction-controller>` elements.
+- [ ] 3.3 Define immutable `logicalTypeName`, `objectId`, and `routeKey` props for application-authored route pages and provide source examples for binding them to the declared context.
+- [ ] 3.4 Add bounded post-mount validation for route-context cardinality, interaction-controller containment, and canonical identity without manufacturing, moving, or selecting semantic elements.
+- [ ] 3.5 Key `RouterView` content by canonical identity and verify that route changes disconnect obsolete contexts, requirements, listeners, and interaction state.
+- [ ] 3.6 Scope async component loading, rejection, diagnostics, focus, and announcements to the active route generation and discard superseded completion.
+- [ ] 3.7 Add a structural test proving `<cw-object>` does not import or inspect Vue Router, Vue injection state, or the page registry.
+
+## 4. Stable Shell and Native Element Bridge
+
+- [ ] 4.1 Export the shell composables and route-view helpers needed by an application-authored root component without exporting a mandatory visual shell hierarchy.
+- [ ] 4.2 Implement bounded development validation for one stable `<cw-graphql-client>`, one router-view region, one default result outlet, and the documented loading and announcement landmarks without repair.
+- [ ] 4.3 Implement endpoint and string-identity binding through authored templates and property-only structured bindings through DOM properties, including explicit Vue `.prop` use where required.
+- [ ] 4.4 Implement a shell-scoped semantic-event bridge for authoritative object navigation, interaction completion, and result events with deterministic listener cleanup on application unmount.
+- [ ] 4.5 Verify native custom-element attributes, properties, slots, pre-upgrade children, `CustomEvent` payloads, event bubbling, and connect/disconnect lifecycle under Vue rendering.
+- [ ] 4.6 Keep GraphQL objects, metadata, members, validation, invocation, and interaction state out of Vue stores and duplicate adapter state.
+
+## 5. Navigation, Home, and Result Policy
+
+- [ ] 5.1 Implement replaceable single-claim policy hooks for navigation, application-entry home behavior, and object, scalar, collection, void, unsupported, and error outcomes.
+- [ ] 5.2 Route complete object identities canonically and reject object-shaped results that lack authoritative public navigation identity without inference.
+- [ ] 5.3 Resolve exactly one eligible active-page result outlet before the shell default and fail closed for duplicate, disconnected, or otherwise ambiguous outlets.
+- [ ] 5.4 Assign normalized scalar and collection results to `<cw-action-results>` so existing result and standalone-collection components retain presentation authority.
+- [ ] 5.5 Refresh the current object context after void results and replace the route with home only when authoritative refresh establishes that the target disappeared.
+- [ ] 5.6 Test application handler replacement so claimed events are handled once and component interaction behavior remains unchanged.
+
+## 6. Route Lifecycle, Accessibility, and Theme
+
+- [ ] 6.1 Coordinate busy state, loading, ready, invalid-route, unavailable, partial-error, unsupported, and terminal-error presentation from router and object-context state.
+- [ ] 6.2 Implement generation-scoped focus movement and live-region announcements that cannot be overwritten by obsolete navigation or async-page work.
+- [ ] 6.3 Ensure unavailable and denied outcomes reveal neither domain state nor authorization rules and do not claim distinctions absent from the authoritative transport.
+- [ ] 6.4 Add a copyable reference shell theme with documented custom properties and hooks for wide, narrow, light, dark, reduced-motion, keyboard, and visible-focus behavior.
+- [ ] 6.5 Run automated accessibility checks and manual keyboard journeys for routing, menus, dialogs, sidebars, result dismissal, and route restoration.
+
+## 7. Shared Petclinic Domain and Vue Application
+
+- [ ] 7.1 Extract the deterministic Petclinic domain and seed configuration into a small shared non-viewer module while preserving public logical types, fixture identities, cardinalities, GraphQL semantics, and source ownership.
+- [ ] 7.2 Update the HTMX Petclinic application to consume the shared module without changing its routes, classpath pages, application shell, selectors, security variants, or toolkit policies.
+- [ ] 7.3 Add a separate Vue Petclinic Spring Boot application with its own entry point, GraphQL endpoint, Vite source application, production output, client-route forwarding, and run profile.
+- [ ] 7.4 Author the Vue Petclinic `index.html` and root `App.vue` with a stable GraphQL provider, menus, branding, loading, announcements, default result outlet, and keyed router-view region.
+- [ ] 7.5 Add at least one source-visible Petclinic custom Vue page declaring its route context and interaction controller and leave another logical type unregistered to demonstrate generic fallback.
+- [ ] 7.6 Demonstrate menus, breadcrumbs, properties, actions, collection paging and filtering, row previews, object navigation, object results, and collection-result presentation without Vue-owned domain queries.
+- [ ] 7.7 Verify production output and direct-refresh routing without requiring a Vite development server or runtime Vue template compiler.
+
+## 8. Verification and Documentation
+
+- [ ] 8.1 Add browser acceptance for direct links, refresh, back and forward, custom-page precedence, async-page races, generic fallback, invalid routes, absent objects, partial errors, menus, interactions, and results.
+- [ ] 8.2 Run Vue acceptance under default Vaadin and native component policies and fail on browser console errors, page errors, failed resources, or accessibility violations.
+- [ ] 8.3 Re-run foundation Node tests, HTMX Node and Java tests, HTMX Petclinic integration and security tests, and existing native, Vaadin, and secured Playwright profiles after Petclinic extraction.
+- [ ] 8.4 Document installation, package exports, Vite configuration, router records, route grammar, history fallback, shell ownership, custom pages, generic fallback, policies, toolkit assets, theming, lifecycle, diagnostics, and CSR-only support.
+- [ ] 8.5 Verify Maven reactor integration, reproducible generated output, dependency notices, Apache RAT, formatting, `git diff --check`, and strict OpenSpec validation.
diff --git a/openspec/planned-changes/web-component-viewer/add-generic-vue-web-component-viewer/design.md b/openspec/planned-changes/web-component-viewer/add-generic-vue-web-component-viewer/design.md
deleted file mode 100644
index 1275dc2223a..00000000000
--- a/openspec/planned-changes/web-component-viewer/add-generic-vue-web-component-viewer/design.md
+++ /dev/null
@@ -1,99 +0,0 @@
-## Context
-
-Vue provides component composition, dynamic components, application plugins, and a mature router.
-Causeway's custom elements already provide the domain-aware controls, object contexts, grid composition, menu composition, validation, and interaction results.
-Applications declare those elements directly in Vue templates.
-A generic Vue viewer should therefore be a router, route-value binder, and lifecycle integration, not a Vue rewrite of those components.
-
-The final customization architecture is route-first.
-The Vue router resolves a bookmark, chooses an exact logical-type application page if registered, and otherwise renders a generic route page containing `<cw-object>`.
-
-## Goals / Non-Goals
-
-**Goals:**
-
-- Provide canonical deep-linkable bookmark routes using Vue Router.
-- Support exact-logical-type custom Vue pages and generic object fallback.
-- Preserve stable menu shell state across route-page changes.
-- Bridge semantic custom-element navigation and result events into replaceable Vue policy.
-- Integrate custom-element registration and lifecycle cleanly with Vue rendering.
-- Provide a complete accessible production-style viewer package and acceptance application.
-
-**Non-Goals:**
-
-- Wrapping every Causeway custom element as a separate Vue component.
-- Reimplementing GraphQL operations, object layout, menu parsing, editors, or validation in Vue.
-- Making `<cw-object>` inspect Vue Router or the page registry.
-- Supporting Nuxt or server-side rendering in the first version.
-- Defining HTMX or Svelte lifecycle behavior.
-
-## Decisions
-
-### Use Vue Router as the customization boundary
-
-The viewer installs canonical object and application-entry routes into a Vue Router instance or exposes route records for an application-owned instance.
-The object route resolves public logical type and identifier.
-It then selects the exact logical-type page registration or the generic route page.
-
-Page selection occurs before `<cw-object>` is created.
-The generic object component remains unaware of custom pages.
-
-### Register framework-native custom pages
-
-Applications register a Vue component, async component, or documented page factory against an exact Causeway logical type.
-The selected application page declares one `<cw-object-context>` and binds the canonical logical type and identifier supplied by the generic route-page boundary.
-The viewer validates or diagnoses the declared boundary but does not manufacture it imperatively.
-
-Custom Vue pages can compose Causeway custom elements, ordinary Vue components, HTML, and application custom elements.
-They consume domain state through their declared object context rather than constructing GraphQL documents in Vue stores.
-
-### Render a generic page when no registration exists
-
-The fallback route-page template declares its GraphQL client association, route-level object context, and `<cw-object>` fallback.
-The router binds endpoint and canonical identity values into those declared elements.
-A stable route key based on canonical bookmark identity ensures old contexts disconnect when navigation changes.
-Superseded component responses remain governed by object-context generation handling.
-
-### Keep the application shell stable
-
-The application-authored root viewer shell declares one stable `<cw-graphql-client>` containing `<cw-menubars>` outside `RouterView` or its equivalent route-page boundary.
-The Vue adapter binds configured client properties but does not create the provider element.
-Menu disclosure, service-action interaction, and menu layout remain component-owned.
-Vue policy receives semantic outcomes and may call router navigation or render non-object results.
-
-### Treat custom elements as the data plane
-
-The package configures or documents Vue custom-element recognition so Causeway element attributes, properties, and native custom events retain their browser semantics.
-A small integration adapter may normalize event subscription and cleanup, but it does not mirror component state into a duplicate Vue domain store.
-
-### Keep home and result policy replaceable
-
-Home-page objects and service actions are resolved from the application-entry contract.
-Default object results navigate to canonical routes, while scalar, collection, and void results use replaceable Vue presentations.
-Applications can override each policy without changing semantic components.
-
-### Defer server-side rendering
-
-The first viewer targets a client-rendered Vue application and browser history.
-Nuxt, SSR, streaming hydration, and server-only route data are separate compatibility work because custom-element upgrade and GraphQL context lifecycle need explicit validation there.
-
-## Risks / Trade-offs
-
-- [Vue may treat unknown tags or properties specially] → Configure custom-element recognition and test attributes, properties, slots, and native events.
-- [Route reuse can retain obsolete object context] → Key route pages by canonical bookmark identity and verify deterministic disconnect.
-- [A duplicate Vue store can emerge] → Keep domain state in semantic object contexts and expose only viewer policy through Vue state.
-- [A page can omit or duplicate its declarative context] → Validate the route-page contract and present a bounded development diagnostic without silently adding a context.
-- [Async custom pages can race navigation] → Associate imports with route generation and discard superseded resolutions.
-- [Viewer routes may diverge] → Share canonical route and fallback fixtures with HTMX and Svelte viewers.
-
-## Migration Plan
-
-The Vue viewer is additive and installed only by Vue applications that select it.
-Applications may begin with generic routes and incrementally register custom logical-type pages.
-Rollback removes the plugin and route records without changing GraphQL or component contracts.
-
-## Open Questions
-
-- Whether the package owns a router instance or primarily exports route records and installation helpers.
-- Whether custom page registration should permit inheritance fallback after exact logical type in a later version.
-- Which non-object result presentation should be supplied by default.
diff --git a/openspec/planned-changes/web-component-viewer/add-generic-vue-web-component-viewer/proposal.md b/openspec/planned-changes/web-component-viewer/add-generic-vue-web-component-viewer/proposal.md
deleted file mode 100644
index 1953412ae68..00000000000
--- a/openspec/planned-changes/web-component-viewer/add-generic-vue-web-component-viewer/proposal.md
+++ /dev/null
@@ -1,36 +0,0 @@
-## Why
-
-Vue applications need a complete generic Causeway viewer rather than only examples showing how to place individual custom elements.
-The viewer's primary responsibility is to use Vue's routing and composition model to choose a logical-type-specific Vue page or a generic page containing `<cw-object>`, while the framework-neutral components continue to own GraphQL and domain semantics.
-
-The architectural ownership boundary is recorded in `coverage-matrix.yaml` entries `REF-VIEWER-01`, `REF-COMPONENT-01`, `REF-COMPONENT-02`, `REF-HOME-01`, and `REF-MENU-01`.
-
-## What Changes
-
-- Add an opt-in generic Vue viewer package and application plugin.
-- Implement canonical bookmark routing using Vue Router while preserving the cross-viewer route meaning.
-- Resolve an exact-logical-type Vue page registration before falling back to a generic Vue route page containing `<cw-object>`.
-- Require application-authored Vue shell and page templates to declare `<cw-graphql-client>` and `<cw-object-context>`, with the router binding endpoint and canonical identity rather than manufacturing those elements.
-- Keep `<cw-object>` unaware of Vue routes, custom-page registration, and framework lifecycle.
-- Compose `<cw-menubars>` in a stable Vue shell and translate semantic custom-element events into router navigation under replaceable policy.
-- Support Vue components, async components, and application page factories as custom logical-type pages.
-- Define home-page, result, loading, not-found, access-denied, partial-error, terminal-error, theme, and accessibility behavior.
-- Add a production-style Vue acceptance application rather than a documentation-only sample.
-
-## Capabilities
-
-### New Capabilities
-
-- `generic-vue-web-component-viewer`: Provides a router-led generic Vue Causeway viewer over the framework-neutral semantic web-component library.
-
-### Modified Capabilities
-
-None.
-
-## Impact
-
-- Adds an optional Vue package, router integration, plugin configuration, shell components, route pages, tests, and documentation.
-- Depends on accepted P0 and P1 rich GraphQL coverage plus completed application-entry, composite-object, and menu-bar capabilities.
-- Uses application-authored native custom elements and semantic events without reimplementing GraphQL schema interpretation or semantic context hierarchy in Vue adapters.
-- Preserves canonical route and fallback semantics shared with the generic HTMX and Svelte viewers.
-- Does not require non-Vue applications to install Vue or Vue Router.
diff --git a/openspec/planned-changes/web-component-viewer/add-generic-vue-web-component-viewer/specs/generic-vue-web-component-viewer/spec.md b/openspec/planned-changes/web-component-viewer/add-generic-vue-web-component-viewer/specs/generic-vue-web-component-viewer/spec.md
deleted file mode 100644
index 90b2010157e..00000000000
--- a/openspec/planned-changes/web-component-viewer/add-generic-vue-web-component-viewer/specs/generic-vue-web-component-viewer/spec.md
+++ /dev/null
@@ -1,92 +0,0 @@
-## ADDED Requirements
-
-### Requirement: Optional router-led Vue viewer
-The project SHALL provide an explicitly installed generic Vue viewer that owns application routing and shell lifecycle while using semantic Causeway custom elements for domain behavior.
-
-#### Scenario: Vue viewer is installed
-- **WHEN** a Vue application installs the viewer package and router integration
-- **THEN** canonical Causeway routes and the documented viewer shell become available
-- **AND** domain state remains component-owned
-
-#### Scenario: Vue viewer is absent
-- **WHEN** an application does not install the package
-- **THEN** Vue and Vue Router are not runtime requirements of the component library
-
-### Requirement: Vue Router bookmark routes
-The viewer SHALL resolve canonical public logical-type and identifier routes through Vue Router with configurable mounting beneath an application base path.
-
-#### Scenario: Bookmark route loads
-- **WHEN** a valid authorized bookmark route is opened, refreshed, or revisited through history
-- **THEN** Vue Router resolves the corresponding route page
-- **AND** route identity remains compatible with the other generic viewers
-
-#### Scenario: Bookmark route fails
-- **WHEN** the bookmark is malformed, absent, stale, or unauthorized
-- **THEN** the route page presents a bounded accessible outcome
-- **AND** reveals no domain state or authorization rule
-
-### Requirement: Vue custom-page precedence
-The Vue route resolver SHALL choose an exact-logical-type registered Vue page before the generic object page.
-Application-authored custom and generic Vue templates SHALL declare their own route-level `<cw-object-context>`, and the router SHALL bind canonical identity without manufacturing that element.
-
-#### Scenario: Vue page is registered
-- **WHEN** a route resolves a logical type with a registered Vue component, async component, or accepted factory
-- **THEN** that page's declared object context is bound to canonical route identity
-
-#### Scenario: No Vue page is registered
-- **WHEN** no exact registration exists
-- **THEN** the route renders a declarative fallback containing one object context and `<cw-object>`
-
-#### Scenario: Generic component connects
-- **WHEN** `<cw-object>` renders the route object
-- **THEN** it uses effective or fallback grid behavior
-- **AND** does not inspect Vue Router or custom-page registrations
-
-### Requirement: Stable Vue application shell
-The application-authored Vue shell SHALL declare one stable `<cw-graphql-client>` containing `<cw-menubars>` and global viewer state outside the changing route-page region.
-The viewer SHALL bind configured client properties without manufacturing the provider element.
-
-#### Scenario: Vue route changes
-- **WHEN** `RouterView` or the equivalent page region changes object routes
-- **THEN** the declared client and menu coordination remain stable
-- **AND** obsolete declared object contexts disconnect deterministically
-
-#### Scenario: Route page has an invalid context boundary
-- **WHEN** a custom or generic Vue page omits or duplicates its route-level object context
-- **THEN** the viewer presents a bounded diagnostic
-- **AND** does not silently create or select a context
-
-### Requirement: Native custom-element integration
-The Vue viewer SHALL preserve Causeway custom-element attributes, properties, slots, native custom events, upgrade behavior, and lifecycle without duplicating their domain state in Vue.
-
-#### Scenario: Semantic event is published
-- **WHEN** a Causeway component emits navigation, interaction, or result semantics
-- **THEN** the Vue viewer adapter forwards it to replaceable viewer policy
-- **AND** does not alter the component's GraphQL operation
-
-### Requirement: Vue home and result policy
-The viewer SHALL provide replaceable Vue policy for configured home entries and scalar, object, collection, and void results.
-
-#### Scenario: Object result uses default policy
-- **WHEN** an interaction produces an object result
-- **THEN** default policy may navigate to its canonical Vue Router route
-
-#### Scenario: Application replaces policy
-- **WHEN** an application registers its own home or result handler
-- **THEN** the handler receives semantic data without replacing component interaction behavior
-
-### Requirement: Vue route lifecycle accessibility
-The viewer SHALL present accessible loading, ready, not-found, access-denied, partial-error, and terminal-error states and manage focus after route navigation.
-
-#### Scenario: Async custom page is superseded
-- **WHEN** navigation changes before an async page resolves
-- **THEN** the obsolete page is not rendered
-- **AND** focus and announcements belong to the current route
-
-### Requirement: Initial client-rendered scope
-The first generic Vue viewer SHALL document client rendering as its supported lifecycle and SHALL NOT imply unverified Nuxt or SSR compatibility.
-
-#### Scenario: SSR support is requested
-- **WHEN** an application requires Nuxt, SSR, or streaming hydration
-- **THEN** the viewer reports that capability as separate compatibility work
-- **AND** does not silently provide inconsistent custom-element hydration
diff --git a/openspec/planned-changes/web-component-viewer/add-generic-vue-web-component-viewer/tasks.md b/openspec/planned-changes/web-component-viewer/add-generic-vue-web-component-viewer/tasks.md
deleted file mode 100644
index 9a229ea8dca..00000000000
--- a/openspec/planned-changes/web-component-viewer/add-generic-vue-web-component-viewer/tasks.md
+++ /dev/null
@@ -1,29 +0,0 @@
-## 1. Package and Router Contract
-
-- [ ] 1.1 Verify all accepted P0 and P1 GraphQL, application-entry, composite-object, and menu-bar prerequisites are complete.
-- [ ] 1.2 Establish the optional Vue package, peer dependencies, plugin contract, custom-element registration, default theme, and acceptance application.
-- [ ] 1.3 Implement canonical route records, route parsing, configurable base path, and bookmark resolution using Vue Router.
-- [ ] 1.4 Maintain cross-viewer route fixtures shared with HTMX and Svelte implementations.
-
-## 2. Custom and Generic Route Pages
-
-- [ ] 2.1 Implement exact-logical-type registration for Vue components, async components, and accepted page factories.
-- [ ] 2.2 Implement application-authored custom and generic route templates that declare one `<cw-object-context>`, with `<cw-object>` in the generic fallback.
-- [ ] 2.3 Bind canonical route identity into declared contexts and fail closed diagnostically when a page omits or duplicates its route context.
-- [ ] 2.4 Key page lifecycle by canonical bookmark identity and dispose disconnected requirements deterministically.
-- [ ] 2.5 Verify `<cw-object>` never reads Vue router or page-registry state.
-
-## 3. Shell, Events, and Policy
-
-- [ ] 3.1 Implement the application-authored stable Vue shell declaring one `<cw-graphql-client>`, `<cw-menubars>` placement, `RouterView` page region, endpoint binding, and route lifecycle states.
-- [ ] 3.2 Bridge semantic custom-element navigation and result events into replaceable Vue router and result policy.
-- [ ] 3.3 Implement configurable home-page object and service-action policy.
-- [ ] 3.4 Keep domain state in GraphQL object contexts rather than a duplicate Vue store.
-
-## 4. Verification and Documentation
-
-- [ ] 4.1 Test deep links, refresh, history, custom pages, async page races, generic fallback, menus, interactions, results, partial errors, absent objects, and access denial.
-- [ ] 4.2 Test declarative client/context ownership, missing and duplicate context diagnostics, custom-element attributes, properties, slots, native events, upgrade ordering, disconnect, and route reuse.
-- [ ] 4.3 Verify responsive layout, keyboard navigation, focus after routing, announcements, light/dark themes, and accessibility.
-- [ ] 4.4 Document installation, router integration, route grammar, custom pages, fallback, policy, theming, lifecycle, SSR exclusion, and framework-neutral boundaries.
-- [ ] 4.5 Run Vue, browser, Maven, GraphQL, accessibility, formatting, and strict OpenSpec validation checks.