# Angular UI Data Flow / View Model Boundary

Use this standard for Angular screens, Runtime Action Center surfaces, app-shell
state, and reusable UI components.

## Rule

UI components render typed view models; services, facades, and signals own
data/state orchestration.

## Required Flow

Use this flow for semantic frontend data:

```text
GraphQL/API/Runtime projection
  -> feature service or facade
  -> signal state
  -> computed typed view model
  -> component template / reusable UI component
```

Socket.IO payloads are invalidation metadata only. They may trigger a service or
facade to refetch canonical GraphQL/Runtime projection data, but they must not
become dashboard truth.

## Responsibilities

Services and facades:

- acquire data from generated GraphQL services, API clients, sockets, browser
  APIs, or Runtime helpers.
- coordinate auth readiness, route activation, socket invalidation, refetch,
  stale-state handling, and retry behavior.
- own signal state for shared or feature-level UI data.
- expose typed snapshots or typed view models to components.

Components:

- activate/deactivate route-scoped facades when needed.
- hold small presentation-only state such as selected tab, expanded row, or
  local copy status.
- render typed inputs and derived `computed()` view models.
- format display-only labels, dates, counts, and badges.
- avoid owning backend/runtime truth or socket truth.

Templates:

- render values from signals, component fields, and typed view models.
- use `@if`, `@for`, and `@switch` for presentation control flow.
- do not orchestrate auth, socket, GraphQL, Runtime, or service truth.
- do not call expensive or domain-mapping methods to rebuild semantic view
  models on every change detection pass.

Reusable UI components:

- receive clean inputs such as labels, body text, badges, rows, menu items, and
  callbacks.
- remain domain-agnostic unless explicitly feature-local.
- do not know Runtime Action Center, GraphQL, Socket.IO, service-status, or
  workflow semantics.

## Good Examples

```text
AdminRuntimeHealthGQL.fetch()
  -> AdminRuntimeHealthStateService.snapshot signal
  -> RuntimeActionCenterFacade live diagnostics computed state
  -> page component computed menu/view model
  -> ui-panel-menu rows
```

```ts
readonly messageRows = computed(() =>
  this.health.snapshot()?.operatorAssistantMessages.map(toMessageRow) ?? [],
);
```

## Bad Examples

```html
<!-- Bad: template performs semantic mapping from raw Runtime records. -->
@for (entry of snapshot.operatorAssistantMessages.sort(sortRuntimeMessages); track entry.id) {
  <runtime-message [severity]="inferSeverity(entry.source, entry.text)" />
}
```

```ts
// Bad: page component owns socket invalidation and GraphQL refetch orchestration.
this.socket.runtimeHealthChanged$.subscribe((event) => {
  if (event.changedSurfaces.includes('runtime_health')) {
    this.adminRuntimeHealthGql.fetch().subscribe(...);
  }
});
```

```ts
// Bad: reusable UI component imports Runtime-specific types.
import type { AdminRuntimeHealthQuery } from '../../core/graphql/generated/graphql';
```

## Exceptions

Small components may format local display values directly. A component may use a
template method only when the method is cheap, presentation-only, and not a
semantic mapping of raw backend/runtime data.

If a chunk intentionally keeps a legacy exception, it must record:

- why the exception is safe now.
- why it is not being fixed in the active chunk.
- which follow-up chunk or carry-forward item owns it.

## Review Checklist

For every frontend/UI chunk, Developer and QA must check:

- Data acquisition is in a service/facade, not a template.
- State coordination is in services/facades/signals.
- Components render typed view models where semantics exist.
- Templates do not orchestrate raw GraphQL/socket/Runtime data.
- Socket payloads are invalidation-only.
- GraphQL/Runtime projections remain canonical truth.
- Frontend code does not infer Runtime, service, workflow, approval, or
  dispatcher truth locally.
- Reusable UI components receive clean domain-agnostic inputs.

## Advisory Scanner

Run the lightweight report when a chunk touches frontend architecture-sensitive
code:

```sh
ai/commands/frontend-architecture-report.sh --json
```

The scanner is advisory in its first version. It highlights likely risks such as
large page components, socket subscriptions in components, generated GraphQL
service injection in components, and template method calls that may rebuild
semantic view models.
