← Cycles
Design · c89

Teams–Sessions Listings

activecreated 2026-09-15· last activity 2026-09-18· mode: assemblage (composing existing phase1 idioms into listing headers), evolution (Teams iteration), archaeology (Sessions surfaces existing world data)

First-pass mocks for Teams listing header upgrade and net-new Sessions listing page in phase1 dashboard style

New in this cycle: The header idiom: a coverage ring where a real denominator exists, a named attention list instead of abstract counts

Why

Teams already has a working listing page from c81 with sound data hierarchy, but its header treatment needs upgrading to match the Users & Devices pattern (coverage rings, named "needs attention" lists) that other designers are establishing as shared header idioms. Sessions has no plural listing page at all — only single-session detail pages exist — so a Sessions roster is net-new design territory. Filtering UI is explicitly out of scope (c88.global-filter's responsibility).

Objective

Produce first-pass mocks for both pages in the current phase1 style, deliberately evaluating which data deserves top-of-page (header), table-row, or expand-only placement — rather than jumping straight to visuals. Establish data-hierarchy patterns that can propagate to other listing pages.

Scope

Key files and areas this cycle touches:

  1. app/pages/phase1/teams-v3.vue — New iteration of phase1/teams.vue: swap coverage/devices-sensored Phase1StatBlocks for DataDonutChart rings, add short named list of people needing attention directly in header. Team strip, roster table, and row-expand stay as-is.
  2. app/pages/phase1/sessions.vue — Net-new listing page: header with total sessions + tokens/dollars (30d) stat pair plus named "sessions needing review" list (sessions with scan_finding event or cost outlier); simple roster table (person, team, agent/technology, started, duration, tokens, dollars, model(s), outcome/flag pill) on DataTable/UxTableList; rows link out to existing session-detail.vue.
  3. app/data/phase1/derived/sessions.ts — New module mirroring derived/teams.ts conventions: SessionRow type, sessionRoster(world), band/totals helper, sessionsVerdict generator. Everything derived from world, nothing hand-typed.
  4. app/data/page-registry.ts — Add phase1 entries for teams-v3 (teams group) and sessions (sessions group).
  5. app/data/phase1-registry.ts — Flag Sessions landing route as new scope beyond original PRO-19…35 plan.
  6. Composition notes — Append to both pages documenting data-hierarchy decisions, matching teams.vue convention.

Explicitly out of scope: global/generic filter UI (c88's territory) — page-local quick filters like existing team strip are fine to keep/reuse but not newly build.

Key Changes

Backfilled 2026-09-18 from the shipped code — Key Changes were not written as the work happened.

  • 2026-09-15 — derived/sessions.ts. New module mirroring derived/teams.ts's conventions: SessionRow (a sessionReceipt(w, s) wrapper with listing-friendly fields flattened on top), sessionRoster(w) (every session in the world's recent sample, ranked violations → runaway cost → clean), sessionsBand(w, rows) (session count against the honest 7-day window, cost with tokens in the sub, the flagged list), and sessionsVerdict(w, rows) (warn only when a flagged session is a policy violation, else attention). Flag state is never re-derived — it reads receipt.attention from session-detail.ts, the one source of truth. sessionsVerdict deliberately not folded into derived.ts's central verdicts map yet.
  • 2026-09-15 — phase1/sessions.vue (net new). The Sessions roster: verdict line, a sessions/cost stat pair labelled "· 7d sample" so it never overstates what's on record (no donut ring — "how many sessions" has no natural denominator), a named "needs a look" list capped at 5 with an overflow note, and a DataTable roster (person, team, agent, started, duration, tokens, dollars, models as un-linked entity chips, outcome pill). Rows link straight to the existing Session detail receipt via onRow — no per-page expand, since session-detail.vue already owns chapters, transcript, raw events, and the actor web. Composition notes appended per the teams.vue convention.
  • 2026-09-15 — phase1/teams-v3.vue. Header-treatment iteration on phase1/teams.vue (PRO-20): the "people covered" and "devices sensored" Phase1StatBlock fractions become DataDonutChart coverage rings (same two numbers from rosterBand, click-to-filter behaviour rides along), plus a named "needs attention" list — band.investigate first (holds a seat, zero telemetry), then filled to 5 from band.uncovered, reusing the roster's own Coverage-column phrasing so header and table never say one fact two ways. "Using AI · 30d" and "installs with an owner" stay plain stat blocks. Question, verdict, team strip, roster, and expand untouched.
  • 2026-09-15 — Registry. teams-v3 (teams group) and sessions (sessions group) entries in app/data/page-registry.ts, both phase: 'phase1'.
  • Not done: scope item 5 — flagging the Sessions landing route in app/data/phase1-registry.ts as new scope beyond PRO-19…35 — was never made; the page's only registration is in page-registry.ts.

Outcome

Written 2026-09-18, after the fact. Left active for Mark to close at the next pass.

Both first-pass mocks shipped on 2026-09-15 in one sitting. The header idiom this cycle set out to establish — a coverage ring where a real denominator exists, a named attention list instead of abstract counts — landed on Teams v3 and, in the ring-less variant, on Sessions; the honesty rule that fell out of it (no ring without a natural whole to divide by) is the more reusable finding than either page. derived/sessions.ts proved the derived/teams.ts module shape generalises to a second listing, and c90 then mirrored it a third time for derived/devices.ts. c90 copied both pages into the qcontrol preview (/qcontrol/sessions verbatim; teams-v3 as the base of the combined Teams/Users/Devices page, where the click-to-filter rings were later replaced by c88's Filter/FilterTriggerBar and the coverage cards by c91's DataMachine presets). Open questions from the pages' composition notes carry forward unresolved: whether a header ring reads as "just a stat" to most users, and whether Sessions wants a per-team/per-agent rollup strip. The phase1-registry flag (scope item 5) was never written.


Note: A reference screenshot of the in-progress Users & Devices page (from another designer) is the visual precedent for header idioms. It currently exists only as inline chat content with no accessible file path — add to cycle folder once available as a file.

Visual record

4 captures — heroes, page slices, and full-page renders. Click to view.

Sessions listing (net new) — verdict, honest 7d-sample stat pair with no ring, named flagged-sessions list, DataTable roster ranked violations → runaway cost → clean
Sessions listing (net new) — verdict, honest 7d-sample stat pair with no ring, named flagged-sessions list, DataTable roster ranked violations → runaway cost → clean open page →history · 9 moments →
Teams v3 header treatment — DataDonutChart coverage rings replace stat-block fractions, plus a named needs-attention list under the band
Teams v3 header treatment — DataDonutChart coverage rings replace stat-block fractions, plus a named needs-attention list under the band open page →history · 14 moments →
c89 full
open page →history · 9 moments →
c89 full
open page →history · 14 moments →

Artifacts

Qpoint Brand Style Guide