# Cartography — UX Flows reference (Mode 4, artifact 2 of 3)

The method + template for `evaluation/ux-flows.md`. Spine in [`cartography.md`](cartography.md); siblings
[`cartography-ia.md`](cartography-ia.md), [`cartography-coverage.md`](cartography-coverage.md).

The UX-flows doc captures the primary end-to-end journeys, each as a **mermaid sequence diagram**. This
is the **black-box adaptation of a code-level workflow trace**: where a source tracer follows call
chains, Cartography follows the **observed wire** — trigger (user action) → surface → the actual API
calls captured in the `session` dimension → state transitions → terminal effect. **Diagram only what was
observed**; mark any inferred hop explicitly.

---

## Participants (the black-box vocabulary)

Map every actor in a captured flow to one of these participants (keep names identical across all
diagrams — the same backend is the same participant everywhere):

| Participant | What it is |
| --- | --- |
| `User` | the operator taking the action |
| `SPA` | the client app (browser) |
| `InternalAPI` | the app-own cookie/token API (the real transport — `/rest`, `/enrich`, `/graphql`, …) |
| `PublicAPI` | the published developer/partner API — **only if the flow actually used it** |
| `JobQueue` | an async batch / worker / job system (the work happens off-request) |
| `Realtime` | a WS / SSE / long-poll channel |
| `3rdParty` | a named external vendor (AI mesh, payments, CDP, email, telephony) |
| `Store` | browser storage / client cache (NuStack, Redux-persist, IndexedDB) |

---

## Identifying the flows (from captured wire, not source)

The entry points are the **captured journeys** in the `session` dimension — you already have the wire;
this turns it into a journey. Per category, look for:

- **Core action** — the primary write: the create / save / submit body + its server resolution
  (`raw/write-flow.md`).
- **Auth & session** — login → token/cookie → the authed read; the refresh path (`raw/auth-*.md`).
- **Realtime** — the WS/SSE/long-poll lifecycle + the event catalog (or the **negative**: "dashboard is
  REST-only" is a real flow finding, not a miss).
- **Data pipeline** — import/export, ingest, sync, bulk/mass-action (often an async `JobQueue` flow).
- **Configuration** — a model/setting change that ripples (e.g. add an attribute → completeness recompute).
- **AI** — a generate/translate/agent call (`raw/*-wire.md`); note brokered-server-side vs client-direct.

Trace each: trigger → which surface → the observed request(s) → branches (conflict/permission/feature
flag → `alt`/`opt`) → loops (polling/retry/batch → `loop`) → the terminal effect (a persisted entity, a
job id, a streamed result). Stop at the terminal write or external response.

## Complexity (sets diagram detail)

- **Steps** (distinct operations): 1–2 simple · 3–5 moderate · 6+ complex.
- **Participants**: 2 simple · 3–4 moderate · 5+ complex.
- **Branching** (`alt`/`opt`): 0 linear · 1–2 moderate · 3+ complex.
- Async (polling / job / child workflow): +1 level.

---

## The output template — `evaluation/ux-flows.md`

````markdown
# <Target> — UX Flows
---
journeys_identified: <N>   # REQUIRED — every primary journey the corpus identifies, whether or not it
                           # was diagrammed. This is the DENOMINATOR of feature-coverage's
                           # `flow_coverage`; without it the metric is reconstructed by whoever scores
                           # it, and a run that identifies few journeys scores the same as one that
                           # identifies many and diagrams them all.
journeys_diagrammed: <N>   # the count of sequence diagrams below
undiagrammed: [<name>, …]  # the named difference — never an empty list with N_identified > N_diagrammed
---
## TL;DR                  (how the product gets work done: sync-REST vs async-job, where realtime lives,
                           the approval/gate pattern, what's brokered server-side)
## Flow index             (table: flow · category · trigger · participants · complexity)
## <Category> flows       (Core action / Auth & session / Realtime / Data pipeline / Configuration / AI —
                           skip empty categories)
  ### <Flow name>
  **Trigger · Surface · Observed?**  (observed-wire | partially-inferred)
  ```mermaid
  sequenceDiagram
      participant User
      participant SPA
      participant InternalAPI
      User->>SPA: <action>
      SPA->>InternalAPI: <METHOD> <path>
      InternalAPI-->>SPA: <status + shape>
      SPA-->>User: <UI effect>
  ```
  **Notes:** (server-side resolution · the gate · the async hop · what was inferred vs observed)
## Cross-dimension reconciliation  (the flow as the app runs it vs as the public API/docs describe it —
                                    drift is a finding; published = fact, observed-drift = tentative)
## Open questions
````

## Diagram rules (from the workflow-mapper discipline)

1. **Arrows:** solid `->>` = request/call · dashed `-->>` = return/response. No dangling calls (every
   request has a response or a noted fire-and-forget).
2. **≤7 participants, ≤15 steps** per diagram. Past that, group with `rect` blocks / `Note over`, or
   split into linked sub-diagrams.
3. **`alt`** = a real workflow branch (conflict vs success), **`loop`** = poll / retry / batch (label
   the condition), **`opt`** = a gated step (permission, feature flag) — not generic error handling.
4. **Labels ≤8 words** — the action, not the implementation detail.
5. **Consistent participant names** across every diagram.
6. **The write-side rule (hard):** a flow that touches a **write / generate / launch** path on a
   `write_side_observed: false` run is diagrammed **as inferred** (dashed arrows, an explicit
   `Note over … : inferred (Pass-1 only)`), **never as observed** — this mirrors the evaluation
   write-side cap, and drawing it solid is a Mode-5 Cartography defect.
