qcontrol Preview
Assemble seven page mocks (Teams & Users, User Details, Team Details, Sessions, Session Details, Devices, Device Details) behind shared app chrome that mimics the real qcontrol shell, ahead of integration with the real app
New in this cycle: The qcontrol preview — seven page mocks behind a left nav and app chrome that mimics the real shell
Why
Phase 1 mock-making has produced the pieces for this: teams-v3.vue and sessions.vue (c89), user-detail-v2.vue, session-detail-v2.vue, device-detail-v2.vue (c81). Each lives as an independent, unchromed page reachable only from the flat /pages/phase1 index — fine for evaluating one concept at a time, wrong for the next step. Team Details doesn't exist yet at all (a team is currently just a ?team= filter on the Teams listing), and neither does a Devices listing (only device-detail) — c89 explicitly left that gap for this cycle to fill, mirroring how it added Sessions.
Objective
Take the best iteration of each page, wire them together behind a left nav and app chrome that mimics the real qcontrol shell (qdash), and put all seven in one place so the flow — Teams → Team/User → Sessions → Session → Devices → Device — can be clicked through and manually tweaked as a whole, ahead of integration with the real qcontrol app.
Scope
app/components/QcontrolSidebar.vue— new site nav component modeled onapp/components/replicas/qdash/AppSidebar.vue, but route-aware and scoped to exactly three links (Teams & Users, Sessions, Devices — the three listing pages only).app/layouts/qcontrol.vue— new layout composing the sidebar + main slot.app/pages/qcontrol/{teams,team,user,sessions,session,devices,device}.vue— seven assembled pages. Five copied/adapted from existing phase1 mocks (state toggle dropped, cross-links repointed to/qcontrol/*);team.vueanddevices.vueare net new.app/data/phase1/derived/devices.ts— new module mirroringderived/sessions.ts's shape, wrapping existing per-device logic inderived/device-detail.ts.app/data/page-registry.ts— one entry as the flow's entry point (/qcontrol/teams).
Explicitly out of scope: the shared routes.ts entityRoute()/HOME system stays untouched (24 other phase1 pages depend on it); filter UI (c88's territory); moving or retiring the original phase1 source pages (copy only).
Key Changes
initial assembly (2026-09-16): Built the chrome and assembled the seven pages. app/components/QcontrolSidebar.vue — a route-aware left nav modeled on the qdash AppSidebar.vue replica, scoped to the three listing links (Teams & Users, Sessions, Devices) with the wordmark on top; app/layouts/qcontrol.vue composes it with the main slot. app/pages/qcontrol/{teams,team,user,sessions,session,devices,device}.vue — five copied/adapted from the best phase1 iteration (teams-v3, sessions, user-detail-v2, session-detail-v2, device-detail-v2; state toggle dropped, cross-links repointed through a local QCONTROL_HOME map rather than the shared routes.ts), team.vue and devices.vue net new. app/data/phase1/derived/devices.ts mirrors derived/sessions.ts's shape (a DeviceRow per world device wrapping coverageGap/deviceHeadline from device-detail.ts, a band, a verdict). app/data/page-registry.ts gained a qcontrol page group and an href override field so registry cards can point at a route outside /pages/<slug> — one qcontrol-preview entry as the flow's front door, then one entry per page. Pages later forked into frozen/working pairs (user.vue/user-v2.vue, session.vue/session-v2.vue, device.vue/device-v2.vue) so manual design iteration has a live target while the assembled original stays as the archive. app/components/QcontrolEntityChip.vue (2026-09-17) extracted the person/device/agent/account/repo chip every qcontrol page repeats.
user-details-v3 (2026-09-17): New app/pages/qcontrol/user-v3.vue executing the dropped designs/user-details - anotated@2x.png — compact identity header, a DataHistoryGraph "Total Session per Agent" chart paired with clickable headline stats, scroll-anchor tabs (Deployments/Agents/Sessions/Surface, no scroll-spy), QcontrolDeviceAgentsCard.vue device cards (green "Sensor Active" banner + a dense nested Agents table), then the Sessions table reused verbatim from user-v2. Versioned as a new file per the repo's own frozen/working pattern: user-v2.vue frozen as the historical archive, every page's QCONTROL_HOME.person repointed to /qcontrol/user-v3, registry entry added and qcontrol-user-v2's marked superseded. Sections the mock doesn't show (verdict line, chain strip, Models card, Accounts/Surface detail) are deferred, not deleted. Fixture additions for the design's data story: one new fully-covered multi-device person in people.ts and an 'iphone' DeviceKind in world/types.ts (one-line kindLabel addition in the eight exhaustive maps). See user-details-v3-prompt.md / -plan.md.
users-devices-listing (2026-09-17): Combined Teams, Users, and Devices into one page (app/pages/qcontrol/teams.vue) per a newer dropped mock (designs/users-devices-listing-page - anotated@2x.png) — NavJumpPills section switcher, a page-level Filter (team/provider) and per-section FilterTriggerBar replacing the old click-to-filter header rings, DataMachine presets for the coverage stat cards, and a net-new Teams table (the mock's own annotation flagged it missing). Retired the standalone /qcontrol/devices route (sidebar + registry updated); its content is now the page's Devices section. First real (non-demo) consumer of the DataMachine/Filter/FilterTriggerBar layer components. See users-devices-listing-prompt.md / -plan.md.
session-details (2026-09-17): Reworked app/pages/qcontrol/session-v2.vue against designs/session-details@2x.png — a two-column body (reading column + sticky metadata rail) replaces the single full-width column below the receipt. Added sessionTranscript() (app/data/phase1/derived/session-detail.ts) mapping the c77 beat/chapter grain onto the c85 TranscriptPanel family's Transcript/TranscriptTurn/TranscriptMessage/ContentPart shape — chapters become turns, each machinery event inside an action beat becomes its own Ran: … tool-call row. Two decisions made with Mark before building (see session-details-prompt.md): policy violations stay out of the transcript entirely (no policy-speaker concept in TranscriptMessage; they remain in the existing Exceptions box, now linking to a raw-events row instead of an in-transcript beat anchor) and the TranscriptNavigator turn-navigator ships despite echoing the removed "Chapters" concept, since it's a separately-shipped c85 interaction. The rail's Tokens/est. Cost/Tool Calls/Policy Events tiles are DataMachine instances (Cost's $ rides the #left slot since DataMetricValue's unit always renders after the number; Policy Events uses healthModes.ZERO_TOLERANCE); User/Agent/Device/Account/Repo reuse the receipt's existing QcontrolEntityChips, relaid as labelled fields. Files is a new list sourced from the session's file_access events directly, honest to the real event shape (no permission-decision field, so a sensitive read reads "sensitive read" rather than the mock's literal "read not allowed"). First real (non-demo) joint consumer of TranscriptPanel and DataMachine. Verified via SSR curl against all five switcher sessions (including the no-events case) — no runtime errors. See session-details-prompt.md / -plan.md.
session-details, work-in-progress toggle (2026-09-17): Follow-up per Mark's review — the pre-mock verdict line + receipt card (identity header, four stat blocks, Exceptions box) and the Composition notes section moved below the mock-faithful transcript/rail view and collapsed behind a "Show Work In Progress" toggle (showWip, off by default), since the rail and Exceptions box already carry that information for an ordinary reader. The scenario switcher and tab switch stay visible at top (still working/navigation aids, not review-only scaffolding).
session-details, transcript disclaimer (2026-09-17): Follow-up — the BYOK/encryption disclaimer paragraph moved below TranscriptPanel (was above it) and collapsed behind a "Show details" toggle (showTranscriptDetails, off by default), so the transcript itself is the first thing a reader sees under the tab switch.
session-details, default session + switcher relocation (2026-09-17): Follow-up — the page now defaults to Kai's blocked-tool session (ses-kai-04, a local DEFAULT_ID override in session-v2.vue, not a change to derived/session-detail.ts's shared DEFAULT_SESSION_ID, which the other session-detail pages still default from) instead of Marcus's sensitive-file session. The "review a session" scenario switcher moved out of the top working view into the Work In Progress block, alongside the verdict/receipt card it was always scaffolding for.
filter alignment pass (2026-09-18): Tuned teams.vue's page-level Filter and per-section FilterTriggerBar placement and the section backgrounds against the mock, iterating with capture checks (public/archive/2026-q3/sweep/c90-filter-align-check*.png, -bg-check.png — scratch shots, not archive entries). Two global layer tweaks made in the same pass while tuning the chrome, shipped in q-nuxt-layer 0.9.13 and visible to every consumer: UxAvatar border weight border-1 → border-2, and UxPageTitle's underline padding pb-1 → pb-3.
Visual record
15 captures — heroes, page slices, and full-page renders. Click to view.















Artifacts
- initial-prompt.md
- thread: session-details — prompt + plan
- thread: user-details-v3 — prompt + plan
- thread: users-devices-listing — prompt + plan
- initial-prompt.md